My wireless card is recognised as being a AR5424 by OpenBSD.  Unfortunately,
it is a non-supported card.  After some hacking, I was able to make it work
by using some code both from Linux and NetBSD device drivers.

After some initial doubts about licensing issues (I though the Linux code
was GPL but at the end I figured out that it is dual-licensed BSD/GPL),
I decided to send my patch to the list.

Final question is: am I breaking something else?  Probably yes since I know
nothing about wireless cards... so, this patch works for me but I did not
tried it with any other card.

Here's the output of pcidump with information about my wireless card:

 20:0:0: Atheros AR5424                                                         
                                                                             
        0x0000: Vendor ID: 168c Product ID: 001c                                
                                                                             
        0x0004: Command: 0007 Status ID: 0010                                   
                                                                             
        0x0008: Class: 02 Subclass: 00 Interface: 00 Revision: 01               
                                                                             
        0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 08  
                                                                             
        0x0010: BAR mem 64bit addr: 0x00000000f8200000                          
                                                                             
        0x0018: BAR empty (00000000)                                            
                                                                             
        0x001c: BAR empty (00000000)                                            
                                                                             
        0x0020: BAR empty (00000000)                                            
                                                                             
        0x0024: BAR empty (00000000)                                            
                                                                             
        0x0028: Cardbus CIS: 00005001                                           
                                                                             
        0x002c: Subsystem Vendor ID: 144f Product ID: 7096                      
                                                                             
        0x0030: Expansion ROM Base Address: 00000000                            
                                                                             
        0x0038: 00000000                                                        
                                                                             
        0x003c: Interrupt Pin: 01 Line: 0b Min Gnt: 00 Max Lat: 00              
                                                                             
        0x0040: Capability 0x01: Power Management                               
                                                                             
        0x0050: Capability 0x05: Message Signaled Interrupts (MSI)              
                                                                             
        0x0060: Capability 0x10: PCI Express                                    
                                                                             
        0x0090: Capability 0x11: Extended Message Signaled Interrupts (MSI-X)   
                                                                             

Regards,
Luis

Index: dev/ic//ar5212.c
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5212.c,v
retrieving revision 1.51
diff -c -p -r1.51 ar5212.c
*** dev/ic//ar5212.c    2 Jun 2009 12:39:02 -0000       1.51
--- dev/ic//ar5212.c    22 Jan 2010 22:31:45 -0000
*************** HAL_BOOL         ar5k_ar5212_nic_wakeup(struct 
*** 30,35 ****
--- 30,36 ----
  u_int16_t      ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP);
  void           ar5k_ar5212_fill(struct ath_hal *);
  HAL_BOOL       ar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int);
+ void           ar5k_ar5212_hw_set_sleep_clock(struct ath_hal *, HAL_BOOL);
  
  /*
   * Initial register setting for the AR5212
*************** ar5k_ar5212_attach(u_int16_t device, voi
*** 237,242 ****
--- 238,248 ----
        } else if (srev == AR5K_SREV_VER_AR2425) {
                hal->ah_radio = AR5K_AR2425;
                hal->ah_phy_spending = AR5K_AR5212_PHY_SPENDING_AR5112;
+       } else if ((hal->ah_mac_version == (AR5K_SREV_VER_AR2424 >> 4)) ||
+               (hal->ah_phy_revision == AR5K_SREV_PHY_5413)) {
+               hal->ah_radio = AR5K_AR5413;
+               hal->ah_single_chip = AH_TRUE;
+               hal->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
        } else if (hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
                hal->ah_radio = AR5K_AR5111;
                hal->ah_phy_spending = AR5K_AR5212_PHY_SPENDING_AR5111;
*************** ar5k_ar5212_attach(u_int16_t device, voi
*** 262,267 ****
--- 268,279 ----
        }
        hal->ah_phy = AR5K_AR5212_PHY(0);
  
+       /* Enable pci core retry fix on Hainan (5213A) and later chips */
+       if (srev >= AR5K_SREV_VER_AR5213A) {
+               AR5K_REG_ENABLE_BITS(AR5K_AR5212_PCICFG,
+                       AR5K_AR5212_PCICFG_RETRY_FIX);
+       }
+ 
        if (hal->ah_pci_express == AH_TRUE) {
                /* PCI-Express based devices need some extra initialization */
                ar5k_write_ini(hal, ar5212_pcie, nitems(ar5212_pcie), 0);
*************** ar5k_ar5212_reset(struct ath_hal *hal, H
*** 485,496 ****
         */
        if (chanchange == AH_TRUE) {
                s_seq = AR5K_REG_READ(AR5K_AR5212_DCU_SEQNUM(0));
-               s_ant = AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
        } else {
                s_seq = 0;
-               s_ant = 1;
        }
  
        s_led[0] = AR5K_REG_READ(AR5K_AR5212_PCICFG) &
            AR5K_AR5212_PCICFG_LEDSTATE;
        s_led[1] = AR5K_REG_READ(AR5K_AR5212_GPIOCR);
--- 497,509 ----
         */
        if (chanchange == AH_TRUE) {
                s_seq = AR5K_REG_READ(AR5K_AR5212_DCU_SEQNUM(0));
        } else {
                s_seq = 0;
        }
  
+       /* Save default antenna */
+       s_ant = AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
+ 
        s_led[0] = AR5K_REG_READ(AR5K_AR5212_PCICFG) &
            AR5K_AR5212_PCICFG_LEDSTATE;
        s_led[1] = AR5K_REG_READ(AR5K_AR5212_GPIOCR);
*************** ar5k_ar5212_reset(struct ath_hal *hal, H
*** 544,549 ****
--- 557,564 ----
                return (AH_FALSE);
        }
  
+       ar5k_ar5212_hw_set_sleep_clock(hal, AH_FALSE);
+ 
        /* PHY access enable */
        AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ);
  
*************** ar5k_ar5212_set_txpower_limit(struct ath
*** 3034,3036 ****
--- 3049,3106 ----
        AR5K_PRINTF("changing txpower to %d\n", power);
        return (ar5k_ar5212_txpower(hal, channel, power));
  }
+ 
+ /*
+  * If there is an external 32KHz crystal available, use it
+  * as ref. clock instead of 32/40MHz clock and baseband clocks
+  * to save power during sleep or restore normal 32/40MHz
+  * operation.
+  *
+  * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+  *      123 - 127) require delay on access.
+  */
+ void
+ ar5k_ar5212_hw_set_sleep_clock(struct ath_hal *hal, HAL_BOOL enable)
+ {
+       struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+ 
+       /* Only set 32KHz settings if we have an external
+        * 32KHz crystal present */
+       if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+               AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
+               enable) {
+               /* TODO */
+       } else {
+               /* Disable sleep clock operation and
+                * restore default parameters */
+               AR5K_REG_DISABLE_BITS(AR5K_AR5212_PCICFG,
+                       AR5K_AR5212_PCICFG_SLEEP_CLOCK_EN);
+ 
+               AR5K_REG_WRITE_BITS(AR5K_AR5212_PCICFG,
+                       AR5K_AR5212_PCICFG_SLEEP_CLOCK_RATE, 0);
+ 
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SCR, 0x1f);
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SLMT,
+                       AR5K_AR5212_PHY_SLMT_32MHZ);
+ 
+               /* TODO: handle other versions */
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SCAL,
+                       AR5K_AR5212_PHY_SCAL_32MHZ);
+ 
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SCLOCK,
+                       AR5K_AR5212_PHY_SCLOCK_32MHZ);
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SDELAY,
+                       AR5K_AR5212_PHY_SCLOCK_32MHZ);
+ 
+               /* TODO: handle other versions */
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SPENDING, 0x14);
+ 
+               /* TODO: handle other versions */
+               AR5K_REG_WRITE_BITS(AR5K_AR5212_USEC,
+                       AR5K_AR5212_USEC_32, 39);
+ 
+               AR5K_REG_WRITE_BITS(AR5K_AR5212_TSF_PARM,
+                       AR5K_AR5212_TSF_PARM_INC, 1);
+       }
+ }
+ 
Index: dev/ic//ar5212reg.h
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5212reg.h,v
retrieving revision 1.12
diff -c -p -r1.12 ar5212reg.h
*** dev/ic//ar5212reg.h 30 Jul 2008 07:15:39 -0000      1.12
--- dev/ic//ar5212reg.h 22 Jan 2010 22:31:45 -0000
*************** typedef enum {
*** 589,622 ****
  /*
   * PCI configuration register
   */
! #define AR5K_AR5212_PCICFG            0x4010
! #define AR5K_AR5212_PCICFG_CLKRUNEN   0x00000004
! #define AR5K_AR5212_PCICFG_EESIZE     0x00000018
! #define AR5K_AR5212_PCICFG_EESIZE_S   3
! #define AR5K_AR5212_PCICFG_EESIZE_4K  0
! #define AR5K_AR5212_PCICFG_EESIZE_8K  1
! #define AR5K_AR5212_PCICFG_EESIZE_16K 2
! #define AR5K_AR5212_PCICFG_EESIZE_FAIL        3
! #define AR5K_AR5212_PCICFG_LED                0x00000060
! #define AR5K_AR5212_PCICFG_LED_NONE   0x00000000
! #define AR5K_AR5212_PCICFG_LED_PEND   0x00000020
! #define AR5K_AR5212_PCICFG_LED_ASSOC  0x00000040
! #define       AR5K_AR5212_PCICFG_BUS_SEL      0x00000380
! #define       AR5K_AR5212_PCICFG_CBEFIX_DIS   0x00000400
! #define AR5K_AR5212_PCICFG_SL_INTEN   0x00000800
! #define AR5K_AR5212_PCICFG_SL_INPEN   0x00002800
! #define AR5K_AR5212_PCICFG_SPWR_DN    0x00010000
! #define AR5K_AR5212_PCICFG_LEDMODE    0x000e0000
! #define AR5K_AR5212_PCICFG_LEDMODE_PROP       0x00000000
! #define AR5K_AR5212_PCICFG_LEDMODE_PROM       0x00020000
! #define AR5K_AR5212_PCICFG_LEDMODE_PWR        0x00040000
! #define AR5K_AR5212_PCICFG_LEDMODE_RAND       0x00060000
! #define AR5K_AR5212_PCICFG_LEDBLINK   0x00700000
! #define AR5K_AR5212_PCICFG_LEDBLINK_S 20
! #define AR5K_AR5212_PCICFG_LEDSLOW    0x00800000
  #define AR5K_AR5212_PCICFG_LEDSTATE                                   \
        (AR5K_AR5212_PCICFG_LED | AR5K_AR5212_PCICFG_LEDMODE |          \
        AR5K_AR5212_PCICFG_LEDBLINK | AR5K_AR5212_PCICFG_LEDSLOW)
  
  /*
   * "General Purpose Input/Output" (GPIO) control register
--- 589,626 ----
  /*
   * PCI configuration register
   */
! #define AR5K_AR5212_PCICFG                    0x4010
! #define AR5K_AR5212_PCICFG_SLEEP_CLOCK_EN     0x00000002 /* Enable sleep 
clock */
! #define AR5K_AR5212_PCICFG_CLKRUNEN           0x00000004
! #define AR5K_AR5212_PCICFG_EESIZE             0x00000018
! #define AR5K_AR5212_PCICFG_EESIZE_S           3
! #define AR5K_AR5212_PCICFG_EESIZE_4K          0
! #define AR5K_AR5212_PCICFG_EESIZE_8K          1
! #define AR5K_AR5212_PCICFG_EESIZE_16K         2
! #define AR5K_AR5212_PCICFG_EESIZE_FAIL                3
! #define AR5K_AR5212_PCICFG_LED                        0x00000060
! #define AR5K_AR5212_PCICFG_LED_NONE           0x00000000
! #define AR5K_AR5212_PCICFG_LED_PEND           0x00000020
! #define AR5K_AR5212_PCICFG_LED_ASSOC          0x00000040
! #define       AR5K_AR5212_PCICFG_BUS_SEL              0x00000380
! #define       AR5K_AR5212_PCICFG_CBEFIX_DIS           0x00000400
! #define AR5K_AR5212_PCICFG_SL_INTEN           0x00000800
! #define AR5K_AR5212_PCICFG_SL_INPEN           0x00002800
! #define AR5K_AR5212_PCICFG_RETRY_FIX          0x00001000 /* Enable pci core 
retry fix */
! #define AR5K_AR5212_PCICFG_SPWR_DN            0x00010000
! #define AR5K_AR5212_PCICFG_LEDMODE            0x000e0000
! #define AR5K_AR5212_PCICFG_LEDMODE_PROP               0x00000000
! #define AR5K_AR5212_PCICFG_LEDMODE_PROM               0x00020000
! #define AR5K_AR5212_PCICFG_LEDMODE_PWR                0x00040000
! #define AR5K_AR5212_PCICFG_LEDMODE_RAND               0x00060000
! #define AR5K_AR5212_PCICFG_LEDBLINK           0x00700000
! #define AR5K_AR5212_PCICFG_LEDBLINK_S         20
! #define AR5K_AR5212_PCICFG_LEDSLOW            0x00800000
  #define AR5K_AR5212_PCICFG_LEDSTATE                                   \
        (AR5K_AR5212_PCICFG_LED | AR5K_AR5212_PCICFG_LEDMODE |          \
        AR5K_AR5212_PCICFG_LEDBLINK | AR5K_AR5212_PCICFG_LEDSLOW)
+ #define AR5K_AR5212_PCICFG_SLEEP_CLOCK_RATE   0x03000000 /* Sleep clock rate 
*/
+ #define AR5K_AR5212_PCICFG_SLEEP_CLOCK_RATE_S 24
  
  /*
   * "General Purpose Input/Output" (GPIO) control register
*************** typedef enum {
*** 993,999 ****
   * TSF parameter register
   */
  #define AR5K_AR5212_TSF_PARM          0x8104
! #define AR5K_AR5212_TSF_PARM_INC_M    0x000000ff
  #define AR5K_AR5212_TSF_PARM_INC_S    0
  
  /*
--- 997,1003 ----
   * TSF parameter register
   */
  #define AR5K_AR5212_TSF_PARM          0x8104
! #define AR5K_AR5212_TSF_PARM_INC      0x000000ff
  #define AR5K_AR5212_TSF_PARM_INC_S    0
  
  /*
Index: dev/ic//ar5xxx.c
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5xxx.c,v
retrieving revision 1.55
diff -c -p -r1.55 ar5xxx.c
*** dev/ic//ar5xxx.c    23 Sep 2009 18:03:30 -0000      1.55
--- dev/ic//ar5xxx.c    22 Jan 2010 22:31:45 -0000
*************** ar5k_eeprom_init(struct ath_hal *hal)
*** 892,897 ****
                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+ 
+               /* XXX: Don't know which versions include these two */
+               AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
+ 
+               if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
+                       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
        }
  
        if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
Index: dev/ic//ar5xxx.h
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5xxx.h,v
retrieving revision 1.47
diff -c -p -r1.47 ar5xxx.h
*** dev/ic//ar5xxx.h    24 Jul 2009 16:31:27 -0000      1.47
--- dev/ic//ar5xxx.h    22 Jan 2010 22:38:15 -0000
*************** struct ar5k_gain {
*** 695,706 ****
  #define AR5K_EEPROM_OBDB1_2GHZ        0x00ed
  
  /* Misc values available since EEPROM 4.0 */
! #define AR5K_EEPROM_MISC0             0x00c4
! #define AR5K_EEPROM_EARSTART(_v)      ((_v) & 0xfff)
! #define AR5K_EEPROM_EEMAP(_v)         (((_v) >> 14) & 0x3)
! #define AR5K_EEPROM_MISC1             0x00c5
! #define AR5K_EEPROM_TARGET_PWRSTART(_v)       ((_v) & 0xfff)
! #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)       (((_v) >> 14) & 0x1)
  
  /* Some EEPROM defines */
  #define AR5K_EEPROM_EEP_SCALE         100
--- 695,709 ----
  #define AR5K_EEPROM_OBDB1_2GHZ        0x00ed
  
  /* Misc values available since EEPROM 4.0 */
! #define AR5K_EEPROM_MISC0                     0x00c4
! #define AR5K_EEPROM_EARSTART(_v)              ((_v) & 0xfff)
! #define AR5K_EEPROM_EEMAP(_v)                 (((_v) >> 14) & 0x3)
! #define AR5K_EEPROM_MISC1                     0x00c5
! #define AR5K_EEPROM_TARGET_PWRSTART(_v)               ((_v) & 0xfff)
! #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)               (((_v) >> 14) & 0x1)
! #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v)   (((_v) >> 15) & 0x1)
! #define AR5K_EEPROM_MISC2                     0x00c6
! #define AR5K_EEPROM_MISC3                     0x00c7
  
  /* Some EEPROM defines */
  #define AR5K_EEPROM_EEP_SCALE         100
*************** struct ar5k_eeprom_info {
*** 751,756 ****
--- 754,761 ----
        u_int16_t       ee_ant_gain;
        u_int16_t       ee_misc0;
        u_int16_t       ee_misc1;
+       u_int16_t       ee_misc2;
+       u_int16_t       ee_misc3;
        u_int16_t       ee_cck_ofdm_gain_delta;
        u_int16_t       ee_cck_ofdm_power_delta;
        u_int16_t       ee_scaled_cck_delta;
*************** struct ar5k_srev_name {
*** 1271,1280 ****
--- 1276,1288 ----
  #define AR5K_SREV_RAD_2112    0x40
  #define AR5K_SREV_RAD_2112A   0x45
  #define AR5K_SREV_RAD_SC0     0x56
+ #define AR5K_SREV_RAD_5413    0x60
  #define AR5K_SREV_RAD_SC1     0x63
  #define AR5K_SREV_RAD_SC2     0xa2
  #define AR5K_SREV_RAD_5133    0xc0
  #define AR5K_SREV_RAD_UNSUPP  0xff
+ 
+ #define AR5K_SREV_PHY_5413    0x61
  
  #define AR5K_DEVID_AR2413     0x001a
  #define AR5K_DEVID_AR5413     0x001b

Reply via email to