diff -u --recursive --new-file linux/CREDITS linux.wavelan/CREDITS
--- linux/CREDITS	Sun Dec 31 11:27:57 2000
+++ linux.wavelan/CREDITS	Sat Jan 27 23:42:42 2001
@@ -1967,6 +1967,13 @@
 S: Potsdam, New York 13676
 S: USA
 
+N: Andreas Neuhaus
+E: andy@fasta.fh-dortmund.de
+W: http://www.fasta.fh-dortmund.de/users/andy/
+D: Author of wvlan_cs, the Lucent WaveLAN/IEEE 802.11 (and
+D: compatibles) wireless network driver.
+S: Germany
+
 N: Michael Neuffer
 E: mike@i-Connect.Net
 E: neuffer@goofy.zdv.uni-mainz.de
diff -u --recursive --new-file linux/Documentation/Configure.help linux.wavelan/Documentation/Configure.help
--- linux/Documentation/Configure.help	Thu Jan  4 15:00:55 2001
+++ linux.wavelan/Documentation/Configure.help	Sat Jan 27 23:42:42 2001
@@ -7360,6 +7360,24 @@
   a module, say M here and read Documentation/modules.txt. If unsure,
   say N.
 
+WaveLAN/IEEE 802.11 wireless support
+CONFIG_PCMCIA_WVLAN
+  Say Y here if you intend to attach a Lucent WaveLAN/IEEE 802.11 (or
+  compatible) wireless Ethernet networking card to your computer. This
+  driver is for the IEEE 802.11 compliant WaveLAN cards.
+
+  The NCR WaveLAN/IEEE 802.11, the Cabletron RoamAbout 802.11 and the
+  Melco WLI-PCM-L11 are also known to work with this driver. Say Y to
+  CONFIG_NET_RADIO also, if you plan to use the kernels wireless
+  extensions. See Documentation/networking/wavelan-ieee.txt for a
+  detailed description.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called wvlan_cs.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt. If unsure,
+  say N.
+
 PLIP (parallel port) support
 CONFIG_PLIP
   PLIP (Parallel Line Internet Protocol) is used to create a
diff -u --recursive --new-file linux/Documentation/networking/00-INDEX linux.wavelan/Documentation/networking/00-INDEX
--- linux/Documentation/networking/00-INDEX	Sat Nov 27 17:27:48 1999
+++ linux.wavelan/Documentation/networking/00-INDEX	Sat Jan 27 23:42:42 2001
@@ -80,6 +80,8 @@
 	- WANPIPE(tm) Multiprotocol WAN Driver for Linux WAN Router
 wavelan.txt
 	- AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver
+wavelan-ieee.txt
+	- Lucent WaveLAN/IEEE 802.11 (and compatibles) wireless networking card
 x25.txt
 	- general info on X.25 development.
 x25-iface.txt
diff -u --recursive --new-file linux/Documentation/networking/wavelan-ieee.txt linux.wavelan/Documentation/networking/wavelan-ieee.txt
--- linux/Documentation/networking/wavelan-ieee.txt	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/Documentation/networking/wavelan-ieee.txt	Sat Jan 27 23:42:42 2001
@@ -0,0 +1,17 @@
+
+	WaveLAN/IEEE 802.11 PCMCIA Linux driver
+	by Andreas Neuhaus <andy@fasta.fh-dortmund.de>
+	http://www.fasta.fh-dortmund.de/users/andy/wvlan/
+
+
+wvlan_cs.o is the Linux device driver for Lucent Technologies' WaveLAN/IEEE
+wireless LAN card. It also works with some other vendor's cards which
+use the WaveLAN/IEEE OEM. The driver works a as card service driver
+under the Linux PCMCIA system. It does not work with the old (Legacy)
+WaveLAN/ISA or WaveLAN/PCMCIA. Check the kernel sources and the PCMCIA
+package for those drivers.
+
+You need the pcmcia_cs package to use this driver. For detailed description
+of configuration options and features please look at man 4 wvlan_cs (which
+is included in pcmcia_cs).
+
diff -u --recursive --new-file linux/MAINTAINERS linux.wavelan/MAINTAINERS
--- linux/MAINTAINERS	Sun Dec 31 11:31:15 2000
+++ linux.wavelan/MAINTAINERS	Sat Jan 27 23:42:42 2001
@@ -1428,6 +1428,12 @@
 W:	http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
 S:	Maintained
 
+WAVELAN/IEEE 802.11 DRIVER
+P:	Andreas Neuhaus
+M:	andy@fasta.fh-dortmund.de
+W:	http://www.fasta.fh-dortmund.de/users/andy/wvlan/
+S:	Maintained
+
 WD7000 SCSI DRIVER
 P:	Miroslav Zagorac
 M:	zaga@fly.cc.fer.hr
diff -u --recursive --new-file linux/drivers/net/pcmcia/Config.in linux.wavelan/drivers/net/pcmcia/Config.in
--- linux/drivers/net/pcmcia/Config.in	Sat Nov 11 20:56:58 2000
+++ linux.wavelan/drivers/net/pcmcia/Config.in	Sun Jan 28 00:05:16 2001
@@ -29,6 +29,7 @@
       dep_tristate '    Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA
       dep_tristate '    AT&T/Lucent Wavelan wireless support' CONFIG_PCMCIA_WAVELAN $CONFIG_PCMCIA
       dep_tristate '    Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA
+      dep_tristate '    WaveLAN/IEEE 802.11 wireless support' CONFIG_PCMCIA_WVLAN $CONFIG_PCMCIA
    fi
 fi
 
@@ -37,7 +38,7 @@
      "$CONFIG_PCMCIA_NMCLAN" = "y" -o "$CONFIG_PCMCIA_SMC91C92" = "y" -o \
      "$CONFIG_PCMCIA_XIRC2PS" = "y" -o "$CONFIG_PCMCIA_RAYCS" = "y" -o \
      "$CONFIG_PCMCIA_NETWAVE" = "y" -o "$CONFIG_PCMCIA_WAVELAN" = "y" -o \
-     "$CONFIG_PCMCIA_XIRTULIP" = "y" ]; then
+     "$CONFIG_PCMCIA_XIRTULIP" = "y" -o "$CONFIG_PCMCIA_WVLAN" = "y" ]; then
    define_bool CONFIG_PCMCIA_NETCARD y
 fi
 
diff -u --recursive --new-file linux/drivers/net/pcmcia/Makefile linux.wavelan/drivers/net/pcmcia/Makefile
--- linux/drivers/net/pcmcia/Makefile	Fri Dec 29 16:07:22 2000
+++ linux.wavelan/drivers/net/pcmcia/Makefile	Sat Jan 27 23:52:25 2001
@@ -28,6 +28,7 @@
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
 obj-$(CONFIG_PCMCIA_NETWAVE)	+= netwave_cs.o
 obj-$(CONFIG_PCMCIA_WAVELAN)	+= wavelan_cs.o
+obj-$(CONFIG_PCMCIA_WVLAN)	+= wvlan_cs.o
 obj-$(CONFIG_AIRONET4500_CS)	+= aironet4500_cs.o
 
 # Cardbus client drivers
@@ -43,3 +44,8 @@
 ibmtr_cs.o: tmp-ibmtr.o ibmtr_cs.c
 	$(CC) $(CFLAGS) -DPCMCIA -c -o tmp-$@ ibmtr_cs.c
 	$(LD) -r -o $@ tmp-$@ tmp-ibmtr.o
+
+wvlan_cs.o: wvlan_cs.c wvlan_hcf.o wvlan_hcfio.o
+	$(CC) $(CFLAGS) -DMODULE -c -o .$@ $<
+	$(LD) -r -o $@ .$@ wvlan_hcf.o wvlan_hcfio.o
+	rm -f .$@
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_cs.c linux.wavelan/drivers/net/pcmcia/wvlan_cs.c
--- linux/drivers/net/pcmcia/wvlan_cs.c	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_cs.c	Sat Jan 27 23:55:46 2001
@@ -0,0 +1,2925 @@
+/********************************************************************
+ *	WaveLAN/IEEE PCMCIA Linux network device driver
+ *
+ *	by Andreas Neuhaus <andy@fasta.fh-dortmund.de>
+ *	http://www.fasta.fh-dortmund.de/users/andy/wvlan/
+ *
+ *	This driver is free software; you can redistribute and/or
+ *	modify it under the terms of the GNU General Public License;
+ *	either version 2 of the license, or (at your option) any
+ *	later version.
+ *	Please send comments/bugfixes/patches to the above address.
+ *
+ *	Based on the Linux PCMCIA Programmer's Guide
+ *	and Lucent Technologies' HCF-Light library (wvlan47).
+ *
+ *	See 'man 4 wvlan_cs' for more information.
+ *
+ * TODO
+ *		We should use multiple Tx buffers to gain performance.
+ *		Move configuration settings to private device data
+ *			(Current version has problems with multiple
+ *			cards when a card reset is necessary).
+ *		Have a closer look to the endianess (PPC problems).
+ *
+ * HISTORY
+ *	v1.0.4.1 2000/02/26 [eric@molitor] fixed to compile with 2.4.0
+ *
+ *	v1.0.4	2000/02/26
+ *		Some changes to fit into kernel 2.3.x.
+ *		Some changes to better fit into the new net API.
+ *		Use of spinlocks for disabling interrupts.
+ *		Conditional to allow ignoring tx timeouts.
+ *		Disable interrupts during config/shutdown/reset.
+ *		Credits go to Jean Tourrilhes for all the following:
+ *		Promiscuous mode (tcpdump now work correctly).
+ *		Set multicast Rx list (RTP now work correctly).
+ *		Hook up watchdog timer in new net API.
+ *		Update frag/rts to new W-Ext.
+ *		Operating mode support + W-Ext (Neat...).
+ *		Power Saving support + W-Ext (useless...).
+ *		WEP (Privacy - Silver+Gold) support + W-Ext (yeah !!!).
+ *		Disable interupts during reading wireless stats.
+ *		(New quality indicator not included, need more work)
+ *		Plus a few cleanups, comments and fixes...
+ *
+ *	v1.0.3	Skipped to not confuse with kernel 2.3.x driver
+ *
+ *	v1.0.2	2000/01/07
+ *		Merged driver into the PCMCIA Card Services package
+ *			(thanks to David Hinds).
+ *		Removed README, added man page (man 4 wvlan_cs).
+ *
+ *	v1.0.1	1999/09/02
+ *		Interrupts are now disabled during ioctl to prevent being
+ *			disturbed during our fiddling with the NIC (occured
+ *			when using wireless tools while heavy loaded link).
+ *		Fixed a problem with more than 6 spy addresses (thanks to
+ *			Thomas Ekstrom).
+ *		Hopefully fixed problems with bigger packet sizes than 1500.
+ *		When you changed parameters that were specified at module
+ *			load time later with wireless_tools and the card was
+ *			reset afterward (e.g. by a Tx timeout), all changes
+ *			were lost. Changes will stay now after a reset.
+ *		Rewrote some parts of this README, added card LEDs description.
+ *		Added medium_reservation, ap_density, frag_threshold and
+ *			transmit_rate to module parameters.
+ *		Applying the patch now also modifies the files SUPPORTED.CARDS
+ *			and MAINTAINERS.
+ *		Signal/noise levels are now reported in dBm (-102..-10).
+ *		Added support for the new wireless extension (get wireless_
+ *			tools 19). Credits go to Jean Tourrilhes for all
+ *			the following:
+ *		Setting channel by giving frequency value is now available.
+ *		Setting/getting ESSID/BSSID/station-name is now possible
+ *			via iwconfig.
+ *		Support to set/get the desired/current bitrate.
+ *		Support to set/get RTS threshold.
+ *		Support to set/get fragmentation threshold.
+ *		Support to set/get AP density.
+ *		Support to set/get port type.
+ *		Fixed a problem with ioctl calls when setting station/network
+ *			name, where the new name string wasn't in kernel space
+ *			(thanks to Danton Nunes).
+ *		Driver sucessful tested on AlphaLinux (thanks to Peter Olson).
+ *		Driver sucessful tested with WaveLAN Turbo cards.
+ *
+ *	v0.2.7	1999/07/20
+ *		Changed release/detach code to fix hotswapping with 2.2/2.3
+ *			kernels (thanks to Derrick J Brashear).
+ *		Fixed wrong adjustment of receive buffer length. This was only
+ *			a problem when a higher level protocol relies on correct
+ *			length information, so it never occured with IPv4
+ *			(thanks to Henrik Gulbrandsen).
+ *
+ *	v0.2.6	1999/05/04
+ *		Added wireless spy and histogram support. Signal levels
+ *			are now reported in ad-hoc mode correctly, but you
+ *			need to use iwspy for it, because we can 'hear' more
+ *			than one remote host in ad-hoc mode (thanks
+ *			to Albert K T Hui for the code and to Richard van
+ *			Leeuwen for the technical details).
+ *		Fixed a bug with wrong tx_bytes count.
+ *		Added GPL file wvlan.COPYING.
+ *
+ *	v0.2.5	1999/03/12
+ *		Hopefully fixed problems with the Makefile patch.
+ *		Changed the interrupt service routine to do never lock up
+ *			in an endless loop (if this ever would happen...).
+ *		Missed a conditional which made the driver unable to compile
+ *			on 2.0.x kernels (thanks to Glenn D. Golden).
+ *
+ *	v0.2.4	1999/03/10
+ *		Tested in ad-hoc mode and with access point (many thanks
+ *			to Frank Bruegmann, who made some hardware available
+ *			to me so that I can now test it myself).
+ *		Change the interrupt service routine to repeat on frame
+ *			reception and deallocate the NICs receiving frame
+ *			buffer correctly (thanks to Glenn D. Golden).
+ *		Fixed a problem with checksums where under some circumstances
+ *			an incorrect packet wasn't recognized. Switched
+ *			on the kernel checksum checking (thanks to Glenn D. Golden).
+ *		Setting the channel value is now checked against valid channel
+ *			values which are read from the card.
+ *		Added private ioctl (iwconfig priv) station_name, network_name
+ *			and current_network. It needs an iwconfig capable of
+ *			setting and gettings strings (thanks to Justin Seger).
+ *		Ioctl (iwconfig) should now return the real current used channel.
+ *		Setting the channel value is now only valid using ad-hoc mode.
+ *			It's useless when using an access points.
+ *		Renamed the ssid parameter to network_name and made it work
+ *			correctly for all port_types. It should work now
+ *			in ad-hoc networks as well as with access points.
+ *		Added entries for the NCR WaveLAN/IEEE and the Cabletron
+ *			RoamAbout 802.11 DS card (thanks to Richard van Leeuwen)
+ *		Support to count the received and transmitted bytes
+ *			if kernel version >2.1.25.
+ *		Changed the reset method in case of Tx-timeouts.
+ *		PM suspend/resume should work now (thanks to Dave Kristol).
+ *		Changed installation and driver package. Read INSTALL in this
+ *			file for information how it works now.
+ *
+ *	v0.2.3	1999/02/25
+ *		Added support to set the own SSID
+ *		Changed standard channel setting to 3 so that it works
+ *			with Windows without specifying a channel (the
+ *			Windows driver seem to default to channel 3).
+ *		Fixed two problems with the Ethernet-II frame de/encapsulation.
+ *
+ *	v0.2.2	1999/02/07
+ *		First public beta release.
+ *		Added support to get link quality via iwconfig.
+ *		Added support to change channel via iwconfig.
+ *		Added changeable MTU setting (thanks to Tomasz Motylewski).
+ *		Added Ethernet-II frame de/encapsulation, because
+ *			HCF-Light doesn't support it.
+ *
+ *	v0.2.1	1999/02/03
+ *		Added channel parameter.
+ *		Rewrote the driver with information made public
+ *			in Lucent's HCF-Light library. The HCF was
+ *			slightly modified to get rid of the compiler
+ *			warnings. The filenames were prefixed with
+ *			wvlan_ to better fit into the pcmcia package.
+ *
+ *	v0.1d	1998/12/21
+ *		Fixed a problem where the NIC was crashing during heavy
+ *			loaded transmissions. Interrupts are now disabled
+ *			during wvlan_tx() function. Seems to work fine now.
+ *
+ *	v0.1c	1998/12/20
+ *		Driver works fine with ad-hoc network.
+ *
+ *	v0.1b	1998/12/19
+ *		First successful send-tests.
+ *
+ *	v0.1a	1998/12/18
+ *		First tests with card functions.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+#include <pcmcia/config.h>
+#include <pcmcia/k_compat.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/wireless.h>
+#if WIRELESS_EXT < 5
+#error "Wireless extension v5 or newer required"
+#endif
+#define WIRELESS_SPY		// enable iwspy support
+#undef HISTOGRAM		// disable histogram of signal levels
+
+// This is needed for station_name, but we may not compile WIRELESS_EXT
+#ifndef IW_ESSID_MAX_SIZE
+#define IW_ESSID_MAX_SIZE	32
+#endif /* IW_ESSID_MAX_SIZE */
+
+#include "wvlan_hcf.h"
+
+/* #define PCMCIA_DEBUG 1	// For developer only :-) */
+
+// Undefine this if you want to ignore Tx timeouts
+// (i.e. card will not be reset on Tx timeouts)
+#define WVLAN_RESET_ON_TX_TIMEOUT
+
+
+/********************************************************************
+ * DEBUG
+ */
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>=(n)) printk(KERN_DEBUG args);
+#else
+#define DEBUG(n, args...) {}
+#endif
+#define DEBUG_INFO		1
+#define DEBUG_NOISY		2
+#define DEBUG_TXRX		3
+#define DEBUG_CALLTRACE		4
+#define DEBUG_INTERRUPT		5
+
+
+/********************************************************************
+ * MISC
+ */
+static char *version = "1.0.4";
+static dev_info_t dev_info = "wvlan_cs";
+static dev_link_t *dev_list = NULL;
+
+// Module parameters
+// Note: all these module parameters should really be "per-device", as
+// opposed to global. It mean converting everything to array and
+// referencing by the dev_list index (to add).
+static u_int irq_mask = 0xdeb8;				// Interrupt mask
+static int irq_list[4] = { -1 };			// Interrupt list (alternative)
+static int port_type = 1;				// Port-type [1]
+static char station_name[IW_ESSID_MAX_SIZE+1] = "\0";	// Name of station []
+static char network_name[IW_ESSID_MAX_SIZE+1] = "\0";	// Name of network []
+static int channel = 3;					// Channel [3]
+static int ap_density = 1;				// AP density [1]
+static int medium_reservation = 2347;			// RTS threshold [2347]
+static int frag_threshold = 2346;			// Fragmentation threshold [2346]
+static int transmit_rate = 3;				// Transmit rate [3]
+static int eth = 0;
+static int mtu = 1500;
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+MODULE_PARM(port_type, "i");
+MODULE_PARM(station_name, "c" __MODULE_STRING(IW_ESSID_MAX_SIZE));
+MODULE_PARM(network_name, "c" __MODULE_STRING(IW_ESSID_MAX_SIZE));
+MODULE_PARM(channel, "i");
+MODULE_PARM(ap_density, "i");
+MODULE_PARM(medium_reservation, "i");
+MODULE_PARM(frag_threshold, "i");
+MODULE_PARM(transmit_rate, "i");
+MODULE_PARM(eth, "i");
+MODULE_PARM(mtu, "i");
+
+// Useful macros we have in pcmcia-cs but not in the kernel
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
+#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
+#define skb_tx_check(dev, skb)
+#define add_rx_bytes(stats, n) (stats)->rx_bytes += n;
+#define add_tx_bytes(stats, n) (stats)->tx_bytes += n;
+#endif
+
+// Ethernet timeout is ((400*HZ)/1000), but we should use a higher
+// value, because wireless transmissions are much slower
+#define TX_TIMEOUT ((4000*HZ)/1000)
+
+// Ethernet-II snap header
+static char snap_header[] = { 0x00, 0x00, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+
+// Valid MTU values (HCF_MAX_MSG (2304) is the max hardware frame size)
+#define WVLAN_MIN_MTU 256
+#define WVLAN_MAX_MTU (HCF_MAX_MSG - sizeof(snap_header))
+
+// Max number of multicast addresses that the filter can accept
+#define WVLAN_MAX_MULTICAST GROUP_ADDR_SIZE/6
+
+// Frequency list (map channels to frequencies)
+const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+				2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+
+// Bit-rate list in 1/2 Mb/s (first is dummy - not for original turbo)
+const int rate_list[] = { 0, 2, 4, -255, 11, 22, -4, -11, 0, 0, 0, 0 };
+
+// A few details needed for WEP (Wireless Equivalent Privacy)
+#define MAX_KEY_SIZE 14			// 128 (?) bits
+#define MIN_KEY_SIZE  5			// 40 bits RC4 - WEP
+#define MAX_KEYS      4			// 4 different keys
+
+// Keep track of wvlanX devices
+#define MAX_WVLAN_CARDS 16
+static struct net_device *wvlandev_index[MAX_WVLAN_CARDS];
+
+// Local data for netdevice
+struct net_local {
+	dev_node_t		node;
+	struct net_device	*dev;		// backtrack device
+	dev_link_t		*link;		// backtrack link
+	spinlock_t		slock;		// spinlock
+	int			interrupt;	// interrupt
+	IFB_STRCT		ifb;		// WaveLAN structure
+	struct net_device_stats	stats;		// device stats
+	u_char			promiscuous;	// Promiscuous mode
+	u_char			allmulticast;	// All multicast mode
+	int			mc_count;	// Number of multicast addrs
+#ifdef WIRELESS_EXT
+	struct iw_statistics	wstats;		// wireless stats
+#ifdef WIRELESS_SPY
+	int			spy_number;
+	u_char			spy_address[IW_MAX_SPY][MAC_ADDR_SIZE];
+	struct iw_quality	spy_stat[IW_MAX_SPY];
+#endif
+#ifdef HISTOGRAM
+	int			his_number;
+	u_char			his_range[16];
+	u_long			his_sum[16];
+#endif
+	int			wep_on;		// WEP enabled
+	int			transmit_key;	// Key used for transmissions
+	KEY_STRCT		key[MAX_KEYS];	// WEP keys & size
+#endif /* WIRELESS_EXT */
+};
+
+// Shortcuts
+#ifdef WIRELESS_EXT
+typedef struct iw_statistics	iw_stats;
+typedef struct iw_quality	iw_qual;
+typedef struct iw_freq		iw_freq;
+#endif /* WIRELESS_EXT */
+
+// Show CardServices error message (syslog)
+static void cs_error (client_handle_t handle, int func, int ret)
+{
+	error_info_t err = { func, ret };
+	CardServices(ReportError, handle, &err);
+}
+
+
+/********************************************************************
+ * FUNCTION PROTOTYPES
+ */
+int wvlan_hw_setmaxdatalen (IFBP ifbp, int maxlen);
+int wvlan_hw_getmacaddr (IFBP ifbp, char *mac, int len);
+int wvlan_hw_getchannellist (IFBP ifbp);
+int wvlan_hw_setporttype (IFBP ifbp, int ptype);
+int wvlan_hw_getporttype (IFBP ifbp);
+int wvlan_hw_setstationname (IFBP ifbp, char *name);
+int wvlan_hw_getstationname (IFBP ifbp, char *name, int len);
+int wvlan_hw_setssid (IFBP ifbp, char *name);
+int wvlan_hw_getssid (IFBP ifbp, char *name, int len, int cur);
+int wvlan_hw_getbssid (IFBP ifbp, char *mac, int len);
+int wvlan_hw_setchannel (IFBP ifbp, int channel);
+int wvlan_hw_getchannel (IFBP ifbp);
+int wvlan_hw_getcurrentchannel (IFBP ifbp);
+int wvlan_hw_setthreshold (IFBP ifbp, int thrh, int cmd);
+int wvlan_hw_getthreshold (IFBP ifbp, int cmd);
+int wvlan_hw_setbitrate (IFBP ifbp, int brate);
+int wvlan_hw_getbitrate (IFBP ifbp, int cur);
+int wvlan_hw_getratelist (IFBP ifbp, char *brlist);
+#ifdef WIRELESS_EXT
+int wvlan_hw_getfrequencylist (IFBP ifbp, iw_freq *list, int max);
+int wvlan_getbitratelist (IFBP ifbp, __s32 *list, int max);
+#endif /* WIRELESS_EXT */
+#if WIRELESS_EXT > 8
+int wvlan_hw_setpower (IFBP ifbp, int enabled, int cmd);
+int wvlan_hw_getpower (IFBP ifbp, int cmd);
+int wvlan_hw_setpmsleep (IFBP ifbp, int duration);
+int wvlan_hw_getpmsleep (IFBP ifbp);
+int wvlan_hw_getprivacy (IFBP ifbp);
+int wvlan_hw_setprivacy (IFBP ifbp, int mode, int transmit, KEY_STRCT *keys);
+#endif /* WIRELESS_EXT > 8 */
+static int wvlan_hw_setpromisc (IFBP ifbp, int promisc);
+
+int wvlan_hw_config (struct net_device *dev);
+int wvlan_hw_shutdown (struct net_device *dev);
+int wvlan_hw_reset (struct net_device *dev);
+
+struct net_device_stats *wvlan_get_stats (struct net_device *dev);
+#ifdef WIRELESS_EXT
+int wvlan_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+struct iw_statistics *wvlan_get_wireless_stats (struct net_device *dev);
+#ifdef WIRELESS_SPY
+static inline void wvlan_spy_gather (struct net_device *dev, u_char *mac, u_char *stats);
+#endif
+#ifdef HISTOGRAM
+static inline void wvlan_his_gather (struct net_device *dev, u_char *stats);
+#endif
+#endif /* WIRELESS_EXT */
+int wvlan_change_mtu (struct net_device *dev, int new_mtu);
+static void wvlan_set_multicast_list (struct net_device *dev);
+
+static void wvlan_watchdog (struct net_device *dev);
+int wvlan_tx (struct sk_buff *skb, struct net_device *dev);
+void wvlan_rx (struct net_device *dev, int len);
+
+static int wvlan_init (struct net_device *dev);
+static int wvlan_open (struct net_device *dev);
+static int wvlan_close (struct net_device *dev);
+
+static void wvlan_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+
+static int wvlan_config (dev_link_t *link);
+static void wvlan_release (u_long arg);
+
+static dev_link_t *wvlan_attach (void);
+static void wvlan_detach (dev_link_t *link);
+
+static int wvlan_event (event_t event, int priority, event_callback_args_t *args);
+
+extern int init_module (void);
+extern void cleanup_module (void);
+
+
+/********************************************************************
+ * HARDWARE SETTINGS
+ */
+// Stupid constants helping clarity
+#define WVLAN_CURRENT	1
+#define WVLAN_DESIRED	0
+
+int wvlan_hw_setmaxdatalen (IFBP ifbp, int maxlen)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_MAX_DATA_LEN;
+	ltv.id[0] = maxlen;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_MAX_DATA_LEN:0x%x) returned 0x%x\n", dev_info, maxlen, rc);
+	return rc;
+}
+
+int wvlan_hw_getmacaddr (IFBP ifbp, char *mac, int len)
+{
+	CFG_MAC_ADDR_STRCT ltv;
+	int rc, l;
+
+	ltv.len = 4;
+	ltv.typ = CFG_CNF_OWN_MAC_ADDR;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_OWN_MAC_ADDR) returned 0x%x\n", dev_info, rc);
+	if (rc)
+		return rc;
+	l = min(len, ltv.len*2);
+	memcpy(mac, (char *)ltv.mac_addr, l);
+	return 0;
+}
+
+int wvlan_hw_getchannellist (IFBP ifbp)
+{
+	CFG_ID_STRCT ltv;
+	int rc, chlist;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CHANNEL_LIST;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	chlist = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CHANNEL_LIST):0x%x returned 0x%x\n", dev_info, chlist, rc);
+	return rc ? 0 : chlist;
+}
+
+int wvlan_hw_setporttype (IFBP ifbp, int ptype)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_PORT_TYPE;
+	ltv.id[0] = ptype;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_PORT_TYPE:0x%x) returned 0x%x\n", dev_info, ptype, rc);
+	return rc;
+}
+
+int wvlan_hw_getporttype (IFBP ifbp)
+{
+	CFG_ID_STRCT ltv;
+	int rc, ptype;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_PORT_TYPE;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	ptype = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_PORT_TYPE):0x%x returned 0x%x\n", dev_info, ptype, rc);
+	return rc ? 0 : ptype;
+}
+
+int wvlan_hw_setstationname (IFBP ifbp, char *name)
+{
+	CFG_ID_STRCT ltv;
+	int rc, l;
+
+	ltv.len = 18;
+	ltv.typ = CFG_CNF_OWN_NAME;
+	l = min(strlen(name), ltv.len*2);
+	ltv.id[0] = l;
+	memcpy((char *) &ltv.id[1], name, l);
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_OWN_NAME:'%s') returned 0x%x\n", dev_info, name, rc);
+	return rc;
+}
+
+int wvlan_hw_getstationname (IFBP ifbp, char *name, int len)
+{
+	CFG_ID_STRCT ltv;
+	int rc, l;
+
+	ltv.len = 18;
+	ltv.typ = CFG_CNF_OWN_NAME;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_OWN_NAME) returned 0x%x\n", dev_info, rc);
+	if (rc)
+		return rc;
+	if (ltv.id[0])
+		l = min(len, ltv.id[0]);
+	else
+		l = min(len, ltv.len*2);	/* It's a feature */
+	memcpy(name, (char *) &ltv.id[1], l);
+	name[l] = 0;
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_OWN_NAME):'%s'\n", dev_info, name);
+	return 0;
+}
+
+int wvlan_hw_setssid (IFBP ifbp, char *name)
+{
+	CFG_ID_STRCT ltv;
+	int rc, l;
+
+	ltv.len = 18;
+	if (port_type == 3)
+		ltv.typ = CFG_CNF_OWN_SSID;
+	else
+		ltv.typ = CFG_CNF_DESIRED_SSID;
+	l = min(strlen(name), ltv.len*2);
+	ltv.id[0] = l;
+	memcpy((char *) &ltv.id[1], name, l);
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_OWN/DESIRED_SSID:'%s') returned 0x%x\n", dev_info, name, rc);
+	return rc;
+}
+
+int wvlan_hw_getssid (IFBP ifbp, char *name, int len, int cur)
+{
+	CFG_ID_STRCT ltv;
+	int rc, l;
+
+	ltv.len = 18;
+	if (cur)
+		ltv.typ = CFG_CURRENT_SSID;
+	else
+		if (port_type == 3)
+			ltv.typ = CFG_CNF_OWN_SSID;
+		else
+			ltv.typ = CFG_CNF_DESIRED_SSID;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_OWN/DESIRED/CURRENT_SSID) returned 0x%x\n", dev_info, rc);
+	if (rc)
+		return rc;
+	if (ltv.id[0])
+	{
+		l = min(len, ltv.id[0]);
+		memcpy(name, (char *) &ltv.id[1], l);
+	}
+	else
+		l = 0;
+	name[l] = '\0';
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_OWN/DESIRED/CURRENT_SSID):'%s'\n", dev_info, name);
+	return 0;
+}
+
+int wvlan_hw_getbssid (IFBP ifbp, char *mac, int len)
+{
+	CFG_MAC_ADDR_STRCT ltv;
+	int rc, l;
+
+	ltv.len = 4;
+	ltv.typ = CFG_CURRENT_BSSID;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CURRENT_BSSID) returned 0x%x\n", dev_info, rc);
+	if (rc)
+		return rc;
+	l = min(len, ltv.len*2);
+	memcpy(mac, (char *)ltv.mac_addr, l);
+	return 0;
+}
+
+int wvlan_hw_setchannel (IFBP ifbp, int channel)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_OWN_CHANNEL;
+	ltv.id[0] = channel;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_OWN_CHANNEL:0x%x) returned 0x%x\n", dev_info, channel, rc);
+	return rc;
+}
+
+int wvlan_hw_getchannel (IFBP ifbp)
+{
+	CFG_ID_STRCT ltv;
+	int rc, channel;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_OWN_CHANNEL;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	channel = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CNF_OWN_CHANNEL):0x%x returned 0x%x\n", dev_info, channel, rc);
+	return rc ? 0 : channel;
+}
+
+int wvlan_hw_getcurrentchannel (IFBP ifbp)
+{
+	CFG_ID_STRCT ltv;
+	int rc, channel;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CURRENT_CHANNEL;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	channel = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CURRENT_CHANNEL):0x%x returned 0x%x\n", dev_info, channel, rc);
+	return rc ? 0 : channel;
+}
+
+int wvlan_hw_setthreshold (IFBP ifbp, int thrh, int cmd)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = cmd;
+	ltv.id[0] = thrh;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(0x%x:0x%x) returned 0x%x\n", dev_info, cmd, thrh, rc);
+	return rc;
+}
+
+int wvlan_hw_getthreshold (IFBP ifbp, int cmd)
+{
+	CFG_ID_STRCT ltv;
+	int rc, thrh;
+
+	ltv.len = 2;
+	ltv.typ = cmd;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	thrh = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(0x%x):0x%x returned 0x%x\n", dev_info, cmd, thrh, rc);
+	return rc ? 0 : thrh;
+}
+
+int wvlan_hw_setbitrate (IFBP ifbp, int brate)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = CFG_TX_RATE_CONTROL;
+	ltv.id[0] = brate;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_TX_RATE_CONTROL:0x%x) returned 0x%x\n", dev_info, brate, rc);
+	return rc;
+}
+
+int wvlan_hw_getbitrate (IFBP ifbp, int cur)
+{
+	CFG_ID_STRCT ltv;
+	int rc, brate;
+
+	ltv.len = 2;
+	ltv.typ = cur ? CFG_CURRENT_TX_RATE : CFG_TX_RATE_CONTROL;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	brate = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_TX_RATE_CONTROL):0x%x returned 0x%x\n", dev_info, brate, rc);
+	return rc ? 0 : brate;
+}
+
+int wvlan_hw_getratelist(IFBP ifbp, char *brlist)
+{
+	CFG_ID_STRCT ltv;
+	int rc, brnum;
+
+	ltv.len = 10;
+	ltv.typ = CFG_SUPPORTED_DATA_RATES;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	brnum = ltv.id[0];
+	memcpy(brlist, (char *) &ltv.id[1], brnum);
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_CHANNEL_LIST):0x%x returned 0x%x\n", dev_info, brnum, rc);
+	return rc ? 0 : brnum;
+}
+
+#ifdef WIRELESS_EXT
+int wvlan_hw_getfrequencylist(IFBP ifbp, iw_freq *list, int max)
+{
+	int chlist = wvlan_hw_getchannellist(ifbp);
+	int i, k = 0;
+
+	/* Compute maximum number of freq to scan */
+	if(max > 15)
+		max = 15;
+
+	/* Check availability */
+	for(i = 0; i < max; i++)
+		if((1 << i) & chlist)
+		{
+#if WIRELESS_EXT > 7
+			list[k].i = i + 1;	/* Set the list index */
+#endif /* WIRELESS_EXT */
+			list[k].m = frequency_list[i] * 100000;
+			list[k++].e = 1;	/* Values in table in MHz -> * 10^5 * 10 */
+		}
+
+	return k;
+}
+
+int wvlan_getbitratelist(IFBP ifbp, __s32 *list, int max)
+{
+	char brlist[9];
+	int brnum = wvlan_hw_getratelist(ifbp, brlist);
+	int i;
+
+	/* Compute maximum number of freq to scan */
+	if(brnum > max)
+		brnum = max;
+
+	/* Convert to Mb/s */
+	for(i = 0; i < max; i++)
+		list[i] = (brlist[i] & 0x7F) * 500000;
+
+	return brnum;
+}
+#endif /* WIRELESS_EXT */
+
+#if WIRELESS_EXT > 8
+int wvlan_hw_setpower (IFBP ifbp, int enabled, int cmd)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = cmd;
+	ltv.id[0] = enabled;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(0x%x:0x%x) returned 0x%x\n", dev_info, cmd, enabled, rc);
+	return rc;
+}
+
+int wvlan_hw_getpower (IFBP ifbp, int cmd)
+{
+	CFG_ID_STRCT ltv;
+	int rc, enabled;
+
+	ltv.len = 2;
+	ltv.typ = cmd;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	enabled = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(0x%x):0x%x returned 0x%x\n", dev_info, cmd, enabled, rc);
+	return rc ? 0 : enabled;
+}
+
+int wvlan_hw_setpmsleep (IFBP ifbp, int duration)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_MAX_SLEEP_DURATION;
+	ltv.id[0] = duration;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CNF_MAX_SLEEP_DURATION:0x%x) returned 0x%x\n", dev_info, duration, rc);
+	return rc;
+}
+
+int wvlan_hw_getpmsleep (IFBP ifbp)
+{
+	CFG_ID_STRCT ltv;
+	int rc, duration;
+
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_MAX_SLEEP_DURATION;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	duration = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CNF_MAX_SLEEP_DURATION):0x%x returned 0x%x\n", dev_info, duration, rc);
+	return rc ? 0 : duration;
+}
+
+int wvlan_hw_getprivacy (IFBP ifbp)
+{
+	CFG_ID_STRCT ltv;
+	int rc, privacy;
+
+	// This function allow to distiguish bronze cards from other
+	// types, to know if WEP exist...
+	// This is stupid, we have no way to distinguish the silver
+	// and gold cards, because the call below return 1 in all
+	// cases. Yuk...
+	ltv.len = 2;
+	ltv.typ = CFG_PRIVACY_OPTION_IMPLEMENTED;
+	rc = hcf_get_info(ifbp, (LTVP) &ltv);
+	privacy = ltv.id[0];
+	DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CNF_MAX_SLEEP_DURATION):0x%x returned 0x%x\n", dev_info, privacy, rc);
+	return rc ? 0 : privacy;
+}
+
+int wvlan_hw_setprivacy (IFBP ifbp, int mode, int transmit, KEY_STRCT *keys)
+{
+	CFG_ID_STRCT ltv;
+	CFG_CNF_DEFAULT_KEYS_STRCT ltv_key;
+	int rc;
+
+	if (mode)
+	{
+		// Set the index of the key used for transmission
+		ltv.len = 2;
+		ltv.typ = CFG_CNF_TX_KEY_ID;
+		ltv.id[0] = transmit;
+		rc = hcf_put_info(ifbp, (LTVP) &ltv);
+		DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_TX_KEY_ID:0x%x) returned 0x%x\n", dev_info, mode, rc);
+		if (rc)
+			return rc;
+
+		// Set the keys themselves (all in on go !)
+		ltv_key.len = sizeof(KEY_STRCT)*MAX_KEYS/2 + 1;
+		ltv_key.typ = CFG_CNF_DEFAULT_KEYS;
+		memcpy((char *) &ltv_key.key, (char *) keys, sizeof(KEY_STRCT)*MAX_KEYS);
+		rc = hcf_put_info(ifbp, (LTVP) &ltv_key);
+		DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_TX_KEY_ID:0x%x) returned 0x%x\n", dev_info, mode, rc);
+		if (rc)
+			return rc;
+	}
+	// enable/disable encryption
+	ltv.len = 2;
+	ltv.typ = CFG_CNF_ENCRYPTION;
+	ltv.id[0] = mode;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_ENCRYPTION:0x%x) returned 0x%x\n", dev_info, mode, rc);
+	return rc;
+}
+#endif /* WIRELESS_EXT > 8 */
+
+static int wvlan_hw_setpromisc (IFBP ifbp, int promisc)
+{
+	CFG_ID_STRCT ltv;
+	int rc;
+
+	ltv.len = 2;
+	ltv.typ = CFG_PROMISCUOUS_MODE;
+	ltv.id[0] = promisc;
+	rc = hcf_put_info(ifbp, (LTVP) &ltv);
+	DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_PROMISCUOUS_MODE:0x%x) returned 0x%x\n", dev_info, promisc, rc);
+	return rc;
+}
+
+
+/********************************************************************
+ * HARDWARE CONFIG / SHUTDOWN / RESET
+ */
+int wvlan_hw_config (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	unsigned long flags;
+	int rc, i, chlist;
+
+	// TODO: Parameters should be stored per-device (in dev->priv).
+	// The problem is that this function erase all the per-device config
+	// done via Wireless Extensions with global variables (ouch!). This
+	// means that multi-card setup are guaranteed not to work.
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_hw_config(%s)\n", dev->name);
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	// Init the HCF library
+	hcf_connect(&local->ifb, dev->base_addr);
+
+	// Init hardware and turn on interrupts
+	rc = hcf_action(&local->ifb, HCF_ACT_CARD_IN);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_CARD_IN) returned 0x%x\n", dev_info, rc);
+#if defined(PCMCIA_DEBUG) && (PCMCIA_DEBUG>=DEBUG_INTERRUPT)
+	local->ifb.IFB_IntEnMask |= HREG_EV_TICK;
+#endif
+	rc = hcf_action(&local->ifb, HCF_ACT_INT_ON);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_ON) returned 0x%x\n", dev_info, rc);
+
+	// Set hardware parameters
+	if (!rc)
+		rc = wvlan_hw_setmaxdatalen(&local->ifb, HCF_MAX_MSG);
+	if (!rc)
+		rc = wvlan_hw_setporttype(&local->ifb, port_type);
+	if (!rc && *station_name)
+		rc = wvlan_hw_setstationname(&local->ifb, station_name);
+	if (!rc && *network_name)
+		rc = wvlan_hw_setssid(&local->ifb, network_name);
+	if (!rc)
+		rc = wvlan_hw_setthreshold(&local->ifb, ap_density, CFG_CNF_SYSTEM_SCALE);
+	if (!rc)
+		rc = wvlan_hw_setthreshold(&local->ifb, medium_reservation, CFG_RTS_THRH);
+	if (!rc)
+		rc = wvlan_hw_setthreshold(&local->ifb, frag_threshold, CFG_FRAGMENTATION_THRH);
+	if (!rc)
+		rc = wvlan_hw_setthreshold(&local->ifb, transmit_rate, CFG_TX_RATE_CONTROL);
+
+	// Check valid channel settings
+	if (!rc && port_type == 3)
+	{
+		chlist = wvlan_hw_getchannellist(&local->ifb);
+		printk(KERN_INFO "%s: Valid channels: ", dev_info);
+		for (i=1; i<17; i++)
+			if (1<<(i-1) & chlist)
+				printk("%d ", i);
+		printk("\n");
+		if (channel<1 || channel>16 || !(1<<(channel-1) & chlist))
+			printk(KERN_WARNING "%s: Channel value of %d is invalid!\n", dev_info, channel);
+		else
+			rc = wvlan_hw_setchannel(&local->ifb, channel);
+	}
+
+	// Enable hardware
+	if (!rc)
+	{
+		rc = hcf_enable(&local->ifb, 0);
+		DEBUG(DEBUG_NOISY, "%s: hcf_enable(0) returned 0x%x\n", dev_info, rc);
+	}
+
+	// Get MAC address
+	if (!rc)
+	{
+		rc = wvlan_hw_getmacaddr(&local->ifb, dev->dev_addr, ETH_ALEN);
+		printk(KERN_INFO "%s: MAC address on %s is ", dev_info, dev->name);
+		for (i=0; i<ETH_ALEN; i++)
+			printk("%02x ", dev->dev_addr[i]);
+		printk("\n");
+	}
+
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	// Report error if any
+	if (rc)
+		printk(KERN_WARNING "%s: Initialization failed!\n", dev_info);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_hw_config()\n");
+	return rc;
+}
+
+int wvlan_hw_shutdown (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	unsigned long flags;
+	int rc;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_hw_shutdown(%s)\n", dev->name);
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	// Disable and shutdown hardware
+	rc = hcf_disable(&local->ifb, 0);
+	DEBUG(DEBUG_NOISY, "%s: hcf_disable(0) returned 0x%x\n", dev_info, rc);
+	rc = hcf_action(&local->ifb, HCF_ACT_INT_OFF);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_OFF) returned 0x%x\n", dev_info, rc);
+	rc = hcf_action(&local->ifb, HCF_ACT_CARD_OUT);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_CARD_OUT) returned 0x%x\n", dev_info, rc);
+
+	// Release HCF library
+	hcf_disconnect(&local->ifb);
+
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_hw_shutdown()\n");
+	return 0;
+}
+
+int wvlan_hw_reset (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	unsigned long flags;
+	int rc;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_hw_reset(%s)\n", dev->name);
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	// Disable hardware
+	rc = hcf_disable(&local->ifb, 0);
+	DEBUG(DEBUG_NOISY, "%s: hcf_disable(0) returned 0x%x\n", dev_info, rc);
+	rc = hcf_action(&local->ifb, HCF_ACT_INT_OFF);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_OFF) returned 0x%x\n", dev_info, rc);
+
+	// Re-Enable hardware
+	rc = hcf_action(&local->ifb, HCF_ACT_INT_ON);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_ON) returned 0x%x\n", dev_info, rc);
+	rc = hcf_enable(&local->ifb, 0);
+	DEBUG(DEBUG_NOISY, "%s: hcf_enable(0) returned 0x%x\n", dev_info, rc);
+
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_hw_reset()\n");
+	return rc;
+}
+
+
+/********************************************************************
+ * NET STATS / IOCTL
+ */
+struct net_device_stats *wvlan_get_stats (struct net_device *dev)
+{
+	DEBUG(DEBUG_CALLTRACE, "<> wvlan_get_stats(%s)\n", dev->name);
+	return(&((struct net_local *) dev->priv)->stats);
+}
+
+#ifdef WIRELESS_EXT
+int wvlan_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	struct iwreq *wrq = (struct iwreq *) rq;
+	unsigned long flags;
+	int rc = 0;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_ioctl(%s, cmd=0x%x)\n", dev->name, cmd);
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	switch (cmd)
+	{
+		// Get name
+		case SIOCGIWNAME:
+			strcpy(wrq->u.name, "IEEE 802.11-DS");
+			break;
+
+		// Set frequency/channel
+		case SIOCSIWFREQ:
+			// If setting by frequency, convert to a channel
+			if((wrq->u.freq.e == 1) &&
+			   (wrq->u.freq.m >= (int) 2.412e8) &&
+			   (wrq->u.freq.m <= (int) 2.487e8))
+			{
+				int f = wrq->u.freq.m / 100000;
+				int c = 0;
+				while((c < 14) && (f != frequency_list[c]))
+					c++;
+				// Hack to fall through...
+				wrq->u.freq.e = 0;
+				wrq->u.freq.m = c + 1;
+			}
+			// Setting by channel number
+			if ((port_type != 3) || (wrq->u.freq.m > 1000) || (wrq->u.freq.e > 0))
+				rc = -EOPNOTSUPP;
+			else
+			{
+				int channel = wrq->u.freq.m;
+				int chlist = wvlan_hw_getchannellist(&local->ifb);
+				if (channel<1 || channel>16 || !(1<<(channel-1) & chlist))
+				{
+					DEBUG(DEBUG_INFO, "%s: New channel value of %d for %s is invalid!\n", dev_info, wrq->u.freq.m, dev->name);
+					rc = -EINVAL;
+				}
+				else
+				{
+					wvlan_hw_setchannel(&local->ifb, wrq->u.freq.m);
+					wvlan_hw_reset(dev);
+					channel = wrq->u.freq.m;
+				}
+			}
+			break;
+
+		// Get frequency/channel
+		case SIOCGIWFREQ:
+#ifdef WEXT_USECHANNELS
+			wrq->u.freq.m = wvlan_hw_getcurrentchannel(&local->ifb);
+			wrq->u.freq.e = 0;
+#else
+			{
+				int f = wvlan_hw_getcurrentchannel(&local->ifb);
+				wrq->u.freq.m = frequency_list[f-1] * 100000;
+				wrq->u.freq.e = 1;
+			}
+#endif
+			break;
+
+#if WIRELESS_EXT > 5
+		// Set desired network name (ESSID)
+		case SIOCSIWESSID:
+			if (wrq->u.data.pointer)
+			{
+				char	essid[IW_ESSID_MAX_SIZE + 1];
+
+				/* Check if we asked for `any' */
+				if(wrq->u.data.flags == 0)
+				{
+					essid[0] = '\0';
+				}
+				else
+				{
+					/* Check the size of the string */
+					if(wrq->u.data.length >
+					   IW_ESSID_MAX_SIZE + 1)
+					{
+						rc = -E2BIG;
+						break;
+					}
+					copy_from_user(essid,
+						       wrq->u.data.pointer,
+						       wrq->u.data.length);
+					essid[IW_ESSID_MAX_SIZE] = '\0';
+				}
+				wvlan_hw_setssid(&local->ifb, essid);
+				wvlan_hw_reset(dev);
+				strncpy(network_name, essid, sizeof(network_name)-1);
+			}
+			break;
+
+		// Get current network name (ESSID)
+		case SIOCGIWESSID:
+			if (wrq->u.data.pointer)
+			{
+				char essid[IW_ESSID_MAX_SIZE + 1];
+				/* Get the essid that was set */
+				wvlan_hw_getssid(&local->ifb, essid,
+						 IW_ESSID_MAX_SIZE,
+						 WVLAN_DESIRED);
+				/* If it was set to any, get the current one */
+				if(strlen(essid) == 0)
+					wvlan_hw_getssid(&local->ifb, essid,
+							 IW_ESSID_MAX_SIZE,
+							 WVLAN_CURRENT);
+
+				/* Push it out ! */
+				wrq->u.data.length = strlen(essid) + 1;
+				wrq->u.data.flags = 1; /* active */
+				copy_to_user(wrq->u.data.pointer, essid, sizeof(essid));
+			}
+			break;
+
+		// Get current Access Point (BSSID)
+		case SIOCGIWAP:
+			wvlan_hw_getbssid(&local->ifb, wrq->u.ap_addr.sa_data, ETH_ALEN);
+			wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+			break;
+
+#endif	/* WIRELESS_EXT > 5 */
+
+#if WIRELESS_EXT > 7
+		// Set desired station name
+		case SIOCSIWNICKN:
+			if (wrq->u.data.pointer)
+			{
+				char	name[IW_ESSID_MAX_SIZE + 1];
+
+				/* Check the size of the string */
+				if(wrq->u.data.length > IW_ESSID_MAX_SIZE + 1)
+				{
+					rc = -E2BIG;
+					break;
+				}
+				copy_from_user(name, wrq->u.data.pointer, wrq->u.data.length);
+				name[IW_ESSID_MAX_SIZE] = '\0';
+				wvlan_hw_setstationname(&local->ifb, name);
+				wvlan_hw_reset(dev);
+				strncpy(station_name, name, sizeof(station_name)-1);
+			}
+			break;
+
+		// Get current station name
+		case SIOCGIWNICKN:
+			if (wrq->u.data.pointer)
+			{
+				char name[IW_ESSID_MAX_SIZE + 1];
+				wvlan_hw_getstationname(&local->ifb, name, IW_ESSID_MAX_SIZE);
+				wrq->u.data.length = strlen(name) + 1;
+				copy_to_user(wrq->u.data.pointer, name, sizeof(name));
+			}
+			break;
+
+		// Set the desired bit-rate
+		case SIOCSIWRATE:
+			{
+				// Start the magic...
+				char	brlist[9];
+				int	brnum = wvlan_hw_getratelist(&local->ifb, brlist);
+				int	brate = wrq->u.bitrate.value/500000;
+				int	wvrate = 0;
+
+				// Auto or fixed ?
+				if(wrq->u.bitrate.fixed == 0)
+					// Let be simple for now...
+					wvrate = 3;
+					// We could read the last desired
+					// channel and set corresp. auto mode
+				else if((wrq->u.bitrate.value <= (brnum * 2 - 1)) &&
+					(wrq->u.bitrate.value > 0))
+				{
+					// Setting by channel index
+					wvrate = wrq->u.bitrate.value;
+				}
+				else
+				{
+					// Setting by frequency value
+					// Find index in magic table
+					while((rate_list[wvrate] != brate) &&
+					      (wvrate < (brnum * 2)))
+						wvrate++;
+
+					// Check if in range
+					if((wvrate < 1) ||
+					   (wvrate >= (brnum * 2)))
+					{
+						rc = -EINVAL;
+						break;
+					}
+				}
+				wvlan_hw_setbitrate(&local->ifb, wvrate);
+				wvlan_hw_reset(dev);
+				transmit_rate = wvrate;
+			}
+			break;
+
+		// Get the current bit-rate
+		case SIOCGIWRATE:
+			{
+				int	wvrate = wvlan_hw_getbitrate(&local->ifb, WVLAN_DESIRED);
+				int	brate = rate_list[wvrate];
+
+				// Auto ?
+				if (brate < 0)
+				{
+					wrq->u.bitrate.fixed = 0;
+					wvrate = wvlan_hw_getbitrate(&local->ifb, WVLAN_CURRENT);
+#if OLD_FIRMWARE
+					// Or maybe I just got it wrong?
+					brate = rate_list[wvrate];
+#else
+					brate = 2 * wvrate;
+					// Mandatory kludge!
+					if (wvrate == 6)
+						brate = 11;
+#endif
+				}
+				else
+					wrq->u.bitrate.fixed = 1;
+
+				wrq->u.bitrate.value = brate * 500000;
+			}
+			break;
+
+		// Set the desired RTS threshold
+		case SIOCSIWRTS:
+			{
+				int rthr = wrq->u.rts.value;
+				// if(wrq->u.rts.fixed == 0) we should complain
+#if WIRELESS_EXT > 8
+				if(wrq->u.rts.disabled)
+					rthr = 2347;
+#endif /* WIRELESS_EXT > 8 */
+				if((rthr < 0) || (rthr > 2347))
+				{
+					rc = -EINVAL;
+					break;
+				}
+				wvlan_hw_setthreshold(&local->ifb, rthr, CFG_RTS_THRH);
+				wvlan_hw_reset(dev);
+				medium_reservation = rthr;
+			}
+			break;
+
+		// Get the current RTS threshold
+		case SIOCGIWRTS:
+			wrq->u.rts.value = wvlan_hw_getthreshold(&local->ifb, CFG_RTS_THRH);
+#if WIRELESS_EXT > 8
+			wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
+#endif /* WIRELESS_EXT > 8 */
+			wrq->u.rts.fixed = 1;
+			break;
+
+		// Set the desired fragmentation threshold
+		case SIOCSIWFRAG:
+			{
+				int fthr = wrq->u.frag.value;
+				// if(wrq->u.frag.fixed == 0) should complain
+#if WIRELESS_EXT > 8
+				if(wrq->u.frag.disabled)
+					fthr = 2346;
+#endif /* WIRELESS_EXT > 8 */
+				if((fthr < 256) || (fthr > 2346))
+				{
+					rc = -EINVAL;
+					break;
+				}
+				fthr &= ~0x1;	// Get an even value
+				wvlan_hw_setthreshold(&local->ifb, fthr, CFG_FRAGMENTATION_THRH);
+				wvlan_hw_reset(dev);
+			}
+			break;
+
+		// Get the current fragmentation threshold
+		case SIOCGIWFRAG:
+			wrq->u.frag.value = wvlan_hw_getthreshold(&local->ifb, CFG_FRAGMENTATION_THRH);
+#if WIRELESS_EXT > 8
+			wrq->u.frag.disabled = (wrq->u.frag.value == 2346);
+#endif /* WIRELESS_EXT > 8 */
+			wrq->u.frag.fixed = 1;
+			break;
+
+		// Set the desired AP density
+		case SIOCSIWSENS:
+			{
+				int dens = wrq->u.sens.value;
+				if((dens < 1) || (dens > 3))
+				{
+					rc = -EINVAL;
+					break;
+				}
+				wvlan_hw_setthreshold(&local->ifb, dens, CFG_CNF_SYSTEM_SCALE);
+				wvlan_hw_reset(dev);
+				ap_density = dens;
+			}
+			break;
+
+		// Get the current AP density
+		case SIOCGIWSENS:
+			wrq->u.sens.value = wvlan_hw_getthreshold(&local->ifb, CFG_CNF_SYSTEM_SCALE);
+			wrq->u.sens.fixed = 0;	/* auto */
+			break;
+#endif	/* WIRELESS_EXT > 7 */
+
+#if WIRELESS_EXT > 8
+		// Set port type
+		case SIOCSIWMODE:
+			{
+				char ptype = 1;
+
+				switch (wrq->u.mode)
+				{
+					case IW_MODE_ADHOC:
+						ptype = 3;
+						// Fall through
+					case IW_MODE_INFRA:
+						wvlan_hw_setporttype(&local->ifb, ptype);
+						wvlan_hw_reset(dev);
+						port_type = ptype;
+						break;
+					default:
+						rc = -EINVAL;
+				}
+			}
+			break;
+
+		// Get port type
+		case SIOCGIWMODE:
+			if (wvlan_hw_getporttype(&local->ifb) == 1)
+				wrq->u.mode = IW_MODE_INFRA;
+			else
+				wrq->u.mode = IW_MODE_ADHOC;
+			break;
+
+		// Set the desired Power Management mode
+		case SIOCSIWPOWER:
+			// Disable it ?
+			if(wrq->u.power.disabled)
+				wvlan_hw_setpower (&local->ifb, 0, CFG_CNF_PM_ENABLED);
+			else
+			{
+				// Check mode
+				switch(wrq->u.power.flags & IW_POWER_MODE)
+				{
+					case IW_POWER_UNICAST_R:
+						wvlan_hw_setpower(&local->ifb, 0, CFG_CNF_MCAST_RX);
+						break;
+					case IW_POWER_ALL_R:
+						wvlan_hw_setpower(&local->ifb, 1, CFG_CNF_MCAST_RX);
+						break;
+					case IW_POWER_ON:	// None = ok
+						break;
+					default:	// Invalid
+						rc = -EINVAL;
+				}
+				// Set period
+				if (wrq->u.power.flags & IW_POWER_PERIOD)
+				{
+					// Activate PM
+					wvlan_hw_setpower(&local->ifb, 1, CFG_CNF_PM_ENABLED);
+					// Hum: check max/min values ?
+					wvlan_hw_setpmsleep (&local->ifb, wrq->u.power.value/1000);
+				}
+				if (wrq->u.power.flags & IW_POWER_TIMEOUT)
+					rc = -EINVAL;	// Invalid
+			}
+			if (!rc)
+				wvlan_hw_reset(dev);
+			break;
+
+		// Get the power management settings
+		case SIOCGIWPOWER:
+			wrq->u.power.disabled = !wvlan_hw_getpower(&local->ifb, CFG_CNF_PM_ENABLED);
+			wrq->u.power.flags = IW_POWER_PERIOD;
+			wrq->u.power.value = wvlan_hw_getpmsleep (&local->ifb) * 1000;
+			if (wvlan_hw_getpower(&local->ifb, CFG_CNF_MCAST_RX))
+				wrq->u.power.flags |= IW_POWER_ALL_R;
+			else
+				wrq->u.power.flags |= IW_POWER_UNICAST_R;
+			break;
+
+		// Set WEP keys and mode
+		case SIOCSIWENCODE:
+			// Is it supported?
+			if (!wvlan_hw_getprivacy(&local->ifb))
+			{
+				rc = -EOPNOTSUPP;
+				break;
+			}
+			// Basic checking: do we have a key to set?
+			if (wrq->u.encoding.pointer != (caddr_t) 0)
+			{
+				int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
+				// Check the size of the key
+				if (wrq->u.encoding.length > MAX_KEY_SIZE)
+				{
+					rc = -EINVAL;
+					break;
+				}
+				// Check the index
+				if ((index < 0) || (index >= MAX_KEYS))
+					index = local->transmit_key;
+				// Cleanup
+				memset(local->key[index].key, 0, MAX_KEY_SIZE);
+				// Copy the key in the driver
+				if (copy_from_user(local->key[index].key, wrq->u.encoding.pointer, wrq->u.encoding.length))
+				{
+					local->key[index].len = 0;
+					rc = -EFAULT;
+					break;
+				}
+				// Set the length
+				if (wrq->u.encoding.length > MIN_KEY_SIZE)
+					local->key[index].len = MAX_KEY_SIZE;
+				else
+					if (wrq->u.encoding.length > 0)
+						local->key[index].len = MIN_KEY_SIZE;
+					else
+						local->key[index].len = 0;
+				// Enable WEP (if possible)
+				if ((index == local->transmit_key) && (local->key[local->transmit_key].len > 0))
+					local->wep_on = 1;
+			}
+			else
+			{
+				int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
+				// Do we want to just set the current transmit key?
+				if ((index >= 0) && (index < MAX_KEYS))
+				{
+					if (local->key[index].len > 0)
+					{
+						local->transmit_key = index;
+						local->wep_on = 1;
+					}
+					else
+						rc = -EINVAL;
+				}
+			}
+			// Read the flags
+			if (wrq->u.encoding.flags & IW_ENCODE_DISABLED)
+				local->wep_on = 0;	// disable encryption
+			if (wrq->u.encoding.flags & IW_ENCODE_RESTRICTED)
+				rc = -EINVAL;		// Invalid
+			// Commit the changes
+			if (rc == 0) {
+				wvlan_hw_setprivacy(&local->ifb, local->wep_on, local->transmit_key, local->key);
+				wvlan_hw_reset(dev);
+			}
+			break;
+
+		// Get the WEP keys and mode
+		case SIOCGIWENCODE:
+			// Is it supported?
+			if (!wvlan_hw_getprivacy(&local->ifb))
+			{
+				rc = -EOPNOTSUPP;
+				break;
+			}
+			// Only super-user can see WEP key
+			if (!capable(CAP_NET_ADMIN))
+			{
+				rc = -EPERM;
+				break;
+			}
+			// Basic checking...
+			if (wrq->u.encoding.pointer != (caddr_t) 0)
+			{
+				int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
+				// Note: should read from adapter(?), and check if WEP capable
+				// Set the flags
+				wrq->u.encoding.flags = 0;
+				if (local->wep_on == 0)
+					wrq->u.encoding.flags |= IW_ENCODE_DISABLED;
+				// Which key do we want
+				if ((index < 0) || (index >= MAX_KEYS))
+					index = local->transmit_key;
+				wrq->u.encoding.flags |= index + 1;
+				// Copy the key to the user buffer
+				wrq->u.encoding.length = local->key[index].len;
+				if (copy_to_user(wrq->u.encoding.pointer, local->key[index].key, local->key[index].len))
+					rc = -EFAULT;
+			}
+			break;
+#endif /* WIRELESS_EXT > 8 */
+
+		// Get range of parameters
+		case SIOCGIWRANGE:
+			if (wrq->u.data.pointer)
+			{
+				struct iw_range range;
+				rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(struct iw_range));
+				if (rc)
+					break;
+				wrq->u.data.length = sizeof(range);
+				// Throughput is no way near 2 Mb/s !
+				// This value should be :
+				//	1.6 Mb/s for the 2 Mb/s card
+				//	~5 Mb/s for the 11 Mb/s card
+				// Jean II
+				range.throughput = 1.6 * 1024 * 1024;
+				range.min_nwid = 0x0000;
+				range.max_nwid = 0x0000;
+				range.num_channels = 14;
+				range.num_frequency = wvlan_hw_getfrequencylist(&local->ifb,
+						      range.freq,
+						      IW_MAX_FREQUENCIES);
+				range.sensitivity = 3;
+				if (port_type == 3 && local->spy_number == 0)
+				{
+					range.max_qual.qual = 0;
+					range.max_qual.level = 0;
+					range.max_qual.noise = 0;
+				}
+				else
+				{
+					range.max_qual.qual = 0x8b - 0x2f;
+					range.max_qual.level = 0x2f - 0x95 - 1;
+					range.max_qual.noise = 0x2f - 0x95 - 1;
+				}
+#if WIRELESS_EXT > 7
+				range.num_bitrates = wvlan_getbitratelist(&local->ifb,
+							range.bitrate,
+							IW_MAX_BITRATES);
+				range.min_rts = 0;
+				range.max_rts = 2347;
+				range.min_frag = 256;
+				range.max_frag = 2346;
+#endif	/* WIRELESS_EXT > 7 */
+#if WIRELESS_EXT > 8
+				// Is WEP it supported?
+				if (wvlan_hw_getprivacy(&local->ifb))
+				{
+					// WEP: RC4 40 bits
+					range.encoding_size[0] = 5;
+					// RC4 ~128 bits
+					range.encoding_size[1] = 14;
+					range.num_encoding_sizes = 2;
+					range.max_encoding_tokens = 4;	// 4 keys
+				}
+				else
+				{
+					range.num_encoding_sizes = 0;
+					range.max_encoding_tokens = 0;
+				}
+#endif /* WIRELESS_EXT > 8 */
+				copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range));
+			}
+			break;
+
+#ifdef WIRELESS_SPY
+		// Set the spy list
+		case SIOCSIWSPY:
+			if (wrq->u.data.length > IW_MAX_SPY)
+			{
+				rc = -E2BIG;
+				break;
+			}
+			local->spy_number = wrq->u.data.length;
+			if (local->spy_number > 0)
+			{
+				struct sockaddr address[IW_MAX_SPY];
+				int i;
+				rc = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(struct sockaddr) * local->spy_number);
+				if (rc)
+					break;
+				copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * local->spy_number);
+				for (i=0; i<local->spy_number; i++)
+					memcpy(local->spy_address[i], address[i].sa_data, MAC_ADDR_SIZE);
+				memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
+				DEBUG(DEBUG_INFO, "%s: New spy list:\n", dev_info);
+				for (i=0; i<wrq->u.data.length; i++)
+					DEBUG(DEBUG_INFO, "%s: %d - %02x:%02x:%02x:%02x:%02x:%02x\n", dev_info, i+1,
+						local->spy_address[i][0], local->spy_address[i][1],
+						local->spy_address[i][2], local->spy_address[i][3],
+						local->spy_address[i][4], local->spy_address[i][5]);
+			}
+			break;
+
+		// Get the spy list
+		case SIOCGIWSPY:
+			wrq->u.data.length = local->spy_number;
+			if ((local->spy_number > 0) && (wrq->u.data.pointer))
+			{
+				struct sockaddr address[IW_MAX_SPY];
+				int i;
+				rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, (sizeof(struct iw_quality)+sizeof(struct sockaddr)) * IW_MAX_SPY);
+				if (rc)
+					break;
+				for (i=0; i<local->spy_number; i++)
+				{
+					memcpy(address[i].sa_data, local->spy_address[i], MAC_ADDR_SIZE);
+					address[i].sa_family = AF_UNIX;
+				}
+				copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number);
+				copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number);
+				for (i=0; i<local->spy_number; i++)
+					local->spy_stat[i].updated = 0;
+			}
+			break;
+#endif /* WIRELESS_SPY */
+
+#ifdef HISTOGRAM
+		// Set the histogram range
+		case SIOCDEVPRIVATE + 0xd:
+			// Only super-user can set histogram data
+			if (!capable(CAP_NET_ADMIN))
+			{
+				rc = -EPERM;
+				break;
+			}
+			if (wrq->u.data.length > 16)
+			{
+				rc = -E2BIG;
+				break;
+			}
+			local->his_number = wrq->u.data.length;
+			if (local->his_number > 0)
+			{
+				rc = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(char) * local->his_number);
+				if (rc)
+					break;
+				copy_from_user(local->his_range, wrq->u.data.pointer, sizeof(char) * local->his_number);
+				memset(local->his_sum, 0, sizeof(long) * 16);
+			}
+			break;
+
+		// Get the histogram statistic
+		case SIOCDEVPRIVATE + 0xe:
+			wrq->u.data.length = local->his_number;
+			if ((local->his_number > 0) && (wrq->u.data.pointer))
+			{
+				rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(long) * 16);
+				if (rc)
+					break;
+				copy_to_user(wrq->u.data.pointer, local->his_sum, sizeof(long) * local->his_number);
+			}
+			break;
+#endif /* HISTOGRAM */
+
+		// Get valid private ioctl calls
+		case SIOCGIWPRIV:
+			if (wrq->u.data.pointer)
+			{
+				struct iw_priv_args priv[] = {
+#ifdef HISTOGRAM
+					{ SIOCDEVPRIVATE + 0xd, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" },
+					{ SIOCDEVPRIVATE + 0xe, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },
+#endif
+#ifdef PCMCIA_DEBUG
+					{ SIOCDEVPRIVATE + 0x0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "force_reset" },
+					{ SIOCDEVPRIVATE + 0x1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "debug_getinfo" },
+#endif
+				};
+				rc = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(priv));
+				if (rc)
+					break;
+				wrq->u.data.length = sizeof(priv) / sizeof(priv[0]);
+				copy_to_user(wrq->u.data.pointer, priv, sizeof(priv));
+			}
+			break;
+
+#ifdef PCMCIA_DEBUG
+		// Force card reset (debug purpose only)
+		case SIOCDEVPRIVATE + 0x0:
+			// Only super-user can reset the card...
+			if (!capable(CAP_NET_ADMIN))
+			{
+				rc = -EPERM;
+				break;
+			}
+			if (*((int *) wrq->u.name) > 0)
+			{
+				// 'hard' reset
+				printk(KERN_DEBUG "%s: Forcing hard reset\n", dev_info);
+				wvlan_hw_shutdown(dev);
+				wvlan_hw_config(dev);
+			}
+			else
+			{
+				// 'soft' reset
+				printk(KERN_DEBUG "%s: Forcing soft reset\n", dev_info);
+				wvlan_hw_reset(dev);
+			}
+			break;
+
+		// Get info from card and dump answer to syslog (debug purpose only)
+		case SIOCDEVPRIVATE + 0x1:
+			{
+				CFG_ID_STRCT ltv;
+				char *p;
+				int typ = *((int *) wrq->u.name);
+				ltv.len = 18;
+				ltv.typ = typ;
+				rc = hcf_get_info(&local->ifb, (LTVP) &ltv);
+				if (rc)
+					printk(KERN_DEBUG "%s: hcf_get_info(0x%x) returned error 0x%x\n", dev_info, typ, rc);
+				else
+				{
+					p = (char *) &ltv.id;
+					printk(KERN_DEBUG "%s: hcf_get_info(0x%x) returned %d words:\n", dev_info, ltv.typ, ltv.len);
+					printk(KERN_DEBUG "%s: hex-dump: ", dev_info);
+					for (rc=0; rc<(ltv.len); rc++)
+						printk("%04x ", ltv.id[rc]);
+					printk("\n");
+					printk(KERN_DEBUG "%s: ascii-dump: '", dev_info);
+					for (rc=0; rc<(ltv.len*2); rc++)
+						printk("%c", (p[rc]>31) ? p[rc] : '.');
+					printk("'\n");
+				}
+			}
+			break;
+#endif /* PCMCIA_DEBUG */
+
+		// All other calls are currently unsupported
+		default:
+			rc = -EOPNOTSUPP;
+	}
+
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_ioctl()\n");
+	return rc;
+}
+
+struct iw_statistics *wvlan_get_wireless_stats (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	CFG_COMMS_QUALITY_STRCT ltv;
+	unsigned long flags;
+	int rc;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_get_wireless_stats(%s)\n", dev->name);
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	local->wstats.status = 0;
+	if (port_type != 3)
+	{
+		ltv.len = 4;
+		ltv.typ = CFG_COMMS_QUALITY;
+		rc = hcf_get_info(&local->ifb, (LTVP) &ltv);
+		DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_COMMS_QUALITY) returned 0x%x\n", dev_info, rc);
+		local->wstats.qual.qual = max(min(ltv.coms_qual, 0x8b-0x2f), 0);
+		local->wstats.qual.level = max(min(ltv.signal_lvl, 0x8a), 0x2f) - 0x95;
+		local->wstats.qual.noise = max(min(ltv.noise_lvl, 0x8a), 0x2f) - 0x95;
+		local->wstats.qual.updated = 7;
+	}
+	else
+	{
+		// Quality levels cannot be determined in ad-hoc mode,
+		// because we can 'hear' more that one remote station.
+		// If a spy address is defined, we report stats of the
+		// first spy address
+		local->wstats.qual.qual = 0;
+		local->wstats.qual.level = 0;
+		local->wstats.qual.noise = 0;
+		local->wstats.qual.updated = 0;
+#ifdef WIRELESS_SPY
+		if (local->spy_number > 0)
+		{
+			local->wstats.qual.qual = local->spy_stat[0].qual;
+			local->wstats.qual.level = local->spy_stat[0].level;
+			local->wstats.qual.noise = local->spy_stat[0].noise;
+			local->wstats.qual.updated = local->spy_stat[0].updated;
+		}
+#endif /* WIRELESS_SPY */
+	}
+
+	// Packets discarded in the wireless adapter due to wireless specific problems
+	local->wstats.discard.nwid = 0;
+	local->wstats.discard.code = local->ifb.IFB_NIC_Tallies.RxWEPUndecryptable;
+	local->wstats.discard.misc = local->ifb.IFB_NIC_Tallies.RxFCSErrors +
+					local->ifb.IFB_NIC_Tallies.RxDiscards_NoBuffer +
+					local->ifb.IFB_NIC_Tallies.TxDiscardsWrongSA;
+
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_get_wireless_stats()\n");
+	return (&local->wstats);
+}
+
+#ifdef WIRELESS_SPY
+static inline void wvlan_spy_gather (struct net_device *dev, u_char *mac, u_char *stats)
+{
+	struct net_local *local = (struct net_local *)dev->priv;
+	int i;
+
+	// Gather wireless spy statistics: for each packet, compare the
+	// source address with out list, and if match, get the stats...
+	for (i=0; i<local->spy_number; i++)
+		if (!memcmp(mac, local->spy_address[i], MAC_ADDR_SIZE))
+		{
+			local->spy_stat[i].qual = stats[2];
+			local->spy_stat[i].level = stats[0] - 0x95;
+			local->spy_stat[i].noise = stats[1] - 0x95;
+			local->spy_stat[i].updated = 7;
+		}
+}
+#endif /* WIRELESS_SPY */
+
+#ifdef HISTOGRAM
+static inline void wvlan_his_gather (struct net_device *dev, u_char *stats)
+{
+	struct net_local *local = (struct net_local *)dev->priv;
+	u_char level = stats[0] - 0x2f;
+	int i;
+
+	// Calculate a histogram of the signal level. Each time the
+	// level goes into our defined set of interval, we increment
+	// the count.
+	i = 0;
+	while ((i < (local->his_number-1)) && (level >= local->his_range[i++]));
+	local->his_sum[i]++;
+}
+#endif /* HISTOGRAM */
+#endif /* WIRELESS_EXT */
+
+int wvlan_change_mtu (struct net_device *dev, int new_mtu)
+{
+	if (new_mtu < WVLAN_MIN_MTU || new_mtu > WVLAN_MAX_MTU)
+	{
+		DEBUG(DEBUG_INFO, "%s: New MTU of %d for %s out of range!\n", dev_info, new_mtu, dev->name);
+		return -EINVAL;
+	}
+	dev->mtu = new_mtu;
+	DEBUG(DEBUG_INFO, "%s: MTU of %s set to %d bytes\n", dev_info, dev->name, new_mtu);
+	return 0;
+}
+
+static void wvlan_set_multicast_list (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *)dev->priv;
+	unsigned long flags;
+
+	// Note: check if hardware up & running?
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	DEBUG(DEBUG_INFO, "%s: setting multicast Rx mode %02X to %d addresses.\n", dev->name, dev->flags, dev->mc_count);
+
+	// Ok, what do we want?
+	if (dev->flags & IFF_PROMISC)
+	{
+		// Enable promiscuous mode: receive all packets.
+		if (!local->promiscuous)
+		{
+			local->promiscuous = 1;
+			local->mc_count = 0;
+			wvlan_hw_setpromisc(&local->ifb, local->promiscuous);
+			dev->flags |= IFF_PROMISC;
+		}
+	}
+	else
+		// If all multicast addresses
+		// or too many multicast addresses for the hardware filter
+		if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > WVLAN_MAX_MULTICAST))
+		{
+			// Disable promiscuous mode, but active the all multicast mode
+			if (!local->promiscuous) {
+				// The Wavelan IEEE doesn't seem to have a
+				// "receive all multicast" flag, which allow to
+				// grab all multicast frames. So we go for
+				// promiscuous and let TCP filter packets,
+				// which is *very* far from optimal.
+				// Note that CNF_MCAST_RX is quite different,
+				// as it specify if the Wavelan will wake up for
+				// the broadcast announcements from the AP (DTIM)
+				local->promiscuous = 1;
+				local->mc_count = 0;
+				wvlan_hw_setpromisc(&local->ifb, local->promiscuous);
+				// Tell the kernel that we are doing a really bad job...
+				dev->flags |= IFF_PROMISC;
+			}
+		}
+		else
+			// If there is some multicast addresses to send
+			if (dev->mc_list != (struct dev_mc_list *) NULL)
+			{
+				// Disable promiscuous mode, but receive all packets
+				// in multicast list
+#ifdef MULTICAST_AVOID
+				if (local->promiscuous || local->allmulticast || (dev->mc_count != local->mc_count))
+#endif
+				{
+					struct dev_mc_list *dmi;
+					int i;
+					CFG_GROUP_ADDR_STRCT ltv;
+					int rc;
+
+					local->promiscuous = 0;
+					local->mc_count = dev->mc_count;
+					// Disable promiscuous
+					wvlan_hw_setpromisc(&local->ifb, local->promiscuous);
+					dev->flags &= ~IFF_PROMISC;
+					// Write multicast addresses in the adapter
+					for (i=0, dmi=dev->mc_list; dmi; dmi=dmi->next)
+					memcpy(ltv.mac_addr[i++], dmi->dmi_addr, dmi->dmi_addrlen);
+					ltv.len = (ETH_ALEN * local->mc_count / 2) + 1;
+					ltv.typ = CFG_GROUP_ADDR;
+					rc = hcf_put_info(&local->ifb, (LTVP) &ltv);
+					DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_GROUP_ADDR:0x%x) returned 0x%x\n", dev_info, local->mc_count, rc);
+				}
+			}
+			else
+			{
+				// Switch to normal mode: disable promiscuous mode and
+				// clear the multicast list.
+				if (local->promiscuous || local->mc_count != 0)
+				{
+					CFG_GROUP_ADDR_STRCT ltv;
+					int rc;
+					local->promiscuous = 0;
+					local->mc_count = 0;
+					wvlan_hw_setpromisc(&local->ifb, local->promiscuous);
+					// Clear multicast list
+					ltv.len = 1;
+					ltv.typ = CFG_GROUP_ADDR;
+					rc = hcf_put_info(&local->ifb, (LTVP) &ltv);
+					DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_GROUP_ADDR:0x%x) returned 0x%x\n", dev_info, local->mc_count, rc);
+				}
+			}
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	return;
+}
+
+
+
+/********************************************************************
+ * NET TX / RX
+ */
+static void wvlan_watchdog (struct net_device *dev)
+{
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_wathdog(%s)\n", dev->name);
+
+	// In theory, we could try to abort the current Tx command here,
+	// this would avoid to go through a long reset process in many
+	// cases (obstruction of the channel, very high contention)...
+
+	// Reset card in case of Tx timeout
+#ifdef WVLAN_RESET_ON_TX_TIMEOUT
+	printk(KERN_WARNING "%s: %s Tx timed out! Resetting card\n", dev_info, dev->name);
+	// Note: those two will take care of locking spinlock & irq
+	wvlan_hw_shutdown(dev);
+	wvlan_hw_config(dev);
+#else
+	printk(KERN_WARNING "%s: %s Tx timed out! Ignoring...\n", dev_info, dev->name);
+#endif
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_watchdog()\n");
+}
+
+int wvlan_tx (struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *)dev->priv;
+	unsigned long flags;
+	int rc, len;
+	char *p;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_tx(%s)\n", dev->name);
+
+#if (KERNEL_VERSION_CODE < KERNEL_VERSION(2,3,42))
+	// We normally shouldn't be called if queue is stopped (transmitter busy)
+	// but older kernel code does anyway. So we'll check if the last
+	// transmission has timed out and reset the device in case
+	if (netif_queue_stopped(dev))
+	{
+		DEBUG(DEBUG_TXRX, "%s: wvlan_tx(%s) called while busy!\n", dev_info, dev->name);
+		if ((jiffies - dev->trans_start) < TX_TIMEOUT)
+			return 1;
+		if (!netif_running(dev))
+		{
+			printk(KERN_WARNING "%s: %s Tx on stopped device!\n", dev_info, dev->name);
+			return 1;
+		}
+		wvlan_watchdog(dev);
+	}
+#endif
+
+	skb_tx_check(dev, skb);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,79))
+	skb->arp = 1;
+#endif
+
+	// Disable interrupts
+	spin_lock_irqsave(&local->slock, flags);
+
+	// Tell queueing layer to stop sending
+	// TODO: We should use multiple Tx buffers and
+	// re-enable the queue (netif_wake_queue()) if
+	// there's space left in the Tx buffers.
+	netif_stop_queue(dev);
+
+	// Prepare packet
+	p = skb->data;
+	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+
+	// Add Ethernet-II frame encapsulation, because
+	// HCF-light doesn't support that.
+	if (p[13] + (p[12] << 8) > 1500)
+	{
+		hcf_put_data(&local->ifb, p, 12, 0);
+		len += sizeof(snap_header);
+		snap_header[1] = (len-0x0e) & 0xff;
+		snap_header[0] = (char)((len-0x0e) >> 8);
+		hcf_put_data(&local->ifb, snap_header, sizeof(snap_header), 0);
+		hcf_put_data(&local->ifb, p+12, len-12-sizeof(snap_header), 0);
+	}
+	else
+		hcf_put_data(&local->ifb, p, len, 0);
+
+	// Send packet
+	rc = hcf_send(&local->ifb, 0);
+
+	// Remeber time transmission and count tx bytes
+	dev->trans_start = jiffies;
+	add_tx_bytes(&local->stats, len);
+
+	// Re-enable interrupts
+	spin_unlock_irqrestore(&local->slock, flags);
+
+	// It might be no good idea doing a printk() debug output during
+	// disabled interrupts (I'm not sure...). So better do it here.
+	DEBUG(DEBUG_TXRX, "%s: Sending 0x%x octets\n", dev_info, len);
+	DEBUG(DEBUG_NOISY, "%s: hcf_send() returned 0x%x\n", dev_info, rc);
+
+	DEV_KFREE_SKB(skb);
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_tx()\n");
+	return 0;
+}
+
+void wvlan_rx (struct net_device *dev, int len)
+{
+	struct net_local *local = (struct net_local *)dev->priv;
+	struct sk_buff *skb;
+	char *p;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_rx(%s)\n", dev->name);
+
+	// Create skb packet
+	skb = dev_alloc_skb(len+2);
+	if (!skb)
+	{
+		printk(KERN_WARNING "%s: %s Rx cannot allocate buffer for new packet\n", dev_info, dev->name);
+		local->stats.rx_dropped++;
+		return;
+	}
+	DEBUG(DEBUG_TXRX, "%s: Receiving 0x%x octets\n", dev_info, len);
+
+	// Align IP on 16b boundary
+	skb_reserve(skb, 2);
+	p = skb_put(skb, len);
+	dev->last_rx = jiffies;
+
+	// Add Ethernet-II frame decapsulation, because
+	// HCF-light doesn't support that.
+	if (local->ifb.IFB_RxStat == 0x2000 || local->ifb.IFB_RxStat == 0x4000)
+	{
+		hcf_get_data(&local->ifb, 0, p, 12);
+		hcf_get_data(&local->ifb, 12+sizeof(snap_header), p+12, len-12-sizeof(snap_header));
+		skb_trim(skb, len-sizeof(snap_header));
+	}
+	else
+		hcf_get_data(&local->ifb, 0, p, len);
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_NONE;
+
+	// Hand the packet over to the kernel
+	netif_rx(skb);
+	local->stats.rx_packets++;
+	add_rx_bytes(&local->stats, len);
+
+#ifdef WIRELESS_EXT
+#if defined(WIRELESS_SPY) || defined(HISTOGRAM)
+	if (
+#ifdef WIRELESS_SPY
+		(local->spy_number > 0) ||
+#endif
+#ifdef HISTOGRAM
+		(local->his_number > 0) ||
+#endif
+		0 )
+	{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(1,3,0))
+		char *srcaddr = skb->mac.raw + MAC_ADDR_SIZE;
+#else
+		char *srcaddr = skb->data + MAX_ADDR_SIZE;
+#endif
+		u_char stats[3];
+		int rc, i;
+		local->wstats.status = 0;
+
+		// Using spy support with port_type==1 will really
+		// slow down everything, because the signal quality
+		// must be queried for each packet here.
+		// If the user really asks for it (set some address in the
+		// spy list), we do it, but he will pay the price.
+		// Note that to get here, you need both WIRELESS_SPY
+		// compiled in AND some addresses in the list !!!
+		// TODO: Get and cache stats here so that they
+		// are available but don't need to be retreived
+		// every time a packet is received.
+#if defined(HISTOGRAM)
+		// We can't be clever...
+		rc = hcf_get_data(&local->ifb, HFS_Q_INFO, stats, 2);
+		DEBUG(DEBUG_NOISY, "%s: hcf_get_data(HFS_Q_INFO) returned 0x%x\n", dev_info, rc);
+#else // Therefore WIRELESS_SPY only !!!
+		memset(&stats, 0, sizeof(stats));
+		// Query only for addresses in our list !
+		for (i=0; i<local->spy_number; i++)
+			if (!memcmp(srcaddr, local->spy_address[i], MAC_ADDR_SIZE))
+			{
+				rc = hcf_get_data(&local->ifb, HFS_Q_INFO, stats, 2);
+				break;
+			}
+#endif
+		stats[2] = stats[0];
+		stats[0] = max(min(stats[1], 0x8a), 0x2f);
+		stats[1] = max(min(stats[2], 0x8a), 0x2f);
+		stats[2] = stats[0] - stats[1];
+#ifdef WIRELESS_SPY
+		wvlan_spy_gather(dev, srcaddr, stats);  
+#endif
+#ifdef HISTOGRAM
+		wvlan_his_gather(dev, stats);
+#endif
+	}
+#endif /* WIRELESS_SPY || HISTOGRAM */
+#endif /* WIRELESS_EXT */
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_rx()\n");
+}
+
+
+/********************************************************************
+ * NET INIT / OPEN / CLOSE
+ */
+static int wvlan_init (struct net_device *dev)
+{
+	DEBUG(DEBUG_CALLTRACE, "<> wvlan_init()\n");
+	return 0;
+}
+
+static int wvlan_open (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	struct dev_link_t *link = local->link;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_open(%s)\n", dev->name);
+
+	// TODO: Power up the card here and power down on close?
+	// For now this is done on device init, not on open
+	// Might be better placed here so that some settings can
+	// be made by shutting down the device without removing
+	// the driver (iwconfig).
+	// But this is no real problem for now :-)
+
+	// Start reception and declare the driver ready
+	if (!local->ifb.IFB_CardStat)
+		return -ENODEV;
+	netif_device_attach(dev);
+	netif_start_queue(dev);
+	local->interrupt = 0;
+	link->open++;
+	MOD_INC_USE_COUNT;
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_open()\n");
+	return 0;
+}
+
+static int wvlan_close (struct net_device *dev)
+{
+	struct net_local *local = (struct net_local *) dev->priv;
+	struct dev_link_t *link = local->link;
+
+	// If the device isn't open, then nothing to do
+	if (!link->open)
+	{
+		DEBUG(DEBUG_CALLTRACE, "<> wvlan_close(%s)\n", dev->name);
+		return 0;
+	}
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_close(%s)\n", dev->name);
+
+	// Close the device
+	link->open--;
+	MOD_DEC_USE_COUNT;
+
+	// Check if card is still present
+	if (netif_running(dev))
+	{
+		netif_stop_queue(dev);
+		netif_device_detach(dev);
+		// TODO: Shutdown hardware (see wvlan_open)
+	}
+	else
+		if (link->state & DEV_STALE_CONFIG)
+			wvlan_release((u_long)link);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_close()\n");
+	return -EINVAL;
+}
+
+
+/********************************************************************
+ * INTERRUPT HANDLER
+ */
+static void wvlan_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct net_local *local = (struct net_local *) dev->priv;
+	int rc, cnt, ev, len;
+
+	DEBUG(DEBUG_INTERRUPT, "-> wvlan_interrupt(%d)\n", irq);
+
+	// Check device
+	if (!dev)
+	{
+		printk(KERN_WARNING "%s: IRQ %d for unknown device!\n", dev_info, irq);
+		return;
+	}
+
+	// Turn off interrupts
+	rc = hcf_action(&local->ifb, HCF_ACT_INT_OFF);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_OFF) returned 0x%x\n", dev_info, rc);
+	if (test_and_set_bit(0, (void *)&local->interrupt))
+		printk(KERN_WARNING "%s: Warning: IRQ %d Reentering interrupt handler!\n", dev_info, irq);
+
+	// Process pending interrupts.
+	// We continue until hcf_service_nic tells that no received
+	// frames are pending. However we should check to not lock up
+	// here in an endless loop.
+	cnt = 7;
+	while (cnt--)
+	{
+		// Ask NIC why interrupt occured
+		ev = hcf_service_nic(&local->ifb);
+		DEBUG(DEBUG_NOISY, "%s: hcf_service_nic() returned 0x%x RscInd 0x%x\n", dev_info, ev, local->ifb.IFB_PIFRscInd);
+
+		// Transmission completion seem to be also signalled with ev==0
+		// better check that out with RscInd and complete transfer also
+		if (local->ifb.IFB_PIFRscInd && netif_queue_stopped(dev))
+			ev |= HREG_EV_TX;
+
+		// HREG_EV_TICK: WMAC controller auxiliary timer tick
+		if (ev & HREG_EV_TICK)
+		{
+			DEBUG(DEBUG_INFO,"%s: Auxiliary timer tick\n", dev_info);
+		}
+
+		// HREG_EV_RES: WMAC controller H/W error (wait timeout)
+		if (ev & HREG_EV_RES)
+		{
+			// This message seems to occur often on heavy load
+			// but it seem to don't have any effects on transmission
+			// so we simply ignore it.
+			//printk(KERN_WARNING "%s: WMAC H/W error (wait timeout, ignoring)!\n", dev_info);
+		}
+
+		// HREG_EV_INFO_DROP: WMAC did not have sufficient RAM to build unsollicited frame
+		if (ev & HREG_EV_INFO_DROP)
+			printk(KERN_WARNING "%s: WMAC did not have sufficient RAM to build unsollicited frame!\n", dev_info);
+
+		// HREG_EV_INFO: WMAC controller asynchronous information frame
+		if (ev & HREG_EV_INFO)
+		{
+			DEBUG(DEBUG_INFO, "%s: WMAC controller asynchronous information frame\n", dev_info);
+		}
+
+		// HREG_EV_CMD: WMAC controller command completed, status and response available
+		//	unnecessary to handle here, it's handled by polling in HCF
+
+		// HREG_EV_ALLOC: WMAC controller asynchronous part of allocation/reclaim completed
+		//	also unnecessary to handle here, it's handled by polling in HCF
+
+		// HREG_EV_TX_EXC: WMAC controller asynchronous transmission unsuccessful completed
+		if (ev & HREG_EV_TX_EXC)
+		{
+			printk(KERN_WARNING "%s: WMAC controller asynchronous transmission unsuccessful completed\n", dev_info);
+			local->stats.tx_errors++;
+			netif_wake_queue(dev);
+		}
+
+		// HREG_EV_TX: WMAC controller asynchronous transmission successful completed
+		if (ev & HREG_EV_TX)
+		{
+			DEBUG(DEBUG_TXRX, "%s: Transmission successful completed\n", dev_info);
+			local->stats.tx_packets++;
+			netif_wake_queue(dev);
+		}
+
+		// HREG_EV_RX: WMAC controller asynchronous receive frame
+		// Break loop if no frame was received.
+		if (!(ev & HREG_EV_RX))
+			break;
+
+		// If a frame was received, we process it and wrap back
+		// up to the top of the while() loop so that hcf_service_nic()
+		// gets called again after the frame drained from the NIC.
+		// This allows us to find out if yet another frame has
+		// arrived, and also to immediately acknowledge the just-
+		// processed frame so that the NIC's buffer gets de-
+		// allocated right away.
+		len = local->ifb.IFB_RxLen;
+		if (len)
+		{
+			DEBUG(DEBUG_INTERRUPT, "%s: Frame received. rx_len=0x%x\n", dev_info, len);
+			wvlan_rx(dev, len);
+		}
+	}
+	if (!cnt)
+		printk(KERN_WARNING "%s: Maximum interrupt loops reached!\n", dev_info);
+
+	// From now on, we don't care if we re-enter the interrupt handler
+	local->interrupt = 0;
+
+	// Turn back interrupts on (unlock)
+	rc = hcf_action(&local->ifb, HCF_ACT_INT_ON);
+	DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_ON) returned 0x%x\n", dev_info, rc);
+
+	DEBUG(DEBUG_INTERRUPT, "<- wvlan_interrupt()\n");
+}
+
+
+/********************************************************************
+ * PCMCIA CONFIG / RELEASE
+ */
+#define CS_CHECK(fn, args...) while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
+#define CFG_CHECK(fn, args...) if (CardServices(fn, args) != 0) goto next_entry
+static int wvlan_config (dev_link_t *link)
+{
+	client_handle_t handle = link->handle;
+	tuple_t tuple;
+	cisparse_t parse;
+	struct net_device *dev = (struct net_device *) link->priv;
+	struct net_local *local = (struct net_local *) dev->priv;
+	int last_fn, last_ret;
+	u_char buf[64];
+	win_req_t req;
+	memreq_t map;
+	int rc, i;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_config(0x%p)\n", link);
+
+	// This reads the card's CONFIG tuple to find its configuration registers.
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	tuple.Attributes = 0;
+	tuple.TupleData = buf;
+	tuple.TupleDataMax = sizeof(buf);
+	tuple.TupleOffset = 0;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	CS_CHECK(GetTupleData, handle, &tuple);
+	CS_CHECK(ParseTuple, handle, &tuple, &parse);
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+
+	// Configure card
+	link->state |= DEV_CONFIG;
+
+	// In this loop, we scan the CIS for configuration table entries,
+	// each of which describes a valid card configuration, including
+	// voltage, IO window, memory window, and interrupt settings.
+	// We make no assumptions about the card to be configured: we use
+	// just the information available in the CIS.  In an ideal world,
+	// this would work for any PCMCIA card, but it requires a complete
+	// and accurate CIS.  In practice, a driver usually "knows" most of
+	// these things without consulting the CIS, and most client drivers
+	// will only use the CIS to fill in implementation-defined details.
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	while (1) {
+		cistpl_cftable_entry_t dflt = { 0 };
+		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+		CFG_CHECK(GetTupleData, handle, &tuple);
+		CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+
+		if (cfg->index == 0) goto next_entry;
+		link->conf.ConfigIndex = cfg->index;
+
+		// Does this card need audio output?
+		if (cfg->flags & CISTPL_CFTABLE_AUDIO)
+		{
+			link->conf.Attributes |= CONF_ENABLE_SPKR;
+			link->conf.Status = CCSR_AUDIO_ENA;
+		}
+	
+		// Use power settings for Vcc and Vpp if present
+		// Note that the CIS values need to be rescaled
+		if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
+		else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
+
+		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+		// Do we need to allocate an interrupt?
+		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
+			link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+		// IO window settings
+		link->io.NumPorts1 = link->io.NumPorts2 = 0;
+		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+			if (!(io->flags & CISTPL_IO_8BIT))
+				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+			if (!(io->flags & CISTPL_IO_16BIT))
+				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+			link->io.BasePort1 = io->win[0].base;
+			link->io.NumPorts1 = io->win[0].len;
+			if (io->nwin > 1) {
+				link->io.Attributes2 = link->io.Attributes1;
+				link->io.BasePort2 = io->win[1].base;
+				link->io.NumPorts2 = io->win[1].len;
+			}
+		}
+
+		// This reserves IO space but doesn't actually enable it
+		CFG_CHECK(RequestIO, link->handle, &link->io);
+
+		// Now set up a common memory window, if needed.  There is room
+		// in the dev_link_t structure for one memory window handle,
+		// but if the base addresses need to be saved, or if multiple
+		// windows are needed, the info should go in the private data
+		// structure for this device.
+		// Note that the memory window base is a physical address, and
+		// needs to be mapped to virtual space with ioremap() before it
+		// is used.
+		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
+			cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
+			req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+			req.Base = mem->win[0].host_addr;
+			req.Size = mem->win[0].len;
+			req.AccessSpeed = 0;
+			link->win = (window_handle_t)link->handle;
+			CFG_CHECK(RequestWindow, &link->win, &req);
+			map.Page = 0; map.CardOffset = mem->win[0].card_addr;
+			CFG_CHECK(MapMemPage, link->win, &map);
+		}
+
+		// If we got this far, we're cool!
+		break;
+
+next_entry:
+		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+			dflt = *cfg;
+		CS_CHECK(GetNextTuple, handle, &tuple);
+	}
+
+	// Allocate an interrupt line.  Note that this does not assign a
+	// handler to the interrupt, unless the 'Handler' member of the
+	// irq structure is initialized.
+	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+	{
+		link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+		link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+		if (irq_list[0] == -1)
+			link->irq.IRQInfo2 = irq_mask;
+		else
+			for (i=0; i<4; i++)
+				link->irq.IRQInfo2 |= 1 << irq_list[i];
+		link->irq.Handler = wvlan_interrupt;
+		link->irq.Instance = dev;
+		CS_CHECK(RequestIRQ, link->handle, &link->irq);
+	}
+
+	// This actually configures the PCMCIA socket -- setting up
+	// the I/O windows and the interrupt mapping, and putting the
+	// card and host interface into "Memory and IO" mode.
+	CS_CHECK(RequestConfiguration, link->handle, &link->conf);
+
+	// Feed the netdevice with this info
+	dev->irq = link->irq.AssignedIRQ;
+	dev->base_addr = link->io.BasePort1;
+	netif_start_queue(dev);
+
+	// Report what we've done
+	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", dev_info, link->conf.ConfigIndex, link->conf.Vcc/10, link->conf.Vcc%10);
+	if (link->conf.Vpp1)
+		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+		printk(", irq %d", link->irq.AssignedIRQ);
+	if (link->io.NumPorts1)
+		printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1);
+	if (link->io.NumPorts2)
+		printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1);
+	if (link->win)
+		printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base+req.Size-1);
+	printk("\n");
+
+	link->state &= ~DEV_CONFIG_PENDING;
+
+	// Make netdevice's name (if not ethX) and remember the device
+	// Not very efficient here, this should go somewhere into dev_list,
+	// but it works for now (taken from register_netdevice in kernel)
+	if (!eth)
+	{
+		for (i=0; i<MAX_WVLAN_CARDS; ++i)
+			if (!wvlandev_index[i])
+			{
+				sprintf(local->node.dev_name, "wvlan%d", i);
+				wvlandev_index[i] = dev;
+				break;
+			}
+	}
+
+	// Register the netdevice
+	rc = register_netdev(dev);
+	if (rc)
+	{
+		printk(KERN_WARNING "%s: register_netdev() failed!\n", dev_info);
+		wvlan_release((u_long)link);
+		return 0;
+	}
+	printk(KERN_INFO "%s: Registered netdevice %s\n", dev_info, dev->name);
+
+	link->dev = &local->node;
+
+	// Success!
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_config()\n");
+	return 1;
+
+cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+	wvlan_release((u_long)link);
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_config()\n");
+	return 0;
+}
+
+static void wvlan_release (u_long arg)
+{
+	dev_link_t *link = (dev_link_t *) arg;
+	struct net_device *dev = (struct net_device *) link->priv;
+	int i;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_release(0x%p)\n", link);
+
+	// If the device is currently in use, we won't release
+	// until it's actually closed.
+	if (link->open)
+	{
+		DEBUG(DEBUG_INFO, "%s: wvlan_release: release postponed, %s still locked\n", dev_info, link->dev->dev_name);
+		link->state |= DEV_STALE_CONFIG;
+		return;
+	}
+
+	// Power down
+	wvlan_hw_shutdown(dev);
+
+	// Remove our device from index (only devices named wvlanX)
+	for (i=0; i<MAX_WVLAN_CARDS; ++i)
+		if (wvlandev_index[i] == dev)
+		{
+			wvlandev_index[i] = NULL;
+			break;
+		}
+
+	if (link->win)
+		CardServices(ReleaseWindow, link->win);
+	CardServices(ReleaseConfiguration, link->handle);
+	if (link->io.NumPorts1)
+		CardServices(ReleaseIO, link->handle, &link->io);
+	if (link->irq.AssignedIRQ)
+		CardServices(ReleaseIRQ, link->handle, &link->irq);
+
+	link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_release()\n");
+}
+
+
+/********************************************************************
+ * PCMCIA ATTACH / DETACH
+ */
+static dev_link_t *wvlan_attach (void)
+{
+	dev_link_t *link;
+	struct net_device *dev;
+	struct net_local *local;
+	int rc;
+	client_reg_t client_reg;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_attach()\n");
+
+	// Flush stale links
+	for (link=dev_list; link; link=link->next)
+		if (link->state & DEV_STALE_LINK)
+			wvlan_detach(link);
+
+	// Initialize the dev_link_t structure
+	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+	memset(link, 0, sizeof(struct dev_link_t));
+	link->release.function = &wvlan_release;
+	link->release.data = (u_long) link;
+	link->conf.Vcc = 50;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+
+	// Allocate space for netdevice (private data of link)
+	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	memset(dev, 0, sizeof(struct net_device));
+	link->priv = dev;
+
+	// Allocate space for netdevice priv (private data of netdevice)
+	local = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+	memset(local, 0, sizeof(struct net_local));
+	dev->priv = local;
+
+	// Initialize specific data
+	local->link = link;
+	local->dev = dev;
+	spin_lock_init(&local->slock);
+
+	// Standard setup for generic data
+	ether_setup(dev);
+
+	// kernel callbacks
+	dev->init = wvlan_init;
+	dev->open = wvlan_open;
+	dev->stop = wvlan_close;
+	dev->hard_start_xmit = wvlan_tx;
+	dev->get_stats = wvlan_get_stats;
+#ifdef WIRELESS_EXT
+	dev->do_ioctl = wvlan_ioctl;
+	dev->get_wireless_stats = wvlan_get_wireless_stats;
+#endif
+	dev->change_mtu = wvlan_change_mtu;
+	dev->set_multicast_list = wvlan_set_multicast_list;
+//	dev->set_mac_address = wvlan_set_mac_address;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,42))
+	dev->tx_timeout = &wvlan_watchdog;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#endif
+
+	// Other netdevice data
+	//dev->name = local->node.dev_name;
+	strcpy(dev->name, local->node.dev_name);
+	dev->mtu = mtu;
+	netif_stop_queue(dev);
+
+	// Register with CardServices
+	link->next = dev_list;
+	dev_list = link;
+	client_reg.dev_info = &dev_info;
+	client_reg.Attributes = INFO_IO_CLIENT;
+	client_reg.EventMask =	CS_EVENT_REGISTRATION_COMPLETE |
+				CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+				CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+				CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+	client_reg.event_handler = &wvlan_event;
+	client_reg.Version = 0x0210;
+	client_reg.event_callback_args.client_data = link;
+
+	rc = CardServices(RegisterClient, &link->handle, &client_reg);
+	if (rc)
+	{
+		cs_error(link->handle, RegisterClient, rc);
+		wvlan_detach(link);
+		return NULL;
+	}
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_attach()\n");
+	return link;
+}
+
+static void wvlan_detach (dev_link_t *link)
+{
+	dev_link_t **linkp;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_detach(0x%p)\n", link);
+
+	// Locate device structure
+	for (linkp=&dev_list; *linkp; linkp=&(*linkp)->next)
+		if (*linkp == link)
+			break;
+	if (!*linkp)
+	{
+		printk(KERN_WARNING "%s: Attempt to detach non-existing PCMCIA client!\n", dev_info);
+		return;
+	}
+
+	// If the device is currently configured and active, we won't
+	// actually delete it yet. Instead, it is marked so that when the
+	// release() function is called, that will trigger a proper
+	// detach()
+	if (link->state & DEV_CONFIG)
+	{
+		DEBUG(DEBUG_INFO, "%s: wvlan_detach: detach postponed, %s still locked\n", dev_info, link->dev->dev_name);
+		wvlan_release((u_long)link);
+		if (link->state & DEV_STALE_CONFIG)
+		{
+			link->state |= DEV_STALE_LINK;
+			return;
+		}
+	}
+
+	// Break the line with CardServices
+	if (link->handle)
+		CardServices(DeregisterClient, link->handle);
+
+	// Unlink device structure, free pieces
+	*linkp = link->next;
+	if (link->priv)
+	{
+		struct net_device *dev = (struct net_device *) link->priv;
+		if (link->dev)
+		{
+			unregister_netdev(dev);
+			DEBUG(DEBUG_INFO, "%s: Netdevice unregistered\n", dev_info);
+		}
+		if (dev->priv)
+			kfree(dev->priv);
+		kfree(link->priv);
+	}
+	kfree(link);
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_detach()\n");
+}
+
+
+/********************************************************************
+ * PCMCIA EVENT HANDLER
+ */
+static int wvlan_event (event_t event, int priority, event_callback_args_t *args)
+{
+	dev_link_t *link = (dev_link_t *) args->client_data;
+	struct net_device *dev = (struct net_device *) link->priv;
+
+	DEBUG(DEBUG_CALLTRACE, "-> wvlan_event(%s, %d, 0x%p)\n",
+		((event==CS_EVENT_REGISTRATION_COMPLETE) ? "registration complete" :
+		((event==CS_EVENT_CARD_INSERTION) ? "card insertion" :
+		((event==CS_EVENT_CARD_REMOVAL) ? "card removal" :
+		((event==CS_EVENT_RESET_PHYSICAL) ? "physical physical" :
+		((event==CS_EVENT_CARD_RESET) ? "card reset" :
+		((event==CS_EVENT_PM_SUSPEND) ? "pm suspend" :
+		((event==CS_EVENT_PM_RESUME) ? "pm resume" :
+		"unknown"))))))), priority, args);
+
+	switch (event)
+	{
+		case CS_EVENT_CARD_INSERTION:
+			link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+			if (!wvlan_config(link) || wvlan_hw_config(dev))
+				dev->irq = 0;
+			break;
+
+		case CS_EVENT_CARD_REMOVAL:
+			link->state &= ~DEV_PRESENT;
+			if (link->state & DEV_CONFIG)
+			{
+				netif_stop_queue(dev);
+				netif_device_detach(dev);
+				link->release.expires = jiffies + (HZ/20);
+				add_timer(&link->release);
+			}
+			break;
+
+		case CS_EVENT_PM_SUSPEND:
+			link->state |= DEV_SUSPEND;
+		case CS_EVENT_RESET_PHYSICAL:
+			if (link->state & DEV_CONFIG)
+			{
+				if (link->open)
+				{
+					netif_stop_queue(dev);
+					netif_device_detach(dev);
+				}
+				CardServices(ReleaseConfiguration, link->handle);
+			}
+			break;
+
+		case CS_EVENT_PM_RESUME:
+			link->state &= ~DEV_SUSPEND;
+			// Fall through
+		case CS_EVENT_CARD_RESET:
+			if (link->state & DEV_CONFIG)
+			{
+				CardServices(RequestConfiguration, link->handle, &link->conf);
+				if (link->open)
+				{
+					wvlan_hw_shutdown(dev);
+					wvlan_hw_config(dev);
+					netif_device_attach(dev);
+					netif_start_queue(dev);
+				}
+			}
+			break;
+	}
+
+	DEBUG(DEBUG_CALLTRACE, "<- wvlan_event()\n");
+	return 0;
+}
+
+
+/********************************************************************
+ * MODULE INSERTION / REMOVAL
+ */
+extern int init_module (void)
+{
+	servinfo_t serv;
+
+	DEBUG(DEBUG_CALLTRACE, "-> init_module()\n");
+
+	printk(KERN_INFO "%s: WaveLAN/IEEE PCMCIA driver v%s\n", dev_info, version);
+	printk(KERN_INFO "%s: (c) Andreas Neuhaus <andy@fasta.fh-dortmund.de>\n", dev_info);
+
+	// Check CardServices release
+	CardServices(GetCardServicesInfo, &serv);
+	if (serv.Revision != CS_RELEASE_CODE)
+	{
+		printk(KERN_WARNING "%s: CardServices release does not match!\n", dev_info);
+		return -1;
+	}
+
+	// Register PCMCIA driver
+	register_pcmcia_driver(&dev_info, &wvlan_attach, &wvlan_detach);
+
+	DEBUG(DEBUG_CALLTRACE, "<- init_module()\n");
+	return 0;
+}
+
+extern void cleanup_module (void)
+{
+	DEBUG(DEBUG_CALLTRACE, "-> cleanup_module()\n");
+
+	// Unregister PCMCIA driver
+	unregister_pcmcia_driver(&dev_info);
+
+	// Remove leftover devices
+	if (dev_list)
+		DEBUG(DEBUG_INFO, "%s: Removing leftover devices!\n", dev_info);
+	while (dev_list)
+	{
+		if (dev_list->state & DEV_CONFIG)
+			wvlan_release((u_long)dev_list);
+		wvlan_detach(dev_list);
+	}
+
+	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+	DEBUG(DEBUG_CALLTRACE, "<- cleanup_module()\n");
+}
+
+
+/********************************************************************
+ * EOF
+ */
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_hcf.c linux.wavelan/drivers/net/pcmcia/wvlan_hcf.c
--- linux/drivers/net/pcmcia/wvlan_hcf.c	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_hcf.c	Sat Jan 27 23:42:42 2001
@@ -0,0 +1,1978 @@
+/* This file is part of the Hardware Control Functions Light (HCF-light) library
+   to control the Lucent Technologies WaveLAN/IEEE Network I/F Card.
+   The HCF is the implementation of the Wireless Connection I/F (WCI).
+   
+   The HCF-light files are a subset of the HCF files. The complete set offers a
+   number of additional facilities, e.g. firmware download, Etherner-II encapsulation,
+   additional diagnostic facilities, ASSERT logic to support debugging, 802.11 support,
+   Configuration Management.
+   This complete set is explicitely not in the Public Domain but can be made 
+   available under certain restriction. (see the pointer below for support)
+   
+   The HCF-light files are free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   
+   At the time of this writing, you can request for support at:
+   betasupport@wavelan.com
+   
+   Documentation is expected to be available in the week of 8 Februari 1999
+
+*/
+
+
+/**************************************************************************************************************
+*
+* FILE   :	HCF.CPP *************** 2.0 ***********************************************************************
+*
+* DATE    :	2000/01/06 23:30:52   1.2
+*
+* AUTHOR :	Nico Valster
+*
+* DESC   :	HCF Routines hcf_action, hcf_connect, hcf_disable
+*						 hcf_disconnect, hcf_download, hcf_enable, hcf_generate_int
+*						 hcf_get_info, hcf_get_data, hcf_service_nic
+*						 hcf_put_info, hcf_put_data, hcf_register_mailbox, hcf_send,
+*						 hcf_send_diag_msg
+*			Local Support Routines for above procedures
+*
+*			Customizable via HCFCFG.H, which is included by HCF.H
+*
+***************************************************************************************************************
+* COPYRIGHT (c) 1995			 by AT&T.	 				All Rights Reserved
+* COPYRIGHT (c) 1996, 1997, 1998 by Lucent Technologies.	All Rights Reserved
+*
+* At the sole discretion of Lucent Technologies parts of this source may be extracted
+* and placed in the Public Domain under the GPL.
+* This extraction takes place by means of an AWK-script acting on embedded tags.
+* The AWK script is:
+ *	BEGIN { c = 0 }
+ *	{ if ( c == 0 ) i = 1}			#if in @HCF_L>..@HCF_L< block, skip
+ *	{ if (name != FILENAME ) name = FILENAME }
+ *	
+ *	{ if ( i && c == 0  ) { print ; hcf_l_cnt++ } }
+ *	#{ if ( i ) { print ; hcf_l_cnt++ } }
+ *	#{if ( c == 0 ) { printf("N%d", c) ; hcf_l_cnt++ } }
+ *	#{if ( c == 1 ) { printf("E%d", c) ; hcf_l_cnt++ } }
+ *	
+ *	#END { printf("%s:: HCF lines: %d, HCF_Light lines: %d", name, NR, hcf_l_cnt ) }
+*
+* and is not in any sense derived from the extracted source. 
+*
+**************************************************************************************************************/
+
+
+
+
+
+/****************************************************************************
+wvlan_hcf.c,v
+Revision 1.2  2000/01/06 23:30:52  root
+*** empty log message ***
+
+ * 
+ *    Rev 1.0   02 Feb 1999 14:32:28   NVALST
+ * Initial revision.
+Revision 1.3  1999/02/01 22:58:40  nico
+*** empty log message ***
+ * 
+ *    Rev 2.12   29 Jan 1999 10:48:40   NVALST
+ * 
+ *    Rev 1.108   28 Jan 1999 14:43:18   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic + download
+ * passed to Marc
+ * 
+****************************************************************************/
+
+/**************************************************************************************************************
+*
+* CHANGE HISTORY
+*
+
+  960702 - NV
+	Original Entry - derived from WaveLAN-I HCF 2.12
+
+
+*
+* ToDo
+*
+ 1:	For all/most functions, update "MSF-accessible fields of Result Block:" entry
+ 2: Use the "numbered comments" in the NARRATIVE consistently, i.e. hcf_put_info
+ 3: hcf_put_data, hcf_send, hcf_send_diag_msg
+	once the dust is settled whether hcf_put_data or hcf_send is the appropriate place is to specify port,
+	it can be considered whether part of the hcf_send_diag_msg and hcf_send can be isolated in a common
+	routine.
+ 4:	hcf_send_diag_msg:
+  	- what are the appropriate return values
+	- once the dust is settled whether type should or shouldn't be parameter of hcf_send_diag_msg, it can
+	  be decided whether the HFX_TX_CNTL_ABS update at each call is needed
+ 5:	hcf_service_nic, hcf_send, hcf_send_diag_msg etc
+ 	check for a CONSISTENT strategy for the testing of IFB_CardStat, for presence, enabled, ports
+ 6:	Decide on the relative merits of HCF_ACT_ASSERT_OFF/_ON versus CFG_REG_MSF_ASSERT
+	
+
+*
+* Implementation Notes
+*
+ -	C++ style cast is not used to keep DA-C happy
+ -	a leading marker of //! is used. The purpose of such a sequence is to help the
+	(maintenance) programmer to understand the flow
+ 	An example in hcf_action( HCF_ACT_802_3 ) is
+	//!		ifbp->IFB_RxFence = 0;
+	which is superfluous because IFB_RxFence gets set at every hcf_service_nic but
+	it shows to the (maintenance) programmer it is an intentional omission at
+	the place where someone could consider it most appropriate at first glance
+ -	using near pointers in a model where ss!=ds is an invitation for disaster, so be aware of how you specify
+ 	your model and how you define variables which are used at interrupt time
+ -	Once the comment "the value of -1 for parameter len is meaningless but it guarantees that the next call
+ 	to bap_ini is interpreted as an initial call, causing the BAP to be really initialized." was considered
+ 	useful information. Does this trick still lingers somewhere;?
+ -	remember that sign extension on 32 bit platforms may cause problems unless code is carefully constructed,
+ 	e.g. use "(hcf_16)~foo" rather than "~foo"
+
+	
+*
+* Miscellaneous Notes
+*
+ -	AccessPoint performance could be improved by adding a hcf_send_pif_msg equivalent of hcf_send_diag_msg
+
+
+*************************************************************************************************************/
+
+#include "wvlan_hcf.h"				// HCF and MSF common include file
+#include "wvlan_hcfdef.h"			// HCF specific include file
+
+/*************************************************************************************************************/
+/***************************************  PROTOTYPES  ********************************************************/
+/*************************************************************************************************************/
+// moving these prototypes to HCFDEF.H turned out to be less attractive in the HCF-light generation
+STATIC int			aux_cntl( IFBP ifbp, hcf_16 cmd );
+STATIC int			calibrate( IFBP ifbp );
+STATIC int			cmd_wait( IFBP ifbp, int cmd_code, int par_0 );
+STATIC void			enable_int(IFBP ifbp, int event );
+       int			hcf_initialize( IFBP ifbp );
+STATIC int			ini_hermes( IFBP ifbp );
+STATIC void	 		isr_info( IFBP ifbp );
+STATIC int			put_info( IFBP ifbp, LTVP ltvp	);
+STATIC hcf_16		alloc( IFBP ifbp, int len );
+
+
+/**************************************************************************************************************
+******************************* D A T A    D E F I N I T I O N S **********************************************
+**************************************************************************************************************/
+
+STATIC hcf_8 BASED hcf_rev[] = "\nHCF1.2\n";
+
+/* Note that the "BASED" construction (supposedly) only amounts to something in the small memory model.
+ * In that case CS and DS are equal, so we can ignore the consequences of casting the BASED cfg_drv_...
+ * structure to hcf_16
+ * Note that the whole BASED riggamarole is needlessly complicated because both the Microsoft Compiler and
+ * Linker are unnecessary restrictive in what far pointer manipulation they allow
+ */
+
+
+/* 
+	The below table accessed via a computed index was the original implementation for hcf_get_info with 
+	CFG_DRV_IDENTITY, CFG_DRV_SUP_RANGE, CFG_DRV_ACT_RANGE_PRI, CFG_DRV_ACT_RANGE_STA, CFG_DRV_ACT_RANGE_HSI
+	as type. However it was reported that the 68K compiler for MAC OS is unable to initialize pointers.
+	Accepting this story at face value, the HCF is coded around this problem by implementing a direct access..
+	To save part of the invested effort, the original table is kept as comment.
+
+STATIC LTV_STRCT*   BASED xxxx[ ] = {
+	(LTV_STRCT*)&cfg_drv_identity,      //CFG_DRV_IDENTITY              0x0826
+	(LTV_STRCT*)&cfg_drv_sup_range,     //CFG_DRV_SUP_RANGE             0x0827
+	(LTV_STRCT*)&cfg_drv_act_range_pri, //CFG_DRV_ACT_RANGE_PRI         0x0828
+	(LTV_STRCT*)&cfg_drv_act_range_sta  //CFG_DRV_ACT_RANGE_STA         0x0829
+	(LTV_STRCT*)&cfg_drv_act_range_hsi	//CFG_DRV_ACT_RANGE_HSI			0x082A
+  };
+*/
+
+
+/**************************************************************************************************************
+************************** T O P   L E V E L   H C F   R O U T I N E S ****************************************
+**************************************************************************************************************/
+
+
+/*******************************************************************************************************************
+
+
+.MODULE			hcf_action
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			NW4
+.APPLICATION	Card configuration
+.DESCRIPTION	Changes the run-time Card behavior
+
+.ARGUMENTS
+  int hcf_action(IFBP ifbp, hcf_action_cmd action )
+.RETURNS
+  int
+
+  MSF-accessible fields of Result Block: -
+
+.NARRATIVE
+
+ Name:	hcf_action
+
+ Summary: Changes the run-time Card behavior
+
+ Parameters:
+  ifbp	address of the Interface Block
+
+  action	number identifying the type of change
+
+  o HCF_ACT_INT_ON		enable interrupt generation by WaveLAN NIC
+  o HCF_ACT_INT_OFF		disable interrupt generation by WaveLAN NIC
+  o HCF_ACT_CARD_IN		MSF reported Card insertion
+  o HCF_ACT_CARD_OUT	MSF reported Card removal
+
+ Returns:
+  o	HCF_ACT_INT_OFF
+		0: no interrupt pending
+		1: interrupt pending
+  o	all other
+		0 (((however, see the special treatment for HCF_ACT_INT_ON)))
+
+ Remarks:
+  o	HCF_ACT_INT_OFF/HCF_ACT_INT_ON codes may be nested but must be balanced. The INT_OFF/INT_ON housekeeping
+	is initialized by hcf_connect with a call of hcf_action with INT_OFF, causing the interrupt generation
+	mechanism to be disabled at first. This suits MSF implementation based on a polling strategy. An MSFT
+	based on a interrupt strategy must call hcf_action with INT_ON in its initialization logic.
+
+  o To prevent I/O while the I/O space is no longer owned by the HCF, due to a card swap, no I/O is allowed
+	when the CARD_STAT_PRESENT bit of IFB_CardStat is off.
+
+.DIAGRAM
+ 2: IFB_IntOffCnt is used to balance the INT_OFF and INT_ON calls.
+ 4: Disabling of the interrupts is simply achieved by writing a zero to the Hermes IntEn register
+ 5: To be able to return the information to the MSF whether an interrupt is actually pending, the Hermes
+	EvStat register is sampled and compared against the current IFB_IntEnMask value
+ 6:	Originally the construction "if ( ifbp->IFB_IntOffCnt-- <= 1 )" was used in stead of
+ 	"if ( --ifbp->IFB_IntOffCnt == 0 )". This serviced to get around the unsigned logic, but as additional
+ 	"benefit" it seemed the most optimal "fail safe" code (in the sense of shortest/quickest path in error
+ 	free flows, fail safe in the sense of too many INT_ON invocations compared to INT_OFF). However when a
+ 	real life MSF programmer ran to a MSF sequence problem, exactly causing that problem, he was annoyed
+ 	with this fail safe code. As a consequence it is taken out. As a side-effect of this unhappy MSF programmer
+ 	adventures to find his problem, the return status is defined to reflect the IFBIntOffCnt, Note that this 
+ 	is solely intended for aid debugging, no MSF logic should depend on this feature, No garuantees for the 
+ 	future are given.
+ 	Enabling of the interrupts is achieved by writing the contents of IFB_IntEnMask to the Hermes IntEn
+ 	register.
+ 7:	Since the card is present again, it must be re-initialized. Since this may be another card we may as well 
+ 	clear all bits in IFB_CardStat and set only the "present" bit. 
+ 	The first call to hcf_enable will restore the contents of HREG_INT_EN register taking the 
+ 	HCF_ACT_IN_ON/OFF history in account.
+ 9:	The MSF must call hcf_action with HCF_ACT_CARD_OUT when the MSF detects a card removal (e.g. when the MSF
+	is notified by the CAD). As a minimum, the "present" bit in IFB_CardStat must be reset, however since
+	the card insertion will clear all other bits, the simplest solution is to clear IFB_CardStat here as well.
+	As a result of the resetting of the CARD_STAT_PRESENT bit, no hcf-function except hcf_action with
+	HCF_ACT_CARD_IN results in card I/O anymore. However hcf_functions may still perform their other
+	activities, e.g. hcf_get_info_mb still supplies a MBIB if one is available.
+	As a result of the resetting of the CARD_STAT_INI bit, the call to hcf_initialize by hcf_action with
+	HCF_ACT_CARD_IN results in re-initialization of the NIC.
+.ENDOC				END DOCUMENTATION
+
+
+**************************************************************************************************************/
+int hcf_action( IFBP ifbp, 					//address of the Interface Block
+				hcf_action_cmd action		/*number identifying the type of change
+											*/
+ 				) {
+
+int		rc = HCF_SUCCESS;
+//int		i, j;
+//hcf_16	scratch[2];
+
+	
+
+	switch (action) {
+	  case HCF_ACT_INT_OFF:						// Disable Interrupt generation
+		ifbp->IFB_IntOffCnt++;																			/* 2 */
+		if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {
+			OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_INT_EN, 0 ); 										/* 4 */
+			if ( IN_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_STAT ) & ifbp->IFB_IntEnMask ) {				/* 5 */
+				rc = HCF_INT_PENDING;
+			}
+		}
+		break;
+		
+	  case HCF_ACT_INT_ON:						// Enable Interrupt generation
+		if ( --ifbp->IFB_IntOffCnt == 0 ) {																/* 6 */
+			if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {
+				OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_INT_EN, ifbp->IFB_IntEnMask );
+			}
+		}
+		rc = ifbp->IFB_IntOffCnt;
+		break;
+		
+	  case  HCF_ACT_CARD_IN:					// MSF reported Card insertion							/* 7 */
+		ifbp->IFB_CardStat = CARD_STAT_PRESENT;
+		hcf_initialize ( ifbp );
+
+		if ( ifbp->IFB_CardStat & CARD_STAT_ENABLED ) {
+		  (void)hcf_enable( ifbp, 0 );
+		}
+		break;
+	
+	  case 	HCF_ACT_CARD_OUT:  					// MSF reported Card removal							/* 9 */
+		ifbp->IFB_CardStat = 0;
+		break;
+		
+		
+	  case 	HCF_ACT_TALLIES:					// Hermes Inquire Tallies (F100) command				/*12 */
+		action = (hcf_action_cmd)(action - HCF_ACT_TALLIES + CFG_TALLIES);
+		if ( ifbp->IFB_CardStat & CARD_STAT_ENABLED ) {
+		  rc = cmd_wait( ifbp, HCMD_INQUIRE, action );
+		}  		
+		break;
+		
+		
+		
+
+	  default:
+		break;
+	}
+	return rc;
+}/* hcf_action */
+
+
+
+/*******************************************************************************************************************
+
+.MODULE			hcf_connect
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Card Initialization Group for WaveLAN based drivers and utilities
+.DESCRIPTION	Initializes Card and HCF housekeeping
+
+.ARGUMENTS
+  void hcf_connect( IFBP ifbp, hcf_io io_base )
+
+.RETURNS
+	n.a.
+
+  MSF-accessible fields of Result Block:
+	IFB_IOBase				entry parameter io_base
+	IFB_IORange				HREG_IO_RANGE (0x40)
+	IFB_HCFVersionMajor		the major part of the PVCS maintained version number
+	IFB_HCFVersionMinor		the minor part of the PVCS maintained version number
+	IFB_Version				version of the IFB layout (0x01 for this release)
+	
+.NARRATIVE
+
+ Parameters:
+	ifbp		address of the Interface Block
+	io_base		I/O Base address of the NIC
+
+
+  Hcf_connect grants access right for the HCF to the IFB and initializes the HCF housekeeping part of the
+  IFB. Hcf_connect does not perform any I/O.
+
+  The HCF-Version fields are set dynamically, because I do not know of any C mechanism to have the compiler
+  and the version control system (PVCS) cooperate to achieve this at compile time.  The HCFVersions fields are
+  constructed by collecting and shifting the low order nibbles of the PVCS controlled ASCII representation.
+  Note that the low order nibble of a space (0x20) nicely coincides with the low order nibble of an ASCII '0'
+  (0x30). Also note that the code breaks when major or minor number exceeds 99.
+
+
+.DIAGRAM
+ 1:	patch_catch is called as early in the flow as the C-entry code allows to help the HCF debugger as much as
+	possible.  The philosophy behind patch_catch versus a simple direct usage of the INT_3 macro is explained
+	in the description of patch_catch
+ 2:	The IFB is zero-filled.
+ 	This presets IFB_CardStat and IFB_TickIni at appropriate values for hcf_initialize.
+10: In addition to the MSF readable fields mentioned in the description section, the following HCF specific
+	fields are given their actual value:
+	  -	a number of fields as side effect of the calls of hcf_action (see item 14)
+	  -	IFB_Magic
+	IFB_VERSION, which reflects the version of the IFB layout, is defined in HCF.H
+14:	Hcf_connect defaults to "no interrupt generation" (by calling hcf_action with the appropriate parameter),
+	"802.3 frame type" and "no card present" (implicitly achieved by the zero-filling of the IFB).
+	Depending on HCFL, the 802.3 frame type is either initialized in line or by calling hcf_action.
+	
+.NOTICE
+  If io_base ever needs to be dynamic, it may be more logical to pass
+	- io_base at hcf_enable or
+	- have a separate hcf_put_config command or
+	- demand a hcf_disconnect - hcf_connect sequence
+	
+.NOTICE
+  On platforms where the NULL-pointer is not a bit-pattern of all zeros, the zero-filling of the IFB results
+  in an seemingly incorrect initialization of IFB_MBp. The implementation of the MailBox manipulation in
+  put_mb_info protects against the absence of a MailBox based on IFB_MBSize, IFB_MBWp and ifbp->IFB_MBRp. This
+  has ramifications on the initialization of the MailBox via hcf_put_info with the CFG_REG_MB type.
+
+.ENDOC				END DOCUMENTATION
+-------------------------------------------------------------------------------------------------------------*/
+void hcf_connect( IFBP ifbp, 					//address of the Interface Block
+				  hcf_io io_base				//I/O Base address of the NIC
+				) {
+
+hcf_8 *q;
+
+#if defined _M_I86TM
+#endif // _M_I86TM
+	
+
+	for ( q = (hcf_8*)&ifbp[1]; q > (hcf_8*)ifbp; *--q = 0) /*NOP*/;									/* 2 */
+
+	ifbp->IFB_Version	= IFB_VERSION;					  												/* 10*/
+	ifbp->IFB_IOBase	= io_base;
+	ifbp->IFB_IORange	= HREG_IO_RANGE;
+	ifbp->IFB_Magic		= HCF_MAGIC;
+	ifbp->IFB_HCFVersionMajor	= (hcf_8)( (hcf_rev[REV_OFFSET] << 4 | hcf_rev[REV_OFFSET+1]) & 0x0F );
+	ifbp->IFB_HCFVersionMinor	= (hcf_8)( hcf_rev[REV_OFFSET+4] == ' ' ?
+								  		   hcf_rev[REV_OFFSET+3] & 0x0F :
+								  		   (hcf_rev[REV_OFFSET+3] << 4 | hcf_rev[REV_OFFSET+4]) & 0x0F );
+
+	(void)hcf_action(ifbp, HCF_ACT_INT_OFF );															/* 14*/
+    ifbp->IFB_FSBase = HFS_ADDR_DEST_ABS;
+	return;
+}/* hcf_connect	*/
+
+
+
+
+
+/*******************************************************************************************************************
+
+.MODULE			hcf_disable
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Card Initialization Group for WaveLAN based drivers and utilities
+.DESCRIPTION    Disables data transmission and reception
+.ARGUMENTS
+  int hcf_disable( IFBP ifbp, hcf_16 port )
+
+.RETURNS
+	HCF_SUCCESS
+	HCF_ERR_NO_NIC
+	HCF_ERR_TIME_OUT (via cmd_wait)
+	HCF_FAILURE (via cmd_wait)
+	
+  MSF-accessible fields of Result Block:
+   	IFB_CardStat  -	reset CARD_STAT_ENABLED bit iff at completion no port enabled anymore
+
+.NARRATIVE
+
+  Parameters:
+	ifbp		address of the Interface Block
+
+  Condition Settings:
+	Card Interrupts	  - Unchanged
+					  -	Disabled (Note that the value of IFB_IntOffCnt is unchanged)
+					    					  
+
+.NOTICE
+ o  hcf_disable may disable the card interrupts, however it does NOT influence IFB_IntOffCnt.
+	This way it is symmetrical with hcf_enable, which does NOT enable the card interrupts.	
+	
+**************************************************************************************************************/
+int hcf_disable( IFBP ifbp, hcf_16 port ) {
+
+int					rc;
+//hcf_16				p_bit;
+
+		rc = cmd_wait( ifbp, HCMD_DISABLE | (port << 8 ), 0 );
+		ifbp->IFB_CardStat &= (hcf_16)~CARD_STAT_ENABLED;
+		(void)hcf_action( ifbp, HCF_ACT_INT_OFF );														/* 40 */
+		ifbp->IFB_IntOffCnt--;
+	return rc;
+}/* hcf_disable */
+
+
+
+/*******************************************************************************************************************
+
+
+.MODULE			hcf_disconnect
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			NW4
+.APPLICATION	Card Connection for WaveLAN based drivers and utilities
+.DESCRIPTION
+  Disable transmission and reception, release the IFB
+.ARGUMENTS
+  void hcf_disconnect( IFBP ifbp )
+.RETURNS
+  void
+
+  MSF-accessible fields of Result Block:
+  	IFB_CardStat	cleared
+
+.NARRATIVE
+  Parameters:
+	ifbp		address of the Interface Block
+
+  Description:
+	Brings the NIC in quiescent state by calling hcf_initialize, thus preventing any interrupts in the future.
+
+.DIAGRAM
+ 1:	hcf_initialize gives a justification to execute the Hermes Initialize command only when really needed.
+ 	Despite this basic philosophy and although the HCF can determine whether the NIC is initialized based
+ 	on IFB_CardStat, the minimal set of actions to initialize the Hermes is always done by calling
+ 	ini_hermes.
+ 5:	clear all IFB fields
+ 	The clearing of IFB_CardStat prevents I/O on any subsequent hcf_function
+
+.ENDOC				END DOCUMENTATION
+-------------------------------------------------------------------------------------------------------------*/
+void hcf_disconnect( IFBP ifbp ) {
+
+hcf_8 *q;
+
+
+	ini_hermes( ifbp );
+
+	for ( q = (hcf_8*)&ifbp[1]; q > (hcf_8*)ifbp; *--q = 0) /*NOP*/;									/* 5 */
+
+}/* hcf_disconnect */
+
+
+
+
+
+/*******************************************************************************************************************
+
+
+.MODULE			hcf_enable
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Card Initialization Group for WaveLAN based drivers and utilities
+.DESCRIPTION    Enables data transmission and reception
+.ARGUMENTS
+  int hcf_enable( IFBP ifbp, hcf_16 port )
+.RETURNS
+	HCF_SUCCESS
+	HCF_ERR_TIME_OUT (via cmd_wait)
+	HCF_FAILURE (via cmd_wait)
+
+  MSF-accessible fields of Result Block
+
+  Condition Settings:
+	Card Interrupts: Off if IFB_IntOffCnt > 0; On if IFB_IntOffCnt == 0
+					 (Note that the value of IFB_IntOffCnt is unchanged)
+
+.NARRATIVE
+  Parameters:
+  	ifbp	address of the Interface Block
+
+  Description:
+
+	hcf_enable takes successively the following actions:
+ 6:	If the requested port is disabled and if the NIC is present, the Hermes Enable command is executed.
+	If CARD_STAT_PRESENT is off, the body of hcf_enable must be skipped to prevent I/O because the I/O space
+	may no longer owned by the HCF, due to a card swap.
+	The IFB_IntEnMask is set to allow Info events, Receive events and Allocate events to generate interrupts
+	and effectuated if appropriate based on IFB_IntOffCnt by calling enable_int.
+	Note that since the effect of interrupt enabling has no effect on IFB_IntOffCnt, this code may
+	be called not only at the transition from disabled to enabled but whenever a port is enabled.
+12:	When the port successfully changes from disabled to enabled - including the case when no NIC is
+	present - , the NIC status as reflected by IFB_CardStat must change to enabled
+
+.DIAGRAM
+
+.NOTICE
+  When the Hermes enable cmd is given, the static configuration of the Hermes is done.
+.ENDOC				END DOCUMENTATION
+
+-------------------------------------------------------------------------------------------------------------*/
+int hcf_enable( IFBP ifbp, hcf_16 port ) {
+
+int	rc;
+
+
+	
+	if ( (ifbp->IFB_CardStat & CARD_STAT_PRESENT) == 0 
+	   ) { rc = HCF_ERR_NO_NIC;	}	/* 6 */
+	else {
+		rc = HCF_SUCCESS;
+			rc = cmd_wait( ifbp, HCMD_ENABLE | ( port << 8 ), 0 );
+			if ( rc == HCF_SUCCESS ) enable_int( ifbp, HREG_EV_INFO | HREG_EV_RX | HREG_EV_ALLOC );		/* 8 */
+	}
+	if ( rc == HCF_SUCCESS || rc == HCF_ERR_NO_NIC ) {
+		ifbp->IFB_CardStat |= CARD_STAT_ENABLED;
+	}
+	return rc;
+
+}/* hcf_enable */
+
+
+
+/*******************************************************************************************************************
+
+
+.MODULE			hcf_get_data
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.APPLICATION	Data Transfer Function for WaveLAN based drivers and utilities
+.DESCRIPTION
+	Obtains received message data parts from NIC RAM
+.ARGUMENTS
+	int hcf_get_data( IFBP ifbp, int offset, wci_bufp bufp, int len )
+	Card Interrupts disabled
+.RETURNS
+	hcf_16
+		zero			NIC not removed during data copying process
+		HCF_ERR_NO_NIC	NIC removed during data copying process
+		......
+
+  MSF-accessible fields of Result Block: -
+
+.NARRATIVE
+	parameters:
+		ifbp		address of the Interface Block
+		offset		offset (in bytes) in buffer in NIC RAM to start copy process
+		len			length (in bytes) of data to be copied
+		bufp		char pointer, address of buffer in PC RAM
+
+	When hcf_service_nic reports the availability of data, hcf_get_data can be
+	called to copy that data from NIC RAM to PC RAM.
+
+	Hcf_get_data copies the number of bytes requested by the parameter len from
+	NIC RAM to PC RAM. If len is larger than the (remaining) length of the
+	message, undefined data is appended to the message. This implies that if
+	hcf_get_data is called while the last hcf_service_nic reported no data
+	available, undefined data is copied.
+
+	Hcf_get_data starts the copy process at the offset requested by the
+	parameter offset, e.g. offset HFS_ADDR_DEST will start copying from the
+	Destination Address, the very begin of the 802.3 framemessage.
+	In case of a fragmented PC RAM buffer, it is the responsibility of the MSF,
+	to specify as offset the cumulative values of the len parameters of the
+	preceeding hcf_get_data calls. This I/F gives a MSF the facility to read
+	(part of) a message and then read it again.
+	
+.DIAGRAM
+.ENDOC				END DOCUMENTATION
+
+
+-------------------------------------------------------------------------------------------------------------*/
+int hcf_get_data( IFBP ifbp, int offset, wci_bufp bufp, int len ) {
+
+int rc = HCF_SUCCESS;
+//int	tlen;
+
+
+	if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {	
+		if ( offset < 0 ) offset -= HFS_STAT;
+		else {
+			offset += ifbp->IFB_FSBase;
+	    }
+		if ( rc == HCF_SUCCESS ) rc = hcfio_string( ifbp, BAP_1, ifbp->IFB_RxFID, offset, bufp, 0, len, IO_IN );
+	}
+	return rc;
+}/* hcf_get_data */
+
+
+
+
+/**************************************************************************************************************
+
+
+ Name:	hcf_get_info
+
+ Summary: Obtains transient and persistent configuration information from the
+	Card and from the HCF
+
+ Parameters:
+  ifbp	address of the Interface Block
+
+  ltvp	address of LengthTypeValue structure specifying the "what" and the "how much" of the information
+  		to be collected from the HCF or from the Hermes
+
+ Returns:
+	int
+		..... ????????????????	
+
+ Remarks: Transfers operation information and transient and persistent
+ 	configuration information from the Card and from the HCF to the MSF.
+	The exact layout of the provided data structure
+	depends on the action code. Copying stops if either the complete
+	Configuration Information is copied or if the number of bytes indicated
+	by len is copied.  Len acts as a safe guard against Configuration
+	Information blocks which have different sizes for different Hermes
+	versions, e.g. when later versions support more tallies than earlier
+	versions. It is a consious decision that unused parts of the PC RAM buffer are not cleared.
+
+ Remarks: The only error against which is protected is the "Read error"
+	as result of Card removal. Only the last hcf_io_string need
+	to be protected because if the first fails the second will fail
+	as well. Checking for cmd_wait errors is supposed superfluous because
+	problems in cmd_wait are already caught or will be caught by
+	hcf_enable.
+	
+	
+ 3:	tallying of "No inquire space" is done by cmd_wait
+
+ Note:
+	the codes for type are "cleverly" chosen to be identical to the RID
+	
+
+ 7:	The return status of cmd_wait and the first hcfio_in_string can be ignored, because when one fails, the
+ 	other fails via the IFB_TimStat mechanism
+		
+**************************************************************************************************************/
+int hcf_get_info(IFBP ifbp, LTVP ltvp ) {
+
+int				rc = HCF_ERR_LEN;
+//hcf_io			reg;
+hcf_16			i, len;
+hcf_16			type;						//don't change type to unsigned cause of "is it a RID" test
+hcf_16 			*q;							//source pointer (Tally-part of IFB)
+//hcf_16 FAR 		*bq;						//source pointer (Identity or Range records)	;?why bq and not e.g. wq
+wci_recordp		p = ltvp->val;				//destination word pointer (in LTV record)
+//wci_bufp		cp = (wci_bufp)ltvp->val;	//destination char pointer (in LTV record)
+
+	
+	len = ltvp->len;
+	type = ltvp->typ;
+	
+	if ( len > 1 ) {
+	
+		rc = HCF_SUCCESS;
+		switch ( type ) {
+			
+#if MSF_COMPONENT_ID != COMP_ID_AP1
+		  case CFG_TALLIES:																				/* 3 */
+			ltvp->len = len = min( len, (hcf_16)(HCF_TOT_TAL_CNT + HCF_TOT_TAL_CNT + 1) );
+			q = (hcf_16*)/*(wci_recordp)*/&ifbp->IFB_NIC_Tallies; //.TxUnicastFrames;
+			while ( --len ) *p++ = *q++;
+			(void)hcf_action( ifbp, HCF_ACT_TALLIES );
+			break;
+#endif //COMP_ID_AP1
+
+			
+
+			
+			
+		  default:
+			rc = HCF_ERR_NO_NIC;
+			if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {
+				rc = HCF_ERR_TIME_OUT;			
+				  	if ( type < CFG_RID_CFG_MIN ) {
+				  		ltvp->len = 0;
+				  	} else {
+						(void)cmd_wait( ifbp, HCMD_ACCESS, type );											/* 7 */
+						(void)hcfio_string( ifbp, BAP_1, type, 0, (wci_bufp)&i, 1, sizeof(hcf_16), IO_IN );
+						ltvp->len = min( i, len );
+						rc = hcfio_string( ifbp, BAP_1, type, sizeof(hcf_16), (wci_bufp)&ltvp->typ, 1, MUL_BY_2(ltvp->len), IO_IN );
+						if ( rc == HCF_SUCCESS && i > len ) rc = HCF_ERR_LEN;
+					}
+			}
+		}
+	}
+	return rc;
+
+}/* hcf_get_info */
+
+
+/*******************************************************************************************************************
+
+.MODULE			hcf_initialize  ;?in fact an hcf-support routine, given an hcf_... name just in case we want to
+								  export it over the WCI later
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Card Initialization Group for WaveLAN based drivers and utilities
+.DESCRIPTION    ..........., in addition, a light-weight diagnostic test of the NIC
+.ARGUMENTS
+  int hcf_initialize( IFBP ifbp )
+
+.RETURNS
+	HCF_SUCCESS
+	HCF_ERR_NO_NIC
+	HCF_ERR_TIME_OUT;
+	HCF_FAILURE (via cmd_wait)
+				(via hcf_get_info)
+	HCF_ERR_INCOMP_PRI
+	HCF_ERR_INCOMP_STA	
+	
+  MSF-accessible fields of Result Block:
+   	IFB_DUIFRscInd, IFB_NotifyRscInd, IFB_PIFRscInd cleared
+   	IFB_MBInfoLen, IFB_RxLen, IFB_RxStat cleared
+   	IFB_CardStat  -	CARD_STAT_ENA_0	through CARD_STAT_ENA_6
+				  -	CARD_STAT_INCOMP_PRI
+				  -	CARD_STAT_INCOMP_STA
+   	
+
+.NARRATIVE
+
+  Parameters:
+	ifbp		address of the Interface Block
+
+  hcf_initialize will successively:
+  -	initialize the NIC by calling ini_hermes
+  -	calibrate the S/W protection timer against the Hermes Timer by calling calibrate
+
+  Condition Settings:
+	Card Interrupts: Disabled  (Note that the value of IFB_IntOffCnt is unchanged)
+
+  Remarks: since hcf_initialize is the first step in the initialization of the card and since the strategy is to
+   detect problems as a side effect of "necessary" actions, hcf_initialize has, in deviation of the general
+   strategy, an additional "wait for busy bit drop" at all places where Hermes commands are executed. An
+   additional complication is that no calibrated value for the protection count can be assumed since it is
+   part of the first execution of hcf_disable to determine this calibrated value (a catch 22). The initial
+   value (set at INI_TICK_INI by hcf_connect) of the protection count is considered safe, because:
+   o the HCF does not use the pipeline mechanism of Hermes commands.
+   o the likelihood of failure (the only time when protection count is relevant) is small.
+   o the time will be sufficiently large on a fast machine (busy bit drops on good NIC before counter expires)
+   o the time will be sufficiently small on a slow machine (counter expires on bad NIC before the enduser
+     switches the power off in despair
+	IFB_TickIni is used in cmd_wait to protect the Initialize command. The time needed to wrap a 32 bit counter
+	around is longer than many humans want to wait, hence the more or less arbitrary value of 0x10000L is
+	chosen, assuming it does not take too long on an XT and is not too short on a scream-machine.
+	Once we passed the CARD_STAT_PRESENT test on IFB_CardStat, the other bits can be reset. This is needed
+	to have a dynamical adjustment of the Station/Primary Incompatibility flags.
+	Especially IFB_TimStat must be cleared (new round, new chances)
+
+ Remarks: First the HCF disables the generation of card interrupts. Next it waits for the Busy bit in the
+   Command register to drop (the additional safety required for hcf_initialize as described above). If the Hermes
+   passes this superficial health test, the Hermes Initialize command is executed. The Initialize command acts
+   as the "best possible" reset under HCF control. A more "severe/reliable" reset is under MSF control via the
+   COR register.
+
+ Remarks: If the Initialize of the Hermes succeeds, the S/W protection counter is calibrated if not already
+   calibrated. This calibration is "reasonably" accurate because the Hermes is in a quiet state as a result of
+   the Initialize command. The hcf_put_info function is used to program the Hermes Tick for its minimum
+   interval (1024 microseconds). Programming the Tick interval terminates the old interval timing immediately
+   and starts the new interval. Due to this ad-hoc switch the first interval has a larger inaccuracy. By
+   timing immediately a second interval the accuracy improves due to the synchronization of HCF and Hermes.
+   After this second interval, the Hermes Tick is programmed for its default value of 1 second again.
+
+.NARRATIVE
+ 2:	Clear all fields of the IFB except those which need to survive hcf_initialize. This is intended to make
+ 	the behavior and - as a consequence - the debugging of the HCF more reproduceable.
+
+ 3:	Disable the interrupt generation facility (see also #30)
+ 5: Depending on whether there is selective disabling of a single port or a collective disabling of
+	all ports a specific bit or all bits representing the enabled ports are reset. In case of "all ports"
+	none of the other bits except CARD_STAT_ENABLED is relevant, so as an easy implementation all those
+	other bits are cleared.
+	The individual bits conveyed in IFB_CardStat are historically grown. To leave the WCI unchanged, the
+	individual "port enabled" bits are scattered through IFB_CardStat. As a consequence there is some bit
+	arithmetic involved to convert a port number to a bit flag
+	The masking of port with HCF_PORT_MASK is a cheap safeguard against I/F violations by the MSF. If the MSF
+	supplies an invalid bit pattern, unwanted bits may end up in Hermes Command register via Disable command
+	with unpredictable effects.
+ 7: Check whether CARD_STAT_PRESENT bit of IFB_CardStat is on. If not the remainder of hcf_initialize must be
+	skipped to prevent I/O because the I/O space may no longer owned by the HCF, due to a card swap.
+12:	When a single port must be disabled AND it is not the only enabled port, that port is selectively
+	disabled. If all ports or the only enabled port is to be disabled, the disabling is skipped and the
+	Hermes Initiate command is supposed to take care of it all.
+16: perform a superficial Hermes health test. Note that in hcf_initialize all (or at least most) activities are
+	checked for conditions like "Busy bit should drop". If such a condition is not met in time, hcf_initialize
+	returns an error code. Hcf_functions which are only called during "normal" operations may ignore such
+	events. Their only obligation is to prevent that the code hangs.
+	Note that early models of the Hermes needed some arbitrary read before the first write activity to operate
+	stable (ref tracker 27). This code achieves that function as a side effect.
+18:	Initialize the Hermes. The results of this way of initialization depends on the capabilities of the Hermes
+  	firmware. Therefore, the Hermes H/W controlled bits, like those in the evitable register are not guaranteed
+  	to be cleared as result of the initialize command. However it is guaranteed that no more events are in the
+    pipeline. Ack-ing indiscriminately all events resolves this problem. An alternative would be to use the
+    resulting value of "IN_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_STAT )" rather than 0xFFFF to specifically
+    only reset those events which are set. This strategy is considered to be only more aesthetically pleasing
+    (if that).
+20:	Perform some housekeeping tasks
+  - Write HCF_MAGIC as signature to S/W support register 0.  This signature is used to detect card removal
+	wherever the presence of the card is critical while HCF may not yet have been informed by the MSF of the
+	removal of the card.  Note that this task can not be postponed because that would cause the hcfio_in_string
+	called by hcf_get_info to fail
+22:
+
+	  -	IFB_TickIni	must be initialized (at INI_TICK_INI) to prevent that actions like hcf_put_info immediately
+	    after hcf_connect (that is without intervening hcf_disable) at an absent (or failing) NIC take too
+	    long.  Note that this is a legal hcf-sequence according to the WCI-specification.
+
+
+
+
+	IFB_TickIni is the value used to initialize the S/W protection counter in a way which makes the
+	expiration period more or less independent of the processor speed. If IFB_TickIni is not yet calibrated,
+	it is done now.
+	First off all the Hermes Tick period is programmed for a "reasonable" interval, currently 8092 or 8k
+	microseconds, by means of hcf_put_info. Note that IFB_DLTarget, which is guaranteed to get the correct
+	value later on in hcf_enable, is misused as re-entrant storage for the RID used to program the Tick period.
+	The HCF synchronizes itself with the Hermes timer by waiting for the first timer tick. This synchronizing is done by
+	ack-ing the Tick regardless of its current value. This guarantees Tick becomes low. Then Tick is sampled
+	till it is high, which guarantees a new complete interval starts in the Hermes. Tick is acked again and
+	another Tick is awaited. This period is as accurate as we can get.
+	To diminish the chance that in a pre-emptive environment IFB_TickIni is calibrated too low because the HCF
+	just happens to loose control during this calibration, the calibration is performed 10 times and the
+	largest value is used.
+	IFB_TickIni is then set at approximately 1 second by multiplying that largest value by 128. The 8k
+	microseconds interval and the multiplication by 128 are chosen as a compromise between accuracy of
+	the calibration. time consumed by the calibration and possibilities for the compiler to optimize
+	the arithmetic.
+26:	Finally the Hermes Tick period is programmed for a "reasonable" runtime interval, currently 1 second
+	(1,000,000/1,024 kilo-microseconds), by means of hcf_put_info (again the available CONCATENATED storage
+	is misused)
+	Note that in case of failure, IFB_TickIni ends up as INI_TICK_INI, which is a supposedly acceptable
+	value to handle the rare case of a broken card.
+30: The Supplier Range of the Primary Firmware function is retrieved from the Hermes and checked against
+	the Top and Bottom level supported by this HCF.
+	If the primary firmware does not supply this RID or supplies the "old" HardwareStructure Info, the
+	Primary Compatibility check is skipped. These conditions are recognized based on the length field supplied
+	by the Hermes. ;?is this wise in the post-GCA area
+32: In case of a HCF compiled for station functionality, the Supplier Range of the Station Firmware function
+	is retrieved from the Hermes and checked against the Top and Bottom level supported by this HCF.
+	Note that the Firmware can have multiple Variants, but that the HCF currently only supports a single
+	variant.
+40:	Perform some more housekeeping tasks
+  -	Decrement ifbp->IFB_IntOffCnt to compensate side effect of ACT_INT_OFF action at begin of hcf_initialize (see
+	#2). This can not be handled by calling hcf_action with HCF_ACT_ON, because this could as undesirable
+	side effect actually enable interrupts
+	
+.NOTICE
+ o  For all practical WCI purposes there is no practical difference between a Hermes disable command at all
+	individual ports and an hermes initialize command
+ o  hcf_initialize disables the card interrupts, however it does NOT influence IFB_IntOffCnt.
+	This way it is symmetrical with hcf_enable, which does NOT enable the card interrupts.	
+
+
+   	IFB_CardStat  -	CARD_STAT_INCOMP_PRI
+				  -	CARD_STAT_INCOMP_STA
+   	
+ 5:	The house keeping is done, consisting of the steps:
+	- allocate a Tx Frame Structure for the protocol stack
+	- allocate a Tx Frame Structure for the utility
+	- allocate a Information Frame Structure for the Notify command
+	Note that a subsequent allocate is only performed if the preceding one
+	succeeded
+	- if all allocates succeeded, the Resource Indicators corresponding
+	  with the Tx Frames are set
+
+
+**************************************************************************************************************/
+int hcf_initialize( IFBP ifbp ) {
+
+int		rc;
+//hcf_16	*p;
+hcf_8	*q;
+
+
+	for ( q = (hcf_8*)&ifbp->IFB_PIFRscInd; q < (hcf_8*)&ifbp[1]; *q++ = 0) /*NOP*/;					/* 2 */
+
+//	if ( (ifbp->IFB_CardStat & CARD_STAT_INI) == 0 ) {				//present but not initialized	/* 7 */
+	do { //;?CARD_STAT_PRESENT check superfluous as long as hcf_initialize is not defined on the WCI
+		rc = ini_hermes( ifbp );
+		if ( rc != HCF_SUCCESS ) break;																/* 32*/
+		OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_SW_0, HCF_MAGIC );									/* 20*/
+		rc = calibrate( ifbp );   																	/* 22*/
+		if ( rc != HCF_SUCCESS ) break;
+
+#if defined MSF_COMPONENT_ID  //;?interesting question at which level HCFL interacts		
+#endif // MSF_COMPONENT_ID
+        ifbp->IFB_CardStat |= CARD_STAT_INI;	//consider this as sufficient to reach CARD_STAT_INI?	/* 24*/
+		if ( rc != HCF_SUCCESS ) break;   //;? apparently this still should follow the moved IFB_DLTarget logic but
+											//;? think this over for the different scenarios
+		if ( ( ifbp->IFB_PIF_FID    = alloc( ifbp, HFS_TX_ALLOC_SIZE )  ) == 0		||				/* 5 */
+			 ( ifbp->IFB_DUIF_FID   = alloc( ifbp, HFS_TX_ALLOC_SIZE )  ) == 0  ) {
+			rc = HCF_FAILURE;
+		} else {
+			ifbp->IFB_PIFRscInd = ifbp->IFB_DUIFRscInd = 1;
+
+		}
+	} while ( 0 ); //pseudo goto-less, accept "warning: conditional expression is constant"
+
+	return rc;
+}/* hcf_initialize */
+
+
+/*******************************************************************************************************************
+
+
+.MODULE			hcf_put_data
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Data Transfer Function for WaveLAN based drivers and utilities
+.ARGUMENTS
+	void hcf_put_data( IFBP ifbp, wci_bufp bufp, int len, hcf_16 port )
+	Card Interrupts disabled
+
+.RETURNS
+	void
+
+  MSF-accessible fields of Result Block: -
+
+.DESCRIPTION	Transfers (part of) transmit message to the NIC and handles
+	the Ethernet-II encapsulation if applicable
+.NARRATIVE
+	parameters:
+		ifbp		address of the Interface Block
+		bufp		char pointer, address of buffer in PC RAM
+		len			length (in bytes) of data to be copied
+		port		HCF_PORT_0 - HCF_PORT_6 .........;?
+					HCF_PUT_DATA_RESET
+
+
+	Refer to hcf_service;?non-existing reference, for a concise description about possible
+	relation/sequencing of hcf_put_data in the Interrupt Service Routine
+	
+	In essence, hcf_put_data copies the number of bytes specified by parameter len from the location in PC
+	RAM specified by bufp to the NIC RAM buffer associated with the Protocol Stack dedicated FID.
+	The first call succeeding hcf_send (or hcf_enable), writes the first byte at offset HFS_ADDR_DEST in
+	the transmit data buffer, successive hcf_put_data calls continue where the preceeding hcf_put_data stopped.
+	
+	IFB_FrameType determines whether the message in the PC RAM buffer is interpreted as an 802.3 or 802.11
+	frame.  This influences:
+ 	o the position where the first byte of the initial hcf_put_data is stored
+ 	o Only in case of the 802.3 frame type, hcf_put_data checks whether the frame is an Ethernet-II rather
+ 	  than an "official" 802.3 frame. The E-II check is based on the length/type field in the MAC header. If
+ 	  this field has a value larger than 1500, E-II is assumed. The implementation of this test fails if the
+	  length/type field is split over 2 hcf_put_data calls.
+	  If E-II is recognized, the length field HFS_LEN_ABS is skipped for the time being and a SNAP header is
+	  inserted starting at HFS_DAT_ABS. This SNAP header represents either RFC1042 or Bridge-Tunnel
+	  encapsulation, depending on whether the type is absent or present in enc_trans_tbl.
+ 	o In case of the 802.11 frame type, hcf_put_data checks whether the complete header + length field is
+ 	  written (note that part of the header may be written by previous hcf_put_data calls and part may be
+ 	  written by this call).  If so, the next byte is written at HFS_DAT_ABS (the 802.3 header area is skipped)
+
+	It is allowed to write the 802.3 header, 802.11 header and/or data in fragments, e.g. the first
+	hcf_put_data call writes 18 bytes starting at location HFS_ADDR_1_ABS and the second call writes 6 more
+	bytes starting at location HFS_ADDR_4. Although Address part #4 is not present in some 802.11 headers,
+	all 4 addressing parts and the length field must be written in case of 802.11. Once the complete header
+	is written, the data part is written starting from offset HFS_DAT_ABS.
+
+	Hcf_put_data does not check for transmit buffer overflow because the Hermes does this protection.
+	In case of a transmit buffer overflow, the surplus which does not fit in the buffer is simply dropped.
+	Note that this possibly results in the transmission of incomplete frames.
+
+.DIAGRAM
+1*: If the card is not present, prevent all I/O because "our" I/O base may have been given away to someone
+	else in a CS/SS environment.  Also no I/O should be performed if the NIC is not enabled. However
+	an MSF which calls hcf_put_data while the NIC is not enabled probably contains a logic flaw (or has a
+	strategy which was not foreseen at the time this was written)
+10* HCF_PUT_DATA_RESET discards all the data put by preceeding hcf_put_data calls and resets the HCF
+	housekeeping just the same as after an hcf_send triggered allocate event.
+	Note: To make the WCI fail-safe, invalid port numbers are silently rejected by treating them as 
+	HCF_PUT_DATA_RESET. Note that the assumption is that this should never ever occure in a debugged MSF and 
+	that during debugging the ASSERT is sufficient support to help the MSF programmer.
+2*:	This statement is only true at the first hcf_put_data call after an hcf_send result or hcf_enable
+	The housekeeping is done.
+ 	o the PIFRscInd is cleared, so the MSF can not begin another hcf_put_data/hcf_send sequence
+	before completing the current one
+ 	o the Tx Encoding flag (TxFrameType) is cleared
+ 	o the index to the first free position in the FID (IFB_PIFLoadIdx) is initialized based on IFB_FSBase.
+ 	  IFB_FSBase is initialized when hcf_action is called with HCF_ACT_802_3 or HCF_ACT_802_11
+3*:	Pay Attention: it may seem attractive to change this code, e.g. to save the superfluous call to
+	hcfio_out_string when the Destination and Source address are written by the preceeding call and the
+	current call starts at the length/type field. However this code is "reasonably carefully" crafted
+	to take in account all boundary conditions. It is very easy to make a change which does not work under
+	all feasible split ups of the message in fragments.
+	First IFB_PIFLoadIdx is checked.
+	  - If IFB_PIFLoadIdx points past HFS_LEN_ABS, the preceeding call(s) to hcf_put_data already passed the
+	  length/type field. As a consequence the fragment can be concatenated to the data already copied to
+	  NIC RAM.
+	  - If IFB_PIFLoadIdx does not point past HFS_LEN_ABS, the current fragment may or may not contain part of
+	  the Destination and/or Source Address and it may or may not contain the length/type field.
+	  If the fragment contains addressing information or -in case of 802.11- length info , this information
+	  is copied/concatenated to the NIC RAM buffer. The working variables (pointer and length of fragment) as
+	  well as the IFB_PIFLoadIdx are adjusted.
+	The semi-obscure differences in the boundary testing are caused by:
+	  o 802.11: the "below the boundary" area is Addr1, Addr2, Addr3, Ctrl, Adrr4 + DataLen and the "above"
+	  	area is the "real" data
+	  o 802.3: the "below the boundary" area is DestAddr + SrcAddr and the "above" area is the length +
+	  	"real" data
+	  o E-II: the "below the boundary" area is DestAddr + SrcAddr, then there is a "virtual" area with the
+	  	SNAP header (which will in the end include the HCF calculated length)  and the "above" area is the
+	  	"protocol stack length" (is in reality the type code) + "real" data
+4*:	If there is still data left, IFB_PIFLoadIdx may need adjustment (802.11 and E-II encapsulation).  Again
+	note that this length check is crucial to prevent mis-manipulation of IFB_PIFLoadIdx in case the header
+	is written in multiple fragments.
+	In case of 802.3, the E-II check is done. In case of E-II, the encapsulation type (RFC1042 versus
+	Bridge-Tunnel) is determined and the corresponding SNAP header is written to NIC RAM and
+	IFB_PIFLoadIdx is adjusted.
+6*:	All data which is not already copied under 3*, is copied here.
+	In case of 802.11, the HFS_DAT field is the first field written by this code.
+	In case of 802.3, the HFS_LEN field is the first field written by this code.
+	In case of E-II encapsulation, the HFS_TYPE field is the first field written by this code.
+	Note that in case of E-II encapsulation, the HFS_LEN field is not written by hcf_put_data at all, but by
+	hcf_send because the data length is not	known till all fragments have been processed.
+	
+.NOTE	
+	The possible split of a single hcf_put_data call into 2 calls to hcfio_out_string results in 2 calls
+	to bap_ini, which may be unexpected while you are debugging, but is never the less the intended behavior.
+	Along the same line a call of hcfio_out_string with a value of 0 for parameter len may be unexpected, e.g.
+	when the len parameter of hcf_put_data is either 1 or 2, the latter depending on the odd/even aspects of
+	IFB_PIFLoadIdx.	
+	
+	
+	
+.NOTE
+	The test on PIFRscInd to distinguish the initial hcf_put_data from subsequent calls is not thread safe.
+	It is assumed that threaded MSFs have their own mechanism to assure that hcf_put_data calls belonging to
+	a single frame are atomic with respect to each other. It is also assumed that the MSF takes care that
+	the hcf_put_data calls of multiple frames do not run concurrent
+	
+	
+.ENDOC				END DOCUMENTATION
+
+
+-------------------------------------------------------------------------------------------------------------*/
+void hcf_put_data( IFBP ifbp, wci_bufp bufp, int len, hcf_16 port ) {
+
+int		idx;				//working index into Tx Frame structure, presume MSF control
+//int		tlen;				//working type/length of frame, working length for partial copy of frame
+	
+
+	if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {															/* 1 */
+			if ( ifbp->IFB_PIFRscInd ) {																	/* 2 */
+				ifbp->IFB_PIFRscInd = 0;
+				ifbp->IFB_PIFLoadIdx = ifbp->IFB_FSBase;    //;?<HCF_L> should result in 0
+			}
+			
+			idx = ifbp->IFB_PIFLoadIdx;
+			ifbp->IFB_PIFLoadIdx += (hcf_16)len;
+			(void)hcfio_string( ifbp, BAP_0, ifbp->IFB_PIF_FID, idx, bufp, 0, len, IO_OUT);		/* 6 */
+	}
+	return;
+}/* hcf_put_data */
+
+
+/**************************************************************************************************************
+
+
+ Name:	hcf_put_info
+
+ Summary: Transfers operation information and transient and persistent
+ 	configuration information to the Card.
+
+ Parameters:
+  ifbp	address of the Interface Block
+
+  type	specifies the RID (as defined by Hermes I/F)
+
+  bufp	address in NIC RAM where record data is located
+
+   len	length of data (in bytes)
+
+.NARRATIVE
+
+ Remarks:
+	CFG_NOTIFY: only runs after hcf_enable
+
+ Remarks: Configuration information is copied from the provided data
+	structure into the Card. The exact layout of the provided data
+	structure depends on the action code. Also the mechanism used to copy
+	the data to the card depends on the action code. In order to make the
+	changes which are based on the Access command (see support routine put_info)
+	sustain over activities like hcf_diagnose and recovery from PCMCIA card
+	insertion, the data associated with these particular action codes, is
+	saved in the IF-block. The codes for this type are "cleverly" chosen to
+	be identical to the RID.
+	
+	bufp is defined as a pointer to items of type hcf_16 because of the
+	correlation with the Hermes definition
+	
+	
+.DIAGRAM
+
+.NOTICE
+	Future enhancements in the functionality offered by the WCI and/or implementation aspects of the HCF
+	may warrant filtering on the type-field of the LTV to recognize non-MSF accessible records, e.g. CFG_TICK
+	
+**************************************************************************************************************/
+
+int hcf_put_info( IFBP ifbp,
+				  LTVP ltvp		/*number identifying the type of change
+<PRE>
+									CFG_INFO_FRAME_MIN	lowest value representing an Information Frame
+									CFG_NOTIFY			Handover Address
+										
+									CFG_TALLIES			Communications Tallies
+									CFG_SCAN			Scan results
+										                        	
+									CFG_LINK_STAT 		Link Status
+									CFG_ASSOC_STAT		Association Status
+								
+</PRE>							*/
+			    ) {
+
+//int			cnt = 3;
+//hcf_16		i = ltvp->len - 1;
+int			rc = HCF_SUCCESS;
+
+	
+	if ( CFG_RID_CFG_MIN <= ltvp->typ && ltvp->typ <= CFG_RID_CFG_MAX ) {
+      	//all codes between 0xFC00 and 0xFCFF are passed to Hermes)
+//		if ( ( ifbp->IFB_CardStat & CARD_STAT_PRI_STA_PRES ) == CARD_STAT_PRESENT ) {
+//			do {
+//				rc = hcfio_string( ifbp, BAP_1,
+//								   ltvp->typ, 0, (wci_bufp)ltvp, 2, MUL_BY_2(ltvp->len + 1), IO_OUT_CHECK );
+//			} while ( cnt-- && rc != HCF_SUCCESS );
+//			if ( rc == HCF_SUCCESS ) rc = cmd_wait( ifbp, HCMD_ACCESS + HCMD_ACCESS_WRITE, ltvp->typ );
+//			if ( rc == HCF_SUCCESS ) rc = put_info( ifbp, ltvp );
+
+		rc = put_info( ifbp, ltvp );
+//		}
+	}	
+	return rc;
+}/* hcf_put_info */
+
+
+
+
+
+/******************************************************************************************************************
+
+.MODULE			hcf_send
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Data Transfer Function for WaveLAN based drivers and utilities
+.DESCRIPTION	Transmit a message on behalf of the protocol stack
+.ARGUMENTS
+	void hcf_send( IFBP ifbp , hcf_send_type type )
+	Card Interrupts disabled
+
+.RETURNS
+	void
+
+  MSF-accessible fields of Result Block: -
+
+.NARRATIVE
+	Hcf_send transmits the Protocol Stack message loaded in NIC RAM by the
+	preceeding hcf_put_data calls.
+
+.DIAGRAM
+1:	The actual data length (the number of bytes in the Tx Frame structure
+	following the 802.3/802.11 Header Info blocks, is determined by
+	IFB_PIFLoadIdx, the index in the Transmit Frame Structure to store the
+	"next" byte. Note that this value must be compensated for the header info
+	by subtracting HFS_DAT.
+2/3:TxFrameType - which is based on the preceding hcf_put_data calls - defines
+	whether the actual data length is written to the 802.11 or 802.3 Header Info
+	block.
+2:	In case of 802.11, the entry parameter type is augmented to reflect	802.11
+	before it is written to the Control Field block.
+3:	In case of 802.3, the actual length must be converted from the native
+	format of the Host (Little Endian in case of an 80x86) to Big Endian before
+	it is written to the 802.3 Header Info block.
+4:	The actual send+reclaim command is performed by the routine send.
+7:	The return status of hcfio_in_string can be ignored, because when it fails, cmd_wait will fail via the
+ 	IFB_TimStat mechanism
+.NOTICE
+  ;?This comment is definitely out of date
+  The choice to let hcf_send calculate the actual data length as
+  IFB_PIFLoadIdx - HFS_DAT, implies that hcf_put_data with the HFS_LUCENT
+  mechanism MUST be used to write the Data Info Block. A change in this I/F
+  will impact hcf_send as well.
+  An alternative would be to have a parameter datlen. If datlen is zero, the
+  current behavior is used. If datlen has a non-zero value, its value is used
+  as the actual data length (without validating against HCF_MAX_MSG and without
+  validating the total number of bytes put by hcf_put_data).
+
+.NOTICE
+  hcf_put_data/send leave the responsibility to only send messages on enabled ports at the MSF level.
+  This is considered the strategy which is sufficiently adequate for all "robust" MSFs, have the least
+  processor utilization and being still acceptable robust at the WCI !!!!!
+.ENDOC				END DOCUMENTATION
+
+------------------------------------------------------------------------------------------------------------*/
+int hcf_send( IFBP ifbp , hcf_16 port ) {	//;?note that port is unused due to ambivalence about what the "right" I/F is
+
+int	rc = HCF_SUCCESS;
+
+
+	if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {												/* 1 */	
+		/* H/W Pointer problem detection */	
+		if ( ifbp->IFB_BAP_0[0] != ifbp->IFB_FSBase ) {	//;?<HCF _L> should BE HARD CODED, also add to send diag msg	/* 30*/
+			rc = hcfio_string( ifbp, BAP_0, ifbp->IFB_PIF_FID, ifbp->IFB_PIFLoadIdx, NULL, 0, 0, IO_OUT_CHECK );
+			
+			if ( rc == HCF_FAILURE ) {
+				ifbp->IFB_PIFRscInd = 1;
+			}
+		}
+		if ( rc == HCF_SUCCESS ) {
+			if ( /*ifbp->IFB_FrameType == ENC_802_11 || */ ifbp->IFB_TxFrameType == ENC_TX_E_II ) {		/* 2 */
+				ifbp->IFB_PIFLoadIdx -= HFS_DAT_ABS;		//actual length of frame					/* 1 */
+				CNV_INT_TO_BIG_NP(&ifbp->IFB_PIFLoadIdx);  //;?is it worthwhile to have this additional macro
+				(void)hcfio_string( ifbp, BAP_0, ifbp->IFB_PIF_FID, HFS_LEN_ABS,
+										(wci_bufp)&ifbp->IFB_PIFLoadIdx, 0, 2, IO_OUT );			/* 7 */
+			}
+//			send( ifbp, ifbp->IFB_PIF_FID, port | ifbp->IFB_FrameType );								/* 4 */
+			(void)cmd_wait( ifbp, HCMD_TX + HCMD_RECL, ifbp->IFB_PIF_FID );			//justify "void"
+		}
+		/* reset the BAP pointer for the Tx Framestructure, note that we access the BAP not the NIC RAM
+		 * after we relinguished control of the Tx FID to the Hermes
+		 */
+		(void)hcfio_string( ifbp, BAP_0, ifbp->IFB_PIF_FID, ifbp->IFB_FSBase, NULL, 0, 0, IO_IN );
+	}
+	return rc;
+} /* hcf_send */
+
+
+
+/*******************************************************************************************************************
+
+.MODULE			hcf_send_diag_msg
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Data Transfer Function for WaveLAN based drivers and utilities
+.DESCRIPTION	Transmit a message on behalf of the Driver-Utility I/F
+.ARGUMENTS
+	void hcf_send_diag_msg( IFBP ifbp, wci_bufp bufp, hcf_16 len )
+	Card Interrupts disabled
+
+.RETURNS
+	void
+
+  MSF-accessible fields of Result Block: -
+
+.NARRATIVE
+	Hcf_send_diag_msg transmits the message
+.DIAGRAM
+
+ 2:
+
+ 4: Based on the assumption that hcf_send_diag_msg is called at a low frequency, HFS_TX_CNTL_ABS is written
+  	on each call rather than using an IFB-field to remember the previous value and update only if needed
+
+
+.ENDOC				END DOCUMENTATION
+
+-------------------------------------------------------------------------------------------------------------*/
+int hcf_send_diag_msg( IFBP ifbp, hcf_16 type, wci_bufp bufp, int len ) {
+
+int rc = HCF_SUCCESS;
+
+
+	if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {
+		rc = HCF_ERR_BUSY; //;?more appropriate value needed
+		if ( ifbp->IFB_DUIFRscInd ) {																	/* 2 */
+			rc = hcfio_string( ifbp, BAP_0, ifbp->IFB_DUIF_FID, HFS_ADDR_DEST_ABS, bufp, 0, len, IO_OUT_CHECK );
+			if ( rc == HCF_SUCCESS ) {
+				ifbp->IFB_DUIFRscInd = 0;
+				(void)hcfio_string( ifbp, BAP_0, ifbp->IFB_PIF_FID, HFS_TX_CNTL_ABS, 		//justify void
+								  (wci_bufp)&type, 1, 2, IO_OUT );								/* 4 */
+				(void)cmd_wait( ifbp, HCMD_TX + HCMD_RECL, ifbp->IFB_DUIF_FID );			
+			}
+		}
+	}
+	return rc;
+} /* hcf_send_diag_msg */
+
+
+
+
+
+/*******************************************************************************************************************
+
+
+.MODULE			hcf_service_nic
+.LIBRARY 		HCF
+.TYPE 			function
+.SYSTEM			msdos
+.APPLICATION	Data Transfer Function for WaveLAN based drivers and utilities
+.DESCRIPTION	Provides received message and link status information
+.ARGUMENTS
+	int	hcf_service_nic(IFBP ifbp )
+	Card Interrupts disabled
+
+.RETURNS
+	int
+		all the bits of the Hermes evitable register, which are encountered during execution of hcf_service_nic
+		the "pseudo"-events HREG_EV_NO_CARD, HREG_EV_DUIF_RX
+	MSF-accessible fields of Result Block
+		IFB_RxLen			0 or Frame size as reported by LAN Controller
+		IFB_RxStat
+		IFB_MBInfoLen
+		IFB_PIFRscInd
+		IFB_DUIFRscInd
+		IFB_NotifyRscInd
+		IFB_HCF_Tallies
+
+
+.NARRATIVE
+	hcf_service_nic is primarily intended to be part of the Interrupt Service Routine.
+	hcf_service_nic is presumed to neither interrupt other HCF-tasks nor to be interrupted by other HCF-tasks.
+	A way to achieve this is to precede hcf_service_nic as well as all other HCF-tasks with a call to
+	hcf_action to disable the card interrupts and, after all work is completed, with a call to hcf_action to
+	restore (which is not necessarily the same as enabling) the card interrupts.
+	In case of a polled environment, it is assumed that the MSF programmer is sufficiently familiar with the
+	specific requirements of that environment to translate the interrupt strategy to a polled strategy.
+	
+	hcf_service_nic services the following Hermes events:
+		HREG_EV_INFO		Asynchronous Information Frame
+		HREG_EV_INFO_DROP	WMAC did not have sufficient RAM to build Unsolicited Information Frame
+		HREG_EV_ALLOC		Asynchronous part of Allocation/Reclaim completed
+		HREG_EV_RX			the detection of the availability of received messages
+
+	If a message is available, its length is reflected by the IFB_RxLen field of the IFB. This length
+	reflects the 802.3 message length (i.e. the data itself but not the Destination Address, Source Address,
+	DataLength field nor the SAP-header in case of decapsulation by the HCF).
+	If no message is available, IFB_RxLen is zero.
+
+  **Buffer free strategy
+	When hcf_service_nic reports the availability of a message, the MSF can access that message or parts
+	thereof, by means of hcf_get_data calls till the next call of hcf_service_nic. Therefore it must be
+	prevented that the LAN Controller writes new data in the buffer associated with the last hcf_service_nic
+	report.
+	As a consequence hcf_service_nic is the only procedure which can free receive buffers for re-use by the
+	LAN Controller. Freeing a buffer is done implicitly by acknowledging the Rx event to the Hermes. The
+	strategy of hcf_service_nic is to free the buffer it has reported as containing an available message in
+	the preceeding call (assuming there was an available message).
+	A consequence of this strategy is that the Interrupt Service Routine of the MSF must repeatedly call
+	hcf_service_nic till hcf_service_nic returns "no message available". It can be reasoned that
+	hcf_action( INT_ON ) should not be given before the MSF has completely processed a reported Rx-frame. The
+	reason is that the INT_ON action is guaranteed to cause a (Rx-)interrupt (the MSF is processing a
+	Rx-frame, hence the Rx-event bit in the Hermes register must be active). This interrupt will cause
+	hcf_service_nic to be called, which will cause the ack-ing of the "last" Rx-event to the Hermes,
+	causing the Hermes to discard the associated NIC RAM buffer.
+
+
+.DIAGRAM
+ 2: IFB_RxLen and IFB_RxStat must be cleared before the NIC presence check otherwise these values may stay
+ 	non-zero if the NIC is pulled out at an inconvenient moment
+ 4: If the card is not present, prevent all I/O because "our" I/O base may have been given away to someone
+	else in a CS/SS environment.
+	The MSF may have considerable latency in informing the HCF of the card removal by means of an hcf_disable.
+	To prevent that hcf_service_nic reports bogus information to the MSF with all - possibly difficult to
+	debug - undesirable side effects, hcf_service_nic pays performance wise the prize to use the momentanuous
+	NIC presence test by checking the contents of the Hermes register HREG_SW_0 against the value HCF_MAGIC.
+ 6:	The return status of hcf_service_nic is defined as reflecting all interrupt causes this call has run into,
+ 	hence an accumulator is needed. This return status services ONLY to help the MSF programmer to debug the
+ 	total system.
+ 	When the card is removed, the pseudo event HREG_EV_NO_CARD is reported.
+ 	NOTE, the HREG_EV_NO_CARD bit is explicitly not intended for the MSF to detect NIC removal. The MSF must
+ 	use its own - environment specific - means for that.
+10:	ack the "old" Rx-event. See "Buffer free strategy" above for more explanation.
+    IFB_RxFID, IFB_RxLen and IFB_RxStat must be cleared to bring both the internal HCF house keeping as the
+    information supplied to the MSF in the state "no frame received"
+12:	The evitable register of the Hermes is sampled and all non-Rx activities are handled.
+ 	The non-Rx activities are:
+	 -	Alloc.  The corresponding FID register is sampled, and based on this FID, either the IFB_PIFRscInd,
+	 	the IFB_DUIFRscInd or the IFB_NotifyRscInd is raised.
+	 	Note that no ASSERT is performed to check whether the RscInd corresponding with the sampled 
+	 	HREG_ALLOC_FID has a zero value. It is felt that this obscures the code to the reader while adding
+	 	little practical value
+	 -	LinkEvent (including solicited and unsolicited tallies) are handled by procedure isr_info.
+	 -	Info drop events are handled by incrementing a tally
+14:	All the non-Rx/non-Cmd activities are acknowledged. Combining all these acknowledgements to a single 
+	place, is considered an optimization.
+	Note that the Rx-acknowledgement is explicitly not included, as justified in "Buffer free strategy" above.
+	Note that the Cmd-acknowledgement is explicitly not included, because all command handling is handled 
+	in line.
+16:	The handling of the non-Rx activities, may have bought the Hermes sufficient time to raise an Rx event
+	in the evitable register (assuming an other Rx event was pending and this loop through hcf_service_nic
+	acknowledged an Rx event). Therefore the evitable register is sampled again. If a frame is available,
+	the FID of that frame and the characteristics (status and length) are read from the NIC. These values are, 
+	after Endianess conversion if needed, stored in IFB_RxStat and IFB_RxLen. IFB_RxLen is also adjusted for 
+	the size of the 802.3 MAC header. Note: Whether this adjustment is the correct/most optimal for 802.11
+	is debatable, however it is paramount that IFB_RxFID and IFB_RxLEN must either be both zero or both
+	non-zero to get a coherent behavior of the MSF+HCF.
+18:	If the Hermes frame status reflects an error - which can only occure in promiscuous mode - the frame
+	is not further processed and control is passed back to the MSF
+20:	WMP messages are processed by copying them to the MailBox. Accu is updated to reflect the reception
+	of the WMP frame to the debugger and sample is modified to go once more through the loop in the hope 
+	to process the next pending Rx frame.
+22: Both in 802.11 mode and 802.3_pure mode, the frame is not further processed (no decapsulation) and 
+	control is passed back to the MSF.
+	In 802.3 mode the HCF checks whether decaposulation is needed (i.e. the Hermes reported Tunnel
+	encapsulation or the Hermes reported 1042 Encapsulation and the frame type does not match one of the 
+	values in enc_trans_tbl.
+	The actual decapsulation takes place on the fly in hcf_get_data, based on the value of IFB_RxFence.
+	Note that in case of decapsulation the SNAP header is not passed to the MSF, hence IFB_RxLen must be 
+	compensated for the SNAP header length
+	
+.NOTICES
+    To make it possible to discriminate between a message without payload (only MAC addresses and implicit
+    the length) it is a convenient I/F to add 14 ( space occupied by MAC addresses and Length) to the
+    Hermes reported payload. So the maintenance programmer should be forwarned when considering changing
+    this strategy. Also the impact on 802.11 should be considered ;?
+.ENDOC				END DOCUMENTATION
+
+-------------------------------------------------------------------------------------------------------------*/
+int	hcf_service_nic(IFBP ifbp ) {
+
+int		accu = HREG_EV_NO_CARD;
+hcf_16	sample, tmp;
+
+
+    ifbp->IFB_RxLen = ifbp->IFB_RxStat = 0;																		/* 2 */
+	if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT && IN_PORT_WORD( ifbp->IFB_IOBase + HREG_SW_0) == HCF_MAGIC ) {	/* 4 */
+		accu = 0;																								/* 6 */
+        if ( ifbp->IFB_RxFID ) {								    											/*10 */
+            OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_ACK, HREG_EV_RX );
+            ifbp->IFB_RxFID = ifbp->IFB_RxLen = ifbp->IFB_RxStat = 0;
+        }
+        sample = IN_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_STAT );												/*12*/
+        accu |= sample;
+
+        if ( sample & HREG_EV_INFO )		isr_info( ifbp );
+        if ( sample & HREG_EV_ALLOC ) {
+            tmp = IN_PORT_WORD(ifbp->IFB_IOBase + HREG_ALLOC_FID );
+            if ( tmp == ifbp->IFB_PIF_FID ) ifbp->IFB_PIFRscInd = 1;
+            else if ( tmp == ifbp->IFB_DUIF_FID ) ifbp->IFB_DUIFRscInd = 1;
+                 else {
+                    ifbp->IFB_NotifyRscInd = 1;
+                 }
+        }
+        tmp = sample & (hcf_16)~(HREG_EV_RX | HREG_EV_CMD );													/*14 */
+        if ( tmp ) OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_ACK, tmp );
+
+        sample = IN_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_STAT );												/*16 */
+        if ( sample & HREG_EV_RX ) {
+            ifbp->IFB_RxFID = IN_PORT_WORD( ifbp->IFB_IOBase + HREG_RX_FID);
+            (void)hcfio_string(ifbp, BAP_1, ifbp->IFB_RxFID, HFS_STAT_ABS, (wci_bufp)&ifbp->IFB_RxStat, 1, 2, IO_IN );
+            (void)hcfio_string(ifbp, BAP_1, ifbp->IFB_RxFID, HFS_DAT_LEN_ABS, (wci_bufp)&ifbp->IFB_RxLen, 1,2,IO_IN );
+            ifbp->IFB_RxLen += HFS_DAT;
+        }
+    }
+	return accu;
+}/* hcf_service_nic */
+
+
+
+
+
+/**************************************************************************************************************
+************************** H C F   S U P P O R T   R O U T I N E S ********************************************
+**************************************************************************************************************/
+
+
+
+/******************************************************************************************************************
+
+
+.MODULE			alloc
+.LIBRARY 		HCF_SUP
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Support for HCFR routines
+.DESCRIPTION	allocates a (TX or Notify) FID in NIC RAM and clears it
+
+.ARGUMENTS
+
+.RETURNS
+  0:	failure
+  <>0:	PIF value
+
+.NARRATIVE
+
+
+.DIAGRAM
+ 1:	execute the allocate command by calling cmd_wait
+ 2: wait till either the alloc event or a time-out occures
+ 3: if the alloc event occures,
+ 	- read the FID to return it to the caller of alloc
+ 	- acknowledge the alloc event
+ 	- clear the storage allocated in NIC RAM (see notice below)
+ 4:	since alloc is only called after an Hermes initialize command but before the Hermes enable, a failing
+	allocation is considered a H/W failure, hence the Miscellaneous Error tally is incremented
+	
+.NOTICE
+ o  Clearing the FID is not only an aesthetical matter, it is also the cheapest (code-size) way to enforce
+ 	  -	correlation between IFB_TxCntl (which is cleared by hcf_disable) and the field HFS_TX_CNTL_ABS of a
+ 		IFB_PIF_FID
+ 	  -	zero value of the field HFS_TX_CNTL_ABS of a IFB_DUIF_FID (hcf_send_diag_msg only supports port 0)
+ 	
+  Note that Card Interrupts are disabled as a side effect of hcf_disable when alloc is called.  This is a
+  necessary condition, otherwise the ISR can get control, causing hcf_service_nic to run.  This would
+  constitute an error because hcf_service_nic needs a defined IFB_PIF_FID and IFB_DUIF_FID to manipulate
+  IFB_PIFRscInd and IFB_DUIFRscInd
+
+  The put_info functions must be called before the alloc calls because of cnfMaxDataLength ;?Really, what is the catch
+ 	
+ 	
+.DIAGRAM
+.ENDOC				END DOCUMENTATION
+*/
+/*-----------------------------------------------------------------------------------------------------------*/
+hcf_16 alloc( IFBP ifbp, int len ) {
+
+hcf_32 prot_cnt = ifbp->IFB_TickIni;
+hcf_16 pif		= 0;
+hcf_16 zero		= 0;
+
+	if ( cmd_wait( ifbp, HCMD_ALLOC, len ) == HCF_SUCCESS ) {											/* 1 */
+		while ( prot_cnt ) {
+			prot_cnt--;
+			if ( IN_PORT_WORD(ifbp->IFB_IOBase + HREG_EV_STAT ) & HREG_EV_ALLOC ) {						/* 2 */
+				pif = IN_PORT_WORD(ifbp->IFB_IOBase + HREG_ALLOC_FID );									/* 3 */
+				OUT_PORT_WORD(ifbp->IFB_IOBase + HREG_EV_ACK, HREG_EV_ALLOC );
+				(void)hcfio_string( ifbp, BAP_0, pif, 0, (wci_bufp)&zero, 0, 2, IO_OUT );	//justify void
+				len = DIV_BY_2( len );
+				while ( --len ) OUT_PORT_WORD( ifbp->IFB_IOBase + BAP_0, 0 );
+				break;
+			}
+		}
+	}
+	return pif;
+}/* alloc */
+
+
+
+
+
+
+
+
+
+/******************************************************************************************************************
+
+.MODULE			calibrate
+.LIBRARY 		HCF_SUP
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Support for HCFR routines
+.DESCRIPTION	
+
+.ARGUMENTS
+  int calibrate( IFBP ifbp )
+	
+.RETURNS
+  HCF_SUCCESS
+  HCF_ERR_TIME_OUT
+  HCF_..... (via hcf_put_info)
+
+.NARRATIVE
+  o
+  o
+
+
+.DIAGRAM
+ 1:	
+ 2:
+ 	
+.NOTICE
+ o
+ 	
+.DIAGRAM
+.ENDOC				END DOCUMENTATION
+*/
+/*-----------------------------------------------------------------------------------------------------------*/
+int calibrate( IFBP ifbp ) {
+
+LTV_STRCT	x;					// initialization with "= { 2, CFG_TICK_TIME};" causes memset 
+								// to be used under some compilers
+int			cnt = 10;
+int			rc = HCF_SUCCESS;
+hcf_32		prot_cnt;
+
+//	if ( ifbp->IFB_TickIni == 0 ) {										                        	/* 22*/
+	x.len = 2;
+	x.typ = CFG_TICK_TIME;
+	x.val[0] = CNV_LITTLE_TO_INT( 8 );	//no compile time conversion available
+	rc = hcf_put_info( ifbp, &x );
+	ifbp->IFB_TickIni = 0;												                        	/* 22*/
+	while ( rc == HCF_SUCCESS && --cnt ) {
+		prot_cnt = 0;
+		OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_ACK, HREG_EV_TICK );
+		while ( (IN_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_STAT ) & HREG_EV_TICK) == 0 &&
+				++prot_cnt <= INI_TICK_INI ) /*NOP*/;
+		ifbp->IFB_TickIni = max( ifbp->IFB_TickIni, prot_cnt);
+	}
+	if ( ifbp->IFB_TickIni == INI_TICK_INI ) rc = HCF_ERR_TIME_OUT;
+	ifbp->IFB_TickIni *= 128;						//time out value of 8*128 = 1024 k microseconds
+//	}
+	x.val[0] = CNV_LITTLE_TO_INT( ONE_SECOND );
+	rc = hcf_put_info( ifbp, &x );
+	return rc;
+} /* calibrate */
+
+
+
+
+
+
+/**************************************************************************************************************
+
+
+.MODULE			cmd_wait
+.LIBRARY 		HCF_SUP
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Support for HCFR routines
+.DESCRIPTION
+
+.ARGUMENTS
+
+.RETURNS
+  hcf_16
+	HCF_SUCCESS
+	HCF_ERR_TIME_OUT
+	HCF_FAILURE
+	HCF_ERR_BUSY
+	
+.NARRATIVE
+.DIAGRAM
+
+ 1:	the test on rc checks whether a BAP initialization or a call to cmd_wait did ever fail. If so, the Hermes
+	is assumed inoperable/defect, and all subsequent bap_ini/cmd_wait calls are nullified till hcf_disable
+	clears the IFB_TimStat field.
+ 	
+ 2:	Based on the Hermes design, the read of the busy bit is superfluous because we wait for the Cmd bit in
+	the Event Status register.
+
+ 3:	When the Hermes reports on another command than the Host just issued, the two are apparently out of
+ 	sync and all bets are off about the consequences. Therefore this situation is treated the same as an
+ 	Hermes failure as indicated by time-out (blocking all further bap_ini/cmd_wait calls till hcf_disable.
+ 	
+ 5:	If HREG_STAT reflects an error it is either an HCF bug or a H/W problem. Since
+	no distinction can be made at forehand, the "vague" HCF_FAILURE code is used
+	
+.NOTICE
+	Due to the general HCF strategy to wait for command completion, a 2nd command can never be excuted
+	overlapping a previous command. As a consequence the Hermes requirement that no Inquiry command may be
+	executed if there is still an unacknowledged Inquiry command outstanding, is automatically met.
+	However, there are two pseudo-asynchronous commands (Diagnose and Download) which do not adhere to this
+	general HCF strategy. In that case we rely on the MSF to do not overlap these commands, but no protection
+	is offered by the HCF
+.ENDOC				END DOCUMENTATION
+*/
+/* -------------------------------------------------------------------------------------------------------------------*/
+int cmd_wait( IFBP ifbp, int cmd_code, int par_0 ) {
+
+int		rc = ifbp->IFB_TimStat;
+hcf_32	prot_cnt = ifbp->IFB_TickIni;
+
+
+	if ( rc == HCF_SUCCESS ) {																			/* 1 */
+		OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_PARAM_0, par_0 );
+		OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_CMD, cmd_code );
+		while (prot_cnt && (IN_PORT_WORD(ifbp->IFB_IOBase + HREG_EV_STAT) & HREG_EV_CMD) == 0 ) prot_cnt--;/*2 */
+		if ( prot_cnt == 0 ) {
+			rc = ifbp->IFB_TimStat = HCF_ERR_TIME_OUT;
+		} else {
+			rc = IN_PORT_WORD( ifbp->IFB_IOBase + HREG_STAT );
+			OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_ACK, HREG_EV_CMD );
+			if ( (rc ^ cmd_code) & HREG_STAT_CMD_CODE ) {												/* 3 */
+				rc = ifbp->IFB_TimStat = HCF_FAILURE;
+			} else {
+				rc &= HREG_STAT_CMD_RESULT;									//Hermes defined Result Code
+			}
+			if ( rc ) rc = HCF_FAILURE;																	/* 5 */
+		}
+	}
+	return rc;
+}/* cmd_wait */
+
+
+
+/***********************************************************************************************************************
+
+
+ Name:	enable_int
+
+ Summary: Enables a specific Hermes interrupt
+
+ Parameters:
+  ifbp	address of the Interface Block
+  event	Hermes event to be enabled as interrupt source
+
+ Remarks: To get the contents of the IntEn register changed is a two step process:
+
+ 	o change the "shadow" in IFB_IntEnMask
+
+ 	o call hcf_action to actually copy the shadow to the IntEn register.
+
+ 	To prevent a change in the "Card Interrupt En/Disabled state, a balancing
+ 	pair of HCF_ACT_INT_OFF and HCF_ACT_INT_ON must be used. To prevent
+ 	a temporary enabling as undesirable side effect, the first call must be
+ 	HCF_ACT_INT_OFF.
+ 	Note that at the very first interrupt, hcf_service_nic causes the removal of
+ 	the Tick and Cmd bit in the IntEn register.
+ 	
+ 	
+.DIAGRAM
+***********************************************************************************************************************/
+//#pragma  Reminder2( "enable_int: shouldn't this be used in more places" )
+void	enable_int(IFBP ifbp, int event ) {
+
+	ifbp->IFB_IntEnMask |= event;
+	(void)hcf_action( ifbp, HCF_ACT_INT_OFF );
+	(void)hcf_action( ifbp, HCF_ACT_INT_ON );
+	return;
+
+}/* enable_int */
+
+
+
+
+
+/****************************************************************************************************************************
+
+
+.MODULE			ini_hermes
+.LIBRARY 		HCF_SUP
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Support for HCF routines
+.DESCRIPTION
+
+.ARGUMENTS
+
+.RETURNS
+  void
+            
+            
+	As side effect of the Hermes Initialize command, the interrupts are disabled            
+.NARRATIVE
+ 1:	
+ 2:	
+.DIAGRAM
+
+.ENDOC				END DOCUMENTATION
+-------------------------------------------------------------------------------------------------------------*/
+int ini_hermes( IFBP ifbp ) {
+
+int		rc = HCF_ERR_NO_NIC;
+//hcf_32	prot_cnt  = ifbp->IFB_TickIni = INI_TICK_INI;	//initialize at best guess before calibration
+hcf_32	prot_cnt;
+
+    if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {//present										/* 7 */
+		if ( ifbp->IFB_TickIni == 0)  ifbp->IFB_TickIni = INI_TICK_INI;	//initialize at best guess before calibration
+		prot_cnt  = ifbp->IFB_TickIni;
+		while (prot_cnt && IN_PORT_WORD(ifbp->IFB_IOBase + HREG_CMD ) & HCMD_BUSY ) prot_cnt--;		/* 16*/
+			
+		rc = HCF_ERR_TIME_OUT;
+		if ( prot_cnt != 0 ) {
+			rc = cmd_wait( ifbp, HCMD_INI, 0 );														/* 18*/
+			OUT_PORT_WORD( ifbp->IFB_IOBase + HREG_EV_ACK, 0xFFFF );
+		}
+
+	}
+	return rc;
+}/* ini_hermes */
+
+
+/****************************************************************************************************************************
+
+
+.MODULE			isr_info
+.LIBRARY 		HCF_SUP
+.TYPE 			function
+.SYSTEM			msdos
+.SYSTEM			unix
+.SYSTEM			NW4
+.APPLICATION	Support for HCF routines
+.DESCRIPTION
+
+.ARGUMENTS
+
+.RETURNS
+  void
+
+.NARRATIVE
+ 1:	info[0] becomes the length of the T-field + the length of the Value-field in words. Note that it is
+	dangerous to determine the length of the Value field by decrementing info[0], because if -e.g. as a
+	result of a bug in the Hermes as has happened in real life- info[0] becomes 0, a decrement results in
+	a very large number. Therefore all code is crafted around an unchanged info[0], with the intention to
+	make the HCF more robust against I/F violations.
+ 2:	This is an example of the strategy described in #1 above. Info[0] is expected to be HCF_NIC_TAL_CNT + 1.
+	By using a pre-decrement, this value results in HCF_NIC_TAL_CNT movements of a single tally value into
+	the IFB_NIC_Tallies area of the IFB.
+ 3:	Although put_info_mb is robust against a len-parameter with value zero, it accepts any bogus value
+	for the type-parameter.
+.DIAGRAM
+
+.ENDOC				END DOCUMENTATION
+-------------------------------------------------------------------------------------------------------------*/
+void isr_info( IFBP ifbp ) {
+
+hcf_16	info[2], tmp;
+hcf_32	*p;
+
+	tmp = IN_PORT_WORD( ifbp->IFB_IOBase + HREG_INFO_FID );
+	(void)hcfio_string(ifbp, BAP_1, tmp, 0, (wci_bufp)info, 2, sizeof(info), IO_IN );						/* 1 */
+	
+	if ( info[1] == CFG_TALLIES ) {
+		if ( info[0] > HCF_NIC_TAL_CNT ) info[0] = HCF_NIC_TAL_CNT + 1;										/* 2 */
+		p = (hcf_32*)&ifbp->IFB_NIC_Tallies;//.TxUnicastFrames;
+		while ( --info[0] ) *p++ += IN_PORT_WORD( ifbp->IFB_IOBase + BAP_1 );
+	}
+	return;
+}/* isr_info */
+
+
+
+
+
+
+#if defined _M_I86TM
+#endif //_M_I86TM
+
+/***********************************************************************************************************************
+
+
+ Name:	put_info
+
+ Summary: stores Hermes configuration information in the ConfigTable of the IFB
+
+ Parameters:
+  ifbp	address of the Interface Block
+  ltvp	address in NIC RAM where LVT-records are located
+
+
+.NARRATIVE
+
+**************************************************************************************************************/
+int put_info( IFBP ifbp, LTVP ltvp	) {
+
+int					cnt = 3;
+//hcf_16				i = ltvp->len - 1;
+int					rc = HCF_SUCCESS;
+
+	
+	if ( ifbp->IFB_CardStat & CARD_STAT_PRESENT ) {
+	
+
+		do {
+			rc = hcfio_string( ifbp, BAP_1,
+							   ltvp->typ, 0, (wci_bufp)ltvp, 2, MUL_BY_2(ltvp->len + 1), IO_OUT_CHECK );
+		} while ( cnt-- && rc != HCF_SUCCESS );
+		if ( rc == HCF_SUCCESS ) rc = cmd_wait( ifbp, HCMD_ACCESS + HCMD_ACCESS_WRITE, ltvp->typ );
+	}	
+	
+	return rc;
+}/* put_info */
+
+
+
+
+
+
+
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_hcf.h linux.wavelan/drivers/net/pcmcia/wvlan_hcf.h
--- linux/drivers/net/pcmcia/wvlan_hcf.h	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_hcf.h	Sun Jan 28 00:07:48 2001
@@ -0,0 +1,287 @@
+/* This file is part of the Hardware Control Functions Light (HCF-light) library
+   to control the Lucent Technologies WaveLAN/IEEE Network I/F Card.
+   The HCF is the implementation of the Wireless Connection I/F (WCI).
+   
+   The HCF-light files are a subset of the HCF files. The complete set offers a
+   number of additional facilities, e.g. firmware download, Etherner-II encapsulation,
+   additional diagnostic facilities, ASSERT logic to support debugging, 802.11 support,
+   Configuration Management.
+   This complete set is explicitely not in the Public Domain but can be made 
+   available under certain restriction. (see the pointer below for support)
+   
+   The HCF-light files are free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   
+   At the time of this writing, you can request for support at:
+   betasupport@wavelan.com
+   
+   Documentation is expected to be available in the week of 8 Februari 1999
+
+*/
+
+
+#ifndef HCF_H
+#define HCF_H 1
+
+/*************************************************************************************************************
+*
+* FILE	 : hcf.h *************** 2.0 *************************************************************************
+*
+* DATE   : 2000/01/06 23:30:52   1.2
+*
+* AUTHOR : Nico Valster
+*
+* DESC   : Definitions and Prototypes for MSF as well as HCF sources
+*
+*			Customizable via HCFCFG.H
+*
+*
+**************************************************************************************************************
+Instructions to convert HCF.H to HCF.INC by means of H2INC
+
+Use a command line which defines the specific macros and command line options
+needed to build the C-part, e.g. for the DOS ODI driver
+		`h2inc /C /Ni /Zp /Zn hcf	 hcf.h`
+
+
+**************************************************************************************************************
+* COPYRIGHT (c) 1996, 1997, 1998 by Lucent Technologies.	 All Rights Reserved.
+**************************************************************************************************************/
+
+/****************************************************************************
+wvlan_hcf.h,v
+Revision 1.2  2000/01/06 23:30:52  root
+*** empty log message ***
+
+ * 
+ *    Rev 1.0   02 Feb 1999 14:32:30   NVALST
+ * Initial revision.
+Revision 1.2  1999/02/01 22:58:35  nico
+*** empty log message ***
+
+Revision 1.1  1999/01/30 19:24:39  nico
+Initial revision
+
+Revision 1.1  1999/01/30 19:07:57  nico
+Initial revision
+
+ * 
+ *    Rev 1.110   29 Jan 1999 15:52:42   NVALST
+ * intermediate, maybe working but seems to need two times to load in 
+ * light-version
+ * 
+ *    Rev 2.12   29 Jan 1999 10:48:44   NVALST
+ * 
+ *    Rev 1.108   28 Jan 1999 14:43:22   NVALST
+ * 
+****************************************************************************/
+
+/**************************************************************************************************************
+*
+* CHANGE HISTORY
+*
+  961018 - NV
+	Original Entry
+
+*************************************************************************************************************/
+
+
+                                                                                                            
+#include "wvlan_hcfcfg.h"	// System Constants to be defined by the MSF-programmer to tailor the HCF
+#include <stddef.h> //do not move to hcf.cpp to keep Chris (Borland) and Marc (MSVC 4)happy (defines NULL)
+
+#include "wvlan_mdd.h"	// Include file common for HCF, MSF, UIL, USF
+
+/************************************************************************************************************/
+/******************   H C F  F U N C T I O N   P A R A M E T E R	 ****************************************/
+/************************************************************************************************************/
+
+//offsets for hcf_put_data and hcf_get_data
+				
+
+// 802.3/E-II/802.11 offsets to access Hermes control fields
+#define HFS_STAT				-0x2E	//0x0000
+#define 	HFS_STAT_ERR		RX_STAT_ERR	//link "natural" HCF name to "natural" MSF name
+
+#define HFS_Q_INFO				-0x28	//0x0006
+#define HFS_TX_CNTL				-0x22	//0x000C
+#define HFS_FRAME_CNTL			-0x20	//0x000E
+#define HFS_ID					-0x1E	//0x0010
+
+// 802.11 relative offsets to access 802.11 header fields 
+#define HFS_ADDR_1				0x00	//0x0012
+#define HFS_ADDR_2				0x06	//0x0018
+#define HFS_ADDR_3				0x0C	//0x001E
+#define HFS_SEQ_CNTL			0x12	//0x0024
+#define HFS_ADDR_4				0x14	//0x0026
+#define HFS_DAT_LEN				0x1A	//0x002C
+
+// 802.3 / E-II relative offsets to access 802.3 header fields
+#define HFS_ADDR_DEST			0x00	//0x002E
+#define HFS_ADDR_SRC			0x06	//0x0034
+#define HFS_LEN					0x0C	//0x003A
+#define HFS_DAT					0x0E	//0x003C
+
+// E-II relative offsets to access SNAP header fields
+#define HFS_TYPE				0x14	//0x0042	//Eternet-II type in 1042/Bridge-Tunnel encapsulated frame
+
+
+//#define HCF_ACT_INT_PENDING	0x0001		//interrupt pending, return status HCF_ACT_INT_OFF
+
+
+
+/*************************************************************************************************************/
+/****************   H C F  F U N C T I O N   R E T U R N   C O D E S   ***************************************/
+/*************************************************************************************************************/
+
+//Debug Purposes only				!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#define HREG_EV_TICK		0x8000	//WMAC Controller Auxiliary Timer Tick
+#define HREG_EV_RES			0x4000	//WMAC Controller H/W error (Wait Time-out)
+#define HREG_EV_INFO_DROP	0x2000	//WMAC did not have sufficient RAM to build Unsollicited Frame
+#define HREG_EV_NO_CARD		0x0800	/* PSEUDO event: card removed											  */
+#define HREG_EV_DUIF_RX     0x0400  /* PSEUDO event: WMP frame received										  */
+#define HREG_EV_INFO		0x0080	//WMAC Controller Asynchronous Information Frame
+#define HREG_EV_CMD			0x0010	//WMAC Controller Command completed, Status and Response avaialble
+#define HREG_EV_ALLOC		0x0008	//WMAC Controller Asynchronous part of Allocation/Reclaim completed
+#define HREG_EV_TX_EXC		0x0004	//WMAC Controller Asynchronous Transmission unsuccessful completed
+#define HREG_EV_TX			0x0002	//WMAC Controller Asynchronous Transmission successful completed
+#define HREG_EV_RX			0x0001	//WMAC Controller Asynchronous Receive Frame
+
+
+
+//=========================================  T A L L I E S  ===================================================
+
+typedef struct CFG_HERMES_TALLIES_STRCT {  //Hermes Tallies (IFB substructure)
+  hcf_32	TxUnicastFrames;
+  hcf_32	TxMulticastFrames;
+  hcf_32	TxFragments;
+  hcf_32	TxUnicastOctets;
+  hcf_32	TxMulticastOctets;
+  hcf_32	TxDeferredTransmissions;
+  hcf_32	TxSingleRetryFrames;
+  hcf_32	TxMultipleRetryFrames;
+  hcf_32	TxRetryLimitExceeded;
+  hcf_32	TxDiscards;
+  hcf_32	RxUnicastFrames;
+  hcf_32	RxMulticastFrames;
+  hcf_32	RxFragments;
+  hcf_32	RxUnicastOctets;
+  hcf_32	RxMulticastOctets;
+  hcf_32	RxFCSErrors;
+  hcf_32	RxDiscards_NoBuffer;
+  hcf_32	TxDiscardsWrongSA;
+  hcf_32	RxWEPUndecryptable;
+  hcf_32	RxMsgInMsgFragments;
+  hcf_32	RxMsgInBadMsgFragments;
+}CFG_HERMES_TALLIES_STRCT;
+
+
+//Note this way to define CFG_TALLIES_STRCT_SIZE implies that all tallies must keep the same (hcf_32) size
+#define		HCF_NIC_TAL_CNT	(sizeof(CFG_HERMES_TALLIES_STRCT)/ sizeof(hcf_32))
+#define		HCF_TOT_TAL_CNT	(HCF_NIC_TAL_CNT)
+
+/************************************************************************************************************/
+/***********   W C I    F U N C T I O N S    P R O T O T Y P E S   ******************************************/
+/************************************************************************************************************/
+
+#define IFB_VERSION 0x82	 			/* initially 80, to be incremented by every IFB layout change		*/
+
+
+
+/* identifier IFB_STRCT on typedef line needed to get the individual fields in the MS Browser DataBase	*/
+typedef struct IFB_STRCT{               //I/F Block
+/* MSF readable part of Result block structure							*************************************/
+  hcf_io		IFB_IOBase;				/* I/O address of Hermes chip as passed by MSF at hcf_connect call	*/
+#if defined HCF_PORT_IO
+  hcf_16		IFB_IOBase_pad;			// Optional field, makes IFB-layout independent of IFB_IOBase size
+#endif //HCF_PORT_IO
+  hcf_16		IFB_IORange;			// I/O Range used by Hermes chip
+  hcf_8			IFB_Version;			/* initially 0, to be incremented by every IFB layout change		*/
+  hcf_8			IFB_Slack_2;			/* align/slack space												*/
+  hcf_8			IFB_HCFVersionMajor;	// Major version of the HCF.0x01 for this release
+  hcf_8			IFB_HCFVersionMinor;	/* Minor version of the HCF.  Incremented for each coding maintenance 
+  										 * cycle. 0x01 for the Initial release								*/
+  CFG_HERMES_TALLIES_STRCT	IFB_NIC_Tallies;	//Hermes tallies
+
+/* part I (survives hcf_disable)    ************************************************************************/
+  hcf_16		IFB_CardStat;			/* see Design spec													*/
+  hcf_16		IFB_FSBase;				// frame type dependent offset (HFS_ADDR_1_ABS or HFS_ADDR_DEST_ABS)
+  hcf_16		IFB_RxFence;			// frame type dependent gap fence (HFS_ADDR_DEST_ABS or HFS_LEN_ABS)
+  hcf_16		IFB_IntOffCnt;			/* see Design spec													*/
+  hcf_32	 	IFB_TickIni;			/* initialization of counter for 1 ms processor loop				*/
+  										/* keep this unsigned otherwise the "clever" ASSERT in hcf_disable 
+  										 * has a higher risk to get into trouble on slow machines
+  										 * keep this hcf_16 to prevent a "close to infinity" time out if
+  										 * calibration fails on 32-bits machine								*/
+  hcf_16		IFB_Magic;				/* see Design spec													*/
+  hcf_16		IFB_Slack_4[2];			/* align/slack space												*/
+
+/* part II (cleared or re-initialized at hcf_disable/hcf_enable)   *****************************************/
+  hcf_8  		IFB_PIFRscInd;			/* see Design spec   //;?Q:int better than hcf_8 A: No!				*/
+  hcf_8			IFB_DUIFRscInd;			/* Value indicating the command resource availability for the 
+  										 * Driver-Utility I/F (i.e. hcf_send_diag_msg).						*/
+  										/* Values: */                                                       
+  										/* * No command resource		0									*/
+  										/* * Command resource available	01h-FFh								*/
+  hcf_8  		IFB_NotifyRscInd;		/* see Design spec   //;?Q:int better than hcf_8 A: No!				*/
+  hcf_8			IFB_Slack_6;			/* align/slack space												*/
+  hcf_16		IFB_PIF_FID;			/* see Design spec													*/
+  hcf_16		IFB_DUIF_FID;			/* field which contains FID value identifying the Tx Frame Structure,
+  										 * to be used by hcf_send_diag_msg									*/
+  hcf_16		IFB_Notify_FID;			/* field which contains FID value identifying the Notify Frame Struct
+  										 * to be used by hcf_put_info in case of Notify type codes			*/
+  hcf_16		IFB_RxFID;				/* see Design spec													*/
+  hcf_16		IFB_MB_FID;				/* pass appropriate FID to hcf_put_mb_info							*/
+  hcf_16		IFB_TxFrameType;		/* see Design spec													*/
+  hcf_16		IFB_RxLen;				/* see Design spec													*/
+  hcf_16		IFB_RxStat;				/* see Design spec													*/
+  hcf_16		IFB_UnloadIdx;			/* see Design spec													*/
+  hcf_16		IFB_PIFLoadIdx;			/* see Design spec													*/
+  hcf_8 		IFB_TxCntl[2];			/* contents of HFS_TX_CNTL field of TFS
+  										 * 0: MACPort, 1: StrucType,TxEx,TxOK								*/
+  hcf_16		IFB_BAP_0[2];			/* offset
+  										 * RID/FID															*/
+  hcf_16		IFB_BAP_1[2];			/* offset
+  										 * RID/FID															*/
+  hcf_16		IFB_IntEnMask;			/* see Design spec													*/
+  hcf_16		IFB_TimStat;			/* BAP initialization or Cmd Completion failed once					*/
+
+}IFB_STRCT;
+
+
+
+typedef IFB_STRCT*	IFBP;
+
+
+EXTERN_C int	hcf_action			(IFBP ifbp, hcf_action_cmd cmd );
+EXTERN_C void	hcf_assert			(IFBP ifbp, wci_bufp file_name, unsigned int line_number, int q );
+EXTERN_C void	hcf_connect			(IFBP ifbp, hcf_io io_base );
+EXTERN_C int	hcf_disable			(IFBP ifbp, hcf_16 port );
+EXTERN_C void	hcf_disconnect		(IFBP ifbp );
+EXTERN_C int	hcf_enable			(IFBP ifbp, hcf_16 port );
+EXTERN_C int	hcf_get_info		(IFBP ifbp, LTVP ltvp );
+EXTERN_C int	hcf_get_data		(IFBP ifbp, int offset, wci_bufp bufp, int len );
+EXTERN_C int	hcf_service_nic		(IFBP ifbp );
+//EXTERN_C void	hcf_put_data		(IFBP ifbp, wci_bufp bufp, int len );
+EXTERN_C void	hcf_put_data		(IFBP ifbp, wci_bufp bufp, int len, hcf_16 port );
+EXTERN_C int	hcf_put_info		(IFBP ifbp, LTVP ltvp );
+EXTERN_C int	hcf_put_header		(IFBP ifbp, int offset, wci_bufp bufp, int len, hcf_8 check );
+EXTERN_C int	hcf_send			(IFBP ifbp, hcf_16 type );
+EXTERN_C int	hcf_send_diag_msg	(IFBP ifbp, hcf_16 type, wci_bufp bufp, int len );
+
+
+
+
+#endif  /* HCF_H */
+
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_hcfcfg.h linux.wavelan/drivers/net/pcmcia/wvlan_hcfcfg.h
--- linux/drivers/net/pcmcia/wvlan_hcfcfg.h	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_hcfcfg.h	Sun Jan 28 00:07:48 2001
@@ -0,0 +1,1083 @@
+/* This file is part of the Hardware Control Functions Light (HCF-light) library
+   to control the Lucent Technologies WaveLAN/IEEE Network I/F Card.
+   The HCF is the implementation of the Wireless Connection I/F (WCI).
+   
+   The HCF-light files are a subset of the HCF files. The complete set offers a
+   number of additional facilities, e.g. firmware download, Etherner-II encapsulation,
+   additional diagnostic facilities, ASSERT logic to support debugging, 802.11 support,
+   Configuration Management.
+   This complete set is explicitely not in the Public Domain but can be made 
+   available under certain restriction. (see the pointer below for support)
+   
+   The HCF-light files are free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   
+   At the time of this writing, you can request for support at:
+   betasupport@wavelan.com
+   
+   Documentation is expected to be available in the week of 8 Februari 1999
+
+*/
+
+
+#ifndef HCFCFG_H                                                     
+#define HCFCFG_H 1
+
+/**************************************************************************************************************
+*
+* FILE	 : hcfcfg.tpl // hcfcfg.h **************************** 2.0 ********************************************
+*
+* DATE   : 2000/01/06 23:30:52   1.2
+*
+* AUTHOR : Nico Valster
+*
+* DESC   : HCF Customization Macros
+*
+***************************************************************************************************************
+* COPYRIGHT (c) 1994, 1995		 by AT&T.	 				All Rights Reserved.
+* COPYRIGHT (c) 1996, 1997, 1998 by Lucent Technologies.	All Rights Reserved.
+*
+***************************************************************************************************************
+*
+* hcfcfg.tpl list all #defines which must be specified to:
+*    I:	adjust the HCF functions defined in HCF.CPP to the characteristics of a specific environment
+* 		o maximum sizes for messages and notification frames, persistent configuration storage
+* 		o Endianess
+*
+*	II:	Compiler specific macros
+* 		o port I/O macros
+* 		o type definitions
+*
+*  III:	Environment specific ASSERT macro
+*
+*   IV: Compiler specific 
+*
+*    V: ;? specific 
+*
+*
+* By copying HCFCFG.TPL to HCFCFG.H and -if needed- modifying the #defines the WCI functionality can be 
+* tailored
+* T O   D O :  A D D   A   R E C I P E   T O   D O   T H I S
+*
+**************************************************************************************************************/
+
+/****************************************************************************
+wvlan_hcfcfg.h,v
+Revision 1.2  2000/01/06 23:30:52  root
+*** empty log message ***
+
+ * 
+ *    Rev 1.0   02 Feb 1999 14:32:32   NVALST
+ * Initial revision.
+Revision 1.2  1999/02/01 21:01:41  nico
+*** empty log message ***
+
+Revision 1.1  1999/01/30 19:24:39  nico
+Initial revision
+
+Revision 1.1  1999/01/30 19:07:57  nico
+Initial revision
+
+ * 
+ *    Rev 1.110   29 Jan 1999 15:52:44   NVALST
+ * intermediate, maybe working but seems to need two times to load in 
+ * light-version
+ * 
+ *    Rev 1.109   29 Jan 1999 12:50:26   NVALST
+ * intermediate
+ * 
+ *    Rev 1.108   28 Jan 1999 14:43:24   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic + download
+ * passed to Marc
+ * 
+ *    Rev 1.107   27 Jan 1999 13:53:24   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic
+ * 
+ *    Rev 1.106   26 Jan 1999 16:42:46   NVALST
+ * intermediate, corrected loop in hcf_service_nic (which was as result of a 
+ * walkthrough, changed from a bug without consequences into one with consequences
+ * 
+ *    Rev 1.105   25 Jan 1999 14:24:48   NVALST
+ * intermediate, hopefully suitable for release
+ * 
+ *    Rev 1.104   22 Jan 1999 16:59:34   NVALST
+ * intermediate, minor corrections + some HCF-L stuff
+ * 
+ *    Rev 1.103   15 Jan 1999 15:14:46   NVALST
+ * intermediate, deposited as HCF2.10
+ * 
+*************************************************************************************************/
+
+
+/****************************************************************************
+*
+* CHANGE HISTORY
+*
+
+  960702 - NV
+	Original Entry - derived from HCF 2.12
+*************************************************************************************************/
+
+
+/*  * * * * * * * * * * * * * * * * * * * * * *  I * * * * * * * * * * * * * * * * * * * * * * */
+
+/*	Endianess
+ *	Default: HCF_LITTLE_ENDIAN
+ *	Little Endian (a.k.a. Intel), least significant byte first
+ *	Big Endian (a.k.a. Motorola), most significant byte first
+ *
+ * If neither HCF_LITTLE_ENDIAN nor HCF_BIG_ENDIAN, the defintion of the following macros must be supplied
+ * by the MSF programmer:
+ *  o CNV_LITTLE_TO_INT(w)			interprets the 16-bits input value as Little Endian, returns an hcf_16
+ * 	o CNV_BIG_TO_INT(w)				interprets the 16-bits input value as Big Endian, returns an hcf_16
+ * 	o CNV_INT_TO_BIG_NP(addr)		converts in place the 16-bit value addressed by a near pointer from hcf_16
+ * 									to Big Endian
+ * 	o CNV_LITTLE_TO_INT_NP(addr)	converts in place the 16-bit value addressed by a near pointer from 
+ *									Little endian to hcf_16
+ *
+ * At a number of places in the HCF code, the CNV_INT_TO_BIG_NP macro is used. While it does have the desired 
+ * effect on all platforms, it's naming is misleading, so revisit all places where these CNV macros are used
+ * to assure the right name is used at the right place.
+ * Hint: introduce CNV_HOST_TO_NETWORK names if appropriate
+ *
+ */
+ 
+#define HCF_LITTLE_ENDIAN			// selects Little Endian (a.k.a. Intel), least significant byte first
+//#define HCF_BIG_ENDIAN				// selects Big Endian (a.k.a. Motorola), most significant byte first
+
+/*	I/O Address size
+ *	Platforms which use port mapped I/O will (in general) have a 64k I/O space, conveniently expressed in
+ *	a 16-bits quantity
+ *	Platforms which use memory mapped I/O will (in general) have an I/O space much larger than 64k,
+ *	and need a 32-bits quantity to express the I/O base
+ *	To accomodate this the macros HCF_PORT_IO and HCF_MEM_IO are available. Exactly 1 of these must be
+ *	defined. If HCF_PORT_IO is defined, the HCF will use an hcf_16 to express I/O base and store in the
+ *	IFB. If HCF_MEM_IO, an hcf_32 is used for this purpose. The default is HCF_PORT_IO
+ */
+#define HCF_PORT_IO
+//#define HCF_MEM_IO
+
+/*	Alignment
+ *	Some platforms can access words on odd boundaries (with possibly an performance impact), at other
+ *	platforms such an access may result in a memory access violation.
+ *	It is assumed that everywhere where the HCF casts a char pointer into a word pointer, the 
+ *	alignment criteria are met. This put some restrictions on the MSF, which are assumed to be 
+ *	"automatically" fullfilled at the applicable platforms
+ *	To assert this assumption, the macro HCF_ALIGN can be defined. The default vaslue is 0, meaning no
+ *	alignment, a value of 2 means word alignment, other values are invalid
+ */
+
+/*  * * * * * * * * * * * * * * * * * * * * * * II * * * * * * * * * * * * * * * * * * * * * * */
+
+
+
+/************************************************************************************************/
+/******************  C O M P I L E R   S P E C I F I C   M A C R O S  ***************************/
+/************************************************************************************************/
+/*************************************************************************************************
+*
+* The platforms supported by this version are:
+*	- Microsoft Visual C 1.5 (16 bits platform)
+*	- Microsoft Visual C 2.0 (32 bits platform)
+*	- Watcom C/C++ 9.5
+*	- SCO UNIX
+*
+* In this version of hcfiocfg.tpl all macros except the MSVC 1.5 versions are either dependent on
+* compiler/environment supplied macros (e.g. _MSC_VER or "def-ed out"
+*
+* By selecting the appropriate Macro definitions by means of modifying the
+* "#ifdef 0/1" lines, the HCF can be adjusted for the I/O chararcteristics of
+* a specific compiler
+*
+* If needed the macros can be modified or replaced with definitions appropriate
+* for your personal platform
+* If you need to make such changes it is appreciated if you inform Lucent Technologies WCND Utrecht
+* That way the changes can become part of the next release of the WCI
+*
+*
+*	The prototypes and functional description of the macros are:
+*
+*	hcf_8	IN_PORT_BYTE(  hcf_16 port)
+*			Reads a byte (8 bits) from the specified port
+*
+*	hcf_16	IN_PORT_WORD(  hcf_16 port)
+*			Reads a word (16 bits) from the specified port
+*
+*	void	OUT_PORT_BYTE( hcf_16 port, hcf_8 value)
+*			Writes a byte (8 bits) to the specified port
+*
+*	void	OUT_PORT_WORD( hcf_16 port, hcf_16 value)
+*			Writes a word (16 bits) to the specified port
+*
+*	void	IN_PORT_STRING( port, dest, len)
+*			Reads len number of words from the specified port to the (FAR) address dest in PC-RAM
+*			Note that len specifies the number of words, NOT the number of bytes
+*			!!!NOTE, although len specifies the number of words, dest MUST be a char pointer NOTE!!!
+*			See also the common notes for IN_PORT_STRING and OUT_PORT_STRING
+*
+*	void	OUT_PORT_STRING( port, src, len)
+*			Writes len number of words from the (FAR) address src in PC-RAM to the specified port
+*			Note that len specifies the number of words, NOT the number of bytes.
+*			!!!NOTE, although len specifies the number of words, src MUST be a char pointer NOTE!!!
+*
+*			The peculiar combination of word-length and char pointers for IN_PORT_STRING as well as
+*			OUT_PORT_STRING is justified by the assumption that it offers a more optimal algorithm
+*
+*			Note to the HCF-implementor:
+*			Due to the passing of the parameters to compiler specific blabla.........
+*			do not use "expressions" as parameters, e.g. don't use "ifbp->IFB_IOBase + HREG_AUX_DATA" but
+*			assign this to a temporary variable.
+*
+*
+*  NOTE!!	For convenience of the MSF-programmer, all {IN|OUT}_PORT_{BYTE|WORD|STRING} macros are allowed to 
+*			modify their parameters (although some might argue that this would constitute bad coding
+*			practice). This has its implications on the HCF, e.g. as a consequence these macros should not
+*			be called with parameters which have side effects, e.g auto-increment.
+*
+*  NOTE!!	in the Micosoft implementation of inline assembly it is O.K. to corrupt all flags except
+*			the direction flag and to corrupt all registers except the segment registers and EDI, ESI, 
+*			ESP and EBP (or their 16 bits equivalents).
+*			Other environments may have other constraints
+*
+*  NOTE!!	in the Intel environment it is O.K to have a word (as a 16 bits quantity) at a byte boundary, 
+*			hence IN_/OUT_PORT_STRING can move words between PC-memory and NIC-memory with as only
+*			constraint that the the words are on a word boundary in NIC-memory. This does not hold true
+*			for all conceivalble environments, e.g. an Motorola 68xxx does not allow this, in other
+*			words whenever there is a move from address in 2*n in one memory type to address 2*m+1 in the
+*			other type, the current templates for IN_/OUT_PORT_STRING are unsuitable. Probably the
+*			boundary conditions imposed by these type of platforms prevent this case from materializing
+*
+*************************************************************************************************/
+
+/************************************************************************************************/
+/****************************  N E T W A R E   3 8 6  *******************************************/
+/************************************************************************************************/
+
+#if defined  __NETWARE_386__	/* WATCOM */
+
+#define	MSF_COMPONENT_ID			COMP_ID_ODI_32
+#define HCF_STA						//station characteristics
+
+#include <conio.h>
+
+//#define CNV_LITTLE_TO_INT(x) (x)			// No endianess conversion needed
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#define FAR							// flat 32-bits code
+#define BASED 
+
+#define IN_PORT_BYTE(port)			((hcf_8)inp( (hcf_io)(port) ))  //;?leave out cast to hcf_8;?
+#define IN_PORT_WORD(port)			(inpw( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)	(outp( (hcf_io)(port), value ))
+#define OUT_PORT_WORD(port, value)	(outpw( (hcf_io)(port), value ))
+
+#define IN_PORT_STRING( prt, dst, n)	while ( n-- ) { *(hcf_16 FAR*)dst = IN_PORT_WORD( prt ); dst += 2; }
+#define OUT_PORT_STRING( prt, src, n)	while ( n-- ) { OUT_PORT_WORD( prt, *(hcf_16 FAR*)src ) ; src  += 2; }
+
+#endif	// __NETWARE_386__
+
+
+// Note:
+// Visual C++ 1.5 : _MSC_VER ==  800
+// Visual C++ 4.0 : _MSC_VER == 1000
+// Visual C++ 4.2 : _MSC_VER == 1020
+
+
+/************************************************************************************************/
+/****************************  P A C K E T   D R I V E R  ***************************************/
+/**********************************  D O S   O D I  *********************************************/
+/************************************************************************************************/
+
+#if defined WVLAN_42 || defined WVLAN_43|| defined WVLAN43L
+
+#pragma warning ( disable: 4001 )
+										
+#define HCF_STA						//station characteristics
+
+#if defined WVLAN_43
+#define	MSF_COMPONENT_ID			COMP_ID_ODI_16
+#define	MSF_COMPONENT_VAR			1
+#define	MSF_COMPONENT_MAJOR_VER		1
+#define	MSF_COMPONENT_MINOR_VER		4
+
+#elif defined WVLAN_42
+#define	MSF_COMPONENT_ID			COMP_ID_PACKET
+#define	MSF_COMPONENT_VAR			1
+#define	MSF_COMPONENT_MAJOR_VER		1
+#define	MSF_COMPONENT_MINOR_VER		24
+
+#elif defined WVLAN43L
+#define	HCF_MAX_CONFIG				0
+
+#define	MSF_COMPONENT_MAJOR_VER		0
+#define	MSF_COMPONENT_MINOR_VER		1
+
+#endif //WVLAN_xx
+										
+#define FAR  __far					// segmented 16 bits mode
+#if defined _M_I86TM
+#define BASED __based(__segname("_CODE"))
+#else
+#define BASED 
+#endif // _M_I86TM
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#include <stdio.h>
+#include <conio.h>
+//#ifndef _DEBUG 
+#pragma intrinsic( _inp, _inpw, _outp, _outpw )
+//#endif // _DEBUG
+
+#define IN_PORT_BYTE(port)			((hcf_8)_inp( (hcf_io)(port) ))
+#define IN_PORT_WORD(port)			((hcf_16)_inpw( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)	((void)_outp( (hcf_io)(port), value ))
+#define OUT_PORT_WORD(port, value)	((void)_outpw( (hcf_io)(port), value ))
+
+#if defined HCF_STRICT
+#define IN_PORT_STRING( prt, dst, n)	{ ips( prt, dst, n); }
+#define OUT_PORT_STRING( prt, dst, n)	{ ops( prt, dst, n); }
+#elif 0												// C implementation
+#define IN_PORT_STRING( prt, dst, n)	while ( n-- ) { *(hcf_16 FAR*)dst = IN_PORT_WORD( prt ); dst += 2; }
+#define OUT_PORT_STRING( prt, src, n)	while ( n-- ) { OUT_PORT_WORD( prt, *(hcf_16 FAR*)src ) ; src  += 2; }
+//;?  WHY hcf_16 FAR*)src and not unsigned char FAR*)src
+#else												// Assembler implementation
+#define IN_PORT_STRING( port, dest, len) __asm 		\
+{													\
+	__asm push di                               	\
+	__asm push es                                 	\
+	__asm mov cx,len                            	\
+	__asm les di,dest                           	\
+	__asm mov dx,port                           	\
+	__asm rep insw                              	\
+	__asm pop es	                            	\
+	__asm pop di	                            	\
+}
+
+#define OUT_PORT_STRING( port, src, len) __asm		\
+{                                               	\
+	__asm push si                                 	\
+	__asm push ds                                 	\
+	__asm mov cx,len                              	\
+	__asm lds si,src                             	\
+	__asm mov dx,port                             	\
+	__asm rep outsw	                            	\
+	__asm pop ds                                  	\
+	__asm pop si                                  	\
+}
+
+#endif	// Asm or C implementation
+
+#endif	/* WVLAN_43, WVLAN_42 (DOS ODI, Packet Driver) */
+
+
+/************************************************************************************************/
+/*************************************  W C I T S T *********************************************/
+/************************************************************************************************/
+
+#if defined WCITST
+
+#pragma warning ( disable: 4001 )
+										
+#define HCF_STA						//station characteristics
+#define HCF_AP						//AccesPoint characteristics
+
+#if _CONSOLE
+#define FAR							// flat 32 bits mode  (also defined in WINDEF.H)
+#define BASED 
+#else
+#define FAR  __far					// segmented 16 bits mode
+#if defined _M_I86TM
+#define BASED __based(__segname("_CODE"))
+#else
+#define BASED 
+#endif // _M_I86TM
+#endif  //_CONSOLE
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#include <stdio.h>
+#include <conio.h>
+#ifndef _DEBUG
+#pragma intrinsic( _inp, _inpw, _outp, _outpw )
+#endif // _DEBUG
+
+#ifdef LOG
+extern FILE* utm_logfile;
+hcf_16	ipw( hcf_16 port );
+hcf_8	ipb( hcf_16 port );
+void	opw( hcf_16 port, hcf_16 value );
+void	opb( hcf_16 port, hcf_8 value );
+
+#define IN_PORT_BYTE(port)			ipb( (hcf_io)(port) )
+#define IN_PORT_WORD(port)			ipw( (hcf_io)(port) )
+#define OUT_PORT_BYTE(port, value)	opb( (hcf_io)(port), (hcf_8)(value) )
+#define OUT_PORT_WORD(port, value)	opw( (hcf_io)(port), (hcf_16)(value) )
+#else //LOG
+#define IN_PORT_BYTE(port)			((hcf_8)_inp( (hcf_io)(port) ))
+#define IN_PORT_WORD(port)			((hcf_16)_inpw( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)	((void)_outp( (hcf_io)(port), value ))
+#define OUT_PORT_WORD(port, value)	((void)_outpw( (hcf_io)(port), value ))
+#endif //LOG
+
+#define	toch_maar_geen_asm
+#if defined(toch_maar_asm)  && !defined(__DA_C__)  //;? temporary solution to satisfy DA-C
+#define IN_PORT_STRING( port, dest, len) __asm 		\
+{													\
+	__asm push di                               	\
+	__asm push es                                 	\
+	__asm mov cx,len                            	\
+	__asm les di,dest                           	\
+	__asm mov dx,port                           	\
+	__asm rep insw                              	\
+	__asm pop es	                            	\
+	__asm pop di	                            	\
+}
+
+#define OUT_PORT_STRING( port, src, len) __asm		\
+{                                               	\
+	__asm push si                                 	\
+	__asm push ds                                 	\
+	__asm mov cx,len                              	\
+	__asm lds si,src                             	\
+	__asm mov dx,port                             	\
+	__asm rep outsw	                            	\
+	__asm pop ds                                  	\
+	__asm pop si                                  	\
+}
+
+#else	//toch_maar_asm  && !__DA_C__
+#define IN_PORT_STRING( prt, dst, n)	while ( n-- ) { *(hcf_16 FAR*)dst = IN_PORT_WORD( prt ); dst += 2; }
+#define OUT_PORT_STRING( prt, src, n)	while ( n-- ) { OUT_PORT_WORD( prt, *(hcf_16 FAR*)src ) ; src  += 2; }
+//;?  WHY hcf_16 FAR*)src and not unsigned char FAR*)src
+#endif	//toch_maar_asm  && !__DA_C__
+
+#endif	/* WCITST */
+
+/************************************************************************************************/
+/********************************************  W S U  *******************************************/
+/************************************************************************************************/
+
+#if 0 //;? conflicts with WIN_CE _MSC_VER >= 1000 	/* Microsoft Visual C ++ 4.x, 5.x */
+
+// Note:
+// Visual C++ 4.0 : _MSC_VER == 1000
+// Visual C++ 4.2 : _MSC_VER == 1020
+
+										
+#pragma warning ( disable: 4001 )
+										
+#define HCF_STA						//station characteristics
+
+//#if defined WVLAN_43
+//#define	MSF_COMPONENT_ID			COMP_ID_ODI_16
+//#else if defined WVLAN_42
+//#define	MSF_COMPONENT_ID			COMP_ID_PACKET
+//#endif //WVLAN_xx
+										
+#if !defined FAR
+//#if _CONSOLE
+//#define FAR							// flat 32 bits mode  (also defined in WINDEF.H)
+//#define BASED 
+//#else
+#define FAR							// far is an obsolete key in Visual C++ 4.x
+//#if defined _M_I86TM
+//#define BASED __based(__segname("_CODE"))
+//#else
+#define BASED 
+//#endif // _M_I86TM
+//#endif  //_CONSOLE
+#endif	//!defined FAR
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#include <stdio.h>
+#include <conio.h>
+
+#define IN_PORT_BYTE(port)			((hcf_8)_inp( (hcf_io)(port) ))
+#define IN_PORT_WORD(port)			((hcf_16)_inpw( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)	((void)_outp( (hcf_io)(port), value ))
+#define OUT_PORT_WORD(port, value)	((void)_outpw( (hcf_io)(port), value ))
+
+#define	toch_maar_geen_asm
+#if defined(toch_maar_asm)
+#define IN_PORT_STRING( port, dest, len) __asm 		\
+{													\
+	__asm push di                               	\
+	__asm push es                                 	\
+	__asm mov cx,len                            	\
+	__asm les di,dest                           	\
+	__asm mov dx,port                           	\
+	__asm rep insw                              	\
+	__asm pop es	                            	\
+	__asm pop di	                            	\
+}
+
+#define OUT_PORT_STRING( port, src, len) __asm		\
+{                                               	\
+	__asm push si                                 	\
+	__asm push ds                                 	\
+	__asm mov cx,len                              	\
+	__asm lds si,src                             	\
+	__asm mov dx,port                             	\
+	__asm rep outsw	                            	\
+	__asm pop ds                                  	\
+	__asm pop si                                  	\
+}
+
+#else	//toch_maar_asm
+#define IN_PORT_STRING( prt, dst, n)	while ( n-- ) { *(hcf_16 FAR*)dst = IN_PORT_WORD( prt ); dst += 2; }
+#define OUT_PORT_STRING( prt, src, n)	while ( n-- ) { OUT_PORT_WORD( prt, *(hcf_16 FAR*)src ) ; src  += 2; }
+//;?  WHY hcf_16 FAR*)src and not unsigned char FAR*)src
+#endif	//toch_maar_asm
+
+#endif	/* _MSC_VER >= 1000 (Microsoft Visual C++ 4.0 ) */
+
+
+
+
+/************************************************************************************************/
+/******************************************  L I N U X  *****************************************/
+/************************************************************************************************/
+
+#if defined __linux__
+
+#define HCF_STA						//station characteristics
+#define	MSF_COMPONENT_ID	COMP_ID_LINUX
+#define	MSF_COMPONENT_VAR			1
+#define	MSF_COMPONENT_MAJOR_VER		0
+#define	MSF_COMPONENT_MINOR_VER		4
+
+#include <asm/io.h>
+
+//#define CNV_LITTLE_TO_INT(x)			// No endianess conversion needed										
+
+#define FAR							// flat 32-bits code
+#define BASED 
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#define IN_PORT_BYTE(port)			((hcf_8)inb( (hcf_io)(port) ))
+#define IN_PORT_WORD(port)			((hcf_16)inw( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)	(outb( (hcf_8) (value), (hcf_io)(port) ))
+#define OUT_PORT_WORD(port, value)	(outw( (hcf_16) (value), (hcf_io)(port) ))
+
+#ifdef	toch_maar_asm
+#else
+#define IN_PORT_STRING( prt, dst, n)	while ( n-- ) { *(hcf_16 FAR*)dst = IN_PORT_WORD( prt ); dst += 2; }
+#define OUT_PORT_STRING( prt, src, n)	while ( n-- ) { OUT_PORT_WORD( prt, *(hcf_16 FAR*)src ) ; src  += 2; }
+#endif	//toch_maar_asm
+
+#endif	/* LINUX */
+
+
+
+/************************************************************************************************/
+/********************************** S C O   U N I X  ********************************************/
+/************************************************************************************************/
+
+#if 0
+
+#define HCF_STA						//station characteristics
+#define	MSF_COMPONENT_ID
+
+//#define CNV_LITTLE_TO_INT(x)			// No endianess conversion needed										
+
+#define FAR							// flat 32-bits code
+#define BASED 
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#define IN_PORT_BYTE(port)			((hcf_8)inb( (hcf_io)(port) ))
+#define IN_PORT_WORD(port)			((hcf_16)inw( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)	(outb( (hcf_io)(port), (hcf_8) (value) ))
+#define OUT_PORT_WORD(port, value)	(outw( (hcf_io)(port), (hcf_16) (value) ))
+
+#define FAR							// flat 32-bits code
+#define BASED 
+
+
+#endif	/* SCO UNIX */
+
+
+/************************************************************************************************/
+/*********************************  M I N I P O R T  ********************************************/
+/************************************************************************************************/
+
+#if 0
+
+#define	MSF_COMPONENT_ID			COMP_ID_MINIPORT
+#define HCF_STA						//station characteristics
+
+#include <ndis.h>
+#include <version.h>
+
+#define	MSF_COMPONENT_VAR			1
+#define	MSF_COMPONENT_MAJOR_VER		TPI_MAJOR_VERSION
+#define	MSF_COMPONENT_MINOR_VER		TPI_MINOR_VERSION
+
+
+//#define CNV_LITTLE_TO_INT(x)			// No endianess conversion needed										
+
+#if !defined FAR
+#define FAR							// flat 32-bits code
+#endif //!defined FAR
+
+#define BASED 
+
+__inline UCHAR NDIS_IN_BYTE( ULONG port )
+{
+    UCHAR value;
+    NdisRawReadPortUchar(port , &value);
+    return (value);
+}
+
+__inline USHORT NDIS_IN_WORD( ULONG port )
+{
+    USHORT value;
+    NdisRawReadPortUshort(port , &value);
+    return (value);
+}
+
+#define IN_PORT_BYTE(port)			NDIS_IN_BYTE( (ULONG) (port) )
+#define IN_PORT_WORD(port)			NDIS_IN_WORD( (ULONG) (port) )
+#define OUT_PORT_BYTE(port, value)	NdisRawWritePortUchar( (ULONG) (port) , (UCHAR) (value))
+#define OUT_PORT_WORD(port, value)	NdisRawWritePortUshort((ULONG) (port) , (USHORT) (value))
+
+#define IN_PORT_STRING(port, addr, len)		NdisRawReadPortBufferUshort(port, addr, (len));
+#define OUT_PORT_STRING(port, addr, len)	NdisRawWritePortBufferUshort(port, addr, (len));
+
+typedef UCHAR	hcf_8;
+typedef USHORT	hcf_16;
+typedef ULONG	hcf_32;
+
+#endif	/* MINIPORT */
+
+/************************************************************************************************/
+/*********************************  W A V E P O I N T  ******************************************/
+/************************************************************************************************/
+
+#if defined WVLAN_81	/* BORLANDC */
+
+#define HCF_AP						//access point characteristics
+#define	MSF_COMPONENT_ID	COMP_ID_AP1
+#define	MSF_COMPONENT_VAR			1
+#define	MSF_COMPONENT_MAJOR_VER		3
+#define	MSF_COMPONENT_MINOR_VER		34
+
+#include <dos.h>
+
+//#define CNV_LITTLE_TO_INT(x)			// No endianess conversion needed										
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+//#define HCF_ASSERT					0  /* debug build only */
+
+#if !defined FAR
+#define FAR  far					// segmented 16 bits mode
+#endif //!defined FAR
+#define BASED 
+
+
+#define IN_PORT_BYTE(port)					(inportb( (hcf_io)(port) ))
+#define IN_PORT_WORD(port)					(inport( (hcf_io)(port) ))
+#define OUT_PORT_BYTE(port, value)      	(outportb( (hcf_io)(port), value ))
+#define OUT_PORT_WORD(port, value)      	(outport( (hcf_io)(port), value ))
+
+#define IN_PORT_STRING(port, addr, len) 	\
+	asm { push di; push es; mov cx,len; les di,addr; mov dx,port; rep insw; pop es; pop di }
+
+#define OUT_PORT_STRING(port, addr, len)	\
+	asm { push si; push ds; mov cx,len; lds si,addr; mov dx,port; rep outsw; pop ds; pop si }
+
+#endif /* WavePoint */
+
+/************************************************************************************************/
+/**************************  MPC860 - Diab or High C 29K   **************************************/
+/************************************************************************************************/
+
+#if defined(__ppc) || defined(_AM29K) //|| (CPU == PPC860)
+
+#define HCF_AP						//AccesPoint characteristics
+#define MSF_COMPONENT_VAR       0
+#define MSF_COMPONENT_ID        0
+#define MSF_COMPONENT_MAJOR_VER 1
+#define MSF_COMPONENT_MINOR_VER 0
+
+#define FAR			// flat 32-bits code
+#define BASED
+
+typedef unsigned char				hcf_8;
+typedef unsigned short				hcf_16;
+typedef unsigned long				hcf_32;
+
+#define SwapBytes(t)    /*lint -e572*/(((t) >> 8) + (((t) & 0xff) << 8))/*lint +e572*/
+
+#if defined(__ppc) || (CPU == PPC860)
+    #ifndef __GNUC__
+        #define __asm__     asm
+    #endif
+
+    #if !defined(_lint)
+        #define EIEIO()     __asm__(" eieio")
+    #else
+        #define EIEIO()
+    #endif
+
+    hcf_8 IN_PORT_BYTE(int port) {
+        hcf_8 value = *(volatile hcf_8 *)(port); EIEIO();
+        return value;
+    }
+
+    hcf_16 IN_PORT_WORD(int port) {
+        hcf_16 value = *(volatile hcf_16 *)(port); EIEIO();
+        value = SwapBytes(value);
+        return value;
+    }
+
+    #define OUT_PORT_BYTE(port, value) { *(volatile hcf_8 *)(port) = (value); EIEIO(); }
+    #define OUT_PORT_WORD(port, value)      \
+            { *(volatile hcf_16 *)(port) = SwapBytes(value); EIEIO(); }
+#else
+    #define IN_PORT_BYTE(port) (*(volatile hcf_8 *)(port))
+    #define IN_PORT_WORD(port) (*(volatile hcf_16 *)(port))
+    #define OUT_PORT_BYTE(port, value) (*(volatile hcf_8 *)(port) = (value))
+    #define OUT_PORT_WORD(port, value) (*(volatile hcf_16 *)(port) = (value))
+#endif
+
+/***************************************************************************/
+
+#define IN_PORT_STRING( port, dest, len)        {                       \
+                        unsigned l = (len);                             \
+                        hcf_16 t, *d = (volatile hcf_16 *)(dest);       \
+                        while (l--) {                                   \
+                            t = IN_PORT_WORD(port);                     \
+                            *d++ = SwapBytes(t);                        \
+                        }                                               \
+                                                }
+
+#define OUT_PORT_STRING( port, src, len)        {                       \
+                        unsigned l = (len);                             \
+                        hcf_16 t, *s = (volatile hcf_16 *)(src);        \
+                        while (l--) {                                   \
+                            t = *s++;                                   \
+                            OUT_PORT_WORD(port, SwapBytes(t));          \
+                        }                                               \
+                                                }
+
+#if PRODUCT == 9150
+    #define HCF_AP
+    #define HCF_ASSERT
+    #undef MSF_COMPONENT_ID
+#endif
+
+#endif	/* MPC860 - Diab or High C 29K */
+
+/************************************************************************************************/
+/***********************************  M A C  O S   **********************************************/
+/************************************************************************************************/
+
+        /**********/
+#if 0   /* MAC_OS */
+        /**********/
+
+#define HCF_STA                     //station characteristics
+#define MSF_COMPONENT_ID            COMP_ID_MAC_OS
+#define MSF_COMPONENT_VAR           0
+#define MSF_COMPONENT_MAJOR_VER     3
+#define MSF_COMPONENT_MINOR_VER     0
+
+#define MAC_OS                      1
+#define FAR                         // flat 32-bits code
+#define BASED
+
+#undef  HCF_LITTLE_ENDIAN           // selects Little Endian (a.k.a. Intel), least significant byte first
+#define HCF_BIG_ENDIAN              // selects Big Endian (a.k.a. Motorola), most significant byte first
+
+#if defined(DEBUG)
+#define HCF_ASSERT                  1
+#endif // DEBUG
+
+typedef unsigned char               hcf_8;
+typedef unsigned short              hcf_16;
+typedef unsigned long               hcf_32;
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+extern volatile unsigned char *MacIOaddr;
+extern hcf_8  IN_PORT_BYTE(hcf_16 port);
+extern void   OUT_PORT_BYTE(hcf_16 port, hcf_8 value);
+extern hcf_16 IN_PORT_WORD(hcf_16 port);
+extern void   OUT_PORT_WORD(hcf_16 port, hcf_16 value);
+extern void   IN_PORT_STRING(hcf_16 port, void *dest, hcf_16 len);
+extern void   OUT_PORT_STRING(hcf_16 port, void *src, hcf_16 len);
+
+#define SwapBytes(t)    (((t) >> 8) + (((t) & 0xff) << 8))
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* MAC_OS */
+
+/************************************************************************************************/
+/***********************************  W I N C E *************************************************/
+/************************************************************************************************/
+
+                  /*********/
+#ifdef _WIN32_WCE /* WINCE */
+                  /*********/
+
+#define	MSF_COMPONENT_ID			COMP_ID_WIN_CE
+#define HCF_STA						//station characteristics
+
+#include <ndis.h>
+#include <version.h>
+#include <ntcompat.h>
+
+#define	MSF_COMPONENT_VAR			1
+#define	MSF_COMPONENT_MAJOR_VER		TPI_MAJOR_VERSION
+#define	MSF_COMPONENT_MINOR_VER		TPI_MINOR_VERSION
+
+#define BASED 
+
+#undef  HCF_LITTLE_ENDIAN           // selects Little Endian (a.k.a. Intel), least significant byte first
+#undef  HCF_BIG_ENDIAN              // selects Big Endian (a.k.a. Motorola), most significant byte first
+
+#if defined(_SH3_) || defined (_SHx_) || defined(_MIPS_) || defined(_X86_)
+#define HCF_LITTLE_ENDIAN
+#endif
+
+#if defined(DEBUG) || defined(_WIN32_WCE_DEBUG)
+#define HCF_ASSERT                  1
+#endif // DEBUG
+
+typedef UCHAR   hcf_8;
+typedef USHORT  hcf_16;
+typedef ULONG   hcf_32;
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define WCE_IO_OFFSET   0x40
+extern ULONG  WceIoAddr;
+
+extern hcf_8  IN_PORT_BYTE(hcf_16 port);
+extern void   OUT_PORT_BYTE(hcf_16 port, hcf_8 value);
+extern hcf_16 IN_PORT_WORD(hcf_16 port);
+extern void   OUT_PORT_WORD(hcf_16 port, hcf_16 value);
+extern void   IN_PORT_STRING(hcf_16 port, void *dest, hcf_16 len);
+extern void   OUT_PORT_STRING(hcf_16 port, void *src, hcf_16 len);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif	/* _WIN32_WCE */
+
+
+/*  * * * * * * * * * * * * * * * * * * * * * *  IV  * * * * * * * * * * * * * * * * * * * * * * */
+
+/***************************************Compiler specific ****************************************/
+
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#else
+#define EXTERN_C
+#endif //__cplusplus
+                                                                                                            
+
+/************************************************************************************************/
+/********** M A C R O S derived of C O M P I L E R   S P E C I F I C   M A C R O S  *************/
+/************************************************************************************************/
+
+typedef hcf_8  FAR *wci_bufp;			 // segmented 16-bits or flat 32-bits pointer to 8 bits unit
+typedef hcf_16 FAR *wci_recordp;		 // segmented 16-bits or flat 32-bits pointer to 16 bits unit
+
+typedef hcf_8  FAR *hcf_8fp;			 // segmented 16-bits or flat 32-bits pointer to 8 bits unit
+typedef hcf_16 FAR *hcf_16fp;			 // segmented 16-bits or flat 32-bits pointer to 16 bits unit
+typedef hcf_32 FAR *hcf_32fp;			 // segmented 16-bits or flat 32-bits pointer to 8 bits unit
+
+
+#if defined HCF_STA && defined HCF_AP
+#if defined WCITST
+#pragma message( "you should also test both in isolation" )
+#else
+error; define exactly one of these terms;
+#endif
+#endif
+#if ! defined HCF_STA && ! defined HCF_AP
+error; define exactly one of these terms;
+#endif
+
+/*  * * * * * * * * * * * * * * * * * * * * * *  V  * * * * * * * * * * * * * * * * * * * * * * */
+
+#if defined HCF_PORT_IO
+#if defined HCF_MEM_IO
+error;
+#else
+typedef hcf_16 hcf_io;
+#endif //HCF_MEM_IO
+#endif //HCF_PORT_IO
+#if defined HCF_MEM_IO
+#if defined HCF_PORT_IO
+error;
+#else
+typedef hcf_32 hcf_io;
+#endif //HCF_PORT_IO
+#endif //HCF_MEM_IO
+
+
+
+/* MSF_COMPONENT_ID is used to define the CFG_IDENTITY_STRCT in HCF.C
+ * CFG_IDENTITY_STRCT is defined in HCF.C purely based on convenience arguments
+ * The HCF can not have the knowledge to determine the ComponentId field of the
+ * Identity record (aka as Version Record), therefore the MSF part of the Drivers
+ * must supply this value via the System Constant MSF_COMPONENT_ID
+ * There is a set of values predefined in MDD.H (format COMP_ID_.....)
+ */
+
+#if defined	MSF_COMPONENT_ID
+#define	DUI_COMPAT_VAR				MSF_COMPONENT_ID
+#define	DUI_COMPAT_BOT              4
+#define	DUI_COMPAT_TOP              4
+#endif // MSF_COMPONENT_ID
+
+/************************************************************************************************/
+/***************  E N V I R O N M E N T   S P E C I F I C   M A C R O S  ************************/
+/************************************************************************************************/
+
+
+#if defined HCF_ASSERT	//the next line may need modification for a specific environment
+extern int	BASED HCF_VAR_0; //Revision 2.0 gives an explanation of the need for HCF_VAR_0
+#endif
+
+#if defined HCF_PROFILING
+#endif
+
+/************************************************************************************************/
+/******  M S F    S U P P O R T    F U N C T I O N S    P R O T O T Y P E S   *******************/
+/************************************************************************************************/
+
+EXTERN_C void msf_assert ( wci_bufp file_namep, unsigned int line_number, hcf_16 trace, int qual );
+
+/* To increase portability, use unsigned char and unsigned char * when accessing parts of larger
+ * types to convert their Endianess
+ */
+
+#if defined HCF_BIG_ENDIAN
+#if defined HCF_LITTLE_ENDIAN
+	error
+#else	//************************************* B I G   E N D I A N *******************************************
+#define CNV_LITTLE_TO_INT(w)    ( ((hcf_16)(w) & 0x00ff) << 8 | ((hcf_16)(w) & 0xff00) >> 8 )
+#define CNV_BIG_TO_INT(w)		(w)		// No endianess conversion needed
+
+#define CNV_INT_TO_BIG_NP(addr)
+#define CNV_LITTLE_TO_INT_NP(addr) {							\
+	hcf_8 temp;													\
+	temp = ((hcf_8 FAR *)(addr))[0];							\
+	((hcf_8 FAR *)(addr))[0] = ((hcf_8 FAR *)(addr))[1];		\
+	((hcf_8 FAR *)(addr))[1] = temp;							\
+}
+
+#endif // HCF_LITTLE_ENDIAN
+#endif // HCF_BIG_ENDIAN
+
+#if defined HCF_LITTLE_ENDIAN
+#if defined HCF_BIG_ENDIAN
+	error; 
+#else	//************************************* L I T T L E   E N D I A N *************************************
+
+#define CNV_LITTLE_TO_INT(w) 	(w)		// No endianess conversion needed
+#define CNV_BIG_TO_INT(w)       ( ((hcf_16)(w) & 0x00ff) << 8 | ((hcf_16)(w) & 0xff00) >> 8 )
+
+#define CNV_INT_TO_BIG_NP(addr) {								\
+	hcf_8 temp;													\
+	temp = ((hcf_8 FAR *)(addr))[0];							\
+	((hcf_8 FAR *)(addr))[0] = ((hcf_8 FAR *)(addr))[1];		\
+	((hcf_8 FAR *)(addr))[1] = temp;							\
+}
+#define CNV_LITTLE_TO_INT_NP(addr)
+
+#endif // HCF_BIG_ENDIAN
+#endif // HCF_LITTLE_ENDIAN
+
+// conversion macros which can be expressed in other macros
+#define CNV_INT_TO_LITTLE(w)	CNV_LITTLE_TO_INT(w)
+#define CNV_INT_TO_BIG(w)		CNV_BIG_TO_INT(w)
+
+#endif //HCFCFG_H
+
+//******************************************* A L I G N M E N T  **********************************************
+#if defined HCF_ALIGN 
+#if HCF_ALIGN != 0 && HCF_ALIGN != 2
+	error;
+#endif // HCF_ALIGN != 0 && HCF_ALIGN != 2
+#else
+#define HCF_ALIGN 0			//default to no alignment
+#endif // HCF_ALIGN  
+
+
+
+
+/*  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *	
+ *	The routines ips and ops (short for InPutString and OutPutString) are created to use the 
+ *	compiler to do the type checking. It turned out that it is too easy to accidentally pass
+ *	a word pointer to the the macros IN_PORT_STRING and OUT_PORT_STRING rather than a byte pointer.
+ *	The "+2" as some macro implementations use, does not have the intended effect in those cases.
+ *	The HCF_STRICT business can be ignored by MSF programmers.
+ *	
+ *  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+#if defined HCF_STRICT
+void ips( hcf_io prt, wci_bufp dst, int n);
+void ops( hcf_io prt, wci_bufp src, int n);
+#endif //HCF_STRICT
+
+
+
+
+
+
+
+#if !defined HCF_MAX_CONFIG
+#define HCF_MAX_CONFIG		256		// maximum accumulated size in hcf_16 of LTV records used in hcf_put_config
+#endif
+
+#if !defined HCF_MAX_MSG
+#define HCF_MAX_MSG			2304	/* WaveLAN Pakket Size										*/
+#endif
+
+#if !defined HCF_MAX_NOTIFY		
+#define HCF_MAX_NOTIFY		6		// maximum size in bytes of "real" data in Notify command
+#endif
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_hcfdef.h linux.wavelan/drivers/net/pcmcia/wvlan_hcfdef.h
--- linux/drivers/net/pcmcia/wvlan_hcfdef.h	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_hcfdef.h	Sat Jan 27 23:42:42 2001
@@ -0,0 +1,375 @@
+/* This file is part of the Hardware Control Functions Light (HCF-light) library
+   to control the Lucent Technologies WaveLAN/IEEE Network I/F Card.
+   The HCF is the implementation of the Wireless Connection I/F (WCI).
+   
+   The HCF-light files are a subset of the HCF files. The complete set offers a
+   number of additional facilities, e.g. firmware download, Etherner-II encapsulation,
+   additional diagnostic facilities, ASSERT logic to support debugging, 802.11 support,
+   Configuration Management.
+   This complete set is explicitely not in the Public Domain but can be made 
+   available under certain restriction. (see the pointer below for support)
+   
+   The HCF-light files are free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   
+   At the time of this writing, you can request for support at:
+   betasupport@wavelan.com
+   
+   Documentation is expected to be available in the week of 8 Februari 1999
+
+*/
+
+
+#ifndef HCFDEFC_H
+#define HCFDEFC_H 1
+
+
+/*************************************************************************************************
+*
+* FILE	 : HCFDEFC.H *************** 2.0 *********************
+*
+* DATE   : 2000/01/06 23:30:53   1.2
+*
+* AUTHOR : Nico Valster
+*
+* DESC   : Definitions and Prototypes for HCF only
+*
+**************************************************************************************************
+* COPYRIGHT (c) 1996, 1997, 1998 by Lucent Technologies.	 All Rights Reserved.
+*************************************************************************************************/
+
+
+/****************************************************************************
+wvlan_hcfdef.h,v
+Revision 1.2  2000/01/06 23:30:53  root
+*** empty log message ***
+
+ * 
+ *    Rev 1.0   02 Feb 1999 14:32:34   NVALST
+ * Initial revision.
+Revision 1.1  1999/01/30 19:24:39  nico
+Initial revision
+
+Revision 1.1  1999/01/30 19:07:57  nico
+Initial revision
+
+ * 
+ *    Rev 1.110   29 Jan 1999 15:52:44   NVALST
+ * intermediate, maybe working but seems to need two times to load in 
+ * light-version
+ * 
+ *    Rev 2.12   29 Jan 1999 10:48:44   NVALST
+ * 
+ *    Rev 1.108   28 Jan 1999 14:43:24   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic + download
+ * passed to Marc
+ * 
+ *    Rev 2.11   27 Jan 1999 16:57:42   NVALST
+ * 
+ *    Rev 1.107   27 Jan 1999 13:53:24   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic
+ * 
+ *    Rev 1.106   26 Jan 1999 16:42:46   NVALST
+ * intermediate, corrected loop in hcf_service_nic (which was as result of a 
+ * walkthrough, changed from a bug without consequences into one with consequences
+ * 
+ *    Rev 1.105   25 Jan 1999 14:24:46   NVALST
+ * intermediate, hopefully suitable for release
+ * 
+ *    Rev 1.104   22 Jan 1999 16:59:34   NVALST
+ * intermediate, minor corrections + some HCF-L stuff
+ * 
+ *    Rev 1.103   15 Jan 1999 15:14:46   NVALST
+ * intermediate, deposited as HCF2.10
+ * 
+ *    Rev 2.10   15 Jan 1999 14:54:34   NVALST
+ * 
+****************************************************************************/
+
+
+/****************************************************************************
+*
+* CHANGE HISTORY
+*
+  961018 - NV
+	Original Entry
+
+**************************************************************************************************/
+
+/************************************************************************************************/
+/*********************************  P R E F I X E S  ********************************************/
+/************************************************************************************************/
+//IFB_		Interface Block
+//HCMD_		Hermes Command
+//HFS_		Hermes (Transmit/Receive) Frame Structure
+//HREG_		Hermes Register
+
+/*************************************************************************************************/
+
+
+/************************************************************************************************/
+/********************************* GENERAL EQUATES **********************************************/
+/************************************************************************************************/
+//#define STATIC			//;?cheap way out to get things compiled while intransition for ObjectOutline
+//#if ! defined STATIC	//;? change to HCF_STATIC some day
+//#if defined _DEBUG || defined OOL
+#define STATIC		EXTERN_C
+//#else
+//#define STATIC		static
+//#endif //_DEBUG
+//#endif // STATIC
+
+
+#define AUX_MAGIC_0				0xFE01
+#define AUX_MAGIC_1				0xDC23
+#define AUX_MAGIC_2				0xBA45
+#define HCF_MAGIC				0x7D37	// "}7" Handle validation
+#define DIAG_MAGIC				0x5A5A
+
+#define	PLUG_DATA_OFFSET        0x3F0000L
+
+
+#define ONE_SECOND				977		// 977 times a Hermes Timer Tick of 1K microseconds ~ 1 second
+#define INI_TICK_INI			0x20000L
+
+#define IO_IN					0		//hcfio_in_string
+#define IO_OUT					1		//hcfio_out_string
+#define IO_OUT_CHECK			2		//enable Data Corruption Detect on hcfio_out_string
+
+#define CARD_STAT_ENA_PRES		(CARD_STAT_ENABLED|CARD_STAT_PRESENT)
+#define CARD_STAT_PRI_PRES		(CARD_STAT_PRESENT|CARD_STAT_INCOMP_PRI)
+#define CARD_STAT_PRI_STA_PRES	(CARD_STAT_PRI_PRES|CARD_STAT_INCOMP_STA)
+
+#define DO_ASSERT				( ifbp->IFB_Magic != HCF_MAGIC && ifbp->IFB_Magic == HCF_MAGIC )	//FALSE without the nasty compiler warning
+
+#define HCF_ASSERT_ACTION			0x0001
+//#define HCF_ASSERT_CONNECT		no use to trace this
+#define HCF_ASSERT_DISABLE			0x0002
+#define HCF_ASSERT_DISCONNECT		0x0004
+#define HCF_ASSERT_ENABLE			0x0008
+#define HCF_ASSERT_GET_DATA			0x0010
+#define HCF_ASSERT_GET_INFO			0x0020
+#define HCF_ASSERT_INITIALIZE		0x0040
+#define HCF_ASSERT_RESEND			0x0080
+#define HCF_ASSERT_SERVICE_NIC		0x0100
+#define HCF_ASSERT_PUT_DATA			0x0200
+#define HCF_ASSERT_PUT_INFO			0x0400
+#define HCF_ASSERT_PUT_HDR			0x0800
+#define HCF_ASSERT_SEND				0x1000
+#define HCF_ASSERT_SEND_DIAG_MSG	0x2000
+#define HCF_ASSERT_INT_OFF			0x4000
+#define HCF_ASSERT_MISC				0x8000	
+
+
+#define	CFG_CONFIG_RID_MASK			0xFC00		//CONFIGURATION RECORDS
+
+#define BAP_0					HREG_DATA_0		//Tx-related register set for WMAC buffer access
+#define BAP_1					HREG_DATA_1		//non Tx-related register set for WMAC buffer access
+/************************************************************************************************/
+/***************************** STRUCTURES *******************************************************/
+/************************************************************************************************/
+                            
+                            
+//************************* Hermes Receive/Transmit Frame Structures
+//HFS_STAT
+//see MMD.H for HFS_STAT_ERR
+#define 	HFS_STAT_MSG_TYPE	0xE000	//Hermes reported Message Type
+#define 	HFS_STAT_1042		0x2000	//RFC1042 Encoded
+#define 	HFS_STAT_TUNNEL		0x4000	//Bridge-Tunnel Encoded
+#define 	HFS_STAT_WMP_MSG	0x6000	//WaveLAN-II Management Protocol Frame
+
+//HFS_TX_CNTL
+//see ENC_802_3/ENC_802_11 definition
+                            
+                            
+//************************* Hermes Register Offsets and Command bits
+#define HREG_IO_RANGE			0x40		//I/O Range used by Hermes
+
+
+//************************* Command/Status
+#define HREG_CMD				0x00		//
+#define 	HCMD_CMD_CODE			0x3F
+#define HREG_PARAM_0			0x02		//
+#define HREG_PARAM_1			0x04		//
+#define HREG_PARAM_2			0x06		//
+#define HREG_STAT				0x08		//
+#define 	HREG_STAT_CMD_CODE		0x003F	//
+#define		HREG_STAT_DIAG_ERR		0x0100
+#define		HREG_STAT_INQUIRE_ERR	0x0500
+#define 	HREG_STAT_CMD_RESULT	0x7F00	//
+#define HREG_RESP_0				0x0A		//
+#define HREG_RESP_1				0x0C		//
+#define HREG_RESP_2				0x0E		//
+
+
+//************************* FID Management
+#define HREG_INFO_FID			0x10		//
+#define HREG_RX_FID				0x20		//
+#define HREG_ALLOC_FID  		0x22		//
+//rsrvd #define HREG_TX_COMPL_FID  	0x24		//
+
+
+//************************* BAP
+#define HREG_SELECT_0			0x18		//
+#define HREG_OFFSET_0			0x1C		//
+//#define 	HREG_OFFSET_BUSY		0x8000	// use HCMD_BUSY
+#define 	HREG_OFFSET_ERR			0x4000	//
+//rsrvd #define 	HREG_OFFSET_DATA_OFFSET	0x0FFF	//
+
+#define HREG_DATA_0				0x36		//
+//rsrvd #define HREG_SELECT_1	0x1A		//
+//rsrvd #define HREG_OFFSET_1	0x1E		//
+
+#define HREG_DATA_1				0x38		//
+
+
+//************************* Event
+#define HREG_EV_STAT			0x30		//
+#define HREG_INT_EN				0x32		//
+#define HREG_EV_ACK				0x34		//
+
+
+//************************* Host Software
+#define HREG_SW_0				0x28		//
+#define HREG_SW_1				0x2A		//
+#define HREG_SW_2				0x2C		//
+//rsrvd #define HREG_SW_3		0x2E		//
+//************************* Control and Auxiliary Port
+
+#define HREG_CNTL				0x14		//
+#define		HREG_CNTL_AUX_ENA		0xC000
+#define		HREG_CNTL_AUX_ENA_STAT	0xC000
+#define		HREG_CNTL_AUX_DIS_STAT	0x0000
+#define		HREG_CNTL_AUX_ENA_CNTL	0x8000
+#define		HREG_CNTL_AUX_DIS_CNTL	0x4000
+#define HREG_AUX_PAGE			0x3A		//
+#define HREG_AUX_OFFSET			0x3C		//
+#define HREG_AUX_DATA			0x3E		//
+
+
+/************************************************************************************************/
+/***************************** END OF STRUCTURES ***********************************************/
+/************************************************************************************************/
+
+
+/************************************************************************************************/
+/**********************************  EQUATES  ***************************************************/
+/************************************************************************************************/
+
+// Tx/Rx frame Structure
+//
+#define HFS_STAT_ABS		(0x2E + HFS_STAT)    		//0x0000
+#define HFS_Q_INFO_ABS		(0x2E + HFS_Q_INFO)			//0x0006
+#define HFS_TX_CNTL_ABS		(0x2E + HFS_TX_CNTL)		//0x000C
+#define HFS_FRAME_CNTL_ABS	(0x2E + HFS_FRAME_CNTL)		//0X000E
+#define HFS_ID_ABS			(0x2E + HFS_ID)				//0X0010
+
+#define HFS_ADDR_1_ABS		(0x12 + HFS_ADDR_1)  		//0x0012
+#define HFS_ADDR_2_ABS		(0x12 + HFS_ADDR_2)  		//0x0018
+#define HFS_ADDR_3_ABS		(0x12 + HFS_ADDR_3)  		//0x001E
+#define HFS_SEQ_CNTL_ABS	(0x12 + HFS_SEQ_CNTL)		//0x0024
+#define HFS_ADDR_4_ABS		(0x12 + HFS_ADDR_4) 		//0x0026
+#define HFS_DAT_LEN_ABS		(0x12 + HFS_DAT_LEN)		//0x002C
+
+#define HFS_ADDR_DEST_ABS   (0x2E + HFS_ADDR_DEST)		//0x002E
+#define HFS_ADDR_SRC_ABS    (0x2E + HFS_ADDR_SRC)		//0x0034
+#define HFS_LEN_ABS	       	(0x2E + HFS_LEN)			//0x003A
+#define HFS_DAT_ABS	       	(0x2E + HFS_DAT)			//0x003C
+#define HFS_TYPE_ABS	    (0x2E + HFS_TYPE)			//0x0042	Eternet-II type in 1042/Bridge-Tunnel encapsulated frame
+
+#define HFS_802_11_GAP		(HFS_DAT_ABS  - HFS_ADDR_DEST_ABS)
+#define HFS_E_II_GAP       	(HFS_TYPE_ABS - HFS_LEN_ABS)
+
+#define KLUDGE_MARGIN		8							//safety margin for Tx Data Corruption workaround
+
+#define HFS_TX_ALLOC_SIZE	HCF_MAX_MSG + HFS_DAT_ABS + KLUDGE_MARGIN
+
+// IFB field related
+//		IFB_TxFrameType
+//#define ENC_TX_802_3           	0x00
+//#define ENC_TX_802_11         	0x11
+#define ENC_TX_E_II				0x0E	//encapsulation flag
+
+// SNAP header for E-II Encapsulation
+#define ENC_TX_1042             0x00
+#define ENC_TX_TUNNEL           0xF8
+
+// Hermes Command Codes and Qualifier bits
+#define 	HCMD_BUSY			0x8000	// Busy bit, applicable for all commands
+#define 	HCMD_RECL			0x0100	// Reclaim bit, applicable for Tx and Inquire
+
+#define HCMD_INI				0x0000	//
+#define HCMD_ENABLE				0x0001	//
+#define HCMD_DISABLE			0x0002	//
+#define HCMD_DIAG				0x0003	//
+#define HCMD_ALLOC				0x000A	//
+#define HCMD_TX					0x000B	//
+#define HCMD_NOTIFY				0x0010	//
+#define HCMD_INQUIRE			0x0011	//
+#define HCMD_ACCESS				0x0021	//
+#define 	HCMD_ACCESS_WRITE		0x0100	//
+#define HCMD_PROGRAM			0x0022	//
+#define 	HCMD_PROGRAM_DISABLE				0x0000	//
+#define 	HCMD_PROGRAM_ENABLE_VOLATILE	 	0x0100	//
+#define 	HCMD_PROGRAM_ENABLE_NON_VOLATILE	0x0200	//
+#define 	HCMD_PROGRAM_NON_VOLATILE			0x0300	//
+
+// Miscellanuos 
+//
+#define REV_OFFSET 16					// offset of Major version within the PVCS generated Version String
+
+
+/************************************************************************************************/
+/**********************************  END OF EQUATES  ********************************************/
+/************************************************************************************************/
+
+
+/************************************************************************************************/
+/**************************************  MACROS  ************************************************/
+/************************************************************************************************/
+
+/************************************************************************************************
+	DEBUG_INT is an undocumented feature to assist the HCF debugger
+	By expanding INT_3 to either an "int 3" or a NOP, it is very easy to check
+	by means of a binary file compare whether a "debug" version really corresponds
+	with a "non-debug" version.
+	;? is is currently unknown whether there is a real reason to restrict this
+	implemenation to the MSVC environment
+*/
+#if defined (_MSC_VER)
+#ifdef DEBUG_INT
+//#pragma message( Reminder "int 3, should be removed before releasing" )
+#define INT_3 __asm int 3
+#else
+#define INT_3 __asm nop
+#endif /*DEBUG_INT*/
+#else
+#define INT_3
+#endif /*_MSC_VER*/
+
+#define MUL_BY_2( x )	( (x) << 1 )	//used to multiply by 2
+#define DIV_BY_2( x )	( (x) >> 1 )	//used to divide by 2
+
+/************************************************************************************************/
+/**************************************  END OF MACROS  *****************************************/
+/************************************************************************************************/
+
+/************************************************************************************************/
+/***************************************  PROTOTYPES  *******************************************/
+/************************************************************************************************/
+
+int 	hcfio_string( IFBP ifbp, int bap, int fid, int offset, wci_bufp pc_addr, int wlen, int blen, int type );
+
+
+#endif	//HCFDEFC_H
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_hcfio.c linux.wavelan/drivers/net/pcmcia/wvlan_hcfio.c
--- linux/drivers/net/pcmcia/wvlan_hcfio.c	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_hcfio.c	Sat Jan 27 23:42:42 2001
@@ -0,0 +1,432 @@
+/* This file is part of the Hardware Control Functions Light (HCF-light) library
+   to control the Lucent Technologies WaveLAN/IEEE Network I/F Card.
+   The HCF is the implementation of the Wireless Connection I/F (WCI).
+   
+   The HCF-light files are a subset of the HCF files. The complete set offers a
+   number of additional facilities, e.g. firmware download, Etherner-II encapsulation,
+   additional diagnostic facilities, ASSERT logic to support debugging, 802.11 support,
+   Configuration Management.
+   This complete set is explicitely not in the Public Domain but can be made 
+   available under certain restriction. (see the pointer below for support)
+   
+   The HCF-light files are free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   
+   At the time of this writing, you can request for support at:
+   betasupport@wavelan.com
+   
+   Documentation is expected to be available in the week of 8 Februari 1999
+
+*/
+
+
+
+/**************************************************************************************************************
+*
+* FILE	  : hcfio.cpp
+*
+* DATE    : 2000/01/06 23:30:53   1.2
+*
+* AUTHOR  : Nico Valster
+*
+* DESC    : WCI-II HCF I/O Support Routines
+*           These routines are isolated in their own *.CPP file to facilitate porting
+*
+*           Customizable via HCFCFG.H which is included by HCF.H
+*
+***************************************************************************************************************
+* COPYRIGHT (c) 1994, 1995 by AT&T. 	   						All Rights Reserved.
+* COPYRIGHT (c) 1996, 1997, 1998 by Lucent Technologies.     	All Rights Reserved.
+**************************************************************************************************************/
+
+/****************************************************************************
+wvlan_hcfio.c,v
+Revision 1.2  2000/01/06 23:30:53  root
+*** empty log message ***
+
+ * 
+ *    Rev 1.0   02 Feb 1999 14:32:30   NVALST
+ * Initial revision.
+Revision 1.1  1999/01/30 19:34:40  nico
+Initial revision
+
+Revision 1.1  1999/01/30 19:24:39  nico
+Initial revision
+
+Revision 1.1  1999/01/30 19:07:33  nico
+Initial revision
+
+ * 
+ *    Rev 1.110   29 Jan 1999 15:52:40   NVALST
+ * intermediate, maybe working but seems to need two times to load in 
+ * light-version
+ * 
+ *    Rev 2.12   29 Jan 1999 10:48:46   NVALST
+ * 
+ *    Rev 1.108   28 Jan 1999 14:43:18   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic + download
+ * passed to Marc
+ * 
+ *    Rev 2.11   27 Jan 1999 16:57:42   NVALST
+ * 
+ *    Rev 1.107   27 Jan 1999 13:53:22   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic
+ * 
+ *    Rev 1.106   26 Jan 1999 16:42:44   NVALST
+ * intermediate, corrected loop in hcf_service_nic (which was as result of a 
+ * walkthrough, changed from a bug without consequences into one with consequences
+ * 
+ *    Rev 1.105   25 Jan 1999 14:24:46   NVALST
+ * intermediate, hopefully suitable for release
+ * 
+ *    Rev 1.104   22 Jan 1999 16:59:30   NVALST
+ * intermediate, minor corrections + some HCF-L stuff
+ * 
+ *    Rev 1.103   15 Jan 1999 15:14:40   NVALST
+ * intermediate, deposited as HCF2.10
+ * 
+****************************************************************************/
+
+
+/****************************************************************************
+*
+* CHANGE HISTORY
+*
+  961121 - NV
+    Original Entry
+
+**************************************************************************************************************/
+
+/* ToDo
+ * the CNV_LITTLE_TO_INT does have the desired effect on all platforms, but it's naming is
+ * misleading, so revisit all these CNV macros to assure the right name is used at the right
+ * place. Hint: introduce CNV_HOST_TO_NETWORK names if appropriate
+ */
+
+
+#include "wvlan_hcf.h"
+#include "wvlan_hcfdef.h"
+
+#ifdef HCF_ASSERT
+static char BASED HCF__FILE__[] = { "  " __FILE__};	/* 6 spaces to supply room to build an LTV record for 
+													 * runtime HCF_ASSERTs.  This record is constructed as:
+													 * - L:		 self explanatory
+													 * - T:		 CFG_MB_ASSERT
+													 * - V[0]:	 line_number
+													 * - V[1..]: (unchanged) file name						*/
+#endif
+
+/*  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *	
+ *	Refer to HCFCFG.H for more information on the routines ips and ops (short for InPutString 
+ *	and OutPutString)
+ *	
+ *  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ 
+#if defined HCF_STRICT
+void ips( hcf_io prt, wci_bufp dst, int n) {
+
+	while ( n-- ) { 
+		*(hcf_16 FAR*)dst = IN_PORT_WORD( prt );
+		dst += 2;
+	}
+} // ips
+
+void ops( hcf_io prt, wci_bufp src, int n) {
+
+	while ( n-- ) {
+		OUT_PORT_WORD( prt, *(hcf_16 FAR*)src );
+		src  += 2;
+	}
+} // ops
+#endif // HCF_STRICT
+
+/***************************************** DOCZ Header ********************************************************
+
+
+.MODULE         hcfio_string
+.LIBRARY        HCF_SUP
+.TYPE           function
+.SYSTEM         msdos
+.SYSTEM         unix
+.SYSTEM         NW4
+.APPLICATION    I/O Support for HCF routines
+.DESCRIPTION    read/write string with specified length from/to WaveLAN NIC RAM to/from PC RAM
+
+
+int hcfio_string( IFBP ifbp, int bap, int fid, 
+				  int offset, wci_bufp pc_addr, int word_len, int tot_len, int type ) {
+.ARGUMENTS
+  IFBP			ifbp			I/F Block
+  int			bap				BAP0/1
+  int			fid				FID/RID
+  int			offset			offset in FID/RID
+  wci_bufp		pc_addr			begin address in PC RAM to write to or read from
+  int			word_len		number of leading words of which the Endianess must be converted
+  int			tot_len			number of bytes to write or read
+  int			type            action code
+								  -	IO_IN			read from NIC RAM
+								  -	IO_OUT			write to NIC RAM
+								  -	IO_OUT_CHECK	Data Corruption Detect
+
+.RETURNS
+  int
+	HCF_SUCCESS     	O.K
+	HCF_ERR_TIME_OUT    BAP can not be initialized
+	HCF_ERR_NO_NIC		card is removed
+	HCF_FAILURE			Data Corruption Detection catched
+
+.NARRATIVE
+
+  hcfio_string has the following tasks:
+  -	copy data from NIC RAM to Host RAM or vice versa
+  - optionally convert the data or part of the data from/to Little Endian format (as used by the NIC) 
+  	to/from the Native Endian format (as used by the Host)
+  -	check for Data Corruption in the data written to the NIC
+	
+  Data is a string with specified length copied from/to a specified offset in a specified Receive Frame 
+  Structure (FID), Transmit Frame Structure (FID) or Record (RID) to/from a Host RAM buffer with a specified
+  begin address.
+  A length of 0 can be specified, resulting in no data transfer. This feature accomodates MSFs in certain
+  Host environments (i.e. ODI) and it is used in the Data Corruption detection.
+  Which Buffer Acces Path (BAP0 or BAP1) is used, is defined by a parameter.  
+  A non-zero return status indicates:
+  -	the selected BAP could not properly be initialized
+  -	the card is removed before completion of the data transfer
+  - the Data Corruption Detection triggered
+  - the NIC is considered inoperational due to a time-out of some Hermes activity in the past
+  In all other cases, a zero is returned.
+  If a card removal is returned, the MSF has the option to drop the message or recover in any other way it 
+  sees fit.
+  BAP Initialization failure indicates an H/W error which is very likely to signal complete H/W failure. Once
+  a BAP Initialization failure has occured all subsequent interactions with the Hermes will return a time out
+  status till the Hermes is re-initialized by means of an hcf_disable (at all ports in case of a multi-port
+  environment)
+
+.DIAGRAM
+
+ 1:	the test on rc checks whether a BAP initialization or a call to cmd_wait did ever fail. If so, the Hermes 
+	is assumed inoperable/defect, and all subsequent bap_ini/cmd_wait calls are nullified till hcf_disable 
+	clears the IFB_TimStat field.
+ 2:	The PCMCIA card can be removed in the middle of the transfer. By depositing a "magic number" in the 
+	HREG_SW_0 register of the Hermes at initialization time and by verifying this location after 
+    reading the string, it can be determined whether the card is still present and the return status is 
+    set accordingly.
+ 3:	The test on offset and fid in the IFB_BAP_<n> structure corresponding with the BAP entry parameter, 
+	assures that the BAP is only initialized if the current set of parameters specifies a location wich is 
+	not consecutive with the last read/write access. If initialization is needed, then:
+	  -	the select register is set
+	  -	the offset register is set
+	  -	the IFB_BAP_<n> structure is initialized
+	  - the offset register is monitored till a successful condition (no busy bit and no error bit) is 
+	  	detected or till the protection counter (calibrated at approx 1 second) expires
+	If the counter expires, this is reflected in IFB_TimStat, so all subsequent calls to hcfio_string
+	fail immediately ( see step 1)
+ 4:	the offset register in the IFB_BAP_<n> structure is updated to be used as described in item 3 above 
+ 	on the next call
+10:	The NIC I/F is optimized for word transfer but it can only handle word transfer at a word boundary. 
+	Therefore an additional test must be done to handle the read preparation in case the begin address in 
+	NIC RAM is odd.
+    This situation is handled by first reading a single byte and secondly reading a string of WORDS with a
+    BYTE length of the requested length minus 1.
+	NOTE: MACRO IN_PORT_STRING possibly modifies p (depending on how the MSF-programmer chooses to construct
+	this macro, so pc_addr can not be used as parameter
+11:	At completion of the word based transfer, a test is made to determine whether 1 additional byte must be 
+	read (odd length starting at even address or even length starting at odd boundary)
+12: finally the optionally conversion of the first words from Little Endian to Native Endian format is done.
+20: first the optionally conversion of the first words from Native Endian to Little Endian format is done.
+	This implies that Endian conversion can ONLY take place at word boundaries.
+	Note that the difference with the IO_IN part of the logic is based on optimization considerations (both
+	speed and size) and the boundary condition to return the output buffer unchanged to the caller
+	Note also that the check on zero-length for output can not be the simple "skip all" as used for input, 
+	because the Data Corruption Detection needs some of the side effects of this code, specifically the 
+	BAP initialization
+21: As for the IO_IN part, the logic must first cope with odd begin addresses in NIC RAM and the bulk of the
+	transfer is done via OUT_PORT_STRING. Due to a flaw in the Hermes, writing the high byte corrupts the 
+	low byte. As a work around, the HCF reads the low byte deposited in NIC RAM by the previous 
+	hcfio_string, merges that byte with the first byte of the current Host RAM buffer into a word and
+	writes that word to NIC RAM via OUT_PORT_WORD. Since OUT_PORT_WORD converts from Native Endian to
+	Little Endian, while at this point of the procedure the Host buffer must have the correct Endianess,
+	the macro CNV_LITTLE_TO_INT counteracts this unwanted adjustment of OUT_PORT_WORD.
+22: At completion of the word based transfer, a test is made to determine whether 1 additional byte must be 
+	written
+30: The case of Data Corruption Detection:
+	First the NIC RAM pointer is aligned on a word boundary to cope with the problem of an odd number of
+	bytes written before. This is done by skipping one additional byte before the Data Corruption 
+	Detection Pattern is appended to the data already written to the NIC RAM.
+	Then 8 bytes fixed pattern is written. The justification of this is given in the NOTICE section below
+31: In order to read the pattern back, the BAP must be initialized to address the begin of the pattern.
+	The select register does not change, so only the offset register needs to be written, followed by
+	a wait for successful completion.
+40: To recognize the case that the NIC is removed during execution of hcfio_string, the same check as in
+	step 2 is done again.
+99:	In the past, one of the asserts in bap_ini (which no longer exists now it is assimilated in hcfio_string) 
+	catched if "offset" was invalid. By calling bap_ini with the original (offset + length), bap_ini would 
+	catch when the MSF passes the RID/FID boundary during the read process. It turned out that this feature 
+	did obscure the tracing during debugging so much that its total effect on the debugging process was 
+	considered detrimental, however re-institution can be considered depending on the bug you are chasing
+
+
+.NOTICE
+The problem is that without known cause, the Hermes internal NIC RAM pointer misses its auto-increment causing 
+two successive writes to NIC RAM to address the same location. As a consequence word <n> is overwritten and 
+a word <n+j> is written at position <n+j-1>. Since the Hermes is unaware of this, nothing in the system is 
+going to catch this, e.g. the frame is received on the other side with correct FCS. As a workaround, the HCF 
+keeps track of where the NIC RAM pointer SHOULD be. After all hcf_put_data calls are done, in other words, 
+when hcf_send is called, the HCF writes a number of words - the kludge pattern - after the MSF-data. Then it 
+sets the NIC RAM pointer by means of a re-initialization of the BAP to where this kludge pattern SHOULD be and 
+reads the first word. This first word must match the kludge pattern, otherwise, apparently, the auto-increment 
+failed. We need to write more than 1 word otherwise if the previous use of that piece of NIC RAM would have 
+left by chance the right "kludge" value just after the newly but incorrectly put data, the test would not 
+trigger. By overwriting the next 3 words as well, we assume the likelihood of this to be sufficiently small. 
+The frequency observed of this problem varies from 1 out of 1000 frames till to low to be noticeable. Just to 
+be on the safe side we assume that the chance of an error is 10E-3. By writing 4 words we reduce the 
+likelihood of an unnoticed problem to 10E-12, but of course this becomes tricky because we don't know whether 
+the chances are independent. Note that the HCF notion of the NIC RAM pointer is a "logical" view in the 
+RID/FID address space, while the Hermes has a completely different physical address value for this pointer, 
+however that difference does not influence above reasoning.
+
+.NOTE
+  Depending on the selected optimization options, using "register int reg" causes some obscure 
+  optimization with si. As a result the code is longer. Therefore, do not invest time to optimize this code 
+  that way during a "maintenance cycle".
+ 
+.NOTE
+  The IN_/OUT_PORT_WORD_/STRING macros are MSF-programmer defined and may or may not have side effects 
+  on their parameters, therefore they can not handle expressions like "len/2". As a solution all these macros
+  must be called via "simple" variables, with no side effects like ++ and their contents is unpredictable
+  at completion of the macro
+  
+.NOTE
+  The implementation is choosen to have input, output and BAP setup all rolled into one monolithic
+  function rather than a more ameniable hcfio_in_string, hcfio_out_string and bap_ini to minimize the 
+  stack usage during Interrupt Service (especially relevant for DOS drivers)
+
+.NOTE
+  The local variable reg corresponds with a register of the appropriate BAP. This is possible by the 
+  intentional choice of the addresses of the individual registers of the two BAPs and the macro used to 
+  specify whether BAP_0 or BAP_1 should be used. The value of reg is changed in the flow of hcfio_string
+  because, depending on the context, reg is most optimal addressing the offset register or the data register.
+
+	
+
+ .ENDOC                          END DOCUMENTATION
+
+-------------------------------------------------------------------------------------------------------------*/
+
+
+int hcfio_string( IFBP ifbp, int bap, int fid, 
+				  int offset, wci_bufp pc_addr, int word_len, int tot_len, int type ) {
+
+hcf_io		reg = ifbp->IFB_IOBase + bap - HREG_DATA_0 + HREG_OFFSET_0;				//reg = offset register
+hcf_32		prot_cnt = ifbp->IFB_TickIni;
+hcf_16  	*p1 = bap == BAP_0 ? ifbp->IFB_BAP_0 : ifbp->IFB_BAP_1;
+wci_bufp	cp;
+wci_recordp	wp = (wci_recordp)pc_addr;
+int			rc;
+int			tlen;
+
+#if HCF_ALIGN != 0
+#endif // HCF_ALIGN
+			/* assumption, writing words takes place only initial, never at odd NIC RAM addresses nor odd PC 
+			 * addresses	*/
+
+	if ( ( rc = ifbp->IFB_TimStat ) == HCF_SUCCESS ) {													/* 1 */
+	    if ( IN_PORT_WORD( ifbp->IFB_IOBase + HREG_SW_0 ) != HCF_MAGIC ) rc =  HCF_ERR_NO_NIC;			/* 2 */
+	}	
+	if ( rc == HCF_SUCCESS ) {
+	
+		/* make sure all preceeding BAP manipulation is settled */
+		while ( prot_cnt && IN_PORT_WORD( reg ) & (HCMD_BUSY|HREG_OFFSET_ERR) ) prot_cnt--;
+	
+		if ( offset != (int)*p1 || fid != (int)*(p1+1) ) {												/* 3 */
+			OUT_PORT_WORD( reg - HREG_OFFSET_0 + HREG_SELECT_0, fid );
+			OUT_PORT_WORD( reg, offset & 0xFFFE );
+			*p1 = (hcf_16)offset;
+			*(p1+1) = (hcf_16)fid;
+			/* use type == IO_IN and len == 0 as a way to set the BAP for the futute, e.g. at the end of hcf_send */
+//			while ( prot_cnt-- && IN_PORT_WORD( reg ) & (HCMD_BUSY|HREG_OFFSET_ERR) ) /*NOP*/;
+			while ( tot_len && prot_cnt && IN_PORT_WORD( reg ) & (HCMD_BUSY|HREG_OFFSET_ERR) ) prot_cnt--;
+			if ( prot_cnt == 0 ) {
+				/* ;? It could be discussed whether the HREG_OFFSET_ERR bit should result in blocking NIC access 
+				 *	till next initialize */
+				rc = ifbp->IFB_TimStat = HCF_ERR_TIME_OUT;
+			}
+		}
+		*p1 += (hcf_16)tot_len;																			/* 4 */
+	}
+	reg += HREG_DATA_0 - HREG_OFFSET_0;												     // reg = data register
+	if ( rc == HCF_SUCCESS && type == IO_IN ) { 														//input
+		if ( tot_len ) {
+			if ( offset & 0x01 ) { /*odd	*/															/* 10*/
+				*pc_addr++ = IN_PORT_BYTE( reg+1 );
+				tot_len--;
+			}
+			cp = pc_addr;
+			tlen = DIV_BY_2( tot_len );
+			IN_PORT_STRING( reg, cp, tlen );
+			if ( tot_len & 1 ) *(pc_addr + tot_len - 1) = IN_PORT_BYTE( reg );							/* 11*/
+			while ( word_len-- ) {
+				CNV_LITTLE_TO_INT_NP( wp );																/* 12*/
+				wp++;
+			}
+		}
+	}
+	if ( rc == HCF_SUCCESS && type != IO_IN ) {											  //output and/or check
+		tlen = word_len;                                                                                /* 20*/
+		while ( tlen-- ) {                                                                              /* 20*/
+			OUT_PORT_WORD( reg, *(wci_recordp)pc_addr );
+			pc_addr += 2;
+		}
+//		tlen = offset + tot_len;
+		if ( tot_len && offset & 0x01 ) {																/* 21*/
+			OUT_PORT_WORD( reg, CNV_LITTLE_TO_INT( (*pc_addr <<8) + IN_PORT_BYTE( reg ) ) );
+			pc_addr++;
+			tot_len--;
+		}
+		word_len = DIV_BY_2( tot_len ) - word_len;	  //misuse no longer needed parameter as temporary variable
+		cp = pc_addr;
+		OUT_PORT_STRING( reg, cp, word_len );
+		if ( tot_len & 1 ) OUT_PORT_BYTE( reg, *(pc_addr + tot_len - 1) );								/* 22*/
+
+
+		if ( type == IO_OUT_CHECK /*&& *p1 != ifbp->IFB_FSBase */) {	//;?<HCF _L> should BE HARD CODED	/* 30*/
+			if ( *p1 & 0X01 ) (void)IN_PORT_WORD( reg );	//align on word boundary
+			OUT_PORT_WORD( reg, 0xCAFE );
+			OUT_PORT_WORD( reg, 0xABBA );
+			OUT_PORT_WORD( reg, 0xDEAD );
+			OUT_PORT_WORD( reg, 0xD00F );
+//!!		OUT_PORT_WORD( bap - HREG_OFFSET_0 + HREG_SELECT_0, fid );									/* 31*/
+			OUT_PORT_WORD( reg - HREG_DATA_0 + HREG_OFFSET_0, (*p1 + 1)&0xFFFE );
+			prot_cnt = ifbp->IFB_TickIni;
+			while ( prot_cnt && IN_PORT_WORD(reg - HREG_DATA_0 + HREG_OFFSET_0) & (HCMD_BUSY|HREG_OFFSET_ERR) ) prot_cnt--;
+			if ( prot_cnt == 0 ) {
+				rc = ifbp->IFB_TimStat = HCF_ERR_TIME_OUT;
+			}
+			if ( IN_PORT_WORD( reg ) != 0xCAFE ) {
+	 			rc = HCF_FAILURE;
+				ifbp->IFB_PIFRscInd = 1;
+//!			} else {
+//!				rc = HCF_SUCCESS;
+			}
+		}
+	}
+	if ( rc == HCF_SUCCESS ) {																			/* 40*/
+	    if ( IN_PORT_WORD( ifbp->IFB_IOBase + HREG_SW_0 ) != HCF_MAGIC ) rc =  HCF_ERR_NO_NIC;
+	}	
+
+//!	ASSERT( bap_ini( ifbp, bap, fid, (offset + len) & 0xFFFE) == HCF_SUCCESS )							/*99 */
+    return rc;
+}/* hcfio_string */
+
diff -u --recursive --new-file linux/drivers/net/pcmcia/wvlan_mdd.h linux.wavelan/drivers/net/pcmcia/wvlan_mdd.h
--- linux/drivers/net/pcmcia/wvlan_mdd.h	Wed Dec 31 18:00:00 1969
+++ linux.wavelan/drivers/net/pcmcia/wvlan_mdd.h	Sat Jan 27 23:42:42 2001
@@ -0,0 +1,465 @@
+/* This file is part of the Hardware Control Functions Light (HCF-light) library
+   to control the Lucent Technologies WaveLAN/IEEE Network I/F Card.
+   The HCF is the implementation of the Wireless Connection I/F (WCI).
+   
+   The HCF-light files are a subset of the HCF files. The complete set offers a
+   number of additional facilities, e.g. firmware download, Etherner-II encapsulation,
+   additional diagnostic facilities, ASSERT logic to support debugging, 802.11 support,
+   Configuration Management.
+   This complete set is explicitely not in the Public Domain but can be made 
+   available under certain restriction. (see the pointer below for support)
+   
+   The HCF-light files are free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+   
+   At the time of this writing, you can request for support at:
+   betasupport@wavelan.com
+   
+   Documentation is expected to be available in the week of 8 Februari 1999
+
+*/
+
+
+#ifndef MDD_H
+#define MDD_H 1
+
+/*************************************************************************************************************
+*
+* FILE	 : mdd.h
+*
+* DATE   : 2000/01/06 23:30:53   1.2
+*
+* AUTHOR : Nico Valster
+*
+* DESC   : Definitions and Prototypes for HCF, MSF, UIL as well as USF sources
+*
+*
+*
+* Implementation Notes
+*
+ -	Typ rather than type is used as field names in structures like CFG_CIS_STRCT because type leads to
+ 	conflicts with MASM when the H-file is converted to an INC-file
+*
+**************************************************************************************************************
+Instructions to convert MDD.H to MDD.INC by means of H2INC
+
+Use a command line which defines the specific macros and command line options
+needed to build the C-part, e.g. for the DOS ODI driver
+		`h2inc /C /Ni /Zp /Zn mdd	 mdd.h`
+
+
+**************************************************************************************************************
+* COPYRIGHT (c) 1998 by Lucent Technologies.	 All Rights Reserved.
+*************************************************************************************************************/
+
+/****************************************************************************
+wvlan_mdd.h,v
+Revision 1.2  2000/01/06 23:30:53  root
+*** empty log message ***
+
+ * 
+ *    Rev 1.0   02 Feb 1999 14:32:36   NVALST
+ * Initial revision.
+Revision 1.3  1999/02/01 22:58:35  nico
+*** empty log message ***
+
+Revision 1.2  1999/02/01 21:01:41  nico
+*** empty log message ***
+
+Revision 1.1  1999/01/30 19:24:39  nico
+Initial revision
+
+Revision 1.1  1999/01/30 19:07:57  nico
+Initial revision
+
+ * 
+ *    Rev 1.110   29 Jan 1999 15:52:44   NVALST
+ * intermediate, maybe working but seems to need two times to load in 
+ * light-version
+ * 
+ *    Rev 2.12   29 Jan 1999 10:48:46   NVALST
+ * 
+ *    Rev 1.108   28 Jan 1999 14:43:24   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic + download
+ * passed to Marc
+ * 
+ *    Rev 2.11   27 Jan 1999 16:57:42   NVALST
+ * 
+ *    Rev 1.107   27 Jan 1999 13:53:24   NVALST
+ * intermediate, once more correction of loop in hcf_service_nic
+ * 
+ *    Rev 1.106   26 Jan 1999 16:42:46   NVALST
+ * intermediate, corrected loop in hcf_service_nic (which was as result of a 
+ * walkthrough, changed from a bug without consequences into one with consequences
+ * 
+ *    Rev 1.105   25 Jan 1999 14:24:48   NVALST
+ * intermediate, hopefully suitable for release
+ * 
+ *    Rev 1.104   22 Jan 1999 16:59:34   NVALST
+ * intermediate, minor corrections + some HCF-L stuff
+ * 
+ *    Rev 1.103   15 Jan 1999 15:14:46   NVALST
+ * intermediate, deposited as HCF2.10
+ * 
+ *    Rev 2.10   15 Jan 1999 14:54:36   NVALST
+ * 
+ *
+****************************************************************************/
+
+
+/****************************************************************************
+*
+* CHANGE HISTORY
+*
+  961018 - NV
+	Original Entry, split of from HCF.H
+
+*************************************************************************************************************/
+
+/******************************      M A C R O S     ********************************************************/
+
+/* min and max macros */
+#if !defined(max)
+#define max(a,b)  (((a) > (b)) ? (a) : (b))
+#endif
+#if !defined(min)
+#define min(a,b)  (((a) < (b)) ? (a) : (b))
+#endif
+
+
+/*************************************************************************************************************/
+
+/****************************** General define ***************************************************************/
+
+#define MAC_ADDR_SIZE			6
+#define GROUP_ADDR_SIZE			(32 * MAC_ADDR_SIZE)
+#define STAT_NAME_SIZE			32
+
+
+
+//IFB field related
+//		IFB_CardStat
+#define CARD_STAT_PRESENT				0x8000U	/* MSF defines card as being present
+												 * controls whether hcf-function is allowed to do I/O		*/
+#define CARD_STAT_ENABLED				0x4000U	// one or more MAC Ports enabled
+#define CARD_STAT_INI					0x0800U	// Hermes Initiliazed
+
+//		IFB_RxStat
+#define RX_STAT_ERR						0x0003U	//Error mask
+#define 	RX_STAT_UNDECR				0x0002U	//Non-decryptable encrypted message
+#define 	RX_STAT_FCS_ERR				0x0001U	//FCS error
+
+/****************************** Xxxxxxxx *********************************************************************/
+
+enum /*hcf_stat*/ {
+	HCF_FAILURE			= 0xFF,		/* An (unspecified) failure, 0xFF is choosen to have a non-ubiquitous value
+	                                 *	Note that HCF_xxxx errors which can end up in the CFG_DIAG LTV should
+	                                 *	never exceed 0xFF, because the high order byte of VAL[0] is reserved
+	                                 *	for Hermes errors
+	                                 */
+	HCF_SUCCESS			= 0x00,		// 0x00: OK
+	//gap for ODI related status
+	HCF_ERR_DIAG_0		= 0x02,		// 0x02: HCF noticed an error after hcf_disable, before diagnose command
+	HCF_ERR_DIAG_1,					// 0x03: HCF noticed an error after succesful diagnose command
+	HCF_ERR_TIME_OUT,               // 0x04: Expected Hermes event did not occure in expected time
+	HCF_ERR_NO_NIC,					// 0x05: card not found (usually yanked away during hcfio_in_string
+	HCF_ERR_BUSY,					// 0x06: ;?Inquire cmd while another Inquire in progress
+	HCF_ERR_SEQ_BUG,				// 0x07: other cmd than the expected completed, probably HCF-bug
+	HCF_ERR_LEN,					// 0x08: buffer size insufficient
+									//		  -	hcf_get_info buffer has a size of 0 or 1 or less than needed
+									//			to accomodate all data
+};
+
+#define	HCF_INT_PENDING			1	// (ODI initiated) return status of hcf_act( HCF_ACT_INT_OFF )
+
+
+
+/* hard coded values (e.g. for HCF_ACT_TALLIES and HCF_ACT_INT_OFF) are needed for HCFL							*/
+typedef enum  { /*hcf_action_cmd*/
+										/*	gap left over by swapping 3 frame mode action with 4 INT_OFF/_ON
+										 *	CARD_IN/_OUT. This was done to have HCFL default automagically
+										 *	to HCF_ACT_802_3_PURE
+										 *	This gap available for future features								*/
+	HCF_ACT_SPARE_03,					//03 gap available for future features
+										/* DUI code 0x04 -> DON'T EVER MOVE 									*/
+										/* DUI code 0x05 -> DON'T EVER MOVE 									*/
+	HCF_ACT_TALLIES = 0x05,				//05 Hermes Inquire Tallies (F100) command
+#if defined HCF_ASSERT
+	HCF_ACT_ASSERT_OFF,					//09 de-activate Assert reporting
+	HCF_ACT_ASSERT_ON,					//0A activate Assert reporting	
+#else	
+#endif // HCF_ASSERT
+										/* DUI code 0x0B -> DON'T EVER MOVE 									*/
+										/* DUI code 0x0C -> DON'T EVER MOVE 									*/
+	HCF_ACT_INT_OFF = 0x0D,				//0D Disable Interrupt generation
+	HCF_ACT_INT_ON,						//0E Enable Interrupt generation
+	HCF_ACT_CARD_IN,					//0F MSF reported Card insertion
+	HCF_ACT_CARD_OUT,  					//10 MSF reported Card removal
+/*	HCF_ACT_MAX							// xxxx: start value for UIL-range, NOT to be passed to HCF
+ *										Too bad, there was originally no spare room created to use
+ *										HCF_ACT_MAX as an equivalent of HCF_ERR_MAX. Since creating
+ *										this room in retrospect would create a backward incompatibilty
+ *										we will just have to live with the haphazard sequence of
+ *										UIL- and HCF specific codes. Theoretically this could be
+ *										corrected when and if there will ever be an overall 
+ *										incompatibilty introduced for another reason
+ */										 
+} hcf_action_cmd;
+
+
+
+
+
+
+
+
+/*============================================================= HCF Defined RECORDS	=========================*/
+/*============================================================= INFORMATION FRRAMES		=====================*/
+#define CFG_INFO_FRAME_MIN				0xF000		//lowest value representing an Informatio Frame
+	
+#define CFG_TALLIES						0xF100		//Communications Tallies
+#define CFG_SCAN						0xF101		//Scan results
+	                        	
+#define CFG_LINK_STAT 					0xF200		//Link Status
+	
+/*============================================================= CONFIGURATION RECORDS	=====================*/
+/*============================================================= mask 0xFCxx				=====================*/						
+//	NETWORK PARAMETERS, STATIC CONFIGURATION ENTITIES
+//FC05, FC0A, FC0B, FC0C, FC0D: SEE W2DN149
+	
+#define CFG_RID_CFG_MIN					0xFC00		//lowest value representing a Configuration RID
+#define CFG_CNF_PORT_TYPE				0xFC00		//[STA] Connection control characteristics
+#define CFG_CNF_OWN_MAC_ADDR			0xFC01		//[STA] MAC Address of this node
+#define CFG_CNF_DESIRED_SSID			0xFC02		//[STA] Service Set identification for connection
+#define CFG_CNF_OWN_CHANNEL				0xFC03		//Communication channel for BSS creation
+#define CFG_CNF_OWN_SSID				0xFC04		//IBSS creation (STA) or ESS (AP) Service Set Ident
+#define CFG_CNF_OWN_ATIM_WINDOW			0xFC05		//[STA] ATIM Window time for IBSS creation
+#define CFG_CNF_SYSTEM_SCALE			0xFC06		//System Scale that specifies the AP density
+#define CFG_CNF_MAX_DATA_LEN			0xFC07		//Maximum length of MAC Frame Body data
+#define CFG_CNF_WDS_ADDR				0xFC08		//[STA] MAC Address of corresponding WDS Link node
+#define CFG_CNF_PM_ENABLED				0xFC09		//[STA] Switch for ESS Power Management (PM) On/Off
+#define CFG_CNF_PM_EPS					0xFC0A		//[STA] Switch for ESS PM EPS/PS Mode
+#define CFG_CNF_MCAST_RX				0xFC0B		//[STA] Switch for ESS PM Multicast reception On/Off
+#define CFG_CNF_MAX_SLEEP_DURATION		0xFC0C		//[STA] Maximum sleep time for ESS PM
+#define CFG_CNF_HOLDOVER_DURATION		0xFC0D		//[STA] Holdover time for ESS PM
+#define CFG_CNF_OWN_NAME				0xFC0E		//Identification text for diagnostic purposes
+
+#define CFG_CNF_ENCRYPTION				0xFC20		//select en/de-cryption of Tx/Rx messages
+	
+	
+//	NETWORK PARAMETERS, DYNAMIC CONFIGURATION ENTITIES
+#define CFG_GROUP_ADDR					0xFC80		//[STA] Multicast MAC Addresses for Rx-message
+#define CFG_CREATE_IBSS					0xFC81		//[STA] Switch for IBSS creation On/Off
+#define CFG_FRAGMENTATION_THRH			0xFC82		//[STA] Fragment length for unicast Tx-message
+#define CFG_RTS_THRH					0xFC83		//[STA] Frame length used for RTS/CTS handshake
+#define CFG_TX_RATE_CONTROL				0xFC84		//[STA] Data rate control for message transmission
+#define CFG_PROMISCUOUS_MODE			0xFC85		//[STA] Switch for Promiscuous mode reception On/Off
+
+#define CFG_CNF_DEFAULT_KEYS			0xFCB0		//defines set of encryption keys
+#define CFG_CNF_TX_KEY_ID			0xFCB1		//select key for encryption of Tx messages
+	
+
+//	BEHAVIOR PARAMETERS	
+#define CFG_TICK_TIME					0xFCE0		//[PRI] Auxiliary Timer tick interval
+#define CFG_RID_CFG_MAX					0xFCFF		//highest value representing an Configuration RID
+
+
+/*============================================================= INFORMATION RECORDS 	=====================*/
+/*============================================================= mask 0xFDxx				=====================*/
+//	NIC INFORMATION	
+#define CFG_RID_INF_MIN					0xFD00		//lowest value representing an Information RID
+#define CFG_PRI_IDENTITY				0xFD02
+#define CFG_PRI_SUP_RANGE				0xFD03		//Primary supplier range
+#define CFG_CFI_ACT_RANGES_PRI			0xFD04
+
+#define CFG_HSI_SUP_RANGE				0xFD09		//H/W - S/W I/F supplier range
+#define CFG_NIC_SERIAL_NUMBER			0xFD0A
+#define CFG_NIC_IDENTITY				0xFD0B
+#define CFG_MFI_SUP_RANGE				0xFD0C
+#define CFG_CFI_SUP_RANGE				0xFD0D
+
+#define CFG_CHANNEL_LIST				0xFD10		//Allowed communication channels
+#define CFG_REG_DOMAINS					0xFD11		//List of intended regulatory domains
+#define CFG_TEMP_TYPE  					0xFD12		//Hardware temperature range code
+#define CFG_CIS							0xFD13		//PC Card Standard Card Information Structure
+
+#define CFG_STA_IDENTITY				0xFD20
+#define CFG_STA_SUP_RANGE				0xFD21		//Station supplier range
+#define CFG_MFI_ACT_RANGES_STA			0xFD22
+#define CFG_CFI_ACT_RANGES_STA			0xFD23
+
+//	MAC INFORMATION
+#define CFG_PORT_STAT					0xFD40		//[STA] Actual MAC Port connection control status
+#define CFG_CURRENT_SSID				0xFD41		//[STA] Identification of the actually connected SS
+#define CFG_CURRENT_BSSID				0xFD42		//[STA] Identification of the actually connected BSS
+#define CFG_COMMS_QUALITY				0xFD43		//[STA] Quality of the Basic Service Set connection
+#define CFG_CURRENT_TX_RATE				0xFD44		//[STA] Actual transmit data rate
+#define CFG_OWN_BEACON_INTERVAL			0xFD45		//Beacon transmit interval time for BSS creation
+#define CFG_CUR_SCALE_THRH				0xFD46		//Actual System Scale thresholds settings
+#define CFG_PROTOCOL_RSP_TIME			0xFD47		//Max time to await a response to a request message
+#define CFG_SHORT_RETRY_LIMIT			0xFD48		//Max number of transmit attempts for short frames
+#define CFG_LONG_RETRY_LIMIT			0xFD49		//Max number of transmit attempts for long frames
+#define CFG_MAX_TX_LIFETIME				0xFD4A		//Max transmit frame handling duration
+#define CFG_MAX_RX_LIFETIME				0xFD4B		//Max received frame handling duration
+#define CFG_CF_POLLABLE					0xFD4C		//[STA] Contention Free pollable capability indication
+#define CFG_AUTHENTICATION_ALGORITHMS	0xFD4D		//Available Authentication Algorithms indication
+#define CFG_AUTHENTICATION_TYPE			0xFD4E		//Available Authentication Types indication
+#define CFG_PRIVACY_OPTION_IMPLEMENTED	0xFD4F		//WEP Option availability indication
+	
+
+//	MODEM INFORMATION	
+#define CFG_PHY_TYPE					0xFDC0		//		// 	Physical layer type indication
+#define CFG_CURRENT_CHANNEL				0xFDC1		//Actual frequency channel used for transmission
+#define CFG_CURRENT_POWER_STATE			0xFDC2		//Actual power consumption status
+#define CFG_CCAMODE						0xFDC3		//Clear channel assessment mode indication
+#define CFG_CCATIME						0xFDC4		//Clear channel assessment time
+#define CFG_MAC_PROCESSING_DELAY		0xFDC5		//MAC processing delay time
+#define CFG_SUPPORTED_DATA_RATES		0xFDC6		//Data rates capability information
+
+#define CFG_RID_INF_MAX					0xFDFF		//highest value representing an Information RID
+
+//} hcf_info_type;
+
+
+
+
+/*************************************************************************************************************/
+
+/****************************** S T R U C T U R E   D E F I N I T I O N S ************************************/
+
+typedef struct LTV_STRCT {	//used for all "minimal" LTV records
+	hcf_16	len;					//default length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	val[1];					//do not change this, some dynamic structures are defined based on this !!
+}LTV_STRCT;
+
+typedef LTV_STRCT FAR *	LTVP;
+
+
+
+
+
+#define COMP_ID_MINIPORT	41				//Windows 9x/NT Miniport
+#define COMP_ID_PACKET		42				//Packet
+#define COMP_ID_ODI_16		43				//DOS ODI
+#define COMP_ID_ODI_32		44				//32-bits ODI
+#define COMP_ID_MAC_OS		45				//Macintosh OS
+#define COMP_ID_WIN_CE		46				//Windows CE Miniport
+#define COMP_ID_LINUX		47				//You never guessed, Linux
+#define COMP_ID_AP1			81				//WaveLAN/IEEE AP
+
+
+
+#define COMP_ROLE_SUPL	00				//supplier
+#define COMP_ROLE_ACT	01				//actor
+
+#define COMP_ID_MFI		01				//Modem		 		- Firmware	I/F
+#define COMP_ID_CFI		02				//Controller		- Firmware	I/F
+#define COMP_ID_PRI		03				//Primary Firmware	- Driver	I/F
+#define COMP_ID_STA		04				//Station Firmware	- Driver	I/F
+#define COMP_ID_DUI		05				//Driver			- Utility	I/F
+#define COMP_ID_HSI		06				//H/W               - Driver	I/F
+
+typedef struct KEY_STRCT {
+	hcf_16	len;			//length of key
+	hcf_8	key[14];		//encryption key
+} KEY_STRCT;
+
+typedef struct CFG_CNF_DEFAULT_KEYS_STRCT {	//CFG_CNF_DEFAULT_KEYS (0xFCB0) defines set of encrypti
+	hcf_16		len;		//default length of RID
+	hcf_16		typ;		//RID identification as defined by Hermes
+	KEY_STRCT	key[4];		//encryption keys
+} CFG_CNF_DEFAULT_KEYS_STRCT;
+
+
+typedef struct CFG_REG_DOMAINS_STRCT {	//CFG_REG_DOMAINS (0xFD11) List of intended regulatory domains.
+	hcf_16	len;					//length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	domains[6];
+}CFG_REG_DOMAINS_STRCT;
+
+typedef struct CFG_CIS_STRCT {			//CFG_CIS (0xFD13) PC Card Standard Card Information Structure
+	hcf_16	len;					//length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	cis[240];				//Compact CIS Area, a linked list of tuples
+}CFG_CIS_STRCT;
+
+
+typedef struct CFG_COMMS_QUALITY_STRCT {//CFG_COMMS_QUALITY (0xFD43) Quality of the Basic Service Set connection [STA]
+	hcf_16	len;					//length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	coms_qual;              //Communication Quality of the BSS the station is connected to
+	hcf_16	signal_lvl;				//Average Signal Level of the BSS the station is connected to
+	hcf_16	noise_lvl;				//Average Noise Level of the currently used Frequency Channel
+}CFG_COMMS_QUALITY_STRCT;
+
+
+
+typedef struct CFG_CUR_SCALE_THRH_STRCT {//CFG_CUR_SCALE_THRH (0xFD46) Actual System Scale thresholds
+	hcf_16	len;					//default length of RID [STA: 6  AP: 4]
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	energy_detect_thrh;		//Receiver H/W Energy Detect Threshold
+	hcf_16	carrier_detect_thrh;	//Receiver H/W Carrier Detect Threshold
+	hcf_16	defer_thrh;				//Receiver H/W Defer Threshold
+	hcf_16	cell_search_thrh;		//Firmware Roaming Cell Search Threshold [STA]
+	hcf_16	out_of_range_thrh;		//Firmware Roaming Out of Range Threshold [STA]
+	hcf_16	delta_snr;				//Firmware Roaming Delta SNR value [STA]
+}CFG_CUR_SCALE_THRH_STRCT;
+
+
+typedef struct CFG_PCF_INFO_STRCT {		//CFG_PCF_INFO (0xFD87) Point Coordination Function capability info [AP]
+	hcf_16	len;					//default length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	energy_detect_thrh;
+	hcf_16	carrier_detect_thrh;
+	hcf_16	defer_thrh;
+	hcf_16	cell_search_thrh;
+	hcf_16	range_thrh;
+}CFG_PCF_INFO_STRCT;
+
+
+typedef struct CFG_MAC_ADDR_STRCT{			//0xFC01	[STA] MAC Address of this node.
+											//0xFC08	STA] MAC Address of corresponding WDS Link node.
+											//0xFC11	[AP] Port 1 MAC Adrs of corresponding WDS Link node
+											//0xFC12	[AP] Port 2 MAC Adrs of corresponding WDS Link node
+											//0xFC13	[AP] Port 3 MAC Adrs of corresponding WDS Link node
+											//0xFC14	[AP] Port 4 MAC Adrs of corresponding WDS Link node
+											//0xFC15	[AP] Port 5 MAC Adrs of corresponding WDS Link node
+											//0xFC16	[AP] Port 6 MAC Adrs of corresponding WDS Link node
+	hcf_16	len;					//default length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	mac_addr[3];
+}CFG_MAC_ADDR_STRCT;
+
+typedef struct CFG_GROUP_ADDR_STRCT{			//0xFC80	//[STA] Multicast MAC Addresses for
+	hcf_16	len;					//default length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	mac_addr[GROUP_ADDR_SIZE/6][3];
+}CFG_GROUP_ADDR_STRCT;
+
+
+typedef struct CFG_ID_STRCT {				//0xFC02	[STA] Service Set identification for connection.
+											//0xFC04	IBSS creation (STA) or ESS (AP) Service Set Ident
+											//0xFC0E	Identification text for diagnostic purposes.
+	hcf_16	len;					//default length of RID
+	hcf_16	typ;					//RID identification as defined by Hermes
+	hcf_16	id[17];
+}CFG_ID_STRCT;
+
+
+typedef void *	DUIP;
+
+#endif // MDD_H
+
+




