/* This is a really ugly header file!  The objective is to keep airo.c as
 * close as possible to what's in the 2.4 kernel.  Basically we want to
 * support the use of airo.c with the latest pcmcia-cs and the 2.0 and 2.2
 * stable kernels.  Basically we end up with ugly hacks to insert code into
 * airo.c without having to put ifdefs into airo.c.
 */
#if LINUX_VERSION_CODE < 0x20400
#define __devinitdata
#define __devinit

#ifdef CONFIG_PCI
#define PCI_ANY_ID 0
struct pci_device_id {
        unsigned short vendor;
        unsigned short id;
        unsigned short fill1;
        unsigned short fill2;
};

struct pci_driver {
        char *name;
        struct pci_device_id *id_table;
        int(*probe)(struct pci_dev *, const struct pci_device_id *);
        void(*remove)(struct pci_dev *);
};
#endif 

#define driver_data sysdata

#define MODULE_DEVICE_TABLE(x,y)

#define del_timer_sync(x) del_timer(x)

#define alloc_etherdev(x) init_etherdev(0, x)
/* init_etherdev does it... */
#define register_netdev(x) 0

/* Before 2.4 this was a void function, so we gotta fake it if we are
   compiling with an older kernel. */
static inline int bogo_request_region(unsigned long x, unsigned long y, 
                                      const char *z) {
        request_region(x, y, z);
        return 1;
}

#define request_region(x,y,z) bogo_request_region(x,y,z)

#define SET_MODULE_OWNER(x)

#define proc_root_driver &proc_root

static int airo_pci_probe(struct pci_dev *a, const struct pci_device_id *b)
{return 0;}
static void airo_pci_remove(struct pci_dev *c) {}

#define set_current_state(x) current->state = x

#if LINUX_VERSION_CODE < 0x20200
#include <asm/segment.h>
#define get_user_bogus(x,y) ((x) = get_fs_byte(y))&0
#undef get_user
#define get_user(x,y) get_user_bogus(x,y)
#define pci_module_init(k) (int)k&0; \
{\
        int j;\
        unsigned char bus, fun;\
\
        for( j = 0; j < 4; j++ ) { \
                unsigned char irq;\
                unsigned int io;\
                if (pcibios_find_device(card_ids[i].vendor, card_ids[i].id, j, \
	                                &bus, &fun ) != PCIBIOS_SUCCESSFUL ) \
                       break;\
                pcibios_read_config_byte(bus, fun, PCI_INTERRUPT_LINE, &irq);\
                pcibios_read_config_dword(bus, fun, PCI_BASE_ADDRESS_2, &io);\
                io &= PCI_BASE_ADDRESS_IO_MASK;\
                init_airo_card( irq, io, 0 );\
        }\
}
#define MODULE_PARM_DESC(x,y)

/* We don't support SMP on 2.0, so we just stub out the spinlocks */
#define spinlock_t int
#define spin_lock_irqsave(x,y) y=1
#define spin_unlock_irqrestore(x,y) y=1
#define SPIN_LOCK_UNLOCKED 1

static void schedule_timeout(long to) {
        current->timeout = to + jiffies;
        schedule();
        current->timeout = 0;
}

static inline void dev_kfree_skb_bogus(struct sk_buff *skb) {
        dev_kfree_skb(skb, FREE_WRITE);
}

#define dev_kfree_skb(x) dev_kfree_skb_bogus(x)
static int in_interrupt(void) { return 0; }
static inline int timer_pending(struct timer_list *ti) {return (int)ti->next;}

#define capable(x) suser()

/* Ah it's magical!  There was a big change of the signatures of these 
   callbacks between 2.0 and 2.2. */
typedef struct file_operations file_operations_t;
#define file_operations bogus_file_operations
struct file_operations {
        file_operations_t real_ops;
        struct inode_operations i_ops;
        int (*open)( struct inode *inode, struct file *file );
        ssize_t (*read)(struct file *file, char *buffer, 
                        size_t len, loff_t *offset);
        ssize_t (*write)(struct file *file, const char *buffer,
			 size_t len, loff_t *offset );
        int (*release)(struct inode *inode, struct file *file );
};

static int open_redirect( struct inode *inode, struct file *file ) {
        return ((struct file_operations*)file->f_op)->open(inode, file);
}
static int read_redirect( struct inode *inode, struct file *file,
                          char *buffer, int len ) {
        return ((struct file_operations*)file->f_op)->
                read(file, buffer, len, &file->f_pos);
}
static int write_redirect( struct inode *inode, struct file *file,
                           const char *buffer, int len ) {
        return ((struct file_operations*)file->f_op)->
                write(file, buffer, len, &file->f_pos);
}
static void release_redirect( struct inode *inode, struct file *file ) {
        ((struct file_operations*)file->f_op)->release(inode, file);
}

static inline int check_match(int len, const char *name,
                              struct proc_dir_entry *pde)
{
        if (len != pde->namelen) return 0;
        return !memcmp(pde->name, name, len);
}

static struct proc_dir_entry *my_proc_lookup(struct proc_dir_entry *parent,
                                             const char *name)
{
        struct proc_dir_entry *pde = parent->subdir;
        int len = strlen(name);
        while(pde) {
                if (pde->low_ino && check_match(len, name, pde)) return pde;
                pde = pde->next;
        }
        return 0;
}
static void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
        struct proc_dir_entry *pde = my_proc_lookup(parent, name);
        if (!pde) return;
        proc_unregister(parent, pde->low_ino);
        kfree(pde);
}

static struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
						struct proc_dir_entry *parent)
{
        struct proc_dir_entry *pde = my_proc_lookup(parent, name);
        int flen = strlen(name);
        if (!pde) {
                pde = (struct proc_dir_entry *)kmalloc(sizeof(*pde)+flen+1,
                                                       GFP_KERNEL);
                if (!pde) return 0;
                memset(pde, 0, sizeof(*pde));
                pde->name = (const char*)&pde[1];
                strcpy((char*)pde->name, name);
                pde->namelen = flen;
                proc_register_dynamic(parent, pde);
        }
        pde->mode = mode;
        pde->nlink = S_ISDIR(mode) ? 2 : 1;
        if (S_ISDIR(mode)) {
                pde->ops = proc_net.ops;
        }
        return pde;
}

static inline int put_user_bogus(char c, char *ptr) {
        put_user(c, ptr);
        return 0;
}
#include <linux/delay.h>
static inline void mdelay(long x) { udelay(x*1000); }
#undef put_user
#define put_user(x,y) put_user_bogus(x,y)
static void my_setproc_ops(struct proc_dir_entry *pde, 
                           struct file_operations *fops)
{
        memset(&fops->i_ops, 0, sizeof(fops->i_ops));
        pde->ops = &fops->i_ops;
        fops->i_ops.default_file_ops = (file_operations_t*)fops;
        fops->real_ops.open = open_redirect;
        fops->real_ops.read = read_redirect;
        fops->real_ops.write = write_redirect;
        fops->real_ops.release = release_redirect;
}

#define SETPROC_OPS(entry, fops) my_setproc_ops(entry, &fops)

#else
/* Here are the 2.2 specific hacks */
#define pci_module_init(k) \
        0; \
        for( i = 0; card_ids[i].vendor; i++ ) { \
                struct pci_dev *dev = 0; \
                while((dev=pci_find_device(card_ids[i].vendor, card_ids[i].id,\
                                             dev))) { \
                        init_airo_card( dev->irq, \
                                        dev->base_address[2] & \
                                        PCI_BASE_ADDRESS_IO_MASK, 0 \
                                ); \
                } \
        } 
#define SETPROC_OPS(entry, fops) (entry)->ops = &(inode_##fops)

static struct file_operations proc_statsdelta_ops;
static struct inode_operations inode_proc_statsdelta_ops = {
        &proc_statsdelta_ops};

static struct file_operations proc_stats_ops;
static struct inode_operations inode_proc_stats_ops = {
	&proc_stats_ops};

static struct file_operations proc_status_ops;
static struct inode_operations inode_proc_status_ops = {
	&proc_status_ops};

static struct file_operations proc_SSID_ops;
static struct inode_operations inode_proc_SSID_ops = {
	&proc_SSID_ops};

static struct file_operations proc_APList_ops;
static struct inode_operations inode_proc_APList_ops = {
	&proc_APList_ops};

static struct file_operations proc_BSSList_ops;
static struct inode_operations inode_proc_BSSList_ops = {
	&proc_BSSList_ops};

static struct file_operations proc_config_ops;
static struct inode_operations inode_proc_config_ops = {
	&proc_config_ops};

static struct file_operations proc_wepkey_ops;
static struct inode_operations inode_proc_wepkey_ops = {
	&proc_wepkey_ops};
#endif
#endif

#ifndef ARPHRD_IEEE80211
#define ARPHRD_IEEE80211 801
#endif

#if LINUX_VERSION_CODE <= 0x20409
#ifdef min
#undef min
#endif
#define min(x,y) (((x)<(y))?x:y)
#endif

#ifndef MODULE_LICENSE
#define MODULE_LICENSE(x)
#endif
