/*+M*************************************************************************
 * Symbol Technologies Trilogy IEEE PCMCIA device driver for Linux.
 *
 * Copyright (c) 2000 Symbol Technologies Inc. -- http://www.symbol.com
 * All rights reserved.
 *
 * Developed for Symbol Technologies Inc. by TriplePoint, Inc.
 *   http://www.triplepoint.com
 *
 * Abstract:
 *
 *     This is a part of the driver for the Trilogy 802.11 11 Mbit
 *     wireless MAC controller as used in Symbol Technologies systems.
 *
 * Author:
 *
 *     Tim Gardner
 *
 *---------------------------------------------------------------------------
 * This driver supports the following features:
 *   - Hot plug/unplug
 *   - Access Point and Ad-Hoc (peer-to-peer) communication
 *   - Card power management
 *
 *   Refer to the manual page for additional configuration, feature, and
 *   support information.
 *---------------------------------------------------------------------------
 * This program is 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, 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.
 *
 * ALTERNATIVELY, this driver may be distributed under the terms of
 * the following license, in which case the provisions of this license
 * are required INSTEAD OF the GNU General Public License. (This clause
 * is necessary due to a potential bad interaction between the GPL and
 * the restrictions contained in a BSD-style copyright.)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, and the entire permission notice in its entirety,
 *    including the disclaimer of warranties.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *-M*************************************************************************/

#ifndef _TrilogyHARDWARE_
#define _TrilogyHARDWARE_

/*
 * Define this macro to enable code for the T3 compact flash
 * version of the spectrum24 adapter.
 */
#define TRILOGY3    1
#define STANDALONE  1
#define MODULE      1

#include <linux/config.h>
#if CONFIG_SMP
#ifndef __SMP__
#define __SMP__
#endif
#endif

#if MODULE
#ifndef _S24_INIT_
#define __NO_VERSION__
#endif
#include <linux/module.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif

#ifdef PCMCIA_DEBUG
#define DBG     1
#endif // PCMCIA_DEBUG
#define DBG     1

/*
 * If you want host scan information updated automatically every 5 seconds,
 * then define this MACRO.
 */
#define S24T_AUTORUN_HOST_SCAN 1

/*
 * STANDALONE is defined when these sources are built outside the PCMCIA package
 * environment, e.g., built against the kernel includes only.
 */
#ifdef STANDALONE
#include <linux/version.h>
#define VERSION(a,b,c) KERNEL_VERSION(a,b,c)
#define ALLOC_SKB(l) dev_alloc_skb((l)+2)
#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
#define NEW_MULTICAST
#define IRQ(a,b,c) (a,b,c)
#define RUN_AT(x) (jiffies+(x))
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99))
#define init_dev_name(dev, node) do { } while (0)
#define copy_dev_name(node, dev) strcpy((node).dev_name, (dev)->name)
#else
#error unimplemented for versions prior to 2.4
#endif

#else
#include <pcmcia/config.h>
#include <pcmcia/k_compat.h>
#endif

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,4))
#include <linux/slab.h>
#else
#include <linux/malloc.h>
#endif
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/bitops.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>

#include <linux/proc_fs.h>

#if S24_PROC_SYS
#include <linux/list.h>
#include "Spectrum24tHash.h"
#endif

#ifdef HAS_WIRELESS_EXTENSIONS
#include <linux/wireless.h>
#define IEEE_WIRELESS
#endif // HAS_WIRELESS_EXTENSIONS

#if (LINUX_VERSION_CODE < VERSION(2,2,0))
#error Not supported for ancient kernels. Too much cruft.
#endif

#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
#include "debug.h"

#if (LINUX_VERSION_CODE < VERSION(2,3,0))
#define local_irq_save(f)  do { save_flags(f); cli(); } while (0)
#define local_irq_restore(f)  do { restore_flags(f); } while (0)
#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL
static inline void __skb_queue_purge(struct sk_buff_head *list)
{
    struct sk_buff *skb;
    while ((skb=__skb_dequeue(list))!=NULL)
        kfree_skb(skb);
}
#endif

typedef struct net_device DEVICE;

#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#define FIELD_OFFSET(type, field)    offsetof(type,field)

#define NELEM(arr) (sizeof(arr) / sizeof(arr[0]))

// The buffer size associated with the LTV record (allowing for the header
// information).
#define MAX_LTV_BUF_SIZE (512 - (sizeof(__u16) * 2))

#define S24T_TALLIES_SIZE (sizeof(CFG_HERMES_TALLIES_STRCT) + \
    (sizeof(__u16) * 2))

/*
 * Uncomment this macro when the firmware supports keylengths other then 5.
 */
#define SPECTRUM24T_KEYLENGTH       1

#define S24T_MAX_MULTICAST           16
#define S24T_MAX_PACKET_SIZE         1500
#define S24T_MAX_NAME_LEN            32
#define S24T_NUM_IO_PORTS            0x40
#define S24T_TX_TIMEOUT              ((400 * HZ) / 1000)

#define S24T_MIN_COMM_QUALITY        0
#define S24T_MAX_COMM_QUALITY        92
#define S24T_MIN_SIGNAL_LEVEL        47
#define S24T_MAX_SIGNAL_LEVEL        138
#define S24T_MIN_NOISE_LEVEL         47
#define S24T_MAX_NOISE_LEVEL         138

#define S24T_ACK_TIMEOUT_MILES_FACTOR   11
#define S24T_MIN_ACK_TIMEOUT            324
#define S24T_MAX_ACK_TIMEOUT            874

#define S24T_EJECTED                 0xffff

#define TX_RATE_1_MBIT              1
#define TX_RATE_2_MBIT              2
#define TX_RATE_5_5_MBIT            4
#define TX_RATE_11_MBIT             8
#define TX_RATE_UNITS               100000

// Host <==> Adapter conversions
#define atohl(v) cpu_to_le32(v)
#define atohs(v) cpu_to_le16(v)
#define htoal(v) le32_to_cpu(v)
#define htoas(v) le16_to_cpu(v)

#if (LINUX_VERSION_CODE < VERSION(2,1,0))
typedef struct {
    volatile unsigned int lock;
} spinlock_t;
#define spin_lock_init(l) do { } while(0)

#ifndef CAP_NET_ADMIN
#  define CAP_NET_ADMIN     12
#  define capable(x)        suser()
#endif // CAP_NET_ADMIN

// All pre-2.1.0 kernels only support integers (32-bit) values or
// normal strings and no MODULE_PARM_DESC().
#define MODULE_PARM_DESC(a,b)
#define p_u8    __u32
#define p_s8    __s32
#define p_u16   __u32
#define p_s16   __s32
#define p_u32   __u32
#define p_s32   __s32
#define p_char  char
#else // LINUX_VERSION_CODE
#define p_u8    __u8
#define p_s8    __s8
#define p_u16   __u16
#define p_s16   __s16
#define p_u32   __u32
#define p_s32   __s32
#define p_char  char
#endif // LINUX_VERSION_CODE

#define DRIVER_NAME     "Spectrum24t"

typedef struct _DownloadBlock 
{
	__u16   usID;
#define FW_UPDATE_START		0		// Initiates firmware update
#define	FW_UPDATE_DATA		1		// Contains firmware image
#define	FW_UPDATE_END		2		// Terminates download and starts programming
#define FW_READ_DATA		3		// Read and return flash memory
#define FW_UPDATE_CIS		4		// Sends CIS file to driver

	__u32	ulBlock;				// START - Number of blocks in image
									// DATA - Block number
									// END - In - CSUM Low, Out - return code
	__u32	ulLength;				// START - Block length
									// DATA - Block length
									// END - In - CSUM High
	__u8	aucData[0];				// Start of image data

} __attribute__ ((packed)) DOWNLOAD_BLOCK, *PDOWNLOAD_BLOCK;

typedef enum {
    FALSE = 0,
    TRUE  = 1
} bool_t;

typedef struct S24T_private {
    dev_node_t                  node;
    DEVICE                      *dev;
    struct net_device_stats     stats;
    volatile __u8               *Cor;
#ifdef WIRELESS_EXT
    struct iw_statistics        wstats;
#endif // WIRELESS_EXT
    u_long                      txBytes;
    __u16                       txFid;
    __u16                       rxFid;

    __u8                        MACAddress[ETH_ALEN];
    char                        NetworkName[S24T_MAX_NAME_LEN+1]; /* ESS ID */
    char                        StationName[S24T_MAX_NAME_LEN+1];
    __u16                       LinkStatus; /* 1 means linked. */

    char                        FwVersion[S24_FW_VERSION_LEN+1];
    char                        FwDate[S24_FW_VERSION_LEN+1];
    /*
     * All 16 bit setup values can be treated in a reasonably generic manner.
     */
#   define                      AntennaDiversity        0
#   define                      PortType                1
#   define                      Channel                 2
#   define                      APDensity               3
#   define                      MaxDataLength           4
#   define                      RtsThreshHold           5
#   define                      TxRateControl           6
#   define                      PromiscuousMode         7
#   define                      TickTime                8
#   define                      FragmentationThreshHold 9
#   define                      EncryptionKeyId         10
#   define                      EncryptionEnabled       11
#   define                      EncryptionAuthentication 12
#   define                      EncryptionKeyLen        13
#   define                      PowerSaveMode           14
#   define                      ReceiveAllMCast         15
#   define                      MaxSleepDuration        16
#   define                      AckTimeout              17
#   define                      MaxParam                18

    __u16                       Param[MaxParam];

    /*
     * Ordinals table addresses.
     */
#   define                      NUM_ORDINAL_TABLES  2
    __u16                       OrdinalTablesStartAddr[NUM_ORDINAL_TABLES];
    __u16                       OrdinalTablesLen[NUM_ORDINAL_TABLES];

    /*
     * Remember distance to the AP in miles.
     */
    __u32                       ApDistance;

#define AUTHENTICATION_ALGORITHM_OPEN_SYSTEM    1
#define AUTHENTICATION_ALGORITHM_SHARED_KEY     2
#define AUTHENTICATION_ALGORITHM_SHARED_KEY_128 3 /* AP only */

#define MAX_NUM_KEY 4
#define MAX_KEY_LEN 13
    __u8                        EncryptionKey[MAX_NUM_KEY][MAX_KEY_LEN];

    S24tInfoRecType             InfoRec;

    /*
     * Keep a record of the current BSSID.
     */
    __u8                        BssId[ETH_ALEN];

    /*
     * Bridge announcements must be translated into WLAP speak.
     */
    __u32                       UseHelloTime;
    __u32                       LastHelloTime;
    ENCAPSULATED_WLAP_BPDU_TYPE Bpdu;

    /*
     * SKB free list. These SKB's are freed at a later time other then in interrupt
     * context.
     */
    struct sk_buff_head         ToBeFreed;

    /*
     * Transmit buffers queued from the net interface. These are straight 802.3
     * packets. SNAP translation is performed after dequeueing for transmit.
     */
    struct sk_buff_head         Tx802_3Queue;

    /*
     * Non-zero when in Access Point mode. It affects how packets are received and
     * transmitted. This value is non-zero whenever the proc filesystem interface
     * is open.
     */
    __u32                       ApMode;

#if S24_PROC_SYS
    /*
     * In AP mode, transmits and receives get queued here. Each skb is assumed to point
     * to a SCORCH_RW. These queues must be guarded since skb's are added and removed
     * within interrupt context.
     */
    struct sk_buff_head         ApTxQueue;
    struct sk_buff_head         ApRxQueue;

    /*
     * Save the proc filesystem name that we registered so that it can be unregistered. See
     * S24T_PROC_NAME_ROOT and S24T_PROCSYS_NAME_FORMAT for formatting.
     */
#   define                      S24T_PROC_NAME_LEN   64
    char                        ProcName[S24T_PROC_NAME_LEN];

    /*
     * Upon proc file system registration, we get a directory entry that we must later
     * use to relate opens and closes to this context.
     */
    struct proc_dir_entry *     ProcFile;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
    struct proc_dir_entry       ProcFileVal;
#endif

    /*
     * Keep track of proc file system opens. Only one is allowed at a time.
     */
    __u32                       ProcSysOpen;

    /*
     * Remember registration status.
     */
    int                         ProcRegistrationStatus;

    /*
     * Default AP braodcast rate.
     */
    __u32                       BcastRate;

    /*
     * Create a hash table for MU and bridged addresses.
     */
#   define MU_HASH_BITS         6
    PMuHashTableType            HashTab;

    /*
     * Set if at least one MU is in power saving mode. This means that all mcast
     * traffic must be queued until ATIM time. All directed traffic must be queued 
     * for the MU that is in power saving mode.
     */
    __u32                       PowerSavingMode;

    /*
     * Use this buffer to generate a Traffic Indication Message (TIM)
     */
#   define MAX_TIM_BIT          2008
#   define MAX_TIM              (MAX_TIM_BIT/8)
    __u8                        Tim[MAX_TIM];

    /*
     * All multicast packets must be queued until after the ATIM beacon if at least
     * one MU is in power saving mode.
     */
    struct sk_buff_head         ApMcastQueue;

#endif

    /*
     * Signal quality values from RID_COMMS_QUALITY.
     */
    __u16                       Cq;
    __u16                       Asl;
    __u16                       Anl;

#if TRILOGY3
    /*
     * Put scan results here.
     */
    __u32                       ScanAuto;
    DS_SCAN_RESULTS             ScanResults;

    /*
     * Group ordinal values.
     */
    __u32                       GroupOrdValid;
    GROUP_ORD                   GroupOrd;

#   define MAX_PDA_LEN_WORDS    512
#   define PDA_START_ADDR       0x3F0000
	__u16			            pda[MAX_PDA_LEN_WORDS];

	// ROM download buffer holding area.

	__u16			            usDownloadPage;
	__u16			            usDownloadOffset;
	__u16			            usDownloadLength;

    __u32                       ulIoPAddr;
    __u32                       uiEsquare;

    __u32                       CorIo;
#endif
} S24tPrivate, *PS24tPrivate;

/*--------------------------------------------------------------------------*/
#ifndef PCMCIA_DEBUG
#define PCMCIA_DEBUG    0
#endif // PCMCIA_DEBUG

#undef  DBG_TRAP
#define DBG_TRAP         {}

#define VALIDATE_PARAMS

#define NIC_INTEN_MASK  (IEN_RX|IEN_ALLOC|IEN_INFO|IEN_TXEXC|IEN_TX)

/////////////////////////////////////////////////////////////////////
//
// Offsets from Adapter->IoPAddr of the ports used to access the Trilogy
// NIC Registers.
//
// Command/Status Registers

#define NIC_COMMAND     0x00
#define NIC_PARAM0      0x02
#define NIC_PARAM1      0x04
#define NIC_PARAM2      0x06
#define NIC_STATUS      0x08
#define NIC_RESP0       0x0A
#define NIC_RESP1       0x0C
#define NIC_RESP2       0x0E

// FID Management Registers

#define NIC_INFO_FID    0x10
#define NIC_RX_FID      0x20
#define NIC_ALLOC_FID   0x22
#define NIC_TX_COMP_FID 0x24

// BAP 0

#define NIC_SELECT0     0x18    // FID/RID 0
#define NIC_OFFSET0     0x1C
#define NIC_DATA0       0x36

// BAP 1

#define NIC_SELECT1     0x1A    // FID/RID 1
#define NIC_OFFSET1     0x1E
#define NIC_DATA1       0x38

// Event

#define NIC_EVSTAT      0x30
#define NIC_INTEN       0x32
#define NIC_EVACK       0x34

// Control

#define NIC_CONTROL     0x14

// Host Software

#define NIC_SW_SUPPORT0 0x28
#define NIC_SW_SUPPORT1 0x2A
#define NIC_SW_SUPPORT2 0x2C
#define NIC_SW_SUPPORT3 0x2E    // reset reason code

// Auxiliary port

#define NIC_AUX_BASE    0x3A
#define NIC_AUX_OFFSET  0x3C
#define NIC_AUX_DATA    0x3E

#define NIC_COR			0x40	// Configuration Option Register (Soft Reset)
#define NIC_HCR			0x42	// Host Configuration Register (Select Genesis Mode for firmware download download)
#define NIC_CCSR		0x44

/////////////////////////////////////////////////////////////////////
//
// Constants for the NIC_COMMAND register.
//
// Controller/State

#define CR_INITIALIZE   0x0000
#define CR_ENABLE       0x0001
#define CR_ENABLE_AP    0x0081
#define CR_DISABLE      0x0002
#define CR_DIAGNOSE     0x0003

// Buffer Management

#define CR_ALLOCATE     0x000A
#define CR_TRANSMIT     0x000B
#define CR_RECLAIM      0x0100

// Regulate

#define CR_NOTIFY       0x0010
#define CR_INQUIRE      0x0011

// Configure

#define CR_ACCESS       0x0021
#define CR_ACCESS_WRITE 0x0121
#define CR_DOWNLOAD     0x0022
#define DL_MODE_DIABLE  0x0000  // Disables AUX port access & makes the
                                // downloaded firmware active
#define DL_MODE_ENABLE_VP 0x0100  // Enables download of firmware image via the
                                // AUX port registers directly into volatile
                                // memory.
#define DL_MODE_ENABLE_NVP 0x0200  // Enables download of firmware  via the AUX
                                // port registers into a temp download buffer
                                // in volatile memory.
#define DL_MODE_FLUSH   0x0300  // Writes the download buffer contents into
                                // the destination area in non-volatile
                                // memory.

#define CR_MIF		    0x0030
#define CR_MIF_WRITE    0x0031
#define CR_SCRATCH      0x0032
#define CR_RADIO_REG    0x2138

#define COMMAND_REGISTER_BUSY   0x8000  // Command Busy bit mask

#define CW_READEE		CR_MIF	// for serial eeprom
#define BAR_CIS		    0x0008		// 0x0400
#define	BUFADDR			0x3000

/////////////////////////////////////////////////////////////////////
//
// BAP register defines

//#define OFFSET_REGISTER_ERROR 0x4000  // Offset register error
#define OFFSET_REGISTER_BUSY    0x8000  // Offset register busy
#define DEAD_OR_EJECTED         0xFFFF  // Dead or ejected card


/////////////////////////////////////////////////////////////////////
//
// Constants for EvStat Register

#define EVS_RX          0x0001  // Frame is received
#define EVS_TX          0x0002  // TX completed
#define EVS_TXEXC       0x0004  // TX unsuccessfully completed
#define EVS_ALLOC       0x0008  // Alloc or reclaim of frame structure buffer
#define EVS_CMD         0x0010  // Command execution is completed
#define EVS_INFO        0x0080  // Information frame is generated
#define EVS_INFO_DROP   0x2000  // Unsolicited frame structure alloc error
#define EVS_WAIT_ERROR  0x4000  // Wait timeout error in the adapter
#define EVS_TICK        0x8000  // Auxiliary timer tick


/////////////////////////////////////////////////////////////////////
//
// Constants for IntEn Register
//
// Specifies what events cause interrupts

#define IEN_RX          0x0001  // Frame reception
#define IEN_TX          0x0002  // TX completed
#define IEN_TXEXC       0x0004  // TX unsuccessfully completed
#define IEN_ALLOC       0x0008  // Alloc or reclaim of frame structure buffer
#define IEN_CMD         0x0010  // Command execution completion
#define IEN_INFO        0x0080  // Information frame is generation
#define IEN_INFO_DROP   0x2000  // Unsolicited frame structure alloc error
#define IEN_WAIT_ERROR  0x4000  // Wait timeout error in the adapter
#define IEN_TICK        0x8000  // Auxiliary timer tick

/////////////////////////////////////////////////////////////////////
//
// Constants for EvAck Register
//
// Specifies what events cause interrupts

#define ACK_RX          0x0001  // Frame reception
#define ACK_TX          0x0002  // TX completed
#define ACK_TXEXC       0x0004  // TX unsuccessfully completed
#define ACK_ALLOC       0x0008  // Alloc or reclaim of frame structure buffer
#define ACK_CMD         0x0010  // Command execution completion
#define ACK_INFO        0x0080  // Information frame is generation
#define ACK_INFO_DROP   0x2000  // Unsolicited frame structure alloc error
#define ACK_WAIT_ERROR  0x4000  // Wait timeout error in the adapter
#define ACK_TICK        0x8000  // Auxiliary timer tick

/////////////////////////////////////////////////////////////////////
//
// Constants for NIC_STATUS Register
#define NIC_STATUS_CMD_MASK                 0x003f
#define NIC_STATUS_RESULT_MASK              0x7f00
#   define NIC_STATUS_RESULT_OK             0x0000
#   define NIC_STATUS_RESULT_CARD_FAILURE   0x0100
#   define NIC_STATUS_RESULT_NO_BUFF        0x0500
#   define NIC_STATUS_RESULT_CMD_ERR        0x7f00

/////////////////////////////////////////////////////////////////////
//
// Constant for RID identification
typedef struct _SUP_RANGE {
    __u16  role;
    __u16  id;
    __u16  variant;
    __u16  bottom;
    __u16  top;
}  __attribute__ ((packed)) SUP_RANGE;

// From AP firmware to report association change of status of stations (0xF201)

typedef struct _ASSOC_STATUS {
    __u16      assocStatus;
    __u8       staAddr[6];
    __u8       oldApAddr[6];          // Optional: only if status is ASSOC_STATUS_STA_REASSOCIATED
}  __attribute__ ((packed)) ASSOC_STATUS, *PASSOC_STATUS;

#define ASSOC_STATUS_STA_ASSOCIATED     1
#define ASSOC_STATUS_STA_REASSOCIATED   2
#define ASSOC_STATUS_STA_DISASSOCIATED  3

#define EVENT_CONNECT       1
#define EVENT_DISCONNECT    2
#define EVENT_ROAM          3
#define EVENT_ASSOCIATE     4
#define EVENT_UNASSOCIATE   5

#define ENCRYPT_FLAG_ENABLE     3
#define ENCRYPT_FLAG_DISABLE    0

typedef struct {
    __u16   Len;
    __u8    String[1];
}  __attribute__((packed)) S24tByteStringType, *PS24tByteStringType;

typedef struct _RID_STRUCT {
    __u16  length;
    __u16  rid;
    union {
        __u16           __u16;
        __u16          linkStatus;
        ASSOC_STATUS    assocStatus;
        SUP_RANGE       supRange;
        __u16           data[250];
    } u;
}  __attribute__ ((packed)) RID_STRUCT, *PRID_STRUCT;


#define DEFAULT_CHANNEL             1
#define DEFAULT_IO_BASE_ADDRESS     0x300
#define DEFAULT_MEMORY_SIZE         0x1000
#define DEFAULT_MEMORY_WINDOW       0xd4000
#define S24T_MAX_RTS                3000
#define S24T_MIN_RTS                1
#define DEFAULT_RTS_THRESHOLD       1600
#define S24T_MIN_FRAG_THRESHOLD     256
#define S24T_MAX_FRAG_THRESHOLD     2346
#define DEFAULT_FRAG_THRESHOLD      S24T_MAX_FRAG_THRESHOLD
#define DEFAULT_TX_RATE             0x0f
#define DEFAULT_INTERRUPT_NUMBER    3
#define MAX_IOBASEADDR              0xFFFF
#define MIN_IOBASEADDR              0x0100
#define MAX_IRQ                     15
#define MIN_IRQ                     2
#define MAX_MULTICAST_LIST          32

#define OFFSET_COR                  0x3e0   // COR offset within Common Memory
#define CS_CIS_MFG_NAME_OFFSET      0x16    // Manufacturer Name string , null terminated
#define CS_CIS_MFG_NAME_LEN         32
#define COR_RESET                   0x80
#define COR_IO_MODE                 0x41
#define COR_CLEAR                   0x0

#define OFFSET_HCR					0x3E2	// hfa3842 host configuration register
#define	HCRHOLD						0x1F	// hold context 7 to load firmware (8 bit SRAM)
#define HCRRUN						0x17	// leave context 7 running in init mode (8 bit)
#define	HCREEHOLD					0xDE	// hold context 7 to load firmware (8 bit SRAM)

// Timeout definitions

#define COMMAND_BUSY_TIMEOUT        100 // * 10 = 1000 microseconds

// Constant for Control Register

#define CTL_AUX_EN      0x8000  // Enable auxiliary port access
#define CTL_AUX_DISABLE 0x4000  // Disable to auxiliary port access
#define CTL_AUX_OPEN    0xC000  // Auxiliary port is open if CTL reg
                                // has this value.
// AUX port access keys.
// The AUX port is locked and to unlock it you have to write the
// following values to the PARAM0-1 registers then write a
// CTL_AUX_EN to the NIC_CONTROL register. When the NIC_CONTROL
// register is a CTL_AUX_OPEN then access to the auxiliary port
// is enabled.

#define AUX_PARAM0_KEY      0xFE01
#define AUX_PARAM1_KEY      0xDC23
#define AUX_PARAM2_KEY      0xBA45

/*
 * Host to CW10 byte ordering. The CW10 is little endian.
 */
extern __inline__ __u16 HTOCW10S(__u16 V)
{
    return(cpu_to_le16(V));
};
extern __inline__ __u16 CW10TOHS(__u16 V)
{
    return(le16_to_cpu(V));
};

extern int S24tInit(struct S24T_private *lp);
extern void S24tHalt(struct S24T_private *lp);
extern int S24tEnable( struct S24T_private *lp, __u32 ApMode);
extern int S24tDisable( struct S24T_private *lp, __u32 ApMode);
extern int S24tIrqEnable( struct S24T_private *lp);
extern int S24tIrqDisable( struct S24T_private *lp);
extern int S24tEvStat( struct S24T_private *lp,__u16 *EvStat);
extern void S24tTx( struct S24T_private *lp, struct sk_buff *skb);
extern void S24tStartTx( struct S24T_private *lp );
#define S24tTxReady(lp) ((lp)->txFid ? 1 : 0)
extern struct sk_buff * S24tRx( struct S24T_private *lp);
extern int S24tGetTxFid( struct S24T_private *lp);
extern int S24tEvAck(  struct S24T_private *lp, __u16 EvAck);
extern int S24tSetMulticast(struct S24T_private *lp,__u32 McBytes,__u8 *Mc);
extern int S24tPromiscuousMode(struct S24T_private *lp,__u16 Enabled);
extern int S24tCardInserted(struct S24T_private *lp);
extern int S24tGetInfoRec(struct S24T_private *lp);
extern int S24tSetEssId(struct S24T_private *lp, char *Essid);
extern int S24tGeneralInfo(struct S24T_private *lp);
extern int S24tReadRid(struct S24T_private *lp,__u16 rid,__u8 *buff,__u32 data_len);
extern int S24tWriteRid(struct S24T_private *lp,__u16 rid,__u8 *buff,__u32 data_len);
extern int S24tReadAuxPort(struct S24T_private *lp,__u8 *dest,__u32 addr,__u32 len);
extern int S24tWriteAuxPort(struct S24T_private *lp,__u8 *src,__u32 addr,__u32 len);
extern int S24tCommand(struct S24T_private *lp,__u16 Command,__u16 *Result,__u16 *P0,__u16 *P1,__u16 *P2);

extern __u8 S24tReadCor(struct S24T_private *lp);
extern void S24tWriteCor(struct S24T_private *lp,__u8 Cor);

extern __u16 S24tRead16(struct S24T_private *lp,__u16 offset);
extern void S24tWrite16(struct S24T_private *lp,__u16 offset,__u16 val);

extern __u8 S24tRead8(struct S24T_private *lp,__u16 offset);
extern void S24tWrite8(struct S24T_private *lp,__u16 offset,__u8 val);

extern int S24tSetChannel(struct S24T_private *lp,__u16 chan);
extern int S24tGetChannel(struct S24T_private *lp,__u16 *chan);

extern int S24tReadScanResults(struct S24T_private *lp,DS_SCAN_RESULTS *results);
extern int S24tReadGroupOrd(struct S24T_private *lp,GROUP_ORD *grp);
extern int S24tWriteTxRate(struct S24T_private *lp,__u32 rate);
extern int S24tGetCurrTxRate(struct S24T_private *lp,__u16 *rate);
extern int S24tWriteRts(struct S24T_private *lp,__u32 rts);
extern int S24tWriteFragThreshold(struct S24T_private *lp,__u32 frag);
extern __u32 S24tMilesToAckTime(struct S24T_private *lp,__u32 miles);
extern int S24tWriteApDistance(struct S24T_private *lp,__u32 miles);
extern int S24tGetComms(struct S24T_private *lp);
extern int S24tGetTableOneOrdinal(struct S24T_private *lp,__u32 Ord,__u32 *Val);
extern int S24tSetStationName(struct S24T_private *lp, char *StationName);
extern int S24tSetApDensity(struct S24T_private *lp,__u32 Density);
extern int S24tSetAntennaDiversity(struct S24T_private *lp,__u16 diversity);
extern int S24tSetReceiveAllMulticasts(struct S24T_private *lp,__u16 enabled);
extern int S24tStartScan(struct S24T_private *lp,__u32 Enable,__u32 OneTime);
extern int S24tReadCw10Reg(struct S24T_private *lp,__u8 RegNum,__u8 *RegVal);
extern int S24tWriteCw10Reg(struct S24T_private *lp,__u8 RegNum,__u8 RegVal);

#if S24_PROC_SYS
extern int S24tRegisterProcSys(PS24tPrivate S24t, dev_link_t **dev_list);
extern void S24tUnRegisterProcSys(PS24tPrivate S24t);
extern void S24tProcQueueRx(PS24tPrivate S24t, struct sk_buff *skb);
extern struct sk_buff *S24tMakeBeacon(struct S24T_private *lp,struct sk_buff *skb);
extern struct sk_buff *S24tApFilterTx(struct S24T_private *lp,struct sk_buff *skb);
extern struct sk_buff *S24tApFilterRx(struct S24T_private *lp,struct sk_buff *skb);

#include "Spectrum24tBeacon.h"

#endif

#if TRILOGY3
/*
 * Define support for Spectrum24tDnld.c. Its a gross, ugly hack for sources files
 * that started life as NDIS sources. But, ime is money...
 */
typedef S24tPrivate *PTRILOGY_ADAPTER;
typedef __u32 ULONG;
typedef __u32 *PULONG;
typedef __u32 UINT;
typedef __u32 *PUINT;
typedef __u16 USHORT;
typedef __u16 *PUSHORT;
typedef __u8 UCHAR;
typedef __u8 *PUCHAR;
typedef __u32 NDIS_STATUS;
typedef __u32 BOOLEAN;
typedef __u16 word;
typedef __u8 byte;
#define VOID void
#define IN
#define OUT

#define NDIS_STATUS_SUCCESS 0
#define NDIS_STATUS_FAILURE (~0)
#define NDIS_MEMORY_CONTIGUOUS 1
#define NDIS_MEMORY_NONCACHED 2

#define CHAIN_BLOCK_SIZE	4096

typedef struct CHAIN 
{
	struct	CHAIN	*next;
			ULONG	ulAddress;
			USHORT	usLength;			// Number of bytes.
			UCHAR	ucData[CHAIN_BLOCK_SIZE];
}  __attribute__((packed)) CHAIN, *PCHAIN;

typedef struct {
    long Hi;
    long Low;
}  __attribute__((packed)) NDIS_PHYSICAL_ADDRESS;

extern NDIS_STATUS NdisAllocateMemory(void *ptr,ULONG len,ULONG flags,NDIS_PHYSICAL_ADDRESS addr);
extern void NdisFreeMemory(void *ptr,ULONG len,ULONG flags);
extern BOOLEAN AdapGetRid(PTRILOGY_ADAPTER lp, PRID_STRUCT Rid, BOOLEAN InfoRec);
extern int AdapAuxPortGet(PTRILOGY_ADAPTER lp, PUSHORT Buff, ULONG Addr, USHORT Wlen);
extern int AdapAuxPortSet(PTRILOGY_ADAPTER lp, PUSHORT Buff, ULONG Addr, USHORT Wlen);
extern void NdisRawWritePortUshort( ULONG Addr, USHORT Val);
extern void NdisRawReadPortUshort( ULONG Addr, USHORT *Val );
extern void AdapWriteUshort(PTRILOGY_ADAPTER lp, USHORT Offset, USHORT Val);
extern NDIS_STATUS TrilogyDownLoadFirmwareToT3Adapter (IN PTRILOGY_ADAPTER pAdapter);
extern BOOLEAN AdapEnableAux (IN  PTRILOGY_ADAPTER pAdapter);

#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,4))
#define min(a,b) ( (a<b) ? a : b )
#endif

#define ZDNLD 0
#define SYMDEBUG(Z,_s_) DBG_TRACE(DbgInfo,"%s\n",(_s_))
#define	SYMDEBUGX(_f_, _s_, _x_) DBG_TRACE(DbgInfo,"%s %08x\n",(_s_),(_x_))
#define SYMDEBUGN(_f_, _s_, _h0_, _h1_, _h2_, _h3_) DBG_TRACE(DbgInfo,"%s %08x %0x %08x %08x\n",(_s_),(_h0_),(_h1_),(_h2_),(_h3_));
#define SYMTRACE(_f_, _t_, _a_, _v_) DBG_TRACE(DbgInfo,"%s\n",(_t_))

#define KMAXTRY 10
#define CW10_STATUS_OK 0

#endif

#endif  // _TrilogyHARDWARE_

