xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/realtek/r8168/r8168_asf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun ################################################################################
4*4882a593Smuzhiyun #
5*4882a593Smuzhiyun # r8168 is the Linux device driver released for Realtek Gigabit Ethernet
6*4882a593Smuzhiyun # controllers with PCI-Express interface.
7*4882a593Smuzhiyun #
8*4882a593Smuzhiyun # Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved.
9*4882a593Smuzhiyun #
10*4882a593Smuzhiyun # This program is free software; you can redistribute it and/or modify it
11*4882a593Smuzhiyun # under the terms of the GNU General Public License as published by the Free
12*4882a593Smuzhiyun # Software Foundation; either version 2 of the License, or (at your option)
13*4882a593Smuzhiyun # any later version.
14*4882a593Smuzhiyun #
15*4882a593Smuzhiyun # This program is distributed in the hope that it will be useful, but WITHOUT
16*4882a593Smuzhiyun # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17*4882a593Smuzhiyun # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18*4882a593Smuzhiyun # more details.
19*4882a593Smuzhiyun #
20*4882a593Smuzhiyun # You should have received a copy of the GNU General Public License along with
21*4882a593Smuzhiyun # this program; if not, see <http://www.gnu.org/licenses/>.
22*4882a593Smuzhiyun #
23*4882a593Smuzhiyun # Author:
24*4882a593Smuzhiyun # Realtek NIC software team <nicfae@realtek.com>
25*4882a593Smuzhiyun # No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
26*4882a593Smuzhiyun #
27*4882a593Smuzhiyun ################################################################################
28*4882a593Smuzhiyun */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /************************************************************************************
31*4882a593Smuzhiyun  *  This product is covered by one or more of the following patents:
32*4882a593Smuzhiyun  *  US6,570,884, US6,115,776, and US6,327,625.
33*4882a593Smuzhiyun  ***********************************************************************************/
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/module.h>
36*4882a593Smuzhiyun #include <linux/version.h>
37*4882a593Smuzhiyun #include <linux/pci.h>
38*4882a593Smuzhiyun #include <linux/netdevice.h>
39*4882a593Smuzhiyun #include <linux/etherdevice.h>
40*4882a593Smuzhiyun #include <linux/delay.h>
41*4882a593Smuzhiyun #include <linux/ethtool.h>
42*4882a593Smuzhiyun #include <linux/mii.h>
43*4882a593Smuzhiyun #include <linux/if_vlan.h>
44*4882a593Smuzhiyun #include <linux/crc32.h>
45*4882a593Smuzhiyun #include <linux/in.h>
46*4882a593Smuzhiyun #include <linux/ip.h>
47*4882a593Smuzhiyun #include <linux/tcp.h>
48*4882a593Smuzhiyun #include <linux/init.h>
49*4882a593Smuzhiyun #include <linux/rtnetlink.h>
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #include <asm/uaccess.h>
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #include "r8168.h"
54*4882a593Smuzhiyun #include "r8168_asf.h"
55*4882a593Smuzhiyun #include "rtl_eeprom.h"
56*4882a593Smuzhiyun 
rtl8168_asf_ioctl(struct net_device * dev,struct ifreq * ifr)57*4882a593Smuzhiyun int rtl8168_asf_ioctl(struct net_device *dev,
58*4882a593Smuzhiyun                       struct ifreq *ifr)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun         struct rtl8168_private *tp = netdev_priv(dev);
61*4882a593Smuzhiyun         void *user_data = ifr->ifr_data;
62*4882a593Smuzhiyun         struct asf_ioctl_struct asf_usrdata;
63*4882a593Smuzhiyun         unsigned long flags;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun         if (tp->mcfg != CFG_METHOD_7 && tp->mcfg != CFG_METHOD_8)
66*4882a593Smuzhiyun                 return -EOPNOTSUPP;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun         if (copy_from_user(&asf_usrdata, user_data, sizeof(struct asf_ioctl_struct)))
69*4882a593Smuzhiyun                 return -EFAULT;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun         spin_lock_irqsave(&tp->lock, flags);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun         switch (asf_usrdata.offset) {
74*4882a593Smuzhiyun         case HBPeriod:
75*4882a593Smuzhiyun                 rtl8168_asf_hbperiod(tp, asf_usrdata.arg, asf_usrdata.u.data);
76*4882a593Smuzhiyun                 break;
77*4882a593Smuzhiyun         case WD8Timer:
78*4882a593Smuzhiyun                 break;
79*4882a593Smuzhiyun         case WD16Rst:
80*4882a593Smuzhiyun                 rtl8168_asf_wd16rst(tp, asf_usrdata.arg, asf_usrdata.u.data);
81*4882a593Smuzhiyun                 break;
82*4882a593Smuzhiyun         case WD8Rst:
83*4882a593Smuzhiyun                 rtl8168_asf_time_period(tp, asf_usrdata.arg, WD8Rst, asf_usrdata.u.data);
84*4882a593Smuzhiyun                 break;
85*4882a593Smuzhiyun         case LSnsrPollCycle:
86*4882a593Smuzhiyun                 rtl8168_asf_time_period(tp, asf_usrdata.arg, LSnsrPollCycle, asf_usrdata.u.data);
87*4882a593Smuzhiyun                 break;
88*4882a593Smuzhiyun         case ASFSnsrPollPrd:
89*4882a593Smuzhiyun                 rtl8168_asf_time_period(tp, asf_usrdata.arg, ASFSnsrPollPrd, asf_usrdata.u.data);
90*4882a593Smuzhiyun                 break;
91*4882a593Smuzhiyun         case AlertReSendItvl:
92*4882a593Smuzhiyun                 rtl8168_asf_time_period(tp, asf_usrdata.arg, AlertReSendItvl, asf_usrdata.u.data);
93*4882a593Smuzhiyun                 break;
94*4882a593Smuzhiyun         case SMBAddr:
95*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, SMBAddr, RW_ONE_BYTE, asf_usrdata.u.data);
96*4882a593Smuzhiyun                 break;
97*4882a593Smuzhiyun         case ASFConfigR0:
98*4882a593Smuzhiyun                 rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR0, asf_usrdata.u.data);
99*4882a593Smuzhiyun                 break;
100*4882a593Smuzhiyun         case ASFConfigR1:
101*4882a593Smuzhiyun                 rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR1, asf_usrdata.u.data);
102*4882a593Smuzhiyun                 break;
103*4882a593Smuzhiyun         case ConsoleMA:
104*4882a593Smuzhiyun                 rtl8168_asf_console_mac(tp, asf_usrdata.arg, asf_usrdata.u.data);
105*4882a593Smuzhiyun                 break;
106*4882a593Smuzhiyun         case ConsoleIP:
107*4882a593Smuzhiyun                 rtl8168_asf_ip_address(tp, asf_usrdata.arg, ConsoleIP, asf_usrdata.u.data);
108*4882a593Smuzhiyun                 break;
109*4882a593Smuzhiyun         case IPAddr:
110*4882a593Smuzhiyun                 rtl8168_asf_ip_address(tp, asf_usrdata.arg, IPAddr, asf_usrdata.u.data);
111*4882a593Smuzhiyun                 break;
112*4882a593Smuzhiyun         case UUID:
113*4882a593Smuzhiyun                 rtl8168_asf_rw_uuid(tp, asf_usrdata.arg, asf_usrdata.u.data);
114*4882a593Smuzhiyun                 break;
115*4882a593Smuzhiyun         case IANA:
116*4882a593Smuzhiyun                 rtl8168_asf_rw_iana(tp, asf_usrdata.arg, asf_usrdata.u.data);
117*4882a593Smuzhiyun                 break;
118*4882a593Smuzhiyun         case SysID:
119*4882a593Smuzhiyun                 rtl8168_asf_rw_systemid(tp, asf_usrdata.arg, asf_usrdata.u.data);
120*4882a593Smuzhiyun                 break;
121*4882a593Smuzhiyun         case Community:
122*4882a593Smuzhiyun                 rtl8168_asf_community_string(tp, asf_usrdata.arg, asf_usrdata.u.string);
123*4882a593Smuzhiyun                 break;
124*4882a593Smuzhiyun         case StringLength:
125*4882a593Smuzhiyun                 rtl8168_asf_community_string_len(tp, asf_usrdata.arg, asf_usrdata.u.data);
126*4882a593Smuzhiyun                 break;
127*4882a593Smuzhiyun         case FmCapMsk:
128*4882a593Smuzhiyun                 rtl8168_asf_capability_masks(tp, asf_usrdata.arg, FmCapMsk, asf_usrdata.u.data);
129*4882a593Smuzhiyun                 break;
130*4882a593Smuzhiyun         case SpCMDMsk:
131*4882a593Smuzhiyun                 rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SpCMDMsk, asf_usrdata.u.data);
132*4882a593Smuzhiyun                 break;
133*4882a593Smuzhiyun         case SysCapMsk:
134*4882a593Smuzhiyun                 rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SysCapMsk, asf_usrdata.u.data);
135*4882a593Smuzhiyun                 break;
136*4882a593Smuzhiyun         case RmtRstAddr:
137*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstAddr, RW_ONE_BYTE, asf_usrdata.u.data);
138*4882a593Smuzhiyun                 break;
139*4882a593Smuzhiyun         case RmtRstCmd:
140*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstCmd, RW_ONE_BYTE, asf_usrdata.u.data);
141*4882a593Smuzhiyun                 break;
142*4882a593Smuzhiyun         case RmtRstData:
143*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstData, RW_ONE_BYTE, asf_usrdata.u.data);
144*4882a593Smuzhiyun                 break;
145*4882a593Smuzhiyun         case RmtPwrOffAddr:
146*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffAddr, RW_ONE_BYTE, asf_usrdata.u.data);
147*4882a593Smuzhiyun                 break;
148*4882a593Smuzhiyun         case RmtPwrOffCmd:
149*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffCmd, RW_ONE_BYTE, asf_usrdata.u.data);
150*4882a593Smuzhiyun                 break;
151*4882a593Smuzhiyun         case RmtPwrOffData:
152*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffData, RW_ONE_BYTE, asf_usrdata.u.data);
153*4882a593Smuzhiyun                 break;
154*4882a593Smuzhiyun         case RmtPwrOnAddr:
155*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnAddr, RW_ONE_BYTE, asf_usrdata.u.data);
156*4882a593Smuzhiyun                 break;
157*4882a593Smuzhiyun         case RmtPwrOnCmd:
158*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnCmd, RW_ONE_BYTE, asf_usrdata.u.data);
159*4882a593Smuzhiyun                 break;
160*4882a593Smuzhiyun         case RmtPwrOnData:
161*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnData, RW_ONE_BYTE, asf_usrdata.u.data);
162*4882a593Smuzhiyun                 break;
163*4882a593Smuzhiyun         case RmtPCRAddr:
164*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRAddr, RW_ONE_BYTE, asf_usrdata.u.data);
165*4882a593Smuzhiyun                 break;
166*4882a593Smuzhiyun         case RmtPCRCmd:
167*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRCmd, RW_ONE_BYTE, asf_usrdata.u.data);
168*4882a593Smuzhiyun                 break;
169*4882a593Smuzhiyun         case RmtPCRData:
170*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRData, RW_ONE_BYTE, asf_usrdata.u.data);
171*4882a593Smuzhiyun                 break;
172*4882a593Smuzhiyun         case ASFSnsr0Addr:
173*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, ASFSnsr0Addr, RW_ONE_BYTE, asf_usrdata.u.data);
174*4882a593Smuzhiyun                 break;
175*4882a593Smuzhiyun         case LSnsrAddr0:
176*4882a593Smuzhiyun                 rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, LSnsrAddr0, RW_ONE_BYTE, asf_usrdata.u.data);
177*4882a593Smuzhiyun                 break;
178*4882a593Smuzhiyun         case KO:
179*4882a593Smuzhiyun                 /* Get/Set Key Operation */
180*4882a593Smuzhiyun                 rtl8168_asf_key_access(tp, asf_usrdata.arg, KO, asf_usrdata.u.data);
181*4882a593Smuzhiyun                 break;
182*4882a593Smuzhiyun         case KA:
183*4882a593Smuzhiyun                 /* Get/Set Key Administrator */
184*4882a593Smuzhiyun                 rtl8168_asf_key_access(tp, asf_usrdata.arg, KA, asf_usrdata.u.data);
185*4882a593Smuzhiyun                 break;
186*4882a593Smuzhiyun         case KG:
187*4882a593Smuzhiyun                 /* Get/Set Key Generation */
188*4882a593Smuzhiyun                 rtl8168_asf_key_access(tp, asf_usrdata.arg, KG, asf_usrdata.u.data);
189*4882a593Smuzhiyun                 break;
190*4882a593Smuzhiyun         case KR:
191*4882a593Smuzhiyun                 /* Get/Set Key Random */
192*4882a593Smuzhiyun                 rtl8168_asf_key_access(tp, asf_usrdata.arg, KR, asf_usrdata.u.data);
193*4882a593Smuzhiyun                 break;
194*4882a593Smuzhiyun         default:
195*4882a593Smuzhiyun                 spin_unlock_irqrestore(&tp->lock, flags);
196*4882a593Smuzhiyun                 return -EOPNOTSUPP;
197*4882a593Smuzhiyun         }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun         spin_unlock_irqrestore(&tp->lock, flags);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun         if (copy_to_user(user_data, &asf_usrdata, sizeof(struct asf_ioctl_struct)))
202*4882a593Smuzhiyun                 return -EFAULT;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun         return 0;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
rtl8168_asf_hbperiod(struct rtl8168_private * tp,int arg,unsigned int * data)207*4882a593Smuzhiyun void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun         if (arg == ASF_GET)
210*4882a593Smuzhiyun                 data[ASFHBPERIOD] = rtl8168_eri_read(tp, HBPeriod, RW_TWO_BYTES, ERIAR_ASF);
211*4882a593Smuzhiyun         else if (arg == ASF_SET) {
212*4882a593Smuzhiyun                 rtl8168_eri_write(tp, HBPeriod, RW_TWO_BYTES, data[ASFHBPERIOD], ERIAR_ASF);
213*4882a593Smuzhiyun                 rtl8168_eri_write(tp, 0x1EC, RW_ONE_BYTE, 0x07, ERIAR_ASF);
214*4882a593Smuzhiyun         }
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun 
rtl8168_asf_wd16rst(struct rtl8168_private * tp,int arg,unsigned int * data)217*4882a593Smuzhiyun void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun         data[ASFWD16RST] = rtl8168_eri_read(tp, WD16Rst, RW_TWO_BYTES, ERIAR_ASF);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
rtl8168_asf_console_mac(struct rtl8168_private * tp,int arg,unsigned int * data)222*4882a593Smuzhiyun void rtl8168_asf_console_mac(struct rtl8168_private *tp, int arg, unsigned int *data)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun         int i;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun         if (arg == ASF_GET) {
227*4882a593Smuzhiyun                 for (i = 0; i < 6; i++)
228*4882a593Smuzhiyun                         data[i] = rtl8168_eri_read(tp, ConsoleMA + i, RW_ONE_BYTE, ERIAR_ASF);
229*4882a593Smuzhiyun         } else if (arg == ASF_SET) {
230*4882a593Smuzhiyun                 for (i = 0; i < 6; i++)
231*4882a593Smuzhiyun                         rtl8168_eri_write(tp, ConsoleMA + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun                 /* write the new console MAC address to EEPROM */
234*4882a593Smuzhiyun                 rtl8168_eeprom_write_sc(tp, 70, (data[1] << 8) | data[0]);
235*4882a593Smuzhiyun                 rtl8168_eeprom_write_sc(tp, 71, (data[3] << 8) | data[2]);
236*4882a593Smuzhiyun                 rtl8168_eeprom_write_sc(tp, 72, (data[5] << 8) | data[4]);
237*4882a593Smuzhiyun         }
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
rtl8168_asf_ip_address(struct rtl8168_private * tp,int arg,int offset,unsigned int * data)240*4882a593Smuzhiyun void rtl8168_asf_ip_address(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun         int i;
243*4882a593Smuzhiyun         int eeprom_off = 0;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun         if (arg == ASF_GET) {
246*4882a593Smuzhiyun                 for (i = 0; i < 4; i++)
247*4882a593Smuzhiyun                         data[i] = rtl8168_eri_read(tp, offset + i, RW_ONE_BYTE, ERIAR_ASF);
248*4882a593Smuzhiyun         } else if (arg == ASF_SET) {
249*4882a593Smuzhiyun                 for (i = 0; i < 4; i++)
250*4882a593Smuzhiyun                         rtl8168_eri_write(tp, offset + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun                 if (offset == ConsoleIP)
253*4882a593Smuzhiyun                         eeprom_off = 73;
254*4882a593Smuzhiyun                 else if (offset == IPAddr)
255*4882a593Smuzhiyun                         eeprom_off = 75;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun                 /* write the new IP address to EEPROM */
258*4882a593Smuzhiyun                 rtl8168_eeprom_write_sc(tp, eeprom_off, (data[1] << 8) | data[0]);
259*4882a593Smuzhiyun                 rtl8168_eeprom_write_sc(tp, eeprom_off + 1, (data[3] << 8) | data[2]);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun         }
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun 
rtl8168_asf_config_regs(struct rtl8168_private * tp,int arg,int offset,unsigned int * data)264*4882a593Smuzhiyun void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun         unsigned int value;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun         if (arg == ASF_GET) {
269*4882a593Smuzhiyun                 data[ASFCAPABILITY] = (rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF) & data[ASFCONFIG]) ? FUNCTION_ENABLE : FUNCTION_DISABLE;
270*4882a593Smuzhiyun         } else if (arg == ASF_SET) {
271*4882a593Smuzhiyun                 value = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun                 if (data[ASFCAPABILITY] == FUNCTION_ENABLE)
274*4882a593Smuzhiyun                         value |= data[ASFCONFIG];
275*4882a593Smuzhiyun                 else if (data[ASFCAPABILITY] == FUNCTION_DISABLE)
276*4882a593Smuzhiyun                         value &= ~data[ASFCONFIG];
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun                 rtl8168_eri_write(tp, offset, RW_ONE_BYTE, value, ERIAR_ASF);
279*4882a593Smuzhiyun         }
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
rtl8168_asf_capability_masks(struct rtl8168_private * tp,int arg,int offset,unsigned int * data)282*4882a593Smuzhiyun void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun         unsigned int len, bit_mask;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun         bit_mask = DISABLE_MASK;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun         if (offset == FmCapMsk) {
289*4882a593Smuzhiyun                 /* System firmware capabilities */
290*4882a593Smuzhiyun                 len = RW_FOUR_BYTES;
291*4882a593Smuzhiyun                 if (data[ASFCAPMASK] == FUNCTION_ENABLE)
292*4882a593Smuzhiyun                         bit_mask = FMW_CAP_MASK;
293*4882a593Smuzhiyun         } else if (offset == SpCMDMsk) {
294*4882a593Smuzhiyun                 /* Special commands */
295*4882a593Smuzhiyun                 len = RW_TWO_BYTES;
296*4882a593Smuzhiyun                 if (data[ASFCAPMASK] == FUNCTION_ENABLE)
297*4882a593Smuzhiyun                         bit_mask = SPC_CMD_MASK;
298*4882a593Smuzhiyun         } else {
299*4882a593Smuzhiyun                 /* System capability (offset == SysCapMsk)*/
300*4882a593Smuzhiyun                 len = RW_ONE_BYTE;
301*4882a593Smuzhiyun                 if (data[ASFCAPMASK] == FUNCTION_ENABLE)
302*4882a593Smuzhiyun                         bit_mask = SYS_CAP_MASK;
303*4882a593Smuzhiyun         }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun         if (arg == ASF_GET)
306*4882a593Smuzhiyun                 data[ASFCAPMASK] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF) ? FUNCTION_ENABLE : FUNCTION_DISABLE;
307*4882a593Smuzhiyun         else /* arg == ASF_SET */
308*4882a593Smuzhiyun                 rtl8168_eri_write(tp, offset, len, bit_mask, ERIAR_ASF);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
rtl8168_asf_community_string(struct rtl8168_private * tp,int arg,char * string)311*4882a593Smuzhiyun void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun         int i;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun         if (arg == ASF_GET) {
316*4882a593Smuzhiyun                 for (i = 0; i < COMMU_STR_MAX_LEN; i++)
317*4882a593Smuzhiyun                         string[i] = rtl8168_eri_read(tp, Community + i, RW_ONE_BYTE, ERIAR_ASF);
318*4882a593Smuzhiyun         } else { /* arg == ASF_SET */
319*4882a593Smuzhiyun                 for (i = 0; i < COMMU_STR_MAX_LEN; i++)
320*4882a593Smuzhiyun                         rtl8168_eri_write(tp, Community + i, RW_ONE_BYTE, string[i], ERIAR_ASF);
321*4882a593Smuzhiyun         }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
rtl8168_asf_community_string_len(struct rtl8168_private * tp,int arg,unsigned int * data)324*4882a593Smuzhiyun void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun         if (arg == ASF_GET)
327*4882a593Smuzhiyun                 data[ASFCOMMULEN] = rtl8168_eri_read(tp, StringLength, RW_ONE_BYTE, ERIAR_ASF);
328*4882a593Smuzhiyun         else /* arg == ASF_SET */
329*4882a593Smuzhiyun                 rtl8168_eri_write(tp, StringLength, RW_ONE_BYTE, data[ASFCOMMULEN], ERIAR_ASF);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
rtl8168_asf_time_period(struct rtl8168_private * tp,int arg,int offset,unsigned int * data)332*4882a593Smuzhiyun void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun         int pos = 0;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun         if (offset == WD8Rst)
337*4882a593Smuzhiyun                 pos = ASFWD8RESET;
338*4882a593Smuzhiyun         else if (offset == LSnsrPollCycle)
339*4882a593Smuzhiyun                 pos = ASFLSNRPOLLCYC;
340*4882a593Smuzhiyun         else if (offset == ASFSnsrPollPrd)
341*4882a593Smuzhiyun                 pos = ASFSNRPOLLCYC;
342*4882a593Smuzhiyun         else if (offset == AlertReSendItvl)
343*4882a593Smuzhiyun                 pos = ASFALERTRESND;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun         if (arg == ASF_GET)
346*4882a593Smuzhiyun                 data[pos] = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF);
347*4882a593Smuzhiyun         else /* arg == ASF_SET */
348*4882a593Smuzhiyun                 rtl8168_eri_write(tp, offset, RW_ONE_BYTE, data[pos], ERIAR_ASF);
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun 
rtl8168_asf_key_access(struct rtl8168_private * tp,int arg,int offset,unsigned int * data)352*4882a593Smuzhiyun void rtl8168_asf_key_access(struct rtl8168_private *tp, int arg, int offset, unsigned int *data)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun         int i, j;
355*4882a593Smuzhiyun         int key_off = 0;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun         if (arg == ASF_GET) {
358*4882a593Smuzhiyun                 for (i = 0; i < KEY_LEN; i++)
359*4882a593Smuzhiyun                         data[i] = rtl8168_eri_read(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, ERIAR_ASF);
360*4882a593Smuzhiyun         } else {
361*4882a593Smuzhiyun                 if (offset == KO)
362*4882a593Smuzhiyun                         key_off = 162;
363*4882a593Smuzhiyun                 else if (offset == KA)
364*4882a593Smuzhiyun                         key_off = 172;
365*4882a593Smuzhiyun                 else if (offset == KG)
366*4882a593Smuzhiyun                         key_off = 182;
367*4882a593Smuzhiyun                 else if (offset == KR)
368*4882a593Smuzhiyun                         key_off = 192;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun                 /* arg == ASF_SET */
371*4882a593Smuzhiyun                 for (i = 0; i < KEY_LEN; i++)
372*4882a593Smuzhiyun                         rtl8168_eri_write(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, data[i], ERIAR_ASF);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun                 /* write the new key to EEPROM */
375*4882a593Smuzhiyun                 for (i = 0, j = 19; i < 10; i++, j = j - 2)
376*4882a593Smuzhiyun                         rtl8168_eeprom_write_sc(tp, key_off + i, (data[j - 1] << 8) | data[j]);
377*4882a593Smuzhiyun         }
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
rtl8168_asf_rw_hexadecimal(struct rtl8168_private * tp,int arg,int offset,int len,unsigned int * data)380*4882a593Smuzhiyun void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun         if (arg == ASF_GET)
383*4882a593Smuzhiyun                 data[ASFRWHEXNUM] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF);
384*4882a593Smuzhiyun         else /* arg == ASF_SET */
385*4882a593Smuzhiyun                 rtl8168_eri_write(tp, offset, len, data[ASFRWHEXNUM], ERIAR_ASF);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
rtl8168_asf_rw_systemid(struct rtl8168_private * tp,int arg,unsigned int * data)388*4882a593Smuzhiyun void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun         int i;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun         if (arg == ASF_GET)
393*4882a593Smuzhiyun                 for (i = 0; i < SYSID_LEN ; i++)
394*4882a593Smuzhiyun                         data[i] = rtl8168_eri_read(tp, SysID + i, RW_ONE_BYTE, ERIAR_ASF);
395*4882a593Smuzhiyun         else /* arg == ASF_SET */
396*4882a593Smuzhiyun                 for (i = 0; i < SYSID_LEN ; i++)
397*4882a593Smuzhiyun                         rtl8168_eri_write(tp, SysID + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
rtl8168_asf_rw_iana(struct rtl8168_private * tp,int arg,unsigned int * data)400*4882a593Smuzhiyun void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun         int i;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun         if (arg == ASF_GET)
405*4882a593Smuzhiyun                 for (i = 0; i < RW_FOUR_BYTES; i++)
406*4882a593Smuzhiyun                         data[i] = rtl8168_eri_read(tp, IANA + i, RW_ONE_BYTE, ERIAR_ASF);
407*4882a593Smuzhiyun         else /* arg == ASF_SET */
408*4882a593Smuzhiyun                 for (i = 0; i < RW_FOUR_BYTES; i++)
409*4882a593Smuzhiyun                         rtl8168_eri_write(tp, IANA + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
rtl8168_asf_rw_uuid(struct rtl8168_private * tp,int arg,unsigned int * data)412*4882a593Smuzhiyun void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun         int i, j;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun         if (arg == ASF_GET)
417*4882a593Smuzhiyun                 for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++)
418*4882a593Smuzhiyun                         data[j] = rtl8168_eri_read(tp, UUID + i, RW_ONE_BYTE, ERIAR_ASF);
419*4882a593Smuzhiyun         else /* arg == ASF_SET */
420*4882a593Smuzhiyun                 for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++)
421*4882a593Smuzhiyun                         rtl8168_eri_write(tp, UUID + i, RW_ONE_BYTE, data[j], ERIAR_ASF);
422*4882a593Smuzhiyun }
423