2 * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
8 * Hardware Initialization and Hardware IO for RTL8185B
10 * Major Change History:
12 * ---------- --------------- -------------------------------
13 * 2006-11-15 Xiong Created
16 * This file is ported from RTL8185B Windows driver.
21 /*--------------------------Include File------------------------------------*/
22 #include <linux/spinlock.h>
25 #include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
26 #include "r8180_93cx6.h" /* Card EEPROM */
28 #include "ieee80211/dot11d.h"
29 /* #define CONFIG_RTL8180_IO_MAP */
30 #define TC_3W_POLL_MAX_TRY_CNT 5
32 static u8 MAC_REG_TABLE[][2] = {
34 /* 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in HwConfigureRTL8185() */
35 /* 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185(). */
36 /* 0x1F0~0x1F8 set in MacConfig_85BASIC() */
37 {0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42},
38 {0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03},
39 {0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03},
40 {0x94, 0x0F}, {0x95, 0x32},
41 {0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00},
42 {0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32},
43 {0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4},
44 {0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00},
48 /* For Flextronics system Logo PCIHCT failure: */
49 /* 0x1C4~0x1CD set no-zero value to avoid PCI configuration space 0x45[7]=1 */
51 {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24},
52 {0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF},
53 {0x82, 0xFF}, {0x83, 0x03},
54 {0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22}, /* lzm add 080826 */
55 {0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22}, /* lzm add 080826 */
61 {0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5},
62 {0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff},
63 {0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08},
64 {0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f},
65 {0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f},
66 {0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff},
67 {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00},
70 {0x5e, 0x00}, {0x9f, 0x03}
74 static u8 ZEBRA_AGC[] = {
76 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
77 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
78 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
79 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
81 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
82 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
83 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
86 static u32 ZEBRA_RF_RX_GAIN_TABLE[] = {
87 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
88 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
89 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
90 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
91 0x0183, 0x0163, 0x0143, 0x0123, 0x0103
94 static u8 OFDM_CONFIG[] = {
95 /* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */
96 /* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */
97 /* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */
99 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
100 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
102 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
103 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
105 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
106 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
108 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
109 0xD8, 0x3C, 0x7B, 0x10, 0x10
112 /*---------------------------------------------------------------
114 * the code is ported from Windows source code
115 *---------------------------------------------------------------
118 void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data)
120 write_nic_byte(dev, offset, data);
121 read_nic_byte(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
124 void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data)
126 write_nic_word(dev, offset, data);
127 read_nic_word(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
130 u8 PlatformIORead1Byte(struct net_device *dev, u32 offset);
132 void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data)
134 if (offset == PhyAddr) {
135 /* For Base Band configuration. */
136 unsigned char cmdByte;
137 unsigned long dataBytes;
141 cmdByte = (u8)(data & 0x000000ff);
146 * The critical section is only BB read/write race condition.
148 * 1. We assume NO one will access BB at DIRQL, otherwise, system will crash for
149 * acquiring the spinlock in such context.
150 * 2. PlatformIOWrite4Byte() MUST NOT be recursive.
152 /* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */
154 for (idx = 0; idx < 30; idx++) {
155 /* Make sure command bit is clear before access it. */
156 u1bTmp = PlatformIORead1Byte(dev, PhyAddr);
157 if ((u1bTmp & BIT7) == 0)
163 for (idx = 0; idx < 3; idx++)
164 PlatformIOWrite1Byte(dev, offset+1+idx, ((u8 *)&dataBytes)[idx]);
166 write_nic_byte(dev, offset, cmdByte);
168 /* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */
170 write_nic_dword(dev, offset, data);
171 read_nic_dword(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
175 u8 PlatformIORead1Byte(struct net_device *dev, u32 offset)
179 data = read_nic_byte(dev, offset);
185 u16 PlatformIORead2Byte(struct net_device *dev, u32 offset)
189 data = read_nic_word(dev, offset);
195 u32 PlatformIORead4Byte(struct net_device *dev, u32 offset)
199 data = read_nic_dword(dev, offset);
205 void SetOutputEnableOfRfPins(struct net_device *dev)
207 write_nic_word(dev, RFPinsEnable, 0x1bff);
210 static bool HwHSSIThreeWire(struct net_device *dev,
217 /* Check if WE and RE are cleared. */
218 for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
219 u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
220 if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0)
225 if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
227 "HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n",
232 /* RTL8187S HSSI Read/Write Function */
233 u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
234 u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
235 write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
237 /* jong: HW SI read must set reg84[3]=0. */
238 u1bTmp = read_nic_byte(dev, RFPinsSelect);
240 write_nic_byte(dev, RFPinsSelect, u1bTmp);
241 /* Fill up data buffer for write operation. */
243 /* SI - reg274[3:0] : RF register's Address */
245 write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
247 write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
249 /* Set up command: WE or RE. */
251 write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
253 write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
256 /* Check if DONE is set. */
257 for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
258 u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
259 if (u1bTmp & SW_3W_CMD1_DONE)
265 write_nic_byte(dev, SW_3W_CMD1, 0);
267 /* Read back data for read operation. */
269 /* Serial Interface : reg363_362[11:0] */
270 *((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ);
271 *((u16 *)pDataBuf) &= 0x0FFF;
277 void RF_WriteReg(struct net_device *dev, u8 offset, u16 data)
279 u16 reg = (data << 4) | (offset & 0x0f);
280 HwHSSIThreeWire(dev, (u8 *)®, true);
283 u16 RF_ReadReg(struct net_device *dev, u8 offset)
285 u16 reg = offset & 0x0f;
286 HwHSSIThreeWire(dev, (u8 *)®, false);
291 /* by Owen on 04/07/14 for writing BB register successfully */
292 void WriteBBPortUchar(struct net_device *dev, u32 Data)
294 /* u8 TimeoutCounter; */
298 UCharData = (u8)((Data & 0x0000ff00) >> 8);
299 PlatformIOWrite4Byte(dev, PhyAddr, Data);
300 /* for(TimeoutCounter = 10; TimeoutCounter > 0; TimeoutCounter--) */
302 PlatformIOWrite4Byte(dev, PhyAddr, Data & 0xffffff7f);
303 RegisterContent = PlatformIORead1Byte(dev, PhyDataR);
304 /*if(UCharData == RegisterContent) */
309 u8 ReadBBPortUchar(struct net_device *dev, u32 addr)
311 /*u8 TimeoutCounter; */
314 PlatformIOWrite4Byte(dev, PhyAddr, addr & 0xffffff7f);
315 RegisterContent = PlatformIORead1Byte(dev, PhyDataR);
317 return RegisterContent;
321 * Perform Antenna settings with antenna diversity on 87SE.
322 * Created by Roger, 2008.01.25.
324 bool SetAntennaConfig87SE(struct net_device *dev,
325 u8 DefaultAnt, /* 0: Main, 1: Aux. */
326 bool bAntDiversity) /* 1:Enable, 0: Disable. */
328 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
329 bool bAntennaSwitched = true;
331 /* printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n", DefaultAnt, bAntDiversity); */
333 /* Threshold for antenna diversity. */
334 write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */
336 if (bAntDiversity) { /* Enable Antenna Diversity. */
337 if (DefaultAnt == 1) { /* aux antenna */
339 /* Mac register, aux antenna */
340 write_nic_byte(dev, ANTSEL, 0x00);
342 /* Config CCK RX antenna. */
343 write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
344 write_phy_cck(dev, 0x01, 0xc7); /* Reg01 : c7 */
346 /* Config OFDM RX antenna. */
347 write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
348 write_phy_ofdm(dev, 0x18, 0xb2); /* Reg18 : b2 */
349 } else { /* use main antenna */
350 /* Mac register, main antenna */
351 write_nic_byte(dev, ANTSEL, 0x03);
353 /* Config CCK RX antenna. */
354 write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
355 write_phy_cck(dev, 0x01, 0xc7); /* Reg01 : c7 */
357 /* Config OFDM RX antenna. */
358 write_phy_ofdm(dev, 0x0d, 0x5c); /* Reg0d : 5c */
359 write_phy_ofdm(dev, 0x18, 0xb2); /* Reg18 : b2 */
362 /* Disable Antenna Diversity. */
363 if (DefaultAnt == 1) { /* aux Antenna */
364 /* Mac register, aux antenna */
365 write_nic_byte(dev, ANTSEL, 0x00);
367 /* Config CCK RX antenna. */
368 write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
369 write_phy_cck(dev, 0x01, 0x47); /* Reg01 : 47 */
371 /* Config OFDM RX antenna. */
372 write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
373 write_phy_ofdm(dev, 0x18, 0x32); /* Reg18 : 32 */
374 } else { /* main Antenna */
375 /* Mac register, main antenna */
376 write_nic_byte(dev, ANTSEL, 0x03);
378 /* Config CCK RX antenna. */
379 write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
380 write_phy_cck(dev, 0x01, 0x47); /* Reg01 : 47 */
382 /* Config OFDM RX antenna. */
383 write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */
384 write_phy_ofdm(dev, 0x18, 0x32); /*Reg18 : 32 */
387 priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */
388 return bAntennaSwitched;
391 *--------------------------------------------------------------
392 * Hardware Initialization.
393 * the code is ported from Windows source code
394 *--------------------------------------------------------------
397 void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev)
400 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
403 u32 u4bRegOffset, u4bRegValue;
404 u16 u4bRF23, u4bRF24;
410 *===========================================================================
411 * 87S_PCIE :: RADIOCFG.TXT
412 *===========================================================================
416 /* Page1 : reg16-reg30 */
417 RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); /* switch to page1 */
418 u4bRF23 = RF_ReadReg(dev, 0x08); mdelay(1);
419 u4bRF24 = RF_ReadReg(dev, 0x09); mdelay(1);
421 if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) {
423 netdev_info(dev, "card type changed from C- to D-cut\n");
426 /* Page0 : reg0-reg15 */
428 RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);/* 1 */
429 RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1);
430 RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);/* 2 */
431 RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);/* 3 */
432 RF_WriteReg(dev, 0x04, 0x0975); mdelay(1);
433 RF_WriteReg(dev, 0x05, 0x0c72); mdelay(1);
434 RF_WriteReg(dev, 0x06, 0x0ae6); mdelay(1);
435 RF_WriteReg(dev, 0x07, 0x00ca); mdelay(1);
436 RF_WriteReg(dev, 0x08, 0x0e1c); mdelay(1);
437 RF_WriteReg(dev, 0x09, 0x02f0); mdelay(1);
438 RF_WriteReg(dev, 0x0a, 0x09d0); mdelay(1);
439 RF_WriteReg(dev, 0x0b, 0x01ba); mdelay(1);
440 RF_WriteReg(dev, 0x0c, 0x0640); mdelay(1);
441 RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1);
442 RF_WriteReg(dev, 0x0e, 0x0020); mdelay(1);
443 RF_WriteReg(dev, 0x0f, 0x0990); mdelay(1);
445 /* Page1 : reg16-reg30 */
446 RF_WriteReg(dev, 0x00, 0x013f); mdelay(1);
447 RF_WriteReg(dev, 0x03, 0x0806); mdelay(1);
448 RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1);
449 RF_WriteReg(dev, 0x05, 0x059b); mdelay(1);
450 RF_WriteReg(dev, 0x06, 0x0081); mdelay(1);
451 RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1);
452 /* Don't write RF23/RF24 to make a difference between 87S C cut and D cut. asked by SD3 stevenl. */
453 RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
454 RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1);
457 RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
458 RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
459 RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1); /* RX LO buffer */
461 RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
462 RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
463 RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1); /* RX LO buffer */
466 RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
467 RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1); /* 6 */
468 RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1);
469 RF_WriteReg(dev, 0x04, 0x0e50); mdelay(1);
471 for (i = 0; i <= 36; i++) {
472 RF_WriteReg(dev, 0x01, i); mdelay(1);
473 RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1);
476 RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /* 203, 343 */
477 RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); /* 400 */
478 RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); /* switch to reg16-reg30, and HSSI disable 137 */
479 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
481 RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); /* Z4 synthesizer loop filter setting, 392 */
482 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
484 RF_WriteReg(dev, 0x00, 0x0037); mdelay(1); /* switch to reg0-reg15, and HSSI disable */
485 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
487 RF_WriteReg(dev, 0x04, 0x0160); mdelay(1); /* CBC on, Tx Rx disable, High gain */
488 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
490 RF_WriteReg(dev, 0x07, 0x0080); mdelay(1); /* Z4 setted channel 1 */
491 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
493 RF_WriteReg(dev, 0x02, 0x088D); mdelay(1); /* LC calibration */
494 mdelay(200); /* Deay 200 ms. */ /* 0xfd */
495 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
496 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
498 RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); /* switch to reg16-reg30 137, and HSSI disable 137 */
499 mdelay(10); /* Deay 10 ms. */ /* 0xfd */
501 RF_WriteReg(dev, 0x07, 0x0000); mdelay(1);
502 RF_WriteReg(dev, 0x07, 0x0180); mdelay(1);
503 RF_WriteReg(dev, 0x07, 0x0220); mdelay(1);
504 RF_WriteReg(dev, 0x07, 0x03E0); mdelay(1);
506 /* DAC calibration off 20070702 */
507 RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1);
508 RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
509 /* For crystal calibration, added by Roger, 2007.12.11. */
510 if (priv->bXtalCalibration) { /* reg 30. */
512 * enable crystal calibration.
513 * RF Reg[30], (1)Xin:[12:9], Xout:[8:5], addr[4:0].
514 * (2)PA Pwr delay timer[15:14], default: 2.4us, set BIT15=0
515 * (3)RF signal on/off when calibration[13], default: on, set BIT13=0.
516 * So we should minus 4 BITs offset.
518 RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
519 printk("ZEBRA_Config_85BASIC_HardCode(): (%02x)\n",
520 (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9);
522 /* using default value. Xin=6, Xout=6. */
523 RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
526 RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1); /* switch to reg0-reg15, and HSSI enable */
527 RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); /* Rx BB start calibration, 00c//+edward */
528 RF_WriteReg(dev, 0x02, 0x004d); mdelay(1); /* temperature meter off */
529 RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); /* Rx mode */
530 mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
531 mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
532 mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
533 RF_WriteReg(dev, 0x00, 0x0197); mdelay(1); /* Rx mode*/ /*+edward */
534 RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1); /* Rx mode*/ /*+edward */
535 RF_WriteReg(dev, 0x00, 0x009f); mdelay(1); /* Rx mode*/ /*+edward */
536 RF_WriteReg(dev, 0x01, 0x0000); mdelay(1); /* Rx mode*/ /*+edward */
537 RF_WriteReg(dev, 0x02, 0x0000); mdelay(1); /* Rx mode*/ /*+edward */
538 /* power save parameters. */
539 u1b24E = read_nic_byte(dev, 0x24E);
540 write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6))));
542 /*=============================================================================
544 *===========================================================================
546 *===========================================================================
548 * [POWER SAVE] Power Saving Parameters by jong. 2007-11-27
549 * CCK reg0x00[7]=1'b1 :power saving for TX (default)
550 * CCK reg0x00[6]=1'b1: power saving for RX (default)
551 * CCK reg0x06[4]=1'b1: turn off channel estimation related circuits if not doing channel estimation.
552 * CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1
553 * CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0
556 write_phy_cck(dev, 0x00, 0xc8);
557 write_phy_cck(dev, 0x06, 0x1c);
558 write_phy_cck(dev, 0x10, 0x78);
559 write_phy_cck(dev, 0x2e, 0xd0);
560 write_phy_cck(dev, 0x2f, 0x06);
561 write_phy_cck(dev, 0x01, 0x46);
564 write_nic_byte(dev, CCK_TXAGC, 0x10);
565 write_nic_byte(dev, OFDM_TXAGC, 0x1B);
566 write_nic_byte(dev, ANTSEL, 0x03);
571 *===========================================================================
573 *===========================================================================
576 write_phy_ofdm(dev, 0x00, 0x12);
578 for (i = 0; i < 128; i++) {
580 data = ZEBRA_AGC[i+1];
582 data = data | 0x0000008F;
584 addr = i + 0x80; /* enable writing AGC table */
586 addr = addr | 0x0000008E;
588 WriteBBPortUchar(dev, data);
589 WriteBBPortUchar(dev, addr);
590 WriteBBPortUchar(dev, 0x0000008E);
593 PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080); /* Annie, 2006-05-05 */
596 *===========================================================================
598 *===========================================================================
600 *===========================================================================
603 for (i = 0; i < 60; i++) {
605 u4bRegValue = OFDM_CONFIG[i];
607 WriteBBPortUchar(dev,
609 (u4bRegOffset & 0x7f) |
610 ((u4bRegValue & 0xff) << 8)));
614 *===========================================================================
616 *===========================================================================
618 /* Config Sw/Hw Combinational Antenna Diversity. Added by Roger, 2008.02.26. */
619 SetAntennaConfig87SE(dev, priv->bDefaultAntenna1, priv->bSwAntennaDiverity);
623 void UpdateInitialGain(struct net_device *dev)
625 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
628 if (priv->eRFPowerState != eRfOn) {
629 /* Don't access BB/RF under disable PLL situation.
630 * RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain - pHalData->eRFPowerState!=eRfOn\n"));
631 * Back to the original state
633 priv->InitialGain = priv->InitialGainBackUp;
637 switch (priv->InitialGain) {
638 case 1: /* m861dBm */
639 write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
640 write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
641 write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
644 case 2: /* m862dBm */
645 write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
646 write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
647 write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
650 case 3: /* m863dBm */
651 write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
652 write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
653 write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
656 case 4: /* m864dBm */
657 write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
658 write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
659 write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
663 write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
664 write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
665 write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
669 write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
670 write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
671 write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
675 write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
676 write_phy_ofdm(dev, 0x24, 0xa6); mdelay(1);
677 write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
681 write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
682 write_phy_ofdm(dev, 0x24, 0xb6); mdelay(1);
683 write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
687 write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
688 write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
689 write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
695 * Tx Power tracking mechanism routine on 87SE.
696 * Created by Roger, 2007.12.11.
698 void InitTxPwrTracking87SE(struct net_device *dev)
702 u4bRfReg = RF_ReadReg(dev, 0x02);
704 /* Enable Thermal meter indication. */
705 RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN); mdelay(1);
708 void PhyConfig8185(struct net_device *dev)
710 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
711 write_nic_dword(dev, RCR, priv->ReceiveConfig);
712 priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
714 ZEBRA_Config_85BASIC_HardCode(dev);
715 /* Set default initial gain state to 4, approved by SD3 DZ, by Bruce, 2007-06-06. */
716 if (priv->bDigMechanism) {
717 if (priv->InitialGain == 0)
718 priv->InitialGain = 4;
722 * Enable thermal meter indication to implement TxPower tracking on 87SE.
723 * We initialize thermal meter here to avoid unsuccessful configuration.
724 * Added by Roger, 2007.12.11.
726 if (priv->bTxPowerTrack)
727 InitTxPwrTracking87SE(dev);
729 priv->InitialGainBackUp = priv->InitialGain;
730 UpdateInitialGain(dev);
735 void HwConfigureRTL8185(struct net_device *dev)
737 /* RTL8185_TODO: Determine Retrylimit, TxAGC, AutoRateFallback control. */
738 u8 bUNIVERSAL_CONTROL_RL = 0;
739 u8 bUNIVERSAL_CONTROL_AGC = 1;
740 u8 bUNIVERSAL_CONTROL_ANT = 1;
741 u8 bAUTO_RATE_FALLBACK_CTL = 1;
743 write_nic_word(dev, BRSR, 0x0fff);
745 val8 = read_nic_byte(dev, CW_CONF);
747 if (bUNIVERSAL_CONTROL_RL)
752 write_nic_byte(dev, CW_CONF, val8);
755 val8 = read_nic_byte(dev, TXAGC_CTL);
756 if (bUNIVERSAL_CONTROL_AGC) {
757 write_nic_byte(dev, CCK_TXAGC, 128);
758 write_nic_byte(dev, OFDM_TXAGC, 128);
765 write_nic_byte(dev, TXAGC_CTL, val8);
767 /* Tx Antenna including Feedback control */
768 val8 = read_nic_byte(dev, TXAGC_CTL);
770 if (bUNIVERSAL_CONTROL_ANT) {
771 write_nic_byte(dev, ANTSEL, 0x00);
774 val8 = val8 & (val8|0x02); /* xiong-2006-11-15 */
777 write_nic_byte(dev, TXAGC_CTL, val8);
779 /* Auto Rate fallback control */
780 val8 = read_nic_byte(dev, RATE_FALLBACK);
782 if (bAUTO_RATE_FALLBACK_CTL) {
783 val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
785 /* <RJ_TODO_8185B> We shall set up the ARFR according to user's setting. */
786 PlatformIOWrite2Byte(dev, ARFR, 0x0fff); /* set 1M ~ 54Mbps. */
788 write_nic_byte(dev, RATE_FALLBACK, val8);
791 static void MacConfig_85BASIC_HardCode(struct net_device *dev)
794 *==========================================================================
796 *==========================================================================
799 u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0;
802 nLinesRead = sizeof(MAC_REG_TABLE)/2;
804 for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */
805 u4bRegOffset = MAC_REG_TABLE[i][0];
806 u4bRegValue = MAC_REG_TABLE[i][1];
808 if (u4bRegOffset == 0x5e)
809 u4bPageIndex = u4bRegValue;
811 u4bRegOffset |= (u4bPageIndex << 8);
813 write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
815 /* ============================================================================ */
818 static void MacConfig_85BASIC(struct net_device *dev)
822 MacConfig_85BASIC_HardCode(dev);
824 /* ============================================================================ */
826 /* Follow TID_AC_MAP of WMac. */
827 write_nic_word(dev, TID_AC_MAP, 0xfa50);
829 /* Interrupt Migration, Jong suggested we use set 0x0000 first, 2005.12.14, by rcnjko. */
830 write_nic_word(dev, IntMig, 0x0000);
832 /* Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. */
833 PlatformIOWrite4Byte(dev, 0x1F0, 0x00000000);
834 PlatformIOWrite4Byte(dev, 0x1F4, 0x00000000);
835 PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
837 /* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */
838 /* power save parameter based on "87SE power save parameters 20071127.doc", as follow. */
840 /* Enable DA10 TX power saving */
841 u1DA = read_nic_byte(dev, PHYPR);
842 write_nic_byte(dev, PHYPR, (u1DA | BIT2));
845 write_nic_word(dev, 0x360, 0x1000);
846 write_nic_word(dev, 0x362, 0x1000);
849 write_nic_word(dev, 0x370, 0x0560);
850 write_nic_word(dev, 0x372, 0x0560);
851 write_nic_word(dev, 0x374, 0x0DA4);
852 write_nic_word(dev, 0x376, 0x0DA4);
853 write_nic_word(dev, 0x378, 0x0560);
854 write_nic_word(dev, 0x37A, 0x0560);
855 write_nic_word(dev, 0x37C, 0x00EC);
856 write_nic_word(dev, 0x37E, 0x00EC); /* +edward */
857 write_nic_byte(dev, 0x24E, 0x01);
860 u8 GetSupportedWirelessMode8185(struct net_device *dev)
862 return WIRELESS_MODE_B | WIRELESS_MODE_G;
865 void ActUpdateChannelAccessSetting(struct net_device *dev,
866 WIRELESS_MODE WirelessMode,
867 PCHANNEL_ACCESS_SETTING ChnlAccessSetting)
869 struct r8180_priv *priv = ieee80211_priv(dev);
870 struct ieee80211_device *ieee = priv->ieee80211;
873 u8 bFollowLegacySetting = 0;
878 * TODO: We still don't know how to set up these registers, just follow WMAC to
882 * Jong said CWmin/CWmax register are not functional in 8185B,
883 * so we shall fill channel access realted register into AC parameter registers,
886 ChnlAccessSetting->SIFS_Timer = 0x22; /* Suggested by Jong, 2005.12.08. */
887 ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
888 ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
889 ChnlAccessSetting->EIFS_Timer = 0x5B; /* Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. */
890 ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
891 ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
893 write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
894 write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer); /* Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29. */
896 u1bAIFS = aSifsTime + (2 * ChnlAccessSetting->SlotTimeTimer);
898 write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
900 write_nic_byte(dev, AckTimeOutReg, 0x5B); /* <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. */
902 { /* Legacy 802.11. */
903 bFollowLegacySetting = 1;
907 /* this setting is copied from rtl8187B. xiong-2006-11-13 */
908 if (bFollowLegacySetting) {
911 * Follow 802.11 seeting to AC parameter, all AC shall use the same parameter.
912 * 2005.12.01, by rcnjko.
914 AcParam.longData = 0;
915 AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */
916 AcParam.f.AciAifsn.f.ACM = 0;
917 AcParam.f.Ecw.f.ECWmin = ChnlAccessSetting->CWminIndex; /* Follow 802.11 CWmin. */
918 AcParam.f.Ecw.f.ECWmax = ChnlAccessSetting->CWmaxIndex; /* Follow 802.11 CWmax. */
919 AcParam.f.TXOPLimit = 0;
921 /* lzm reserved 080826 */
922 /* For turbo mode setting. port from 87B by Isaiah 2008-08-01 */
923 if (ieee->current_network.Turbo_Enable == 1)
924 AcParam.f.TXOPLimit = 0x01FF;
925 /* For 87SE with Intel 4965 Ad-Hoc mode have poor throughput (19MB) */
926 if (ieee->iw_mode == IW_MODE_ADHOC)
927 AcParam.f.TXOPLimit = 0x0020;
929 for (eACI = 0; eACI < AC_MAX; eACI++) {
930 AcParam.f.AciAifsn.f.ACI = (u8)eACI;
932 PAC_PARAM pAcParam = (PAC_PARAM)(&AcParam);
937 /* Retrieve parameters to update. */
938 eACI = pAcParam->f.AciAifsn.f.ACI;
939 u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * ChnlAccessSetting->SlotTimeTimer + aSifsTime;
940 u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) |
941 (((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET) |
942 (((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET) |
943 (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
947 /* write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); */
951 /* write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); */
955 /* write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); */
959 /* write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); */
963 DMESGW("SetHwReg8185(): invalid ACI: %d !\n", eACI);
968 /* If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. */
970 PACI_AIFSN pAciAifsn = (PACI_AIFSN)(&pAcParam->f.AciAifsn);
971 AC_CODING eACI = pAciAifsn->f.ACI;
973 /*for 8187B AsynIORead issue */
975 if (pAciAifsn->f.ACM) {
979 AcmCtrl |= (BEQ_ACM_EN|BEQ_ACM_CTL|ACM_HW_EN); /* or 0x21 */
983 AcmCtrl |= (VIQ_ACM_EN|VIQ_ACM_CTL|ACM_HW_EN); /* or 0x42 */
987 AcmCtrl |= (VOQ_ACM_EN|VOQ_ACM_CTL|ACM_HW_EN); /* or 0x84 */
991 DMESGW("SetHwReg8185(): [HW_VAR_ACM_CTRL] ACM set failed: eACI is %d\n", eACI);
998 AcmCtrl &= ((~BEQ_ACM_EN) & (~BEQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0xDE */
1002 AcmCtrl &= ((~VIQ_ACM_EN) & (~VIQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0xBD */
1006 AcmCtrl &= ((~VOQ_ACM_EN) & (~VOQ_ACM_CTL) & (~ACM_HW_EN)); /* and 0x7B */
1013 write_nic_byte(dev, ACM_CONTROL, 0);
1020 void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode)
1022 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1023 struct ieee80211_device *ieee = priv->ieee80211;
1024 u8 btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
1026 if ((btWirelessMode & btSupportedWirelessMode) == 0) {
1027 /* Don't switch to unsupported wireless mode, 2006.02.15, by rcnjko. */
1028 DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n",
1029 btWirelessMode, btSupportedWirelessMode);
1033 /* 1. Assign wireless mode to switch if necessary. */
1034 if (btWirelessMode == WIRELESS_MODE_AUTO) {
1035 if ((btSupportedWirelessMode & WIRELESS_MODE_A)) {
1036 btWirelessMode = WIRELESS_MODE_A;
1037 } else if (btSupportedWirelessMode & WIRELESS_MODE_G) {
1038 btWirelessMode = WIRELESS_MODE_G;
1040 } else if ((btSupportedWirelessMode & WIRELESS_MODE_B)) {
1041 btWirelessMode = WIRELESS_MODE_B;
1043 DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n",
1044 btSupportedWirelessMode);
1045 btWirelessMode = WIRELESS_MODE_B;
1050 * 2. Swtich band: RF or BB specific actions,
1051 * for example, refresh tables in omc8255, or change initial gain if necessary.
1052 * Nothing to do for Zebra to switch band.
1053 * Update current wireless mode if we switch to specified band successfully.
1056 ieee->mode = (WIRELESS_MODE)btWirelessMode;
1058 /* 3. Change related setting. */
1059 if (ieee->mode == WIRELESS_MODE_A)
1060 DMESG("WIRELESS_MODE_A\n");
1061 else if (ieee->mode == WIRELESS_MODE_B)
1062 DMESG("WIRELESS_MODE_B\n");
1063 else if (ieee->mode == WIRELESS_MODE_G)
1064 DMESG("WIRELESS_MODE_G\n");
1066 ActUpdateChannelAccessSetting( dev, ieee->mode, &priv->ChannelAccessSetting);
1069 void rtl8185b_irq_enable(struct net_device *dev)
1071 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1073 priv->irq_enabled = 1;
1074 write_nic_dword(dev, IMR, priv->IntrMask);
1077 void MgntDisconnectIBSS(struct net_device *dev)
1079 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1082 for (i = 0; i < 6 ; i++)
1083 priv->ieee80211->current_network.bssid[i] = 0x55;
1087 priv->ieee80211->state = IEEE80211_NOLINK;
1091 * Vista add a Adhoc profile, HW radio off until OID_DOT11_RESET_REQUEST
1092 * Driver would set MSR=NO_LINK, then HW Radio ON, MgntQueue Stuck.
1093 * Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send.
1095 * Disable Beacon Queue Own bit, suggested by jong
1097 ieee80211_stop_send_beacons(priv->ieee80211);
1099 priv->ieee80211->link_change(dev);
1100 notify_wx_assoc_event(priv->ieee80211);
1103 void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn)
1105 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1108 SendDisassociation(priv->ieee80211, asSta, asRsn);
1110 if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) {
1111 /* ShuChen TODO: change media status. */
1113 for (i = 0; i < 6; i++)
1114 priv->ieee80211->current_network.bssid[i] = 0x22;
1116 ieee80211_disassociate(priv->ieee80211);
1120 void MgntDisconnectAP(struct net_device *dev, u8 asRsn)
1122 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1125 * Commented out by rcnjko, 2005.01.27:
1126 * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
1128 * 2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
1130 * In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
1131 * 2004.10.11, by rcnjko.
1133 MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid, asRsn);
1135 priv->ieee80211->state = IEEE80211_NOLINK;
1138 bool MgntDisconnect(struct net_device *dev, u8 asRsn)
1140 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1142 * Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
1145 if (IS_DOT11D_ENABLE(priv->ieee80211))
1146 Dot11d_Reset(priv->ieee80211);
1147 /* In adhoc mode, update beacon frame. */
1148 if (priv->ieee80211->state == IEEE80211_LINKED) {
1149 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1150 MgntDisconnectIBSS(dev);
1152 if (priv->ieee80211->iw_mode == IW_MODE_INFRA) {
1154 * We clear key here instead of MgntDisconnectAP() because that
1155 * MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
1156 * e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
1157 * used to handle disassociation related things to AP, e.g. send Disassoc
1158 * frame to AP. 2005.01.27, by rcnjko.
1160 MgntDisconnectAP(dev, asRsn);
1162 /* Indicate Disconnect, 2005.02.23, by rcnjko. */
1168 * Chang RF Power State.
1169 * Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
1174 bool SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState)
1176 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1177 bool bResult = false;
1179 if (eRFPowerState == priv->eRFPowerState)
1182 bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
1187 bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u32 ChangeSource)
1189 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1190 bool bActionAllowed = false;
1191 bool bConnectBySSID = false;
1192 RT_RF_POWER_STATE rtState;
1193 u16 RFWaitCounter = 0;
1196 * Prevent the race condition of RF state change. By Bruce, 2007-11-28.
1197 * Only one thread can change the RF state at one time, and others should wait to be executed.
1200 spin_lock_irqsave(&priv->rf_ps_lock, flag);
1201 if (priv->RFChangeInProgress) {
1202 spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
1203 /* Set RF after the previous action is done. */
1204 while (priv->RFChangeInProgress) {
1206 udelay(1000); /* 1 ms */
1208 /* Wait too long, return FALSE to avoid to be stuck here. */
1209 if (RFWaitCounter > 1000) { /* 1sec */
1210 printk("MgntActSet_RF_State(): Wait too long to set RF\n");
1211 /* TODO: Reset RF state? */
1216 priv->RFChangeInProgress = true;
1217 spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
1221 rtState = priv->eRFPowerState;
1223 switch (StateToSet) {
1226 * Turn On RF no matter the IPS setting because we need to update the RF state to Ndis under Vista, or
1227 * the Windows does not allow the driver to perform site survey any more. By Bruce, 2007-10-02.
1229 priv->RfOffReason &= (~ChangeSource);
1231 if (!priv->RfOffReason) {
1232 priv->RfOffReason = 0;
1233 bActionAllowed = true;
1235 if (rtState == eRfOff && ChangeSource >= RF_CHANGE_BY_HW)
1236 bConnectBySSID = true;
1241 /* 070125, rcnjko: we always keep connected in AP mode. */
1243 if (priv->RfOffReason > RF_CHANGE_BY_IPS) {
1246 * Disconnect to current BSS when radio off. Asked by QuanTa.
1248 * Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(),
1249 * because we do NOT need to set ssid to dummy ones.
1251 MgntDisconnect(dev, disas_lv_ss);
1252 /* Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI. */
1255 priv->RfOffReason |= ChangeSource;
1256 bActionAllowed = true;
1259 priv->RfOffReason |= ChangeSource;
1260 bActionAllowed = true;
1266 if (bActionAllowed) {
1267 /* Config HW to the specified mode. */
1268 SetRFPowerState(dev, StateToSet);
1271 /* Release RF spinlock */
1272 spin_lock_irqsave(&priv->rf_ps_lock, flag);
1273 priv->RFChangeInProgress = false;
1274 spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
1275 return bActionAllowed;
1278 void InactivePowerSave(struct net_device *dev)
1280 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1282 * This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
1283 * is really scheduled.
1284 * The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
1285 * previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
1286 * blocks the IPS procedure of switching RF.
1288 priv->bSwRfProcessing = true;
1290 MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS);
1293 * To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
1296 priv->bSwRfProcessing = false;
1301 * Enter the inactive power save mode. RF will be off
1303 void IPSEnter(struct net_device *dev)
1305 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1306 RT_RF_POWER_STATE rtState;
1307 if (priv->bInactivePs) {
1308 rtState = priv->eRFPowerState;
1311 * Do not enter IPS in the following conditions:
1312 * (1) RF is already OFF or Sleep
1313 * (2) bSwRfProcessing (indicates the IPS is still under going)
1314 * (3) Connected (only disconnected can trigger IPS)
1315 * (4) IBSS (send Beacon)
1316 * (5) AP mode (send Beacon)
1318 if (rtState == eRfOn && !priv->bSwRfProcessing
1319 && (priv->ieee80211->state != IEEE80211_LINKED)) {
1320 priv->eInactivePowerState = eRfOff;
1321 InactivePowerSave(dev);
1325 void IPSLeave(struct net_device *dev)
1327 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1328 RT_RF_POWER_STATE rtState;
1329 if (priv->bInactivePs) {
1330 rtState = priv->eRFPowerState;
1331 if ((rtState == eRfOff || rtState == eRfSleep) && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
1332 priv->eInactivePowerState = eRfOn;
1333 InactivePowerSave(dev);
1338 void rtl8185b_adapter_start(struct net_device *dev)
1340 struct r8180_priv *priv = ieee80211_priv(dev);
1341 struct ieee80211_device *ieee = priv->ieee80211;
1343 u8 SupportedWirelessMode;
1344 u8 InitWirelessMode;
1345 u8 bInvalidWirelessMode = 0;
1351 write_nic_byte(dev, 0x24e, (BIT5|BIT6|BIT0));
1354 priv->dma_poll_mask = 0;
1355 priv->dma_poll_stop_mask = 0;
1357 HwConfigureRTL8185(dev);
1358 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
1359 write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
1360 write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); /* default network type to 'No Link' */
1361 write_nic_word(dev, BcnItv, 100);
1362 write_nic_word(dev, AtimWnd, 2);
1363 PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
1364 write_nic_byte(dev, WPA_CONFIG, 0);
1365 MacConfig_85BASIC(dev);
1366 /* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko. */
1367 /* BT_DEMO_BOARD type */
1368 PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
1371 *---------------------------------------------------------------------------
1372 * Set up PHY related.
1373 *---------------------------------------------------------------------------
1375 /* Enable Config3.PARAM_En to revise AnaaParm. */
1376 write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */
1377 tmpu8 = read_nic_byte(dev, CONFIG3);
1378 write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En));
1379 /* Turn on Analog power. */
1380 /* Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko. */
1381 write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
1382 write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
1383 write_nic_word(dev, ANAPARAM3, 0x0010);
1385 write_nic_byte(dev, CONFIG3, tmpu8);
1386 write_nic_byte(dev, CR9346, 0x00);
1387 /* enable EEM0 and EEM1 in 9346CR */
1388 btCR9346 = read_nic_byte(dev, CR9346);
1389 write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
1391 /* B cut use LED1 to control HW RF on/off */
1392 TmpU1b = read_nic_byte(dev, CONFIG5);
1393 TmpU1b = TmpU1b & ~BIT3;
1394 write_nic_byte(dev, CONFIG5, TmpU1b);
1396 /* disable EEM0 and EEM1 in 9346CR */
1397 btCR9346 &= ~(0xC0);
1398 write_nic_byte(dev, CR9346, btCR9346);
1400 /* Enable Led (suggested by Jong) */
1401 /* B-cut RF Radio on/off 5e[3]=0 */
1402 btPSR = read_nic_byte(dev, PSR);
1403 write_nic_byte(dev, PSR, (btPSR | BIT3));
1404 /* setup initial timing for RFE. */
1405 write_nic_word(dev, RFPinsOutput, 0x0480);
1406 SetOutputEnableOfRfPins(dev);
1407 write_nic_word(dev, RFPinsSelect, 0x2488);
1413 * We assume RegWirelessMode has already been initialized before,
1414 * however, we has to validate the wireless mode here and provide a
1415 * reasonable initialized value if necessary. 2005.01.13, by rcnjko.
1417 SupportedWirelessMode = GetSupportedWirelessMode8185(dev);
1418 if ((ieee->mode != WIRELESS_MODE_B) &&
1419 (ieee->mode != WIRELESS_MODE_G) &&
1420 (ieee->mode != WIRELESS_MODE_A) &&
1421 (ieee->mode != WIRELESS_MODE_AUTO)) {
1422 /* It should be one of B, G, A, or AUTO. */
1423 bInvalidWirelessMode = 1;
1425 /* One of B, G, A, or AUTO. */
1426 /* Check if the wireless mode is supported by RF. */
1427 if ((ieee->mode != WIRELESS_MODE_AUTO) &&
1428 (ieee->mode & SupportedWirelessMode) == 0) {
1429 bInvalidWirelessMode = 1;
1433 if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) {
1434 /* Auto or other invalid value. */
1435 /* Assigne a wireless mode to initialize. */
1436 if ((SupportedWirelessMode & WIRELESS_MODE_A)) {
1437 InitWirelessMode = WIRELESS_MODE_A;
1438 } else if ((SupportedWirelessMode & WIRELESS_MODE_G)) {
1439 InitWirelessMode = WIRELESS_MODE_G;
1440 } else if ((SupportedWirelessMode & WIRELESS_MODE_B)) {
1441 InitWirelessMode = WIRELESS_MODE_B;
1443 DMESGW("InitializeAdapter8185(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n",
1444 SupportedWirelessMode);
1445 InitWirelessMode = WIRELESS_MODE_B;
1448 /* Initialize RegWirelessMode if it is not a valid one. */
1449 if (bInvalidWirelessMode)
1450 ieee->mode = (WIRELESS_MODE)InitWirelessMode;
1453 /* One of B, G, A. */
1454 InitWirelessMode = ieee->mode;
1456 priv->eRFPowerState = eRfOff;
1457 priv->RfOffReason = 0;
1459 MgntActSet_RF_State(dev, eRfOn, 0);
1462 * If inactive power mode is enabled, disable rf while in disconnected state.
1464 if (priv->bInactivePs)
1465 MgntActSet_RF_State(dev , eRfOff, RF_CHANGE_BY_IPS);
1467 ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
1469 /* ----------------------------------------------------------------------------- */
1471 rtl8185b_irq_enable(dev);
1473 netif_start_queue(dev);
1476 void rtl8185b_rx_enable(struct net_device *dev)
1479 /* for now we accept data, management & ctl frame*/
1480 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1483 if (dev->flags & IFF_PROMISC)
1484 DMESG("NIC in promisc mode");
1486 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
1487 dev->flags & IFF_PROMISC) {
1488 priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM);
1489 priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
1492 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR)
1493 priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF | RCR_APWRMGT | RCR_AICV;
1496 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
1497 priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACRC32;
1499 write_nic_dword(dev, RCR, priv->ReceiveConfig);
1503 cmd = read_nic_byte(dev, CMD);
1504 write_nic_byte(dev, CMD, cmd | (1<<CMD_RX_ENABLE_SHIFT));
1508 void rtl8185b_tx_enable(struct net_device *dev)
1512 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1514 write_nic_dword(dev, TCR, priv->TransmitConfig);
1515 byte = read_nic_byte(dev, MSR);
1516 byte |= MSR_LINK_ENEDCA;
1517 write_nic_byte(dev, MSR, byte);
1521 cmd = read_nic_byte(dev, CMD);
1522 write_nic_byte(dev, CMD, cmd | (1<<CMD_TX_ENABLE_SHIFT));