blob: e20e619e2dec42345159c059e6031043894ed2e6 [file] [log] [blame]
/*
Copyright 2004, 2005 Jean-Baptiste Note
This file is part of prism54usb.
prism54usb 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 of the License, or
(at your option) any later version.
prism54usb 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 prism54usb; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _HAVE_ISL_SM_H_
#define _HAVE_ISL_SM_H_
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/list.h>
#include <linux/firmware.h>
#ifdef MADWIFI
#include <linux/version.h>
#include "net80211/if_media.h"
#include "net80211/ieee80211_var.h"
#else
#include <net/ieee80211softmac.h>
#define PCIUART 1
#endif /* MADWIFI */
#include "islsm_protocol.h"
#include "islsm_alloc.h"
#include "islsm_uart.h"
#include "islsm_bra.h"
enum islsm_state {
/* in this state we just received the plug event */
ISLSM_PROBE = 0,
/* communication bridge is ok (usb, pci) */
ISLSM_BRIDGE_OK,
/* rom is ok -- the uart protocol is ok */
ISLSM_ROM_OK,
/* firmware is being uploaded */
ISLSM_FW_UPLOAD,
/* freemac has been uploaded and is ok */
ISLSM_FREEMAC,
/* softmac has been uploaded and is ok */
ISLSM_SOFTMAC,
};
/* callback typedefs */
typedef int (*islsm_tx_t) (struct sk_buff *);
struct islsm {
/* intersil-firmware specific state machine
* variables
*/
/* islsm instances management */
unsigned minor;
unsigned islsm_state;
/*
* Parameters set by the BRA parsing
*/
/* LMAC type */
enum islsm_fw_type fw_type;
/* LMAC memory mapping */
/* Generic LMac framespace */
uint32_t frame_mem_start;
uint32_t frame_mem_end;
/* specialized LMac framespace */
/* reserved space for control frames */
uint32_t txframe_mem_start;
uint32_t txframe_mem_end;
/* reserved space for rx frames */
uint32_t rxframe_mem_start;
/* memory allocator proper */
mem_descr_t memory;
/* Rate index table */
/* The frame format uses indexes in a table for specifying the
* sending rate of various frames. This rate table is present in
* the BRA. We mirror it here for use as a lookup table */
char bra_rate_table[ISLSM_BRA_RATE_TABLE_SIZE];
/*
* Other parameters (sort this mess)
*/
/* firmware name */
#define ISLSM_FW_NAME_LEN 33
char firmware_name[ISLSM_FW_NAME_LEN + 1];
/* LEDs state */
unsigned led_mode;
unsigned led_setting;
/* reserve this much space ahead of the skb for the needs of the
hardware tx queues */
size_t device_tx_header_space;
/* sm_tx_header_space to be added */
/* sm_rx_header_space to be added (for monitor mode) */
enum islsm_versions device_version;
/* signalled when particular states in the configuration have
been reached : init interrupt, then mgmt readback end */
struct completion dev_init_comp;
int wait_flag;
struct sm_p smpar;
short soft_rxfilter;
u8 filter_rateset[8];
/*
* Parameters and data set by parsing of the EEPROM contents
*/
/* number of rates defined in the readback */
uint8_t pa_points_per_curve;
uint8_t *eeprom;
size_t eeprom_size;
size_t pda_offset;
size_t pda_length;
/* FIXME : these arrays are *huge* (255 elements) -- we should
* get rid of them */
#ifdef MADWIFI
struct wlan_pda_output_limits_channel_rev0_s output_pwr_limits[IEEE80211_CHAN_MAX];
struct fw_cal_data_sample finfo4[IEEE80211_CHAN_MAX][ISLSM_POINTS_PER_CURVE];
struct wlan_pda_iq_autocal_s finfo6[IEEE80211_CHAN_MAX];
#else /* MADWIFI */
struct wlan_pda_output_limits_channel_rev0_s output_pwr_limits[ISLSM_NR_CHANNELS + 1];
struct fw_cal_data_sample finfo4[ISLSM_NR_CHANNELS + 1][ISLSM_POINTS_PER_CURVE];
struct wlan_pda_iq_autocal_s finfo6[ISLSM_NR_CHANNELS + 1];
#endif
unsigned int last_chan;
#ifdef MADWIFI
struct ieee80211com sc_ic;
struct ieee80211_beacon_offsets islsm_boff;
int (*ieee80211_newstate) (struct ieee80211com *,
enum ieee80211_state,
int);
struct timer_list scan_ch; /* AP scan timer */
#endif /* MADWIFI */
/* struct timer_list stats_update; */
struct net_device_stats statistics;
#ifdef CONFIG_WLAN_80211
struct iw_statistics iwstatistics;
#endif /* CONFIG_WLAN_80211 */
/* device-specific state machine and callbacks
We handle three types of devices :
- usb first generation
- usb second generation
- pci devices
These hooks are in no mean set in stone; they are here for
experimentation and will give way to a cleaner approach once
we have a general picture of how things work.
*/
/* boots the device */
int (*isl_boot) (struct net_device *);
int (*isl_stop) (struct net_device *);
/* transmits the data in the skb to the lmac */
islsm_tx_t isl_tx;
/* device operations */
int (*isl_romboot) (struct islsm *);
int (*isl_load_fw) (struct islsm *,
const struct firmware *);
/* uart structure and callbacks */
#ifdef PCIUART
uart_instance_t uart;
void (*uart_prot_init) (struct islsm *);
void (*uart_cts) (struct islsm *);
void (*uart_prot_exit) (struct islsm *);
#endif /* PCIUART */
/* low-level stuff */
/* read and write from the pci side */
uint32_t (*isl_read_pcireg) (struct islsm *,
uint32_t address);
void (*isl_write_pcireg) (struct islsm *,
uint32_t value,
uint32_t address);
uint32_t (*isl_read_devmem) (struct islsm *,
uint32_t address);
void (*isl_write_devmem) (struct islsm *,
uint32_t value,
uint32_t address);
/*
* It should not be needed as we can fetch it with an offsetof
* macro. But this is safer in case allocations ever get out-of-line.
*/
struct net_device *netdev;
#ifndef MADWIFI
struct ieee80211_device *ieee;
struct ieee80211softmac_device *softmac;
#endif
/* This is the structure below us, filled with p54u or islpci
* device reference */
/* This must be the last item so that it points to the data
* allocated beyond this structure by alloc_islsm */
u8 priv[];
};
/*
* These functions are modelled after the netdev and ieee80211 ones.
* The train of structs for softmac:
* [netdev][ieee80211][ieee80211softmac][islsm][p54u]
*/
#ifdef MADWIFI
#define NETDEV_OF_ISLSM(device) ((device)->netdev)
#define ISLSM_OF_NETDEV(device) ((struct islsm *) netdev_priv(device))
#define SET_NETDEV(device,netdevice) ((device)->netdev = (netdevice))
extern inline void *islsm_priv(struct net_device *dev) {
return ((struct islsm *)netdev_priv(dev))->priv;
}
#else
#define NETDEV_OF_ISLSM(device) ((device)->netdev)
#define ISLSM_OF_NETDEV(device) ((struct islsm *) ieee80211softmac_priv(device))
static inline void *islsm_priv(struct net_device *dev) {
return ((struct islsm *)ieee80211softmac_priv(dev))->priv;
}
#endif /* MADWIFI */
/*
* Control block used by islsm
*/
struct islsm_cb {
struct islsm_alloc_cb alloc;
};
struct net_device *alloc_islsm(int sizeof_priv);
void free_islsm(struct net_device *dev);
int register_islsm(struct net_device *netdev);
void unregister_islsm(struct net_device *netdev);
int islsm_mode_set_filter(struct net_device *netdev, int mode);
extern int islsm_wait_timeout(struct islsm *islsm,
unsigned int delay);
/* now the helper functions, for sending packets */
int islsm_outofband_msg(struct islsm *islsm,
void *buf, size_t size);
int islsm_stats_readback(struct islsm *islsm);
void islsm_make_control_led(struct islsm *islsm,
char *buf, uint16_t mode,
uint16_t perm_setting,
uint16_t temp_setting,
uint16_t duration);
void islsm_make_freequeue(struct islsm *islsm,
char *buf, uint8_t queue_id);
int islsm_set_filter(struct islsm *islsm,
uint16_t filter_type,
const uint8_t *bssid, uint16_t magic2,
uint32_t magic3, uint16_t magic8,
uint16_t magic9);
int islsm_freq_change(struct islsm *islsm,
uint16_t channel, uint16_t freq,
uint16_t magic1, uint16_t magic2);
int islsm_data_tx(struct islsm *islsm, struct sm_tx_p *txp,
struct sk_buff *skb);
int islsm_eeprom_readback(struct islsm *islsm);
int islsm_led_perm(struct islsm *islsm,
uint16_t mode, uint16_t perm_setting);
int islsm_led_temp(struct islsm *islsm,
uint16_t temp_setting, unsigned ms);
int islsm_ping_device(struct islsm *islsm, unsigned length);
/* now the helper functions, for receiving packets */
void islsm_data_input(struct sk_buff *skb);
void islsm_bootup_input(struct sk_buff *skb);
int islsm_parse_eeprom(struct islsm *islsm);
int islsm_request_firmware(const struct firmware **fw,
struct islsm *device);
/* protocol settings */
void islsm_params_init(struct islsm *islsm);
/* helper function to get rid of -- replace with a standard one from one
* of the stacks */
static inline unsigned int
islsm_ref_to_chan(unsigned int ref)
{
/* FIXME : only works for the B/G band, we now need it for the A
band */
#ifdef MADWIFI
return ieee80211_mhz2ieee(ref, IEEE80211_CHAN_2GHZ);
#else
/* kludgy as hell */
unsigned int out;
#define ISLSM_REF_CHAN0 0x0967
if (ref <= ISLSM_REF_CHAN0) {
printk(KERN_ERR
"%s: Problem requesting channel of ref %i : too small\n",
"islsm", ref);
return 0;
}
out = (ref - ISLSM_REF_CHAN0) / 5;
if (out > 14) {
if (ref == 2484)
return 14;
printk(KERN_ERR
"%s: Problem requesting channel of ref %i : "
"channel %i too big\n", "islsm", ref, out);
return 0;
}
return out;
#undef ISLSM_REF_CHAN0
#endif /* MADWIFI */
}
int islsm_chan_to_freq(unsigned int chan);
unsigned int islsm_freq_to_chan(int freq);
/* Helper function for the hardware stacks, to be used to free a
TX skb successfully transmitted to the umac */
static inline void
islsm_txskb_free(struct sk_buff *skb) {
struct net_device *netdev = skb->dev;
struct islsm *islsm = ISLSM_OF_NETDEV(netdev);
uint32_t lmac_addr = LMAC_ADDR_OF_SKB(skb);
unsigned flags = LMAC_ALLOC_FLAGS(skb);
if (flags & ISLSM_ALLOC_FREE_WHEN_SUBMITTED)
islsm_free(&islsm->memory, lmac_addr);
dev_kfree_skb_irq(skb);
}
#endif /* _HAVE_ISL_SM_H_ */