00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <sys/mman.h>
00029 #include <stdio.h>
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032
00033 #define AR5K_PCICFG 0x4010
00034 #define AR5K_PCICFG_EEAE 0x00000001
00035 #define AR5K_PCICFG_CLKRUNEN 0x00000004
00036 #define AR5K_PCICFG_LED_PEND 0x00000020
00037 #define AR5K_PCICFG_LED_ACT 0x00000040
00038 #define AR5K_PCICFG_SL_INTEN 0x00000800
00039 #define AR5K_PCICFG_BCTL 0x00001000
00040 #define AR5K_PCICFG_SPWR_DN 0x00010000
00041
00042
00043 #define AR5211_EEPROM_ADDR 0x6000
00044 #define AR5211_EEPROM_DATA 0x6004
00045 #define AR5211_EEPROM_COMD 0x6008
00046 #define AR5211_EEPROM_COMD_READ 0x0001
00047 #define AR5211_EEPROM_COMD_WRITE 0x0002
00048 #define AR5211_EEPROM_COMD_RESET 0x0003
00049 #define AR5211_EEPROM_STATUS 0x600C
00050 #define AR5211_EEPROM_STAT_RDERR 0x0001
00051 #define AR5211_EEPROM_STAT_RDDONE 0x0002
00052 #define AR5211_EEPROM_STAT_WRERR 0x0003
00053 #define AR5211_EEPROM_STAT_WRDONE 0x0004
00054 #define AR5211_EEPROM_CONF 0x6010
00055
00056 #define VT_WLAN_IN32(a) (*((volatile unsigned long int *)(mem + (a))))
00057 #define VT_WLAN_OUT32(v,a) (*((volatile unsigned long int *)(mem + (a))) = (v))
00058
00059 int
00060 vt_ar5211_eeprom_read( unsigned char *mem,
00061 unsigned long int offset,
00062 unsigned short int *data )
00063 {
00064 int timeout = 10000 ;
00065 unsigned long int status ;
00066
00067 VT_WLAN_OUT32( 0, AR5211_EEPROM_CONF ),
00068 usleep( 5 ) ;
00069
00071 VT_WLAN_OUT32( VT_WLAN_IN32(AR5211_EEPROM_COMD)
00072 | AR5211_EEPROM_COMD_RESET, AR5211_EEPROM_COMD) ;
00073 usleep( 5 ) ;
00074
00076 VT_WLAN_OUT32( (unsigned char) offset, AR5211_EEPROM_ADDR) ;
00077 usleep( 5 ) ;
00078
00079 VT_WLAN_OUT32( VT_WLAN_IN32(AR5211_EEPROM_COMD)
00080 | AR5211_EEPROM_COMD_READ, AR5211_EEPROM_COMD) ;
00081
00082 while (timeout > 0) {
00083 usleep(1) ;
00084 status = VT_WLAN_IN32(AR5211_EEPROM_STATUS) ;
00085 if (status & AR5211_EEPROM_STAT_RDDONE) {
00086 if (status & AR5211_EEPROM_STAT_RDERR) {
00087 (void) fputs( "eeprom read access failed!\n",
00088 stderr ) ;
00089 return 1 ;
00090 }
00091 status = VT_WLAN_IN32(AR5211_EEPROM_DATA) ;
00092 *data = status & 0x0000ffff ;
00093 return 0 ;
00094 }
00095 timeout-- ;
00096 }
00097
00098 (void) fputs( "eeprom read timeout!\n", stderr ) ;
00099
00100 return 1 ;
00101 }
00102
00103 int
00104 vt_ar5211_eeprom_write( unsigned char *mem,
00105 unsigned int offset,
00106 unsigned short int new_data )
00107 {
00108 int timeout = 10000 ;
00109 unsigned long int status ;
00110 unsigned long int pcicfg ;
00111 int i ;
00112 unsigned short int sdata ;
00113
00115 pcicfg = VT_WLAN_IN32( AR5K_PCICFG ) ;
00116 VT_WLAN_OUT32( ( pcicfg & ~AR5K_PCICFG_SPWR_DN ), AR5K_PCICFG ) ;
00117 usleep( 500 ) ;
00118 VT_WLAN_OUT32( pcicfg | AR5K_PCICFG_EEAE , AR5K_PCICFG) ;
00119 usleep( 50 ) ;
00120
00121 VT_WLAN_OUT32( 0, AR5211_EEPROM_STATUS );
00122 usleep( 50 ) ;
00123
00124
00125 VT_WLAN_OUT32( 0x0, AR5211_EEPROM_CONF ) ;
00126 usleep( 50 ) ;
00127
00128 i = 100 ;
00129 retry:
00131 VT_WLAN_OUT32( AR5211_EEPROM_COMD_RESET, AR5211_EEPROM_COMD);
00132 usleep( 500 ) ;
00133
00134
00135 VT_WLAN_OUT32( new_data, AR5211_EEPROM_DATA );
00136 usleep( 5 ) ;
00137
00139 VT_WLAN_OUT32( offset, AR5211_EEPROM_ADDR);
00140 usleep( 5 ) ;
00141
00142 VT_WLAN_OUT32( AR5211_EEPROM_COMD_WRITE, AR5211_EEPROM_COMD);
00143 usleep( 5 ) ;
00144
00145 for ( timeout = 10000 ; timeout > 0 ; --timeout ) {
00146 status = VT_WLAN_IN32( AR5211_EEPROM_STATUS );
00147 if ( status & 0xC ) {
00148 if ( status & AR5211_EEPROM_STAT_WRERR ) {
00149 fprintf( stderr,
00150 "eeprom write access failed!\n");
00151 return 1 ;
00152 }
00153 VT_WLAN_OUT32( 0, AR5211_EEPROM_STATUS );
00154 usleep( 10 ) ;
00155 break ;
00156 }
00157 usleep( 10 ) ;
00158 timeout--;
00159 }
00160 (void) vt_ar5211_eeprom_read( mem, offset, &sdata ) ;
00161 if ( ( sdata != new_data ) && i ) {
00162 --i ;
00163 fprintf( stderr, "Retrying eeprom write!\n");
00164 goto retry ;
00165 }
00166
00167 return !i ;
00168 }
00169
00170 static void
00171 Usage( char *progname )
00172 {
00173 (void) fprintf( stderr,
00174 "Usage: %s physical_address_base new_country_code\n",
00175 progname ) ;
00176 return ;
00177 }
00178
00179 int
00180 main( int argc, char **argv )
00181 {
00182 unsigned long int base_addr ;
00183 int fd ;
00184 void *membase ;
00185 unsigned short int sdata ;
00186 unsigned short int new_cc ;
00187
00188 if ( argc < 3 ) {
00189 Usage( argv[0] ) ;
00190 return -1 ;
00191 }
00192
00193 base_addr = strtoul( argv[2], NULL, 0 ) ;
00194 if ( base_addr > 0xFFFF ) {
00195 (void) fputs(
00196 "Error: New domain code must be 16 bits or less\n",
00197 stderr ) ;
00198 Usage( argv[0] ) ;
00199 return -2 ;
00200 }
00201 new_cc = (unsigned short int) base_addr ;
00202 base_addr = strtoul( argv[1], NULL, 0 ) ;
00203 #define ATHEROS_PCI_MEM_SIZE 0x10000
00204 fd = open( "/dev/mem", O_RDWR ) ;
00205 if ( fd < 0 ) {
00206 fprintf( stderr, "Open of /dev/mem failed!\n" ) ;
00207 return -2 ;
00208 }
00209 membase = mmap( 0, ATHEROS_PCI_MEM_SIZE, PROT_READ|PROT_WRITE,
00210 MAP_SHARED|MAP_FILE, fd, base_addr ) ;
00211 if ( membase == (void *) -1 ) {
00212 fprintf( stderr,
00213 "Mmap of device at 0x%08X for 0x%X bytes failed!\n",
00214 base_addr, ATHEROS_PCI_MEM_SIZE ) ;
00215 return -3 ;
00216 }
00217
00218 #if 0
00219 (void) vt_ar5211_eeprom_write( (unsigned char *) membase,
00220 AR5K_EEPROM_PROTECT_OFFSET, 0 ) ;
00221 #endif
00222
00223 if ( vt_ar5211_eeprom_read( (unsigned char *) membase, 0xBF, &sdata ) )
00224 fprintf( stderr, "EEPROM read failed\n" ) ;
00225
00226 printf( "Current value 0x%04X will change to 0x%04X\n", sdata,
00227 new_cc ) ;
00228
00229 if ( vt_ar5211_eeprom_write( (unsigned char *) membase, 0xBF, new_cc ) )
00230 fprintf( stderr, "EEPROM write failed\n" ) ;
00231
00232 if ( vt_ar5211_eeprom_read( (unsigned char *) membase, 0xBF, &sdata ) )
00233 fprintf( stderr, "EEPROM read failed\n" ) ;
00234
00235 if ( sdata != new_cc )
00236 fprintf( stderr, "Write & read don't match 0x%04X != 0x%04X\n",
00237 new_cc, sdata ) ;
00238
00239 return 0 ;
00240 }
00241