Warning, cross-references for /kernel/drivers/usb/rtl8187b.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
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
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
0110 #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B
0111 #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D
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
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
0261
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
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,
0314 (__le32 *) 0xFFF4,
0315 (__le32 *) 0xFFFC,
0316 (__le32 *) 0xFFF8,
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
0345
0346
0347 iowrite8((u8 *)&map->BRSR + 1, eifs);
0348
0349
0350
0351
0352
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
0432
0433
0434
0435
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
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;
0652 aifsn[1] = 2;
0653 aifsn[2] = 7;
0654 aifsn[3] = 3;
0655 iowrite8(&map->ACM_CONTROL, 0);
0656
0657
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
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
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
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
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 , 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
0795
0796
0797
0798
0799
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
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,
0880 0x00, 0x23, 0x4D, 0xAF, 0x00, 0x3C,
0881
0882
0883
0884 0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E,
0885 0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7E,
0886
0887 0x20, 0x00,
0888
0889 0x8E, 0x91, 0x42, 0x11, 0x67, 0x00, 0x00, 0x00,
0890 0x64, 0x00,
0891 0x01, 0x04,
0892
0893 0x00, 0x06, 0x6C, 0x65, 0x6E, 0x6F, 0x76, 0x63,
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,
0907 0x01, 0x05,
0908 0x00, 0x26, 0xCB, 0xD0, 0x77, 0x46,
0909 0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E,
0910 0x00, 0x26, 0xCB, 0xD0, 0x77, 0x46,
0911 0x00, 0x00,
0912
0913 0x00, 0x10, 0x42, 0x55, 0x20, 0x57, 0x69, 0x72, 0x65,
0914 0x6C, 0x65, 0x73, 0x73, 0x20, 0x48, 0x65, 0x6C, 0x70,
0915
0916 0x01, 0x08, 0x82, 0x84, 0x8B, 0x0C, 0x12, 0x96, 0x18, 0x24
0917 };
0918 #endif
0919 #if 0
0920 uint8 pkt[] = {
0921 0x80, 0x00,
0922 0x00, 0x00,
0923 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0924 0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E,
0925 0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E,
0926 0x00, 0x00,
0927 0x8E, 0x91, 0x42, 0x11, 0x67, 0x00, 0x00, 0x00,
0928 0x64, 0x00,
0929 0x01, 0x04,
0930
0931 0x00, 0x04, 0x54, 0x65, 0x73, 0x74,
0932
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
0941
0942 0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E,
0943 0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7E,
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
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
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
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
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
1105 return;
1106
1107 if (ieee80211_is_beacon (h->frame_control)) {
1108
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
1123 - 4
1124
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
1134
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
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);
1162 debug_info_element (&v, &l);
1163 } else if (ieee80211_is_probe_resp (h->frame_control)) {
1164 DLOG ("PROBE RESPONSE");
1165 } else if (ieee80211_is_data (h->frame_control)) {
1166
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
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
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 ) |
1292 (7 << 10 ) |
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 ) |
1303 (7 << 0 ) |
1304 (7 << 21 ));
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 ) |
1323 (7 << 10 ) |
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 ) |
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
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;
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
1426
1427
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
1441
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, ®16);
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
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
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,
1769 0x23, 0x88, 0x7c, 0xb5,
1770 0x23, 0x88, 0x7c, 0xc5,
1771 0x33, 0x80, 0x79, 0xc5,
1772 0x43, 0x78, 0x76, 0xc5,
1773 0x53, 0x60, 0x73, 0xc5,
1774 0x63, 0x58, 0x70, 0xc5,
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);
1842
1843
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
1997 rtl8225_write_phy_cck(0x10, 0x9b);
1998 rtl8225_write_phy_ofdm(0x26, 0x90);
1999
2000 iowrite8(&map->TX_ANTENNA, 0x03);
2001 msleep(1);
2002 iowrite32((__le32 *)0xFF94, 0x3dc00002);
2003
2004
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
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 ;
2150 else if (cck_power <= 11)
2151 tmp += 8;
2152 else
2153 tmp += 16;
2154 } else {
2155 if (cck_power <= 5)
2156 ;
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,
2214 0x23, 0x15, 0xb5,
2215 0x23, 0x15, 0xc5,
2216 0x33, 0x15, 0xc5,
2217 0x43, 0x15, 0xc5,
2218 0x53, 0x15, 0xc5,
2219 0x63, 0x15, 0xc5
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
2361 rtl8225_write_phy_cck(0x10, 0x9b);
2362 rtl8225_write_phy_ofdm(0x26, 0x90);
2363
2364 iowrite8(&map->TX_ANTENNA, 0x03);
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
2534
2535
2536
2537
2538
2539
2540
2541