/* rt2x00.h * * Copyright (C) 2004 - 2005 rt2x00-2.0.0-b3 SourceForge Project * * 2006 rtnet adaption by Daniel Gregorek * * * 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 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. */ /* Module: rt2x00 Abstract: rt2x00 global information. Supported chipsets: RT2560 */ #ifndef RT2X00_H #define RT2X00_H #include #include #include #include #define MAX_UNITS 2 /* * Module information. */ #define DRV_NAME "rt2x00" #define DRV_VERSION "0.1" #define DRV_AUTHOR "Daniel Gregorek " //#define CONFIG_RT2X00_DEBUG /* * Debug defines. * The debug variable will be exported by the device specific module. * For this reason this variable must be set to extern to make it accessible * to the core module as well. */ #ifdef CONFIG_RT2X00_DEBUG extern int rt2x00_debug_level; #define DEBUG_PRINTK(__message...) \ do { \ rtdm_printk(__message); \ } while (0) #else /* CONFIG_RT2X00_DEBUG */ #define DEBUG_PRINTK(__message...) \ do { \ } while (0) #endif /* CONFIG_RT2X00_DEBUG */ /* * Various debug levels. * PANIC and ERROR indicates serious problems within the module, * these should never be ignored and thus we will always print the message. */ #define PANIC(__message, __args...) \ rtdm_printk(KERN_PANIC DRV_NAME "->%s: Panic - " __message, \ __FUNCTION__, ##__args); #define ERROR(__message, __args...) \ rtdm_printk(KERN_ERR DRV_NAME "->%s: Error - " __message, \ __FUNCTION__, ##__args); #define WARNING(__message, __args...) \ rtdm_printk(KERN_WARNING DRV_NAME "->%s: Warning - " __message, \ __FUNCTION__, ##__args); #define NOTICE(__message, __args...) \ rtdm_printk(KERN_NOTICE DRV_NAME "->%s: Notice - " __message, \ __FUNCTION__, ##__args); #define INFO(__message, __args...) \ rtdm_printk(KERN_INFO DRV_NAME "->%s: Info - " __message, \ __FUNCTION__, ##__args); #define DEBUG(__message, __args...) \ DEBUG_PRINTK(KERN_DEBUG DRV_NAME "->%s: Debug - " __message, \ __FUNCTION__, ##__args); /* * RT2x00 ring types. */ /* * Ring names. */ #define RING_RX 0x01 /* Ring used for receiving packets. */ #define RING_TX 0x02 /* Ring used for transmitting normal packets. */ /* * Ring sizes. */ #define DATA_FRAME_SIZE 2432 #define MGMT_FRAME_SIZE 256 /* * RT2x00 xmit flags. */ #define XMIT_IFS_SIFS 0x0001 #define XMIT_IFS_BACKOFF 0x0002 #define XMIT_IFS_NEW_BACKOFF 0x0004 #define XMIT_IFS_NONE 0x0008 #define XMIT_NEW_SEQUENCE 0x0010 #define XMIT_ACK 0x0020 #define XMIT_TIMESTAMP 0x0040 #define XMIT_RTS 0x0080 #define XMIT_OFDM 0x0100 #define XMIT_LONG_RETRY 0x0200 #define XMIT_MORE_FRAGS 0x0400 #define XMIT_SHORT_PREAMBLE 0x0800 #define XMIT_START 0x1000 /* * RT2x00 Statistics flags. */ #define STATS_TX_RESULT 0x01 #define STATS_TX_RETRY_COUNT 0x02 #define STATS_RX_CRC 0x10 #define STATS_RX_PHYSICAL 0x20 #define STATS_RX_QUALITY 0x40 #define STATS_RX_DROP 0x80 /* * TX result flags. */ #define TX_SUCCESS 0 #define TX_SUCCESS_RETRY 1 #define TX_FAIL_RETRY 2 #define TX_FAIL_INVALID 3 #define TX_FAIL_OTHER 4 /* * Channel type defines. */ #define CHANNEL_OFDM 0x01 #define CHANNEL_UNII_LOW 0x02 #define CHANNEL_HIPERLAN2 0x04 #define CHANNEL_UNII_HIGH 0x08 #define CHANNEL_OFDM_MIN 1 #define CHANNEL_OFDM_MAX 14 #define CHANNEL_UNII_LOW_MIN 36 #define CHANNEL_UNII_LOW_MAX 64 #define CHANNEL_HIPERLAN2_MIN 100 #define CHANNEL_HIPERLAN2_MAX 140 #define CHANNEL_UNII_HIGH_MIN 149 #define CHANNEL_UNII_HIGH_MAX 161 /* * Device 802.11abg capabilities. */ static struct _rt2x00_capabilities { u8 txpower[6]; u8 bitrate[12]; } __attribute__ ((packed)) capabilities = { /* * tx-power. */ .txpower = { 3, 12, 25, 50, 75, 100, }, /* * Bitrates */ .bitrate = { 2, 4, 11, 22, /* CCK. */ 12, 18, 24, 36, 48, 72, 96, 108, /* OFDM. */ }, }; struct _rt2x00_config { u8 config_flags; #define CONFIG_DROP_BCAST 0x0001 #define CONFIG_DROP_MCAST 0x0002 #define CONFIG_AUTORESP 0x0004 u8 antenna_tx; u8 antenna_rx; u8 bssid[ETH_ALEN]; u8 short_retry; u8 long_retry; u8 channel; u8 bitrate; /* 0.5Mbit/sec */ u8 txpower; /* % */ u8 bbpsens; /* * LED status */ u8 led_status; u16 __pad2; /* For alignment only. */ /* * Duration values in us. */ u8 plcp; u8 sifs; u8 slot_time; /* * Configuration values that have to be updated to device. */ u16 update_flags; #define UPDATE_ALL_CONFIG 0xffff #define UPDATE_BSSID 0x0001 #define UPDATE_PACKET_FILTER 0x0002 #define UPDATE_CHANNEL 0x0004 #define UPDATE_BITRATE 0x0008 #define UPDATE_RETRY 0x0010 #define UPDATE_TXPOWER 0x0020 #define UPDATE_ANTENNA 0x0040 #define UPDATE_DURATION 0x0080 #define UPDATE_PREAMBLE 0x0100 #define UPDATE_AUTORESP 0x0200 #define UPDATE_LED_STATUS 0x0400 #define UPDATE_BBPSENS 0x0800 } __attribute__((packed)); struct _rt2x00_core { /* * RT2x00 device status flags (atomic read/write access). */ unsigned long flags; #define DEVICE_ENABLED 0 /* Device has been opened. */ #define DEVICE_AWAKE 1 /* Device is not suspended. */ #define DEVICE_RADIO_ON 2 /* Device antenna is enabled. */ #define DEVICE_CONFIG_UPDATE 3 /* Device is updating configuration. */ /* * Device handler. */ struct _rt2x00_dev_handler *handler; /* * RTnet device we belong to. */ struct rtnet_device *rtnet_dev; /* * RTwlan stack structure. */ struct rtwlan_device *rtwlan_dev; /* * Device configuration. */ struct _rt2x00_config config; void *priv; } __attribute__((packed)); /* * Device specific handlers. */ struct _rt2x00_dev_handler { /* * Device specific module. */ struct module *dev_module; /* * Initialization handlers. */ int (*dev_probe)(struct _rt2x00_core *core, void *priv); int (*dev_remove)(struct _rt2x00_core *core); /* * Radio control. */ int (*dev_radio_on)(struct _rt2x00_core *core); int (*dev_radio_off)(struct _rt2x00_core *core); /* * Configuration handlers. */ int (*dev_update_config)(struct _rt2x00_core *core, u16 update_flags); /* * xmit handler. */ int (*dev_xmit_packet)(struct _rt2x00_core *core, struct rtskb *rtskb, u16 rate, u16 xmit_flags); /* * Handler for direct access to register from core. */ int (*dev_register_access)(struct _rt2x00_core *core, int request, u32 address, u32 *value); } __attribute__((packed)); static inline void *rt2x00_priv(const struct _rt2x00_core *core) { return core->priv; } /* * Duration calculations * The rate variable passed is: 2 * real_rate (in Mb/s). * Therefore length has to be multiplied with 8 to convert bytes to bits and mulltiply the length * with 2 to compensate for the difference between real_rate and the rate variable. */ #define ACK_SIZE 14 #define IEEE80211_HEADER 24 static inline u16 get_duration(const unsigned int size, const u8 rate) { return ((size * 8 * 2) / rate); } static inline u16 get_duration_res(const unsigned int size, const u8 rate) { return ((size * 8 * 2) % rate); } static inline u16 get_preamble(const struct _rt2x00_config *config) { return 144; } /* * Register handlers. * We store the position of a register field inside a field structure, * This will simplify the process of setting and reading a certain field * inside the register. */ struct _rt2x00_field16 { u16 bit_offset; u16 bit_mask; } __attribute__((packed)); struct _rt2x00_field32 { u32 bit_offset; u32 bit_mask; } __attribute__((packed)); #define FIELD16(__offset, __mask) \ ((struct _rt2x00_field16){ (__offset), (__mask) }) #define FIELD32(__offset, __mask) \ ((struct _rt2x00_field32){ (__offset), (__mask) }) static inline void rt2x00_set_field32(u32 *reg, const struct _rt2x00_field32 field, const u32 value) { *reg &= cpu_to_le32(~(field.bit_mask)); *reg |= cpu_to_le32((value << field.bit_offset) & field.bit_mask); } static inline void rt2x00_set_field32_nb(u32 *reg, const struct _rt2x00_field32 field, const u32 value) { *reg &= ~(field.bit_mask); *reg |= (value << field.bit_offset) & field.bit_mask; } static inline u32 rt2x00_get_field32(const u32 reg, const struct _rt2x00_field32 field) { return (le32_to_cpu(reg) & field.bit_mask) >> field.bit_offset; } static inline u32 rt2x00_get_field32_nb(const u32 reg, const struct _rt2x00_field32 field) { return (reg & field.bit_mask) >> field.bit_offset; } static inline void rt2x00_set_field16(u16 *reg, const struct _rt2x00_field16 field, const u16 value) { *reg &= cpu_to_le16(~(field.bit_mask)); *reg |= cpu_to_le16((value << field.bit_offset) & field.bit_mask); } static inline void rt2x00_set_field16_nb(u16 *reg, const struct _rt2x00_field16 field, const u16 value) { *reg &= ~(field.bit_mask); *reg |= (value << field.bit_offset) & field.bit_mask; } static inline u16 rt2x00_get_field16(const u16 reg, const struct _rt2x00_field16 field) { return (le16_to_cpu(reg) & field.bit_mask) >> field.bit_offset; } static inline u16 rt2x00_get_field16_nb(const u16 reg, const struct _rt2x00_field16 field) { return (reg & field.bit_mask) >> field.bit_offset; } /* * rf register sructure for channel selection. */ struct _rf_channel { u32 rf1; u32 rf2; u32 rf3; u32 rf4; } __attribute__((packed)); /* * Chipset identification * The chipset on the device is composed of a RT and RF chip. * The chipset combination is important for determining device capabilities. */ struct _rt2x00_chip { u16 rt; u16 rf; } __attribute__((packed)); /* * Set chipset data. * Some rf values for RT2400 devices are equal to rf values for RT2500 devices. * To prevent problems, all rf values will be masked to clearly seperate each chipset. */ static inline void set_chip(struct _rt2x00_chip *chipset, const u16 rt, const u16 rf) { INFO("Chipset detected - rt: %04x, rf: %04x.\n", rt, rf); chipset->rt = rt; chipset->rf = rf | (chipset->rt & 0xff00); } static inline char rt2x00_rt(const struct _rt2x00_chip *chipset, const u16 chip) { return (chipset->rt == chip); } static inline char rt2x00_rf(const struct _rt2x00_chip *chipset, const u16 chip) { return (chipset->rf == chip); } static inline u16 rt2x00_get_rf(const struct _rt2x00_chip *chipset) { return chipset->rf; } /* * _data_ring * Data rings are used by the device to send and receive packets. * The data_addr is the base address of the data memory. * Device specifice information is pointed to by the priv pointer. * The index values may only be changed with the functions ring_index_inc() * and ring_index_done_inc(). */ struct _data_ring { /* * Base address of packet ring. */ dma_addr_t data_dma; void *data_addr; /* * Private device specific data. */ void *priv; struct _rt2x00_core *core; /* * Current index values. */ u8 index; u8 index_done; /* * Ring type set with RING_* define. */ u8 ring_type; /* * Number of entries in this ring. */ u8 max_entries; /* * Size of packet and descriptor in bytes. */ u16 entry_size; u16 desc_size; /* * Total allocated memory size. */ u32 mem_size; } __attribute__((packed)); /* * Number of entries in a packet ring. */ #define RX_ENTRIES 8 #define TX_ENTRIES 8 #define ATIM_ENTRIES 1 #define PRIO_ENTRIES 2 #define BEACON_ENTRIES 1 /* * Initialization and cleanup routines. */ static inline void rt2x00_init_ring(struct _rt2x00_core *core, struct _data_ring *ring, const u8 ring_type, const u16 max_entries, const u16 entry_size, const u16 desc_size) { ring->core = core; ring->index = 0; ring->index_done = 0; ring->ring_type = ring_type; ring->max_entries = max_entries; ring->entry_size = entry_size; ring->desc_size = desc_size; ring->mem_size = ring->max_entries * (ring->desc_size + ring->entry_size); } static inline void rt2x00_deinit_ring(struct _data_ring *ring) { ring->core = NULL; ring->index = 0; ring->index_done = 0; ring->ring_type = 0; ring->max_entries = 0; ring->entry_size = 0; ring->desc_size = 0; ring->mem_size = 0; } /* * Ring index manipulation functions. */ static inline void rt2x00_ring_index_inc(struct _data_ring *ring) { ring->index = (++ring->index < ring->max_entries) ? ring->index : 0; } static inline void rt2x00_ring_index_done_inc(struct _data_ring *ring) { ring->index_done = (++ring->index_done < ring->max_entries) ? ring->index_done : 0; } static inline void rt2x00_ring_clear_index(struct _data_ring *ring) { ring->index = 0; ring->index_done = 0; } static inline u8 rt2x00_ring_empty(struct _data_ring *ring) { return ring->index_done == ring->index; } static inline u8 rt2x00_ring_free_entries(struct _data_ring *ring) { if (ring->index >= ring->index_done) return ring->max_entries - (ring->index - ring->index_done); else return ring->index_done - ring->index; } /* * Return PLCP value matching the rate. * PLCP values according to ieee802.11a-1999 p.14. */ static inline u8 rt2x00_get_plcp(const u8 rate) { u8 counter = 0x00; u8 plcp[12] = { 0x00, 0x01, 0x02, 0x03, /* CCK. */ 0x0b, 0x0f, 0x0a, 0x0e, 0x09, 0x0d, 0x08, 0x0c, /* OFDM. */ }; for (; counter < 12; counter++) { if (capabilities.bitrate[counter] == rate) return plcp[counter]; } return 0xff; } #define OFDM_CHANNEL(__channel) \ ((__channel) >= CHANNEL_OFDM_MIN && (__channel) <= CHANNEL_OFDM_MAX) #define UNII_LOW_CHANNEL(__channel) \ ((__channel) >= CHANNEL_UNII_LOW_MIN && \ (__channel) <= CHANNEL_UNII_LOW_MAX) #define HIPERLAN2_CHANNEL(__channel) \ ((__channel) >= CHANNEL_HIPERLAN2_MIN && \ (__channel) <= CHANNEL_HIPERLAN2_MAX) #define UNII_HIGH_CHANNEL(__channel) \ ((__channel) >= CHANNEL_UNII_HIGH_MIN && \ (__channel) <= CHANNEL_UNII_HIGH_MAX) /* * Return the index value of the channel starting from the first channel of the range. * Where range can be OFDM, UNII (low), HiperLAN2 or UNII (high). */ static inline int rt2x00_get_channel_index(const u8 channel) { if (OFDM_CHANNEL(channel)) return (channel - 1); if (channel % 4) return -EINVAL; if (UNII_LOW_CHANNEL(channel)) return ((channel - CHANNEL_UNII_LOW_MIN) / 4); else if (HIPERLAN2_CHANNEL(channel)) return ((channel - CHANNEL_HIPERLAN2_MIN) / 4); else if (UNII_HIGH_CHANNEL(channel)) return ((channel - CHANNEL_UNII_HIGH_MIN) / 4); return -EINVAL; } /* * RT2x00 core module functions that can be used in the device specific modules. */ extern struct rtnet_device * rt2x00_core_probe(struct _rt2x00_dev_handler *handler, void *priv, u32 sizeof_dev); extern void rt2x00_core_remove(struct rtnet_device *rtnet_dev); #endif