]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-4965-commands.h
Merge git://git.infradead.org/battery-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / iwlwifi / iwl-4965-commands.h
index 575a065f8e5c4a16949673c0830650022e3c6659..3bcd107e2d71bf441c2b3840043ceffe0048525f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -30,7 +30,7 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *****************************************************************************/
+/*
+ * Please use this file (iwl-4965-commands.h) only for uCode API definitions.
+ * Please use iwl-4965-hw.h for hardware-related definitions.
+ * Please use iwl-4965.h for driver implementation definitions.
+ */
 
 #ifndef __iwl4965_commands_h__
 #define __iwl4965_commands_h__
@@ -79,6 +84,9 @@ enum {
        REPLY_REMOVE_STA = 0x19,        /* not used */
        REPLY_REMOVE_ALL_STA = 0x1a,    /* not used */
 
+       /* Security */
+       REPLY_WEPKEY = 0x20,
+
        /* RX, TX, LEDs */
        REPLY_TX = 0x1c,
        REPLY_RATE_SCALE = 0x47,        /* 3945 only */
@@ -115,10 +123,10 @@ enum {
        REPLY_TX_PWR_TABLE_CMD = 0x97,
        MEASURE_ABORT_NOTIFICATION = 0x99,      /* not used */
 
-       /* BT config command */
+       /* Bluetooth device coexistance config command */
        REPLY_BT_CONFIG = 0x9b,
 
-       /* 4965 Statistics */
+       /* Statistics */
        REPLY_STATISTICS_CMD = 0x9c,
        STATISTICS_NOTIFICATION = 0x9d,
 
@@ -134,7 +142,7 @@ enum {
        REPLY_PHY_CALIBRATION_CMD = 0xb0,
        REPLY_RX_PHY_CMD = 0xc0,
        REPLY_RX_MPDU_CMD = 0xc1,
-       REPLY_4965_RX = 0xc3,
+       REPLY_RX = 0xc3,
        REPLY_COMPRESSED_BA = 0xc5,
        REPLY_MAX = 0xff
 };
@@ -142,29 +150,46 @@ enum {
 /******************************************************************************
  * (0)
  * Commonly used structures and definitions:
- * Command header, rate_n_flags
+ * Command header, rate_n_flags, txpower
  *
  *****************************************************************************/
 
+/* iwl_cmd_header flags value */
 #define IWL_CMD_FAILED_MSK 0x40
 
-struct iwl4965_cmd_header {
-       u8 cmd;
-       u8 flags;
-       /* We have 15 LSB to use as we please (MSB indicates
-        * a frame Rx'd from the HW).  We encode the following
-        * information into the sequence field:
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+       u8 cmd;         /* Command ID:  REPLY_RXON, etc. */
+       u8 flags;       /* IWL_CMD_* */
+       /*
+        * The driver sets up the sequence number to values of its chosing.
+        * uCode does not use this value, but passes it back to the driver
+        * when sending the response to each driver-originated command, so
+        * the driver can match the response to the command.  Since the values
+        * don't get used by uCode, the driver may set up an arbitrary format.
         *
-        *  0:7    index in fifo
-        *  8:13   fifo selection
-        * 14:14   bit indicating if this packet references the 'extra'
-        *         storage at the end of the memory queue
-        * 15:15   (Rx indication)
+        * There is one exception:  uCode sets bit 15 when it originates
+        * the response/notification, i.e. when the response/notification
+        * is not a direct response to a command sent by the driver.  For
+        * example, uCode issues REPLY_3945_RX when it sends a received frame
+        * to the driver; it is not a direct response to any driver command.
         *
+        * The Linux driver uses the following format:
+        *
+        *  0:7    index/position within Tx queue
+        *  8:13   Tx queue selection
+        * 14:14   driver sets this to indicate command is in the 'huge'
+        *         storage at the end of the command buffers, i.e. scan cmd
+        * 15:15   uCode sets this in uCode-originated response/notification
         */
        __le16 sequence;
 
-       /* command data follows immediately */
+       /* command or response/notification data follows immediately */
        u8 data[0];
 } __attribute__ ((packed));
 
@@ -172,7 +197,7 @@ struct iwl4965_cmd_header {
  * 4965 rate_n_flags bit fields
  *
  * rate_n_flags format is used in following 4965 commands:
- *  REPLY_4965_RX (response only)
+ *  REPLY_RX (response only)
  *  REPLY_TX (both command and response)
  *  REPLY_TX_LINK_QUALITY_CMD
  *
@@ -213,28 +238,28 @@ struct iwl4965_cmd_header {
 #define RATE_MCS_HT_DUP_POS 5
 #define RATE_MCS_HT_DUP_MSK 0x20
 
-/* (1) HT format, (0) legacy format in bits 7:0 */
+/* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */
 #define RATE_MCS_FLAGS_POS 8
 #define RATE_MCS_HT_POS 8
 #define RATE_MCS_HT_MSK 0x100
 
-/* (1) CCK, (0) OFDM.  HT (bit 8) must be "0" for this bit to be valid */
+/* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be "0" for this bit to be valid */
 #define RATE_MCS_CCK_POS 9
 #define RATE_MCS_CCK_MSK 0x200
 
-/* (1) Use Green Field preamble */
+/* Bit 10: (1) Use Green Field preamble */
 #define RATE_MCS_GF_POS 10
 #define RATE_MCS_GF_MSK 0x400
 
-/* (1) Use 40Mhz FAT channel width, (0) use 20 MHz legacy channel width */
+/* Bit 11: (1) Use 40Mhz FAT chnl width, (0) use 20 MHz legacy chnl width */
 #define RATE_MCS_FAT_POS 11
 #define RATE_MCS_FAT_MSK 0x800
 
-/* (1) Duplicate data on both 20MHz channels.  FAT (bit 11) must be set. */
+/* Bit 12: (1) Duplicate data on both 20MHz chnls.  FAT (bit 11) must be set. */
 #define RATE_MCS_DUP_POS 12
 #define RATE_MCS_DUP_MSK 0x1000
 
-/* (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
+/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
 #define RATE_MCS_SGI_POS 13
 #define RATE_MCS_SGI_MSK 0x2000
 
@@ -244,11 +269,69 @@ struct iwl4965_cmd_header {
  *          10 B active, A inactive
  *          11 Both active
  */
-#define RATE_MCS_ANT_A_POS     14
-#define RATE_MCS_ANT_B_POS     15
-#define RATE_MCS_ANT_A_MSK     0x4000
-#define RATE_MCS_ANT_B_MSK     0x8000
-#define RATE_MCS_ANT_AB_MSK    0xc000
+#define RATE_MCS_ANT_POS       14
+#define RATE_MCS_ANT_A_MSK     0x04000
+#define RATE_MCS_ANT_B_MSK     0x08000
+#define RATE_MCS_ANT_AB_MSK    0x0C000
+
+
+/**
+ * struct iwl4965_tx_power - txpower format used in REPLY_SCAN_CMD
+ *
+ * Scan uses only one transmitter, so only one analog/dsp gain pair is needed.
+ */
+struct iwl4965_tx_power {
+       u8 tx_gain;             /* gain for analog radio */
+       u8 dsp_atten;           /* gain for DSP */
+} __attribute__ ((packed));
+
+#define POWER_TABLE_NUM_ENTRIES                        33
+#define POWER_TABLE_NUM_HT_OFDM_ENTRIES                32
+#define POWER_TABLE_CCK_ENTRY                  32
+
+/**
+ * union iwl4965_tx_power_dual_stream
+ *
+ * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Use __le32 version (struct tx_power_dual_stream) when building command.
+ *
+ * Driver provides radio gain and DSP attenuation settings to device in pairs,
+ * one value for each transmitter chain.  The first value is for transmitter A,
+ * second for transmitter B.
+ *
+ * For SISO bit rates, both values in a pair should be identical.
+ * For MIMO rates, one value may be different from the other,
+ * in order to balance the Tx output between the two transmitters.
+ *
+ * See more details in doc for TXPOWER in iwl-4965-hw.h.
+ */
+union iwl4965_tx_power_dual_stream {
+       struct {
+               u8 radio_tx_gain[2];
+               u8 dsp_predis_atten[2];
+       } s;
+       u32 dw;
+};
+
+/**
+ * struct tx_power_dual_stream
+ *
+ * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Same format as iwl_tx_power_dual_stream, but __le32
+ */
+struct tx_power_dual_stream {
+       __le32 dw;
+} __attribute__ ((packed));
+
+/**
+ * struct iwl4965_tx_power_db
+ *
+ * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl4965_tx_power_db {
+       struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
+} __attribute__ ((packed));
 
 
 /******************************************************************************
@@ -261,45 +344,120 @@ struct iwl4965_cmd_header {
 #define INITIALIZE_SUBTYPE    (9)
 
 /*
- * REPLY_ALIVE = 0x1 (response only, not a command)
+ * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "initialize alive" notification once the initialization
+ * uCode image has completed its work, and is ready to load the runtime image.
+ * This is the *first* "alive" notification that the driver will receive after
+ * rebooting uCode; the "initialize" alive is indicated by subtype field == 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * For 4965, this notification contains important calibration data for
+ * calculating txpower settings:
+ *
+ * 1)  Power supply voltage indication.  The voltage sensor outputs higher
+ *     values for lower voltage, and vice versa.
+ *
+ * 2)  Temperature measurement parameters, for each of two channel widths
+ *     (20 MHz and 40 MHz) supported by the radios.  Temperature sensing
+ *     is done via one of the receiver chains, and channel width influences
+ *     the results.
+ *
+ * 3)  Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation,
+ *     for each of 5 frequency ranges.
  */
-struct iwl4965_alive_resp {
+struct iwl4965_init_alive_resp {
        u8 ucode_minor;
        u8 ucode_major;
        __le16 reserved1;
        u8 sw_rev[8];
        u8 ver_type;
-       u8 ver_subtype;
+       u8 ver_subtype;         /* "9" for initialize alive */
        __le16 reserved2;
        __le32 log_event_table_ptr;
        __le32 error_event_table_ptr;
        __le32 timestamp;
        __le32 is_valid;
+
+       /* calibration values from "initialize" uCode */
+       __le32 voltage;         /* signed, higher value is lower voltage */
+       __le32 therm_r1[2];     /* signed, 1st for normal, 2nd for FAT channel*/
+       __le32 therm_r2[2];     /* signed */
+       __le32 therm_r3[2];     /* signed */
+       __le32 therm_r4[2];     /* signed */
+       __le32 tx_atten[5][2];  /* signed MIMO gain comp, 5 freq groups,
+                                * 2 Tx chains */
 } __attribute__ ((packed));
 
-struct iwl4965_init_alive_resp {
+
+/**
+ * REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "alive" notification once the runtime image is ready
+ * to receive commands from the driver.  This is the *second* "alive"
+ * notification that the driver will receive after rebooting uCode;
+ * this "alive" is indicated by subtype field != 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * This response includes two pointers to structures within the device's
+ * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging:
+ *
+ * 1)  log_event_table_ptr indicates base of the event log.  This traces
+ *     a 256-entry history of uCode execution within a circular buffer.
+ *     Its header format is:
+ *
+ *     __le32 log_size;     log capacity (in number of entries)
+ *     __le32 type;         (1) timestamp with each entry, (0) no timestamp
+ *     __le32 wraps;        # times uCode has wrapped to top of circular buffer
+ *      __le32 write_index;  next circular buffer entry that uCode would fill
+ *
+ *     The header is followed by the circular buffer of log entries.  Entries
+ *     with timestamps have the following format:
+ *
+ *     __le32 event_id;     range 0 - 1500
+ *     __le32 timestamp;    low 32 bits of TSF (of network, if associated)
+ *     __le32 data;         event_id-specific data value
+ *
+ *     Entries without timestamps contain only event_id and data.
+ *
+ * 2)  error_event_table_ptr indicates base of the error log.  This contains
+ *     information about any uCode error that occurs.  For 4965, the format
+ *     of the error log is:
+ *
+ *     __le32 valid;        (nonzero) valid, (0) log is empty
+ *     __le32 error_id;     type of error
+ *     __le32 pc;           program counter
+ *     __le32 blink1;       branch link
+ *     __le32 blink2;       branch link
+ *     __le32 ilink1;       interrupt link
+ *     __le32 ilink2;       interrupt link
+ *     __le32 data1;        error-specific data
+ *     __le32 data2;        error-specific data
+ *     __le32 line;         source code line of error
+ *     __le32 bcon_time;    beacon timer
+ *     __le32 tsf_low;      network timestamp function timer
+ *     __le32 tsf_hi;       network timestamp function timer
+ *
+ * The Linux driver can print both logs to the system log when a uCode error
+ * occurs.
+ */
+struct iwl4965_alive_resp {
        u8 ucode_minor;
        u8 ucode_major;
        __le16 reserved1;
        u8 sw_rev[8];
        u8 ver_type;
-       u8 ver_subtype;
+       u8 ver_subtype;                 /* not "9" for runtime alive */
        __le16 reserved2;
-       __le32 log_event_table_ptr;
-       __le32 error_event_table_ptr;
+       __le32 log_event_table_ptr;     /* SRAM address for event log */
+       __le32 error_event_table_ptr;   /* SRAM address for error log */
        __le32 timestamp;
        __le32 is_valid;
-
-       /* calibration values from "initialize" uCode */
-       __le32 voltage;         /* signed */
-       __le32 therm_r1[2];     /* signed 1st for normal, 2nd for FAT channel */
-       __le32 therm_r2[2];     /* signed */
-       __le32 therm_r3[2];     /* signed */
-       __le32 therm_r4[2];     /* signed */
-       __le32 tx_atten[5][2];  /* signed MIMO gain comp, 5 freq groups,
-                                * 2 Tx chains */
 } __attribute__ ((packed));
 
+
 union tsf {
        u8 byte[8];
        __le16 word[4];
@@ -335,6 +493,21 @@ enum {
        RXON_DEV_TYPE_SNIFFER = 6,
 };
 
+
+#define RXON_RX_CHAIN_DRIVER_FORCE_MSK         __constant_cpu_to_le16(0x1 << 0)
+#define RXON_RX_CHAIN_VALID_MSK                        __constant_cpu_to_le16(0x7 << 1)
+#define RXON_RX_CHAIN_VALID_POS                        (1)
+#define RXON_RX_CHAIN_FORCE_SEL_MSK            __constant_cpu_to_le16(0x7 << 4)
+#define RXON_RX_CHAIN_FORCE_SEL_POS            (4)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK       __constant_cpu_to_le16(0x7 << 7)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS       (7)
+#define RXON_RX_CHAIN_CNT_MSK                  __constant_cpu_to_le16(0x3 << 10)
+#define RXON_RX_CHAIN_CNT_POS                  (10)
+#define RXON_RX_CHAIN_MIMO_CNT_MSK             __constant_cpu_to_le16(0x3 << 12)
+#define RXON_RX_CHAIN_MIMO_CNT_POS             (12)
+#define RXON_RX_CHAIN_MIMO_FORCE_MSK           __constant_cpu_to_le16(0x1 << 14)
+#define RXON_RX_CHAIN_MIMO_FORCE_POS           (14)
+
 /* rx_config flags */
 /* band & modulation selection */
 #define RXON_FLG_BAND_24G_MSK           __constant_cpu_to_le32(1 << 0)
@@ -358,6 +531,21 @@ enum {
 * (according to ON_AIR deassertion) */
 #define RXON_FLG_TSF2HOST_MSK           __constant_cpu_to_le32(1 << 15)
 
+
+/* HT flags */
+#define RXON_FLG_CTRL_CHANNEL_LOC_POS          (22)
+#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK       __constant_cpu_to_le32(0x1 << 22)
+
+#define RXON_FLG_HT_OPERATING_MODE_POS         (23)
+
+#define RXON_FLG_HT_PROT_MSK                   __constant_cpu_to_le32(0x1 << 23)
+#define RXON_FLG_FAT_PROT_MSK                  __constant_cpu_to_le32(0x2 << 23)
+
+#define RXON_FLG_CHANNEL_MODE_POS              (25)
+#define RXON_FLG_CHANNEL_MODE_MSK              __constant_cpu_to_le32(0x3 << 25)
+#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK      __constant_cpu_to_le32(0x1 << 25)
+#define RXON_FLG_CHANNEL_MODE_MIXED_MSK                __constant_cpu_to_le32(0x2 << 25)
+
 /* rx_config filter flags */
 /* accept all data frames */
 #define RXON_FILTER_PROMISC_MSK         __constant_cpu_to_le32(1 << 0)
@@ -374,8 +562,22 @@ enum {
 /* transfer to host non bssid beacons in associated state */
 #define RXON_FILTER_BCON_AWARE_MSK      __constant_cpu_to_le32(1 << 6)
 
-/*
+/**
  * REPLY_RXON = 0x10 (command, has simple generic response)
+ *
+ * RXON tunes the radio tuner to a service channel, and sets up a number
+ * of parameters that are used primarily for Rx, but also for Tx operations.
+ *
+ * NOTE:  When tuning to a new channel, driver must set the
+ *        RXON_FILTER_ASSOC_MSK to 0.  This will clear station-dependent
+ *        info within the device, including the station tables, tx retry
+ *        rate tables, and txpower tables.  Driver must build a new station
+ *        table and txpower table before transmitting anything on the RXON
+ *        channel.
+ *
+ * NOTE:  All RXONs wipe clean the internal txpower table.  Driver must
+ *        issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
+ *        regardless of whether RXON_FILTER_ASSOC_MSK is set.
  */
 struct iwl4965_rxon_cmd {
        u8 node_addr[6];
@@ -423,22 +625,6 @@ struct iwl4965_rxon_time_cmd {
        __le16 reserved;
 } __attribute__ ((packed));
 
-struct iwl4965_tx_power {
-       u8 tx_gain;             /* gain for analog radio */
-       u8 dsp_atten;           /* gain for DSP */
-} __attribute__ ((packed));
-
-#define POWER_TABLE_NUM_ENTRIES                        33
-#define POWER_TABLE_NUM_HT_OFDM_ENTRIES                32
-#define POWER_TABLE_CCK_ENTRY                  32
-struct tx_power_dual_stream {
-       __le32 dw;
-} __attribute__ ((packed));
-
-struct iwl4965_tx_power_db {
-       struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
-} __attribute__ ((packed));
-
 /*
  * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
  */
@@ -466,6 +652,23 @@ struct iwl4965_csa_notification {
  * Quality-of-Service (QOS) Commands & Responses:
  *
  *****************************************************************************/
+
+/**
+ * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
+ * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
+ *
+ * @cw_min: Contention window, start value in numbers of slots.
+ *          Should be a power-of-2, minus 1.  Device's default is 0x0f.
+ * @cw_max: Contention window, max value in numbers of slots.
+ *          Should be a power-of-2, minus 1.  Device's default is 0x3f.
+ * @aifsn:  Number of slots in Arbitration Interframe Space (before
+ *          performing random backoff timing prior to Tx).  Device default 1.
+ * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.
+ *
+ * Device will automatically increase contention window by (2*CW) + 1 for each
+ * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
+ * value, to cap the CW value.
+ */
 struct iwl4965_ac_qos {
        __le16 cw_min;
        __le16 cw_max;
@@ -479,14 +682,14 @@ struct iwl4965_ac_qos {
 #define QOS_PARAM_FLG_TGN_MSK          __constant_cpu_to_le32(0x02)
 #define QOS_PARAM_FLG_TXOP_TYPE_MSK    __constant_cpu_to_le32(0x10)
 
-/*
- *  TXFIFO Queue number defines
- */
-/* number of Access categories (AC) (EDCA), queues 0..3 */
+/* Number of Access Categories (AC) (EDCA), queues 0..3 */
 #define AC_NUM                4
 
 /*
  * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
+ *
+ * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
+ * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
  */
 struct iwl4965_qosparam_cmd {
        __le32 qos_flags;
@@ -501,39 +704,56 @@ struct iwl4965_qosparam_cmd {
 /*
  * Multi station support
  */
+
+/* Special, dedicated locations within device's station table */
 #define        IWL_AP_ID               0
 #define IWL_MULTICAST_ID       1
 #define        IWL_STA_ID              2
-
-#define        IWL3945_BROADCAST_ID    24
-#define IWL3945_STATION_COUNT  25
-
 #define IWL4965_BROADCAST_ID   31
 #define        IWL4965_STATION_COUNT   32
 
 #define        IWL_STATION_COUNT       32      /* MAX(3945,4965)*/
 #define        IWL_INVALID_STATION     255
 
-#define STA_FLG_PWR_SAVE_MSK           __constant_cpu_to_le32(1<<8);
-
+#define STA_FLG_PWR_SAVE_MSK           __constant_cpu_to_le32(1 << 8);
+#define STA_FLG_RTS_MIMO_PROT_MSK      __constant_cpu_to_le32(1 << 17)
+#define STA_FLG_AGG_MPDU_8US_MSK       __constant_cpu_to_le32(1 << 18)
+#define STA_FLG_MAX_AGG_SIZE_POS       (19)
+#define STA_FLG_MAX_AGG_SIZE_MSK       __constant_cpu_to_le32(3 << 19)
+#define STA_FLG_FAT_EN_MSK             __constant_cpu_to_le32(1 << 21)
+#define STA_FLG_MIMO_DIS_MSK           __constant_cpu_to_le32(1 << 22)
+#define STA_FLG_AGG_MPDU_DENSITY_POS   (23)
+#define STA_FLG_AGG_MPDU_DENSITY_MSK   __constant_cpu_to_le32(7 << 23)
+
+/* Use in mode field.  1: modify existing entry, 0: add new station entry */
 #define STA_CONTROL_MODIFY_MSK         0x01
 
 /* key flags __le16*/
-#define STA_KEY_FLG_ENCRYPT_MSK        __constant_cpu_to_le16(0x7)
-#define STA_KEY_FLG_NO_ENC     __constant_cpu_to_le16(0x0)
-#define STA_KEY_FLG_WEP                __constant_cpu_to_le16(0x1)
-#define STA_KEY_FLG_CCMP       __constant_cpu_to_le16(0x2)
-#define STA_KEY_FLG_TKIP       __constant_cpu_to_le16(0x3)
+#define STA_KEY_FLG_ENCRYPT_MSK        __constant_cpu_to_le16(0x0007)
+#define STA_KEY_FLG_NO_ENC     __constant_cpu_to_le16(0x0000)
+#define STA_KEY_FLG_WEP                __constant_cpu_to_le16(0x0001)
+#define STA_KEY_FLG_CCMP       __constant_cpu_to_le16(0x0002)
+#define STA_KEY_FLG_TKIP       __constant_cpu_to_le16(0x0003)
 
 #define STA_KEY_FLG_KEYID_POS  8
 #define STA_KEY_FLG_INVALID    __constant_cpu_to_le16(0x0800)
+/* wep key is either from global key (0) or from station info array (1) */
+#define STA_KEY_FLG_MAP_KEY_MSK        __constant_cpu_to_le16(0x0008)
+
+/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
+#define STA_KEY_FLG_KEY_SIZE_MSK     __constant_cpu_to_le16(0x1000)
+#define STA_KEY_MULTICAST_MSK        __constant_cpu_to_le16(0x4000)
+#define STA_KEY_MAX_NUM                8
 
-/* modify flags  */
+/* Flags indicate whether to modify vs. don't change various station params */
 #define        STA_MODIFY_KEY_MASK             0x01
 #define        STA_MODIFY_TID_DISABLE_TX       0x02
 #define        STA_MODIFY_TX_RATE_MSK          0x04
 #define STA_MODIFY_ADDBA_TID_MSK       0x08
 #define STA_MODIFY_DELBA_TID_MSK       0x10
+
+/* Receiver address (actually, Rx station's index into station table),
+ * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
 #define BUILD_RAxTID(sta_id, tid)      (((sta_id) << 4) + (tid))
 
 struct iwl4965_keyinfo {
@@ -541,10 +761,23 @@ struct iwl4965_keyinfo {
        u8 tkip_rx_tsc_byte2;   /* TSC[2] for key mix ph1 detection */
        u8 reserved1;
        __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
-       __le16 reserved2;
+       u8 key_offset;
+       u8 reserved2;
        u8 key[16];             /* 16-byte unicast decryption key */
 } __attribute__ ((packed));
 
+/**
+ * struct sta_id_modify
+ * @addr[ETH_ALEN]: station's MAC address
+ * @sta_id: index of station in uCode's station table
+ * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
+ *
+ * Driver selects unused table index when adding new station,
+ * or the index to a pre-existing station entry when modifying that station.
+ * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
+ *
+ * modify_mask flags select which parameters to modify vs. leave alone.
+ */
 struct sta_id_modify {
        u8 addr[ETH_ALEN];
        __le16 reserved1;
@@ -555,30 +788,94 @@ struct sta_id_modify {
 
 /*
  * REPLY_ADD_STA = 0x18 (command)
+ *
+ * The device contains an internal table of per-station information,
+ * with info on security keys, aggregation parameters, and Tx rates for
+ * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD,
+ * 3945 uses REPLY_RATE_SCALE to set up rate tables).
+ *
+ * REPLY_ADD_STA sets up the table entry for one station, either creating
+ * a new entry, or modifying a pre-existing one.
+ *
+ * NOTE:  RXON command (without "associated" bit set) wipes the station table
+ *        clean.  Moving into RF_KILL state does this also.  Driver must set up
+ *        new station table before transmitting anything on the RXON channel
+ *        (except active scans or active measurements; those commands carry
+ *        their own txpower/rate setup data).
+ *
+ *        When getting started on a new channel, driver must set up the
+ *        IWL_BROADCAST_ID entry (last entry in the table).  For a client
+ *        station in a BSS, once an AP is selected, driver sets up the AP STA
+ *        in the IWL_AP_ID entry (1st entry in the table).  BROADCAST and AP
+ *        are all that are needed for a BSS client station.  If the device is
+ *        used as AP, or in an IBSS network, driver must set up station table
+ *        entries for all STAs in network, starting with index IWL_STA_ID.
  */
 struct iwl4965_addsta_cmd {
-       u8 mode;
+       u8 mode;                /* 1: modify existing, 0: add new station */
        u8 reserved[3];
        struct sta_id_modify sta;
        struct iwl4965_keyinfo key;
-       __le32 station_flags;
-       __le32 station_flags_msk;
+       __le32 station_flags;           /* STA_FLG_* */
+       __le32 station_flags_msk;       /* STA_FLG_* */
+
+       /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+        * corresponding to bit (e.g. bit 5 controls TID 5).
+        * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
        __le16 tid_disable_tx;
+
        __le16  reserved1;
+
+       /* TID for which to add block-ack support.
+        * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
        u8 add_immediate_ba_tid;
+
+       /* TID for which to remove block-ack support.
+        * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
        u8 remove_immediate_ba_tid;
+
+       /* Starting Sequence Number for added block-ack support.
+        * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
        __le16 add_immediate_ba_ssn;
+
        __le32 reserved2;
 } __attribute__ ((packed));
 
+#define ADD_STA_SUCCESS_MSK            0x1
+#define ADD_STA_NO_ROOM_IN_TABLE       0x2
+#define ADD_STA_NO_BLOCK_ACK_RESOURCE  0x4
+#define ADD_STA_MODIFY_NON_EXIST_STA   0x8
 /*
  * REPLY_ADD_STA = 0x18 (response)
  */
 struct iwl4965_add_sta_resp {
-       u8 status;
+       u8 status;      /* ADD_STA_* */
+} __attribute__ ((packed));
+
+/*
+ * REPLY_WEP_KEY = 0x20
+ */
+struct iwl_wep_key {
+       u8 key_index;
+       u8 key_offset;
+       u8 reserved1[2];
+       u8 key_size;
+       u8 reserved2[3];
+       u8 key[16];
+} __attribute__ ((packed));
+
+struct iwl_wep_cmd {
+       u8 num_keys;
+       u8 global_key_type;
+       u8 flags;
+       u8 reserved;
+       struct iwl_wep_key key[0];
 } __attribute__ ((packed));
 
-#define ADD_STA_SUCCESS_MSK              0x1
+#define WEP_KEY_WEP_TYPE 1
+#define WEP_KEYS_MAX 4
+#define WEP_INVALID_OFFSET 0xff
+#define WEP_KEY_LEN_128 13
 
 /******************************************************************************
  * (4)
@@ -605,26 +902,35 @@ struct iwl4965_rx_frame_hdr {
        u8 payload[0];
 } __attribute__ ((packed));
 
-#define        RX_RES_STATUS_NO_CRC32_ERROR    __constant_cpu_to_le32(1 << 0)
-#define        RX_RES_STATUS_NO_RXE_OVERFLOW   __constant_cpu_to_le32(1 << 1)
+#define RX_RES_STATUS_NO_CRC32_ERROR   __constant_cpu_to_le32(1 << 0)
+#define RX_RES_STATUS_NO_RXE_OVERFLOW  __constant_cpu_to_le32(1 << 1)
+
+#define RX_RES_PHY_FLAGS_BAND_24_MSK   __constant_cpu_to_le16(1 << 0)
+#define RX_RES_PHY_FLAGS_MOD_CCK_MSK           __constant_cpu_to_le16(1 << 1)
+#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK    __constant_cpu_to_le16(1 << 2)
+#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK       __constant_cpu_to_le16(1 << 3)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK           __constant_cpu_to_le16(0xf0)
 
-#define        RX_RES_PHY_FLAGS_BAND_24_MSK    __constant_cpu_to_le16(1 << 0)
-#define        RX_RES_PHY_FLAGS_MOD_CCK_MSK            __constant_cpu_to_le16(1 << 1)
-#define        RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK     __constant_cpu_to_le16(1 << 2)
-#define        RX_RES_PHY_FLAGS_NARROW_BAND_MSK        __constant_cpu_to_le16(1 << 3)
-#define        RX_RES_PHY_FLAGS_ANTENNA_MSK            __constant_cpu_to_le16(0xf0)
+#define RX_RES_STATUS_SEC_TYPE_MSK     (0x7 << 8)
+#define RX_RES_STATUS_SEC_TYPE_NONE    (0x0 << 8)
+#define RX_RES_STATUS_SEC_TYPE_WEP     (0x1 << 8)
+#define RX_RES_STATUS_SEC_TYPE_CCMP    (0x2 << 8)
+#define RX_RES_STATUS_SEC_TYPE_TKIP    (0x3 << 8)
+#define        RX_RES_STATUS_SEC_TYPE_ERR      (0x7 << 8)
 
-#define        RX_RES_STATUS_SEC_TYPE_MSK      (0x7 << 8)
-#define        RX_RES_STATUS_SEC_TYPE_NONE     (0x0 << 8)
-#define        RX_RES_STATUS_SEC_TYPE_WEP      (0x1 << 8)
-#define        RX_RES_STATUS_SEC_TYPE_CCMP     (0x2 << 8)
-#define        RX_RES_STATUS_SEC_TYPE_TKIP     (0x3 << 8)
+#define RX_RES_STATUS_STATION_FOUND    (1<<6)
+#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH (1<<7)
 
-#define        RX_RES_STATUS_DECRYPT_TYPE_MSK  (0x3 << 11)
-#define        RX_RES_STATUS_NOT_DECRYPT       (0x0 << 11)
-#define        RX_RES_STATUS_DECRYPT_OK        (0x3 << 11)
-#define        RX_RES_STATUS_BAD_ICV_MIC       (0x1 << 11)
-#define        RX_RES_STATUS_BAD_KEY_TTAK      (0x2 << 11)
+#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
+#define RX_RES_STATUS_NOT_DECRYPT      (0x0 << 11)
+#define RX_RES_STATUS_DECRYPT_OK       (0x3 << 11)
+#define RX_RES_STATUS_BAD_ICV_MIC      (0x1 << 11)
+#define RX_RES_STATUS_BAD_KEY_TTAK     (0x2 << 11)
+
+#define RX_MPDU_RES_STATUS_ICV_OK      (0x20)
+#define RX_MPDU_RES_STATUS_MIC_OK      (0x40)
+#define RX_MPDU_RES_STATUS_TTAK_OK     (1 << 7)
+#define RX_MPDU_RES_STATUS_DEC_DONE_MSK        (0x800)
 
 struct iwl4965_rx_frame_end {
        __le32 status;
@@ -659,7 +965,7 @@ struct iwl4965_rx_non_cfg_phy {
 } __attribute__ ((packed));
 
 /*
- * REPLY_4965_RX = 0xc3 (response only, not a command)
+ * REPLY_RX = 0xc3 (response only, not a command)
  * Used only for legacy (non 11n) frames.
  */
 #define RX_RES_PHY_CNT 14
@@ -674,8 +980,8 @@ struct iwl4965_rx_phy_res {
        __le16 channel;         /* channel number */
        __le16 non_cfg_phy[RX_RES_PHY_CNT];     /* upto 14 phy entries */
        __le32 reserved2;
-       __le32 rate_n_flags;
-       __le16 byte_count;              /* frame's byte-count */
+       __le32 rate_n_flags;    /* RATE_MCS_* */
+       __le16 byte_count;      /* frame's byte-count */
        __le16 reserved3;
 } __attribute__ ((packed));
 
@@ -689,41 +995,100 @@ struct iwl4965_rx_mpdu_res_start {
  * (5)
  * Tx Commands & Responses:
  *
+ * Driver must place each REPLY_TX command into one of the prioritized Tx
+ * queues in host DRAM, shared between driver and device (see comments for
+ * SCD registers and Tx/Rx Queues).  When the device's Tx scheduler and uCode
+ * are preparing to transmit, the device pulls the Tx command over the PCI
+ * bus via one of the device's Tx DMA channels, to fill an internal FIFO
+ * from which data will be transmitted.
+ *
+ * uCode handles all timing and protocol related to control frames
+ * (RTS/CTS/ACK), based on flags in the Tx command.  uCode and Tx scheduler
+ * handle reception of block-acks; uCode updates the host driver via
+ * REPLY_COMPRESSED_BA (4965).
+ *
+ * uCode handles retrying Tx when an ACK is expected but not received.
+ * This includes trying lower data rates than the one requested in the Tx
+ * command, as set up by the REPLY_RATE_SCALE (for 3945) or
+ * REPLY_TX_LINK_QUALITY_CMD (4965).
+ *
+ * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
+ * This command must be executed after every RXON command, before Tx can occur.
  *****************************************************************************/
 
-/* Tx flags */
+/* REPLY_TX Tx flags field */
+
+/* 1: Use Request-To-Send protocol before this frame.
+ * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
 #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
+
+/* 1: Transmit Clear-To-Send to self before this frame.
+ * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
+ * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
 #define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
+
+/* 1: Expect ACK from receiving station
+ * 0: Don't expect ACK (MAC header's duration field s/b 0)
+ * Set this for unicast frames, but not broadcast/multicast. */
 #define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
+
+/* For 4965:
+ * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
+ *    Tx command's initial_rate_index indicates first rate to try;
+ *    uCode walks through table for additional Tx attempts.
+ * 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
+ *    This rate will be used for all Tx attempts; it will not be scaled. */
 #define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
+
+/* 1: Expect immediate block-ack.
+ * Set when Txing a block-ack request frame.  Also set TX_CMD_FLG_ACK_MSK. */
 #define TX_CMD_FLG_IMM_BA_RSP_MASK  __constant_cpu_to_le32(1 << 6)
+
+/* 1: Frame requires full Tx-Op protection.
+ * Set this if either RTS or CTS Tx Flag gets set. */
 #define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
+
+/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
+ * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
 #define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
 #define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
 #define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
 
-/* ucode ignores BT priority for this frame */
+/* 1: Ignore Bluetooth priority for this frame.
+ * 0: Delay Tx until Bluetooth device is done (normal usage). */
 #define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
 
-/* ucode overrides sequence control */
+/* 1: uCode overrides sequence control field in MAC header.
+ * 0: Driver provides sequence control field in MAC header.
+ * Set this for management frames, non-QOS data frames, non-unicast frames,
+ * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
 #define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
 
-/* signal that this frame is non-last MPDU */
+/* 1: This frame is non-last MPDU; more fragments are coming.
+ * 0: Last fragment, or not using fragmentation. */
 #define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
 
-/* calculate TSF in outgoing frame */
+/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
+ * 0: No TSF required in outgoing frame.
+ * Set this for transmitting beacons and probe responses. */
 #define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
 
-/* activate TX calibration. */
-#define TX_CMD_FLG_CALIB_MSK __constant_cpu_to_le32(1 << 17)
-
-/* signals that 2 bytes pad was inserted
-   after the MAC header */
+/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
+ *    alignment of frame's payload data field.
+ * 0: No pad
+ * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
+ * field (but not both).  Driver must align frame data (i.e. data following
+ * MAC header) to DWORD boundary. */
 #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
 
+/* accelerate aggregation support
+ * 0 - no CCMP encryption; 1 - CCMP encryption */
+#define TX_CMD_FLG_AGG_CCMP_MSK __constant_cpu_to_le32(1 << 22)
+
 /* HCCA-AP - disable duration overwriting. */
 #define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
 
+
 /*
  * TX command security control
  */
@@ -735,12 +1100,13 @@ struct iwl4965_rx_mpdu_res_start {
 #define TX_CMD_SEC_KEY128      0x08
 
 /*
- * TX command Frame life time
+ * 4965 uCode updates these Tx attempt count values in host DRAM.
+ * Used for managing Tx retries when expecting block-acks.
+ * Driver should set these fields to 0.
  */
-
 struct iwl4965_dram_scratch {
-       u8 try_cnt;
-       u8 bt_kill_cnt;
+       u8 try_cnt;             /* Tx attempts */
+       u8 bt_kill_cnt;         /* Tx attempts blocked by Bluetooth device */
        __le16 reserved;
 } __attribute__ ((packed));
 
@@ -748,13 +1114,47 @@ struct iwl4965_dram_scratch {
  * REPLY_TX = 0x1c (command)
  */
 struct iwl4965_tx_cmd {
+       /*
+        * MPDU byte count:
+        * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+        * + 8 byte IV for CCM or TKIP (not used for WEP)
+        * + Data payload
+        * + 8-byte MIC (not used for CCM/WEP)
+        * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
+        *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+        * Range: 14-2342 bytes.
+        */
        __le16 len;
+
+       /*
+        * MPDU or MSDU byte count for next frame.
+        * Used for fragmentation and bursting, but not 11n aggregation.
+        * Same as "len", but for next frame.  Set to 0 if not applicable.
+        */
        __le16 next_frame_len;
-       __le32 tx_flags;
+
+       __le32 tx_flags;        /* TX_CMD_FLG_* */
+
+       /* 4965's uCode may modify this field of the Tx command (in host DRAM!).
+        * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
        struct iwl4965_dram_scratch scratch;
-       __le32 rate_n_flags;
+
+       /* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
+       __le32 rate_n_flags;    /* RATE_MCS_* */
+
+       /* Index of destination station in uCode's station table */
        u8 sta_id;
-       u8 sec_ctl;
+
+       /* Type of security encryption:  CCM or TKIP */
+       u8 sec_ctl;             /* TX_CMD_SEC_* */
+
+       /*
+        * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial
+        * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set.  Normally "0" for
+        * data frames, this field may be used to selectively reduce initial
+        * rate (via non-0 value) for special frames (e.g. management), while
+        * still supporting rate scaling for all frames.
+        */
        u8 initial_rate_index;
        u8 reserved;
        u8 key[16];
@@ -764,8 +1164,12 @@ struct iwl4965_tx_cmd {
                __le32 life_time;
                __le32 attempt;
        } stop_time;
+
+       /* Host DRAM physical address pointer to "scratch" in this command.
+        * Must be dword aligned.  "0" in dram_lsb_ptr disables usage. */
        __le32 dram_lsb_ptr;
        u8 dram_msb_ptr;
+
        u8 rts_retry_limit;     /*byte 50 */
        u8 data_retry_limit;    /*byte 51 */
        u8 tid_tspec;
@@ -773,7 +1177,17 @@ struct iwl4965_tx_cmd {
                __le16 pm_frame_timeout;
                __le16 attempt_duration;
        } timeout;
+
+       /*
+        * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+        * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+        */
        __le16 driver_txop;
+
+       /*
+        * MAC header goes here, followed by 2 bytes padding if MAC header
+        * length is 26 or 30 bytes, followed by payload data
+        */
        u8 payload[0];
        struct ieee80211_hdr hdr[0];
 } __attribute__ ((packed));
@@ -846,7 +1260,7 @@ enum {
 };
 
 /* *******************************
- * TX aggregation state
+ * TX aggregation status
  ******************************* */
 
 enum {
@@ -870,46 +1284,111 @@ enum {
  AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
  AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
 
+/* # tx attempts for first frame in aggregation */
 #define AGG_TX_STATE_TRY_CNT_POS 12
 #define AGG_TX_STATE_TRY_CNT_MSK 0xf000
 
+/* Command ID and sequence number of Tx command for this frame */
 #define AGG_TX_STATE_SEQ_NUM_POS 16
 #define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
 
 /*
  * REPLY_TX = 0x1c (response)
+ *
+ * This response may be in one of two slightly different formats, indicated
+ * by the frame_count field:
+ *
+ * 1)  No aggregation (frame_count == 1).  This reports Tx results for
+ *     a single frame.  Multiple attempts, at various bit rates, may have
+ *     been made for this frame.
+ *
+ * 2)  Aggregation (frame_count > 1).  This reports Tx results for
+ *     2 or more frames that used block-acknowledge.  All frames were
+ *     transmitted at same rate.  Rate scaling may have been used if first
+ *     frame in this new agg block failed in previous agg block(s).
+ *
+ *     Note that, for aggregation, ACK (block-ack) status is not delivered here;
+ *     block-ack has not been received by the time the 4965 records this status.
+ *     This status relates to reasons the tx might have been blocked or aborted
+ *     within the sending station (this 4965), rather than whether it was
+ *     received successfully by the destination station.
  */
 struct iwl4965_tx_resp {
        u8 frame_count;         /* 1 no aggregation, >1 aggregation */
-       u8 bt_kill_count;
+       u8 bt_kill_count;       /* # blocked by bluetooth (unused for agg) */
+       u8 failure_rts;         /* # failures due to unsuccessful RTS */
+       u8 failure_frame;       /* # failures due to no ACK (unused for agg) */
+
+       /* For non-agg:  Rate at which frame was successful.
+        * For agg:  Rate at which all frames were transmitted. */
+       __le32 rate_n_flags;    /* RATE_MCS_*  */
+
+       /* For non-agg:  RTS + CTS + frame tx attempts time + ACK.
+        * For agg:  RTS + CTS + aggregation tx time + block-ack time. */
+       __le16 wireless_media_time;     /* uSecs */
+
+       __le16 reserved;
+       __le32 pa_power1;       /* RF power amplifier measurement (not used) */
+       __le32 pa_power2;
+
+       /*
+        * For non-agg:  frame status TX_STATUS_*
+        * For agg:  status of 1st frame, AGG_TX_STATE_*; other frame status
+        *           fields follow this one, up to frame_count.
+        *           Bit fields:
+        *           11- 0:  AGG_TX_STATE_* status code
+        *           15-12:  Retry count for 1st frame in aggregation (retries
+        *                   occur if tx failed for this frame when it was a
+        *                   member of a previous aggregation block).  If rate
+        *                   scaling is used, retry count indicates the rate
+        *                   table entry used for all frames in the new agg.
+        *           31-16:  Sequence # for this frame's Tx cmd (not SSN!)
+        */
+       __le32 status;  /* TX status (for aggregation status of 1st frame) */
+} __attribute__ ((packed));
+
+struct agg_tx_status {
+       __le16 status;
+       __le16 sequence;
+} __attribute__ ((packed));
+
+struct iwl4965_tx_resp_agg {
+       u8 frame_count;         /* 1 no aggregation, >1 aggregation */
+       u8 reserved1;
        u8 failure_rts;
        u8 failure_frame;
        __le32 rate_n_flags;
        __le16 wireless_media_time;
-       __le16 reserved;
+       __le16 reserved3;
        __le32 pa_power1;
        __le32 pa_power2;
-       __le32 status;  /* TX status (for aggregation status of 1st frame) */
+       struct agg_tx_status status;    /* TX status (for aggregation status */
+                                       /* of 1st frame) */
 } __attribute__ ((packed));
 
 /*
  * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+ *
+ * Reports Block-Acknowledge from recipient station
  */
 struct iwl4965_compressed_ba_resp {
        __le32 sta_addr_lo32;
        __le16 sta_addr_hi16;
        __le16 reserved;
+
+       /* Index of recipient (BA-sending) station in uCode's station table */
        u8 sta_id;
        u8 tid;
-       __le16 ba_seq_ctl;
-       __le32 ba_bitmap0;
-       __le32 ba_bitmap1;
+       __le16 seq_ctl;
+       __le64 bitmap;
        __le16 scd_flow;
        __le16 scd_ssn;
 } __attribute__ ((packed));
 
 /*
  * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
+ *
+ * See details under "TXPOWER" in iwl-4965-hw.h.
  */
 struct iwl4965_txpowertable_cmd {
        u8 band;                /* 0: 5 GHz, 1: 2.4 GHz */
@@ -919,47 +1398,292 @@ struct iwl4965_txpowertable_cmd {
 } __attribute__ ((packed));
 
 /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
-#define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK   (1<<0)
+#define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK   (1 << 0)
 
+/* # of EDCA prioritized tx fifos */
 #define  LINK_QUAL_AC_NUM AC_NUM
+
+/* # entries in rate scale table to support Tx retries */
 #define  LINK_QUAL_MAX_RETRY_NUM 16
 
-#define  LINK_QUAL_ANT_A_MSK (1<<0)
-#define  LINK_QUAL_ANT_B_MSK (1<<1)
+/* Tx antenna selection values */
+#define  LINK_QUAL_ANT_A_MSK (1 << 0)
+#define  LINK_QUAL_ANT_B_MSK (1 << 1)
 #define  LINK_QUAL_ANT_MSK   (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
 
-struct iwl4965_link_qual_general_params {
+
+/**
+ * struct iwl_link_qual_general_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl_link_qual_general_params {
        u8 flags;
+
+       /* No entries at or above this (driver chosen) index contain MIMO */
        u8 mimo_delimiter;
-       u8 single_stream_ant_msk;
-       u8 dual_stream_ant_msk;
+
+       /* Best single antenna to use for single stream (legacy, SISO). */
+       u8 single_stream_ant_msk;       /* LINK_QUAL_ANT_* */
+
+       /* Best antennas to use for MIMO (unused for 4965, assumes both). */
+       u8 dual_stream_ant_msk;         /* LINK_QUAL_ANT_* */
+
+       /*
+        * If driver needs to use different initial rates for different
+        * EDCA QOS access categories (as implemented by tx fifos 0-3),
+        * this table will set that up, by indicating the indexes in the
+        * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start.
+        * Otherwise, driver should set all entries to 0.
+        *
+        * Entry usage:
+        * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice
+        * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3.
+        */
        u8 start_rate_index[LINK_QUAL_AC_NUM];
 } __attribute__ ((packed));
 
-struct iwl4965_link_qual_agg_params {
+/**
+ * struct iwl_link_qual_agg_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl_link_qual_agg_params {
+
+       /* Maximum number of uSec in aggregation.
+        * Driver should set this to 4000 (4 milliseconds). */
        __le16 agg_time_limit;
+
+       /*
+        * Number of Tx retries allowed for a frame, before that frame will
+        * no longer be considered for the start of an aggregation sequence
+        * (scheduler will then try to tx it as single frame).
+        * Driver should set this to 3.
+        */
        u8 agg_dis_start_th;
+
+       /*
+        * Maximum number of frames in aggregation.
+        * 0 = no limit (default).  1 = no aggregation.
+        * Other values = max # frames in aggregation.
+        */
        u8 agg_frame_cnt_limit;
+
        __le32 reserved;
 } __attribute__ ((packed));
 
 /*
  * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
+ *
+ * For 4965 only; 3945 uses REPLY_RATE_SCALE.
+ *
+ * Each station in the 4965's internal station table has its own table of 16
+ * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when
+ * an ACK is not received.  This command replaces the entire table for
+ * one station.
+ *
+ * NOTE:  Station must already be in 4965's station table.  Use REPLY_ADD_STA.
+ *
+ * The rate scaling procedures described below work well.  Of course, other
+ * procedures are possible, and may work better for particular environments.
+ *
+ *
+ * FILLING THE RATE TABLE
+ *
+ * Given a particular initial rate and mode, as determined by the rate
+ * scaling algorithm described below, the Linux driver uses the following
+ * formula to fill the rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table in the
+ * Link Quality command:
+ *
+ *
+ * 1)  If using High-throughput (HT) (SISO or MIMO) initial rate:
+ *     a) Use this same initial rate for first 3 entries.
+ *     b) Find next lower available rate using same mode (SISO or MIMO),
+ *        use for next 3 entries.  If no lower rate available, switch to
+ *        legacy mode (no FAT channel, no MIMO, no short guard interval).
+ *     c) If using MIMO, set command's mimo_delimiter to number of entries
+ *        using MIMO (3 or 6).
+ *     d) After trying 2 HT rates, switch to legacy mode (no FAT channel,
+ *        no MIMO, no short guard interval), at the next lower bit rate
+ *        (e.g. if second HT bit rate was 54, try 48 legacy), and follow
+ *        legacy procedure for remaining table entries.
+ *
+ * 2)  If using legacy initial rate:
+ *     a) Use the initial rate for only one entry.
+ *     b) For each following entry, reduce the rate to next lower available
+ *        rate, until reaching the lowest available rate.
+ *     c) When reducing rate, also switch antenna selection.
+ *     d) Once lowest available rate is reached, repeat this rate until
+ *        rate table is filled (16 entries), switching antenna each entry.
+ *
+ *
+ * ACCUMULATING HISTORY
+ *
+ * The rate scaling algorithm for 4965, as implemented in Linux driver, uses
+ * two sets of frame Tx success history:  One for the current/active modulation
+ * mode, and one for a speculative/search mode that is being attempted.  If the
+ * speculative mode turns out to be more effective (i.e. actual transfer
+ * rate is better), then the driver continues to use the speculative mode
+ * as the new current active mode.
+ *
+ * Each history set contains, separately for each possible rate, data for a
+ * sliding window of the 62 most recent tx attempts at that rate.  The data
+ * includes a shifting bitmap of success(1)/failure(0), and sums of successful
+ * and attempted frames, from which the driver can additionally calculate a
+ * success ratio (success / attempted) and number of failures
+ * (attempted - success), and control the size of the window (attempted).
+ * The driver uses the bit map to remove successes from the success sum, as
+ * the oldest tx attempts fall out of the window.
+ *
+ * When the 4965 makes multiple tx attempts for a given frame, each attempt
+ * might be at a different rate, and have different modulation characteristics
+ * (e.g. antenna, fat channel, short guard interval), as set up in the rate
+ * scaling table in the Link Quality command.  The driver must determine
+ * which rate table entry was used for each tx attempt, to determine which
+ * rate-specific history to update, and record only those attempts that
+ * match the modulation characteristics of the history set.
+ *
+ * When using block-ack (aggregation), all frames are transmitted at the same
+ * rate, since there is no per-attempt acknowledgement from the destination
+ * station.  The Tx response struct iwl_tx_resp indicates the Tx rate in
+ * rate_n_flags field.  After receiving a block-ack, the driver can update
+ * history for the entire block all at once.
+ *
+ *
+ * FINDING BEST STARTING RATE:
+ *
+ * When working with a selected initial modulation mode (see below), the
+ * driver attempts to find a best initial rate.  The initial rate is the
+ * first entry in the Link Quality command's rate table.
+ *
+ * 1)  Calculate actual throughput (success ratio * expected throughput, see
+ *     table below) for current initial rate.  Do this only if enough frames
+ *     have been attempted to make the value meaningful:  at least 6 failed
+ *     tx attempts, or at least 8 successes.  If not enough, don't try rate
+ *     scaling yet.
+ *
+ * 2)  Find available rates adjacent to current initial rate.  Available means:
+ *     a)  supported by hardware &&
+ *     b)  supported by association &&
+ *     c)  within any constraints selected by user
+ *
+ * 3)  Gather measured throughputs for adjacent rates.  These might not have
+ *     enough history to calculate a throughput.  That's okay, we might try
+ *     using one of them anyway!
+ *
+ * 4)  Try decreasing rate if, for current rate:
+ *     a)  success ratio is < 15% ||
+ *     b)  lower adjacent rate has better measured throughput ||
+ *     c)  higher adjacent rate has worse throughput, and lower is unmeasured
+ *
+ *     As a sanity check, if decrease was determined above, leave rate
+ *     unchanged if:
+ *     a)  lower rate unavailable
+ *     b)  success ratio at current rate > 85% (very good)
+ *     c)  current measured throughput is better than expected throughput
+ *         of lower rate (under perfect 100% tx conditions, see table below)
+ *
+ * 5)  Try increasing rate if, for current rate:
+ *     a)  success ratio is < 15% ||
+ *     b)  both adjacent rates' throughputs are unmeasured (try it!) ||
+ *     b)  higher adjacent rate has better measured throughput ||
+ *     c)  lower adjacent rate has worse throughput, and higher is unmeasured
+ *
+ *     As a sanity check, if increase was determined above, leave rate
+ *     unchanged if:
+ *     a)  success ratio at current rate < 70%.  This is not particularly
+ *         good performance; higher rate is sure to have poorer success.
+ *
+ * 6)  Re-evaluate the rate after each tx frame.  If working with block-
+ *     acknowledge, history and statistics may be calculated for the entire
+ *     block (including prior history that fits within the history windows),
+ *     before re-evaluation.
+ *
+ * FINDING BEST STARTING MODULATION MODE:
+ *
+ * After working with a modulation mode for a "while" (and doing rate scaling),
+ * the driver searches for a new initial mode in an attempt to improve
+ * throughput.  The "while" is measured by numbers of attempted frames:
+ *
+ * For legacy mode, search for new mode after:
+ *   480 successful frames, or 160 failed frames
+ * For high-throughput modes (SISO or MIMO), search for new mode after:
+ *   4500 successful frames, or 400 failed frames
+ *
+ * Mode switch possibilities are (3 for each mode):
+ *
+ * For legacy:
+ *   Change antenna, try SISO (if HT association), try MIMO (if HT association)
+ * For SISO:
+ *   Change antenna, try MIMO, try shortened guard interval (SGI)
+ * For MIMO:
+ *   Try SISO antenna A, SISO antenna B, try shortened guard interval (SGI)
+ *
+ * When trying a new mode, use the same bit rate as the old/current mode when
+ * trying antenna switches and shortened guard interval.  When switching to
+ * SISO from MIMO or legacy, or to MIMO from SISO or legacy, use a rate
+ * for which the expected throughput (under perfect conditions) is about the
+ * same or slightly better than the actual measured throughput delivered by
+ * the old/current mode.
+ *
+ * Actual throughput can be estimated by multiplying the expected throughput
+ * by the success ratio (successful / attempted tx frames).  Frame size is
+ * not considered in this calculation; it assumes that frame size will average
+ * out to be fairly consistent over several samples.  The following are
+ * metric values for expected throughput assuming 100% success ratio.
+ * Only G band has support for CCK rates:
+ *
+ *           RATE:  1    2    5   11    6   9   12   18   24   36   48   54   60
+ *
+ *              G:  7   13   35   58   40  57   72   98  121  154  177  186  186
+ *              A:  0    0    0    0   40  57   72   98  121  154  177  186  186
+ *     SISO 20MHz:  0    0    0    0   42  42   76  102  124  159  183  193  202
+ * SGI SISO 20MHz:  0    0    0    0   46  46   82  110  132  168  192  202  211
+ *     MIMO 20MHz:  0    0    0    0   74  74  123  155  179  214  236  244  251
+ * SGI MIMO 20MHz:  0    0    0    0   81  81  131  164  188  222  243  251  257
+ *     SISO 40MHz:  0    0    0    0   77  77  127  160  184  220  242  250  257
+ * SGI SISO 40MHz:  0    0    0    0   83  83  135  169  193  229  250  257  264
+ *     MIMO 40MHz:  0    0    0    0  123 123  182  214  235  264  279  285  289
+ * SGI MIMO 40MHz:  0    0    0    0  131 131  191  222  242  270  284  289  293
+ *
+ * After the new mode has been tried for a short while (minimum of 6 failed
+ * frames or 8 successful frames), compare success ratio and actual throughput
+ * estimate of the new mode with the old.  If either is better with the new
+ * mode, continue to use the new mode.
+ *
+ * Continue comparing modes until all 3 possibilities have been tried.
+ * If moving from legacy to HT, try all 3 possibilities from the new HT
+ * mode.  After trying all 3, a best mode is found.  Continue to use this mode
+ * for the longer "while" described above (e.g. 480 successful frames for
+ * legacy), and then repeat the search process.
+ *
  */
-struct iwl4965_link_quality_cmd {
+struct iwl_link_quality_cmd {
+
+       /* Index of destination/recipient station in uCode's station table */
        u8 sta_id;
        u8 reserved1;
-       __le16 control;
-       struct iwl4965_link_qual_general_params general_params;
-       struct iwl4965_link_qual_agg_params agg_params;
+       __le16 control;         /* not used */
+       struct iwl_link_qual_general_params general_params;
+       struct iwl_link_qual_agg_params agg_params;
+
+       /*
+        * Rate info; when using rate-scaling, Tx command's initial_rate_index
+        * specifies 1st Tx rate attempted, via index into this table.
+        * 4965 works its way through table when retrying Tx.
+        */
        struct {
-               __le32 rate_n_flags;
+               __le32 rate_n_flags;    /* RATE_MCS_*, IWL_RATE_* */
        } rs_table[LINK_QUAL_MAX_RETRY_NUM];
        __le32 reserved2;
 } __attribute__ ((packed));
 
 /*
  * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
+ *
+ * 3945 and 4965 support hardware handshake with Bluetooth device on
+ * same platform.  Bluetooth device alerts wireless device when it will Tx;
+ * wireless device can delay or kill its own Tx to accomodate.
  */
 struct iwl4965_bt_cmd {
        u8 flags;
@@ -1126,9 +1850,9 @@ struct iwl4965_spectrum_notification {
  */
 #define IWL_POWER_VEC_SIZE 5
 
-#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK       __constant_cpu_to_le16(1<<0)
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK          __constant_cpu_to_le16(1<<2)
-#define IWL_POWER_PCI_PM_MSK                   __constant_cpu_to_le16(1<<3)
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK       __constant_cpu_to_le16(1 << 0)
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK          __constant_cpu_to_le16(1 << 2)
+#define IWL_POWER_PCI_PM_MSK                   __constant_cpu_to_le16(1 << 3)
 
 struct iwl4965_powertable_cmd {
        __le16 flags;
@@ -1202,20 +1926,47 @@ struct iwl4965_ct_kill_config {
  *
  *****************************************************************************/
 
+/**
+ * struct iwl4965_scan_channel - entry in REPLY_SCAN_CMD channel table
+ *
+ * One for each channel in the scan list.
+ * Each channel can independently select:
+ * 1)  SSID for directed active scans
+ * 2)  Txpower setting (for rate specified within Tx command)
+ * 3)  How long to stay on-channel (behavior may be modified by quiet_time,
+ *     quiet_plcp_th, good_CRC_th)
+ *
+ * To avoid uCode errors, make sure the following are true (see comments
+ * under struct iwl4965_scan_cmd about max_out_time and quiet_time):
+ * 1)  If using passive_dwell (i.e. passive_dwell != 0):
+ *     active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
+ * 2)  quiet_time <= active_dwell
+ * 3)  If restricting off-channel time (i.e. max_out_time !=0):
+ *     passive_dwell < max_out_time
+ *     active_dwell < max_out_time
+ */
 struct iwl4965_scan_channel {
-       /* type is defined as:
-        * 0:0 active (0 - passive)
-        * 1:4 SSID direct
-        *     If 1 is set then corresponding SSID IE is transmitted in probe
+       /*
+        * type is defined as:
+        * 0:0 1 = active, 0 = passive
+        * 1:4 SSID direct bit map; if a bit is set, then corresponding
+        *     SSID IE is transmitted in probe request.
         * 5:7 reserved
         */
        u8 type;
-       u8 channel;
+       u8 channel;     /* band is selected by iwl4965_scan_cmd "flags" field */
        struct iwl4965_tx_power tpc;
-       __le16 active_dwell;
-       __le16 passive_dwell;
+       __le16 active_dwell;    /* in 1024-uSec TU (time units), typ 5-50 */
+       __le16 passive_dwell;   /* in 1024-uSec TU (time units), typ 20-500 */
 } __attribute__ ((packed));
 
+/**
+ * struct iwl4965_ssid_ie - directed scan network information element
+ *
+ * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
+ * in struct iwl4965_scan_channel; each channel may select different ssids from
+ * among the 4 entries.  SSID IEs get transmitted in reverse order of entry.
+ */
 struct iwl4965_ssid_ie {
        u8 id;
        u8 len;
@@ -1229,40 +1980,98 @@ struct iwl4965_ssid_ie {
 
 /*
  * REPLY_SCAN_CMD = 0x80 (command)
+ *
+ * The hardware scan command is very powerful; the driver can set it up to
+ * maintain (relatively) normal network traffic while doing a scan in the
+ * background.  The max_out_time and suspend_time control the ratio of how
+ * long the device stays on an associated network channel ("service channel")
+ * vs. how long it's away from the service channel, i.e. tuned to other channels
+ * for scanning.
+ *
+ * max_out_time is the max time off-channel (in usec), and suspend_time
+ * is how long (in "extended beacon" format) that the scan is "suspended"
+ * after returning to the service channel.  That is, suspend_time is the
+ * time that we stay on the service channel, doing normal work, between
+ * scan segments.  The driver may set these parameters differently to support
+ * scanning when associated vs. not associated, and light vs. heavy traffic
+ * loads when associated.
+ *
+ * After receiving this command, the device's scan engine does the following;
+ *
+ * 1)  Sends SCAN_START notification to driver
+ * 2)  Checks to see if it has time to do scan for one channel
+ * 3)  Sends NULL packet, with power-save (PS) bit set to 1,
+ *     to tell AP that we're going off-channel
+ * 4)  Tunes to first channel in scan list, does active or passive scan
+ * 5)  Sends SCAN_RESULT notification to driver
+ * 6)  Checks to see if it has time to do scan on *next* channel in list
+ * 7)  Repeats 4-6 until it no longer has time to scan the next channel
+ *     before max_out_time expires
+ * 8)  Returns to service channel
+ * 9)  Sends NULL packet with PS=0 to tell AP that we're back
+ * 10) Stays on service channel until suspend_time expires
+ * 11) Repeats entire process 2-10 until list is complete
+ * 12) Sends SCAN_COMPLETE notification
+ *
+ * For fast, efficient scans, the scan command also has support for staying on
+ * a channel for just a short time, if doing active scanning and getting no
+ * responses to the transmitted probe request.  This time is controlled by
+ * quiet_time, and the number of received packets below which a channel is
+ * considered "quiet" is controlled by quiet_plcp_threshold.
+ *
+ * For active scanning on channels that have regulatory restrictions against
+ * blindly transmitting, the scan can listen before transmitting, to make sure
+ * that there is already legitimate activity on the channel.  If enough
+ * packets are cleanly received on the channel (controlled by good_CRC_th,
+ * typical value 1), the scan engine starts transmitting probe requests.
+ *
+ * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
+ *
+ * To avoid uCode errors, see timing restrictions described under
+ * struct iwl4965_scan_channel.
  */
 struct iwl4965_scan_cmd {
        __le16 len;
        u8 reserved0;
-       u8 channel_count;
-       __le16 quiet_time;     /* dwell only this long on quiet chnl
-                               * (active scan) */
-       __le16 quiet_plcp_th;  /* quiet chnl is < this # pkts (typ. 1) */
-       __le16 good_CRC_th;    /* passive -> active promotion threshold */
-       __le16 rx_chain;
-       __le32 max_out_time;   /* max usec to be out of associated (service)
-                               * chnl */
-       __le32 suspend_time;   /* pause scan this long when returning to svc
-                               * chnl.
-                               * 3945 -- 31:24 # beacons, 19:0 additional usec,
-                               * 4965 -- 31:22 # beacons, 21:0 additional usec.
-                               */
-       __le32 flags;
-       __le32 filter_flags;
-
+       u8 channel_count;       /* # channels in channel list */
+       __le16 quiet_time;      /* dwell only this # millisecs on quiet channel
+                                * (only for active scan) */
+       __le16 quiet_plcp_th;   /* quiet chnl is < this # pkts (typ. 1) */
+       __le16 good_CRC_th;     /* passive -> active promotion threshold */
+       __le16 rx_chain;        /* RXON_RX_CHAIN_* */
+       __le32 max_out_time;    /* max usec to be away from associated (service)
+                                * channel */
+       __le32 suspend_time;    /* pause scan this long (in "extended beacon
+                                * format") when returning to service chnl:
+                                * 3945; 31:24 # beacons, 19:0 additional usec,
+                                * 4965; 31:22 # beacons, 21:0 additional usec.
+                                */
+       __le32 flags;           /* RXON_FLG_* */
+       __le32 filter_flags;    /* RXON_FILTER_* */
+
+       /* For active scans (set to all-0s for passive scans).
+        * Does not include payload.  Must specify Tx rate; no rate scaling. */
        struct iwl4965_tx_cmd tx_cmd;
+
+       /* For directed active scans (set to all-0s otherwise) */
        struct iwl4965_ssid_ie direct_scan[PROBE_OPTION_MAX];
 
-       u8 data[0];
        /*
-        * The channels start after the probe request payload and are of type:
+        * Probe request frame, followed by channel list.
+        *
+        * Size of probe request frame is specified by byte count in tx_cmd.
+        * Channel list follows immediately after probe request frame.
+        * Number of channels in list is specified by channel_count.
+        * Each channel in list is of type:
         *
         * struct iwl4965_scan_channel channels[0];
         *
         * NOTE:  Only one band of channels can be scanned per pass.  You
-        * can not mix 2.4GHz channels and 5.2GHz channels and must
-        * request a scan multiple times (not concurrently)
-        *
+        * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+        * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+        * before requesting another scan.
         */
+       u8 data[0];
 } __attribute__ ((packed));
 
 /* Can abort will notify by complete notification with abort status. */
@@ -1432,7 +2241,7 @@ struct statistics_rx_non_phy {
        __le32 interference_data_flag;  /* flag for interference data
                                         * availability. 1 when data is
                                         * available. */
-       __le32 channel_load;    /* counts RX Enable time */
+       __le32 channel_load;            /* counts RX Enable time in uSec */
        __le32 dsp_false_alarms;        /* DSP false alarm (both OFDM
                                         * and CCK) counter */
        __le32 beacon_rssi_a;
@@ -1881,7 +2690,7 @@ struct iwl4965_led_cmd {
 
 struct iwl4965_rx_packet {
        __le32 len;
-       struct iwl4965_cmd_header hdr;
+       struct iwl_cmd_header hdr;
        union {
                struct iwl4965_alive_resp alive_frame;
                struct iwl4965_rx_frame rx_frame;