Please note: This project is no longer active. The website is kept online for historic purposes only.
If you´re looking for a Linux driver for your Atheros WLAN device, you should continue here .

Ticket #1206: debrand.c

File debrand.c, 7.4 kB (added by proski, 15 years ago)

Program to remove non-atheros subsystem ID (not working on AR5005G)

Line 
1 /*
2   * This program is derived from code bearing the following Copyright(s)
3   */
4  /*                                                        -*- linux-c -*-
5   *   _  _ ____ __ _ ___ ____ ____ __ _ _ _ _ |
6   * .  \/  |--| | \|  |  |--< [__] | \| | _X_ | s e c u r e  s y s t e m s
7   *
8   * .vt|ar5k - PCI/CardBus 802.11a WirelessLAN driver for Atheros AR5k chipsets
9   *
10   * Copyright (c) 2002, .vantronix | secure systems
11   *                     and Reyk Floeter <reyk@va...>
12   *
13   * This program is free software ; you can redistribute it and/or modify
14   * it under the terms of the GNU General Public License as published by
15   * the Free Software Foundation ; either version 2 of the License, or
16   * (at your option) any later version.
17   *
18   * This program is distributed in the hope that it will be useful,
19   * but WITHOUT ANY WARRANTY ; without even the implied warranty of
20   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   * GNU General Public License for more details.
22   *
23   * You should have received a copy of the GNU General Public License
24   * along with this program ; if not, write to the Free Software
25   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26   *
27   * Modified by wulu to change pci network class 02/06/2006
28   * Modified by Pavel Roskin to change subsystem ID 03/27/2007
29   *
30   */
31
32 #include <sys/mman.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37
38 #define AR5K_PCICFG 0x4010
39 #define AR5K_PCICFG_EEAE 0x00000001
40 #define AR5K_PCICFG_CLKRUNEN 0x00000004
41 #define AR5K_PCICFG_LED_PEND 0x00000020
42 #define AR5K_PCICFG_LED_ACT 0x00000040
43 #define AR5K_PCICFG_SL_INTEN 0x00000800
44 #define AR5K_PCICFG_BCTL                 0x00001000
45 #define AR5K_PCICFG_SPWR_DN 0x00010000
46
47  /* EEPROM Registers in the MAC */
48 #define AR5211_EEPROM_ADDR 0x6000
49 #define AR5211_EEPROM_DATA 0x6004
50 #define AR5211_EEPROM_COMD 0x6008
51 #define AR5211_EEPROM_COMD_READ 0x0001
52 #define AR5211_EEPROM_COMD_WRITE 0x0002
53 #define AR5211_EEPROM_COMD_RESET 0x0003
54 #define AR5211_EEPROM_STATUS 0x600C
55 #define AR5211_EEPROM_STAT_RDERR 0x0001
56 #define AR5211_EEPROM_STAT_RDDONE 0x0002
57 #define AR5211_EEPROM_STAT_WRERR 0x0003
58 #define AR5211_EEPROM_STAT_WRDONE 0x0004
59 #define AR5211_EEPROM_CONF 0x6010
60 #define ATHEROS_PCI_MEM_SIZE 0x10000
61 #define VT_WLAN_IN32(a)  (*((volatile unsigned long int *)(mem + (a))))
62 #define VT_WLAN_OUT32(v,a) (*((volatile unsigned long int *)(mem + (a))) = (v))
63
64 #define ATHEROS_EEPROM_VENDOR_ID 1
65 #define ATHEROS_EEPROM_DEVICE_ID 0
66 #define ATHEROS_EEPROM_SUBVENDOR_ID 8
67 #define ATHEROS_EEPROM_SUBDEVICE_ID 7
68
69 #define ATHEROS_PCI_ID_VENDOR 0x168c
70 #define ATHEROS_PCI_ID_SYSTEM 0x001a
71
72 static int
73 vt_ar5211_eeprom_read(unsigned char *mem, unsigned long int offset,
74                       unsigned short int *data)
75 {
76         int timeout = 10000;
77         unsigned long int status;
78
79         VT_WLAN_OUT32(0, AR5211_EEPROM_CONF), usleep(5);
80
81         /** enable eeprom read access */
82         VT_WLAN_OUT32(VT_WLAN_IN32(AR5211_EEPROM_COMD)
83                       | AR5211_EEPROM_COMD_RESET, AR5211_EEPROM_COMD);
84         usleep(5);
85
86         /** set address */
87         VT_WLAN_OUT32((unsigned char)offset, AR5211_EEPROM_ADDR);
88         usleep(5);
89
90         VT_WLAN_OUT32(VT_WLAN_IN32(AR5211_EEPROM_COMD)
91                       | AR5211_EEPROM_COMD_READ, AR5211_EEPROM_COMD);
92
93         while (timeout > 0) {
94                 usleep(1);
95                 status = VT_WLAN_IN32(AR5211_EEPROM_STATUS);
96                 if (status & AR5211_EEPROM_STAT_RDDONE) {
97                         if (status & AR5211_EEPROM_STAT_RDERR) {
98                                 (void)fputs("eeprom read access failed!\n",
99                                             stderr);
100                                 return 1;
101                         }
102                         status = VT_WLAN_IN32(AR5211_EEPROM_DATA);
103                         *data = status & 0x0000ffff;
104                         return 0;
105                 }
106                 timeout--;
107         }
108
109         (void)fputs("eeprom read timeout!\n", stderr);
110
111         return 1;
112 }
113
114 static int
115 vt_ar5211_eeprom_write(unsigned char *mem, unsigned int offset,
116                        unsigned short int new_data)
117 {
118         int timeout = 10000;
119         unsigned long int status;
120         unsigned long int pcicfg;
121         int i;
122         unsigned short int sdata;
123
124         /** enable eeprom access */
125         pcicfg = VT_WLAN_IN32(AR5K_PCICFG);
126         VT_WLAN_OUT32((pcicfg & ~AR5K_PCICFG_SPWR_DN), AR5K_PCICFG);
127         usleep(500);
128         VT_WLAN_OUT32(pcicfg | AR5K_PCICFG_EEAE /* | 0x2 */ , AR5K_PCICFG);
129         usleep(50);
130
131         VT_WLAN_OUT32(0, AR5211_EEPROM_STATUS);
132         usleep(50);
133
134         /* VT_WLAN_OUT32( 0x1, AR5211_EEPROM_CONF ) ; */
135         VT_WLAN_OUT32(0x0, AR5211_EEPROM_CONF);
136         usleep(50);
137
138         i = 100;
139       retry:
140         /** enable eeprom write access */
141         VT_WLAN_OUT32(AR5211_EEPROM_COMD_RESET, AR5211_EEPROM_COMD);
142         usleep(500);
143
144         /* Write data */
145         VT_WLAN_OUT32(new_data, AR5211_EEPROM_DATA);
146         usleep(5);
147
148         /** set address */
149         VT_WLAN_OUT32(offset, AR5211_EEPROM_ADDR);
150         usleep(5);
151
152         VT_WLAN_OUT32(AR5211_EEPROM_COMD_WRITE, AR5211_EEPROM_COMD);
153         usleep(5);
154
155         for (timeout = 10000; timeout > 0; --timeout) {
156                 status = VT_WLAN_IN32(AR5211_EEPROM_STATUS);
157                 if (status & 0xC) {
158                         if (status & AR5211_EEPROM_STAT_WRERR) {
159                                 fprintf(stderr,
160                                         "eeprom write access failed!\n");
161                                 return 1;
162                         }
163                         VT_WLAN_OUT32(0, AR5211_EEPROM_STATUS);
164                         usleep(10);
165                         break;
166                 }
167                 usleep(10);
168                 timeout--;
169         }
170         (void)vt_ar5211_eeprom_read(mem, offset, &sdata);
171         if ((sdata != new_data) && i) {
172                 --i;
173                 fprintf(stderr, "Retrying eeprom write!\n");
174                 goto retry;
175         }
176
177         return !i;
178 }
179
180 static void Usage(char *progname)
181 {
182         (void)fprintf(stderr, "Usage: %s physical_address_base\n", progname);
183         return;
184 }
185
186 int main(int argc, char **argv)
187 {
188         unsigned long int base_addr;
189         int fd;
190         unsigned char *membase;
191         unsigned short int vid, did, svid, sdid;
192         char input = 'y';
193         int warned = 0;
194
195         if (argc < 2) {
196                 Usage(argv[0]);
197                 exit(1);
198         }
199
200         base_addr = strtoul(argv[1], NULL, 16);
201
202         printf("\nusing 0x%lx as memory base address\n", base_addr);
203
204         fd = open("/dev/mem", O_RDWR);
205         if (fd < 0) {
206                 fprintf(stderr, "Open of /dev/mem failed!\n");
207                 exit(2);
208         }
209         membase = (unsigned char *)
210             mmap(0, ATHEROS_PCI_MEM_SIZE, PROT_READ | PROT_WRITE,
211                  MAP_SHARED | MAP_FILE, fd, base_addr);
212         if (membase == (unsigned char *)-1) {
213                 fprintf(stderr,
214                         "Mmap of device at 0x%08lX for 0x%X bytes failed!\n",
215                         base_addr, ATHEROS_PCI_MEM_SIZE);
216                 exit(3);
217         }
218
219         if (vt_ar5211_eeprom_read(membase, ATHEROS_EEPROM_VENDOR_ID, &vid)) {
220                 fprintf(stderr, "Vendor ID read failed - aborting\n");
221                 exit(4);
222         }
223
224         if (vt_ar5211_eeprom_read(membase, ATHEROS_EEPROM_DEVICE_ID, &did)) {
225                 fprintf(stderr, "Device ID read failed - aborting\n");
226                 exit(4);
227         }
228
229         if (vt_ar5211_eeprom_read(membase, ATHEROS_EEPROM_SUBVENDOR_ID, &svid)) {
230                 fprintf(stderr, "Subsystem Vendor ID read failed - aborting\n");
231                 exit(4);
232         }
233
234         if (vt_ar5211_eeprom_read(membase, ATHEROS_EEPROM_SUBDEVICE_ID, &sdid)) {
235                 fprintf(stderr, "Subsystem Device ID read failed - aborting\n");
236                 exit(4);
237         }
238
239         printf("Found device %04x:%04x %04x:%04x\n", vid, did, svid, sdid);
240         if (vid != ATHEROS_PCI_ID_VENDOR) {
241                 printf("WARNING: Vendor ID (%04x) is not Atheros (%04x)!\n",
242                        vid, ATHEROS_PCI_ID_VENDOR);
243                 warned = 1;
244         }
245         if (did != ATHEROS_PCI_ID_SYSTEM) {
246                 printf("WARNING: Device ID (%04x) is not AR5005G (%04x)!\n",
247                        did, ATHEROS_PCI_ID_SYSTEM);
248                 warned = 1;
249         }
250         if (warned) {
251                 printf("WARNING: Continue at your own risk!\n");
252         }
253
254         svid = vid;
255         sdid = did;
256
257         printf("Reprogramming ID to %04x:%04x %04x:%04x\n", vid, did, svid,
258                sdid);
259         printf("Is it OK? [y/N] ");
260         input = getchar();
261         if (input != 'y' && input != 'Y') {
262                 printf("Not confirmed\n");
263                 exit(5);
264         }
265         if (vt_ar5211_eeprom_write(membase, ATHEROS_EEPROM_SUBVENDOR_ID, svid)) {
266                 fprintf(stderr, "Subsystem Vendor ID write failed\n");
267                 exit(6);
268         }
269         if (vt_ar5211_eeprom_write(membase, ATHEROS_EEPROM_SUBDEVICE_ID, sdid)) {
270                 fprintf(stderr, "Subsystem Device ID write failed\n");
271                 exit(6);
272         }
273         printf("Done!\n");
274         return 0;
275 }