3 Copyright (C) 2001-2017 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include "radio_protos.h"
26 #include "eeprom_protos.h"
27 #include "timer_protos.h"
28 #include "realtek8187.h"
31 static UBYTE
GetPowerPair(struct DevUnit
*unit
, UWORD index
,
32 struct DevBase
*base
);
33 static VOID
WritePHY(struct DevUnit
*unit
, UWORD index
, ULONG value
,
34 struct DevBase
*base
);
37 static const UWORD gain_table
[] =
39 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
40 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
41 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
42 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
43 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
44 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
45 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
46 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
47 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
48 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
49 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
50 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
54 static const UBYTE agc_table
[] =
56 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57,
57 0x55, 0x53, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x47,
58 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
59 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27,
60 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17,
61 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
62 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
63 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
64 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
65 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
66 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
67 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
68 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f,
69 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
70 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
71 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
75 static const UBYTE ofdm_table
[] =
77 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
78 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
79 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
80 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
81 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
82 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
83 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
84 0x6d, 0x3c, 0xfb, 0x07
88 static UBYTE rtl8225_power_tables
[][8] =
90 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
91 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
92 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
93 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
94 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
95 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
96 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
97 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}
101 static UBYTE rtl8225_ch14_power_tables
[][8] =
103 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
104 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
105 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
106 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
107 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
108 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
109 {0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00},
110 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}
114 static UBYTE rtl8225_ofdm_power
[] = {0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4};
117 static const UBYTE eeprom_power_locations_l
[] =
119 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x7a, 0x7b,
120 0x7c, 0x7d, 0x36, 0x37, 0x38, 0x39
124 static const UBYTE eeprom_power_locations_b
[] =
126 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x7a, 0x7b,
127 0x7c, 0x7d, 0x36, 0x14, 0x38, 0x39
131 /****i* realtek8180.device/InitialiseRadio *********************************
137 * success = InitialiseRadio(unit, reinsertion)
139 * BOOL InitialiseRadio(struct DevUnit *, BOOL);
148 * success - Success indicator.
150 ****************************************************************************
154 BOOL
InitialiseRadio(struct DevUnit
*unit
, struct DevBase
*base
)
159 /* Get radio revision */
161 if((LEWord(ReadEEPROM(unit
, R8180ROM_RFCHIPID
, base
)) & 0xff) == 5)
163 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, 0x80);
164 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
, 0x80);
165 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
, 0x80);
166 BusyMilliDelay(500, base
);
168 WriteRadio(unit
, 0x0, 0x1b7, base
);
170 if(ReadRadio(unit
, 0x8, base
) != 0x588 ||
171 ReadRadio(unit
, 0x9, base
) != 0x700)
172 unit
->radio_type
= RTL8225_RADIO
;
174 unit
->radio_type
= RTL8225V2_RADIO
;
175 WriteRadio(unit
, 0x0, 0xb7, base
);
178 unit
->radio_type
= RTL8225V2B_RADIO
;
180 /* Initialise radio */
182 WriteRadio(unit
, 0x0, 0xb7, base
);
183 WriteRadio(unit
, 0x1, 0xee0, base
);
184 WriteRadio(unit
, 0x2, 0x44d, base
);
185 WriteRadio(unit
, 0x3, 0x441, base
);
186 WriteRadio(unit
, 0x4, 0x8c3, base
);
187 WriteRadio(unit
, 0x5, 0xc72, base
);
188 WriteRadio(unit
, 0x6, 0xe6, base
);
189 WriteRadio(unit
, 0x7, 0x82a, base
);
190 WriteRadio(unit
, 0x8, 0x3f, base
);
191 WriteRadio(unit
, 0x9, 0x335, base
);
192 WriteRadio(unit
, 0xa, 0x9d4, base
);
193 WriteRadio(unit
, 0xb, 0x7bb, base
);
194 WriteRadio(unit
, 0xc, 0x850, base
);
195 WriteRadio(unit
, 0xd, 0xcdf, base
);
196 WriteRadio(unit
, 0xe, 0x2b, base
);
197 WriteRadio(unit
, 0xf, 0x114, base
);
198 WriteRadio(unit
, 0x0, 0x1b7, base
);
200 for(i
= 0; i
< sizeof(gain_table
) / sizeof(UWORD
); i
++)
202 WriteRadio(unit
, 0x1, i
+ 1, base
);
203 WriteRadio(unit
, 0x2, gain_table
[i
], base
);
206 WriteRadio(unit
, 0x3, 0x80, base
);
207 WriteRadio(unit
, 0x5, 0x4, base
);
208 WriteRadio(unit
, 0x0, 0xb7, base
);
209 BusyMilliDelay(100, base
);
211 WriteRadio(unit
, 0x2, 0xc4d, base
);
212 WriteRadio(unit
, 0x2, 0x44d, base
);
213 WriteRadio(unit
, 0x0, 0x2bf, base
);
215 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_TXGAINCCK
, 0x3);
216 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_TXGAINOFDM
, 0x7);
217 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_TXANTENNA
, 0x3);
219 WriteOFDM(unit
, 0x80, 0x12, base
);
220 for(i
= 0; i
< sizeof(agc_table
); i
++)
222 WriteOFDM(unit
, 0xf, agc_table
[i
], base
);
223 WriteOFDM(unit
, 0xe, 0x80 + i
, base
);
224 WriteOFDM(unit
, 0xe, 0, base
);
226 WriteOFDM(unit
, 0x80, 0x10, base
);
228 for(i
= 0; i
< sizeof(ofdm_table
); i
++)
229 WriteOFDM(unit
, i
, ofdm_table
[i
], base
);
231 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_ACVO
, (7 << 12) | (3 << 8) | 0x1c);
232 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_ACVI
, (7 << 12) | (3 << 8) | 0x1c);
233 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_ACBE
, (7 << 12) | (3 << 8) | 0x1c);
234 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_ACBK
, (7 << 12) | (3 << 8) | 0x1c);
236 WriteOFDM(unit
, 0x97, 0x46, base
);
237 WriteOFDM(unit
, 0xa4, 0xb6, base
);
238 WriteOFDM(unit
, 0x85, 0xfc, base
);
239 WriteCCK(unit
, 0xc1, 0x88, base
);
248 VOID
GetPower(struct DevUnit
*unit
, struct DevBase
*base
)
250 const UBYTE
*locations
;
254 if(unit
->generation
== RTL8187L_GEN
)
255 locations
= eeprom_power_locations_l
;
257 locations
= eeprom_power_locations_b
;
259 for(i
= 0; i
< 14; i
++)
261 value
= GetPowerPair(unit
, locations
[i
], base
);
262 unit
->cck_power
[i
] = value
& 0xf;
263 unit
->ofdm_power
[i
] = value
>> 4;
269 static UBYTE
GetPowerPair(struct DevUnit
*unit
, UWORD index
,
270 struct DevBase
*base
)
274 value
= LEWord(ReadEEPROM(unit
, index
>> 1, base
));
275 if((index
& 0x1) != 0)
283 VOID
SetPower(struct DevUnit
*unit
, struct DevBase
*base
)
285 UBYTE power_level
, tx_gain
, table_no
, n
;
286 const UBYTE
*power_table
;
288 ULONG tx_conf
, loop_tx_conf
, channel_code
;
290 /* Get CCK power level and gain */
292 power_level
= unit
->cck_power
[unit
->channel
];
293 if(unit
->radio_type
== RTL8225_RADIO
)
297 table_no
= power_level
% 6;
298 tx_gain
= (2 << power_level
/ 6) - 1;
304 if(unit
->generation
!= RTL8187B1_GEN
)
306 power_level
+= unit
->base_cck_power
;
311 tx_gain
= power_level
<< 1;
314 /* Adjust power table number for RTL8225v2b */
316 if(unit
->radio_type
== RTL8225V2B_RADIO
)
318 if(unit
->generation
== RTL8187B1_GEN
)
320 if(power_level
> 11 && unit
->channel
!= 14)
322 else if(power_level
> 6)
333 if(unit
->channel
!= 14)
337 else if(power_level
> 11)
343 /* Get CCK power table and write it to chip */
345 if(unit
->channel
== 14)
346 power_table
= rtl8225_ch14_power_tables
[table_no
];
348 power_table
= rtl8225_power_tables
[table_no
];
350 for(i
= 0; i
< 8; i
++)
351 WriteCCK(unit
, 0x44 + i
, power_table
[i
], base
);
355 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_TXGAINCCK
, tx_gain
);
356 BusyMilliDelay(1, base
);
358 /* Get OFDM power level */
360 power_level
= unit
->ofdm_power
[unit
->channel
];
363 if(unit
->radio_type
<= RTL8225V2_RADIO
)
369 if(unit
->generation
!= RTL8187B1_GEN
)
374 if(unit
->radio_type
>= RTL8225V2_RADIO
)
375 power_level
+= unit
->base_ofdm_power
;
379 /* Enable analogue parameter 2 */
381 if(unit
->radio_type
<= RTL8225V2_RADIO
)
383 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_EEPROM
, R8180ECMD_CONFIG
);
384 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_CONFIG3
,
385 unit
->ByteIn(unit
->card
, 0x100 + R8180REG_CONFIG3
)
386 | R8180REG_CONFIG3F_ANAPARAMWRITE
);
387 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_ANAPARAM2
, 0x860c7312);
388 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_CONFIG3
,
389 unit
->ByteIn(unit
->card
, 0x100 + R8180REG_CONFIG3
)
390 & ~R8180REG_CONFIG3F_ANAPARAMWRITE
);
391 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_EEPROM
, 0);
396 if(unit
->radio_type
== RTL8225_RADIO
)
397 tx_gain
= (2 << power_level
/ 6) - 1;
399 tx_gain
= power_level
<< 1;
401 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_TXGAINOFDM
, tx_gain
);
403 /* Set up OFDM power */
405 if(unit
->radio_type
== RTL8225V2B_RADIO
)
407 if(unit
->generation
== RTL8187B1_GEN
)
418 else if(power_level
> 11)
423 WriteOFDM(unit
, 0x87, n
, base
);
424 WriteOFDM(unit
, 0x89, n
, base
);
426 else if(unit
->radio_type
== RTL8225V2_RADIO
)
428 WriteOFDM(unit
, 0x2, 0x42, base
);
429 WriteOFDM(unit
, 0x5, 0, base
);
430 WriteOFDM(unit
, 0x6, 0x40, base
);
431 WriteOFDM(unit
, 0x7, 0, base
);
432 WriteOFDM(unit
, 0x8, 0x40, base
);
436 n
= rtl8225_ofdm_power
[power_level
% 6];
437 WriteOFDM(unit
, 0x2, 0x42, base
);
438 WriteOFDM(unit
, 0x5, n
, base
);
439 WriteOFDM(unit
, 0x6, 0, base
);
440 WriteOFDM(unit
, 0x7, n
, base
);
441 WriteOFDM(unit
, 0x8, 0, base
);
444 BusyMilliDelay(1, base
);
448 tx_conf
= unit
->LELongIn(unit
->card
, 0x100 + R8180REG_TXCONF
);
449 loop_tx_conf
= tx_conf
& ~R8180REG_TXCONFF_LOOPBACK
450 | 1 << R8180REG_TXCONFB_LOOPBACK
;
451 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_TXCONF
,
453 if(unit
->channel
== 14)
454 channel_code
= 0xf72;
456 channel_code
= 0x7dc + unit
->channel
* 0x80;
457 WriteRadio(unit
, 0x7, channel_code
, base
);
458 BusyMilliDelay(10, base
);
459 unit
->LELongOut(unit
->card
, 0x100 + R8180REG_TXCONF
, tx_conf
);
466 /****i* realtek8180.device/WriteCCK ****************************************
469 * WriteCCK -- Write to a CCK PHY register.
472 * WriteCCK(unit, index, value)
474 * VOID WriteCCK(struct DevUnit *, UWORD, UWORD);
477 * unit - A unit of this device.
478 * index - Offset of register.
479 * value - Value to write to register.
484 ****************************************************************************
488 VOID
WriteCCK(struct DevUnit
*unit
, UWORD index
, UWORD value
,
489 struct DevBase
*base
)
491 WritePHY(unit
, index
, value
| 1 << 16, base
);
498 /****i* realtek8180.device/WriteOFDM ***************************************
501 * WriteOFDM -- Write to an OFDM PHY register.
504 * WriteOFDM(unit, index, value)
506 * VOID WriteOFDM(struct DevUnit *, UWORD, UWORD);
509 * unit - A unit of this device.
510 * index - Offset of register.
511 * value - Value to write to register.
516 ****************************************************************************
520 VOID
WriteOFDM(struct DevUnit
*unit
, UWORD index
, UWORD value
,
521 struct DevBase
*base
)
523 WritePHY(unit
, index
, value
, base
);
530 /****i* realtek8180.device/WritePHY ****************************************
533 * WritePHY -- Write to a CCK PHY register.
536 * WritePHY(unit, index, value)
538 * VOID WritePHY(struct DevUnit *, UWORD, ULONG);
541 * unit - A unit of this device.
542 * index - Offset of register.
543 * value - Value to write to register.
548 ****************************************************************************
552 static VOID
WritePHY(struct DevUnit
*unit
, UWORD index
, ULONG value
,
553 struct DevBase
*base
)
557 data
= value
<< 8 | index
| 0x80;
558 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_PHY
+ 3, data
>> 24);
559 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_PHY
+ 2, data
>> 16);
560 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_PHY
+ 1, data
>> 8);
561 unit
->ByteOut(unit
->card
, 0x100 + R8180REG_PHY
, data
);
568 /****i* realtek8180.device/ReadRadio ***************************************
571 * ReadRadio -- Read a radio register.
574 * value = ReadRadio(unit, index)
576 * UWORD ReadRadio(struct DevUnit *, UWORD);
579 * unit - A unit of this device.
580 * index - Offset of register.
583 * value - Value read from radio register.
585 ****************************************************************************
589 UWORD
ReadRadio(struct DevUnit
*unit
, UWORD index
,
590 struct DevBase
*base
)
592 UWORD value
= 0, value2
, output_reg
, enable_reg
, select_reg
;
595 output_reg
= unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
)
597 enable_reg
= unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
);
598 select_reg
= unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
);
599 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
,
601 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
,
603 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
605 BusyMicroDelay(4, base
);
607 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, output_reg
);
608 BusyMicroDelay(5, base
);
610 for(i
= 4; i
>= 0; i
--)
612 value2
= output_reg
| index
>> i
& 1;
616 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, value2
);
617 BusyMicroDelay(1, base
);
620 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, value2
| 0x2);
621 BusyMicroDelay(2, base
);
623 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, value2
| 0x2);
624 BusyMicroDelay(2, base
);
628 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, value2
);
629 BusyMicroDelay(1, base
);
633 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
635 BusyMicroDelay(2, base
);
637 for(i
= 0; i
< 2; i
++)
639 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
641 BusyMicroDelay(2, base
);
644 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
,
645 (enable_reg
| 0xe) & ~1);
647 for(i
= 11; i
>= 0; i
--)
649 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
651 BusyMicroDelay(1, base
);
653 for(j
= 0; j
< 3; j
++)
655 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
657 BusyMicroDelay(2, base
);
660 if((unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSINPUT
) & 0x2)
664 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
666 BusyMicroDelay(2, base
);
669 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, output_reg
| 0xc);
670 BusyMicroDelay(2, base
);
672 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
, enable_reg
);
673 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
, select_reg
);
674 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, 0x3a0);
681 /****i* realtek8180.device/WriteRadio **************************************
684 * WriteRadio -- Write to a radio register.
687 * WriteRadio(unit, index, value)
689 * VOID WriteRadio(struct DevUnit *, UWORD, UWORD);
692 * unit - A unit of this device.
693 * index - Offset of register.
694 * value - Value to write to register.
699 ****************************************************************************
703 VOID
WriteRadio(struct DevUnit
*unit
, UWORD index
, UWORD value
,
704 struct DevBase
*base
)
706 UWORD output_reg
, enable_reg
, select_reg
, value2
;
710 data
= (value
<< 4) | (index
& 0xf);
712 output_reg
= unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
)
714 enable_reg
= unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
);
715 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSENABLE
,
717 select_reg
= unit
->LEWordIn(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
);
718 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
,
720 BusyMicroDelay(10, base
);
722 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
724 BusyMicroDelay(2, base
);
726 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
, output_reg
);
727 BusyMicroDelay(10, base
);
729 if(unit
->bus
== USB_BUS
&& unit
->generation
>= RTL8187B0_GEN
)
730 unit
->LEWordOut(unit
->card
, 0x8225 << 16 | 0x200 + index
, value
);
733 for(i
= 15; i
>= 0; i
--)
735 value2
= output_reg
| (data
& (1 << i
)) >> i
;
738 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
740 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
742 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
745 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
750 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
752 BusyMicroDelay(10, base
);
754 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSOUTPUT
,
756 unit
->LEWordOut(unit
->card
, 0x100 + R8180REG_RFPINSSELECT
, select_reg
);