Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/usb/rtl8187b.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 /* The Realtek 8187B is a common USB Wi-Fi chipset */
0019 
0020 /* Based on the Linux driver:
0021  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
0022  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
0023  *
0024  * Based on the r8187 driver, which is:
0025  * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
0026  *
0027  * The driver was extended to the RTL8187B in 2008 by:
0028  *      Herton Ronaldo Krzesinski <herton@mandriva.com.br>
0029  *  Hin-Tak Leung <htl10@users.sourceforge.net>
0030  *  Larry Finger <Larry.Finger@lwfinger.net>
0031  *
0032  * Magic delays and register offsets below are taken from the original
0033  * r8187 driver sources.  Thanks to Realtek for their support!
0034  *
0035  * This program is free software; you can redistribute it and/or modify
0036  * it under the terms of the GNU General Public License version 2 as
0037  * published by the Free Software Foundation.
0038  */
0039 
0040 #include <drivers/usb/usb.h>
0041 #include <drivers/usb/uhci.h>
0042 #include <drivers/net/ethernet.h>
0043 #include <drivers/net/ieee80211.h>
0044 #include <drivers/net/mac80211.h>
0045 #include <drivers/net/ieee80211_standard.h>
0046 #include <util/printf.h>
0047 #include <util/circular.h>
0048 #include <kernel.h>
0049 #include "sched/sched.h"
0050 #include <drivers/eeprom/93cx6.h>
0051 #include "rtl818x.h"
0052 
0053 //#define DEBUG_RTL8187B
0054 #define DEBUG_RTL8187B_TX
0055 
0056 #ifdef DEBUG_RTL8187B
0057 #define DLOG(fmt,...) DLOG_PREFIX("rtl8187b",fmt,##__VA_ARGS__)
0058 #else
0059 #define DLOG(fmt,...) ;
0060 #endif
0061 
0062 #ifdef DEBUG_RTL8187B_TX
0063 #define DLOGTX(fmt,...) DLOG_PREFIX("rtl8187b",fmt,##__VA_ARGS__)
0064 #else
0065 #define DLOGTX(fmt,...) ;
0066 #endif
0067 
0068 static struct { uint16 v, p; char *s; } compat_list[] = {
0069   { 0x0846, 0x4260, "Netgear WG111v3 [RTL8187B]" },
0070   { 0xFFFF, 0xFFFF, NULL }
0071 };
0072 
0073 static const struct ieee80211_rate rtl818x_rates[] = {
0074   { .bitrate = 10, .hw_value = 0, },
0075   { .bitrate = 20, .hw_value = 1, },
0076   { .bitrate = 55, .hw_value = 2, },
0077   { .bitrate = 110, .hw_value = 3, },
0078   { .bitrate = 60, .hw_value = 4, },
0079   { .bitrate = 90, .hw_value = 5, },
0080   { .bitrate = 120, .hw_value = 6, },
0081   { .bitrate = 180, .hw_value = 7, },
0082   { .bitrate = 240, .hw_value = 8, },
0083   { .bitrate = 360, .hw_value = 9, },
0084   { .bitrate = 480, .hw_value = 10, },
0085   { .bitrate = 540, .hw_value = 11, },
0086 };
0087 
0088 static const struct ieee80211_channel rtl818x_channels[] = {
0089   { .center_freq = 2412 },
0090   { .center_freq = 2417 },
0091   { .center_freq = 2422 },
0092   { .center_freq = 2427 },
0093   { .center_freq = 2432 },
0094   { .center_freq = 2437 },
0095   { .center_freq = 2442 },
0096   { .center_freq = 2447 },
0097   { .center_freq = 2452 },
0098   { .center_freq = 2457 },
0099   { .center_freq = 2462 },
0100   { .center_freq = 2467 },
0101   { .center_freq = 2472 },
0102   { .center_freq = 2484 },
0103 };
0104 
0105 #define ETH_ALEN ETH_ADDR_LEN
0106 
0107 #define RTL8187_EEPROM_TXPWR_BASE   0x05
0108 #define RTL8187_EEPROM_MAC_ADDR     0x07
0109 #define RTL8187_EEPROM_TXPWR_CHAN_1 0x16    /* 3 channels */
0110 #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B    /* 2 channels */
0111 #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D    /* 2 channels */
0112 #define RTL8187_EEPROM_SELECT_GPIO  0x3B
0113 
0114 #define RTL8187_REQ_GET_REG 0x05
0115 #define RTL8187_REQ_SET_REG 0x05
0116 #define RTL8187_REQT_READ   0xC0
0117 #define RTL8187_REQT_WRITE  0x40
0118 
0119 #define RTL8187_MAX_RX      0x9C4
0120 
0121 #define RFKILL_MASK_8187_89_97  0x2
0122 #define RFKILL_MASK_8198    0x4
0123 
0124 #define RTL8187_RTL8225_ANAPARAM_ON 0xa0000a59
0125 #define RTL8187_RTL8225_ANAPARAM2_ON    0x860c7312
0126 #define RTL8187_RTL8225_ANAPARAM_OFF    0xa00beb59
0127 #define RTL8187_RTL8225_ANAPARAM2_OFF   0x840dec11
0128 
0129 #define RTL8187B_RTL8225_ANAPARAM_ON    0x45090658
0130 #define RTL8187B_RTL8225_ANAPARAM2_ON   0x727f3f52
0131 #define RTL8187B_RTL8225_ANAPARAM3_ON   0x00
0132 #define RTL8187B_RTL8225_ANAPARAM_OFF   0x55480658
0133 #define RTL8187B_RTL8225_ANAPARAM2_OFF  0x72003f50
0134 #define RTL8187B_RTL8225_ANAPARAM3_OFF  0x00
0135 
0136 static USB_DEVICE_INFO *usbdev;
0137 /* a map of the configuration info on the chipset */
0138 static struct rtl818x_csr *map = (struct rtl818x_csr *)0xFF00;
0139 static struct eeprom_93cx6 eeprom;
0140 static uint8 rfkill_mask;
0141 static uint8 ethaddr[ETH_ADDR_LEN];
0142 static bool is_rtl8187b;
0143 static enum {
0144   RTL8187BvB, RTL8187BvD, RTL8187BvE
0145 } hw_rev;
0146 static struct ieee80211_channel channels[14];
0147 static struct ieee80211_rate rates[12];
0148 static const struct rtl818x_rf_ops *rf;
0149 static uint8 slot_time, aifsn[4];
0150 static struct ieee80211_hw *hwdev;
0151 
0152 #define udelay(x) tsc_delay_usec (x)
0153 #define msleep(x) sched_usleep (x*1000);
0154 
0155 /* ************************************************** */
0156 
0157 static int
0158 control_msg (uint8 req, uint8 reqtype, uint16 val, uint16 index,
0159              uint8 *data, uint16 len)
0160 {
0161   USB_DEV_REQ setup_req;
0162   setup_req.bmRequestType = reqtype;
0163   setup_req.bRequest = req;
0164   setup_req.wValue = val;
0165   setup_req.wIndex = index;
0166   setup_req.wLength = len;
0167 
0168   return usb_control_transfer (usbdev, (addr_t) &setup_req,
0169                                sizeof (USB_DEV_REQ), data, len);
0170 }
0171 
0172 #define iowrite_template(sz)                                            \
0173   static inline uint##sz                                                \
0174   ioread##sz##_idx (void* addr, uint8 idx)                              \
0175   {                                                                     \
0176     uint##sz val;                                                       \
0177     control_msg (RTL8187_REQ_GET_REG, RTL8187_REQT_READ,                \
0178                  (uint) addr, idx & 0x03, (uint8*)&val, sizeof (val));  \
0179     return val;                                                         \
0180   }                                                                     \
0181   static inline uint##sz                                                \
0182   ioread##sz (void* addr) { return ioread##sz##_idx (addr, 0); }        \
0183   static inline void                                                    \
0184   iowrite##sz##_idx (void* addr, uint##sz val, uint8 idx)               \
0185   {                                                                     \
0186     control_msg (RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,               \
0187                  (uint) addr, idx & 0x03, (uint8*)&val, sizeof (val));  \
0188   }                                                                     \
0189   static inline void                                                    \
0190   iowrite##sz (void* addr, uint##sz val)                                \
0191   { iowrite##sz##_idx (addr, val, 0); }
0192 
0193 iowrite_template(8)
0194 iowrite_template(16)
0195 iowrite_template(32)
0196 
0197 /* ************************************************** */
0198 
0199 void
0200 rtl8187_write_phy(u8 addr, u32 data)
0201 {
0202   data <<= 8;
0203   data |= addr | 0x80;
0204 
0205   iowrite8(&map->PHY[3], (data >> 24) & 0xFF);
0206   iowrite8(&map->PHY[2], (data >> 16) & 0xFF);
0207   iowrite8(&map->PHY[1], (data >> 8) & 0xFF);
0208   iowrite8(&map->PHY[0], data & 0xFF);
0209 }
0210 
0211 /* ************************************************** */
0212 
0213 static void
0214 eeprom_read (struct eeprom_93cx6 *eeprom)
0215 {
0216   uint8 reg = ioread8 (&map->EEPROM_CMD);
0217   eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
0218   eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
0219   eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
0220   eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
0221 }
0222 
0223 static void
0224 eeprom_write (struct eeprom_93cx6 *eeprom)
0225 {
0226   uint8 reg = RTL818X_EEPROM_CMD_PROGRAM;
0227   if (eeprom->reg_data_in)
0228     reg |= RTL818X_EEPROM_CMD_WRITE;
0229   if (eeprom->reg_data_out)
0230     reg |= RTL818X_EEPROM_CMD_READ;
0231   if (eeprom->reg_data_clock)
0232     reg |= RTL818X_EEPROM_CMD_CK;
0233   if (eeprom->reg_chip_select)
0234     reg |= RTL818X_EEPROM_CMD_CS;
0235 
0236   iowrite8 (&map->EEPROM_CMD, reg);
0237   udelay (10);
0238 }
0239 
0240 /* ************************************************** */
0241 
0242 static bool
0243 is_radio_enabled (void)
0244 {
0245   u8 gpio;
0246   gpio = ioread8 (&map->GPIO0);
0247   iowrite8 (&map->GPIO0, gpio & ~rfkill_mask);
0248   gpio = ioread8 (&map->GPIO1);
0249 
0250   return gpio & rfkill_mask;
0251 }
0252 
0253 static void
0254 rfkill_init (void)
0255 {
0256   bool enabled = is_radio_enabled ();
0257   DLOG ("wireless radio switch is %s",
0258         enabled ? "on" : "off");
0259 
0260   /* FIXME: what to do... */
0261   /* wiphy_rfkill_set_hwstate (hw->wiphy, !rfkill_off); */
0262 }
0263 
0264 /* ************************************************** */
0265 
0266 
0267 static bool
0268 add_iface (struct ieee80211_hw *dev,
0269            struct ieee80211_if_init_conf *conf)
0270 {
0271   int i;
0272 
0273   DLOG ("add_iface ethaddr=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
0274         ethaddr[0], ethaddr[1], ethaddr[2], 
0275         ethaddr[3], ethaddr[4], ethaddr[5]);
0276   iowrite8 (&map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
0277   for (i=0; i<ETH_ADDR_LEN; i++)
0278     iowrite8 (&map->MAC[i], ethaddr[i]);
0279   iowrite8 (&map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
0280 
0281   return TRUE;
0282 }
0283 
0284 static void
0285 rem_iface (struct ieee80211_hw *dev,
0286            struct ieee80211_if_init_conf *conf)
0287 {
0288   DLOG ("rem_iface");
0289 }
0290 
0291 static bool
0292 config (struct ieee80211_hw *dev, u32 changed)
0293 {
0294   struct ieee80211_conf *conf = &dev->conf;
0295   u32 reg;
0296   reg = ioread32 (&map->TX_CONF);
0297   /* Enable TX loopback during channel changes to avoid TX */
0298   iowrite32 (&map->TX_CONF, reg | RTL818X_TX_CONF_LOOPBACK_MAC);
0299   DLOG ("setting channel to freq=%d", conf->channel->center_freq);
0300   rf->set_chan (conf);
0301   msleep (10);
0302   iowrite32 (&map->TX_CONF, reg);
0303 
0304   iowrite16 (&map->ATIM_WND, 2);
0305   iowrite16 (&map->ATIMTR_INTERVAL, 100);
0306   iowrite16 (&map->BEACON_INTERVAL, 100);
0307   iowrite16 (&map->BEACON_INTERVAL_TIME, 100);
0308 
0309   return TRUE;
0310 }
0311 
0312 static __le32 *rtl8187b_ac_addr[4] = {
0313   (__le32 *) 0xFFF0, /* AC_VO */
0314   (__le32 *) 0xFFF4, /* AC_VI */
0315   (__le32 *) 0xFFFC, /* AC_BK */
0316   (__le32 *) 0xFFF8, /* AC_BE */
0317 };
0318 #define SIFS_TIME 0xa
0319 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
0320 
0321 static void
0322 conf_erp(bool use_short_slot,
0323          bool use_short_preamble)
0324 {
0325   if (is_rtl8187b) {
0326     u8 difs, eifs;
0327     u16 ack_timeout;
0328     int queue;
0329 
0330     if (use_short_slot) {
0331       slot_time = 0x9;
0332       difs = 0x1c;
0333       eifs = 0x53;
0334     } else {
0335       slot_time = 0x14;
0336       difs = 0x32;
0337       eifs = 0x5b;
0338     }
0339     iowrite8(&map->SIFS, 0x22);
0340     iowrite8(&map->SLOT, slot_time);
0341     iowrite8(&map->DIFS, difs);
0342 
0343     /*
0344      * BRSR+1 on 8187B is in fact EIFS register
0345      * Value in units of 4 us
0346      */
0347     iowrite8((u8 *)&map->BRSR + 1, eifs);
0348 
0349     /*
0350      * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout
0351      * register. In units of 4 us like eifs register
0352      * ack_timeout = ack duration + plcp + difs + preamble
0353      */
0354     ack_timeout = 112 + 48 + difs;
0355     if (use_short_preamble)
0356       ack_timeout += 72;
0357     else
0358       ack_timeout += 144;
0359     iowrite8(&map->CARRIER_SENSE_COUNTER,
0360              DIV_ROUND_UP(ack_timeout, 4));
0361 
0362     for (queue = 0; queue < 4; queue++)
0363       iowrite8((u8 *) rtl8187b_ac_addr[queue],
0364                aifsn[queue] * slot_time +
0365                SIFS_TIME);
0366   } else {
0367     iowrite8(&map->SIFS, 0x22);
0368     if (use_short_slot) {
0369       iowrite8(&map->SLOT, 0x9);
0370       iowrite8(&map->DIFS, 0x14);
0371       iowrite8(&map->EIFS, 91 - 0x14);
0372     } else {
0373       iowrite8(&map->SLOT, 0x14);
0374       iowrite8(&map->DIFS, 0x24);
0375       iowrite8(&map->EIFS, 91 - 0x24);
0376     }
0377   }
0378 }
0379 
0380 static void
0381 bss_info_changed(struct ieee80211_hw *dev,
0382                  struct ieee80211_vif *vif,
0383                  struct ieee80211_bss_conf *info,
0384                  u32 changed)
0385 {
0386   int i;
0387   u8 reg;
0388 
0389   if (changed & BSS_CHANGED_BSSID) {
0390     for (i = 0; i < ETH_ALEN; i++)
0391       iowrite8(&map->BSSID[i],
0392                info->bssid[i]);
0393 
0394     if (is_rtl8187b)
0395       reg = RTL818X_MSR_ENEDCA;
0396     else
0397       reg = 0;
0398 
0399     if (is_valid_ether_addr(info->bssid)) {
0400       reg |= RTL818X_MSR_INFRA;
0401       iowrite8(&map->MSR, reg);
0402     } else {
0403       reg |= RTL818X_MSR_NO_LINK;
0404       iowrite8(&map->MSR, reg);
0405     }
0406 
0407   }
0408 
0409   if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
0410     conf_erp(info->use_short_slot,
0411              info->use_short_preamble);
0412 }
0413 
0414 
0415 static bool
0416 conf_tx (struct ieee80211_hw *dev,
0417          u16 queue, const struct ieee80211_tx_queue_params *params)
0418 {
0419   u8 cw_min, cw_max;
0420 
0421   if (queue > 3)
0422     return FALSE;
0423 
0424   cw_min = fls(params->cw_min);
0425   cw_max = fls(params->cw_max);
0426 
0427   if (is_rtl8187b) {
0428     aifsn[queue] = params->aifs;
0429 
0430     /*
0431      * This is the structure of AC_*_PARAM registers in 8187B:
0432      * - TXOP limit field, bit offset = 16
0433      * - ECWmax, bit offset = 12
0434      * - ECWmin, bit offset = 8
0435      * - AIFS, bit offset = 0
0436      */
0437     iowrite32(rtl8187b_ac_addr[queue],
0438               (params->txop << 16) | (cw_max << 12) |
0439               (cw_min << 8) | (params->aifs *
0440                                slot_time + SIFS_TIME));
0441   } else {
0442     if (queue != 0)
0443       return FALSE;
0444 
0445     iowrite8(&map->CW_VAL,
0446              cw_min | (cw_max << 4));
0447   }
0448   return TRUE;
0449 }
0450 
0451 static bool
0452 cmd_reset (void)
0453 {
0454   u8 reg;
0455   int i;
0456 
0457   reg = ioread8(&map->CMD);
0458   reg &= (1 << 1);
0459   reg |= RTL818X_CMD_RESET;
0460   iowrite8(&map->CMD, reg);
0461 
0462   i = 10;
0463   do {
0464     msleep(2);
0465     if (!(ioread8(&map->CMD) &
0466           RTL818X_CMD_RESET))
0467       break;
0468   } while (--i);
0469 
0470   if (!i) {
0471     DLOG("Reset timeout!");
0472     return FALSE;
0473   }
0474 
0475   /* reload registers from eeprom */
0476   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
0477 
0478   i = 10;
0479   do {
0480     msleep(4);
0481     if (!(ioread8(&map->EEPROM_CMD) &
0482           RTL818X_EEPROM_CMD_CONFIG))
0483       break;
0484   } while (--i);
0485 
0486   if (!i) {
0487     DLOG("eeprom reset timeout!");
0488     return FALSE;
0489   }
0490 
0491   DLOG ("reset success");
0492   return TRUE;
0493 }
0494 
0495 static const u8 rtl8187b_reg_table[][3] = {
0496   {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0},
0497   {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0},
0498   {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0},
0499   {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0},
0500 
0501   {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1},
0502   {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1},
0503   {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1},
0504   {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1},
0505   {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1},
0506   {0xF7, 0x07, 1}, {0xF8, 0x08, 1},
0507 
0508   {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2},
0509   {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2},
0510   {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2},
0511   {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2},
0512   {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2},
0513   {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2},
0514   {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2},
0515   {0x73, 0x9A, 2},
0516 
0517   {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0},
0518   {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0},
0519   {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0},
0520   {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0},
0521   {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2},
0522 
0523   {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0},
0524   {0x8F, 0x00, 0}
0525 };
0526 
0527 static bool
0528 init_hw (void)
0529 {
0530   uint8 reg;
0531   bool res;
0532   int i;
0533 
0534   DLOG ("init_hw");
0535 
0536   iowrite8 (&map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
0537   reg = ioread8 (&map->CONFIG3);
0538 
0539   reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT;
0540   iowrite8(&map->CONFIG3, reg);
0541   iowrite32(&map->ANAPARAM2,
0542                     RTL8187B_RTL8225_ANAPARAM2_ON);
0543   iowrite32(&map->ANAPARAM,
0544                     RTL8187B_RTL8225_ANAPARAM_ON);
0545   iowrite8(&map->ANAPARAM3,
0546                    RTL8187B_RTL8225_ANAPARAM3_ON);
0547 
0548   iowrite8((u8 *)0xFF61, 0x10);
0549   reg = ioread8((u8 *)0xFF62);
0550   iowrite8((u8 *)0xFF62, reg & ~(1 << 5));
0551   iowrite8((u8 *)0xFF62, reg | (1 << 5));
0552 
0553   reg = ioread8(&map->CONFIG3);
0554   reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE;
0555   iowrite8(&map->CONFIG3, reg);
0556 
0557   iowrite8(&map->EEPROM_CMD,
0558                    RTL818X_EEPROM_CMD_NORMAL);
0559 
0560   res = cmd_reset();
0561   if (!res)
0562     return res;
0563 
0564   iowrite16((__le16 *)0xFF2D, 0x0FFF);
0565   reg = ioread8(&map->CW_CONF);
0566   reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
0567   iowrite8(&map->CW_CONF, reg);
0568   reg = ioread8(&map->TX_AGC_CTL);
0569   reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT |
0570     RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
0571   iowrite8(&map->TX_AGC_CTL, reg);
0572 
0573   iowrite16_idx((__le16 *)0xFFE0, 0x0FFF, 1);
0574 
0575   iowrite16(&map->BEACON_INTERVAL, 100);
0576   iowrite16(&map->ATIM_WND, 2);
0577   iowrite16_idx((__le16 *)0xFFD4, 0xFFFF, 1);
0578 
0579   iowrite8(&map->EEPROM_CMD,
0580                    RTL818X_EEPROM_CMD_CONFIG);
0581   reg = ioread8(&map->CONFIG1);
0582   iowrite8(&map->CONFIG1, (reg & 0x3F) | 0x80);
0583   iowrite8(&map->EEPROM_CMD,
0584                    RTL818X_EEPROM_CMD_NORMAL);
0585 
0586   iowrite8(&map->WPA_CONF, 0);
0587   for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) {
0588     iowrite8_idx(        (u8 *)(u32)
0589                          (rtl8187b_reg_table[i][0] | 0xFF00),
0590                          rtl8187b_reg_table[i][1],
0591                          rtl8187b_reg_table[i][2]);
0592   }
0593 
0594   iowrite16(&map->TID_AC_MAP, 0xFA50);
0595   iowrite16(&map->INT_MIG, 0);
0596 
0597   iowrite32_idx((__le32 *)0xFFF0, 0, 1);
0598   iowrite32_idx((__le32 *)0xFFF4, 0, 1);
0599   iowrite8_idx((u8 *)0xFFF8, 0, 1);
0600 
0601   iowrite32(&map->RF_TIMING, 0x00004001);
0602 
0603   iowrite16_idx((__le16 *)0xFF72, 0x569A, 2);
0604 
0605   iowrite8(&map->EEPROM_CMD,
0606                    RTL818X_EEPROM_CMD_CONFIG);
0607   reg = ioread8(&map->CONFIG3);
0608   reg |= RTL818X_CONFIG3_ANAPARAM_WRITE;
0609   iowrite8(&map->CONFIG3, reg);
0610   iowrite8(&map->EEPROM_CMD,
0611                    RTL818X_EEPROM_CMD_NORMAL);
0612 
0613   iowrite16(&map->RFPinsOutput, 0x0480);
0614   iowrite16(&map->RFPinsSelect, 0x2488);
0615   iowrite16(&map->RFPinsEnable, 0x1FFF);
0616   msleep(100);
0617 
0618   rf->init();
0619 
0620   reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE;
0621   iowrite8(&map->CMD, reg);
0622   iowrite16(&map->INT_MASK, 0xFFFF);
0623 
0624   iowrite8((u8 *)0xFE41, 0xF4);
0625   iowrite8((u8 *)0xFE40, 0x00);
0626   iowrite8((u8 *)0xFE42, 0x00);
0627   iowrite8((u8 *)0xFE42, 0x01);
0628   iowrite8((u8 *)0xFE40, 0x0F);
0629   iowrite8((u8 *)0xFE42, 0x00);
0630   iowrite8((u8 *)0xFE42, 0x01);
0631 
0632   reg = ioread8((u8 *)0xFFDB);
0633   iowrite8((u8 *)0xFFDB, reg | (1 << 2));
0634   iowrite16_idx((__le16 *)0xFF72, 0x59FA, 3);
0635   iowrite16_idx((__le16 *)0xFF74, 0x59D2, 3);
0636   iowrite16_idx((__le16 *)0xFF76, 0x59D2, 3);
0637   iowrite16_idx((__le16 *)0xFF78, 0x19FA, 3);
0638   iowrite16_idx((__le16 *)0xFF7A, 0x19FA, 3);
0639   iowrite16_idx((__le16 *)0xFF7C, 0x00D0, 3);
0640   iowrite8((u8 *)0xFF61, 0);
0641   iowrite8_idx((u8 *)0xFF80, 0x0F, 1);
0642   iowrite8_idx((u8 *)0xFF83, 0x03, 1);
0643   iowrite8((u8 *)0xFFDA, 0x10);
0644   iowrite8_idx((u8 *)0xFF4D, 0x08, 2);
0645 
0646   iowrite32(&map->HSSI_PARA, 0x0600321B);
0647 
0648   iowrite16_idx((__le16 *)0xFFEC, 0x0800, 1);
0649 
0650   slot_time = 0x9;
0651   aifsn[0] = 2; /* AIFSN[AC_VO] */
0652   aifsn[1] = 2; /* AIFSN[AC_VI] */
0653   aifsn[2] = 7; /* AIFSN[AC_BK] */
0654   aifsn[3] = 3; /* AIFSN[AC_BE] */
0655   iowrite8(&map->ACM_CONTROL, 0);
0656 
0657   /* ENEDCA flag must always be set, transmit issues? */
0658   iowrite8(&map->MSR, RTL818X_MSR_ENEDCA);
0659 
0660   return TRUE;
0661 }
0662 
0663 /* ************************************************** */
0664 
0665 static void
0666 debug_buf (char *prefix, uint8 *buf, u32 len)
0667 {
0668   s32 i, j;
0669 
0670   for (i=0;i<len;i+=8) {
0671     logger_printf ("%s: ", prefix);
0672     for (j=0;j<8;j++) {
0673       if (i+j >= len) break;
0674       logger_printf ("%.02X ", buf[i+j]);
0675     }
0676     logger_printf ("\n");
0677   }
0678 }
0679 
0680 /* ************************************************** */
0681 
0682 #define STATUS_EPT 9
0683 #define STATUS_MAXPKT 64
0684 
0685 /*
0686  * Read from status buffer:
0687  *
0688  * bits [30:31] = cmd type:
0689  * - 0 indicates tx beacon interrupt
0690  * - 1 indicates tx close descriptor
0691  *
0692  * In the case of tx beacon interrupt:
0693  * [0:9] = Last Beacon CW
0694  * [10:29] = reserved
0695  * [30:31] = 00b
0696  * [32:63] = Last Beacon TSF
0697  *
0698  * If it's tx close descriptor:
0699  * [0:7] = Packet Retry Count
0700  * [8:14] = RTS Retry Count
0701  * [15] = TOK
0702  * [16:27] = Sequence No
0703  * [28] = LS
0704  * [29] = FS
0705  * [30:31] = 01b
0706  * [32:47] = unused (reserved?)
0707  * [48:63] = MAC Used Time
0708  */
0709 
0710 static void
0711 do_status (void)
0712 {
0713   u64 buf;
0714   u32 act_len, pkt_rc, seq_no;
0715   bool tok;
0716 
0717   if (usb_bulk_transfer (usbdev, STATUS_EPT, &buf, sizeof (buf),
0718                          STATUS_MAXPKT, DIR_IN, &act_len) == 0) {
0719     if (act_len > 0) {
0720       DLOGTX ("status: 0x%.08X %.08X",
0721               (u32) (buf >> 32), (u32) buf);
0722       if (((buf >> 30) & 0x3) == 1) {
0723         /* TX close descriptor */
0724         pkt_rc = buf & 0xFF;
0725         tok = (buf & (1 << 15) ? TRUE : FALSE);
0726         seq_no = (buf >> 16) & 0xFFF;
0727         DLOGTX ("status: TX close: pkt_rc=%d tok=%d seq_no=0x%x LS=%d FS=%d",
0728                 pkt_rc, tok, seq_no,
0729                 (buf & (1 << 28)) ? TRUE : FALSE,
0730                 (buf & (1 << 29)) ? TRUE : FALSE);
0731       } else {
0732         /* TX beacon interrupt */
0733         DLOGTX ("status: TX beacon: last_CW=%d last_TSF=%d",
0734                 buf & 0x3FF,
0735                 buf >> 32);
0736       }
0737     } else
0738       DLOGTX ("status: act_len==0");
0739   }
0740 }
0741 
0742 /* ************************************************** */
0743 
0744 #define TX_MAXPKT 64
0745 static u8 tx_endps[4] = { 6, 7, 5, 4 };
0746 static volatile u8 cur_tx_ep = 0;
0747 
0748 struct rtl8187_tx_hdr {
0749   __le32 flags;
0750   __le16 rts_duration;
0751   __le16 len;
0752   __le32 retry;
0753 } PACKED;
0754 
0755 struct rtl8187b_tx_hdr {
0756   __le32 flags;
0757   __le16 rts_duration;
0758   __le16 len;
0759   __le32 unused_1;
0760   __le16 unused_2;
0761   __le16 tx_duration;
0762   __le32 unused_3;
0763   __le32 retry;
0764   __le32 unused_4[2];
0765 } PACKED;
0766 
0767 uint seq_no = 1;
0768 
0769 static int
0770 _tx (uint8 *pkt, u32 len)
0771 {
0772   struct ieee80211_hdr * dot11hdr = ((struct ieee80211_hdr *) pkt);
0773   u16 fc = dot11hdr->frame_control, dur_id;
0774   u32 act_len, rate=3 /*11mbps*/, acktime;
0775   int ret, ep;
0776   struct rtl8187b_tx_hdr hdr;
0777   static uint8 buf[2500];
0778 
0779   DLOGTX ("tx: 0x%x len=%d", pkt[0], len);
0780 
0781   memset (&hdr, 0, sizeof (hdr));
0782 
0783   hdr.flags = len;
0784   hdr.flags |= RTL818X_TX_DESC_FLAG_NO_ENC;
0785   hdr.flags |= RTL818X_TX_DESC_FLAG_FS;
0786   hdr.flags |= RTL818X_TX_DESC_FLAG_LS;
0787   hdr.retry = 0 << 8;
0788   hdr.tx_duration = ieee80211_calc_duration (len, rate);
0789 #define ACK_LEN 10
0790   acktime = ieee80211_calc_duration (ACK_LEN, rate);
0791   if (is_broadcast_ether_addr(dot11hdr->addr1))
0792     dur_id = 0;
0793   else {
0794     /* until I do fragmentation of packets...
0795     if (i == nr_frags - 1)
0796       dur_id = acktime + ieee->sifs_time;
0797     else {
0798       dur_id = 2*acktime + 3*ieee->sifs_time + hdr_len +
0799         ( i == nr_frags - 2) ? last_payload_size : payload_size;
0800     }
0801     */
0802     dur_id = 2*acktime + 3*SIFS_TIME + sizeof (struct ieee80211_hdr) + len;
0803   }
0804 
0805   dot11hdr->duration_id = __cpu_to_le16 (dur_id);
0806   memcpy (buf, &hdr, sizeof (hdr));
0807   memcpy (buf+sizeof (hdr), pkt, len);
0808 
0809   /* set sequence number */
0810   buf[sizeof (hdr)+22] = (seq_no & 0xF) << 4;
0811   buf[sizeof (hdr)+23] = (seq_no >> 4) & 0xFF;
0812 
0813   len += sizeof (hdr);
0814 
0815 #ifdef DEBUG_RTL8187B_TX
0816   debug_buf ("rtl8187b: tx", buf, len);
0817 #endif
0818 
0819   if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
0820     ep = 12;
0821   else
0822     ep = tx_endps[cur_tx_ep];
0823 
0824   if (usb_bulk_transfer (usbdev, ep, &buf, len,
0825                          TX_MAXPKT, DIR_OUT, &act_len) == 0) {
0826     do_status ();
0827     DLOGTX ("tx: sent %d bytes", act_len);
0828     ret=act_len;
0829   } else ret=0;
0830 
0831   if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) {
0832     cur_tx_ep++;
0833     cur_tx_ep &= 0x03;
0834   }
0835 
0836   seq_no++;
0837   seq_no &= 0xFFF;
0838 
0839   return ret;
0840 }
0841 
0842 #define TX_BUF_DATA_MAX 2500
0843 typedef struct {
0844   u8 data[TX_BUF_DATA_MAX];
0845   u32 len;
0846 } tx_qbuf_t;
0847 
0848 #define TX_BUF_LEN 1
0849 static uint32 tx_stack[1024] ALIGNED(0x1000);
0850 static circular tx_circ;
0851 static tx_qbuf_t tx_circ_buf[TX_BUF_LEN];
0852 static void
0853 tx_thread (void)
0854 {
0855   DLOGTX ("tx: hello from 0x%x", str ());
0856   for (;;) {
0857     tx_qbuf_t qb;
0858     circular_remove (&tx_circ, &qb);
0859     _tx (qb.data, qb.len);
0860   }
0861 }
0862 
0863 static int
0864 tx (struct ieee80211_hw *dev, sk_buff_t *skb)
0865 {
0866   tx_qbuf_t qb;
0867 
0868   if (skb->len > TX_BUF_DATA_MAX) return 0;
0869   qb.len = skb->len;
0870   memcpy (qb.data, skb->data, qb.len);
0871   circular_insert (&tx_circ, &qb);
0872   return skb->len;
0873 }
0874 
0875 static void
0876 tx_probe_resp (void)
0877 {
0878   uint8 pkt[] = {
0879     0x50, 0x00, 0x3A, 0x01,             /* PROBE RESPONSE */
0880     0x00, 0x23, 0x4D, 0xAF, 0x00, 0x3C, /* DA */
0881 
0882     //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0883     //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0884     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E, /* SA */
0885     0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7E, /* BSS ID */
0886 
0887     0x20, 0x00,
0888 
0889     0x8E, 0x91, 0x42, 0x11, 0x67, 0x00, 0x00, 0x00, /* timestamp */
0890     0x64, 0x00,                                     /* interval */
0891     0x01, 0x04,                                     /* capability */
0892 
0893     0x00, 0x06, 0x6C, 0x65, 0x6E, 0x6F, 0x76, 0x63, /* SSID lenovc */
0894 
0895     0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, 0x12, 0x18, 0x24
0896   };
0897   _tx (pkt, sizeof (pkt));
0898 }
0899 
0900 static void
0901 tx_beacon (void)
0902 {
0903   u32 len;
0904 #if 0
0905   uint8 pkt[] = {
0906     0x00, 0x01,                 /* MGMT AssocReq toDS */
0907     0x01, 0x05,
0908     0x00, 0x26, 0xCB, 0xD0, 0x77, 0x46, /* DA */
0909     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E, /* SA */
0910     0x00, 0x26, 0xCB, 0xD0, 0x77, 0x46, /* BSS ID */
0911     0x00, 0x00,                         /* SeqCtrl */
0912     /* SSID BU Wireless Help */
0913     0x00, 0x10, 0x42, 0x55, 0x20, 0x57, 0x69, 0x72, 0x65,
0914     0x6C, 0x65, 0x73, 0x73, 0x20, 0x48, 0x65, 0x6C, 0x70,
0915     /* Supported Rates */
0916     0x01, 0x08, 0x82, 0x84, 0x8B, 0x0C, 0x12, 0x96, 0x18, 0x24
0917   };
0918 #endif
0919 #if 0
0920   uint8 pkt[] = {
0921     0x80, 0x00,                 /* MGMT Beacon */
0922     0x00, 0x00,
0923     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
0924     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E, /* SA */
0925     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E, /* BSS ID */
0926     0x00, 0x00,                         /* SeqCtrl */
0927     0x8E, 0x91, 0x42, 0x11, 0x67, 0x00, 0x00, 0x00, /* timestamp */
0928     0x64, 0x00,                                     /* interval */
0929     0x01, 0x04,                                     /* capability */
0930     /* SSID Test */
0931     0x00, 0x04, 0x54, 0x65, 0x73, 0x74,
0932     /* Supported Rates */
0933     0x01, 0x08, 0x82, 0x84, 0x8B, 0x0C, 0x12, 0x96, 0x18, 0x24
0934   };
0935 #endif
0936 #if 1
0937   uint8 pkt[] = {
0938     0x80, 0x00, 0x00, 0x00,
0939     0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0940     //0x00, 0x23, 0x4d, 0xaf, 0x00, 0x3c,
0941     //0xb6, 0x27, 0x07, 0xb6, 0x00, 0x3c,
0942     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E, /* SA */
0943     0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7E, /* BSS ID */
0944     0x40, 0x46,
0945     0x00, 0x62, 0xc5, 0x02, 0x00, 0x00, 0x00, 0x00,
0946     0x64, 0x00,
0947     0x22, 0x00,
0948     0x00, 0x06, 0x6c, 0x65, 0x6e, 0x6f, 0x76, 0x63,
0949     0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24,
0950     0x03, 0x01, 0x01,
0951     0x06, 0x02, 0x00, 0x00,
0952     0x2a, 0x01, 0x00,
0953     0x32, 0x04, 0x30, 0x48, 0x60, 0x6c
0954   };
0955 #endif
0956 
0957   len = sizeof (pkt);
0958 
0959   _tx (pkt, len);
0960 }
0961 
0962 /* ************************************************** */
0963 
0964 /*
0965   15:48:57.615816 314us Probe Request (lenova) [1.0* 2.0* 5.5* 11.0* 6.0 9.0 12.0
0966   18.0 Mbit]
0967         0x0000:  4000 3a01 ffff ffff ffff 0023 4daf 003c
0968         0x0010:  ffff ffff ffff 7000 0006 6c65 6e6f 7661
0969         0x0020:  0108 8284 8b96 0c12 1824 3204 3048 606c
0970 */
0971 
0972 /*
0973 rtl8187b: rx: act_len=72
0974 rtl8187b: rx: 40 00 3A 01 FF FF FF FF
0975 rtl8187b: rx: FF FF 00 23 4D AF 00 3C
0976 rtl8187b: rx: FF FF FF FF FF FF 20 00
0977 rtl8187b: rx: 00 06 6C 65 6E 6F 76 63
0978 rtl8187b: rx: 01 08 82 84 8B 96 0C 12
0979 rtl8187b: rx: 18 24 32 04 30 48 60 6C
0980 rtl8187b: rx: 3E 87 B5 87 34 00 01 00
0981 rtl8187b: rx: 45 79 A5 0C 00 00 00 00
0982 rtl8187b: rx: 4B 90 FE 00 8E F6 EF 1C
0983 rtl8187b: HDR: flags=0x00010034 agc=0xFE rssi=0x90 mactime=0x00000000 0CA57945
0984 rtl8187b: FC=0x0040 MGMT 0x40 SEQ=0x0020
0985 rtl8187b: PROBE REQUEST
0986 rtl8187b:     SA=00:23:4D:AF:00:3C
0987 rtl8187b:   SSID lenovc
0988 rtl8187b:   SUPPORTED-RATE 0x82
0989 rtl8187b:   SUPPORTED-RATE 0x84
0990 rtl8187b:   SUPPORTED-RATE 0x8B
0991 rtl8187b:   SUPPORTED-RATE 0x96
0992 rtl8187b:   SUPPORTED-RATE 0x0C
0993 rtl8187b:   SUPPORTED-RATE 0x12
0994 rtl8187b:   SUPPORTED-RATE 0x18
0995 rtl8187b:   SUPPORTED-RATE 0x24
0996 */
0997 
0998 static u32 rx_conf;
0999 
1000 static uint32 rx_stack[2048] ALIGNED(0x1000);
1001 static uint32 status_stack[1024] ALIGNED(0x1000);
1002 
1003 #define RX_EPT (is_rtl8187b ? 3 : 1)
1004 #define RX_MAXPKT 64
1005 
1006 static void
1007 debug_info_element (u8 **p_buf, s32 *p_len)
1008 {
1009   uint8 ssid[IEEE80211_MAX_SSID_LEN+1];
1010   u8 *buf = *p_buf;
1011   s32 i;
1012 
1013   switch (buf[0]) {
1014   case WLAN_EID_SSID:
1015     memset (ssid, 0, IEEE80211_MAX_SSID_LEN+1);
1016     memcpy (ssid, &buf[2], buf[1]);
1017     DLOG ("  SSID %s", ssid);
1018     break;
1019   case WLAN_EID_SUPP_RATES:
1020     for (i=0; i<buf[1]; i++)
1021       DLOG ("  SUPPORTED-RATE 0x%.02X", buf[2+i]);
1022     break;
1023   case WLAN_EID_DS_PARAMS:
1024     DLOG ("  DS PARAMS CURRENT CHANNEL %d", buf[2]);
1025     break;
1026   case WLAN_EID_COUNTRY:
1027     DLOG ("  COUNTRY %c%c%c", buf[2], buf[3], buf[4]);
1028     break;
1029   default:
1030     DLOG ("  IE-ID %d LEN %d", buf[0], buf[1]);
1031     break;
1032   }
1033   *p_len -= (buf[1] + 2);
1034   *p_buf += (buf[1] + 2);
1035 }
1036 
1037 static void
1038 debug_info_elements (u8 *buf, s32 len)
1039 {
1040   uint8 id = 0;
1041   DLOG ("Info Elements: (%p, %d)", buf, len);
1042   while (len > 0) {
1043     if (buf[0] < id)
1044       /* elements come in ascending order by ID */
1045       break;
1046     id = buf[0];
1047     debug_info_element (&buf, &len);
1048   }
1049 }
1050 
1051 struct rtl8187_rx_hdr {
1052   __le32 flags;
1053   u8 noise;
1054   u8 signal;
1055   u8 agc;
1056   u8 reserved;
1057   __le64 mac_time;
1058 } PACKED;
1059 
1060 struct rtl8187b_rx_hdr {
1061   __le32 flags;
1062   __le64 mac_time;
1063   u8 sq;
1064   u8 rssi;
1065   u8 agc;
1066   u8 flags2;
1067   __le16 snr_long2end;
1068   s8 pwdb_g12;
1069   u8 fot;
1070 } PACKED;
1071 
1072 static void
1073 debug_rx (u8 *buf, u32 len)
1074 {
1075   u32 req = 0;
1076   struct ieee80211_hdr *h = (struct ieee80211_hdr *) buf;
1077   char *type;
1078   struct rtl8187b_rx_hdr *hdr =
1079     /* "footer" really */
1080     (struct rtl8187b_rx_hdr *) &buf[len - sizeof (struct rtl8187b_rx_hdr)];
1081 
1082   DLOG ("HDR: flags=0x%.08X agc=0x%X rssi=0x%X mactime=0x%.08X %.08X",
1083         hdr->flags, hdr->agc, hdr->rssi,
1084         (u32) (hdr->mac_time >> 32),
1085         (u32) hdr->mac_time);
1086 
1087   req += sizeof (struct ieee80211_hdr);
1088   if (len < req) return;
1089 
1090   if (ieee80211_is_mgmt (h->frame_control))
1091     type = "MGMT";
1092   else if (ieee80211_is_ctl (h->frame_control))
1093     type = "CTRL";
1094   else if (ieee80211_is_data (h->frame_control))
1095     type = "DATA";
1096   else
1097     type = "????";
1098 
1099   DLOG ("FC=0x%.04X %s 0x%x SEQ=0x%.04X", h->frame_control, type,
1100         h->frame_control & IEEE80211_FCTL_STYPE,
1101         h->seq_ctrl);
1102 
1103   if (h->seq_ctrl & 0x000F)
1104     /* don't bother with fragments beyond the first */
1105     return;
1106 
1107   if (ieee80211_is_beacon (h->frame_control)) {
1108     /* interpret beacon frame */
1109     struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
1110     DLOG ("BEACON bssid=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1111           m->bssid[0], m->bssid[1], m->bssid[2],
1112           m->bssid[3], m->bssid[4], m->bssid[5]);
1113     DLOG ("  time=0x%.08X %.08X interval=0x%.04X capability=0x%.04X %s %s",
1114           (u32) (m->u.beacon.timestamp >> 32),
1115           (u32) (m->u.beacon.timestamp >> 00),
1116           m->u.beacon.beacon_int,
1117           m->u.beacon.capab_info,
1118           m->u.beacon.capab_info & WLAN_CAPABILITY_ESS ? "ESS" : "",
1119           m->u.beacon.capab_info & WLAN_CAPABILITY_IBSS ? "IBSS" : "");
1120     debug_info_elements (m->u.beacon.variable,
1121                          len
1122                          /* minus FCS */
1123                          - 4
1124                          /* minus header */
1125                          - ((u32) m->u.beacon.variable - (u32) m));
1126   } else if (ieee80211_is_assoc_req (h->frame_control)) {
1127     struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
1128     uint8 *v = m->u.assoc_req.variable;
1129     s32 l = len;
1130     DLOG ("ASSOC REQUEST capab=0x%.04X interval=0x%.04X",
1131           m->u.assoc_req.capab_info,
1132           m->u.assoc_req.listen_interval);
1133     //debug_info_element (&v, &l); /* SSID */
1134     //debug_info_element (&v, &l); /* Supported Rates */
1135   } else if (ieee80211_is_assoc_resp (h->frame_control)) {
1136     struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
1137     uint8 *v = m->u.assoc_resp.variable;
1138     s32 l = len;
1139     DLOG ("ASSOC RESPONSE capab=0x%.04X status=0x%.04X aid=0x%.04X",
1140           m->u.assoc_resp.capab_info,
1141           m->u.assoc_resp.status_code,
1142           m->u.assoc_resp.aid);
1143     //debug_info_element (&v, &l); /* Supported Rates */
1144   } else if (ieee80211_is_probe_req (h->frame_control)) {
1145     struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf;
1146     uint8 *v = m->u.probe_req.variable;
1147     s32 l = len;
1148     DLOG ("PROBE REQUEST");
1149     DLOG ("    SA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1150             h->addr2[0], h->addr2[1], h->addr2[2],
1151             h->addr2[3], h->addr2[4], h->addr2[5]);
1152 #if 0
1153     if (h->addr2[0] == 0x00 &&
1154         h->addr2[1] == 0x23 &&
1155         h->addr2[2] == 0x4D &&
1156         h->addr2[3] == 0xAF &&
1157         h->addr2[4] == 0x00 &&
1158         h->addr2[5] == 0x3C   )
1159       tx_probe_resp ();
1160 #endif
1161     debug_info_element (&v, &l); /* SSID */
1162     debug_info_element (&v, &l); /* Supported Rates */
1163   } else if (ieee80211_is_probe_resp (h->frame_control)) {
1164     DLOG ("PROBE RESPONSE");
1165   } else if (ieee80211_is_data (h->frame_control)) {
1166     /* get some info out of a DATA frame */
1167     bool toDS, fromDS;
1168     toDS = ieee80211_has_tods (h->frame_control);
1169     fromDS = ieee80211_has_fromds (h->frame_control);
1170     if (!toDS && !fromDS) {
1171       DLOG ("  IBSS/DLS");
1172       DLOG ("    DA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1173             h->addr1[0], h->addr1[1], h->addr1[2],
1174             h->addr1[3], h->addr1[4], h->addr1[5]);
1175       DLOG ("    SA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1176             h->addr2[0], h->addr2[1], h->addr2[2],
1177             h->addr2[3], h->addr2[4], h->addr2[5]);
1178       DLOG ("    BSSID=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1179             h->addr3[0], h->addr3[1], h->addr3[2],
1180             h->addr3[3], h->addr3[4], h->addr3[5]);
1181     } else if (!toDS && fromDS) {
1182       DLOG ("  AP -> STA");
1183       DLOG ("    DA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1184             h->addr1[0], h->addr1[1], h->addr1[2],
1185             h->addr1[3], h->addr1[4], h->addr1[5]);
1186       DLOG ("    BSSID=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1187             h->addr2[0], h->addr2[1], h->addr2[2],
1188             h->addr2[3], h->addr2[4], h->addr2[5]);
1189       DLOG ("    SA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1190             h->addr3[0], h->addr3[1], h->addr3[2],
1191             h->addr3[3], h->addr3[4], h->addr3[5]);
1192     } else if (toDS && !fromDS) {
1193       DLOG ("  STA -> AP");
1194       DLOG ("    BSSID=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1195             h->addr1[0], h->addr1[1], h->addr1[2],
1196             h->addr1[3], h->addr1[4], h->addr1[5]);
1197       DLOG ("    SA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1198             h->addr2[0], h->addr2[1], h->addr2[2],
1199             h->addr2[3], h->addr2[4], h->addr2[5]);
1200       DLOG ("    DA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1201             h->addr3[0], h->addr3[1], h->addr3[2],
1202             h->addr3[3], h->addr3[4], h->addr3[5]);
1203     } else {
1204       DLOG ("  unspecified (WDS)");
1205       DLOG ("    RA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1206             h->addr1[0], h->addr1[1], h->addr1[2],
1207             h->addr1[3], h->addr1[4], h->addr1[5]);
1208       DLOG ("    TA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1209             h->addr2[0], h->addr2[1], h->addr2[2],
1210             h->addr2[3], h->addr2[4], h->addr2[5]);
1211       DLOG ("    DA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1212             h->addr3[0], h->addr3[1], h->addr3[2],
1213             h->addr3[3], h->addr3[4], h->addr3[5]);
1214       DLOG ("    SA=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1215             h->addr4[0], h->addr4[1], h->addr4[2],
1216             h->addr4[3], h->addr4[4], h->addr4[5]);
1217     }
1218   }
1219 }
1220 
1221 static void
1222 rx_thread (void)
1223 {
1224   u8 buf[RTL8187_MAX_RX];
1225   u32 act_len;
1226   int i;
1227 
1228   DLOG ("rx: hello from 0x%x", str ());
1229   lookup_TSS (str ())->priority = 0;
1230   for (;;) {
1231     if (usb_bulk_transfer (usbdev, RX_EPT, &buf, sizeof (buf),
1232                            RX_MAXPKT, DIR_IN, &act_len) == 0) {
1233       if (act_len > sizeof (struct rtl8187b_rx_hdr)) {
1234         struct sk_buff skb;
1235 #ifdef DEBUG_RTL8187B
1236         DLOG ("rx: act_len=%d", act_len);
1237         debug_buf ("rtl8187b: rx", buf, act_len);
1238         debug_rx (buf, act_len);
1239 #endif
1240         skb.data = buf;
1241         skb.len = act_len - sizeof (struct rtl8187b_rx_hdr);
1242         ieee80211_rx (hwdev, &skb);
1243       } else
1244         DLOG ("rx: packet < %d", sizeof (struct rtl8187b_rx_hdr));
1245     }
1246   }
1247 }
1248 
1249 static void
1250 status_thread (void)
1251 {
1252   DLOG ("status: hello from 0x%x", str ());
1253   for (;;) {
1254   }
1255 }
1256 
1257 static void
1258 init_urbs (void)
1259 {
1260   start_kernel_thread ((u32) rx_thread, (u32) &rx_stack[2047]);
1261 }
1262 
1263 static void
1264 init_status_urb (void)
1265 {
1266   //start_kernel_thread ((u32) status_thread, (u32) &status_stack[1023]);
1267 }
1268 
1269 static bool
1270 start (struct ieee80211_hw *hw)
1271 {
1272   u32 reg;
1273   bool ret;
1274 
1275   ret = init_hw ();
1276 
1277   if (!ret)
1278     goto rtl8187_start_exit;
1279 
1280   //init_usb_anchor(&priv->anchored);
1281 
1282   circular_init (&tx_circ, tx_circ_buf, TX_BUF_LEN, sizeof (tx_qbuf_t));
1283   start_kernel_thread ((u32) tx_thread, (u32) &tx_stack[1023]);
1284 
1285   if (is_rtl8187b) {
1286     reg = RTL818X_RX_CONF_MGMT |
1287       RTL818X_RX_CONF_DATA |
1288       RTL818X_RX_CONF_BROADCAST |
1289       RTL818X_RX_CONF_NICMAC |
1290       RTL818X_RX_CONF_BSSID |
1291       (7 << 13 /* RX FIFO threshold NONE */) |
1292       (7 << 10 /* MAX RX DMA */) |
1293       RTL818X_RX_CONF_RX_AUTORESETPHY |
1294       RTL818X_RX_CONF_ONLYERLPKT |
1295       RTL818X_RX_CONF_MULTICAST;
1296     rx_conf = reg;
1297     iowrite32(&map->RX_CONF, reg);
1298 
1299     iowrite32(&map->TX_CONF,
1300                       RTL818X_TX_CONF_HW_SEQNUM |
1301                       RTL818X_TX_CONF_DISREQQSIZE |
1302                       (7 << 8  /* short retry limit */) |
1303                       (7 << 0  /* long retry limit */) |
1304                       (7 << 21 /* MAX TX DMA */));
1305     init_urbs();
1306     init_status_urb();
1307     goto rtl8187_start_exit;
1308   }
1309 
1310   iowrite16(&map->INT_MASK, 0xFFFF);
1311 
1312   iowrite32(&map->MAR[0], ~0);
1313   iowrite32(&map->MAR[1], ~0);
1314 
1315   init_urbs();
1316 
1317   reg = RTL818X_RX_CONF_ONLYERLPKT |
1318     RTL818X_RX_CONF_RX_AUTORESETPHY |
1319     RTL818X_RX_CONF_BSSID |
1320     RTL818X_RX_CONF_MGMT |
1321     RTL818X_RX_CONF_DATA |
1322     (7 << 13 /* RX FIFO threshold NONE */) |
1323     (7 << 10 /* MAX RX DMA */) |
1324     RTL818X_RX_CONF_BROADCAST |
1325     RTL818X_RX_CONF_NICMAC;
1326 
1327   rx_conf = reg;
1328   iowrite32(&map->RX_CONF, reg);
1329 
1330   reg = ioread8(&map->CW_CONF);
1331   reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
1332   reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
1333   iowrite8(&map->CW_CONF, reg);
1334 
1335   reg = ioread8(&map->TX_AGC_CTL);
1336   reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
1337   reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
1338   reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
1339   iowrite8(&map->TX_AGC_CTL, reg);
1340 
1341   reg  = RTL818X_TX_CONF_CW_MIN |
1342     (7 << 21 /* MAX TX DMA */) |
1343     RTL818X_TX_CONF_NO_ICV;
1344   iowrite32(&map->TX_CONF, reg);
1345 
1346   reg = ioread8(&map->CMD);
1347   reg |= RTL818X_CMD_TX_ENABLE;
1348   reg |= RTL818X_CMD_RX_ENABLE;
1349   iowrite8(&map->CMD, reg);
1350   //INIT_DELAYED_WORK(&priv->work, rtl8187_work);
1351 
1352  rtl8187_start_exit:
1353   return ret;
1354 }
1355 
1356 static void
1357 stop (struct ieee80211_hw *hw)
1358 {
1359   DLOG ("stop");
1360 }
1361 
1362 static uint16 txpwr_base;
1363 static uint8 asic_rev, queues;
1364 const struct rtl818x_rf_ops * rtl8187_detect_rf(void);
1365 
1366 static struct ieee80211_ops rtl8187b_ops = {
1367   .start            = start,
1368   .stop             = stop,
1369   .config           = config,
1370   .add_interface    = add_iface,
1371   .remove_interface = rem_iface,
1372   .bss_info_changed = bss_info_changed,
1373   .conf_tx          = conf_tx,
1374   .tx               = tx
1375 };
1376 
1377 static bool
1378 probe (USB_DEVICE_INFO *info, USB_CFG_DESC *cfgd, USB_IF_DESC *ifd)
1379 {
1380   struct ieee80211_hw *dev;
1381   char *chipname;
1382   int i;
1383   uint8 reg;
1384   uint16 txpwr, reg16;
1385   struct ieee80211_channel *channel;
1386 
1387   for (i=0; compat_list[i].v != 0xFFFF; i++) {
1388     if (compat_list[i].v == info->devd.idVendor &&
1389         compat_list[i].p == info->devd.idProduct)
1390       break;
1391   }
1392   if (compat_list[i].v == 0xFFFF)
1393     return FALSE;
1394   DLOG ("Found USB device address=%d: %s", info->address, compat_list[i].s);
1395 
1396   if (usb_set_configuration (info, cfgd->bConfigurationValue) != 0) {
1397     DLOG ("set_configuration: failed");
1398     return FALSE;
1399   }
1400 
1401   usbdev = info;
1402   is_rtl8187b = TRUE;           /* assume for now */
1403 
1404   eeprom.register_read = eeprom_read;
1405   eeprom.register_write = eeprom_write;
1406   if (ioread32 (&map->RX_CONF) & (1 << 6))
1407     eeprom.width = PCI_EEPROM_WIDTH_93C66;
1408   else
1409     eeprom.width = PCI_EEPROM_WIDTH_93C46;
1410 
1411   iowrite8 (&map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
1412   udelay (10);
1413   eeprom_93cx6_multiread (&eeprom, RTL8187_EEPROM_MAC_ADDR,
1414                           (uint16 *) ethaddr, 3);
1415 
1416   DLOG ("ethaddr=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
1417         ethaddr[0], ethaddr[1], ethaddr[2],
1418         ethaddr[3], ethaddr[4], ethaddr[5]);
1419 
1420   eeprom_93cx6_read (&eeprom, RTL8187_EEPROM_TXPWR_BASE, &txpwr_base);
1421   DLOG ("txpwr_base=0x%.04X", txpwr_base);
1422 
1423   reg = ioread8 (&map->PGSELECT) & ~1;
1424   iowrite8 (&map->PGSELECT, reg | 1);
1425   /* 0 means asic B-cut, we should use SW 3 wire
1426    * bit-by-bit banging for radio. 1 means we can use
1427    * USB specific request to write radio registers */
1428   asic_rev = ioread8 ((uint8*) 0xFFFE) & 0x3;
1429   iowrite8 (&map->PGSELECT, reg);
1430   iowrite8 (&map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
1431 
1432   DLOG ("asic_rev=0x%.02X", asic_rev);
1433 
1434   if (!is_rtl8187b) {
1435     u32 reg32;
1436     reg32 = ioread32(&map->TX_CONF);
1437     reg32 &= RTL818X_TX_CONF_HWVER_MASK;
1438     switch (reg32) {
1439     case RTL818X_TX_CONF_R8187vD_B:
1440       /* Some RTL8187B devices have a USB ID of 0x8187
1441        * detect them here */
1442       chipname = "RTL8187BvB(early)";
1443       is_rtl8187b = TRUE;
1444       hw_rev = RTL8187BvB;
1445       break;
1446     case RTL818X_TX_CONF_R8187vD:
1447       chipname = "RTL8187vD";
1448       break;
1449     default:
1450       chipname = "RTL8187vB (default)";
1451       break;
1452     }
1453   } else {
1454 
1455     switch (ioread8 ((u8*)0xFFE1)) {
1456     case RTL818X_R8187B_B:
1457       hw_rev = RTL8187BvB;
1458       chipname = "RTL8187BvB";
1459       break;
1460     case RTL818X_R8187B_D:
1461       hw_rev = RTL8187BvD;
1462       chipname = "RTL8187BvD";
1463       break;
1464     case RTL818X_R8187B_E:
1465       hw_rev = RTL8187BvE;
1466       chipname = "RTL8187BvE";
1467       break;
1468     default:
1469       hw_rev = RTL8187BvB;
1470       chipname = "RTL8187BvB (default)";
1471       break;
1472     }
1473   }
1474   DLOG ("hw_rev=%s", chipname);
1475 
1476   memcpy (channels, rtl818x_channels, sizeof (rtl818x_channels));
1477   memcpy (rates, rtl818x_rates, sizeof (rtl818x_rates));
1478 
1479   channel = channels;
1480   for (i=0; i<3; i++) {
1481     eeprom_93cx6_read (&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
1482                        &txpwr);
1483     (*channel++).hw_value = txpwr & 0xFF;
1484     (*channel++).hw_value = txpwr >> 8;
1485   }
1486   for (i=0; i<2; i++) {
1487     eeprom_93cx6_read (&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
1488                        &txpwr);
1489     (*channel++).hw_value = txpwr & 0xFF;
1490     (*channel++).hw_value = txpwr >> 8;
1491   }
1492 
1493   if (!is_rtl8187b) {
1494     for (i = 0; i < 2; i++) {
1495       eeprom_93cx6_read(&eeprom,
1496                         RTL8187_EEPROM_TXPWR_CHAN_6 + i,
1497                         &txpwr);
1498       (*channel++).hw_value = txpwr & 0xFF;
1499       (*channel++).hw_value = txpwr >> 8;
1500     }
1501   } else {
1502     eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6,
1503                       &txpwr);
1504     (*channel++).hw_value = txpwr & 0xFF;
1505 
1506     eeprom_93cx6_read(&eeprom, 0x0A, &txpwr);
1507     (*channel++).hw_value = txpwr & 0xFF;
1508 
1509     eeprom_93cx6_read(&eeprom, 0x1C, &txpwr);
1510     (*channel++).hw_value = txpwr & 0xFF;
1511     (*channel++).hw_value = txpwr >> 8;
1512   }
1513 
1514   rfkill_mask = RFKILL_MASK_8187_89_97;
1515   eeprom_93cx6_read (&eeprom, RTL8187_EEPROM_SELECT_GPIO, &reg16);
1516   if (reg16 & 0xFF00)
1517     rfkill_mask = RFKILL_MASK_8198;
1518   DLOG ("rfkill_mask=0x%x", rfkill_mask);
1519 
1520   rf = rtl8187_detect_rf ();
1521   DLOG ("detected RF name: %s", rf->name);
1522 
1523   if (is_rtl8187b) queues = 4; else queues = 1;
1524 
1525   rfkill_init ();
1526 
1527   hwdev = dev = ieee80211_alloc_hw (0, &rtl8187b_ops);
1528 
1529   if (!dev) return FALSE;
1530 
1531   if (!ieee80211_register_hw (dev))
1532     return FALSE;
1533 
1534   return TRUE;
1535 }
1536 
1537 /* ************************************************** */
1538 
1539 static USB_DRIVER rtl8187b_usb_driver = {
1540   .probe = probe
1541 };
1542 
1543 extern bool
1544 usb_rtl8187b_driver_init (void)
1545 {
1546   return usb_register_driver (&rtl8187b_usb_driver);
1547 }
1548 
1549 /* ************************************************** */
1550 
1551 /* Radio tuning for RTL8225 on RTL8187 */
1552 
1553 static inline
1554 void rtl8225_write_phy_ofdm(u8 addr, u32 data)
1555 {
1556   rtl8187_write_phy (addr, data);
1557 }
1558 
1559 static inline
1560 void rtl8225_write_phy_cck(u8 addr, u32 data)
1561 {
1562   rtl8187_write_phy (addr, data | 0x10000);
1563 }
1564 
1565 /* used when asic_rev==0 */
1566 static void
1567 rtl8225_write_bitbang (u8 addr, u16 data)
1568 {
1569   u16 reg80, reg84, reg82;
1570   u32 bangdata;
1571   int i;
1572 
1573   bangdata = (data << 4) | (addr & 0xf);
1574 
1575   reg80 = ioread16(&map->RFPinsOutput) & 0xfff3;
1576   reg82 = ioread16(&map->RFPinsEnable);
1577 
1578   iowrite16(&map->RFPinsEnable, reg82 | 0x7);
1579 
1580   reg84 = ioread16(&map->RFPinsSelect);
1581   iowrite16(&map->RFPinsSelect, reg84 | 0x7);
1582   udelay(10);
1583 
1584   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1585   udelay(2);
1586   iowrite16(&map->RFPinsOutput, reg80);
1587   udelay(10);
1588 
1589   for (i = 15; i >= 0; i--) {
1590     u16 reg = reg80 | (bangdata & (1 << i)) >> i;
1591 
1592     if (i & 1)
1593       iowrite16(&map->RFPinsOutput, reg);
1594 
1595     iowrite16(&map->RFPinsOutput, reg | (1 << 1));
1596     iowrite16(&map->RFPinsOutput, reg | (1 << 1));
1597 
1598     if (!(i & 1))
1599       iowrite16(&map->RFPinsOutput, reg);
1600   }
1601 
1602   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1603   udelay(10);
1604 
1605   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1606   iowrite16(&map->RFPinsSelect, reg84);
1607 }
1608 
1609 static void
1610 rtl8225_write_8051(u8 addr, __le16 data)
1611 {
1612   u16 reg80, reg82, reg84;
1613 
1614   reg80 = ioread16(&map->RFPinsOutput);
1615   reg82 = ioread16(&map->RFPinsEnable);
1616   reg84 = ioread16(&map->RFPinsSelect);
1617 
1618   reg80 &= ~(0x3 << 2);
1619   reg84 &= ~0xF;
1620 
1621   iowrite16(&map->RFPinsEnable, reg82 | 0x0007);
1622   iowrite16(&map->RFPinsSelect, reg84 | 0x0007);
1623   udelay(10);
1624 
1625   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1626   udelay(2);
1627 
1628   iowrite16(&map->RFPinsOutput, reg80);
1629   udelay(10);
1630 
1631   control_msg(RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
1632               addr, 0x8225, (uint8*)&data, sizeof(data));
1633 
1634   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1635   udelay(10);
1636 
1637   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1638   iowrite16(&map->RFPinsSelect, reg84);
1639 }
1640 
1641 static void rtl8225_write(u8 addr, u16 data)
1642 {
1643   if (asic_rev)
1644     rtl8225_write_8051(addr, data);
1645   else
1646     rtl8225_write_bitbang(addr, data);
1647 }
1648 
1649 static u16 rtl8225_read(u8 addr)
1650 {
1651   u16 reg80, reg82, reg84, out;
1652   int i;
1653 
1654   reg80 = ioread16(&map->RFPinsOutput);
1655   reg82 = ioread16(&map->RFPinsEnable);
1656   reg84 = ioread16(&map->RFPinsSelect);
1657 
1658   reg80 &= ~0xF;
1659 
1660   iowrite16(&map->RFPinsEnable, reg82 | 0x000F);
1661   iowrite16(&map->RFPinsSelect, reg84 | 0x000F);
1662 
1663   iowrite16(&map->RFPinsOutput, reg80 | (1 << 2));
1664   udelay(4);
1665   iowrite16(&map->RFPinsOutput, reg80);
1666   udelay(5);
1667 
1668   for (i = 4; i >= 0; i--) {
1669     u16 reg = reg80 | ((addr >> i) & 1);
1670 
1671     if (!(i & 1)) {
1672       iowrite16(&map->RFPinsOutput, reg);
1673       udelay(1);
1674     }
1675 
1676     iowrite16(&map->RFPinsOutput,
1677                       reg | (1 << 1));
1678     udelay(2);
1679     iowrite16(&map->RFPinsOutput,
1680                       reg | (1 << 1));
1681     udelay(2);
1682 
1683     if (i & 1) {
1684       iowrite16(&map->RFPinsOutput, reg);
1685       udelay(1);
1686     }
1687   }
1688 
1689   iowrite16(&map->RFPinsOutput,
1690                     reg80 | (1 << 3) | (1 << 1));
1691   udelay(2);
1692   iowrite16(&map->RFPinsOutput,
1693                     reg80 | (1 << 3));
1694   udelay(2);
1695   iowrite16(&map->RFPinsOutput,
1696                     reg80 | (1 << 3));
1697   udelay(2);
1698 
1699   out = 0;
1700   for (i = 11; i >= 0; i--) {
1701     iowrite16(&map->RFPinsOutput,
1702                       reg80 | (1 << 3));
1703     udelay(1);
1704     iowrite16(&map->RFPinsOutput,
1705                       reg80 | (1 << 3) | (1 << 1));
1706     udelay(2);
1707     iowrite16(&map->RFPinsOutput,
1708                       reg80 | (1 << 3) | (1 << 1));
1709     udelay(2);
1710     iowrite16(&map->RFPinsOutput,
1711                       reg80 | (1 << 3) | (1 << 1));
1712     udelay(2);
1713 
1714     if (ioread16(&map->RFPinsInput) & (1 << 1))
1715       out |= 1 << i;
1716 
1717     iowrite16(&map->RFPinsOutput,
1718                       reg80 | (1 << 3));
1719     udelay(2);
1720   }
1721 
1722   iowrite16(&map->RFPinsOutput,
1723                     reg80 | (1 << 3) | (1 << 2));
1724   udelay(2);
1725 
1726   iowrite16(&map->RFPinsEnable, reg82);
1727   iowrite16(&map->RFPinsSelect, reg84);
1728   iowrite16(&map->RFPinsOutput, 0x03A0);
1729 
1730   return out;
1731 }
1732 
1733 static const u16 rtl8225bcd_rxgain[] = {
1734   0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
1735   0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
1736   0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
1737   0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
1738   0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
1739   0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
1740   0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
1741   0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
1742   0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
1743   0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
1744   0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
1745   0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
1746 };
1747 
1748 static const u8 rtl8225_agc[] = {
1749   0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
1750   0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
1751   0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
1752   0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
1753   0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
1754   0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
1755   0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
1756   0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
1757   0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
1758   0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
1759   0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
1760   0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
1761   0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
1762   0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1763   0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1764   0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
1765 };
1766 
1767 static const u8 rtl8225_gain[] = {
1768   0x23, 0x88, 0x7c, 0xa5,   /* -82dBm */
1769   0x23, 0x88, 0x7c, 0xb5,   /* -82dBm */
1770   0x23, 0x88, 0x7c, 0xc5,   /* -82dBm */
1771   0x33, 0x80, 0x79, 0xc5,   /* -78dBm */
1772   0x43, 0x78, 0x76, 0xc5,   /* -74dBm */
1773   0x53, 0x60, 0x73, 0xc5,   /* -70dBm */
1774   0x63, 0x58, 0x70, 0xc5,   /* -66dBm */
1775 };
1776 
1777 static const u8 rtl8225_threshold[] = {
1778   0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
1779 };
1780 
1781 static const u8 rtl8225_tx_gain_cck_ofdm[] = {
1782   0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
1783 };
1784 
1785 static const u8 rtl8225_tx_power_cck[] = {
1786   0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
1787   0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
1788   0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
1789   0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
1790   0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
1791   0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
1792 };
1793 
1794 static const u8 rtl8225_tx_power_cck_ch14[] = {
1795   0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
1796   0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
1797   0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
1798   0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
1799   0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
1800   0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
1801 };
1802 
1803 static const u8 rtl8225_tx_power_ofdm[] = {
1804   0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
1805 };
1806 
1807 static const u32 rtl8225_chan[] = {
1808   0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
1809   0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
1810 };
1811 
1812 #define min(a,b) ((a) < (b) ? (a) : (b))
1813 
1814 static void rtl8225_rf_set_tx_power(int channel)
1815 {
1816   u8 cck_power, ofdm_power;
1817   const u8 *tmp;
1818   u32 reg;
1819   int i;
1820 
1821   cck_power = channels[channel - 1].hw_value & 0xF;
1822   ofdm_power = channels[channel - 1].hw_value >> 4;
1823 
1824   cck_power = min(cck_power, (u8)11);
1825   if (ofdm_power > (u8)15)
1826     ofdm_power = 25;
1827   else
1828     ofdm_power += 10;
1829 
1830   iowrite8(&map->TX_GAIN_CCK,
1831                    rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
1832 
1833   if (channel == 14)
1834     tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
1835   else
1836     tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
1837 
1838   for (i = 0; i < 8; i++)
1839     rtl8225_write_phy_cck(0x44 + i, *tmp++);
1840 
1841   msleep(1); // FIXME: optional?
1842 
1843   /* anaparam2 on */
1844   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
1845   reg = ioread8(&map->CONFIG3);
1846   iowrite8(&map->CONFIG3,
1847                    reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
1848   iowrite32(&map->ANAPARAM2,
1849                     RTL8187_RTL8225_ANAPARAM2_ON);
1850   iowrite8(&map->CONFIG3,
1851                    reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
1852   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
1853 
1854   rtl8225_write_phy_ofdm(2, 0x42);
1855   rtl8225_write_phy_ofdm(6, 0x00);
1856   rtl8225_write_phy_ofdm(8, 0x00);
1857 
1858   iowrite8(&map->TX_GAIN_OFDM,
1859                    rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
1860 
1861   tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
1862 
1863   rtl8225_write_phy_ofdm(5, *tmp);
1864   rtl8225_write_phy_ofdm(7, *tmp);
1865 
1866   msleep(1);
1867 }
1868 
1869 static void
1870 rtl8225_rf_init(void)
1871 {
1872   int i;
1873 
1874   rtl8225_write(0x0, 0x067);
1875   rtl8225_write(0x1, 0xFE0);
1876   rtl8225_write(0x2, 0x44D);
1877   rtl8225_write(0x3, 0x441);
1878   rtl8225_write(0x4, 0x486);
1879   rtl8225_write(0x5, 0xBC0);
1880   rtl8225_write(0x6, 0xAE6);
1881   rtl8225_write(0x7, 0x82A);
1882   rtl8225_write(0x8, 0x01F);
1883   rtl8225_write(0x9, 0x334);
1884   rtl8225_write(0xA, 0xFD4);
1885   rtl8225_write(0xB, 0x391);
1886   rtl8225_write(0xC, 0x050);
1887   rtl8225_write(0xD, 0x6DB);
1888   rtl8225_write(0xE, 0x029);
1889   rtl8225_write(0xF, 0x914); msleep(100);
1890 
1891   rtl8225_write(0x2, 0xC4D); msleep(200);
1892   rtl8225_write(0x2, 0x44D); msleep(200);
1893 
1894   if (!(rtl8225_read(6) & (1 << 7))) {
1895     rtl8225_write(0x02, 0x0c4d);
1896     msleep(200);
1897     rtl8225_write(0x02, 0x044d);
1898     msleep(100);
1899     if (!(rtl8225_read(6) & (1 << 7)))
1900       DLOG("RF Calibration Failed! %x\n",
1901            rtl8225_read(6));
1902   }
1903 
1904   rtl8225_write(0x0, 0x127);
1905 
1906   for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
1907     rtl8225_write(0x1, i + 1);
1908     rtl8225_write(0x2, rtl8225bcd_rxgain[i]);
1909   }
1910 
1911   rtl8225_write(0x0, 0x027);
1912   rtl8225_write(0x0, 0x22F);
1913 
1914   for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
1915     rtl8225_write_phy_ofdm(0xB, rtl8225_agc[i]);
1916     rtl8225_write_phy_ofdm(0xA, 0x80 + i);
1917   }
1918 
1919   msleep(1);
1920 
1921   rtl8225_write_phy_ofdm(0x00, 0x01);
1922   rtl8225_write_phy_ofdm(0x01, 0x02);
1923   rtl8225_write_phy_ofdm(0x02, 0x42);
1924   rtl8225_write_phy_ofdm(0x03, 0x00);
1925   rtl8225_write_phy_ofdm(0x04, 0x00);
1926   rtl8225_write_phy_ofdm(0x05, 0x00);
1927   rtl8225_write_phy_ofdm(0x06, 0x40);
1928   rtl8225_write_phy_ofdm(0x07, 0x00);
1929   rtl8225_write_phy_ofdm(0x08, 0x40);
1930   rtl8225_write_phy_ofdm(0x09, 0xfe);
1931   rtl8225_write_phy_ofdm(0x0a, 0x09);
1932   rtl8225_write_phy_ofdm(0x0b, 0x80);
1933   rtl8225_write_phy_ofdm(0x0c, 0x01);
1934   rtl8225_write_phy_ofdm(0x0e, 0xd3);
1935   rtl8225_write_phy_ofdm(0x0f, 0x38);
1936   rtl8225_write_phy_ofdm(0x10, 0x84);
1937   rtl8225_write_phy_ofdm(0x11, 0x06);
1938   rtl8225_write_phy_ofdm(0x12, 0x20);
1939   rtl8225_write_phy_ofdm(0x13, 0x20);
1940   rtl8225_write_phy_ofdm(0x14, 0x00);
1941   rtl8225_write_phy_ofdm(0x15, 0x40);
1942   rtl8225_write_phy_ofdm(0x16, 0x00);
1943   rtl8225_write_phy_ofdm(0x17, 0x40);
1944   rtl8225_write_phy_ofdm(0x18, 0xef);
1945   rtl8225_write_phy_ofdm(0x19, 0x19);
1946   rtl8225_write_phy_ofdm(0x1a, 0x20);
1947   rtl8225_write_phy_ofdm(0x1b, 0x76);
1948   rtl8225_write_phy_ofdm(0x1c, 0x04);
1949   rtl8225_write_phy_ofdm(0x1e, 0x95);
1950   rtl8225_write_phy_ofdm(0x1f, 0x75);
1951   rtl8225_write_phy_ofdm(0x20, 0x1f);
1952   rtl8225_write_phy_ofdm(0x21, 0x27);
1953   rtl8225_write_phy_ofdm(0x22, 0x16);
1954   rtl8225_write_phy_ofdm(0x24, 0x46);
1955   rtl8225_write_phy_ofdm(0x25, 0x20);
1956   rtl8225_write_phy_ofdm(0x26, 0x90);
1957   rtl8225_write_phy_ofdm(0x27, 0x88);
1958 
1959   rtl8225_write_phy_ofdm(0x0d, rtl8225_gain[2 * 4]);
1960   rtl8225_write_phy_ofdm(0x1b, rtl8225_gain[2 * 4 + 2]);
1961   rtl8225_write_phy_ofdm(0x1d, rtl8225_gain[2 * 4 + 3]);
1962   rtl8225_write_phy_ofdm(0x23, rtl8225_gain[2 * 4 + 1]);
1963 
1964   rtl8225_write_phy_cck(0x00, 0x98);
1965   rtl8225_write_phy_cck(0x03, 0x20);
1966   rtl8225_write_phy_cck(0x04, 0x7e);
1967   rtl8225_write_phy_cck(0x05, 0x12);
1968   rtl8225_write_phy_cck(0x06, 0xfc);
1969   rtl8225_write_phy_cck(0x07, 0x78);
1970   rtl8225_write_phy_cck(0x08, 0x2e);
1971   rtl8225_write_phy_cck(0x10, 0x9b);
1972   rtl8225_write_phy_cck(0x11, 0x88);
1973   rtl8225_write_phy_cck(0x12, 0x47);
1974   rtl8225_write_phy_cck(0x13, 0xd0);
1975   rtl8225_write_phy_cck(0x19, 0x00);
1976   rtl8225_write_phy_cck(0x1a, 0xa0);
1977   rtl8225_write_phy_cck(0x1b, 0x08);
1978   rtl8225_write_phy_cck(0x40, 0x86);
1979   rtl8225_write_phy_cck(0x41, 0x8d);
1980   rtl8225_write_phy_cck(0x42, 0x15);
1981   rtl8225_write_phy_cck(0x43, 0x18);
1982   rtl8225_write_phy_cck(0x44, 0x1f);
1983   rtl8225_write_phy_cck(0x45, 0x1e);
1984   rtl8225_write_phy_cck(0x46, 0x1a);
1985   rtl8225_write_phy_cck(0x47, 0x15);
1986   rtl8225_write_phy_cck(0x48, 0x10);
1987   rtl8225_write_phy_cck(0x49, 0x0a);
1988   rtl8225_write_phy_cck(0x4a, 0x05);
1989   rtl8225_write_phy_cck(0x4b, 0x02);
1990   rtl8225_write_phy_cck(0x4c, 0x05);
1991 
1992   iowrite8(&map->TESTR, 0x0D);
1993 
1994   rtl8225_rf_set_tx_power(1);
1995 
1996   /* RX antenna default to A */
1997   rtl8225_write_phy_cck(0x10, 0x9b);            /* B: 0xDB */
1998   rtl8225_write_phy_ofdm(0x26, 0x90);       /* B: 0x10 */
1999 
2000   iowrite8(&map->TX_ANTENNA, 0x03); /* B: 0x00 */
2001   msleep(1);
2002   iowrite32((__le32 *)0xFF94, 0x3dc00002);
2003 
2004   /* set sensitivity */
2005   rtl8225_write(0x0c, 0x50);
2006   rtl8225_write_phy_ofdm(0x0d, rtl8225_gain[2 * 4]);
2007   rtl8225_write_phy_ofdm(0x1b, rtl8225_gain[2 * 4 + 2]);
2008   rtl8225_write_phy_ofdm(0x1d, rtl8225_gain[2 * 4 + 3]);
2009   rtl8225_write_phy_ofdm(0x23, rtl8225_gain[2 * 4 + 1]);
2010   rtl8225_write_phy_cck(0x41, rtl8225_threshold[2]);
2011 }
2012 
2013 static const u8 rtl8225z2_agc[] = {
2014   0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
2015   0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
2016   0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
2017   0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
2018   0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2019   0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
2020   0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
2021   0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
2022   0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
2023   0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
2024   0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
2025 };
2026 static const u8 rtl8225z2_ofdm[] = {
2027   0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
2028   0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
2029   0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
2030   0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
2031   0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
2032   0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
2033   0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
2034   0x6d, 0x3c, 0xfb, 0x07
2035 };
2036 
2037 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
2038   0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
2039   0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
2040   0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
2041   0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
2042 };
2043 
2044 static const u8 rtl8225z2_tx_power_cck[] = {
2045   0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
2046   0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
2047   0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
2048   0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
2049 };
2050 
2051 static const u8 rtl8225z2_tx_power_ofdm[] = {
2052   0x42, 0x00, 0x40, 0x00, 0x40
2053 };
2054 
2055 static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
2056   0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
2057   0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
2058   0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
2059   0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
2060   0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
2061   0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
2062 };
2063 
2064 static void rtl8225z2_rf_set_tx_power(int channel)
2065 {
2066   u8 cck_power, ofdm_power;
2067   const u8 *tmp;
2068   u32 reg;
2069   int i;
2070 
2071   cck_power = channels[channel - 1].hw_value & 0xF;
2072   ofdm_power = channels[channel - 1].hw_value >> 4;
2073 
2074   cck_power = min(cck_power, (u8)15);
2075   cck_power += txpwr_base & 0xF;
2076   cck_power = min(cck_power, (u8)35);
2077 
2078   if (ofdm_power > (u8)15)
2079     ofdm_power = 25;
2080   else
2081     ofdm_power += 10;
2082   ofdm_power += txpwr_base >> 4;
2083   ofdm_power = min(ofdm_power, (u8)35);
2084 
2085   if (channel == 14)
2086     tmp = rtl8225z2_tx_power_cck_ch14;
2087   else
2088     tmp = rtl8225z2_tx_power_cck;
2089 
2090   for (i = 0; i < 8; i++)
2091     rtl8225_write_phy_cck(0x44 + i, *tmp++);
2092 
2093   iowrite8(&map->TX_GAIN_CCK,
2094                    rtl8225z2_tx_gain_cck_ofdm[cck_power]);
2095   msleep(1);
2096 
2097   /* anaparam2 on */
2098   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
2099   reg = ioread8(&map->CONFIG3);
2100   iowrite8(&map->CONFIG3,
2101                    reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
2102   iowrite32(&map->ANAPARAM2,
2103                     RTL8187_RTL8225_ANAPARAM2_ON);
2104   iowrite8(&map->CONFIG3,
2105                    reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
2106   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
2107 
2108   rtl8225_write_phy_ofdm(2, 0x42);
2109   rtl8225_write_phy_ofdm(5, 0x00);
2110   rtl8225_write_phy_ofdm(6, 0x40);
2111   rtl8225_write_phy_ofdm(7, 0x00);
2112   rtl8225_write_phy_ofdm(8, 0x40);
2113 
2114   iowrite8(&map->TX_GAIN_OFDM,
2115                    rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
2116   msleep(1);
2117 }
2118 
2119 static void rtl8225z2_b_rf_set_tx_power(int channel)
2120 {
2121   u8 cck_power, ofdm_power;
2122   const u8 *tmp;
2123   int i;
2124 
2125   cck_power = channels[channel - 1].hw_value & 0xF;
2126   ofdm_power = channels[channel - 1].hw_value >> 4;
2127 
2128   if (cck_power > 15)
2129     cck_power = (hw_rev == RTL8187BvB) ? 15 : 22;
2130   else
2131     cck_power += (hw_rev == RTL8187BvB) ? 0 : 7;
2132   cck_power += txpwr_base & 0xF;
2133   cck_power = min(cck_power, (u8)35);
2134 
2135   if (ofdm_power > 15)
2136     ofdm_power = (hw_rev == RTL8187BvB) ? 17 : 25;
2137   else
2138     ofdm_power += (hw_rev == RTL8187BvB) ? 2 : 10;
2139   ofdm_power += (txpwr_base >> 4) & 0xF;
2140   ofdm_power = min(ofdm_power, (u8)35);
2141 
2142   if (channel == 14)
2143     tmp = rtl8225z2_tx_power_cck_ch14;
2144   else
2145     tmp = rtl8225z2_tx_power_cck;
2146 
2147   if (hw_rev == RTL8187BvB) {
2148     if (cck_power <= 6)
2149       ; /* do nothing */
2150     else if (cck_power <= 11)
2151       tmp += 8;
2152     else
2153       tmp += 16;
2154   } else {
2155     if (cck_power <= 5)
2156       ; /* do nothing */
2157     else if (cck_power <= 11)
2158       tmp += 8;
2159     else if (cck_power <= 17)
2160       tmp += 16;
2161     else
2162       tmp += 24;
2163   }
2164 
2165   for (i = 0; i < 8; i++)
2166     rtl8225_write_phy_cck(0x44 + i, *tmp++);
2167 
2168   iowrite8(&map->TX_GAIN_CCK,
2169                    rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
2170   msleep(1);
2171 
2172   iowrite8(&map->TX_GAIN_OFDM,
2173                    rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
2174   if (hw_rev == RTL8187BvB) {
2175     if (ofdm_power <= 11) {
2176       rtl8225_write_phy_ofdm(0x87, 0x60);
2177       rtl8225_write_phy_ofdm(0x89, 0x60);
2178     } else {
2179       rtl8225_write_phy_ofdm(0x87, 0x5c);
2180       rtl8225_write_phy_ofdm(0x89, 0x5c);
2181     }
2182   } else {
2183     if (ofdm_power <= 11) {
2184       rtl8225_write_phy_ofdm(0x87, 0x5c);
2185       rtl8225_write_phy_ofdm(0x89, 0x5c);
2186     } else if (ofdm_power <= 17) {
2187       rtl8225_write_phy_ofdm(0x87, 0x54);
2188       rtl8225_write_phy_ofdm(0x89, 0x54);
2189     } else {
2190       rtl8225_write_phy_ofdm(0x87, 0x50);
2191       rtl8225_write_phy_ofdm(0x89, 0x50);
2192     }
2193   }
2194   msleep(1);
2195 }
2196 
2197 static const u16 rtl8225z2_rxgain[] = {
2198   0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
2199   0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
2200   0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
2201   0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
2202   0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
2203   0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
2204   0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
2205   0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
2206   0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
2207   0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
2208   0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
2209   0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
2210 };
2211 
2212 static const u8 rtl8225z2_gain_bg[] = {
2213   0x23, 0x15, 0xa5, /* -82-1dBm */
2214   0x23, 0x15, 0xb5, /* -82-2dBm */
2215   0x23, 0x15, 0xc5, /* -82-3dBm */
2216   0x33, 0x15, 0xc5, /* -78dBm */
2217   0x43, 0x15, 0xc5, /* -74dBm */
2218   0x53, 0x15, 0xc5, /* -70dBm */
2219   0x63, 0x15, 0xc5  /* -66dBm */
2220 };
2221 
2222 static void
2223 rtl8225z2_rf_init(void)
2224 {
2225   int i;
2226 
2227   rtl8225_write(0x0, 0x2BF);
2228   rtl8225_write(0x1, 0xEE0);
2229   rtl8225_write(0x2, 0x44D);
2230   rtl8225_write(0x3, 0x441);
2231   rtl8225_write(0x4, 0x8C3);
2232   rtl8225_write(0x5, 0xC72);
2233   rtl8225_write(0x6, 0x0E6);
2234   rtl8225_write(0x7, 0x82A);
2235   rtl8225_write(0x8, 0x03F);
2236   rtl8225_write(0x9, 0x335);
2237   rtl8225_write(0xa, 0x9D4);
2238   rtl8225_write(0xb, 0x7BB);
2239   rtl8225_write(0xc, 0x850);
2240   rtl8225_write(0xd, 0xCDF);
2241   rtl8225_write(0xe, 0x02B);
2242   rtl8225_write(0xf, 0x114);
2243   msleep(100);
2244 
2245   rtl8225_write(0x0, 0x1B7);
2246 
2247   for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
2248     rtl8225_write(0x1, i + 1);
2249     rtl8225_write(0x2, rtl8225z2_rxgain[i]);
2250   }
2251 
2252   rtl8225_write(0x3, 0x080);
2253   rtl8225_write(0x5, 0x004);
2254   rtl8225_write(0x0, 0x0B7);
2255   rtl8225_write(0x2, 0xc4D);
2256 
2257   msleep(200);
2258   rtl8225_write(0x2, 0x44D);
2259   msleep(100);
2260 
2261   if (!(rtl8225_read(6) & (1 << 7))) {
2262     rtl8225_write(0x02, 0x0C4D);
2263     msleep(200);
2264     rtl8225_write(0x02, 0x044D);
2265     msleep(100);
2266     if (!(rtl8225_read(6) & (1 << 7)))
2267       DLOG("RF Calibration Failed! %x\n",
2268            rtl8225_read(6));
2269   }
2270 
2271   msleep(200);
2272 
2273   rtl8225_write(0x0, 0x2BF);
2274 
2275   for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
2276     rtl8225_write_phy_ofdm(0xB, rtl8225_agc[i]);
2277     rtl8225_write_phy_ofdm(0xA, 0x80 + i);
2278   }
2279 
2280   msleep(1);
2281 
2282   rtl8225_write_phy_ofdm(0x00, 0x01);
2283   rtl8225_write_phy_ofdm(0x01, 0x02);
2284   rtl8225_write_phy_ofdm(0x02, 0x42);
2285   rtl8225_write_phy_ofdm(0x03, 0x00);
2286   rtl8225_write_phy_ofdm(0x04, 0x00);
2287   rtl8225_write_phy_ofdm(0x05, 0x00);
2288   rtl8225_write_phy_ofdm(0x06, 0x40);
2289   rtl8225_write_phy_ofdm(0x07, 0x00);
2290   rtl8225_write_phy_ofdm(0x08, 0x40);
2291   rtl8225_write_phy_ofdm(0x09, 0xfe);
2292   rtl8225_write_phy_ofdm(0x0a, 0x08);
2293   rtl8225_write_phy_ofdm(0x0b, 0x80);
2294   rtl8225_write_phy_ofdm(0x0c, 0x01);
2295   rtl8225_write_phy_ofdm(0x0d, 0x43);
2296   rtl8225_write_phy_ofdm(0x0e, 0xd3);
2297   rtl8225_write_phy_ofdm(0x0f, 0x38);
2298   rtl8225_write_phy_ofdm(0x10, 0x84);
2299   rtl8225_write_phy_ofdm(0x11, 0x07);
2300   rtl8225_write_phy_ofdm(0x12, 0x20);
2301   rtl8225_write_phy_ofdm(0x13, 0x20);
2302   rtl8225_write_phy_ofdm(0x14, 0x00);
2303   rtl8225_write_phy_ofdm(0x15, 0x40);
2304   rtl8225_write_phy_ofdm(0x16, 0x00);
2305   rtl8225_write_phy_ofdm(0x17, 0x40);
2306   rtl8225_write_phy_ofdm(0x18, 0xef);
2307   rtl8225_write_phy_ofdm(0x19, 0x19);
2308   rtl8225_write_phy_ofdm(0x1a, 0x20);
2309   rtl8225_write_phy_ofdm(0x1b, 0x15);
2310   rtl8225_write_phy_ofdm(0x1c, 0x04);
2311   rtl8225_write_phy_ofdm(0x1d, 0xc5);
2312   rtl8225_write_phy_ofdm(0x1e, 0x95);
2313   rtl8225_write_phy_ofdm(0x1f, 0x75);
2314   rtl8225_write_phy_ofdm(0x20, 0x1f);
2315   rtl8225_write_phy_ofdm(0x21, 0x17);
2316   rtl8225_write_phy_ofdm(0x22, 0x16);
2317   rtl8225_write_phy_ofdm(0x23, 0x80);
2318   rtl8225_write_phy_ofdm(0x24, 0x46);
2319   rtl8225_write_phy_ofdm(0x25, 0x00);
2320   rtl8225_write_phy_ofdm(0x26, 0x90);
2321   rtl8225_write_phy_ofdm(0x27, 0x88);
2322 
2323   rtl8225_write_phy_ofdm(0x0b, rtl8225z2_gain_bg[4 * 3]);
2324   rtl8225_write_phy_ofdm(0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
2325   rtl8225_write_phy_ofdm(0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
2326   rtl8225_write_phy_ofdm(0x21, 0x37);
2327 
2328   rtl8225_write_phy_cck(0x00, 0x98);
2329   rtl8225_write_phy_cck(0x03, 0x20);
2330   rtl8225_write_phy_cck(0x04, 0x7e);
2331   rtl8225_write_phy_cck(0x05, 0x12);
2332   rtl8225_write_phy_cck(0x06, 0xfc);
2333   rtl8225_write_phy_cck(0x07, 0x78);
2334   rtl8225_write_phy_cck(0x08, 0x2e);
2335   rtl8225_write_phy_cck(0x10, 0x9b);
2336   rtl8225_write_phy_cck(0x11, 0x88);
2337   rtl8225_write_phy_cck(0x12, 0x47);
2338   rtl8225_write_phy_cck(0x13, 0xd0);
2339   rtl8225_write_phy_cck(0x19, 0x00);
2340   rtl8225_write_phy_cck(0x1a, 0xa0);
2341   rtl8225_write_phy_cck(0x1b, 0x08);
2342   rtl8225_write_phy_cck(0x40, 0x86);
2343   rtl8225_write_phy_cck(0x41, 0x8d);
2344   rtl8225_write_phy_cck(0x42, 0x15);
2345   rtl8225_write_phy_cck(0x43, 0x18);
2346   rtl8225_write_phy_cck(0x44, 0x36);
2347   rtl8225_write_phy_cck(0x45, 0x35);
2348   rtl8225_write_phy_cck(0x46, 0x2e);
2349   rtl8225_write_phy_cck(0x47, 0x25);
2350   rtl8225_write_phy_cck(0x48, 0x1c);
2351   rtl8225_write_phy_cck(0x49, 0x12);
2352   rtl8225_write_phy_cck(0x4a, 0x09);
2353   rtl8225_write_phy_cck(0x4b, 0x04);
2354   rtl8225_write_phy_cck(0x4c, 0x05);
2355 
2356   iowrite8((u8 *)0xFF5B, 0x0D); msleep(1);
2357 
2358   rtl8225z2_rf_set_tx_power(1);
2359 
2360   /* RX antenna default to A */
2361   rtl8225_write_phy_cck(0x10, 0x9b);            /* B: 0xDB */
2362   rtl8225_write_phy_ofdm(0x26, 0x90);       /* B: 0x10 */
2363 
2364   iowrite8(&map->TX_ANTENNA, 0x03); /* B: 0x00 */
2365   msleep(1);
2366   iowrite32((__le32 *)0xFF94, 0x3dc00002);
2367 }
2368 
2369 static void
2370 rtl8225z2_b_rf_init(void)
2371 {
2372   int i;
2373 
2374   DLOG ("rtl8225z2_b_rf_init");
2375 
2376   rtl8225_write(0x0, 0x0B7);
2377   rtl8225_write(0x1, 0xEE0);
2378   rtl8225_write(0x2, 0x44D);
2379   rtl8225_write(0x3, 0x441);
2380   rtl8225_write(0x4, 0x8C3);
2381   rtl8225_write(0x5, 0xC72);
2382   rtl8225_write(0x6, 0x0E6);
2383   rtl8225_write(0x7, 0x82A);
2384   rtl8225_write(0x8, 0x03F);
2385   rtl8225_write(0x9, 0x335);
2386   rtl8225_write(0xa, 0x9D4);
2387   rtl8225_write(0xb, 0x7BB);
2388   rtl8225_write(0xc, 0x850);
2389   rtl8225_write(0xd, 0xCDF);
2390   rtl8225_write(0xe, 0x02B);
2391   rtl8225_write(0xf, 0x114);
2392 
2393   rtl8225_write(0x0, 0x1B7);
2394 
2395 #if 1
2396   DLOG ("writing rxgain");
2397   for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
2398     DLOG ("rxgain[%d]", i);
2399     rtl8225_write(0x1, i + 1);
2400     rtl8225_write(0x2, rtl8225z2_rxgain[i]);
2401   }
2402 #endif
2403 
2404   rtl8225_write(0x3, 0x080);
2405   rtl8225_write(0x5, 0x004);
2406   rtl8225_write(0x0, 0x0B7);
2407 
2408   rtl8225_write(0x2, 0xC4D);
2409 
2410   rtl8225_write(0x2, 0x44D);
2411   rtl8225_write(0x0, 0x2BF);
2412 
2413   iowrite8(&map->TX_GAIN_CCK, 0x03);
2414   iowrite8(&map->TX_GAIN_OFDM, 0x07);
2415   iowrite8(&map->TX_ANTENNA, 0x03);
2416 
2417 #if 1
2418   DLOG ("writing agc");
2419   rtl8225_write_phy_ofdm(0x80, 0x12);
2420   for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
2421     rtl8225_write_phy_ofdm(0xF, rtl8225z2_agc[i]);
2422     rtl8225_write_phy_ofdm(0xE, 0x80 + i);
2423     rtl8225_write_phy_ofdm(0xE, 0);
2424   }
2425   rtl8225_write_phy_ofdm(0x80, 0x10);
2426 
2427   DLOG ("writing ofdm");
2428   for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
2429     rtl8225_write_phy_ofdm(i, rtl8225z2_ofdm[i]);
2430 
2431   rtl8225_write_phy_ofdm(0x97, 0x46);
2432   rtl8225_write_phy_ofdm(0xa4, 0xb6);
2433   rtl8225_write_phy_ofdm(0x85, 0xfc);
2434   rtl8225_write_phy_cck(0xc1, 0x88);
2435 #endif
2436 
2437   DLOG ("rf init finished");
2438 }
2439 
2440 static void rtl8225_rf_stop(void)
2441 {
2442   u8 reg;
2443 
2444   rtl8225_write(0x4, 0x1f);
2445 
2446   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
2447   reg = ioread8(&map->CONFIG3);
2448   iowrite8(&map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
2449   if (!is_rtl8187b) {
2450     iowrite32(&map->ANAPARAM2,
2451                       RTL8187_RTL8225_ANAPARAM2_OFF);
2452     iowrite32(&map->ANAPARAM,
2453                       RTL8187_RTL8225_ANAPARAM_OFF);
2454   } else {
2455     iowrite32(&map->ANAPARAM2,
2456                       RTL8187B_RTL8225_ANAPARAM2_OFF);
2457     iowrite32(&map->ANAPARAM,
2458                       RTL8187B_RTL8225_ANAPARAM_OFF);
2459     iowrite8(&map->ANAPARAM3,
2460                      RTL8187B_RTL8225_ANAPARAM3_OFF);
2461   }
2462   iowrite8(&map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
2463   iowrite8(&map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
2464 }
2465 
2466 static void
2467 rtl8225_rf_set_channel(struct ieee80211_conf *conf)
2468 {
2469   int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
2470 
2471   if (rf->init == rtl8225_rf_init)
2472     rtl8225_rf_set_tx_power(chan);
2473   else if (rf->init == rtl8225z2_rf_init)
2474     rtl8225z2_rf_set_tx_power(chan);
2475   else
2476     rtl8225z2_b_rf_set_tx_power(chan);
2477 
2478   rtl8225_write(0x7, rtl8225_chan[chan - 1]);
2479   msleep(10);
2480 }
2481 
2482 static const struct rtl818x_rf_ops rtl8225_ops = {
2483   .name     = "rtl8225",
2484   .init     = rtl8225_rf_init,
2485   .stop     = rtl8225_rf_stop,
2486   .set_chan = rtl8225_rf_set_channel
2487 };
2488 
2489 static const struct rtl818x_rf_ops rtl8225z2_ops = {
2490   .name     = "rtl8225z2",
2491   .init     = rtl8225z2_rf_init,
2492   .stop     = rtl8225_rf_stop,
2493   .set_chan = rtl8225_rf_set_channel
2494 };
2495 
2496 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
2497   .name     = "rtl8225z2",
2498   .init     = rtl8225z2_b_rf_init,
2499   .stop     = rtl8225_rf_stop,
2500   .set_chan = rtl8225_rf_set_channel
2501 };
2502 
2503 const struct rtl818x_rf_ops *
2504 rtl8187_detect_rf(void)
2505 {
2506   u16 reg8, reg9;
2507 
2508   if (!is_rtl8187b) {
2509     rtl8225_write(0, 0x1B7);
2510 
2511     reg8 = rtl8225_read(8);
2512     reg9 = rtl8225_read(9);
2513 
2514     rtl8225_write(0, 0x0B7);
2515 
2516     if (reg8 != 0x588 || reg9 != 0x700)
2517       return &rtl8225_ops;
2518 
2519     return &rtl8225z2_ops;
2520   } else
2521     return &rtl8225z2_b_ops;
2522 }
2523 
2524 #include "module/header.h"
2525 
2526 static const struct module_ops mod_ops = {
2527   .init = usb_rtl8187b_driver_init
2528 };
2529 
2530 DEF_MODULE (usb___rtl8187b, "USB rtl8187b wifi driver", &mod_ops, {"usb", "net___ethernet"});
2531 
2532 /*
2533  * Local Variables:
2534  * indent-tabs-mode: nil
2535  * mode: C
2536  * c-file-style: "gnu"
2537  * c-basic-offset: 2
2538  * End:
2539  */
2540 
2541 /* vi: set et sw=2 sts=2: */