Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

* 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1519 commits)
  staging: et131x: Remove redundant check and return statement
  staging: et131x: Mainly whitespace changes to appease checkpatch
  staging: et131x: Remove last of the forward declarations
  staging: et131x: Remove even more forward declarations
  staging: et131x: Remove yet more forward declarations
  staging: et131x: Remove more forward declarations
  staging: et131x: Remove forward declaration of et131x_adapter_setup
  staging: et131x: Remove some forward declarations
  staging: et131x: Remove unused rx_ring.recv_packet_pool
  staging: et131x: Remove call to find pci pm capability
  staging: et131x: Remove redundant et131x_reset_recv() call
  staging: et131x: Remove unused rx_ring.recv_buffer_pool
  Staging: bcm: Fix three initialization errors in InterfaceDld.c
  Staging: bcm: Fix coding style issues in InterfaceDld.c
  staging:iio:dac: Add AD5360 driver
  staging:iio:trigger:bfin-timer: Fix compile error
  Staging: vt6655: add some range checks before memcpy()
  Staging: vt6655: whitespace fixes to iotcl.c
  Staging: vt6656: add some range checks before memcpy()
  Staging: vt6656: whitespace cleanups in ioctl.c
  ...

Fix up conflicts in:
 - drivers/{Kconfig,Makefile}, drivers/staging/{Kconfig,Makefile}:
	vg driver movement
 - drivers/staging/brcm80211/brcmfmac/{dhd_linux.c,mac80211_if.c}:
	driver removal vs now stale changes
 - drivers/staging/rtl8192e/r8192E_core.c:
	driver removal vs now stale changes
 - drivers/staging/et131x/et131*:
	driver consolidation into one file, tried to do fixups
This commit is contained in:
Linus Torvalds 2011-10-26 15:39:02 +02:00
commit aa77677e0a
725 changed files with 104276 additions and 180820 deletions

View File

@ -6171,7 +6171,7 @@ S: Maintained
STAGING SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@suse.de>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
L: devel@driverdev.osuosl.org
S: Maintained
F: drivers/staging/
@ -6212,6 +6212,11 @@ M: David Rowe <david@rowetel.com>
S: Odd Fixes
F: drivers/staging/echo/
STAGING - ET131X NETWORK DRIVER
M: Mark Einon <mark.einon@gmail.com>
S: Odd Fixes
F: drivers/staging/et131x/
STAGING - FLARION FT1000 DRIVERS
M: Marek Belisko <marek.belisko@gmail.com>
S: Odd Fixes
@ -6240,6 +6245,13 @@ W: http://www.lirc.org/
S: Odd Fixes
F: drivers/staging/lirc/
STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
M: Julian Andres Klode <jak@jak-linux.org>
M: Marc Dietrich <marvin24@gmx.de>
L: ac100@lists.launchpad.net (moderated for non-subscribers)
S: Maintained
F: drivers/staging/nvec/
STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
M: Andres Salomon <dilinger@queued.net>
M: Chris Ball <cjb@laptop.org>

View File

@ -189,5 +189,6 @@
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
#endif

View File

@ -132,6 +132,8 @@ source "drivers/iommu/Kconfig"
source "drivers/virt/Kconfig"
source "drivers/hv/Kconfig"
source "drivers/devfreq/Kconfig"
endmenu

View File

@ -129,5 +129,6 @@ obj-$(CONFIG_IOMMU_SUPPORT) += iommu/
# Virtualization drivers
obj-$(CONFIG_VIRT_DRIVERS) += virt/
obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_PM_DEVFREQ) += devfreq/

View File

@ -1,613 +0,0 @@
/*
* atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
*
* Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*
*/
#ifndef _SCC_H
#define _SCC_H
#include <linux/delay.h>
/* Special configuration ioctls for the Atari SCC5380 Serial
* Communications Controller
*/
/* ioctl command codes */
#define TIOCGATSCC 0x54c0 /* get SCC configuration */
#define TIOCSATSCC 0x54c1 /* set SCC configuration */
#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */
/* Clock sources */
#define CLK_RTxC 0
#define CLK_TRxC 1
#define CLK_PCLK 2
/* baud_bases for the common clocks in the Atari. These are the real
* frequencies divided by 16.
*/
#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */
#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */
#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */
#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */
#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused
* clock sources */
/* The SCC clock configuration structure */
struct scc_clock_config {
unsigned RTxC_base; /* base_baud of RTxC */
unsigned TRxC_base; /* base_baud of TRxC */
unsigned PCLK_base; /* base_baud of PCLK, both channels! */
struct {
unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
unsigned divisor; /* divisor for base baud, valid values:
* see below */
} baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300,
* 600, 1200, 1800, 2400, 4800, 9600,
* 19200, 38400, 57600 and 115200 bps.
* The last two could be replaced by
* other rates > 38400 if they're not
* possible.
*/
};
/* The following divisors are valid:
*
* - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
* the BRG)
*
* - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
*
* - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
*
*/
struct scc_port {
struct gs_port gs;
volatile unsigned char *ctrlp;
volatile unsigned char *datap;
int x_char; /* xon/xoff character */
int c_dcd;
int channel;
struct scc_port *port_a; /* Reference to port A and B */
struct scc_port *port_b; /* structs for reg access */
};
#define SCC_MAGIC 0x52696368
/***********************************************************************/
/* */
/* Register Names */
/* */
/***********************************************************************/
/* The SCC documentation gives no explicit names to the registers,
* they're just called WR0..15 and RR0..15. To make the source code
* better readable and make the transparent write reg read access (see
* below) possible, I christen them here with self-invented names.
* Note that (real) read registers are assigned numbers 16..31. WR7'
* has number 33.
*/
#define COMMAND_REG 0 /* wo */
#define INT_AND_DMA_REG 1 /* wo */
#define INT_VECTOR_REG 2 /* rw, common to both channels */
#define RX_CTRL_REG 3 /* rw */
#define AUX1_CTRL_REG 4 /* rw */
#define TX_CTRL_REG 5 /* rw */
#define SYNC_ADR_REG 6 /* wo */
#define SYNC_CHAR_REG 7 /* wo */
#define SDLC_OPTION_REG 33 /* wo */
#define TX_DATA_REG 8 /* wo */
#define MASTER_INT_CTRL 9 /* wo, common to both channels */
#define AUX2_CTRL_REG 10 /* rw */
#define CLK_CTRL_REG 11 /* wo */
#define TIMER_LOW_REG 12 /* rw */
#define TIMER_HIGH_REG 13 /* rw */
#define DPLL_CTRL_REG 14 /* wo */
#define INT_CTRL_REG 15 /* rw */
#define STATUS_REG 16 /* ro */
#define SPCOND_STATUS_REG 17 /* wo */
/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
#define CURR_VECTOR_REG 18 /* Ch. B only, Ch. A for rw */
#define INT_PENDING_REG 19 /* Channel A only! */
/* RR4 is WR4, if b6(MR7') == 1 */
/* RR5 is WR5, if b6(MR7') == 1 */
#define FS_FIFO_LOW_REG 22 /* ro */
#define FS_FIFO_HIGH_REG 23 /* ro */
#define RX_DATA_REG 24 /* ro */
/* RR9 is WR3, if b6(MR7') == 1 */
#define DPLL_STATUS_REG 26 /* ro */
/* RR11 is WR10, if b6(MR7') == 1 */
/* RR12 is WR12 */
/* RR13 is WR13 */
/* RR14 not present */
/* RR15 is WR15 */
/***********************************************************************/
/* */
/* Register Values */
/* */
/***********************************************************************/
/* WR0: COMMAND_REG "CR" */
#define CR_RX_CRC_RESET 0x40
#define CR_TX_CRC_RESET 0x80
#define CR_TX_UNDERRUN_RESET 0xc0
#define CR_EXTSTAT_RESET 0x10
#define CR_SEND_ABORT 0x18
#define CR_ENAB_INT_NEXT_RX 0x20
#define CR_TX_PENDING_RESET 0x28
#define CR_ERROR_RESET 0x30
#define CR_HIGHEST_IUS_RESET 0x38
/* WR1: INT_AND_DMA_REG "IDR" */
#define IDR_EXTSTAT_INT_ENAB 0x01
#define IDR_TX_INT_ENAB 0x02
#define IDR_PARERR_AS_SPCOND 0x04
#define IDR_RX_INT_DISAB 0x00
#define IDR_RX_INT_FIRST 0x08
#define IDR_RX_INT_ALL 0x10
#define IDR_RX_INT_SPCOND 0x18
#define IDR_RX_INT_MASK 0x18
#define IDR_WAITREQ_RX 0x20
#define IDR_WAITREQ_IS_REQ 0x40
#define IDR_WAITREQ_ENAB 0x80
/* WR3: RX_CTRL_REG "RCR" */
#define RCR_RX_ENAB 0x01
#define RCR_DISCARD_SYNC_CHARS 0x02
#define RCR_ADDR_SEARCH 0x04
#define RCR_CRC_ENAB 0x08
#define RCR_SEARCH_MODE 0x10
#define RCR_AUTO_ENAB_MODE 0x20
#define RCR_CHSIZE_MASK 0xc0
#define RCR_CHSIZE_5 0x00
#define RCR_CHSIZE_6 0x40
#define RCR_CHSIZE_7 0x80
#define RCR_CHSIZE_8 0xc0
/* WR4: AUX1_CTRL_REG "A1CR" */
#define A1CR_PARITY_MASK 0x03
#define A1CR_PARITY_NONE 0x00
#define A1CR_PARITY_ODD 0x01
#define A1CR_PARITY_EVEN 0x03
#define A1CR_MODE_MASK 0x0c
#define A1CR_MODE_SYNCR 0x00
#define A1CR_MODE_ASYNC_1 0x04
#define A1CR_MODE_ASYNC_15 0x08
#define A1CR_MODE_ASYNC_2 0x0c
#define A1CR_SYNCR_MODE_MASK 0x30
#define A1CR_SYNCR_MONOSYNC 0x00
#define A1CR_SYNCR_BISYNC 0x10
#define A1CR_SYNCR_SDLC 0x20
#define A1CR_SYNCR_EXTCSYNC 0x30
#define A1CR_CLKMODE_MASK 0xc0
#define A1CR_CLKMODE_x1 0x00
#define A1CR_CLKMODE_x16 0x40
#define A1CR_CLKMODE_x32 0x80
#define A1CR_CLKMODE_x64 0xc0
/* WR5: TX_CTRL_REG "TCR" */
#define TCR_TX_CRC_ENAB 0x01
#define TCR_RTS 0x02
#define TCR_USE_CRC_CCITT 0x00
#define TCR_USE_CRC_16 0x04
#define TCR_TX_ENAB 0x08
#define TCR_SEND_BREAK 0x10
#define TCR_CHSIZE_MASK 0x60
#define TCR_CHSIZE_5 0x00
#define TCR_CHSIZE_6 0x20
#define TCR_CHSIZE_7 0x40
#define TCR_CHSIZE_8 0x60
#define TCR_DTR 0x80
/* WR7': SLDC_OPTION_REG "SOR" */
#define SOR_AUTO_TX_ENAB 0x01
#define SOR_AUTO_EOM_RESET 0x02
#define SOR_AUTO_RTS_MODE 0x04
#define SOR_NRZI_DISAB_HIGH 0x08
#define SOR_ALT_DTRREQ_TIMING 0x10
#define SOR_READ_CRC_CHARS 0x20
#define SOR_EXTENDED_REG_ACCESS 0x40
/* WR9: MASTER_INT_CTRL "MIC" */
#define MIC_VEC_INCL_STAT 0x01
#define MIC_NO_VECTOR 0x02
#define MIC_DISAB_LOWER_CHAIN 0x04
#define MIC_MASTER_INT_ENAB 0x08
#define MIC_STATUS_HIGH 0x10
#define MIC_IGN_INTACK 0x20
#define MIC_NO_RESET 0x00
#define MIC_CH_A_RESET 0x40
#define MIC_CH_B_RESET 0x80
#define MIC_HARD_RESET 0xc0
/* WR10: AUX2_CTRL_REG "A2CR" */
#define A2CR_SYNC_6 0x01
#define A2CR_LOOP_MODE 0x02
#define A2CR_ABORT_ON_UNDERRUN 0x04
#define A2CR_MARK_IDLE 0x08
#define A2CR_GO_ACTIVE_ON_POLL 0x10
#define A2CR_CODING_MASK 0x60
#define A2CR_CODING_NRZ 0x00
#define A2CR_CODING_NRZI 0x20
#define A2CR_CODING_FM1 0x40
#define A2CR_CODING_FM0 0x60
#define A2CR_PRESET_CRC_1 0x80
/* WR11: CLK_CTRL_REG "CCR" */
#define CCR_TRxCOUT_MASK 0x03
#define CCR_TRxCOUT_XTAL 0x00
#define CCR_TRxCOUT_TXCLK 0x01
#define CCR_TRxCOUT_BRG 0x02
#define CCR_TRxCOUT_DPLL 0x03
#define CCR_TRxC_OUTPUT 0x04
#define CCR_TXCLK_MASK 0x18
#define CCR_TXCLK_RTxC 0x00
#define CCR_TXCLK_TRxC 0x08
#define CCR_TXCLK_BRG 0x10
#define CCR_TXCLK_DPLL 0x18
#define CCR_RXCLK_MASK 0x60
#define CCR_RXCLK_RTxC 0x00
#define CCR_RXCLK_TRxC 0x20
#define CCR_RXCLK_BRG 0x40
#define CCR_RXCLK_DPLL 0x60
#define CCR_RTxC_XTAL 0x80
/* WR14: DPLL_CTRL_REG "DCR" */
#define DCR_BRG_ENAB 0x01
#define DCR_BRG_USE_PCLK 0x02
#define DCR_DTRREQ_IS_REQ 0x04
#define DCR_AUTO_ECHO 0x08
#define DCR_LOCAL_LOOPBACK 0x10
#define DCR_DPLL_EDGE_SEARCH 0x20
#define DCR_DPLL_ERR_RESET 0x40
#define DCR_DPLL_DISAB 0x60
#define DCR_DPLL_CLK_BRG 0x80
#define DCR_DPLL_CLK_RTxC 0xa0
#define DCR_DPLL_FM 0xc0
#define DCR_DPLL_NRZI 0xe0
/* WR15: INT_CTRL_REG "ICR" */
#define ICR_OPTIONREG_SELECT 0x01
#define ICR_ENAB_BRG_ZERO_INT 0x02
#define ICR_USE_FS_FIFO 0x04
#define ICR_ENAB_DCD_INT 0x08
#define ICR_ENAB_SYNC_INT 0x10
#define ICR_ENAB_CTS_INT 0x20
#define ICR_ENAB_UNDERRUN_INT 0x40
#define ICR_ENAB_BREAK_INT 0x80
/* RR0: STATUS_REG "SR" */
#define SR_CHAR_AVAIL 0x01
#define SR_BRG_ZERO 0x02
#define SR_TX_BUF_EMPTY 0x04
#define SR_DCD 0x08
#define SR_SYNC_ABORT 0x10
#define SR_CTS 0x20
#define SR_TX_UNDERRUN 0x40
#define SR_BREAK 0x80
/* RR1: SPCOND_STATUS_REG "SCSR" */
#define SCSR_ALL_SENT 0x01
#define SCSR_RESIDUAL_MASK 0x0e
#define SCSR_PARITY_ERR 0x10
#define SCSR_RX_OVERRUN 0x20
#define SCSR_CRC_FRAME_ERR 0x40
#define SCSR_END_OF_FRAME 0x80
/* RR3: INT_PENDING_REG "IPR" */
#define IPR_B_EXTSTAT 0x01
#define IPR_B_TX 0x02
#define IPR_B_RX 0x04
#define IPR_A_EXTSTAT 0x08
#define IPR_A_TX 0x10
#define IPR_A_RX 0x20
/* RR7: FS_FIFO_HIGH_REG "FFHR" */
#define FFHR_CNT_MASK 0x3f
#define FFHR_IS_FROM_FIFO 0x40
#define FFHR_FIFO_OVERRUN 0x80
/* RR10: DPLL_STATUS_REG "DSR" */
#define DSR_ON_LOOP 0x02
#define DSR_ON_LOOP_SENDING 0x10
#define DSR_TWO_CLK_MISSING 0x40
#define DSR_ONE_CLK_MISSING 0x80
/***********************************************************************/
/* */
/* Register Access */
/* */
/***********************************************************************/
/* The SCC needs 3.5 PCLK cycles recovery time between to register
* accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
* 125 ns = 437.5 ns. This is too short for udelay().
* 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
* quite right
*/
#define scc_reg_delay() \
do { \
if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) \
__asm__ __volatile__ ( " nop; nop"); \
else if (MACH_IS_ATARI) \
__asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
} while (0)
static unsigned char scc_shadow[2][16];
/* The following functions should relax the somehow complicated
* register access of the SCC. _SCCwrite() stores all written values
* (except for WR0 and WR8) in shadow registers for later recall. This
* removes the burden of remembering written values as needed. The
* extra work of storing the value doesn't count, since a delay is
* needed after a SCC access anyway. Additionally, _SCCwrite() manages
* writes to WR0 and WR8 differently, because these can be accessed
* directly with less overhead. Another special case are WR7 and WR7'.
* _SCCwrite automatically checks what of this registers is selected
* and changes b0 of WR15 if needed.
*
* _SCCread() for standard read registers is straightforward, except
* for RR2 (split into two "virtual" registers: one for the value
* written to WR2 (from the shadow) and one for the vector including
* status from RR2, Ch. B) and RR3. The latter must be read from
* Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
* be accessed directly as before.
*
* The two inline function contain complicated switch statements. But
* I rely on regno and final_delay being constants, so gcc can reduce
* the whole stuff to just some assembler statements.
*
* _SCCwrite and _SCCread aren't intended to be used directly under
* normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
* for that purpose. They assume that a local variable 'port' is
* declared and pointing to the port's scc_struct entry. The
* variants with "_NB" appended should be used if no other SCC
* accesses follow immediately (within 0.5 usecs). They just skip the
* final delay nops.
*
* Please note that accesses to SCC registers should only take place
* when interrupts are turned off (at least if SCC interrupts are
* enabled). Otherwise, an interrupt could interfere with the
* two-stage accessing process.
*
*/
static __inline__ void _SCCwrite(
struct scc_port *port,
unsigned char *shadow,
volatile unsigned char *_scc_del,
int regno,
unsigned char val, int final_delay )
{
switch( regno ) {
case COMMAND_REG:
/* WR0 can be written directly without pointing */
*port->ctrlp = val;
break;
case SYNC_CHAR_REG:
/* For WR7, first set b0 of WR15 to 0, if needed */
if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
*port->ctrlp = 15;
shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
scc_reg_delay();
*port->ctrlp = shadow[INT_CTRL_REG];
scc_reg_delay();
}
goto normal_case;
case SDLC_OPTION_REG:
/* For WR7', first set b0 of WR15 to 1, if needed */
if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
*port->ctrlp = 15;
shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
scc_reg_delay();
*port->ctrlp = shadow[INT_CTRL_REG];
scc_reg_delay();
}
*port->ctrlp = 7;
shadow[8] = val; /* WR7' shadowed at WR8 */
scc_reg_delay();
*port->ctrlp = val;
break;
case TX_DATA_REG: /* WR8 */
/* TX_DATA_REG can be accessed directly on some h/w */
if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
{
*port->ctrlp = regno;
scc_reg_delay();
*port->ctrlp = val;
}
else
*port->datap = val;
break;
case MASTER_INT_CTRL:
*port->ctrlp = regno;
val &= 0x3f; /* bits 6..7 are the reset commands */
scc_shadow[0][regno] = val;
scc_reg_delay();
*port->ctrlp = val;
break;
case DPLL_CTRL_REG:
*port->ctrlp = regno;
val &= 0x1f; /* bits 5..7 are the DPLL commands */
shadow[regno] = val;
scc_reg_delay();
*port->ctrlp = val;
break;
case 1 ... 6:
case 10 ... 13:
case 15:
normal_case:
*port->ctrlp = regno;
shadow[regno] = val;
scc_reg_delay();
*port->ctrlp = val;
break;
default:
printk( "Bad SCC write access to WR%d\n", regno );
break;
}
if (final_delay)
scc_reg_delay();
}
static __inline__ unsigned char _SCCread(
struct scc_port *port,
unsigned char *shadow,
volatile unsigned char *_scc_del,
int regno, int final_delay )
{
unsigned char rv;
switch( regno ) {
/* --- real read registers --- */
case STATUS_REG:
rv = *port->ctrlp;
break;
case INT_PENDING_REG:
/* RR3: read only from Channel A! */
port = port->port_a;
goto normal_case;
case RX_DATA_REG:
/* RR8 can be accessed directly on some h/w */
if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
{
*port->ctrlp = 8;
scc_reg_delay();
rv = *port->ctrlp;
}
else
rv = *port->datap;
break;
case CURR_VECTOR_REG:
/* RR2 (vector including status) from Ch. B */
port = port->port_b;
goto normal_case;
/* --- reading write registers: access the shadow --- */
case 1 ... 7:
case 10 ... 15:
return shadow[regno]; /* no final delay! */
/* WR7' is special, because it is shadowed at the place of WR8 */
case SDLC_OPTION_REG:
return shadow[8]; /* no final delay! */
/* WR9 is special too, because it is common for both channels */
case MASTER_INT_CTRL:
return scc_shadow[0][9]; /* no final delay! */
default:
printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
regno & ~16 );
break;
case SPCOND_STATUS_REG:
case FS_FIFO_LOW_REG:
case FS_FIFO_HIGH_REG:
case DPLL_STATUS_REG:
normal_case:
*port->ctrlp = regno & 0x0f;
scc_reg_delay();
rv = *port->ctrlp;
break;
}
if (final_delay)
scc_reg_delay();
return rv;
}
#define SCC_ACCESS_INIT(port) \
unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
#define SCCwrite(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
#define SCCwrite_NB(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
#define SCCread(reg) _SCCread(port,_scc_shadow,scc_del,(reg),1)
#define SCCread_NB(reg) _SCCread(port,_scc_shadow,scc_del,(reg),0)
#define SCCmod(reg,and,or) SCCwrite((reg),(SCCread(reg)&(and))|(or))
#endif /* _SCC_H */

14
drivers/hv/Kconfig Normal file
View File

@ -0,0 +1,14 @@
config HYPERV
tristate "Microsoft Hyper-V client drivers"
depends on X86 && ACPI && PCI
help
Select this option to run Linux as a Hyper-V client operating
system.
config HYPERV_UTILS
tristate "Microsoft Hyper-V Utilities driver"
depends on HYPERV && CONNECTOR && NLS
help
Select this option to enable the Hyper-V Utilities.

7
drivers/hv/Makefile Normal file
View File

@ -0,0 +1,7 @@
obj-$(CONFIG_HYPERV) += hv_vmbus.o
obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o
hv_vmbus-y := vmbus_drv.o \
hv.o connection.o channel.o \
channel_mgmt.o ring_buffer.o
hv_utils-y := hv_util.o hv_kvp.o

View File

@ -26,8 +26,8 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/hyperv.h>
#include "hyperv.h"
#include "hyperv_vmbus.h"
#define NUM_PAGES_SPANNED(addr, len) \
@ -76,15 +76,14 @@ void vmbus_get_debug_info(struct vmbus_channel *channel,
struct hv_monitor_page *monitorpage;
u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
/* u32 monitorBit = 1 << monitorOffset; */
debuginfo->relid = channel->offermsg.child_relid;
debuginfo->state = channel->state;
memcpy(&debuginfo->interfacetype,
&channel->offermsg.offer.if_type, sizeof(struct hv_guid));
&channel->offermsg.offer.if_type, sizeof(uuid_le));
memcpy(&debuginfo->interface_instance,
&channel->offermsg.offer.if_instance,
sizeof(struct hv_guid));
sizeof(uuid_le));
monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
@ -119,8 +118,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
void (*onchannelcallback)(void *context), void *context)
{
struct vmbus_channel_open_channel *openMsg;
struct vmbus_channel_msginfo *openInfo = NULL;
struct vmbus_channel_open_channel *open_msg;
struct vmbus_channel_msginfo *open_info = NULL;
void *in, *out;
unsigned long flags;
int ret, t, err = 0;
@ -173,24 +172,24 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
}
/* Create and init the channel open message */
openInfo = kmalloc(sizeof(*openInfo) +
open_info = kmalloc(sizeof(*open_info) +
sizeof(struct vmbus_channel_open_channel),
GFP_KERNEL);
if (!openInfo) {
if (!open_info) {
err = -ENOMEM;
goto errorout;
}
init_completion(&openInfo->waitevent);
init_completion(&open_info->waitevent);
openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
openMsg->openid = newchannel->offermsg.child_relid;
openMsg->child_relid = newchannel->offermsg.child_relid;
openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
open_msg->openid = newchannel->offermsg.child_relid;
open_msg->child_relid = newchannel->offermsg.child_relid;
open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
PAGE_SHIFT;
openMsg->server_contextarea_gpadlhandle = 0;
open_msg->server_contextarea_gpadlhandle = 0;
if (userdatalen > MAX_USER_DEFINED_BYTES) {
err = -EINVAL;
@ -198,35 +197,35 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
}
if (userdatalen)
memcpy(openMsg->userdata, userdata, userdatalen);
memcpy(open_msg->userdata, userdata, userdatalen);
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_add_tail(&openInfo->msglistentry,
list_add_tail(&open_info->msglistentry,
&vmbus_connection.chn_msg_list);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
ret = vmbus_post_msg(openMsg,
ret = vmbus_post_msg(open_msg,
sizeof(struct vmbus_channel_open_channel));
if (ret != 0)
goto cleanup;
t = wait_for_completion_timeout(&openInfo->waitevent, 5*HZ);
t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
if (t == 0) {
err = -ETIMEDOUT;
goto errorout;
}
if (openInfo->response.open_result.status)
err = openInfo->response.open_result.status;
if (open_info->response.open_result.status)
err = open_info->response.open_result.status;
cleanup:
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_del(&openInfo->msglistentry);
list_del(&open_info->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
kfree(openInfo);
kfree(open_info);
return err;
errorout:
@ -234,56 +233,11 @@ errorout:
hv_ringbuffer_cleanup(&newchannel->inbound);
free_pages((unsigned long)out,
get_order(send_ringbuffer_size + recv_ringbuffer_size));
kfree(openInfo);
kfree(open_info);
return err;
}
EXPORT_SYMBOL_GPL(vmbus_open);
/*
* dump_gpadl_body - Dump the gpadl body message to the console for
* debugging purposes.
*/
static void dump_gpadl_body(struct vmbus_channel_gpadl_body *gpadl, u32 len)
{
int i;
int pfncount;
pfncount = (len - sizeof(struct vmbus_channel_gpadl_body)) /
sizeof(u64);
DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", len, pfncount);
for (i = 0; i < pfncount; i++)
DPRINT_DBG(VMBUS, "gpadl body - %d) pfn %llu",
i, gpadl->pfn[i]);
}
/*
* dump_gpadl_header - Dump the gpadl header message to the console for
* debugging purposes.
*/
static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl)
{
int i, j;
int pagecount;
DPRINT_DBG(VMBUS,
"gpadl header - relid %d, range count %d, range buflen %d",
gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen);
for (i = 0; i < gpadl->rangecount; i++) {
pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT;
pagecount = (pagecount > 26) ? 26 : pagecount;
DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
"page count %d", i, gpadl->range[i].byte_count,
gpadl->range[i].byte_offset, pagecount);
for (j = 0; j < pagecount; j++)
DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
gpadl->range[i].pfn_array[j]);
}
}
/*
* create_gpadl_header - Creates a gpadl for the specified buffer
*/
@ -437,7 +391,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
{
struct vmbus_channel_gpadl_header *gpadlmsg;
struct vmbus_channel_gpadl_body *gpadl_body;
/* struct vmbus_channel_gpadl_created *gpadlCreated; */
struct vmbus_channel_msginfo *msginfo = NULL;
struct vmbus_channel_msginfo *submsginfo;
u32 msgcount;
@ -461,7 +414,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
gpadlmsg->child_relid = channel->offermsg.child_relid;
gpadlmsg->gpadl = next_gpadl_handle;
dump_gpadl_header(gpadlmsg);
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_add_tail(&msginfo->msglistentry,
@ -485,8 +437,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
CHANNELMSG_GPADL_BODY;
gpadl_body->gpadl = next_gpadl_handle;
dump_gpadl_body(gpadl_body, submsginfo->msgsize -
sizeof(*submsginfo));
ret = vmbus_post_msg(gpadl_body,
submsginfo->msgsize -
sizeof(*submsginfo));
@ -522,8 +472,6 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
unsigned long flags;
int ret, t;
/* ASSERT(gpadl_handle != 0); */
info = kmalloc(sizeof(*info) +
sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
if (!info)
@ -565,9 +513,12 @@ void vmbus_close(struct vmbus_channel *channel)
{
struct vmbus_channel_close_channel *msg;
int ret;
unsigned long flags;
/* Stop callback and cancel the timer asap */
spin_lock_irqsave(&channel->inbound_lock, flags);
channel->onchannel_callback = NULL;
spin_unlock_irqrestore(&channel->inbound_lock, flags);
/* Send a closing message */
@ -787,19 +738,15 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
u32 packetlen;
u32 userlen;
int ret;
unsigned long flags;
*buffer_actual_len = 0;
*requestid = 0;
spin_lock_irqsave(&channel->inbound_lock, flags);
ret = hv_ringbuffer_peek(&channel->inbound, &desc,
sizeof(struct vmpacket_descriptor));
if (ret != 0) {
spin_unlock_irqrestore(&channel->inbound_lock, flags);
if (ret != 0)
return 0;
}
packetlen = desc.len8 << 3;
userlen = packetlen - (desc.offset8 << 3);
@ -807,7 +754,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
*buffer_actual_len = userlen;
if (userlen > bufferlen) {
spin_unlock_irqrestore(&channel->inbound_lock, flags);
pr_err("Buffer too small - got %d needs %d\n",
bufferlen, userlen);
@ -820,7 +766,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
(desc.offset8 << 3));
spin_unlock_irqrestore(&channel->inbound_lock, flags);
return 0;
}
@ -837,19 +782,15 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
u32 packetlen;
u32 userlen;
int ret;
unsigned long flags;
*buffer_actual_len = 0;
*requestid = 0;
spin_lock_irqsave(&channel->inbound_lock, flags);
ret = hv_ringbuffer_peek(&channel->inbound, &desc,
sizeof(struct vmpacket_descriptor));
if (ret != 0) {
spin_unlock_irqrestore(&channel->inbound_lock, flags);
if (ret != 0)
return 0;
}
packetlen = desc.len8 << 3;
@ -858,12 +799,10 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
*buffer_actual_len = packetlen;
if (packetlen > bufferlen) {
spin_unlock_irqrestore(&channel->inbound_lock, flags);
pr_err("Buffer too small - needed %d bytes but "
"got space for only %d bytes\n",
packetlen, bufferlen);
return -2;
return -ENOBUFS;
}
*requestid = desc.trans_id;
@ -871,7 +810,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
/* Copy over the entire packet to the user buffer */
ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
spin_unlock_irqrestore(&channel->inbound_lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);

View File

@ -28,8 +28,8 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/completion.h>
#include <linux/hyperv.h>
#include "hyperv.h"
#include "hyperv_vmbus.h"
struct vmbus_channel_message_table_entry {
@ -40,12 +40,12 @@ struct vmbus_channel_message_table_entry {
#define MAX_MSG_TYPES 4
#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
static const struct hv_guid
static const uuid_le
supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
/* Storage - SCSI */
{
.data = {
.b = {
0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
}
@ -54,7 +54,7 @@ static const struct hv_guid
/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
/* Network */
{
.data = {
.b = {
0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
}
@ -63,7 +63,7 @@ static const struct hv_guid
/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
/* Input */
{
.data = {
.b = {
0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
}
@ -72,7 +72,7 @@ static const struct hv_guid
/* {32412632-86cb-44a2-9b5c-50d1417354f5} */
/* IDE */
{
.data = {
.b = {
0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
}
@ -80,7 +80,7 @@ static const struct hv_guid
/* 0E0B6031-5213-4934-818B-38D90CED39DB */
/* Shutdown */
{
.data = {
.b = {
0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
}
@ -88,7 +88,7 @@ static const struct hv_guid
/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
/* TimeSync */
{
.data = {
.b = {
0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
}
@ -96,7 +96,7 @@ static const struct hv_guid
/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
/* Heartbeat */
{
.data = {
.b = {
0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
}
@ -104,7 +104,7 @@ static const struct hv_guid
/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
/* KVP */
{
.data = {
.b = {
0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
}
@ -114,7 +114,7 @@ static const struct hv_guid
/**
* prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
* vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
* @icmsghdrp: Pointer to msg header structure
* @icmsg_negotiate: Pointer to negotiate message structure
* @buf: Raw buffer channel data
@ -128,9 +128,8 @@ static const struct hv_guid
*
* Mainly used by Hyper-V drivers.
*/
void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
struct icmsg_negotiate *negop,
u8 *buf)
void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
struct icmsg_negotiate *negop, u8 *buf)
{
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
icmsghdrp->icmsgsize = 0x10;
@ -156,119 +155,7 @@ void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
negop->icmsg_vercnt = 1;
}
}
EXPORT_SYMBOL(prep_negotiate_resp);
/**
* chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK
* Hyper-V requests
* @context: Pointer to argument structure.
*
* Set up the default handler for non device driver specific requests
* from Hyper-V. This stub responds to the default negotiate messages
* that come in for every non IDE/SCSI/Network request.
* This behavior is normally overwritten in the hv_utils driver. That
* driver handles requests like graceful shutdown, heartbeats etc.
*
* Mainly used by Hyper-V drivers.
*/
void chn_cb_negotiate(void *context)
{
struct vmbus_channel *channel = context;
u8 *buf;
u32 buflen, recvlen;
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct icmsg_negotiate *negop = NULL;
if (channel->util_index >= 0) {
/*
* This is a properly initialized util channel.
* Route this callback appropriately and setup state
* so that we don't need to reroute again.
*/
if (hv_cb_utils[channel->util_index].callback != NULL) {
/*
* The util driver has established a handler for
* this service; do the magic.
*/
channel->onchannel_callback =
hv_cb_utils[channel->util_index].callback;
(hv_cb_utils[channel->util_index].callback)(channel);
return;
}
}
buflen = PAGE_SIZE;
buf = kmalloc(buflen, GFP_ATOMIC);
vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
if (recvlen > 0) {
icmsghdrp = (struct icmsg_hdr *)&buf[
sizeof(struct vmbuspipe_hdr)];
prep_negotiate_resp(icmsghdrp, negop, buf);
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE;
vmbus_sendpacket(channel, buf,
recvlen, requestid,
VM_PKT_DATA_INBAND, 0);
}
kfree(buf);
}
EXPORT_SYMBOL(chn_cb_negotiate);
/*
* Function table used for message responses for non IDE/SCSI/Network type
* messages. (Such as KVP/Shutdown etc)
*/
struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
/* 0E0B6031-5213-4934-818B-38D90CED39DB */
/* Shutdown */
{
.msg_type = HV_SHUTDOWN_MSG,
.data = {
0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
},
.log_msg = "Shutdown channel functionality initialized"
},
/* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
/* TimeSync */
{
.msg_type = HV_TIMESYNC_MSG,
.data = {
0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
},
.log_msg = "Timesync channel functionality initialized"
},
/* {57164f39-9115-4e78-ab55-382f3bd5422d} */
/* Heartbeat */
{
.msg_type = HV_HEARTBEAT_MSG,
.data = {
0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
},
.log_msg = "Heartbeat channel functionality initialized"
},
/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
/* KVP */
{
.data = {
0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
},
.log_msg = "KVP channel functionality initialized"
},
};
EXPORT_SYMBOL(hv_cb_utils);
EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
/*
* alloc_channel - Allocate and initialize a vmbus channel object
@ -309,7 +196,7 @@ static void release_channel(struct work_struct *work)
/*
* free_channel - Release the resources used by the vmbus channel object
*/
void free_channel(struct vmbus_channel *channel)
static void free_channel(struct vmbus_channel *channel)
{
/*
@ -333,7 +220,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
struct vmbus_channel,
work);
vmbus_child_device_unregister(channel->device_obj);
vmbus_device_unregister(channel->device_obj);
}
/*
@ -348,7 +235,6 @@ static void vmbus_process_offer(struct work_struct *work)
struct vmbus_channel *channel;
bool fnew = true;
int ret;
int cnt;
unsigned long flags;
/* The next possible work is rescind handling */
@ -358,12 +244,10 @@ static void vmbus_process_offer(struct work_struct *work)
spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
if (!memcmp(&channel->offermsg.offer.if_type,
&newchannel->offermsg.offer.if_type,
sizeof(struct hv_guid)) &&
!memcmp(&channel->offermsg.offer.if_instance,
&newchannel->offermsg.offer.if_instance,
sizeof(struct hv_guid))) {
if (!uuid_le_cmp(channel->offermsg.offer.if_type,
newchannel->offermsg.offer.if_type) &&
!uuid_le_cmp(channel->offermsg.offer.if_instance,
newchannel->offermsg.offer.if_instance)) {
fnew = false;
break;
}
@ -385,7 +269,7 @@ static void vmbus_process_offer(struct work_struct *work)
* We need to set the DeviceObject field before calling
* vmbus_child_dev_add()
*/
newchannel->device_obj = vmbus_child_device_create(
newchannel->device_obj = vmbus_device_create(
&newchannel->offermsg.offer.if_type,
&newchannel->offermsg.offer.if_instance,
newchannel);
@ -395,7 +279,7 @@ static void vmbus_process_offer(struct work_struct *work)
* binding which eventually invokes the device driver's AddDevice()
* method.
*/
ret = vmbus_child_device_register(newchannel->device_obj);
ret = vmbus_device_register(newchannel->device_obj);
if (ret != 0) {
pr_err("unable to add child device object (relid %d)\n",
newchannel->offermsg.child_relid);
@ -412,48 +296,26 @@ static void vmbus_process_offer(struct work_struct *work)
* can cleanup properly
*/
newchannel->state = CHANNEL_OPEN_STATE;
newchannel->util_index = -1; /* Invalid index */
/* Open IC channels */
for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
if (memcmp(&newchannel->offermsg.offer.if_type,
&hv_cb_utils[cnt].data,
sizeof(struct hv_guid)) == 0 &&
vmbus_open(newchannel, 2 * PAGE_SIZE,
2 * PAGE_SIZE, NULL, 0,
chn_cb_negotiate,
newchannel) == 0) {
hv_cb_utils[cnt].channel = newchannel;
newchannel->util_index = cnt;
pr_info("%s\n", hv_cb_utils[cnt].log_msg);
}
}
}
}
/*
* vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
*
* We ignore all offers except network and storage offers. For each network and
* storage offers, we create a channel object and queue a work item to the
* channel object to process the offer synchronously
*/
static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
{
struct vmbus_channel_offer_channel *offer;
struct vmbus_channel *newchannel;
struct hv_guid *guidtype;
struct hv_guid *guidinstance;
uuid_le *guidtype;
uuid_le *guidinstance;
int i;
int fsupported = 0;
offer = (struct vmbus_channel_offer_channel *)hdr;
for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
if (memcmp(&offer->offer.if_type,
&supported_device_classes[i],
sizeof(struct hv_guid)) == 0) {
if (!uuid_le_cmp(offer->offer.if_type,
supported_device_classes[i])) {
fsupported = 1;
break;
}

View File

@ -25,11 +25,12 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include "hyperv.h"
#include <linux/hyperv.h>
#include <asm/hyperv.h>
#include "hyperv_vmbus.h"
@ -49,10 +50,6 @@ int vmbus_connect(void)
struct vmbus_channel_initiate_contact *msg;
unsigned long flags;
/* Make sure we are not connecting or connected */
if (vmbus_connection.conn_state != DISCONNECTED)
return -EISCONN;
/* Initialize the vmbus connection */
vmbus_connection.conn_state = CONNECTING;
vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
@ -214,8 +211,7 @@ struct vmbus_channel *relid2channel(u32 relid)
static void process_chn_event(u32 relid)
{
struct vmbus_channel *channel;
/* ASSERT(relId > 0); */
unsigned long flags;
/*
* Find the channel based on this relid and invokes the
@ -223,11 +219,27 @@ static void process_chn_event(u32 relid)
*/
channel = relid2channel(relid);
if (channel) {
channel->onchannel_callback(channel->channel_callback_context);
} else {
if (!channel) {
pr_err("channel not found for relid - %u\n", relid);
return;
}
/*
* A channel once created is persistent even when there
* is no driver handling the device. An unloading driver
* sets the onchannel_callback to NULL under the
* protection of the channel inbound_lock. Thus, checking
* and invoking the driver specific callback takes care of
* orderly unloading of the driver.
*/
spin_lock_irqsave(&channel->inbound_lock, flags);
if (channel->onchannel_callback != NULL)
channel->onchannel_callback(channel->channel_callback_context);
else
pr_err("no channel callback for relid - %u\n", relid);
spin_unlock_irqrestore(&channel->inbound_lock, flags);
}
/*
@ -248,16 +260,17 @@ void vmbus_on_event(unsigned long data)
if (!recv_int_page[dword])
continue;
for (bit = 0; bit < 32; bit++) {
if (sync_test_and_clear_bit(bit, (unsigned long *)&recv_int_page[dword])) {
if (sync_test_and_clear_bit(bit,
(unsigned long *)&recv_int_page[dword])) {
relid = (dword << 5) + bit;
if (relid == 0) {
if (relid == 0)
/*
* Special case - vmbus
* channel protocol msg
*/
continue;
}
process_chn_event(relid);
}
}
@ -270,10 +283,25 @@ void vmbus_on_event(unsigned long data)
int vmbus_post_msg(void *buffer, size_t buflen)
{
union hv_connection_id conn_id;
int ret = 0;
int retries = 0;
conn_id.asu32 = 0;
conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
return hv_post_message(conn_id, 1, buffer, buflen);
/*
* hv_post_message() can have transient failures because of
* insufficient resources. Retry the operation a couple of
* times before giving up.
*/
while (retries < 3) {
ret = hv_post_message(conn_id, 1, buffer, buflen);
if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
return ret;
retries++;
msleep(100);
}
return ret;
}
/*

View File

@ -25,8 +25,8 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include "hyperv.h"
#include <linux/hyperv.h>
#include <asm/hyperv.h>
#include "hyperv_vmbus.h"
/* The one and only */
@ -111,7 +111,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)
u64 hv_status = 0;
u64 input_address = (input) ? virt_to_phys(input) : 0;
u64 output_address = (output) ? virt_to_phys(output) : 0;
volatile void *hypercall_page = hv_context.hypercall_page;
void *hypercall_page = hv_context.hypercall_page;
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
@ -132,7 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output)
u64 output_address = (output) ? virt_to_phys(output) : 0;
u32 output_address_hi = output_address >> 32;
u32 output_address_lo = output_address & 0xFFFFFFFF;
volatile void *hypercall_page = hv_context.hypercall_page;
void *hypercall_page = hv_context.hypercall_page;
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
"=a"(hv_status_lo) : "d" (control_hi),
@ -151,7 +151,6 @@ static u64 do_hypercall(u64 control, void *input, void *output)
*/
int hv_init(void)
{
int ret = 0;
int max_leaf;
union hv_x64_msr_hypercall_contents hypercall_msr;
void *virtaddr = NULL;
@ -164,11 +163,7 @@ int hv_init(void)
goto cleanup;
max_leaf = query_hypervisor_info();
/* HvQueryHypervisorFeatures(maxLeaf); */
/*
* We only support running on top of Hyper-V
*/
rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
if (hv_context.guestid != 0)
@ -181,10 +176,6 @@ int hv_init(void)
/* See if the hypercall page is already set */
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
/*
* Allocate the hypercall page memory
* virtaddr = osd_page_alloc(1);
*/
virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
if (!virtaddr)
@ -222,7 +213,7 @@ int hv_init(void)
hv_context.signal_event_param->flag_number = 0;
hv_context.signal_event_param->rsvdz = 0;
return ret;
return 0;
cleanup:
if (virtaddr) {
@ -233,8 +224,8 @@ cleanup:
vfree(virtaddr);
}
ret = -1;
return ret;
return -ENOTSUPP;
}
/*
@ -378,7 +369,7 @@ void hv_synic_init(void *irqarg)
shared_sint.as_uint64 = 0;
shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */
shared_sint.masked = false;
shared_sint.auto_eoi = true;
shared_sint.auto_eoi = false;
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);

View File

@ -26,8 +26,8 @@
#include <linux/nls.h>
#include <linux/connector.h>
#include <linux/workqueue.h>
#include <linux/hyperv.h>
#include "hyperv.h"
#include "hv_kvp.h"
@ -44,21 +44,24 @@
static struct {
bool active; /* transaction status - active or not */
int recv_len; /* number of bytes received. */
int index; /* current index */
struct vmbus_channel *recv_channel; /* chn we got the request */
u64 recv_req_id; /* request ID. */
} kvp_transaction;
static int kvp_send_key(int index);
static void kvp_send_key(struct work_struct *dummy);
#define TIMEOUT_FIRED 1
static void kvp_respond_to_host(char *key, char *value, int error);
static void kvp_work_func(struct work_struct *dummy);
static void kvp_register(void);
static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
static const char kvp_name[] = "kvp_kernel_module";
static int timeout_fired;
static u8 *recv_buffer;
/*
* Register the kernel component with the user-level daemon.
@ -90,8 +93,7 @@ kvp_work_func(struct work_struct *dummy)
* If the timer fires, the user-mode component has not responded;
* process the pending transaction.
*/
kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired);
timeout_fired = 1;
kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
}
/*
@ -121,10 +123,11 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
}
}
static int
kvp_send_key(int index)
static void
kvp_send_key(struct work_struct *dummy)
{
struct cn_msg *msg;
int index = kvp_transaction.index;
msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
@ -136,9 +139,8 @@ kvp_send_key(int index)
msg->len = sizeof(struct hv_ku_msg);
cn_netlink_send(msg, 0, GFP_ATOMIC);
kfree(msg);
return 0;
}
return 1;
return;
}
/*
@ -177,6 +179,15 @@ kvp_respond_to_host(char *key, char *value, int error)
channel = kvp_transaction.recv_channel;
req_id = kvp_transaction.recv_req_id;
kvp_transaction.active = false;
if (channel->onchannel_callback == NULL)
/*
* We have raced with util driver being unloaded;
* silently return.
*/
return;
icmsghdrp = (struct icmsg_hdr *)
&recv_buffer[sizeof(struct vmbuspipe_hdr)];
kvp_msg = (struct hv_kvp_msg *)
@ -217,7 +228,6 @@ response_done:
vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
VM_PKT_DATA_INBAND, 0);
kvp_transaction.active = false;
}
/*
@ -243,10 +253,6 @@ void hv_kvp_onchannelcallback(void *context)
struct icmsg_negotiate *negop = NULL;
if (kvp_transaction.active)
return;
vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
if (recvlen > 0) {
@ -254,7 +260,7 @@ void hv_kvp_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
} else {
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) +
@ -282,6 +288,7 @@ void hv_kvp_onchannelcallback(void *context)
kvp_transaction.recv_channel = channel;
kvp_transaction.recv_req_id = requestid;
kvp_transaction.active = true;
kvp_transaction.index = kvp_data->index;
/*
* Get the information from the
@ -292,8 +299,8 @@ void hv_kvp_onchannelcallback(void *context)
* Set a timeout to deal with
* user-mode not responding.
*/
kvp_send_key(kvp_data->index);
schedule_delayed_work(&kvp_work, 100);
schedule_work(&kvp_sendkey_work);
schedule_delayed_work(&kvp_work, 5*HZ);
return;
@ -312,16 +319,14 @@ callback_done:
}
int
hv_kvp_init(void)
hv_kvp_init(struct hv_util_service *srv)
{
int err;
err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
if (err)
return err;
recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!recv_buffer)
return -ENOMEM;
recv_buffer = srv->recv_buffer;
return 0;
}
@ -330,5 +335,5 @@ void hv_kvp_deinit(void)
{
cn_del_callback(&kvp_id);
cancel_delayed_work_sync(&kvp_work);
kfree(recv_buffer);
cancel_work_sync(&kvp_sendkey_work);
}

View File

@ -175,7 +175,7 @@ struct hv_kvp_msg {
struct hv_kvp_msg_enumerate kvp_data;
};
int hv_kvp_init(void);
int hv_kvp_init(struct hv_util_service *);
void hv_kvp_deinit(void);
void hv_kvp_onchannelcallback(void *);

View File

@ -26,15 +26,31 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/reboot.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/hyperv.h>
#include "hyperv.h"
#include "hv_kvp.h"
static u8 *shut_txf_buf;
static u8 *time_txf_buf;
static u8 *hbeat_txf_buf;
static void shutdown_onchannelcallback(void *context);
static struct hv_util_service util_shutdown = {
.util_cb = shutdown_onchannelcallback,
};
static void timesync_onchannelcallback(void *context);
static struct hv_util_service util_timesynch = {
.util_cb = timesync_onchannelcallback,
};
static void heartbeat_onchannelcallback(void *context);
static struct hv_util_service util_heartbeat = {
.util_cb = heartbeat_onchannelcallback,
};
static struct hv_util_service util_kvp = {
.util_cb = hv_kvp_onchannelcallback,
.util_init = hv_kvp_init,
.util_deinit = hv_kvp_deinit,
};
static void shutdown_onchannelcallback(void *context)
{
@ -42,6 +58,7 @@ static void shutdown_onchannelcallback(void *context)
u32 recvlen;
u64 requestid;
u8 execute_shutdown = false;
u8 *shut_txf_buf = util_shutdown.recv_buffer;
struct shutdown_msg_data *shutdown_msg;
@ -56,7 +73,7 @@ static void shutdown_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
} else {
shutdown_msg =
(struct shutdown_msg_data *)&shut_txf_buf[
@ -91,7 +108,7 @@ static void shutdown_onchannelcallback(void *context)
}
if (execute_shutdown == true)
orderly_poweroff(false);
orderly_poweroff(true);
}
/*
@ -108,6 +125,24 @@ static inline void do_adj_guesttime(u64 hosttime)
do_settimeofday(&host_ts);
}
/*
* Set the host time in a process context.
*/
struct adj_time_work {
struct work_struct work;
u64 host_time;
};
static void hv_set_host_time(struct work_struct *work)
{
struct adj_time_work *wrk;
wrk = container_of(work, struct adj_time_work, work);
do_adj_guesttime(wrk->host_time);
kfree(wrk);
}
/*
* Synchronize time with host after reboot, restore, etc.
*
@ -121,17 +156,26 @@ static inline void do_adj_guesttime(u64 hosttime)
*/
static inline void adj_guesttime(u64 hosttime, u8 flags)
{
struct adj_time_work *wrk;
static s32 scnt = 50;
wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC);
if (wrk == NULL)
return;
wrk->host_time = hosttime;
if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
do_adj_guesttime(hosttime);
INIT_WORK(&wrk->work, hv_set_host_time);
schedule_work(&wrk->work);
return;
}
if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
scnt--;
do_adj_guesttime(hosttime);
}
INIT_WORK(&wrk->work, hv_set_host_time);
schedule_work(&wrk->work);
} else
kfree(wrk);
}
/*
@ -144,6 +188,7 @@ static void timesync_onchannelcallback(void *context)
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct ictimesync_data *timedatap;
u8 *time_txf_buf = util_timesynch.recv_buffer;
vmbus_recvpacket(channel, time_txf_buf,
PAGE_SIZE, &recvlen, &requestid);
@ -153,7 +198,7 @@ static void timesync_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
} else {
timedatap = (struct ictimesync_data *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr) +
@ -182,6 +227,7 @@ static void heartbeat_onchannelcallback(void *context)
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct heartbeat_msg_data *heartbeat_msg;
u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
vmbus_recvpacket(channel, hbeat_txf_buf,
PAGE_SIZE, &recvlen, &requestid);
@ -191,7 +237,7 @@ static void heartbeat_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
} else {
heartbeat_msg =
(struct heartbeat_msg_data *)&hbeat_txf_buf[
@ -210,92 +256,94 @@ static void heartbeat_onchannelcallback(void *context)
}
}
static const struct pci_device_id __initconst
hv_utils_pci_table[] __maybe_unused = {
{ PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
static const struct dmi_system_id __initconst
hv_utils_dmi_table[] __maybe_unused = {
static int util_probe(struct hv_device *dev,
const struct hv_vmbus_device_id *dev_id)
{
.ident = "Hyper-V",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
},
},
struct hv_util_service *srv =
(struct hv_util_service *)dev_id->driver_data;
int ret;
srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!srv->recv_buffer)
return -ENOMEM;
if (srv->util_init) {
ret = srv->util_init(srv);
if (ret) {
ret = -ENODEV;
goto error1;
}
}
ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
srv->util_cb, dev->channel);
if (ret)
goto error;
hv_set_drvdata(dev, srv);
return 0;
error:
if (srv->util_deinit)
srv->util_deinit();
error1:
kfree(srv->recv_buffer);
return ret;
}
static int util_remove(struct hv_device *dev)
{
struct hv_util_service *srv = hv_get_drvdata(dev);
vmbus_close(dev->channel);
if (srv->util_deinit)
srv->util_deinit();
kfree(srv->recv_buffer);
return 0;
}
static const struct hv_vmbus_device_id id_table[] = {
/* Shutdown guid */
{ VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB)
.driver_data = (unsigned long)&util_shutdown },
/* Time synch guid */
{ VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf)
.driver_data = (unsigned long)&util_timesynch },
/* Heartbeat guid */
{ VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d)
.driver_data = (unsigned long)&util_heartbeat },
/* KVP guid */
{ VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6)
.driver_data = (unsigned long)&util_kvp },
{ },
};
MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
MODULE_DEVICE_TABLE(vmbus, id_table);
/* The one and only one */
static struct hv_driver util_drv = {
.name = "hv_util",
.id_table = id_table,
.probe = util_probe,
.remove = util_remove,
};
static int __init init_hyperv_utils(void)
{
pr_info("Registering HyperV Utility Driver\n");
if (hv_kvp_init())
return -ENODEV;
if (!dmi_check_system(hv_utils_dmi_table))
return -ENODEV;
shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
pr_info("Unable to allocate memory for receive buffer\n");
kfree(shut_txf_buf);
kfree(time_txf_buf);
kfree(hbeat_txf_buf);
return -ENOMEM;
}
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
hv_cb_utils[HV_TIMESYNC_MSG].callback = &timesync_onchannelcallback;
hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback;
return 0;
return vmbus_driver_register(&util_drv);
}
static void exit_hyperv_utils(void)
{
pr_info("De-Registered HyperV Utility Driver\n");
if (hv_cb_utils[HV_SHUTDOWN_MSG].channel != NULL)
hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
&chn_cb_negotiate;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = NULL;
if (hv_cb_utils[HV_TIMESYNC_MSG].channel != NULL)
hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
&chn_cb_negotiate;
hv_cb_utils[HV_TIMESYNC_MSG].callback = NULL;
if (hv_cb_utils[HV_HEARTBEAT_MSG].channel != NULL)
hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
&chn_cb_negotiate;
hv_cb_utils[HV_HEARTBEAT_MSG].callback = NULL;
if (hv_cb_utils[HV_KVP_MSG].channel != NULL)
hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
&chn_cb_negotiate;
hv_cb_utils[HV_KVP_MSG].callback = NULL;
hv_kvp_deinit();
kfree(shut_txf_buf);
kfree(time_txf_buf);
kfree(hbeat_txf_buf);
vmbus_driver_unregister(&util_drv);
}
module_init(init_hyperv_utils);

View File

@ -28,8 +28,7 @@
#include <linux/list.h>
#include <asm/sync_bitops.h>
#include <linux/atomic.h>
#include "hyperv.h"
#include <linux/hyperv.h>
/*
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
@ -451,8 +450,8 @@ enum {
/* #define VMBUS_PORT_ID 11 */
/* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */
static const struct hv_guid VMBUS_SERVICE_ID = {
.data = {
static const uuid_le VMBUS_SERVICE_ID = {
.b = {
0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c,
0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4
},
@ -530,8 +529,6 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info);
void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix);
void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
@ -601,12 +598,12 @@ extern struct vmbus_connection vmbus_connection;
/* General vmbus interface */
struct hv_device *vmbus_child_device_create(struct hv_guid *type,
struct hv_guid *instance,
struct hv_device *vmbus_device_create(uuid_le *type,
uuid_le *instance,
struct vmbus_channel *channel);
int vmbus_child_device_register(struct hv_device *child_device_obj);
void vmbus_child_device_unregister(struct hv_device *device_obj);
int vmbus_device_register(struct hv_device *child_device_obj);
void vmbus_device_unregister(struct hv_device *device_obj);
/* static void */
/* VmbusChildDeviceDestroy( */

View File

@ -25,8 +25,8 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/hyperv.h>
#include "hyperv.h"
#include "hyperv_vmbus.h"
@ -34,7 +34,8 @@
/* Amount of space to write to */
#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
#define BYTES_AVAIL_TO_WRITE(r, w, z) \
((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
/*
@ -171,37 +172,6 @@ hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info)
return (u64)ring_info->ring_buffer->write_index << 32;
}
/*
*
* hv_dump_ring_info()
*
* Dump out to console the ring buffer info
*
*/
void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix)
{
u32 bytes_avail_towrite;
u32 bytes_avail_toread;
hv_get_ringbuffer_availbytes(ring_info,
&bytes_avail_toread,
&bytes_avail_towrite);
DPRINT(VMBUS,
DEBUG_RING_LVL,
"%s <<ringinfo %p buffer %p avail write %u "
"avail read %u read idx %u write idx %u>>",
prefix,
ring_info,
ring_info->ring_buffer->buffer,
bytes_avail_towrite,
bytes_avail_toread,
ring_info->ring_buffer->read_index,
ring_info->ring_buffer->write_index);
}
/*
*
* hv_copyfrom_ringbuffer()
@ -390,7 +360,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
/* is empty since the read index == write index */
if (bytes_avail_towrite <= totalbytes_towrite) {
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
return -1;
return -EAGAIN;
}
/* Write to the ring buffer */
@ -450,7 +420,7 @@ int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info,
spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
return -1;
return -EAGAIN;
}
/* Convert to byte offset */
@ -496,7 +466,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
if (bytes_avail_toread < buflen) {
spin_unlock_irqrestore(&inring_info->ring_lock, flags);
return -1;
return -EAGAIN;
}
next_read_location =

View File

@ -28,14 +28,12 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <linux/completion.h>
#include "hyperv.h"
#include <linux/hyperv.h>
#include <asm/hyperv.h>
#include "hyperv_vmbus.h"
@ -43,15 +41,28 @@ static struct acpi_device *hv_acpi_dev;
static struct tasklet_struct msg_dpc;
static struct tasklet_struct event_dpc;
unsigned int vmbus_loglevel = (ALL_MODULES << 16 | INFO_LVL);
EXPORT_SYMBOL(vmbus_loglevel);
/* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
/* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
static struct completion probe_event;
static int irq;
struct hv_device_info {
u32 chn_id;
u32 chn_state;
uuid_le chn_type;
uuid_le chn_instance;
u32 monitor_id;
u32 server_monitor_pending;
u32 server_monitor_latency;
u32 server_monitor_conn_id;
u32 client_monitor_pending;
u32 client_monitor_latency;
u32 client_monitor_conn_id;
struct hv_dev_port_info inbound;
struct hv_dev_port_info outbound;
};
static void get_channel_info(struct hv_device *device,
struct hv_device_info *info)
{
@ -65,9 +76,9 @@ static void get_channel_info(struct hv_device *device,
info->chn_id = debug_info.relid;
info->chn_state = debug_info.state;
memcpy(&info->chn_type, &debug_info.interfacetype,
sizeof(struct hv_guid));
sizeof(uuid_le));
memcpy(&info->chn_instance, &debug_info.interface_instance,
sizeof(struct hv_guid));
sizeof(uuid_le));
info->monitor_id = debug_info.monitorid;
@ -97,6 +108,14 @@ static void get_channel_info(struct hv_device *device,
debug_info.outbound.bytes_avail_towrite;
}
#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
{
int i;
for (i = 0; i < VMBUS_ALIAS_LEN; i += 2)
sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
}
/*
* vmbus_show_device_attr - Show the device attribute in sysfs.
*
@ -108,97 +127,105 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
char *buf)
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_device_info device_info;
struct hv_device_info *device_info;
char alias_name[VMBUS_ALIAS_LEN + 1];
int ret = 0;
memset(&device_info, 0, sizeof(struct hv_device_info));
device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL);
if (!device_info)
return ret;
get_channel_info(hv_dev, &device_info);
get_channel_info(hv_dev, device_info);
if (!strcmp(dev_attr->attr.name, "class_id")) {
return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}\n",
device_info.chn_type.data[3],
device_info.chn_type.data[2],
device_info.chn_type.data[1],
device_info.chn_type.data[0],
device_info.chn_type.data[5],
device_info.chn_type.data[4],
device_info.chn_type.data[7],
device_info.chn_type.data[6],
device_info.chn_type.data[8],
device_info.chn_type.data[9],
device_info.chn_type.data[10],
device_info.chn_type.data[11],
device_info.chn_type.data[12],
device_info.chn_type.data[13],
device_info.chn_type.data[14],
device_info.chn_type.data[15]);
device_info->chn_type.b[3],
device_info->chn_type.b[2],
device_info->chn_type.b[1],
device_info->chn_type.b[0],
device_info->chn_type.b[5],
device_info->chn_type.b[4],
device_info->chn_type.b[7],
device_info->chn_type.b[6],
device_info->chn_type.b[8],
device_info->chn_type.b[9],
device_info->chn_type.b[10],
device_info->chn_type.b[11],
device_info->chn_type.b[12],
device_info->chn_type.b[13],
device_info->chn_type.b[14],
device_info->chn_type.b[15]);
} else if (!strcmp(dev_attr->attr.name, "device_id")) {
return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}\n",
device_info.chn_instance.data[3],
device_info.chn_instance.data[2],
device_info.chn_instance.data[1],
device_info.chn_instance.data[0],
device_info.chn_instance.data[5],
device_info.chn_instance.data[4],
device_info.chn_instance.data[7],
device_info.chn_instance.data[6],
device_info.chn_instance.data[8],
device_info.chn_instance.data[9],
device_info.chn_instance.data[10],
device_info.chn_instance.data[11],
device_info.chn_instance.data[12],
device_info.chn_instance.data[13],
device_info.chn_instance.data[14],
device_info.chn_instance.data[15]);
device_info->chn_instance.b[3],
device_info->chn_instance.b[2],
device_info->chn_instance.b[1],
device_info->chn_instance.b[0],
device_info->chn_instance.b[5],
device_info->chn_instance.b[4],
device_info->chn_instance.b[7],
device_info->chn_instance.b[6],
device_info->chn_instance.b[8],
device_info->chn_instance.b[9],
device_info->chn_instance.b[10],
device_info->chn_instance.b[11],
device_info->chn_instance.b[12],
device_info->chn_instance.b[13],
device_info->chn_instance.b[14],
device_info->chn_instance.b[15]);
} else if (!strcmp(dev_attr->attr.name, "modalias")) {
print_alias_name(hv_dev, alias_name);
ret = sprintf(buf, "vmbus:%s\n", alias_name);
} else if (!strcmp(dev_attr->attr.name, "state")) {
return sprintf(buf, "%d\n", device_info.chn_state);
ret = sprintf(buf, "%d\n", device_info->chn_state);
} else if (!strcmp(dev_attr->attr.name, "id")) {
return sprintf(buf, "%d\n", device_info.chn_id);
ret = sprintf(buf, "%d\n", device_info->chn_id);
} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
return sprintf(buf, "%d\n", device_info.outbound.int_mask);
ret = sprintf(buf, "%d\n", device_info->outbound.int_mask);
} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
return sprintf(buf, "%d\n", device_info.outbound.read_idx);
ret = sprintf(buf, "%d\n", device_info->outbound.read_idx);
} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
return sprintf(buf, "%d\n", device_info.outbound.write_idx);
ret = sprintf(buf, "%d\n", device_info->outbound.write_idx);
} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
return sprintf(buf, "%d\n",
device_info.outbound.bytes_avail_toread);
ret = sprintf(buf, "%d\n",
device_info->outbound.bytes_avail_toread);
} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
return sprintf(buf, "%d\n",
device_info.outbound.bytes_avail_towrite);
ret = sprintf(buf, "%d\n",
device_info->outbound.bytes_avail_towrite);
} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
return sprintf(buf, "%d\n", device_info.inbound.int_mask);
ret = sprintf(buf, "%d\n", device_info->inbound.int_mask);
} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
return sprintf(buf, "%d\n", device_info.inbound.read_idx);
ret = sprintf(buf, "%d\n", device_info->inbound.read_idx);
} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
return sprintf(buf, "%d\n", device_info.inbound.write_idx);
ret = sprintf(buf, "%d\n", device_info->inbound.write_idx);
} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
return sprintf(buf, "%d\n",
device_info.inbound.bytes_avail_toread);
ret = sprintf(buf, "%d\n",
device_info->inbound.bytes_avail_toread);
} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
return sprintf(buf, "%d\n",
device_info.inbound.bytes_avail_towrite);
ret = sprintf(buf, "%d\n",
device_info->inbound.bytes_avail_towrite);
} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
return sprintf(buf, "%d\n", device_info.monitor_id);
ret = sprintf(buf, "%d\n", device_info->monitor_id);
} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
return sprintf(buf, "%d\n", device_info.server_monitor_pending);
ret = sprintf(buf, "%d\n", device_info->server_monitor_pending);
} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
return sprintf(buf, "%d\n", device_info.server_monitor_latency);
ret = sprintf(buf, "%d\n", device_info->server_monitor_latency);
} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
return sprintf(buf, "%d\n",
device_info.server_monitor_conn_id);
ret = sprintf(buf, "%d\n",
device_info->server_monitor_conn_id);
} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
return sprintf(buf, "%d\n", device_info.client_monitor_pending);
ret = sprintf(buf, "%d\n", device_info->client_monitor_pending);
} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
return sprintf(buf, "%d\n", device_info.client_monitor_latency);
ret = sprintf(buf, "%d\n", device_info->client_monitor_latency);
} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
return sprintf(buf, "%d\n",
device_info.client_monitor_conn_id);
} else {
return 0;
ret = sprintf(buf, "%d\n",
device_info->client_monitor_conn_id);
}
kfree(device_info);
return ret;
}
/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
@ -208,6 +235,7 @@ static struct device_attribute vmbus_device_attrs[] = {
__ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
__ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
@ -238,76 +266,60 @@ static struct device_attribute vmbus_device_attrs[] = {
* This routine is invoked when a device is added or removed on the vmbus to
* generate a uevent to udev in the userspace. The udev will then look at its
* rule and the uevent generated here to load the appropriate driver
*
* The alias string will be of the form vmbus:guid where guid is the string
* representation of the device guid (each byte of the guid will be
* represented with two hex characters.
*/
static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
{
struct hv_device *dev = device_to_hv_device(device);
int ret;
char alias_name[VMBUS_ALIAS_LEN + 1];
ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={"
"%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}",
dev->dev_type.data[3],
dev->dev_type.data[2],
dev->dev_type.data[1],
dev->dev_type.data[0],
dev->dev_type.data[5],
dev->dev_type.data[4],
dev->dev_type.data[7],
dev->dev_type.data[6],
dev->dev_type.data[8],
dev->dev_type.data[9],
dev->dev_type.data[10],
dev->dev_type.data[11],
dev->dev_type.data[12],
dev->dev_type.data[13],
dev->dev_type.data[14],
dev->dev_type.data[15]);
if (ret)
print_alias_name(dev, alias_name);
ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name);
return ret;
ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={"
"%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}",
dev->dev_instance.data[3],
dev->dev_instance.data[2],
dev->dev_instance.data[1],
dev->dev_instance.data[0],
dev->dev_instance.data[5],
dev->dev_instance.data[4],
dev->dev_instance.data[7],
dev->dev_instance.data[6],
dev->dev_instance.data[8],
dev->dev_instance.data[9],
dev->dev_instance.data[10],
dev->dev_instance.data[11],
dev->dev_instance.data[12],
dev->dev_instance.data[13],
dev->dev_instance.data[14],
dev->dev_instance.data[15]);
if (ret)
return ret;
return 0;
}
static uuid_le null_guid;
static inline bool is_null_guid(const __u8 *guid)
{
if (memcmp(guid, &null_guid, sizeof(uuid_le)))
return false;
return true;
}
/*
* Return a matching hv_vmbus_device_id pointer.
* If there is no match, return NULL.
*/
static const struct hv_vmbus_device_id *hv_vmbus_get_id(
const struct hv_vmbus_device_id *id,
__u8 *guid)
{
for (; !is_null_guid(id->guid); id++)
if (!memcmp(&id->guid, guid, sizeof(uuid_le)))
return id;
return NULL;
}
/*
* vmbus_match - Attempt to match the specified device to the specified driver
*/
static int vmbus_match(struct device *device, struct device_driver *driver)
{
int match = 0;
struct hv_driver *drv = drv_to_hv_drv(driver);
struct hv_device *hv_dev = device_to_hv_device(device);
/* We found our driver ? */
if (memcmp(&hv_dev->dev_type, &drv->dev_type,
sizeof(struct hv_guid)) == 0)
match = 1;
if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b))
return 1;
return match;
return 0;
}
/*
@ -319,9 +331,11 @@ static int vmbus_probe(struct device *child_device)
struct hv_driver *drv =
drv_to_hv_drv(child_device->driver);
struct hv_device *dev = device_to_hv_device(child_device);
const struct hv_vmbus_device_id *dev_id;
dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b);
if (drv->probe) {
ret = drv->probe(dev);
ret = drv->probe(dev, dev_id);
if (ret != 0)
pr_err("probe failed for device %s (%d)\n",
dev_name(child_device), ret);
@ -339,22 +353,14 @@ static int vmbus_probe(struct device *child_device)
*/
static int vmbus_remove(struct device *child_device)
{
int ret;
struct hv_driver *drv;
struct hv_driver *drv = drv_to_hv_drv(child_device->driver);
struct hv_device *dev = device_to_hv_device(child_device);
if (child_device->driver) {
drv = drv_to_hv_drv(child_device->driver);
if (drv->remove) {
ret = drv->remove(dev);
} else {
if (drv->remove)
drv->remove(dev);
else
pr_err("remove not set for driver %s\n",
dev_name(child_device));
ret = -ENODEV;
}
}
return 0;
}
@ -422,9 +428,6 @@ static void vmbus_onmessage_work(struct work_struct *work)
kfree(ctx);
}
/*
* vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior
*/
static void vmbus_on_msg_dpc(unsigned long data)
{
int cpu = smp_processor_id();
@ -468,53 +471,42 @@ static void vmbus_on_msg_dpc(unsigned long data)
}
}
/*
* vmbus_on_isr - ISR routine
*/
static int vmbus_on_isr(void)
static irqreturn_t vmbus_isr(int irq, void *dev_id)
{
int ret = 0;
int cpu = smp_processor_id();
void *page_addr;
struct hv_message *msg;
union hv_synic_event_flags *event;
bool handled = false;
page_addr = hv_context.synic_message_page[cpu];
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
/* Check if there are actual msgs to be process */
if (msg->header.message_type != HVMSG_NONE)
ret |= 0x1;
/*
* Check for events before checking for messages. This is the order
* in which events and messages are checked in Windows guests on
* Hyper-V, and the Windows team suggested we do the same.
*/
page_addr = hv_context.synic_event_page[cpu];
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
/* Since we are a child, we only need to check bit 0 */
if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0]))
ret |= 0x2;
return ret;
}
static irqreturn_t vmbus_isr(int irq, void *dev_id)
{
int ret;
ret = vmbus_on_isr();
/* Schedules a dpc if necessary */
if (ret > 0) {
if (test_bit(0, (unsigned long *)&ret))
tasklet_schedule(&msg_dpc);
if (test_bit(1, (unsigned long *)&ret))
if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
handled = true;
tasklet_schedule(&event_dpc);
return IRQ_HANDLED;
} else {
return IRQ_NONE;
}
page_addr = hv_context.synic_message_page[cpu];
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
/* Check if there are actual msgs to be processed */
if (msg->header.message_type != HVMSG_NONE) {
handled = true;
tasklet_schedule(&msg_dpc);
}
if (handled)
return IRQ_HANDLED;
else
return IRQ_NONE;
}
/*
@ -538,26 +530,20 @@ static int vmbus_bus_init(int irq)
return ret;
}
/* Initialize the bus context */
tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
tasklet_init(&event_dpc, vmbus_on_event, 0);
/* Now, register the bus with LDM */
ret = bus_register(&hv_bus);
if (ret)
return ret;
goto err_cleanup;
/* Get the interrupt resource */
ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
driver_name, hv_acpi_dev);
if (ret != 0) {
pr_err("Unable to request IRQ %d\n",
irq);
bus_unregister(&hv_bus);
return ret;
goto err_unregister;
}
vector = IRQ0_VECTOR + irq;
@ -568,76 +554,81 @@ static int vmbus_bus_init(int irq)
*/
on_each_cpu(hv_synic_init, (void *)&vector, 1);
ret = vmbus_connect();
if (ret) {
free_irq(irq, hv_acpi_dev);
bus_unregister(&hv_bus);
return ret;
}
if (ret)
goto err_irq;
vmbus_request_offers();
return 0;
err_irq:
free_irq(irq, hv_acpi_dev);
err_unregister:
bus_unregister(&hv_bus);
err_cleanup:
hv_cleanup();
return ret;
}
/**
* vmbus_child_driver_register() - Register a vmbus's child driver
* __vmbus_child_driver_register - Register a vmbus's driver
* @drv: Pointer to driver structure you want to register
*
* @owner: owner module of the drv
* @mod_name: module name string
*
* Registers the given driver with Linux through the 'driver_register()' call
* And sets up the hyper-v vmbus handling for this driver.
* and sets up the hyper-v vmbus handling for this driver.
* It will return the state of the 'driver_register()' call.
*
* Mainly used by Hyper-V drivers.
*/
int vmbus_child_driver_register(struct device_driver *drv)
int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name)
{
int ret;
pr_info("child driver registering - name %s\n", drv->name);
pr_info("registering driver %s\n", hv_driver->name);
/* The child driver on this vmbus */
drv->bus = &hv_bus;
hv_driver->driver.name = hv_driver->name;
hv_driver->driver.owner = owner;
hv_driver->driver.mod_name = mod_name;
hv_driver->driver.bus = &hv_bus;
ret = driver_register(drv);
ret = driver_register(&hv_driver->driver);
vmbus_request_offers();
return ret;
}
EXPORT_SYMBOL(vmbus_child_driver_register);
EXPORT_SYMBOL_GPL(__vmbus_driver_register);
/**
* vmbus_child_driver_unregister() - Unregister a vmbus's child driver
* vmbus_driver_unregister() - Unregister a vmbus's driver
* @drv: Pointer to driver structure you want to un-register
*
*
* Un-register the given driver with Linux through the 'driver_unregister()'
* call. And ungegisters the driver from the Hyper-V vmbus handler.
*
* Mainly used by Hyper-V drivers.
* Un-register the given driver that was previous registered with a call to
* vmbus_driver_register()
*/
void vmbus_child_driver_unregister(struct device_driver *drv)
void vmbus_driver_unregister(struct hv_driver *hv_driver)
{
pr_info("child driver unregistering - name %s\n", drv->name);
pr_info("unregistering driver %s\n", hv_driver->name);
driver_unregister(drv);
driver_unregister(&hv_driver->driver);
}
EXPORT_SYMBOL(vmbus_child_driver_unregister);
EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
/*
* vmbus_child_device_create - Creates and registers a new child device
* vmbus_device_create - Creates and registers a new child device
* on the vmbus.
*/
struct hv_device *vmbus_child_device_create(struct hv_guid *type,
struct hv_guid *instance,
struct hv_device *vmbus_device_create(uuid_le *type,
uuid_le *instance,
struct vmbus_channel *channel)
{
struct hv_device *child_device_obj;
/* Allocate the new child device */
child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL);
if (!child_device_obj) {
pr_err("Unable to allocate device object for child device\n");
@ -645,29 +636,27 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
}
child_device_obj->channel = channel;
memcpy(&child_device_obj->dev_type, type, sizeof(struct hv_guid));
memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
memcpy(&child_device_obj->dev_instance, instance,
sizeof(struct hv_guid));
sizeof(uuid_le));
return child_device_obj;
}
/*
* vmbus_child_device_register - Register the child device
* vmbus_device_register - Register the child device
*/
int vmbus_child_device_register(struct hv_device *child_device_obj)
int vmbus_device_register(struct hv_device *child_device_obj)
{
int ret = 0;
static atomic_t device_num = ATOMIC_INIT(0);
/* Set the device name. Otherwise, device_register() will fail. */
dev_set_name(&child_device_obj->device, "vmbus_0_%d",
atomic_inc_return(&device_num));
/* The new device belongs to this bus */
child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */
child_device_obj->device.bus = &hv_bus;
child_device_obj->device.parent = &hv_acpi_dev->dev;
child_device_obj->device.release = vmbus_device_release;
@ -687,10 +676,10 @@ int vmbus_child_device_register(struct hv_device *child_device_obj)
}
/*
* vmbus_child_device_unregister - Remove the specified child device
* vmbus_device_unregister - Remove the specified child device
* from the vmbus.
*/
void vmbus_child_device_unregister(struct hv_device *device_obj)
void vmbus_device_unregister(struct hv_device *device_obj)
{
/*
* Kick off the process of unregistering the device.
@ -727,8 +716,7 @@ static int vmbus_acpi_add(struct acpi_device *device)
hv_acpi_dev = device;
result =
acpi_walk_resources(device->handle, METHOD_NAME__CRS,
result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
vmbus_walk_resources, &irq);
if (ACPI_FAILURE(result)) {
@ -754,21 +742,9 @@ static struct acpi_driver vmbus_acpi_driver = {
},
};
/*
* We use a PCI table to determine if we should autoload this driver This is
* needed by distro tools to determine if the hyperv drivers should be
* installed and/or configured. We don't do anything else with the table, but
* it needs to be present.
*/
static const struct pci_device_id microsoft_hv_pci_table[] = {
{ PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
static int __init hv_acpi_init(void)
{
int ret;
int ret, t;
init_completion(&probe_event);
@ -781,15 +757,24 @@ static int __init hv_acpi_init(void)
if (ret)
return ret;
wait_for_completion(&probe_event);
t = wait_for_completion_timeout(&probe_event, 5*HZ);
if (t == 0) {
ret = -ETIMEDOUT;
goto cleanup;
}
if (irq <= 0) {
acpi_bus_unregister_driver(&vmbus_acpi_driver);
return -ENODEV;
ret = -ENODEV;
goto cleanup;
}
ret = vmbus_bus_init(irq);
if (ret)
goto cleanup;
return 0;
cleanup:
acpi_bus_unregister_driver(&vmbus_acpi_driver);
return ret;
}
@ -797,6 +782,5 @@ static int __init hv_acpi_init(void)
MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR);
module_init(hv_acpi_init);

View File

@ -46,8 +46,6 @@ source "drivers/staging/wlan-ng/Kconfig"
source "drivers/staging/echo/Kconfig"
source "drivers/staging/comedi/Kconfig"
source "drivers/staging/olpc_dcon/Kconfig"
@ -66,6 +64,8 @@ source "drivers/staging/rtl8712/Kconfig"
source "drivers/staging/rts_pstor/Kconfig"
source "drivers/staging/rts5139/Kconfig"
source "drivers/staging/frontier/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"

View File

@ -15,8 +15,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/
obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_ASUS_OLED) += asus_oled/
@ -26,6 +24,7 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
obj-$(CONFIG_RTS5139) += rts5139/
obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_POHMELFS) += pohmelfs/

View File

@ -28,6 +28,7 @@
#include <linux/string.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/module.h>
#include "altera.h"
#include "altera-exprt.h"
#include "altera-jtag.h"
@ -2384,7 +2385,7 @@ static int altera_get_act_info(u8 *p,
act_proc_attribute =
(p[proc_table + (13 * act_proc_id) + 8] & 0x03);
procptr = (struct altera_procinfo *)
procptr =
kzalloc(sizeof(struct altera_procinfo),
GFP_KERNEL);

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +1,71 @@
#include "headers.h"
int InterfaceFileDownload( PVOID arg,
struct file *flp,
unsigned int on_chip_loc)
int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
{
// unsigned int reg=0;
/* unsigned int reg = 0; */
mm_segment_t oldfs = {0};
int errno=0, len=0 /*,is_config_file = 0*/;
int errno = 0, len = 0; /* ,is_config_file = 0 */
loff_t pos = 0;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
//PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter;
/* PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; */
char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
if (!buff)
{
return -ENOMEM;
}
while(1)
{
oldfs=get_fs(); set_fs(get_ds());
len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
set_fs(oldfs);
if(len<=0)
{
if(len<0)
{
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
errno=len;
}
else
{
errno = 0;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
}
break;
}
//BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, buff, MAX_TRANSFER_CTRL_BYTE_USB);
errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len) ;
if(errno)
{
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed! status: %d", errno);
break;
while (1) {
oldfs = get_fs();
set_fs(get_ds());
len = vfs_read(flp, (void __force __user *)buff,
MAX_TRANSFER_CTRL_BYTE_USB, &pos);
set_fs(oldfs);
if (len <= 0) {
if (len < 0) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
DBG_TYPE_INITEXIT, MP_INIT,
DBG_LVL_ALL, "len < 0");
errno = len;
} else {
errno = 0;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
DBG_TYPE_INITEXIT, MP_INIT,
DBG_LVL_ALL,
"Got end of file!");
}
break;
}
/* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
* DBG_LVL_ALL, buff,
* MAX_TRANSFER_CTRL_BYTE_USB);
*/
errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
if (errno) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
DBG_TYPE_PRINTK, 0, 0,
"WRM Failed! status: %d", errno);
break;
}
on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
}/* End of for(;;)*/
}
kfree(buff);
return errno;
}
int InterfaceFileReadbackFromChip( PVOID arg,
struct file *flp,
unsigned int on_chip_loc)
int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc)
{
char *buff, *buff_readback;
unsigned int reg = 0;
mm_segment_t oldfs = {0};
int errno = 0, len = 0, is_config_file = 0;
loff_t pos = 0;
static int fw_down = 0;
static int fw_down;
INT Status = STATUS_SUCCESS;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
if(!buff || !buff_readback)
{
if (!buff || !buff_readback) {
kfree(buff);
kfree(buff_readback);
@ -78,52 +76,42 @@ int InterfaceFileReadbackFromChip( PVOID arg,
memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
while(1)
{
oldfs=get_fs(); set_fs(get_ds());
while (1) {
oldfs = get_fs();
set_fs(get_ds());
len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
set_fs(oldfs);
fw_down++;
if(len<=0)
{
if(len<0)
{
if (len <= 0) {
if (len < 0) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
errno = len;
}
else
{
} else {
errno = 0;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
}
break;
}
Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
if(Status)
{
if (Status) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
goto exit;
}
reg++;
if((len-sizeof(unsigned int))<4)
{
if(memcmp(buff_readback, buff, len))
{
if ((len-sizeof(unsigned int)) < 4) {
if (memcmp(buff_readback, buff, len)) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len);
Status = -EIO;
goto exit;
}
}
else
{
} else {
len -= 4;
while(len)
{
if(*(unsigned int*)&buff_readback[len] != *(unsigned int *)&buff[len])
{
while (len) {
if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
@ -135,69 +123,60 @@ int InterfaceFileReadbackFromChip( PVOID arg,
}
on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
} /* End of while(1) */
exit:
kfree(buff);
kfree(buff_readback);
return Status;
}
static int bcm_download_config_file(PMINI_ADAPTER Adapter,
FIRMWARE_INFO *psFwInfo)
static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
{
int retval = STATUS_SUCCESS;
B_UINT32 value = 0;
if (Adapter->pstargetparams == NULL) {
Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
if (Adapter->pstargetparams == NULL)
{
if((Adapter->pstargetparams =
kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL)
{
return -ENOMEM;
}
}
if (psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
{
return -EIO;
}
retval = copy_from_user(Adapter->pstargetparams,
psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
if(retval)
{
retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
if (retval) {
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
return -EFAULT;
}
/* Parse the structure and then Download the Firmware */
beceem_parse_target_struct(Adapter);
//Initializing the NVM.
/* Initializing the NVM. */
BcmInitNVM(Adapter);
retval = InitLedSettings(Adapter);
if(retval)
{
if (retval) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
return retval;
}
if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
{
if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->LEDInfo.bLedInitDone = FALSE;
Adapter->DriverState = DRIVER_INIT;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)
{
if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
Adapter->DriverState = FW_DOWNLOAD;
wake_up(&Adapter->LEDInfo.notify_led_event);
}
/* Initialize the DDR Controller */
retval = ddr_init(Adapter);
if(retval)
{
if (retval) {
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
return retval;
}
@ -206,49 +185,36 @@ static int bcm_download_config_file(PMINI_ADAPTER Adapter,
wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
if(Adapter->eNVMType == NVM_FLASH)
{
if (Adapter->eNVMType == NVM_FLASH) {
retval = PropagateCalParamsFromFlashToMemory(Adapter);
if(retval)
{
if (retval) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval);
return retval;
}
}
retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(STARGETPARAMS), CONFIG_BEGIN_ADDR);
if (retval)
{
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
}
else
Adapter->bCfgDownloaded = TRUE;
return retval;
}
static int bcm_compare_buff_contents(unsigned char *readbackbuff,
unsigned char *buff,unsigned int len)
static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
{
int retval = STATUS_SUCCESS;
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
if((len-sizeof(unsigned int))<4)
{
if ((len-sizeof(unsigned int)) < 4) {
if (memcmp(readbackbuff , buff, len))
{
retval = -EINVAL;
}
}
else
{
} else {
len -= 4;
while(len)
{
if(*(unsigned int*)&readbackbuff[len] !=
*(unsigned int *)&buff[len])
{
while (len) {
if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
@ -260,41 +226,35 @@ static int bcm_compare_buff_contents(unsigned char *readbackbuff,
}
return retval;
}
int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
{
int retval = STATUS_SUCCESS;
PUCHAR buff = NULL;
/* Config File is needed for the Driver to download the Config file and
Firmware. Check for the Config file to be first to be sent from the
Application
* Firmware. Check for the Config file to be first to be sent from the
* Application
*/
atomic_set(&Adapter->uiMBupdate, FALSE);
if(!Adapter->bCfgDownloaded &&
psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR)
{
if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
/* Can't Download Firmware. */
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
return -EINVAL;
}
/* If Config File, Finish the DDR Settings and then Download CFG File */
if(psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
{
if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
retval = bcm_download_config_file(Adapter, psFwInfo);
}
else
{
} else {
buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
if(buff==NULL)
{
if (buff == NULL) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory");
return -ENOMEM;
}
retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
if(retval != STATUS_SUCCESS)
{
if (retval != STATUS_SUCCESS) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
retval = -EFAULT;
goto error;
@ -304,31 +264,29 @@ int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
buff,
psFwInfo->u32FirmwareLength,
psFwInfo->u32StartingAddress);
if(retval != STATUS_SUCCESS)
{
if (retval != STATUS_SUCCESS) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval);
goto error;
}
}
error:
kfree(buff);
return retval;
}
static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength,
ULONG u32StartingAddress)
static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
{
unsigned int len = 0;
int retval = STATUS_SUCCESS;
len = u32FirmwareLength;
while(u32FirmwareLength)
{
while (u32FirmwareLength) {
len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
if(retval)
{
if (retval) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
break;
}
@ -337,66 +295,56 @@ static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Firmware
mappedbuffer += len;
}
return retval;
}
static INT buffRdbkVerify(PMINI_ADAPTER Adapter,
PUCHAR mappedbuffer, UINT u32FirmwareLength,
ULONG u32StartingAddress)
static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
{
UINT len = u32FirmwareLength;
INT retval = STATUS_SUCCESS;
PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
if(NULL == readbackbuff)
{
if (NULL == readbackbuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
return -ENOMEM;
}
while (u32FirmwareLength && !retval)
{
while (u32FirmwareLength && !retval) {
len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
retval = rdm(Adapter, u32StartingAddress, readbackbuff, len);
if(retval)
{
if (retval) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
break;
}
if (STATUS_SUCCESS != (retval = bcm_compare_buff_contents (readbackbuff, mappedbuffer, len)))
{
retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
if (STATUS_SUCCESS != retval)
break;
}
u32StartingAddress += len;
u32FirmwareLength -= len;
mappedbuffer += len;
} /* end of while (u32FirmwareLength && !retval) */
kfree(readbackbuff);
return retval;
}
INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
unsigned long u32StartingAddress)
INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress)
{
INT status = STATUS_SUCCESS;
status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
if(status != STATUS_SUCCESS)
{
if (status != STATUS_SUCCESS) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed");
goto error;
}
status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
if(status != STATUS_SUCCESS)
{
if (status != STATUS_SUCCESS) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed");
goto error;
}
error:
return status;
}

View File

@ -139,8 +139,7 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE);
}
static int
usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
int retval;
@ -281,8 +280,9 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
int i = 0;
for (i = 0; i < MAXIMUM_USB_TCB; i++) {
if ((psIntfAdapter->asUsbTcb[i].urb =
usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
psIntfAdapter->asUsbTcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
if (psIntfAdapter->asUsbTcb[i].urb == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Tx urb for index %d\n", i);
return -ENOMEM;
@ -290,14 +290,17 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
}
for (i = 0; i < MAXIMUM_USB_RCB; i++) {
if ((psIntfAdapter->asUsbRcb[i].urb =
usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
psIntfAdapter->asUsbRcb[i].urb = usb_alloc_urb(0, GFP_KERNEL);
if (psIntfAdapter->asUsbRcb[i].urb == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Rx urb for index %d\n", i);
return -ENOMEM;
}
if ((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer =
kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL) {
psIntfAdapter->asUsbRcb[i].urb->transfer_buffer = kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL);
if (psIntfAdapter->asUsbRcb[i].urb->transfer_buffer == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
"Can't allocate Rx buffer for index %d\n", i);
return -ENOMEM;
@ -389,32 +392,32 @@ static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descripto
static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
{
return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd));
return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
{
return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd));
return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd);
}
static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
{
return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd));
return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
{
return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd));
return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd);
}
static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
{
return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd));
return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd);
}
static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
{
return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd));
return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
}
static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
@ -641,8 +644,8 @@ static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message)
static int InterfaceResume(struct usb_interface *intf)
{
PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf);
mdelay(100);
mdelay(100);
psIntfAdapter->bSuspended = FALSE;
StartInterruptUrb(psIntfAdapter);

View File

@ -1,37 +1,34 @@
#include "headers.h"
INT
InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
UINT addr,
PVOID buff,
INT len)
{
int retval = 0;
USHORT usRetries = 0;
if(psIntfAdapter == NULL )
{
if (psIntfAdapter == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
return -EINVAL;
}
if(psIntfAdapter->psAdapter->device_removed == TRUE)
{
if (psIntfAdapter->psAdapter->device_removed == TRUE) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
return -ENODEV;
}
if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
{
if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus");
return -EACCES;
}
if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
{
if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
return -EACCES;
}
psIntfAdapter->psAdapter->DeviceAccess = TRUE;
do {
retval = usb_control_msg(psIntfAdapter->udev,
usb_rcvctrlpipe(psIntfAdapter->udev, 0),
@ -44,30 +41,25 @@ InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
5000);
usRetries++;
if(-ENODEV == retval)
{
if (-ENODEV == retval) {
psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
} while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
if(retval < 0)
{
if (retval < 0) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries);
psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return retval;
}
else
{
} else {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return STATUS_SUCCESS;
}
}
INT
InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
UINT addr,
PVOID buff,
INT len)
@ -75,30 +67,28 @@ InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
int retval = 0;
USHORT usRetries = 0;
if(psIntfAdapter == NULL )
{
if (psIntfAdapter == NULL) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
return -EINVAL;
}
if(psIntfAdapter->psAdapter->device_removed == TRUE)
{
if (psIntfAdapter->psAdapter->device_removed == TRUE) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
return -ENODEV;
}
if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
{
if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus...");
return -EACCES;
}
if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
{
if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed..");
return -EACCES;
}
psIntfAdapter->psAdapter->DeviceAccess = TRUE;
do {
retval = usb_control_msg(psIntfAdapter->udev,
usb_sndctrlpipe(psIntfAdapter->udev, 0),
@ -111,32 +101,25 @@ InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
5000);
usRetries++;
if(-ENODEV == retval)
{
if (-ENODEV == retval) {
psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}
} while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
if(retval < 0)
{
if (retval < 0) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return retval;
}
else
{
} else {
psIntfAdapter->psAdapter->DeviceAccess = FALSE;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
return STATUS_SUCCESS;
}
}
}
INT
BcmRDM(PVOID arg,
INT BcmRDM(PVOID arg,
UINT addr,
PVOID buff,
INT len)
@ -144,8 +127,7 @@ BcmRDM(PVOID arg,
return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
}
INT
BcmWRM(PVOID arg,
INT BcmWRM(PVOID arg,
UINT addr,
PVOID buff,
INT len)
@ -153,33 +135,30 @@ BcmWRM(PVOID arg,
return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
}
INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
{
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
INT status = STATUS_SUCCESS;
/*
usb_clear_halt - tells device to clear endpoint halt/stall condition
@dev: device whose endpoint is halted
@pipe: endpoint "pipe" being cleared
@ Context: !in_interrupt ()
usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
This is used to clear halt conditions for bulk and interrupt endpoints only.
Control and isochronous endpoints never halts.
Any URBs queued for such an endpoint should normally be unlinked by the driver
before clearing the halt condition.
* usb_clear_halt - tells device to clear endpoint halt/stall condition
* @dev: device whose endpoint is halted
* @pipe: endpoint "pipe" being cleared
* @ Context: !in_interrupt ()
*
* usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
* This is used to clear halt conditions for bulk and interrupt endpoints only.
* Control and isochronous endpoints never halts.
*
* Any URBs queued for such an endpoint should normally be unlinked by the driver
* before clearing the halt condition.
*
*/
//Killing all the submitted urbs to different end points.
/* Killing all the submitted urbs to different end points. */
Bcm_kill_all_URBs(psIntfAdapter);
//clear the halted/stalled state for every end point
/* clear the halted/stalled state for every end point */
status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe);
if (status != STATUS_SUCCESS)
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
@ -195,13 +174,12 @@ INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
return status;
}
VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
{
struct urb *tempUrb = NULL;
UINT i;
/**
/*
* usb_kill_urb - cancel a transfer request and wait for it to finish
* @urb: pointer to URB describing a previously submitted request,
* returns nothing as it is void returned API.
@ -209,36 +187,31 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
* This routine cancels an in-progress request. It is guaranteed that
* upon return all completion handlers will have finished and the URB
* will be totally idle and available for reuse
*
* This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule().
*
**/
*/
/* Cancel submitted Interrupt-URB's */
if(psIntfAdapter->psInterruptUrb != NULL)
{
if (psIntfAdapter->psInterruptUrb != NULL) {
if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
usb_kill_urb(psIntfAdapter->psInterruptUrb);
}
/* Cancel All submitted TX URB's */
for(i = 0; i < MAXIMUM_USB_TCB; i++)
{
for (i = 0; i < MAXIMUM_USB_TCB; i++) {
tempUrb = psIntfAdapter->asUsbTcb[i].urb;
if(tempUrb)
{
if (tempUrb) {
if (tempUrb->status == -EINPROGRESS)
usb_kill_urb(tempUrb);
}
}
for(i = 0; i < MAXIMUM_USB_RCB; i++)
{
for (i = 0; i < MAXIMUM_USB_RCB; i++) {
tempUrb = psIntfAdapter->asUsbRcb[i].urb;
if(tempUrb)
{
if (tempUrb) {
if (tempUrb->status == -EINPROGRESS)
usb_kill_urb(tempUrb);
}
@ -260,6 +233,5 @@ VOID putUsbSuspend(struct work_struct *work)
if (psIntfAdapter->bSuspended == FALSE)
usb_autopm_put_interface(intf);
}

View File

@ -4,9 +4,9 @@
#ifndef __MACROS_H__
#define __MACROS_H__
#define TX_TIMER_PERIOD 10 //10 msec
#define TX_TIMER_PERIOD 10 /*10 msec*/
#define MAX_CLASSIFIERS 100
//#define MAX_CLASSIFIERS_PER_SF 20
/* #define MAX_CLASSIFIERS_PER_SF 20 */
#define MAX_TARGET_DSX_BUFFERS 24
#define MAX_CNTRL_PKTS 100
@ -20,20 +20,20 @@
#define MAC_ADDR_REGISTER 0xbf60d000
///////////Quality of Service///////////////////////////
/* Quality of Service */
#define NO_OF_QUEUES 17
#define HiPriority NO_OF_QUEUES-1
#define HiPriority (NO_OF_QUEUES-1)
#define LowPriority 0
#define BE 2
#define rtPS 4
#define ERTPS 5
#define UGS 6
#define BE_BUCKET_SIZE 1024*1024*100 //32kb
#define rtPS_BUCKET_SIZE 1024*1024*100 //8kb
#define MAX_ALLOWED_RATE 1024*1024*100
#define BE_BUCKET_SIZE (1024*1024*100) /* 32kb */
#define rtPS_BUCKET_SIZE (1024*1024*100) /* 8kb */
#define MAX_ALLOWED_RATE (1024*1024*100)
#define TX_PACKET_THRESHOLD 10
#define XSECONDS 1*HZ
#define XSECONDS (1*HZ)
#define DSC_ACTIVATE_REQUEST 248
#define QUEUE_DEPTH_OFFSET 0x1fc01000
#define MAX_DEVICE_DESC_SIZE 2040
@ -54,7 +54,7 @@
#define IP_PACKET_ONLY_MODE 0
#define ETH_PACKET_TUNNELING_MODE 1
////////////Link Request//////////////
/* Link Request */
#define SET_MAC_ADDRESS_REQUEST 0
#define SYNC_UP_REQUEST 1
#define SYNCED_UP 2
@ -111,11 +111,11 @@
#define LEADER_SIZE sizeof(LEADER)
#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND)
#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND)
#define CM_REQUEST_SIZE LEADER_SIZE + sizeof(stLocalSFChangeRequest)
#define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest))
#define IDLE_REQ_SIZE sizeof(PACKETTOSEND)
#define MAX_TRANSFER_CTRL_BYTE_USB 2 * 1024
#define MAX_TRANSFER_CTRL_BYTE_USB (2*1024)
#define GET_MAILBOX1_REG_REQUEST 0x87
#define GET_MAILBOX1_REG_RESPONSE 0x67
@ -147,10 +147,10 @@
#define CM_INDICATION 6
#define PARAM_RESP 7
#define BUFFER_1K 1024
#define BUFFER_2K BUFFER_1K*2
#define BUFFER_4K BUFFER_2K*2
#define BUFFER_8K BUFFER_4K*2
#define BUFFER_16K BUFFER_8K*2
#define BUFFER_2K (BUFFER_1K*2)
#define BUFFER_4K (BUFFER_2K*2)
#define BUFFER_8K (BUFFER_4K*2)
#define BUFFER_16K (BUFFER_8K*2)
#define DOWNLINK_DIR 0
#define UPLINK_DIR 1
@ -183,8 +183,7 @@ enum enLinkStatus {
COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW = 9
};
typedef enum _E_PHS_DSC_ACTION
{
typedef enum _E_PHS_DSC_ACTION {
eAddPHSRule = 0,
eSetPHSRule,
eDeletePHSRule,
@ -192,9 +191,9 @@ typedef enum _E_PHS_DSC_ACTION
} E_PHS_DSC_ACTION;
#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 // Host to Mac
#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 // Mac to Host
#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 //0b000010000
#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 /* Host to Mac */
#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 /* Mac to Host */
#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 /* 0b000010000 */
#define MINIMUM_PENDING_DESCRIPTORS 5
#define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC
@ -263,15 +262,15 @@ typedef enum _E_PHS_DSC_ACTION
#define INVALID_QUEUE_INDEX NO_OF_QUEUES
#define INVALID_PID (pid_t)-1
#define INVALID_PID ((pid_t)-1)
#define DDR_80_MHZ 0
#define DDR_100_MHZ 1
#define DDR_120_MHZ 2 // Additional Frequency for T3LP
#define DDR_120_MHZ 2 /* Additional Frequency for T3LP */
#define DDR_133_MHZ 3
#define DDR_140_MHZ 4 // Not Used (Reserved for future)
#define DDR_160_MHZ 5 // Additional Frequency for T3LP
#define DDR_180_MHZ 6 // Not Used (Reserved for future)
#define DDR_200_MHZ 7 // Not Used (Reserved for future)
#define DDR_140_MHZ 4 /* Not Used (Reserved for future) */
#define DDR_160_MHZ 5 /* Additional Frequency for T3LP */
#define DDR_180_MHZ 6 /* Not Used (Reserved for future) */
#define DDR_200_MHZ 7 /* Not Used (Reserved for future) */
#define MIPS_200_MHZ 0
#define MIPS_160_MHZ 1
@ -311,7 +310,7 @@ typedef enum _E_PHS_DSC_ACTION
#define CHIP_ID_REG 0x0F000000
#define GPIO_MODE_REG 0x0F000034
#define GPIO_OUTPUT_REG 0x0F00003C
#define WIMAX_MAX_ALLOWED_RATE 1024*1024*50
#define WIMAX_MAX_ALLOWED_RATE (1024*1024*50)
#define T3 0xbece0300
#define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400
@ -330,16 +329,14 @@ typedef enum _E_PHS_DSC_ACTION
#define HPM_CONFIG_MSW 0x0F000D58
#define T3B 0xbece0310
typedef enum eNVM_TYPE
{
typedef enum eNVM_TYPE {
NVM_AUTODETECT = 0,
NVM_EEPROM,
NVM_FLASH,
NVM_UNKNOWN
} NVM_TYPE;
typedef enum ePMU_MODES
{
typedef enum ePMU_MODES {
HYBRID_MODE_7C = 0,
INTERNAL_MODE_6 = 1,
HYBRID_MODE_6 = 2
@ -360,4 +357,4 @@ enum eAbortPattern {
#define SKB_CB_LATENCY_OFFSET 1
#define SKB_CB_TCPACK_OFFSET 2
#endif //__MACROS_H__
#endif /* __MACROS_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -74,4 +74,6 @@
#define DRV_VERSION VER_FILEVERSION_STR
#define PFX DRV_NAME " "
extern struct class *bcm_class;
#endif

View File

@ -4013,7 +4013,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature");
return STATUS_FAILURE;
Status = STATUS_FAILURE;
goto out;
}
uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
@ -4026,7 +4027,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size");
return STATUS_FAILURE;
Status = STATUS_FAILURE;
goto out;
}
uiTotalDataToCopy = ISOLength;
@ -4143,7 +4145,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature");
return STATUS_FAILURE;
Status = STATUS_FAILURE;
goto out;
}
uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
@ -4156,7 +4159,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
if(uiTotalDataToCopy < ISOLength)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size");
return STATUS_FAILURE;
Status = STATUS_FAILURE;
goto out;
}
uiTotalDataToCopy = ISOLength;
@ -4257,6 +4261,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
}
out:
kfree(Buff);
return Status;

View File

@ -1,40 +0,0 @@
config BRCMUTIL
tristate
default n
config BRCMSMAC
tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
default n
depends on PCI
depends on WLAN && MAC80211
depends on X86 || MIPS
select BRCMUTIL
select FW_LOADER
select CRC_CCITT
---help---
This module adds support for PCIe wireless adapters based on Broadcom
IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll
be called brcmsmac.ko.
config BRCMFMAC
tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
default n
depends on MMC
depends on WLAN && CFG80211
depends on X86 || MIPS
select BRCMUTIL
select FW_LOADER
select WIRELESS_EXT
select WEXT_PRIV
---help---
This module adds support for embedded wireless adapters based on
Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's
wireless extensions subsystem. If you choose to build a module,
it'll be called brcmfmac.ko.
config BRCMDBG
bool "Broadcom driver debug functions"
default n
depends on BRCMSMAC || BRCMFMAC
---help---
Selecting this enables additional code for debug purposes.

View File

@ -1,24 +0,0 @@
#
# Makefile fragment for Broadcom 802.11n Networking Device Driver
#
# Copyright (c) 2010 Broadcom Corporation
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# common flags
subdir-ccflags-y := -DBCMDMA32
subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG
obj-$(CONFIG_BRCMUTIL) += brcmutil/
obj-$(CONFIG_BRCMFMAC) += brcmfmac/
obj-$(CONFIG_BRCMSMAC) += brcmsmac/

View File

@ -1 +0,0 @@
refer to: http://linuxwireless.org/en/users/Drivers/brcm80211

View File

@ -1,13 +0,0 @@
To Do List for Broadcom Mac80211 driver before getting in mainline
Bugs
====
- none known at this moment
brcmfmac
=====================
- ASSERTS deprecated in mainline, replace by warning + error handling
brcm80211 info page
=====================
http://linuxwireless.org/en/users/Drivers/brcm80211

View File

@ -1,39 +0,0 @@
#
# Makefile fragment for Broadcom 802.11n Networking Device Driver
#
# Copyright (c) 2010 Broadcom Corporation
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ccflags-y := \
-DBRCMF_FIRSTREAD=64 \
-DBRCMF_SDALIGN=64 \
-DMAX_HDR_READ=64
ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS
ccflags-y += \
-Idrivers/staging/brcm80211/brcmfmac \
-Idrivers/staging/brcm80211/include
DHDOFILES = \
wl_cfg80211.o \
dhd_cdc.o \
dhd_common.o \
dhd_sdio.o \
dhd_linux.o \
bcmsdh.o \
bcmsdh_sdmmc.o
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += $(DHDOFILES)

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _bcmchip_h_
#define _bcmchip_h_
/* bcm4329 */
/* SDIO device core, ID 0x829 */
#define BCM4329_CORE_BUS_BASE 0x18011000
/* internal memory core, ID 0x80e */
#define BCM4329_CORE_SOCRAM_BASE 0x18003000
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
/* firmware name */
#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin"
#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt"
#endif /* _bcmchip_h_ */

View File

@ -1,642 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* ****************** SDIO CARD Interface Functions **************************/
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <defs.h>
#include <brcm_hw_ids.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
#include <soc.h>
#include "dhd.h"
#include "dhd_bus.h"
#include "sdio_host.h"
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
#define BRCMF_SD_ERROR_VAL 0x0001 /* Error */
#define BRCMF_SD_INFO_VAL 0x0002 /* Info */
#ifdef BCMDBG
#define BRCMF_SD_ERROR(x) \
do { \
if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
net_ratelimit()) \
printk x; \
} while (0)
#define BRCMF_SD_INFO(x) \
do { \
if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
net_ratelimit()) \
printk x; \
} while (0)
#else /* BCMDBG */
#define BRCMF_SD_ERROR(x)
#define BRCMF_SD_INFO(x)
#endif /* BCMDBG */
/* debugging macros */
#define SDLX_MSG(x)
#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
#define SDIOH_DATA_PIO 0 /* PIO mode */
#define SDIOH_DATA_DMA 1 /* DMA mode */
struct brcmf_sdio_card {
bool init_success; /* underlying driver successfully attached */
void *sdioh; /* handler for sdioh */
u32 vendevid; /* Target Vendor and Device ID on SD bus */
bool regfail; /* Save status of last
reg_read/reg_write call */
u32 sbwad; /* Save backplane window address */
};
/**
* SDIO Host Controller info
*/
struct sdio_hc {
struct sdio_hc *next;
struct device *dev; /* platform device handle */
void *regs; /* SDIO Host Controller address */
struct brcmf_sdio_card *card;
void *ch;
unsigned int oob_irq;
unsigned long oob_flags; /* OOB Host specifiction
as edge and etc */
bool oob_irq_registered;
};
/* local copy of bcm sd handler */
static struct brcmf_sdio_card *l_card;
const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
static struct sdio_hc *sdhcinfo;
/* driver info, initialized when brcmf_sdio_register is called */
static struct brcmf_sdioh_driver drvinfo = { NULL, NULL };
/* Module parameters specific to each host-controller driver */
module_param(sd_msglevel, uint, 0);
extern uint sd_f2_blocksize;
module_param(sd_f2_blocksize, int, 0);
/* forward declarations */
int brcmf_sdio_probe(struct device *dev);
EXPORT_SYMBOL(brcmf_sdio_probe);
int brcmf_sdio_remove(struct device *dev);
EXPORT_SYMBOL(brcmf_sdio_remove);
struct brcmf_sdio_card*
brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq)
{
struct brcmf_sdio_card *card;
card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC);
if (card == NULL) {
BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
return NULL;
}
/* save the handler locally */
l_card = card;
card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
if (!card->sdioh) {
brcmf_sdcard_detach(card);
return NULL;
}
card->init_success = true;
*regsva = SI_ENUM_BASE;
/* Report the BAR, to fix if needed */
card->sbwad = SI_ENUM_BASE;
return card;
}
int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
{
if (card != NULL) {
if (card->sdioh) {
brcmf_sdioh_detach(card->sdioh);
card->sdioh = NULL;
}
kfree(card);
}
l_card = NULL;
return 0;
}
int
brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
void *params, int plen, void *arg, int len, bool set)
{
return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
len, set);
}
int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
{
return brcmf_sdioh_interrupt_set(card->sdioh, true);
}
int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
{
return brcmf_sdioh_interrupt_set(card->sdioh, false);
}
int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
void (*fn)(void *), void *argh)
{
return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
}
int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
{
return brcmf_sdioh_interrupt_deregister(card->sdioh);
}
u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
int *err)
{
int status;
s32 retry = 0;
u8 data = 0;
if (!card)
card = l_card;
do {
if (retry) /* wait for 1 ms till bus get settled down */
udelay(1000);
status =
brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
(u8 *) &data);
} while (status != 0
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
if (err)
*err = status;
BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
__func__, fnc_num, addr, data));
return data;
}
void
brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
u8 data, int *err)
{
int status;
s32 retry = 0;
if (!card)
card = l_card;
do {
if (retry) /* wait for 1 ms till bus get settled down */
udelay(1000);
status =
brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
(u8 *) &data);
} while (status != 0
&& (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
if (err)
*err = status;
BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
__func__, fnc_num, addr, data));
}
u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
u32 addr, int *err)
{
int status;
u32 data = 0;
if (!card)
card = l_card;
status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_READ, fnc_num, addr, &data, 4);
if (err)
*err = status;
BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
__func__, fnc_num, addr, data));
return data;
}
void
brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
u32 addr, u32 data, int *err)
{
int status;
if (!card)
card = l_card;
status =
brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_WRITE, fnc_num, addr, &data, 4);
if (err)
*err = status;
BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
__func__, fnc_num, addr, data));
}
int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
uint length)
{
int status;
u8 *tmp_buf, *tmp_ptr;
u8 *ptr;
bool ascii = func & ~0xf;
func &= 0x7;
if (!card)
card = l_card;
status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length);
if (ascii) {
/* Move binary bits to tmp and format them
into the provided buffer. */
tmp_buf = kmalloc(length, GFP_ATOMIC);
if (tmp_buf == NULL) {
BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
return -ENOMEM;
}
memcpy(tmp_buf, cis, length);
for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
tmp_ptr++) {
ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
ptr += sprintf((char *)ptr, "\n");
}
kfree(tmp_buf);
}
return status;
}
static int
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
{
int err = 0;
brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
(address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
if (!err)
brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
SBSDIO_FUNC1_SBADDRMID,
(address >> 16) & SBSDIO_SBADDRMID_MASK,
&err);
if (!err)
brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
SBSDIO_FUNC1_SBADDRHIGH,
(address >> 24) & SBSDIO_SBADDRHIGH_MASK,
&err);
return err;
}
u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
{
int status;
u32 word = 0;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
if (!card)
card = l_card;
if (bar0 != card->sbwad) {
if (brcmf_sdcard_set_sbaddr_window(card, bar0))
return 0xFFFFFFFF;
card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (size == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
card->regfail = (status != 0);
BRCMF_SD_INFO(("u32data = 0x%x\n", word));
/* if ok, return appropriately masked word */
if (status == 0) {
switch (size) {
case sizeof(u8):
return word & 0xff;
case sizeof(u16):
return word & 0xffff;
case sizeof(u32):
return word;
default:
card->regfail = true;
}
}
/* otherwise, bad sdio access or invalid size */
BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
addr, size));
return 0xFFFFFFFF;
}
u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
u32 data)
{
int status;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
__func__, addr, size * 8, data));
if (!card)
card = l_card;
if (bar0 != card->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(card, bar0);
if (err)
return err;
card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
if (size == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
status =
brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
card->regfail = (status != 0);
if (status == 0)
return 0;
BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
__func__, data, addr, size));
return 0xFFFFFFFF;
}
bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
{
return card->regfail;
}
int
brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
uint flags,
u8 *buf, uint nbytes, struct sk_buff *pkt,
void (*complete)(void *handle, int status,
bool sync_waiting),
void *handle)
{
int status;
uint incr_fix;
uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
__func__, fn, addr, nbytes));
/* Async not implemented yet */
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
if (bar0 != card->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(card, bar0);
if (err)
return err;
card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
return status;
}
int
brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes, void *pkt,
void (*complete)(void *handle, int status,
bool sync_waiting),
void *handle)
{
uint incr_fix;
uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
__func__, fn, addr, nbytes));
/* Async not implemented yet */
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
if (bar0 != card->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(card, bar0);
if (err)
return err;
card->sbwad = bar0;
}
addr &= SBSDIO_SB_OFT_ADDR_MASK;
incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
}
int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
u8 *buf, uint nbytes)
{
addr &= SBSDIO_SB_OFT_ADDR_MASK;
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
addr, 4, nbytes, buf, NULL);
}
int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
{
return brcmf_sdioh_abort(card->sdioh, fn);
}
int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
{
card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
return card->vendevid;
}
u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
{
if (!card)
card = l_card;
return card->sbwad;
}
int brcmf_sdio_probe(struct device *dev)
{
struct sdio_hc *sdhc = NULL;
u32 regs = 0;
struct brcmf_sdio_card *card = NULL;
int irq = 0;
u32 vendevid;
unsigned long irq_flags = 0;
/* allocate SDIO Host Controller state info */
sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC);
if (!sdhc) {
SDLX_MSG(("%s: out of memory\n", __func__));
goto err;
}
sdhc->dev = (void *)dev;
card = brcmf_sdcard_attach((void *)0, &regs, irq);
if (!card) {
SDLX_MSG(("%s: attach failed\n", __func__));
goto err;
}
sdhc->card = card;
sdhc->oob_irq = irq;
sdhc->oob_flags = irq_flags;
sdhc->oob_irq_registered = false; /* to make sure.. */
/* chain SDIO Host Controller info together */
sdhc->next = sdhcinfo;
sdhcinfo = sdhc;
/* Read the vendor/device ID from the CIS */
vendevid = brcmf_sdcard_query_device(card);
/* try to attach to the target device */
sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
0, 0, 0, 0, regs, card);
if (!sdhc->ch) {
SDLX_MSG(("%s: device attach failed\n", __func__));
goto err;
}
return 0;
/* error handling */
err:
if (sdhc) {
if (sdhc->card)
brcmf_sdcard_detach(sdhc->card);
kfree(sdhc);
}
return -ENODEV;
}
int brcmf_sdio_remove(struct device *dev)
{
struct sdio_hc *sdhc, *prev;
sdhc = sdhcinfo;
drvinfo.detach(sdhc->ch);
brcmf_sdcard_detach(sdhc->card);
/* find the SDIO Host Controller state for this pdev
and take it out from the list */
for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
if (sdhc->dev == (void *)dev) {
if (prev)
prev->next = sdhc->next;
else
sdhcinfo = NULL;
break;
}
prev = sdhc;
}
if (!sdhc) {
SDLX_MSG(("%s: failed\n", __func__));
return 0;
}
/* release SDIO Host Controller info */
kfree(sdhc);
return 0;
}
int brcmf_sdio_register(struct brcmf_sdioh_driver *driver)
{
drvinfo = *driver;
SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
return brcmf_sdio_function_init();
}
void brcmf_sdio_unregister(void)
{
brcmf_sdio_function_cleanup();
}
void brcmf_sdio_wdtmr_enable(bool enable)
{
if (enable)
brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms);
else
brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,904 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/****************
* Common types *
*/
#ifndef _BRCMF_H_
#define _BRCMF_H_
#define BRCMF_VERSION_STR "4.218.248.5"
#define BRCMF_C_IOCTL_SMLEN 256 /* "small" ioctl buffer required */
#define BRCMF_C_IOCTL_MEDLEN 1536 /* "med" ioctl buffer required */
#define BRCMF_C_IOCTL_MAXLEN 8192
#define BRCMF_C_UP 2
#define BRCMF_C_SET_PROMISC 10
#define BRCMF_C_GET_RATE 12
#define BRCMF_C_GET_INFRA 19
#define BRCMF_C_SET_INFRA 20
#define BRCMF_C_GET_AUTH 21
#define BRCMF_C_SET_AUTH 22
#define BRCMF_C_GET_BSSID 23
#define BRCMF_C_GET_SSID 25
#define BRCMF_C_SET_SSID 26
#define BRCMF_C_GET_CHANNEL 29
#define BRCMF_C_GET_SRL 31
#define BRCMF_C_GET_LRL 33
#define BRCMF_C_GET_RADIO 37
#define BRCMF_C_SET_RADIO 38
#define BRCMF_C_GET_PHYTYPE 39
#define BRCMF_C_SET_KEY 45
#define BRCMF_C_SET_PASSIVE_SCAN 49
#define BRCMF_C_SCAN 50
#define BRCMF_C_SCAN_RESULTS 51
#define BRCMF_C_DISASSOC 52
#define BRCMF_C_REASSOC 53
#define BRCMF_C_SET_ROAM_TRIGGER 55
#define BRCMF_C_SET_ROAM_DELTA 57
#define BRCMF_C_GET_DTIMPRD 77
#define BRCMF_C_SET_COUNTRY 84
#define BRCMF_C_GET_PM 85
#define BRCMF_C_SET_PM 86
#define BRCMF_C_GET_AP 117
#define BRCMF_C_SET_AP 118
#define BRCMF_C_GET_RSSI 127
#define BRCMF_C_GET_WSEC 133
#define BRCMF_C_SET_WSEC 134
#define BRCMF_C_GET_PHY_NOISE 135
#define BRCMF_C_GET_BSS_INFO 136
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201
#define BRCMF_C_GET_VALID_CHANNELS 217
#define BRCMF_C_GET_KEY_PRIMARY 235
#define BRCMF_C_SET_KEY_PRIMARY 236
#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258
#define BRCMF_C_GET_VAR 262
#define BRCMF_C_SET_VAR 263
/* phy types (returned by WLC_GET_PHYTPE) */
#define WLC_PHY_TYPE_A 0
#define WLC_PHY_TYPE_B 1
#define WLC_PHY_TYPE_G 2
#define WLC_PHY_TYPE_N 4
#define WLC_PHY_TYPE_LP 5
#define WLC_PHY_TYPE_SSN 6
#define WLC_PHY_TYPE_HT 7
#define WLC_PHY_TYPE_LCN 8
#define WLC_PHY_TYPE_NULL 0xf
#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter, u)
#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
offsetof(struct brcmf_pkt_filter_pattern, mask_and_pattern)
#define BRCMF_EVENTING_MASK_LEN 16
#define TOE_TX_CSUM_OL 0x00000001
#define TOE_RX_CSUM_OL 0x00000002
/* maximum channels returned by the get valid channels iovar */
#define WL_NUMCHANNELS 64
#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */
/* size of brcmf_scan_params not including variable length array */
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
/* masks for channel and ssid count */
#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
#define BRCMF_SCAN_ACTION_START 1
#define BRCMF_SCAN_ACTION_CONTINUE 2
#define WL_SCAN_ACTION_ABORT 3
#define BRCMF_ISCAN_REQ_VERSION 1
/* brcmf_iscan_results status values */
#define BRCMF_SCAN_RESULTS_SUCCESS 0
#define BRCMF_SCAN_RESULTS_PARTIAL 1
#define BRCMF_SCAN_RESULTS_PENDING 2
#define BRCMF_SCAN_RESULTS_ABORTED 3
#define BRCMF_SCAN_RESULTS_NO_MEM 4
#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
#define BRCMF_PRIMARY_KEY (1 << 1) /* primary (ie tx) key */
#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */
/* For supporting multiple interfaces */
#define BRCMF_MAX_IFS 16
#define BRCMF_DEL_IF -0xe
#define BRCMF_BAD_IF -0xf
#define DOT11_BSSTYPE_ANY 2
#define DOT11_MAX_DEFAULT_KEYS 4
#define BRCMF_EVENT_MSG_LINK 0x01
#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
#define BRCMF_EVENT_MSG_GROUP 0x04
struct brcmf_event_msg {
u16 version;
u16 flags;
u32 event_type;
u32 status;
u32 reason;
u32 auth_type;
u32 datalen;
u8 addr[ETH_ALEN];
char ifname[IFNAMSIZ];
} __packed;
struct brcm_ethhdr {
u16 subtype;
u16 length;
u8 version;
u8 oui[3];
u16 usr_subtype;
} __packed;
struct brcmf_event {
struct ethhdr eth;
struct brcm_ethhdr hdr;
struct brcmf_event_msg msg;
} __packed;
struct dngl_stats {
unsigned long rx_packets; /* total packets received */
unsigned long tx_packets; /* total packets transmitted */
unsigned long rx_bytes; /* total bytes received */
unsigned long tx_bytes; /* total bytes transmitted */
unsigned long rx_errors; /* bad packets received */
unsigned long tx_errors; /* packet transmit problems */
unsigned long rx_dropped; /* packets dropped by dongle */
unsigned long tx_dropped; /* packets dropped by dongle */
unsigned long multicast; /* multicast packets received */
};
#define BRCMF_E_SET_SSID 0
#define BRCMF_E_JOIN 1
#define BRCMF_E_START 2
#define BRCMF_E_AUTH 3
#define BRCMF_E_AUTH_IND 4
#define BRCMF_E_DEAUTH 5
#define BRCMF_E_DEAUTH_IND 6
#define BRCMF_E_ASSOC 7
#define BRCMF_E_ASSOC_IND 8
#define BRCMF_E_REASSOC 9
#define BRCMF_E_REASSOC_IND 10
#define BRCMF_E_DISASSOC 11
#define BRCMF_E_DISASSOC_IND 12
#define BRCMF_E_QUIET_START 13
#define BRCMF_E_QUIET_END 14
#define BRCMF_E_BEACON_RX 15
#define BRCMF_E_LINK 16
#define BRCMF_E_MIC_ERROR 17
#define BRCMF_E_NDIS_LINK 18
#define BRCMF_E_ROAM 19
#define BRCMF_E_TXFAIL 20
#define BRCMF_E_PMKID_CACHE 21
#define BRCMF_E_RETROGRADE_TSF 22
#define BRCMF_E_PRUNE 23
#define BRCMF_E_AUTOAUTH 24
#define BRCMF_E_EAPOL_MSG 25
#define BRCMF_E_SCAN_COMPLETE 26
#define BRCMF_E_ADDTS_IND 27
#define BRCMF_E_DELTS_IND 28
#define BRCMF_E_BCNSENT_IND 29
#define BRCMF_E_BCNRX_MSG 30
#define BRCMF_E_BCNLOST_MSG 31
#define BRCMF_E_ROAM_PREP 32
#define BRCMF_E_PFN_NET_FOUND 33
#define BRCMF_E_PFN_NET_LOST 34
#define BRCMF_E_RESET_COMPLETE 35
#define BRCMF_E_JOIN_START 36
#define BRCMF_E_ROAM_START 37
#define BRCMF_E_ASSOC_START 38
#define BRCMF_E_IBSS_ASSOC 39
#define BRCMF_E_RADIO 40
#define BRCMF_E_PSM_WATCHDOG 41
#define BRCMF_E_PROBREQ_MSG 44
#define BRCMF_E_SCAN_CONFIRM_IND 45
#define BRCMF_E_PSK_SUP 46
#define BRCMF_E_COUNTRY_CODE_CHANGED 47
#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48
#define BRCMF_E_ICV_ERROR 49
#define BRCMF_E_UNICAST_DECODE_ERROR 50
#define BRCMF_E_MULTICAST_DECODE_ERROR 51
#define BRCMF_E_TRACE 52
#define BRCMF_E_IF 54
#define BRCMF_E_RSSI 56
#define BRCMF_E_PFN_SCAN_COMPLETE 57
#define BRCMF_E_EXTLOG_MSG 58
#define BRCMF_E_ACTION_FRAME 59
#define BRCMF_E_ACTION_FRAME_COMPLETE 60
#define BRCMF_E_PRE_ASSOC_IND 61
#define BRCMF_E_PRE_REASSOC_IND 62
#define BRCMF_E_CHANNEL_ADOPTED 63
#define BRCMF_E_AP_STARTED 64
#define BRCMF_E_DFS_AP_STOP 65
#define BRCMF_E_DFS_AP_RESUME 66
#define BRCMF_E_RESERVED1 67
#define BRCMF_E_RESERVED2 68
#define BRCMF_E_ESCAN_RESULT 69
#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
#define BRCMF_E_DCS_REQUEST 73
#define BRCMF_E_FIFO_CREDIT_MAP 74
#define BRCMF_E_LAST 75
#define BRCMF_E_STATUS_SUCCESS 0
#define BRCMF_E_STATUS_FAIL 1
#define BRCMF_E_STATUS_TIMEOUT 2
#define BRCMF_E_STATUS_NO_NETWORKS 3
#define BRCMF_E_STATUS_ABORT 4
#define BRCMF_E_STATUS_NO_ACK 5
#define BRCMF_E_STATUS_UNSOLICITED 6
#define BRCMF_E_STATUS_ATTEMPT 7
#define BRCMF_E_STATUS_PARTIAL 8
#define BRCMF_E_STATUS_NEWSCAN 9
#define BRCMF_E_STATUS_NEWASSOC 10
#define BRCMF_E_STATUS_11HQUIET 11
#define BRCMF_E_STATUS_SUPPRESS 12
#define BRCMF_E_STATUS_NOCHANS 13
#define BRCMF_E_STATUS_CS_ABORT 15
#define BRCMF_E_STATUS_ERROR 16
#define BRCMF_E_REASON_INITIAL_ASSOC 0
#define BRCMF_E_REASON_LOW_RSSI 1
#define BRCMF_E_REASON_DEAUTH 2
#define BRCMF_E_REASON_DISASSOC 3
#define BRCMF_E_REASON_BCNS_LOST 4
#define BRCMF_E_REASON_MINTXRATE 9
#define BRCMF_E_REASON_TXFAIL 10
#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
#define BRCMF_E_REASON_DIRECTED_ROAM 6
#define BRCMF_E_REASON_TSPEC_REJECTED 7
#define BRCMF_E_REASON_BETTER_AP 8
#define BRCMF_E_PRUNE_ENCR_MISMATCH 1
#define BRCMF_E_PRUNE_BCAST_BSSID 2
#define BRCMF_E_PRUNE_MAC_DENY 3
#define BRCMF_E_PRUNE_MAC_NA 4
#define BRCMF_E_PRUNE_REG_PASSV 5
#define BRCMF_E_PRUNE_SPCT_MGMT 6
#define BRCMF_E_PRUNE_RADAR 7
#define BRCMF_E_RSN_MISMATCH 8
#define BRCMF_E_PRUNE_NO_COMMON_RATES 9
#define BRCMF_E_PRUNE_BASIC_RATES 10
#define BRCMF_E_PRUNE_CIPHER_NA 12
#define BRCMF_E_PRUNE_KNOWN_STA 13
#define BRCMF_E_PRUNE_WDS_PEER 15
#define BRCMF_E_PRUNE_QBSS_LOAD 16
#define BRCMF_E_PRUNE_HOME_AP 17
#define BRCMF_E_SUP_OTHER 0
#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1
#define BRCMF_E_SUP_BAD_UCAST_WEP128 2
#define BRCMF_E_SUP_BAD_UCAST_WEP40 3
#define BRCMF_E_SUP_UNSUP_KEY_LEN 4
#define BRCMF_E_SUP_PW_KEY_CIPHER 5
#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6
#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7
#define BRCMF_E_SUP_NO_INSTALL_FLAG 8
#define BRCMF_E_SUP_MSG3_NO_GTK 9
#define BRCMF_E_SUP_GRP_KEY_CIPHER 10
#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11
#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12
#define BRCMF_E_SUP_SEND_FAIL 13
#define BRCMF_E_SUP_DEAUTH 14
#define BRCMF_E_IF_ADD 1
#define BRCMF_E_IF_DEL 2
#define BRCMF_E_IF_CHANGE 3
#define BRCMF_E_IF_ROLE_STA 0
#define BRCMF_E_IF_ROLE_AP 1
#define BRCMF_E_IF_ROLE_WDS 2
#define BRCMF_E_LINK_BCN_LOSS 1
#define BRCMF_E_LINK_DISASSOC 2
#define BRCMF_E_LINK_ASSOC_REC 3
#define BRCMF_E_LINK_BSSCFG_DIS 4
/* The level of bus communication with the dongle */
enum brcmf_bus_state {
BRCMF_BUS_DOWN, /* Not ready for frame transfers */
BRCMF_BUS_LOAD, /* Download access only (CPU reset) */
BRCMF_BUS_DATA /* Ready for frame transfers */
};
/* Pattern matching filter. Specifies an offset within received packets to
* start matching, the pattern to match, the size of the pattern, and a bitmask
* that indicates which bits within the pattern should be matched.
*/
struct brcmf_pkt_filter_pattern {
u32 offset; /* Offset within received packet to start pattern matching.
* Offset '0' is the first byte of the ethernet header.
*/
u32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
u8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts
* at offset 0. Pattern immediately follows mask.
*/
};
/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
struct brcmf_pkt_filter {
u32 id; /* Unique filter id, specified by app. */
u32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
u32 negate_match; /* Negate the result of filter matches */
union { /* Filter definitions */
struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */
} u;
};
/* IOVAR "pkt_filter_enable" parameter. */
struct brcmf_pkt_filter_enable {
u32 id; /* Unique filter id */
u32 enable; /* Enable/disable bool */
};
/* BSS info structure
* Applications MUST CHECK ie_offset field and length field to access IEs and
* next bss_info structure in a vector (in struct brcmf_scan_results)
*/
struct brcmf_bss_info {
u32 version; /* version field */
u32 length; /* byte length of data in this record,
* starting at version and including IEs
*/
u8 BSSID[ETH_ALEN];
u16 beacon_period; /* units are Kusec */
u16 capability; /* Capability information */
u8 SSID_len;
u8 SSID[32];
struct {
uint count; /* # rates in this set */
u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
} rateset; /* supported rates */
chanspec_t chanspec; /* chanspec for bss */
u16 atim_window; /* units are Kusec */
u8 dtim_period; /* DTIM period */
s16 RSSI; /* receive signal strength (in dBm) */
s8 phy_noise; /* noise (in dBm) */
u8 n_cap; /* BSS is 802.11N Capable */
u32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */
u8 ctl_ch; /* 802.11N BSS control channel number */
u32 reserved32[1]; /* Reserved for expansion of BSS properties */
u8 flags; /* flags */
u8 reserved[3]; /* Reserved for expansion of BSS properties */
u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
u16 ie_offset; /* offset at which IEs start, from beginning */
u32 ie_length; /* byte length of Information Elements */
s16 SNR; /* average SNR of during frame reception */
/* Add new fields here */
/* variable length Information Elements */
};
struct brcmf_ssid {
u32 SSID_len;
unsigned char SSID[32];
};
struct brcmf_scan_params {
struct brcmf_ssid ssid; /* default: {0, ""} */
u8 bssid[ETH_ALEN]; /* default: bcast */
s8 bss_type; /* default: any,
* DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
*/
u8 scan_type; /* flags, 0 use default */
s32 nprobes; /* -1 use default, number of probes per channel */
s32 active_time; /* -1 use default, dwell time per channel for
* active scanning
*/
s32 passive_time; /* -1 use default, dwell time per channel
* for passive scanning
*/
s32 home_time; /* -1 use default, dwell time for the home channel
* between channel scans
*/
s32 channel_num; /* count of channels and ssids that follow
*
* low half is count of channels in
* channel_list, 0 means default (use all
* available channels)
*
* high half is entries in struct brcmf_ssid
* array that follows channel_list, aligned for
* s32 (4 bytes) meaning an odd channel count
* implies a 2-byte pad between end of
* channel_list and first ssid
*
* if ssid count is zero, single ssid in the
* fixed parameter portion is assumed, otherwise
* ssid in the fixed portion is ignored
*/
u16 channel_list[1]; /* list of chanspecs */
};
/* incremental scan struct */
struct brcmf_iscan_params {
u32 version;
u16 action;
u16 scan_duration;
struct brcmf_scan_params params;
};
/* 3 fields + size of brcmf_scan_params, not including variable length array */
#define BRCMF_ISCAN_PARAMS_FIXED_SIZE \
(offsetof(struct brcmf_iscan_params, params) + \
sizeof(struct brcmf_ssid))
struct brcmf_scan_results {
u32 buflen;
u32 version;
u32 count;
struct brcmf_bss_info bss_info[1];
};
/* used for association with a specific BSSID and chanspec list */
struct brcmf_assoc_params {
u8 bssid[ETH_ALEN]; /* 00:00:00:00:00:00: broadcast scan */
s32 chanspec_num; /* 0: all available channels,
* otherwise count of chanspecs in chanspec_list
*/
chanspec_t chanspec_list[1]; /* list of chanspecs */
};
#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
(sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t))
/* used for join with or without a specific bssid and channel list */
struct brcmf_join_params {
struct brcmf_ssid ssid;
struct brcmf_assoc_params params;
};
/* size of brcmf_scan_results not including variable length array */
#define BRCMF_SCAN_RESULTS_FIXED_SIZE \
(sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info))
/* incremental scan results struct */
struct brcmf_iscan_results {
u32 status;
struct brcmf_scan_results results;
};
/* size of brcmf_iscan_results not including variable length array */
#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
(BRCMF_SCAN_RESULTS_FIXED_SIZE + \
offsetof(struct brcmf_iscan_results, results))
struct brcmf_wsec_key {
u32 index; /* key index */
u32 len; /* key length */
u8 data[WLAN_MAX_KEY_LEN]; /* key data */
u32 pad_1[18];
u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
u32 flags; /* misc flags */
u32 pad_2[2];
int pad_3;
int iv_initialized; /* has IV been initialized already? */
int pad_4;
/* Rx IV */
struct {
u32 hi; /* upper 32 bits of IV */
u16 lo; /* lower 16 bits of IV */
} rxiv;
u32 pad_5[2];
u8 ea[ETH_ALEN]; /* per station */
};
/* Used to get specific STA parameters */
struct brcmf_scb_val {
u32 val;
u8 ea[ETH_ALEN];
};
/* channel encoding */
struct brcmf_channel_info {
int hw_channel;
int target_channel;
int scan_channel;
};
/* Linux network driver ioctl encoding */
struct brcmf_ioctl {
uint cmd; /* common ioctl definition */
void *buf; /* pointer to user buffer */
uint len; /* length of user buffer */
u8 set; /* get or set request (optional) */
uint used; /* bytes read or written (optional) */
uint needed; /* bytes needed (optional) */
};
/* Forward decls for struct brcmf_pub (see below) */
struct brcmf_bus; /* device bus info */
struct brcmf_proto; /* device communication protocol info */
struct brcmf_info; /* device driver info */
/* Common structure for module and instance linkage */
struct brcmf_pub {
/* Linkage ponters */
struct brcmf_bus *bus;
struct brcmf_proto *prot;
struct brcmf_info *info;
/* Internal brcmf items */
bool up; /* Driver up/down (to OS) */
bool txoff; /* Transmit flow-controlled */
bool dongle_reset; /* true = DEVRESET put dongle into reset */
enum brcmf_bus_state busstate;
uint hdrlen; /* Total BRCMF header length (proto + bus) */
uint maxctl; /* Max size rxctl request from proto to bus */
uint rxsz; /* Rx buffer size bus module should use */
u8 wme_dp; /* wme discard priority */
/* Dongle media info */
bool iswl; /* Dongle-resident driver is wl */
unsigned long drv_version; /* Version of dongle-resident driver */
u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
struct dngl_stats dstats; /* Stats for dongle-based data */
/* Additional stats for the bus level */
unsigned long tx_packets; /* Data packets sent to dongle */
unsigned long tx_multicast; /* Multicast data packets sent to dongle */
unsigned long tx_errors; /* Errors in sending data to dongle */
unsigned long tx_ctlpkts; /* Control packets sent to dongle */
unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */
unsigned long rx_packets; /* Packets sent up the network interface */
unsigned long rx_multicast; /* Multicast packets sent up the network
interface */
unsigned long rx_errors; /* Errors processing rx data packets */
unsigned long rx_ctlpkts; /* Control frames processed from dongle */
unsigned long rx_ctlerrs; /* Errors in processing rx control frames */
unsigned long rx_dropped; /* Packets dropped locally (no memory) */
unsigned long rx_flushed; /* Packets flushed due to
unscheduled sendup thread */
unsigned long wd_dpc_sched; /* Number of times dpc scheduled by
watchdog timer */
unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead
was used. */
unsigned long tx_realloc; /* Number of tx packets we had to realloc for
headroom */
unsigned long fc_packets; /* Number of flow control pkts recvd */
/* Last error return */
int bcmerror;
uint tickcnt;
/* Last error from dongle */
int dongle_error;
/* Suspend disable flag flag */
int suspend_disable_flag; /* "1" to disable all extra powersaving
during suspend */
int in_suspend; /* flag set to 1 when early suspend called */
int dtim_skip; /* dtim skip , default 0 means wake each dtim */
/* Pkt filter defination */
char *pktfilter[100];
int pktfilter_count;
u8 country_code[BRCM_CNTRY_BUF_SZ];
char eventmask[BRCMF_EVENTING_MASK_LEN];
};
struct brcmf_if_event {
u8 ifidx;
u8 action;
u8 flags;
u8 bssidx;
};
struct brcmf_timeout {
u32 limit; /* Expiration time (usec) */
u32 increment; /* Current expiration increment (usec) */
u32 elapsed; /* Current elapsed time (usec) */
u32 tick; /* O/S tick time (usec) */
};
struct bcmevent_name {
uint event;
const char *name;
};
#if defined(CONFIG_PM_SLEEP)
extern atomic_t brcmf_mmc_suspend;
#define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
#define _BRCMF_PM_RESUME_WAIT(a, b) do { \
int retry = 0; \
while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \
wait_event_timeout(a, false, HZ/100); \
} \
} while (0)
#define BRCMF_PM_RESUME_WAIT(a) _BRCMF_PM_RESUME_WAIT(a, 30)
#define BRCMF_PM_RESUME_RETURN_ERROR(a) \
do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0)
#define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
uint countdown = (us) + 9999; \
while ((exp) && (countdown >= 10000)) { \
wait_event_timeout(a, false, HZ/100); \
countdown -= 10000; \
} \
} while (0)
#else
#define BRCMF_PM_RESUME_WAIT_INIT(a)
#define BRCMF_PM_RESUME_WAIT(a)
#define BRCMF_PM_RESUME_RETURN_ERROR(a)
#define BRCMF_SPINWAIT_SLEEP_INIT(a)
#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
uint countdown = (us) + 9; \
while ((exp) && (countdown >= 10)) { \
udelay(10); \
countdown -= 10; \
} \
} while (0)
#endif /* defined(CONFIG_PM_SLEEP) */
/*
* Insmod parameters for debug/test
*/
/* Use interrupts */
extern uint brcmf_intr;
/* Use polling */
extern uint brcmf_poll;
/* ARP offload agent mode */
extern uint brcmf_arp_mode;
/* ARP offload enable */
extern uint brcmf_arp_enable;
/* Pkt filte enable control */
extern uint brcmf_pkt_filter_enable;
/* Pkt filter init setup */
extern uint brcmf_pkt_filter_init;
/* Pkt filter mode control */
extern uint brcmf_master_mode;
/* Roaming mode control */
extern uint brcmf_roam;
/* Roaming mode control */
extern uint brcmf_radio_up;
/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
extern int brcmf_idletime;
#define BRCMF_IDLETIME_TICKS 1
/* SDIO Drive Strength */
extern uint brcmf_sdiod_drive_strength;
/* Override to force tx queueing all the time */
extern uint brcmf_force_tx_queueing;
#ifdef SDTEST
/* Echo packet generator (SDIO), pkts/s */
extern uint brcmf_pktgen;
/* Echo packet len (0 => sawtooth, max 1800) */
extern uint brcmf_pktgen_len;
#define BRCMF_MAX_PKTGEN_LEN 1800
#endif
extern const struct bcmevent_name bcmevent_names[];
extern const int bcmevent_names_size;
static inline void MUTEX_LOCK_INIT(struct brcmf_pub *drvr)
{
}
static inline void MUTEX_LOCK(struct brcmf_pub *drvr)
{
}
static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr)
{
}
static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr)
{
}
static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr)
{
}
static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr)
{
}
static inline void MUTEX_LOCK_WL_SCAN_SET_INIT(void)
{
}
static inline void MUTEX_LOCK_WL_SCAN_SET(void)
{
}
static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
{
}
/* Indication from bus module regarding presence/insertion of dongle.
* Return struct brcmf_pub pointer, used as handle to OS module in later calls.
* Returned structure should have bus and prot pointers filled in.
* bus_hdrlen specifies required headroom for bus module header.
*/
extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus,
uint bus_hdrlen);
extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
extern int brcmf_netdev_wait_pend8021x(struct net_device *dev);
/* Indication from bus module regarding removal/absence of dongle */
extern void brcmf_detach(struct brcmf_pub *drvr);
/* Indication from bus module to change flow-control state */
extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on);
extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
struct sk_buff *pkt, int prec);
/* Receive frame for delivery to OS. Callee disposes of rxp. */
extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
struct sk_buff *rxp, int numpkt);
/* Return pointer to interface name */
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
/* Notify tx completion */
extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
bool success);
/* Query ioctl */
extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
/* OS independent layer functions */
extern int brcmf_os_proto_block(struct brcmf_pub *drvr);
extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr);
extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
bool *pending);
extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr);
extern unsigned int brcmf_os_get_ioctl_resp_timeout(void);
extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
#ifdef BCMDBG
extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size);
#endif /* BCMDBG */
extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
void *pktdata, struct brcmf_event_msg *,
void **data_ptr);
extern void brcmf_c_init(void);
extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle,
char *name, u8 *mac_addr, u32 flags, u8 bssidx);
extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
/* Send packet to dongle via data channel */
extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
struct sk_buff *pkt);
extern int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag);
extern int brcmf_bus_start(struct brcmf_pub *drvr);
extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
int enable, int master_mode);
/* Linux network driver ioctl encoding */
struct brcmf_c_ioctl {
uint cmd; /* common ioctl definition */
void *buf; /* pointer to user buffer */
uint len; /* length of user buffer */
bool set; /* get or set request (optional) */
uint used; /* bytes read or written (optional) */
uint needed; /* bytes needed (optional) */
uint driver; /* to identify target driver */
};
/* per-driver magic numbers */
#define BRCMF_IOCTL_MAGIC 0x00444944
/* bump this number if you change the ioctl interface */
#define BRCMF_IOCTL_VERSION 1
#define BRCMF_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
/* common ioctl definitions */
#define BRCMF_GET_MAGIC 0
#define BRCMF_GET_VERSION 1
#define BRCMF_GET_VAR 2
#define BRCMF_SET_VAR 3
/* message levels */
#define BRCMF_ERROR_VAL 0x0001
#define BRCMF_TRACE_VAL 0x0002
#define BRCMF_INFO_VAL 0x0004
#define BRCMF_DATA_VAL 0x0008
#define BRCMF_CTL_VAL 0x0010
#define BRCMF_TIMER_VAL 0x0020
#define BRCMF_HDRS_VAL 0x0040
#define BRCMF_BYTES_VAL 0x0080
#define BRCMF_INTR_VAL 0x0100
#define BRCMF_GLOM_VAL 0x0400
#define BRCMF_EVENT_VAL 0x0800
#define BRCMF_BTA_VAL 0x1000
#define BRCMF_ISCAN_VAL 0x2000
#ifdef SDTEST
/* For pktgen iovar */
struct brcmf_pktgen {
uint version; /* To allow structure change tracking */
uint freq; /* Max ticks between tx/rx attempts */
uint count; /* Test packets to send/rcv each attempt */
uint print; /* Print counts every <print> attempts */
uint total; /* Total packets (or bursts) */
uint minlen; /* Minimum length of packets to send */
uint maxlen; /* Maximum length of packets to send */
uint numsent; /* Count of test packets sent */
uint numrcvd; /* Count of test packets received */
uint numfail; /* Count of test send failures */
uint mode; /* Test mode (type of test packets) */
uint stop; /* Stop after this many tx failures */
};
/* Version in case structure changes */
#define BRCMF_PKTGEN_VERSION 2
/* Type of test packets to use */
#define BRCMF_PKTGEN_ECHO 1 /* Send echo requests */
#define BRCMF_PKTGEN_SEND 2 /* Send discard packets */
#define BRCMF_PKTGEN_RXBURST 3 /* Request dongle send N packets */
#define BRCMF_PKTGEN_RECV 4 /* Continuous rx from continuous
tx dongle */
#endif /* SDTEST */
/* Enter idle immediately (no timeout) */
#define BRCMF_IDLE_IMMEDIATE (-1)
/* Values for idleclock iovar: other values are the sd_divisor to use
when idle */
#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change
when idle */
#endif /* _BRCMF_H_ */

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCMF_BUS_H_
#define _BRCMF_BUS_H_
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef BRCMF_SDALIGN
#define BRCMF_SDALIGN 32
#endif
#if !ISPOWEROF2(BRCMF_SDALIGN)
#error BRCMF_SDALIGN is not a power of 2!
#endif
/*
* Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
*/
/* dongle ram module parameter */
extern int brcmf_dongle_memsize;
/* Tx/Rx bounds module parameters */
extern uint brcmf_txbound;
extern uint brcmf_rxbound;
/* Watchdog timer interval */
extern uint brcmf_watchdog_ms;
/* Indicate (dis)interest in finding dongles. */
extern int brcmf_bus_register(void);
extern void brcmf_bus_unregister(void);
/* Stop bus module: clear pending frames, disable data flow */
extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex);
/* Initialize bus module: prepare for communication w/dongle */
extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex);
/* Send a data frame to the dongle. Callee disposes of txp. */
extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp);
/* Send/receive a control message to/from the dongle.
* Expects caller to enforce a single outstanding transaction.
*/
extern int
brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
extern int
brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
/* Check for and handle local prot-specific iovar commands */
extern int brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
void *params, int plen, void *arg, int len,
bool set);
/* Add bus dump output to a buffer */
extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr,
struct brcmu_strbuf *strbuf);
/* Clear any bus counters */
extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr);
extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick);
#endif /* _BRCMF_BUS_H_ */

View File

@ -1,502 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
#include <defs.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
#include "dhd.h"
#include "dhd_proto.h"
#include "dhd_bus.h"
#include "dhd_dbg.h"
struct brcmf_proto_cdc_ioctl {
u32 cmd; /* ioctl command value */
u32 len; /* lower 16: output buflen;
* upper 16: input buflen (excludes header) */
u32 flags; /* flag defns given below */
u32 status; /* status code returned from the device */
};
/* Max valid buffer size that can be sent to the dongle */
#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
/* CDC flag definitions */
#define CDCF_IOC_ERROR 0x01 /* 1=ioctl cmd failed */
#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
#define CDCF_IOC_IF_SHIFT 12
#define CDCF_IOC_ID_MASK 0xFFFF0000 /* id an ioctl pairing */
#define CDCF_IOC_ID_SHIFT 16 /* ID Mask shift bits */
#define CDC_IOC_ID(flags) \
(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
#define CDC_SET_IF_IDX(hdr, idx) \
((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
((idx) << CDCF_IOC_IF_SHIFT)))
/*
* BDC header - Broadcom specific extension of CDC.
* Used on data packets to convey priority across USB.
*/
#define BDC_HEADER_LEN 4
#define BDC_PROTO_VER 1 /* Protocol version */
#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */
#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
#define BDC_PRIORITY_MASK 0x7
#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */
#define BDC_FLAG2_IF_SHIFT 0
#define BDC_GET_IF_IDX(hdr) \
((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
#define BDC_SET_IF_IDX(hdr, idx) \
((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
((idx) << BDC_FLAG2_IF_SHIFT)))
struct brcmf_proto_bdc_header {
u8 flags;
u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */
u8 flags2;
u8 rssi;
};
#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE
* (amount of header tha might be added)
* plus any space that might be needed
* for alignment padding.
*/
#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
* round off at the end of buffer
*/
struct brcmf_proto {
u16 reqid;
u8 pending;
u32 lastcmd;
u8 bus_header[BUS_HEADER_LEN];
struct brcmf_proto_cdc_ioctl msg;
unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN];
};
static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
{
struct brcmf_proto *prot = drvr->prot;
int len = le32_to_cpu(prot->msg.len) +
sizeof(struct brcmf_proto_cdc_ioctl);
BRCMF_TRACE(("%s: Enter\n", __func__));
/* NOTE : cdc->msg.len holds the desired length of the buffer to be
* returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
* is actually sent to the dongle
*/
if (len > CDC_MAX_MSG_SIZE)
len = CDC_MAX_MSG_SIZE;
/* Send request */
return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg,
len);
}
static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
{
int ret;
struct brcmf_proto *prot = drvr->prot;
BRCMF_TRACE(("%s: Enter\n", __func__));
do {
ret = brcmf_sdbrcm_bus_rxctl(drvr->bus,
(unsigned char *)&prot->msg,
len + sizeof(struct brcmf_proto_cdc_ioctl));
if (ret < 0)
break;
} while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
return ret;
}
int
brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
void *buf, uint len)
{
struct brcmf_proto *prot = drvr->prot;
struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
void *info;
int ret = 0, retries = 0;
u32 id, flags = 0;
BRCMF_TRACE(("%s: Enter\n", __func__));
BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
/* Respond "bcmerror" and "bcmerrorstr" with local cache */
if (cmd == BRCMF_C_GET_VAR && buf) {
if (!strcmp((char *)buf, "bcmerrorstr")) {
strncpy((char *)buf, "bcm_error",
BCME_STRLEN);
goto done;
} else if (!strcmp((char *)buf, "bcmerror")) {
*(int *)buf = drvr->dongle_error;
goto done;
}
}
memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
CDC_SET_IF_IDX(msg, ifidx);
msg->flags = cpu_to_le32(msg->flags);
if (buf)
memcpy(prot->buf, buf, len);
ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0) {
BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg "
"failed w/status %d\n", ret));
goto done;
}
retry:
/* wait for interrupt and get first fragment */
ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
if (ret < 0)
goto done;
flags = le32_to_cpu(msg->flags);
id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
if ((id < prot->reqid) && (++retries < RETRIES))
goto retry;
if (id != prot->reqid) {
BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
brcmf_ifname(drvr, ifidx), __func__, id,
prot->reqid));
ret = -EINVAL;
goto done;
}
/* Check info buffer */
info = (void *)&msg[1];
/* Copy info buffer */
if (buf) {
if (ret < (int)len)
len = ret;
memcpy(buf, info, len);
}
/* Check the ERROR flag */
if (flags & CDCF_IOC_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
drvr->dongle_error = ret;
}
done:
return ret;
}
int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
void *buf, uint len)
{
struct brcmf_proto *prot = drvr->prot;
struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
int ret = 0;
u32 flags, id;
BRCMF_TRACE(("%s: Enter\n", __func__));
BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
msg->cmd = cpu_to_le32(cmd);
msg->len = cpu_to_le32(len);
msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
CDC_SET_IF_IDX(msg, ifidx);
msg->flags = cpu_to_le32(msg->flags);
if (buf)
memcpy(prot->buf, buf, len);
ret = brcmf_proto_cdc_msg(drvr);
if (ret < 0)
goto done;
ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
if (ret < 0)
goto done;
flags = le32_to_cpu(msg->flags);
id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
if (id != prot->reqid) {
BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
brcmf_ifname(drvr, ifidx), __func__, id,
prot->reqid));
ret = -EINVAL;
goto done;
}
/* Check the ERROR flag */
if (flags & CDCF_IOC_ERROR) {
ret = le32_to_cpu(msg->status);
/* Cache error from dongle */
drvr->dongle_error = ret;
}
done:
return ret;
}
int
brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc,
void *buf, int len)
{
struct brcmf_proto *prot = drvr->prot;
int ret = -1;
if (drvr->busstate == BRCMF_BUS_DOWN) {
BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
__func__));
return ret;
}
brcmf_os_proto_block(drvr);
BRCMF_TRACE(("%s: Enter\n", __func__));
if (len > BRCMF_C_IOCTL_MAXLEN)
goto done;
if (prot->pending == true) {
BRCMF_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
"lastcmd=0x%x (%lu)\n",
ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
(unsigned long)prot->lastcmd));
if ((ioc->cmd == BRCMF_C_SET_VAR) ||
(ioc->cmd == BRCMF_C_GET_VAR))
BRCMF_TRACE(("iovar cmd=%s\n", (char *)buf));
goto done;
}
prot->pending = true;
prot->lastcmd = ioc->cmd;
if (ioc->set)
ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd,
buf, len);
else {
ret = brcmf_proto_cdc_query_ioctl(drvr, ifidx, ioc->cmd,
buf, len);
if (ret > 0)
ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl);
}
/* Too many programs assume ioctl() returns 0 on success */
if (ret >= 0)
ret = 0;
else {
struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
/* len == needed when set/query fails from dongle */
ioc->needed = le32_to_cpu(msg->len);
}
/* Intercept the wme_dp ioctl here */
if (!ret && ioc->cmd == BRCMF_C_SET_VAR &&
!strcmp(buf, "wme_dp")) {
int slen, val = 0;
slen = strlen("wme_dp") + 1;
if (len >= (int)(slen + sizeof(int)))
memcpy(&val, (char *)buf + slen, sizeof(int));
drvr->wme_dp = (u8) le32_to_cpu(val);
}
prot->pending = false;
done:
brcmf_os_proto_unblock(drvr);
return ret;
}
#define PKTSUMNEEDED(skb) \
(((struct sk_buff *)(skb))->ip_summed == CHECKSUM_PARTIAL)
#define PKTSETSUMGOOD(skb, x) \
(((struct sk_buff *)(skb))->ip_summed = \
((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
{
brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid);
}
void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
struct sk_buff *pktbuf)
{
struct brcmf_proto_bdc_header *h;
BRCMF_TRACE(("%s: Enter\n", __func__));
/* Push BDC header used to convey priority for buses that don't */
skb_push(pktbuf, BDC_HEADER_LEN);
h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
if (PKTSUMNEEDED(pktbuf))
h->flags |= BDC_FLAG_SUM_NEEDED;
h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
h->flags2 = 0;
h->rssi = 0;
BDC_SET_IF_IDX(h, ifidx);
}
int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
struct sk_buff *pktbuf)
{
struct brcmf_proto_bdc_header *h;
BRCMF_TRACE(("%s: Enter\n", __func__));
/* Pop BDC header used to convey priority for buses that don't */
if (pktbuf->len < BDC_HEADER_LEN) {
BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
pktbuf->len, BDC_HEADER_LEN));
return -EBADE;
}
h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
*ifidx = BDC_GET_IF_IDX(h);
if (*ifidx >= BRCMF_MAX_IFS) {
BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n",
__func__, *ifidx));
return -EBADE;
}
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
BDC_PROTO_VER) {
BRCMF_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
brcmf_ifname(drvr, *ifidx), h->flags));
return -EBADE;
}
if (h->flags & BDC_FLAG_SUM_GOOD) {
BRCMF_INFO(("%s: BDC packet received with good rx-csum, "
"flags 0x%x\n",
brcmf_ifname(drvr, *ifidx), h->flags));
PKTSETSUMGOOD(pktbuf, true);
}
pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
skb_pull(pktbuf, BDC_HEADER_LEN);
return 0;
}
int brcmf_proto_attach(struct brcmf_pub *drvr)
{
struct brcmf_proto *cdc;
cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
if (!cdc) {
BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
goto fail;
}
/* ensure that the msg buf directly follows the cdc msg struct */
if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n"));
goto fail;
}
drvr->prot = cdc;
drvr->hdrlen += BDC_HEADER_LEN;
drvr->maxctl = BRCMF_C_IOCTL_MAXLEN +
sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN;
return 0;
fail:
kfree(cdc);
return -ENOMEM;
}
/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */
void brcmf_proto_detach(struct brcmf_pub *drvr)
{
kfree(drvr->prot);
drvr->prot = NULL;
}
void brcmf_proto_dstats(struct brcmf_pub *drvr)
{
/* No stats from dongle added yet, copy bus stats */
drvr->dstats.tx_packets = drvr->tx_packets;
drvr->dstats.tx_errors = drvr->tx_errors;
drvr->dstats.rx_packets = drvr->rx_packets;
drvr->dstats.rx_errors = drvr->rx_errors;
drvr->dstats.rx_dropped = drvr->rx_dropped;
drvr->dstats.multicast = drvr->rx_multicast;
return;
}
int brcmf_proto_init(struct brcmf_pub *drvr)
{
int ret = 0;
char buf[128];
BRCMF_TRACE(("%s: Enter\n", __func__));
brcmf_os_proto_block(drvr);
/* Get the device MAC address */
strcpy(buf, "cur_etheraddr");
ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR,
buf, sizeof(buf));
if (ret < 0) {
brcmf_os_proto_unblock(drvr);
return ret;
}
memcpy(drvr->mac, buf, ETH_ALEN);
brcmf_os_proto_unblock(drvr);
ret = brcmf_c_preinit_ioctls(drvr);
/* Always assumes wl for now */
drvr->iswl = true;
return ret;
}
void brcmf_proto_stop(struct brcmf_pub *drvr)
{
/* Nothing to do for CDC */
}

File diff suppressed because it is too large Load Diff

View File

@ -1,70 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCMF_DBG_H_
#define _BRCMF_DBG_H_
#if defined(BCMDBG)
#define BRCMF_ERROR(args) \
do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \
printk args; } while (0)
#define BRCMF_TRACE(args) do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \
printk args; } while (0)
#define BRCMF_INFO(args) do {if (brcmf_msg_level & BRCMF_INFO_VAL) \
printk args; } while (0)
#define BRCMF_DATA(args) do {if (brcmf_msg_level & BRCMF_DATA_VAL) \
printk args; } while (0)
#define BRCMF_CTL(args) do {if (brcmf_msg_level & BRCMF_CTL_VAL) \
printk args; } while (0)
#define BRCMF_TIMER(args) do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \
printk args; } while (0)
#define BRCMF_INTR(args) do {if (brcmf_msg_level & BRCMF_INTR_VAL) \
printk args; } while (0)
#define BRCMF_GLOM(args) do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \
printk args; } while (0)
#define BRCMF_EVENT(args) do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \
printk args; } while (0)
#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL)
#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
#else /* (defined BCMDBG) || (defined BCMDBG) */
#define BRCMF_ERROR(args) do {if (net_ratelimit()) printk args; } while (0)
#define BRCMF_TRACE(args)
#define BRCMF_INFO(args)
#define BRCMF_DATA(args)
#define BRCMF_CTL(args)
#define BRCMF_TIMER(args)
#define BRCMF_INTR(args)
#define BRCMF_GLOM(args)
#define BRCMF_EVENT(args)
#define BRCMF_DATA_ON() 0
#define BRCMF_CTL_ON() 0
#define BRCMF_HDRS_ON() 0
#define BRCMF_BYTES_ON() 0
#define BRCMF_GLOM_ON() 0
#endif /* defined(BCMDBG) */
extern int brcmf_msg_level;
#endif /* _BRCMF_DBG_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCMF_PROTO_H_
#define _BRCMF_PROTO_H_
#ifndef IOCTL_RESP_TIMEOUT
#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
#endif
#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */
#endif
/*
* Exported from the brcmf protocol module (brcmf_cdc)
*/
/* Linkage, sets prot link and updates hdrlen in pub */
extern int brcmf_proto_attach(struct brcmf_pub *drvr);
/* Unlink, frees allocated protocol memory (including brcmf_proto) */
extern void brcmf_proto_detach(struct brcmf_pub *drvr);
/* Initialize protocol: sync w/dongle state.
* Sets dongle media info (iswl, drv_version, mac address).
*/
extern int brcmf_proto_init(struct brcmf_pub *drvr);
/* Stop protocol: sync w/dongle state. */
extern void brcmf_proto_stop(struct brcmf_pub *drvr);
/* Add any protocol-specific data header.
* Caller must reserve prot_hdrlen prepend space.
*/
extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
struct sk_buff *txp);
/* Remove any protocol-specific data header. */
extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
struct sk_buff *rxp);
/* Use protocol to issue ioctl to dongle */
extern int brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx,
struct brcmf_ioctl *ioc, void *buf, int len);
/* Add prot dump output to a buffer */
extern void brcmf_proto_dump(struct brcmf_pub *drvr,
struct brcmu_strbuf *strbuf);
/* Update local copy of dongle statistics */
extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc,
void *buf, uint buflen);
extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr);
extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx,
uint cmd, void *buf, uint len);
#endif /* _BRCMF_PROTO_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,347 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_SDH_H_
#define _BRCM_SDH_H_
#include <linux/skbuff.h>
extern const uint brcmf_sdio_msglevel;
#define SDIO_FUNC_0 0
#define SDIO_FUNC_1 1
#define SDIO_FUNC_2 2
#define SDIOD_FBR_SIZE 0x100
/* io_en */
#define SDIO_FUNC_ENABLE_1 0x02
#define SDIO_FUNC_ENABLE_2 0x04
/* io_rdys */
#define SDIO_FUNC_READY_1 0x02
#define SDIO_FUNC_READY_2 0x04
/* intr_status */
#define INTR_STATUS_FUNC1 0x2
#define INTR_STATUS_FUNC2 0x4
/* Maximum number of I/O funcs */
#define SDIOD_MAX_IOFUNCS 7
#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */
/* function 1 miscellaneous registers */
#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */
#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */
#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */
#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */
#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */
#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */
#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */
#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */
#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */
#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */
/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */
#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */
#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */
#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */
#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */
#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */
#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */
#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */
#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */
#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
/* function 1 OCP space */
#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */
#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */
/* some duplication with sbsdpcmdev.h here */
/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */
#define SDIOH_READ 0 /* Read request */
#define SDIOH_WRITE 1 /* Write request */
#define SDIOH_DATA_FIX 0 /* Fixed addressing */
#define SDIOH_DATA_INC 1 /* Incremental addressing */
/* internal return code */
#define SUCCESS 0
#define ERROR 1
/* forward declarations */
struct brcmf_sdio_card;
struct brcmf_sdreg {
int func;
int offset;
int value;
};
struct sdioh_info {
struct osl_info *osh; /* osh handler */
bool client_intr_enabled; /* interrupt connnected flag */
bool intr_handler_valid; /* client driver interrupt handler valid */
void (*intr_handler)(void *); /* registered interrupt handler */
void *intr_handler_arg; /* argument to call interrupt handler */
u16 intmask; /* Current active interrupts */
void *sdos_info; /* Pointer to per-OS private data */
uint irq; /* Client irq */
int intrcount; /* Client interrupts */
bool sd_blockmode; /* sd_blockmode == false => 64 Byte Cmd 53s. */
/* Must be on for sd_multiblock to be effective */
bool use_client_ints; /* If this is false, make sure to restore */
int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
u8 num_funcs; /* Supported funcs on client */
u32 com_cis_ptr;
u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
uint max_dma_len;
uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */
/* SDDMA_DESCRIPTOR SGList[32]; *//* Scatter/Gather DMA List */
};
struct brcmf_sdmmc_instance {
struct sdioh_info *sd;
struct sdio_func *func[SDIOD_MAX_IOFUNCS];
u32 host_claimed;
};
/* Attach and build an interface to the underlying SD host driver.
* - Allocates resources (structs, arrays, mem, OS handles, etc) needed by
* brcmf_sdcard.
* - Returns the sdio card handle and virtual address base for register access.
* The returned handle should be used in all subsequent calls, but the bcmsh
* implementation may maintain a single "default" handle (e.g. the first or
* most recent one) to enable single-instance implementations to pass NULL.
*/
extern struct brcmf_sdio_card*
brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq);
/* Detach - freeup resources allocated in attach */
extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card);
/* Enable/disable SD interrupt */
extern int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card);
extern int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card);
/* Register/deregister device interrupt handler. */
extern int
brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
void (*fn)(void *), void *argh);
extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card);
/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
* fn: function number
* addr: unmodified SDIO-space address
* data: data byte to write
* err: pointer to error code (or NULL)
*/
extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint func,
u32 addr, int *err);
extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint func,
u32 addr, u8 data, int *err);
/* Read/Write 4bytes from/to cfg space */
extern u32
brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
u32 addr, int *err);
extern void brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card,
uint fnc_num, u32 addr,
u32 data, int *err);
/* Read CIS content for specified function.
* fn: function whose CIS is being requested (0 is common CIS)
* cis: pointer to memory location to place results
* length: number of bytes to read
* Internally, this routine uses the values from the cis base regs (0x9-0xB)
* to form an SDIO-space address to read the data from.
*/
extern int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func,
u8 *cis, uint length);
/* Synchronous access to device (client) core registers via CMD53 to F1.
* addr: backplane address (i.e. >= regsva from attach)
* size: register width in bytes (2 or 4)
* data: data for register write
*/
extern u32
brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size);
extern u32
brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
u32 data);
/* Indicate if last reg read/write failed */
extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card);
/* Buffer transfer to/from device (client) core via cmd53.
* fn: function number
* addr: backplane address (i.e. >= regsva from attach)
* flags: backplane width, address increment, sync/async
* buf: pointer to memory data buffer
* nbytes: number of bytes to transfer to/from buf
* pkt: pointer to packet associated with buf (if any)
* complete: callback function for command completion (async only)
* handle: handle for completion callback (first arg in callback)
* Returns 0 or error code.
* NOTE: Async operation is not currently supported.
*/
extern int
brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes, void *pkt,
void (*complete)(void *handle, int status,
bool sync_waiting),
void *handle);
extern int
brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt,
void (*complete)(void *handle, int status,
bool sync_waiting),
void *handle);
/* Flags bits */
#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */
#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */
#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */
/* Pending (non-error) return code */
#define BCME_PENDING 1
/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
* rw: read or write (0/1)
* addr: direct SDIO address
* buf: pointer to memory data buffer
* nbytes: number of bytes to transfer to/from buf
* Returns 0 or error code.
*/
extern int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
u8 *buf, uint nbytes);
/* Issue an abort to the specified function */
extern int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn);
/* Returns the "Device ID" of target device on the SDIO bus. */
extern int brcmf_sdcard_query_device(struct brcmf_sdio_card *card);
/* Miscellaneous knob tweaker. */
extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
void *params, int plen, void *arg, int len,
bool set);
/* helper functions */
/* callback functions */
struct brcmf_sdioh_driver {
/* attach to device */
void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
u16 func, uint bustype, u32 regsva, void *param);
/* detach from device */
void (*detach) (void *ch);
};
struct sdioh_info;
/* platform specific/high level functions */
extern int brcmf_sdio_function_init(void);
extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver);
extern void brcmf_sdio_unregister(void);
extern void brcmf_sdio_function_cleanup(void);
extern int brcmf_sdio_probe(struct device *dev);
extern int brcmf_sdio_remove(struct device *dev);
/* Function to return current window addr */
extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card);
/* Allocate/init/free per-OS private data */
extern int brcmf_sdioh_osinit(struct sdioh_info *sd);
extern void brcmf_sdioh_osfree(struct sdioh_info *sd);
/* Core interrupt enable/disable of device interrupts */
extern void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd);
extern void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd);
/* attach, return handler on success, NULL if failed.
* The handler shall be provided by all subsequent calls. No local cache
* cfghdl points to the starting address of pci device mapped memory
*/
extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq);
extern int brcmf_sdioh_detach(struct sdioh_info *si);
extern int
brcmf_sdioh_interrupt_register(struct sdioh_info *si,
void (*sdioh_cb_fn)(void *), void *argh);
extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *si);
/* enable or disable SD interrupt */
extern int
brcmf_sdioh_interrupt_set(struct sdioh_info *si, bool enable_disable);
/* read or write one byte using cmd52 */
extern int
brcmf_sdioh_request_byte(struct sdioh_info *si, uint rw, uint fnc, uint addr,
u8 *byte);
/* read or write 2/4 bytes using cmd53 */
extern int
brcmf_sdioh_request_word(struct sdioh_info *si, uint cmd_type,
uint rw, uint fnc, uint addr,
u32 *word, uint nbyte);
/* read or write any buffer using cmd53 */
extern int
brcmf_sdioh_request_buffer(struct sdioh_info *si, uint pio_dma,
uint fix_inc, uint rw, uint fnc_num,
u32 addr, uint regwidth,
u32 buflen, u8 *buffer, struct sk_buff *pkt);
/* get cis data */
extern int
brcmf_sdioh_cis_read(struct sdioh_info *si, uint fuc, u8 *cis, u32 length);
extern int
brcmf_sdioh_cfg_read(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
extern int
brcmf_sdioh_cfg_write(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
/* handle iovars */
extern int brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
void *params, int plen, void *arg, int len, bool set);
/* Issue abort to the specified function and clear controller as needed */
extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc);
/* Watchdog timer interface for pm ops */
extern void brcmf_sdio_wdtmr_enable(bool enable);
extern uint sd_msglevel; /* Debug message level */
extern struct brcmf_sdmmc_instance *gInstance;
#endif /* _BRCM_SDH_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,356 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _wl_cfg80211_h_
#define _wl_cfg80211_h_
struct brcmf_cfg80211_conf;
struct brcmf_cfg80211_iface;
struct brcmf_cfg80211_priv;
struct brcmf_cfg80211_security;
struct brcmf_cfg80211_ibss;
#define WL_DBG_NONE 0
#define WL_DBG_CONN (1 << 5)
#define WL_DBG_SCAN (1 << 4)
#define WL_DBG_TRACE (1 << 3)
#define WL_DBG_INFO (1 << 1)
#define WL_DBG_ERR (1 << 0)
#define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \
(WL_DBG_SCAN) | (WL_DBG_CONN))
#define WL_ERR(fmt, args...) \
do { \
if (brcmf_dbg_level & WL_DBG_ERR) { \
if (net_ratelimit()) { \
printk(KERN_ERR "ERROR @%s : " fmt, \
__func__, ##args); \
} \
} \
} while (0)
#if (defined BCMDBG)
#define WL_INFO(fmt, args...) \
do { \
if (brcmf_dbg_level & WL_DBG_INFO) { \
if (net_ratelimit()) { \
printk(KERN_ERR "INFO @%s : " fmt, \
__func__, ##args); \
} \
} \
} while (0)
#define WL_TRACE(fmt, args...) \
do { \
if (brcmf_dbg_level & WL_DBG_TRACE) { \
if (net_ratelimit()) { \
printk(KERN_ERR "TRACE @%s : " fmt, \
__func__, ##args); \
} \
} \
} while (0)
#define WL_SCAN(fmt, args...) \
do { \
if (brcmf_dbg_level & WL_DBG_SCAN) { \
if (net_ratelimit()) { \
printk(KERN_ERR "SCAN @%s : " fmt, \
__func__, ##args); \
} \
} \
} while (0)
#define WL_CONN(fmt, args...) \
do { \
if (brcmf_dbg_level & WL_DBG_CONN) { \
if (net_ratelimit()) { \
printk(KERN_ERR "CONN @%s : " fmt, \
__func__, ##args); \
} \
} \
} while (0)
#else /* (defined BCMDBG) */
#define WL_INFO(fmt, args...)
#define WL_TRACE(fmt, args...)
#define WL_SCAN(fmt, args...)
#define WL_CONN(fmt, args...)
#endif /* (defined BCMDBG) */
#define WL_NUM_SCAN_MAX 1
#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used
* for 2.6.33 kernel
* or later
*/
#define WL_SCAN_BUF_MAX (1024 * 8)
#define WL_TLV_INFO_MAX 1024
#define WL_BSS_INFO_MAX 2048
#define WL_ASSOC_INFO_MAX 512 /*
* needs to grab assoc info from dongle to
* report it to cfg80211 through "connect"
* event
*/
#define WL_IOCTL_LEN_MAX 1024
#define WL_EXTRA_BUF_MAX 2048
#define WL_ISCAN_BUF_MAX 2048 /*
* the buf length can be BRCMF_C_IOCTL_MAXLEN
* to reduce iteration
*/
#define WL_ISCAN_TIMER_INTERVAL_MS 3000
#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1)
#define WL_AP_MAX 256 /* virtually unlimitted as long
* as kernel memory allows
*/
#define WL_ROAM_TRIGGER_LEVEL -75
#define WL_ROAM_DELTA 20
#define WL_BEACON_TIMEOUT 3
#define WL_SCAN_CHANNEL_TIME 40
#define WL_SCAN_UNASSOC_TIME 40
#define WL_SCAN_PASSIVE_TIME 120
/* dongle status */
enum wl_status {
WL_STATUS_READY,
WL_STATUS_SCANNING,
WL_STATUS_SCAN_ABORTING,
WL_STATUS_CONNECTING,
WL_STATUS_CONNECTED
};
/* wi-fi mode */
enum wl_mode {
WL_MODE_BSS,
WL_MODE_IBSS,
WL_MODE_AP
};
/* dongle profile list */
enum wl_prof_list {
WL_PROF_MODE,
WL_PROF_SSID,
WL_PROF_SEC,
WL_PROF_IBSS,
WL_PROF_BAND,
WL_PROF_BSSID,
WL_PROF_ACT,
WL_PROF_BEACONINT,
WL_PROF_DTIMPERIOD
};
/* dongle iscan state */
enum wl_iscan_state {
WL_ISCAN_STATE_IDLE,
WL_ISCAN_STATE_SCANING
};
/* dongle configuration */
struct brcmf_cfg80211_conf {
u32 mode; /* adhoc , infrastructure or ap */
u32 frag_threshold;
u32 rts_threshold;
u32 retry_short;
u32 retry_long;
s32 tx_power;
struct ieee80211_channel channel;
};
/* cfg80211 main event loop */
struct brcmf_cfg80211_event_loop {
s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv,
struct net_device *ndev,
const struct brcmf_event_msg *e,
void *data);
};
/* representing interface of cfg80211 plane */
struct brcmf_cfg80211_iface {
struct brcmf_cfg80211_priv *cfg_priv;
};
struct brcmf_cfg80211_dev {
void *driver_data; /* to store cfg80211 object information */
};
/* basic structure of scan request */
struct brcmf_cfg80211_scan_req {
struct brcmf_ssid ssid;
};
/* basic structure of information element */
struct brcmf_cfg80211_ie {
u16 offset;
u8 buf[WL_TLV_INFO_MAX];
};
/* event queue for cfg80211 main event */
struct brcmf_cfg80211_event_q {
struct list_head eq_list;
u32 etype;
struct brcmf_event_msg emsg;
s8 edata[1];
};
/* security information with currently associated ap */
struct brcmf_cfg80211_security {
u32 wpa_versions;
u32 auth_type;
u32 cipher_pairwise;
u32 cipher_group;
u32 wpa_auth;
};
/* ibss information for currently joined ibss network */
struct brcmf_cfg80211_ibss {
u8 beacon_interval; /* in millisecond */
u8 atim; /* in millisecond */
s8 join_only;
u8 band;
u8 channel;
};
/* dongle profile */
struct brcmf_cfg80211_profile {
u32 mode;
struct brcmf_ssid ssid;
u8 bssid[ETH_ALEN];
u16 beacon_interval;
u8 dtim_period;
struct brcmf_cfg80211_security sec;
struct brcmf_cfg80211_ibss ibss;
s32 band;
};
/* dongle iscan event loop */
struct brcmf_cfg80211_iscan_eloop {
s32 (*handler[WL_SCAN_ERSULTS_LAST])
(struct brcmf_cfg80211_priv *cfg_priv);
};
/* dongle iscan controller */
struct brcmf_cfg80211_iscan_ctrl {
struct net_device *dev;
struct timer_list timer;
u32 timer_ms;
u32 timer_on;
s32 state;
struct task_struct *tsk;
struct semaphore sync;
struct brcmf_cfg80211_iscan_eloop el;
void *data;
s8 ioctl_buf[BRCMF_C_IOCTL_SMLEN];
s8 scan_buf[WL_ISCAN_BUF_MAX];
};
/* association inform */
struct brcmf_cfg80211_connect_info {
u8 *req_ie;
s32 req_ie_len;
u8 *resp_ie;
s32 resp_ie_len;
};
/* assoc ie length */
struct brcmf_cfg80211_assoc_ielen {
u32 req_len;
u32 resp_len;
};
/* wpa2 pmk list */
struct brcmf_cfg80211_pmk_list {
pmkid_list_t pmkids;
pmkid_t foo[MAXPMKID - 1];
};
/* dongle private data of cfg80211 interface */
struct brcmf_cfg80211_priv {
struct wireless_dev *wdev; /* representing wl cfg80211 device */
struct brcmf_cfg80211_conf *conf; /* dongle configuration */
struct cfg80211_scan_request *scan_request; /* scan request
object */
struct brcmf_cfg80211_event_loop el; /* main event loop */
struct list_head eq_list; /* used for event queue */
spinlock_t eq_lock; /* for event queue synchronization */
struct mutex usr_sync; /* maily for dongle up/down synchronization */
struct brcmf_scan_results *bss_list; /* bss_list holding scanned
ap information */
struct brcmf_scan_results *scan_results;
struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object
for internal purpose */
struct wl_cfg80211_bss_info *bss_info; /* bss information for
cfg80211 layer */
struct brcmf_cfg80211_ie ie; /* information element object for
internal purpose */
struct semaphore event_sync; /* for synchronization of main event
thread */
struct brcmf_cfg80211_profile *profile; /* holding dongle profile */
struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */
struct brcmf_cfg80211_connect_info conn_info; /* association info */
struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */
struct task_struct *event_tsk; /* task of main event handler thread */
unsigned long status; /* current dongle status */
void *pub;
u32 channel; /* current channel */
bool iscan_on; /* iscan on/off switch */
bool iscan_kickstart; /* indicate iscan already started */
bool active_scan; /* current scan mode */
bool ibss_starter; /* indicates this sta is ibss starter */
bool link_up; /* link/connection up flag */
bool pwr_save; /* indicate whether dongle to support
power save mode */
bool dongle_up; /* indicate whether dongle up or not */
bool roam_on; /* on/off switch for dongle self-roaming */
bool scan_tried; /* indicates if first scan attempted */
u8 *ioctl_buf; /* ioctl buffer */
u8 *extra_buf; /* maily to grab assoc information */
struct dentry *debugfsdir;
u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
};
#define cfg_to_wiphy(w) (w->wdev->wiphy)
#define wiphy_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wiphy_priv(w)))
#define cfg_to_wdev(w) (w->wdev)
#define wdev_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wdev_priv(w)))
#define cfg_to_ndev(w) (w->wdev->netdev)
#define ndev_to_cfg(n) (wdev_to_cfg(n->ieee80211_ptr))
#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data))
#define cfg_to_iscan(w) (w->iscan)
#define cfg_to_conn(w) (&w->conn_info)
static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
struct brcmf_bss_info *bss)
{
return bss = bss ?
(struct brcmf_bss_info *)((unsigned long)bss +
le32_to_cpu(bss->length)) :
list->bss_info;
}
#define for_each_bss(list, bss, __i) \
for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
extern s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data);
extern void brcmf_cfg80211_detach(void);
/* event handler from dongle */
extern void brcmf_cfg80211_event(struct net_device *ndev,
const struct brcmf_event_msg *e, void *data);
extern void brcmf_cfg80211_sdio_func(void *func); /* set sdio function info */
extern struct sdio_func *brcmf_cfg80211_get_sdio_func(void);
extern s32 brcmf_cfg80211_up(void); /* dongle up */
extern s32 brcmf_cfg80211_down(void); /* dongle down */
#endif /* _wl_cfg80211_h_ */

View File

@ -1,58 +0,0 @@
#
# Makefile fragment for Broadcom 802.11n Networking Device Driver
#
# Copyright (c) 2010 Broadcom Corporation
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ccflags-y := \
-DWLC_HIGH \
-DWLC_LOW \
-DSTA \
-DWME \
-DWL11N \
-DDBAND \
-DBCMNVRAMR \
-Idrivers/staging/brcm80211/brcmsmac \
-Idrivers/staging/brcm80211/brcmsmac/phy \
-Idrivers/staging/brcm80211/include
BRCMSMAC_OFILES := \
mac80211_if.o \
ucode_loader.o \
alloc.o \
ampdu.o \
antsel.o \
bmac.o \
channel.o \
main.o \
phy_shim.o \
pmu.o \
rate.o \
stf.o \
aiutils.o \
phy/phy_cmn.o \
phy/phy_lcn.o \
phy/phy_n.o \
phy/phytbl_lcn.o \
phy/phytbl_n.o \
phy/phy_qmath.o \
otp.o \
srom.o \
dma.o \
nicpci.o
MODULEPFX := brcmsmac
obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o
$(MODULEPFX)-objs = $(BRCMSMAC_OFILES)

File diff suppressed because it is too large Load Diff

View File

@ -1,584 +0,0 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_AIUTILS_H_
#define _BRCM_AIUTILS_H_
#include "types.h"
/*
* SOC Interconnect Address Map.
* All regions may not exist on all chips.
*/
/* Physical SDRAM */
#define SI_SDRAM_BASE 0x00000000
/* Host Mode sb2pcitranslation0 (64 MB) */
#define SI_PCI_MEM 0x08000000
#define SI_PCI_MEM_SZ (64 * 1024 * 1024)
/* Host Mode sb2pcitranslation1 (64 MB) */
#define SI_PCI_CFG 0x0c000000
/* Byteswapped Physical SDRAM */
#define SI_SDRAM_SWAPPED 0x10000000
/* Region 2 for sdram (512 MB) */
#define SI_SDRAM_R2 0x80000000
#ifdef SI_ENUM_BASE_VARIABLE
#define SI_ENUM_BASE (sii->pub.si_enum_base)
#else
#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
#endif /* SI_ENUM_BASE_VARIABLE */
/* Wrapper space base */
#define SI_WRAP_BASE 0x18100000
/* each core gets 4Kbytes for registers */
#define SI_CORE_SIZE 0x1000
/*
* Max cores (this is arbitrary, for software
* convenience and could be changed if we
* make any larger chips
*/
#define SI_MAXCORES 16
/* On-chip RAM on chips that also have DDR */
#define SI_FASTRAM 0x19000000
#define SI_FASTRAM_SWAPPED 0x19800000
/* Flash Region 2 (region 1 shadowed here) */
#define SI_FLASH2 0x1c000000
/* Size of Flash Region 2 */
#define SI_FLASH2_SZ 0x02000000
/* ARM Cortex-M3 ROM */
#define SI_ARMCM3_ROM 0x1e000000
/* MIPS Flash Region 1 */
#define SI_FLASH1 0x1fc00000
/* MIPS Size of Flash Region 1 */
#define SI_FLASH1_SZ 0x00400000
/* ARM7TDMI-S ROM */
#define SI_ARM7S_ROM 0x20000000
/* ARM Cortex-M3 SRAM Region 2 */
#define SI_ARMCM3_SRAM2 0x60000000
/* ARM7TDMI-S SRAM Region 2 */
#define SI_ARM7S_SRAM2 0x80000000
/* ARM Flash Region 1 */
#define SI_ARM_FLASH1 0xffff0000
/* ARM Size of Flash Region 1 */
#define SI_ARM_FLASH1_SZ 0x00010000
/* Client Mode sb2pcitranslation2 (1 GB) */
#define SI_PCI_DMA 0x40000000
/* Client Mode sb2pcitranslation2 (1 GB) */
#define SI_PCI_DMA2 0x80000000
/* Client Mode sb2pcitranslation2 size in bytes */
#define SI_PCI_DMA_SZ 0x40000000
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
#define SI_PCIE_DMA_L32 0x00000000
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
#define SI_PCIE_DMA_H32 0x80000000
/* core codes */
#define NODEV_CORE_ID 0x700 /* Invalid coreid */
#define CC_CORE_ID 0x800 /* chipcommon core */
#define ILINE20_CORE_ID 0x801 /* iline20 core */
#define SRAM_CORE_ID 0x802 /* sram core */
#define SDRAM_CORE_ID 0x803 /* sdram core */
#define PCI_CORE_ID 0x804 /* pci core */
#define MIPS_CORE_ID 0x805 /* mips core */
#define ENET_CORE_ID 0x806 /* enet mac core */
#define CODEC_CORE_ID 0x807 /* v90 codec core */
#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */
#define ADSL_CORE_ID 0x809 /* ADSL core */
#define ILINE100_CORE_ID 0x80a /* iline100 core */
#define IPSEC_CORE_ID 0x80b /* ipsec core */
#define UTOPIA_CORE_ID 0x80c /* utopia core */
#define PCMCIA_CORE_ID 0x80d /* pcmcia core */
#define SOCRAM_CORE_ID 0x80e /* internal memory core */
#define MEMC_CORE_ID 0x80f /* memc sdram core */
#define OFDM_CORE_ID 0x810 /* OFDM phy core */
#define EXTIF_CORE_ID 0x811 /* external interface core */
#define D11_CORE_ID 0x812 /* 802.11 MAC core */
#define APHY_CORE_ID 0x813 /* 802.11a phy core */
#define BPHY_CORE_ID 0x814 /* 802.11b phy core */
#define GPHY_CORE_ID 0x815 /* 802.11g phy core */
#define MIPS33_CORE_ID 0x816 /* mips3302 core */
#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */
#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */
#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */
#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */
#define SDIOH_CORE_ID 0x81b /* sdio host core */
#define ROBO_CORE_ID 0x81c /* roboswitch core */
#define ATA100_CORE_ID 0x81d /* parallel ATA core */
#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */
#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */
#define PCIE_CORE_ID 0x820 /* pci express core */
#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */
#define SRAMC_CORE_ID 0x822 /* SRAM controller core */
#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */
#define ARM11_CORE_ID 0x824 /* ARM 1176 core */
#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */
#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */
#define PMU_CORE_ID 0x827 /* PMU core */
#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */
#define SDIOD_CORE_ID 0x829 /* SDIO device core */
#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */
#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */
#define MIPS74K_CORE_ID 0x82c /* mips 74k core */
#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */
#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */
#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */
#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */
#define SC_CORE_ID 0x831 /* shared common core */
#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */
#define SPIH_CORE_ID 0x833 /* SPI host core */
#define I2S_CORE_ID 0x834 /* I2S core */
#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
#define DEF_AI_COMP 0xfff /* Default component, in ai chips it
* maps all unused address ranges
*/
/* chipcommon being the first core: */
#define SI_CC_IDX 0
/* SOC Interconnect types (aka chip types) */
#define SOCI_AI 1
/* Common core control flags */
#define SICF_BIST_EN 0x8000
#define SICF_PME_EN 0x4000
#define SICF_CORE_BITS 0x3ffc
#define SICF_FGC 0x0002
#define SICF_CLOCK_EN 0x0001
/* Common core status flags */
#define SISF_BIST_DONE 0x8000
#define SISF_BIST_ERROR 0x4000
#define SISF_GATED_CLK 0x2000
#define SISF_DMA64 0x1000
#define SISF_CORE_BITS 0x0fff
/* A register that is common to all cores to
* communicate w/PMU regarding clock control.
*/
#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */
/* clk_ctl_st register */
#define CCS_FORCEALP 0x00000001 /* force ALP request */
#define CCS_FORCEHT 0x00000002 /* force HT request */
#define CCS_FORCEILP 0x00000004 /* force ILP request */
#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */
#define CCS_HTAREQ 0x00000010 /* HT Avail Request */
#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */
#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */
#define CCS_ERSRC_REQ_SHIFT 8
#define CCS_ALPAVAIL 0x00010000 /* ALP is available */
#define CCS_HTAVAIL 0x00020000 /* HT is available */
#define CCS_BP_ON_APL 0x00040000 /* RO: running on ALP clock */
#define CCS_BP_ON_HT 0x00080000 /* RO: running on HT clock */
#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */
#define CCS_ERSRC_STS_SHIFT 24
/* HT avail in chipc and pcmcia on 4328a0 */
#define CCS0_HTAVAIL 0x00010000
/* ALP avail in chipc and pcmcia on 4328a0 */
#define CCS0_ALPAVAIL 0x00020000
/* Not really related to SOC Interconnect, but a couple of software
* conventions for the use the flash space:
*/
/* Minumum amount of flash we support */
#define FLASH_MIN 0x00020000 /* Minimum flash size */
/* A boot/binary may have an embedded block that describes its size */
#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */
#define BISZ_MAGIC 0x4249535a /* Marked with value: 'BISZ' */
#define BISZ_MAGIC_IDX 0 /* Word 0: magic */
#define BISZ_TXTST_IDX 1 /* 1: text start */
#define BISZ_TXTEND_IDX 2 /* 2: text end */
#define BISZ_DATAST_IDX 3 /* 3: data start */
#define BISZ_DATAEND_IDX 4 /* 4: data end */
#define BISZ_BSSST_IDX 5 /* 5: bss start */
#define BISZ_BSSEND_IDX 6 /* 6: bss end */
#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */
#define CC_SROM_OTP 0x800 /* SROM/OTP address space */
/* gpiotimerval */
#define GPIO_ONTIME_SHIFT 16
/* Fields in clkdiv */
#define CLKD_OTP 0x000f0000
#define CLKD_OTP_SHIFT 16
/* When Srom support present, fields in sromcontrol */
#define SRC_START 0x80000000
#define SRC_BUSY 0x80000000
#define SRC_OPCODE 0x60000000
#define SRC_OP_READ 0x00000000
#define SRC_OP_WRITE 0x20000000
#define SRC_OP_WRDIS 0x40000000
#define SRC_OP_WREN 0x60000000
#define SRC_OTPSEL 0x00000010
#define SRC_LOCK 0x00000008
#define SRC_SIZE_MASK 0x00000006
#define SRC_SIZE_1K 0x00000000
#define SRC_SIZE_4K 0x00000002
#define SRC_SIZE_16K 0x00000004
#define SRC_SIZE_SHIFT 1
#define SRC_PRESENT 0x00000001
/* 4330 chip-specific ChipStatus register bits */
#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */
#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */
#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */
#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */
#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */
#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */
#define CST4330_OTP_PRESENT 0x00000010
#define CST4330_LPO_AUTODET_EN 0x00000020
#define CST4330_ARMREMAP_0 0x00000040
#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */
#define CST4330_ILPDIV_EN 0x00000100
#define CST4330_LPO_SEL 0x00000200
#define CST4330_RES_INIT_MODE_SHIFT 10
#define CST4330_RES_INIT_MODE_MASK 0x00000c00
#define CST4330_CBUCK_MODE_SHIFT 12
#define CST4330_CBUCK_MODE_MASK 0x00003000
#define CST4330_CBUCK_POWER_OK 0x00004000
#define CST4330_BB_PLL_LOCKED 0x00008000
/* Package IDs */
#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */
#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */
#define BCM4717_PKG_ID 9 /* 4717 package id */
#define BCM4718_PKG_ID 10 /* 4718 package id */
#define HDLSIM_PKG_ID 14 /* HDL simulator package id */
#define HWSIM_PKG_ID 15 /* Hardware simulator package id */
#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */
/* these are router chips */
#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */
#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */
#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */
#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */
#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */
#define SI_INFO(sih) ((struct si_info *)sih)
#define GOODCOREADDR(x, b) \
(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
IS_ALIGNED((x), SI_CORE_SIZE))
#define GOODREGS(regs) \
((regs) != NULL && IS_ALIGNED((unsigned long)(regs), SI_CORE_SIZE))
#define BADCOREADDR 0
#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES)
#define NOREV -1 /* Invalid rev */
/* Newer chips can access PCI/PCIE and CC core without requiring to change
* PCI BAR0 WIN
*/
#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \
(((si)->pub.buscoretype == PCI_CORE_ID) && \
(si)->pub.buscorerev >= 13))
#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET))
#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET))
/*
* Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
* before after core switching to avoid invalid register accesss inside ISR.
*/
#define INTR_OFF(si, intr_val) \
if ((si)->intrsoff_fn && \
(si)->coreid[(si)->curidx] == (si)->dev_coreid) \
intr_val = (*(si)->intrsoff_fn)((si)->intr_arg)
#define INTR_RESTORE(si, intr_val) \
if ((si)->intrsrestore_fn && \
(si)->coreid[(si)->curidx] == (si)->dev_coreid) \
(*(si)->intrsrestore_fn)((si)->intr_arg, intr_val)
/* dynamic clock control defines */
#define LPOMINFREQ 25000 /* low power oscillator min */
#define LPOMAXFREQ 43000 /* low power oscillator max */
#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
#define PCIMINFREQ 25000000 /* 25 MHz */
#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
#define PCI(si) (((si)->pub.bustype == PCI_BUS) && \
((si)->pub.buscoretype == PCI_CORE_ID))
#define PCIE(si) (((si)->pub.bustype == PCI_BUS) && \
((si)->pub.buscoretype == PCIE_CORE_ID))
#define PCI_FORCEHT(si) \
(PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
/* GPIO Based LED powersave defines */
#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
#ifndef DEFAULT_GPIOTIMERVAL
#define DEFAULT_GPIOTIMERVAL \
((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
#endif
/*
* Data structure to export all chip specific common variables
* public (read-only) portion of aiutils handle returned by si_attach()
*/
struct si_pub {
uint bustype; /* SI_BUS, PCI_BUS */
uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
uint buscorerev; /* buscore rev */
uint buscoreidx; /* buscore index */
int ccrev; /* chip common core rev */
u32 cccaps; /* chip common capabilities */
u32 cccaps_ext; /* chip common capabilities extension */
int pmurev; /* pmu core rev */
u32 pmucaps; /* pmu capabilities */
uint boardtype; /* board type */
uint boardvendor; /* board vendor */
uint boardflags; /* board flags */
uint boardflags2; /* board flags2 */
uint chip; /* chip number */
uint chiprev; /* chip revision */
uint chippkg; /* chip package option */
u32 chipst; /* chip status */
bool issim; /* chip is in simulation or emulation */
uint socirev; /* SOC interconnect rev */
bool pci_pr32414;
};
/*
* Many of the routines below take an 'sih' handle as their first arg.
* Allocate this by calling si_attach(). Free it by calling si_detach().
* At any one time, the sih is logically focused on one particular si core
* (the "current core").
* Use si_setcore() or si_setcoreidx() to change the association to another core
*/
#define BADIDX (SI_MAXCORES + 1)
/* clkctl xtal what flags */
#define XTAL 0x1 /* primary crystal oscillator (2050) */
#define PLL 0x2 /* main chip pll */
/* clkctl clk mode */
#define CLK_FAST 0 /* force fast (pll) clock */
#define CLK_DYNAMIC 2 /* enable dynamic clock control */
/* GPIO usage priorities */
#define GPIO_DRV_PRIORITY 0 /* Driver */
#define GPIO_APP_PRIORITY 1 /* Application */
#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO
* reservation
*/
/* GPIO pull up/down */
#define GPIO_PULLUP 0
#define GPIO_PULLDN 1
/* GPIO event regtype */
#define GPIO_REGEVT 0 /* GPIO register event */
#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */
#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */
/* device path */
#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */
/* SI routine enumeration: to be used by update function with multiple hooks */
#define SI_DOATTACH 1
#define SI_PCIDOWN 2
#define SI_PCIUP 3
/* PMU clock/power control */
#if defined(BCMPMUCTL)
#define PMUCTL_ENAB(sih) (BCMPMUCTL)
#else
#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU)
#endif
/* chipcommon clock/power control (exclusive with PMU's) */
#if defined(BCMPMUCTL) && BCMPMUCTL
#define CCCTL_ENAB(sih) (0)
#define CCPLL_ENAB(sih) (0)
#else
#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL)
#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK)
#endif
typedef void (*gpio_handler_t) (u32 stat, void *arg);
/* External PA enable mask */
#define GPIO_CTRL_EPA_EN_MASK 0x40
#define SI_ERROR(args)
#ifdef BCMDBG
#define SI_MSG(args) printk args
#else
#define SI_MSG(args)
#endif /* BCMDBG */
/* Define SI_VMSG to printf for verbose debugging, but don't check it in */
#define SI_VMSG(args)
#define IS_SIM(chippkg) \
((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
typedef u32(*si_intrsoff_t) (void *intr_arg);
typedef void (*si_intrsrestore_t) (void *intr_arg, u32 arg);
typedef bool(*si_intrsenabled_t) (void *intr_arg);
struct gpioh_item {
void *arg;
bool level;
gpio_handler_t handler;
u32 event;
struct gpioh_item *next;
};
/* misc si info needed by some of the routines */
struct si_info {
struct si_pub pub; /* back plane public state (must be first) */
void *pbus; /* handle to bus (pci/sdio/..) */
uint dev_coreid; /* the core provides driver functions */
void *intr_arg; /* interrupt callback function arg */
si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
void *pch; /* PCI/E core handle */
char *vars;
uint varsz;
void *curmap; /* current regs va */
void *regs[SI_MAXCORES]; /* other regs va */
uint curidx; /* current core index */
uint numcores; /* # discovered cores */
uint coreid[SI_MAXCORES]; /* id of each core */
u32 coresba[SI_MAXCORES]; /* backplane address of each core */
void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */
u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */
u32 coresba_size[SI_MAXCORES]; /* backplane address space size */
u32 coresba2_size[SI_MAXCORES]; /* second address space size */
void *curwrap; /* current wrapper va */
void *wrappers[SI_MAXCORES]; /* other cores wrapper va */
u32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */
u32 cia[SI_MAXCORES]; /* erom cia entry for each core */
u32 cib[SI_MAXCORES]; /* erom cia entry for each core */
u32 oob_router; /* oob router registers for axi */
};
/* AMBA Interconnect exported externs */
extern void ai_scan(struct si_pub *sih, void *regs);
extern uint ai_flag(struct si_pub *sih);
extern void ai_setint(struct si_pub *sih, int siflag);
extern uint ai_coreidx(struct si_pub *sih);
extern uint ai_corevendor(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern bool ai_iscoreup(struct si_pub *sih);
extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
uint val);
extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
extern void ai_core_disable(struct si_pub *sih, u32 bits);
extern int ai_numaddrspaces(struct si_pub *sih);
extern u32 ai_addrspace(struct si_pub *sih, uint asidx);
extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx);
extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val);
/* === exported functions === */
extern struct si_pub *ai_attach(void *regs, uint bustype,
void *sdh, char **vars, uint *varsz);
extern void ai_detach(struct si_pub *sih);
extern bool ai_pci_war16165(struct si_pub *sih);
extern uint ai_coreid(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
uint val);
extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val);
extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
extern bool ai_iscoreup(struct si_pub *sih);
extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit);
extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
extern void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
extern void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
uint *intr_val);
extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val);
extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
extern void ai_core_disable(struct si_pub *sih, u32 bits);
extern u32 ai_alp_clock(struct si_pub *sih);
extern u32 ai_ilp_clock(struct si_pub *sih);
extern void ai_pci_setup(struct si_pub *sih, uint coremask);
extern void ai_setint(struct si_pub *sih, int siflag);
extern bool ai_backplane64(struct si_pub *sih);
extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
void *intrsrestore_fn,
void *intrsenabled_fn, void *intr_arg);
extern void ai_deregister_intr_callback(struct si_pub *sih);
extern void ai_clkctl_init(struct si_pub *sih);
extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
extern bool ai_clkctl_cc(struct si_pub *sih, uint mode);
extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on);
extern bool ai_deviceremoved(struct si_pub *sih);
extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val,
u8 priority);
/* OTP status */
extern bool ai_is_otp_disabled(struct si_pub *sih);
/* SPROM availability */
extern bool ai_is_sprom_available(struct si_pub *sih);
/*
* Build device path. Path size must be >= SI_DEVPATH_BUFSZ.
* The returned path is NULL terminated and has trailing '/'.
* Return 0 on success, nonzero otherwise.
*/
extern int ai_devpath(struct si_pub *sih, char *path, int size);
/* Read variable with prepending the devpath to the name */
extern char *ai_getdevpathvar(struct si_pub *sih, const char *name);
extern int ai_getdevpathintvar(struct si_pub *sih, const char *name);
extern void ai_pci_sleep(struct si_pub *sih);
extern void ai_pci_down(struct si_pub *sih);
extern void ai_pci_up(struct si_pub *sih);
extern int ai_pci_fixcfg(struct si_pub *sih);
extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
/* Enable Ex-PA for 4313 */
extern void ai_epa_4313war(struct si_pub *sih);
char *ai_getnvramflvar(struct si_pub *sih, const char *name);
#endif /* _BRCM_AIUTILS_H_ */

View File

@ -1,275 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <brcmu_utils.h>
#include "types.h"
#include "pub.h"
#include "main.h"
#include "alloc.h"
static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit);
static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg);
static struct brcms_pub *brcms_c_pub_malloc(uint unit,
uint *err, uint devid);
static void brcms_c_pub_mfree(struct brcms_pub *pub);
static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid);
static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid)
{
tunables->ntxd = NTXD;
tunables->nrxd = NRXD;
tunables->rxbufsz = RXBUFSZ;
tunables->nrxbufpost = NRXBUFPOST;
tunables->maxscb = MAXSCB;
tunables->ampdunummpdu = AMPDU_NUM_MPDU;
tunables->maxpktcb = MAXPKTCB;
tunables->maxucodebss = BRCMS_MAX_UCODE_BSS;
tunables->maxucodebss4 = BRCMS_MAX_UCODE_BSS4;
tunables->maxbss = MAXBSS;
tunables->datahiwat = BRCMS_DATAHIWAT;
tunables->ampdudatahiwat = BRCMS_AMPDUDATAHIWAT;
tunables->rxbnd = RXBND;
tunables->txsbnd = TXSBND;
}
static struct brcms_pub *brcms_c_pub_malloc(uint unit, uint *err, uint devid)
{
struct brcms_pub *pub;
pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
if (pub == NULL) {
*err = 1001;
goto fail;
}
pub->tunables = kzalloc(sizeof(struct brcms_tunables), GFP_ATOMIC);
if (pub->tunables == NULL) {
*err = 1028;
goto fail;
}
/* need to init the tunables now */
brcms_c_tunables_init(pub->tunables, devid);
pub->multicast = kzalloc(ETH_ALEN * MAXMULTILIST, GFP_ATOMIC);
if (pub->multicast == NULL) {
*err = 1003;
goto fail;
}
return pub;
fail:
brcms_c_pub_mfree(pub);
return NULL;
}
static void brcms_c_pub_mfree(struct brcms_pub *pub)
{
if (pub == NULL)
return;
kfree(pub->multicast);
kfree(pub->tunables);
kfree(pub);
}
static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
{
struct brcms_bss_cfg *cfg;
cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
if (cfg == NULL)
goto fail;
cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
if (cfg->current_bss == NULL)
goto fail;
return cfg;
fail:
brcms_c_bsscfg_mfree(cfg);
return NULL;
}
static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
{
if (cfg == NULL)
return;
kfree(cfg->maclist);
kfree(cfg->current_bss);
kfree(cfg);
}
static void brcms_c_bsscfg_ID_assign(struct brcms_c_info *wlc,
struct brcms_bss_cfg *bsscfg)
{
bsscfg->ID = wlc->next_bsscfg_ID;
wlc->next_bsscfg_ID++;
}
/*
* The common driver entry routine. Error codes should be unique
*/
struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid)
{
struct brcms_c_info *wlc;
wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
if (wlc == NULL) {
*err = 1002;
goto fail;
}
/* allocate struct brcms_c_pub state structure */
wlc->pub = brcms_c_pub_malloc(unit, err, devid);
if (wlc->pub == NULL) {
*err = 1003;
goto fail;
}
wlc->pub->wlc = wlc;
/* allocate struct brcms_hardware state structure */
wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
if (wlc->hw == NULL) {
*err = 1005;
goto fail;
}
wlc->hw->wlc = wlc;
wlc->hw->bandstate[0] =
kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
if (wlc->hw->bandstate[0] == NULL) {
*err = 1006;
goto fail;
} else {
int i;
for (i = 1; i < MAXBANDS; i++) {
wlc->hw->bandstate[i] = (struct brcms_hw_band *)
((unsigned long)wlc->hw->bandstate[0] +
(sizeof(struct brcms_hw_band) * i));
}
}
wlc->modulecb =
kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
if (wlc->modulecb == NULL) {
*err = 1009;
goto fail;
}
wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
if (wlc->default_bss == NULL) {
*err = 1010;
goto fail;
}
wlc->cfg = brcms_c_bsscfg_malloc(unit);
if (wlc->cfg == NULL) {
*err = 1011;
goto fail;
}
brcms_c_bsscfg_ID_assign(wlc, wlc->cfg);
wlc->wsec_def_keys[0] =
kzalloc(sizeof(struct wsec_key) * BRCMS_DEFAULT_KEYS,
GFP_ATOMIC);
if (wlc->wsec_def_keys[0] == NULL) {
*err = 1015;
goto fail;
} else {
int i;
for (i = 1; i < BRCMS_DEFAULT_KEYS; i++) {
wlc->wsec_def_keys[i] = (struct wsec_key *)
((unsigned long)wlc->wsec_def_keys[0] +
(sizeof(struct wsec_key) * i));
}
}
wlc->protection = kzalloc(sizeof(struct brcms_protection),
GFP_ATOMIC);
if (wlc->protection == NULL) {
*err = 1016;
goto fail;
}
wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
if (wlc->stf == NULL) {
*err = 1017;
goto fail;
}
wlc->bandstate[0] =
kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
if (wlc->bandstate[0] == NULL) {
*err = 1025;
goto fail;
} else {
int i;
for (i = 1; i < MAXBANDS; i++) {
wlc->bandstate[i] = (struct brcms_band *)
((unsigned long)wlc->bandstate[0]
+ (sizeof(struct brcms_band)*i));
}
}
wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
if (wlc->corestate == NULL) {
*err = 1026;
goto fail;
}
wlc->corestate->macstat_snapshot =
kzalloc(sizeof(struct macstat), GFP_ATOMIC);
if (wlc->corestate->macstat_snapshot == NULL) {
*err = 1027;
goto fail;
}
return wlc;
fail:
brcms_c_detach_mfree(wlc);
return NULL;
}
void brcms_c_detach_mfree(struct brcms_c_info *wlc)
{
if (wlc == NULL)
return;
brcms_c_bsscfg_mfree(wlc->cfg);
brcms_c_pub_mfree(wlc->pub);
kfree(wlc->modulecb);
kfree(wlc->default_bss);
kfree(wlc->wsec_def_keys[0]);
kfree(wlc->protection);
kfree(wlc->stf);
kfree(wlc->bandstate[0]);
kfree(wlc->corestate->macstat_snapshot);
kfree(wlc->corestate);
kfree(wlc->hw->bandstate[0]);
kfree(wlc->hw);
/* free the wlc */
kfree(wlc);
wlc = NULL;
}

View File

@ -1,19 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
extern struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err,
uint devid);
extern void brcms_c_detach_mfree(struct brcms_c_info *wlc);

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_AMPDU_H_
#define _BRCM_AMPDU_H_
extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
extern int brcms_c_sendampdu(struct ampdu_info *ampdu,
struct brcms_txq_info *qi,
struct sk_buff **aggp, int prec);
extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
struct sk_buff *p, struct tx_status *txs);
extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu);
#endif /* _BRCM_AMPDU_H_ */

View File

@ -1,311 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/slab.h>
#include <net/mac80211.h>
#include "types.h"
#include "bmac.h"
#include "main.h"
#include "phy_shim.h"
#include "antsel.h"
#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */
#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */
#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */
#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */
#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */
#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */
/* useful macros */
#define BRCMS_ANTSEL_11N_0(ant) ((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
#define BRCMS_ANTSEL_11N_1(ant) (((ant) & ANT_SELCFG_MASK) & 0xf)
#define BRCMS_ANTIDX_11N(ant) (((BRCMS_ANTSEL_11N_0(ant)) << 2) +\
(BRCMS_ANTSEL_11N_1(ant)))
#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
#define BRCMS_ANTSEL_11N(ant) ((ant) & ANT_SELCFG_MASK)
/* antenna switch */
/* defines for no boardlevel antenna diversity */
#define ANT_SELCFG_DEF_2x2 0x01 /* default antenna configuration */
/* 2x3 antdiv defines and tables for GPIO communication */
#define ANT_SELCFG_NUM_2x3 3
#define ANT_SELCFG_DEF_2x3 0x01 /* default antenna configuration */
/* 2x4 antdiv rev4 defines and tables for GPIO communication */
#define ANT_SELCFG_NUM_2x4 4
#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */
/* static functions */
static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
struct brcms_antselcfg *antsel);
static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id);
static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
static void brcms_c_antsel_init_cfg(struct antsel_info *asi,
struct brcms_antselcfg *antsel,
bool auto_sel);
const u16 mimo_2x4_div_antselpat_tbl[] = {
0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */
0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */
0, 0, 0, 0, /* n.a. */
0, 0, 0, 0 /* n.a. */
};
const u8 mimo_2x4_div_antselid_tbl[16] = {
0, 0, 0, 0, 0, 2, 3, 0,
0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */
};
const u16 mimo_2x3_div_antselpat_tbl[] = {
16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */
16, 16, 16, 16, /* n.a. */
16, 2, 16, 16, /* ant0: 2 ant1: 1 */
16, 16, 16, 16 /* n.a. */
};
const u8 mimo_2x3_div_antselid_tbl[16] = {
0, 1, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */
};
struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
{
struct antsel_info *asi;
asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
if (!asi) {
wiphy_err(wlc->wiphy, "wl%d: brcms_c_antsel_attach: out of "
"mem\n", wlc->pub->unit);
return NULL;
}
asi->wlc = wlc;
asi->pub = wlc->pub;
asi->antsel_type = ANTSEL_NA;
asi->antsel_avail = false;
asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
switch (asi->antsel_antswitch) {
case ANTSWITCH_TYPE_1:
case ANTSWITCH_TYPE_2:
case ANTSWITCH_TYPE_3:
/* 4321/2 board with 2x3 switch logic */
asi->antsel_type = ANTSEL_2x3;
/* Antenna selection availability */
if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
asi->antsel_avail = true;
} else
if (((u16) getintvar(asi->pub->vars, "aa2g") ==
3)
|| ((u16) getintvar(asi->pub->vars, "aa5g")
== 3)) {
asi->antsel_avail = false;
} else {
asi->antsel_avail = false;
wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
"board cfg invalid\n");
}
break;
default:
break;
}
} else if ((asi->pub->sromrev == 4) &&
((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
/* hack to match old 4321CB2 cards with 2of3 antenna switch */
asi->antsel_type = ANTSEL_2x3;
asi->antsel_avail = true;
} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
asi->antsel_type = ANTSEL_2x4;
asi->antsel_avail = true;
}
/* Set the antenna selection type for the low driver */
brcms_b_antsel_type_set(wlc->hw, asi->antsel_type);
/* Init (auto/manual) antenna selection */
brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true);
brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true);
return asi;
}
void brcms_c_antsel_detach(struct antsel_info *asi)
{
kfree(asi);
}
void brcms_c_antsel_init(struct antsel_info *asi)
{
if ((asi->antsel_type == ANTSEL_2x3) ||
(asi->antsel_type == ANTSEL_2x4))
brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n);
}
/* boardlevel antenna selection: init antenna selection structure */
static void
brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
bool auto_sel)
{
if (asi->antsel_type == ANTSEL_2x3) {
u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
} else if (asi->antsel_type == ANTSEL_2x4) {
antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
} else { /* no antenna selection available */
antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
antsel->num_antcfg = 0;
}
}
void
brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
u8 antselid, u8 fbantselid, u8 *antcfg,
u8 *fbantcfg)
{
u8 ant;
/* if use default, assign it and return */
if (usedef) {
*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
*fbantcfg = *antcfg;
return;
}
if (!sel) {
*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
*fbantcfg = *antcfg;
} else {
ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
*antcfg = brcms_c_antsel_id2antcfg(asi, antselid);
*fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid);
} else {
*antcfg =
asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
*fbantcfg = *antcfg;
}
}
return;
}
/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
{
u8 antselid = 0;
if (asi->antsel_type == ANTSEL_2x4) {
/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
return antselid;
} else if (asi->antsel_type == ANTSEL_2x3) {
/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
return antselid;
}
return antselid;
}
/* boardlevel antenna selection: convert id to ant_cfg */
static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
{
u8 antcfg = ANT_SELCFG_DEF_2x2;
if (asi->antsel_type == ANTSEL_2x4) {
/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
return antcfg;
} else if (asi->antsel_type == ANTSEL_2x3) {
/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
return antcfg;
}
return antcfg;
}
/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */
static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
{
u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg));
u16 mimo_antsel = 0;
if (asi->antsel_type == ANTSEL_2x4) {
/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
return mimo_antsel;
} else if (asi->antsel_type == ANTSEL_2x3) {
/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
return mimo_antsel;
}
return mimo_antsel;
}
/* boardlevel antenna selection: ucode interface control */
static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
struct brcms_antselcfg *antsel)
{
struct brcms_c_info *wlc = asi->wlc;
u8 ant_cfg;
u16 mimo_antsel;
/* 1) Update TX antconfig for all frames that are not unicast data
* (aka default TX)
*/
ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
brcms_c_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
/* Update driver stats for currently selected default tx/rx antenna config */
asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
/* 2) Update RX antconfig for all frames that are not unicast data
* (aka default RX)
*/
ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
brcms_c_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
/* Update driver stats for currently selected default tx/rx antenna config */
asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
return 0;
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_ANTSEL_H_
#define _BRCM_ANTSEL_H_
extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc);
extern void brcms_c_antsel_detach(struct antsel_info *asi);
extern void brcms_c_antsel_init(struct antsel_info *asi);
extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef,
bool sel,
u8 id, u8 fbid, u8 *antcfg,
u8 *fbantcfg);
extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
#endif /* _BRCM_ANTSEL_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,174 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_BOTTOM_MAC_H_
#define _BRCM_BOTTOM_MAC_H_
#include <brcmu_wifi.h>
#include "types.h"
/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info)
driver */
struct brcms_b_state {
u32 machwcap; /* mac hw capibility */
u32 preamble_ovr; /* preamble override */
};
enum {
IOV_BMAC_DIAG,
IOV_BMAC_SBGPIOTIMERVAL,
IOV_BMAC_SBGPIOOUT,
IOV_BMAC_CCGPIOCTRL, /* CC GPIOCTRL REG */
IOV_BMAC_CCGPIOOUT, /* CC GPIOOUT REG */
IOV_BMAC_CCGPIOOUTEN, /* CC GPIOOUTEN REG */
IOV_BMAC_CCGPIOIN, /* CC GPIOIN REG */
IOV_BMAC_WPSGPIO, /* WPS push button GPIO pin */
IOV_BMAC_OTPDUMP,
IOV_BMAC_OTPSTAT,
IOV_BMAC_PCIEASPM, /* obfuscation clkreq/aspm control */
IOV_BMAC_PCIEADVCORRMASK, /* advanced correctable error mask */
IOV_BMAC_PCIECLKREQ, /* PCIE 1.1 clockreq enab support */
IOV_BMAC_PCIELCREG, /* PCIE LCREG */
IOV_BMAC_SBGPIOTIMERMASK,
IOV_BMAC_RFDISABLEDLY,
IOV_BMAC_PCIEREG, /* PCIE REG */
IOV_BMAC_PCICFGREG, /* PCI Config register */
IOV_BMAC_PCIESERDESREG, /* PCIE SERDES REG (dev, 0}offset) */
IOV_BMAC_PCIEGPIOOUT, /* PCIEOUT REG */
IOV_BMAC_PCIEGPIOOUTEN, /* PCIEOUTEN REG */
IOV_BMAC_PCIECLKREQENCTRL, /* clkreqenctrl REG (PCIE REV > 6.0 */
IOV_BMAC_DMALPBK,
IOV_BMAC_CCREG,
IOV_BMAC_COREREG,
IOV_BMAC_SDCIS,
IOV_BMAC_SDIO_DRIVE,
IOV_BMAC_OTPW,
IOV_BMAC_NVOTPW,
IOV_BMAC_SROM,
IOV_BMAC_SRCRC,
IOV_BMAC_CIS_SOURCE,
IOV_BMAC_CISVAR,
IOV_BMAC_OTPLOCK,
IOV_BMAC_OTP_CHIPID,
IOV_BMAC_CUSTOMVAR1,
IOV_BMAC_BOARDFLAGS,
IOV_BMAC_BOARDFLAGS2,
IOV_BMAC_WPSLED,
IOV_BMAC_NVRAM_SOURCE,
IOV_BMAC_OTP_RAW_READ,
IOV_BMAC_LAST
};
extern int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
uint unit, bool piomode, void *regsva, uint bustype,
void *btparam);
extern int brcms_b_detach(struct brcms_c_info *wlc);
extern void brcms_b_watchdog(void *arg);
/* up/down, reset, clk */
extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
uint offset, const void *buf, int len,
u32 sel);
extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
void *buf, int len, u32 sel);
#define brcms_b_copyfrom_shm(wlc_hw, offset, buf, len) \
brcms_b_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
#define brcms_b_copyto_shm(wlc_hw, offset, buf, len) \
brcms_b_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
extern void brcms_b_reset(struct brcms_hardware *wlc_hw);
extern void brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
bool mute);
extern int brcms_b_up_prep(struct brcms_hardware *wlc_hw);
extern int brcms_b_up_finish(struct brcms_hardware *wlc_hw);
extern int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw);
extern int brcms_b_down_finish(struct brcms_hardware *wlc_hw);
extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
/* chanspec, ucode interface */
extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
chanspec_t chanspec,
bool mute, struct txpwr_limits *txpwr);
extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
uint *blocks);
extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
u16 val, int bands);
extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
extern u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands);
extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
u8 antsel_type);
extern int brcms_b_state_get(struct brcms_hardware *wlc_hw,
struct brcms_b_state *state);
extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
u16 v);
extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
int offset, int len, void *buf);
extern void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
uint *len);
extern void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw,
u8 *ea);
extern bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw);
extern void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw,
bool shortslot);
extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
u8 stf_mode);
extern void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw);
extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
u32 override_bit);
extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
u32 override_bit);
extern void brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw,
int match_reg_offset,
const u8 *addr);
extern void brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw,
void *bcn, int len, bool both);
extern void brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
u32 *tsf_h_ptr);
extern void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin);
extern void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax);
extern void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL,
u16 LRL);
extern void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw);
/* API for BMAC driver (e.g. wlc_phy.c etc) */
extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
extern void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set,
mbool req_bit);
extern void brcms_b_hw_up(struct brcms_hardware *wlc_hw);
extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
extern void brcms_b_antsel_set(struct brcms_hardware *wlc_hw,
u32 antsel_avail);
#endif /* _BRCM_BOTTOM_MAC_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_CHANNEL_H_
#define _BRCM_CHANNEL_H_
/* conversion for phy txpwr calculations that use .25 dB units */
#define BRCMS_TXPWR_DB_FACTOR 4
/* maxpwr mapping to 5GHz band channels:
* maxpwr[0] - channels [34-48]
* maxpwr[1] - channels [52-60]
* maxpwr[2] - channels [62-64]
* maxpwr[3] - channels [100-140]
* maxpwr[4] - channels [149-165]
*/
#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */
/* power level in group of 2.4GHz band channels:
* maxpwr[0] - CCK channels [1]
* maxpwr[1] - CCK channels [2-10]
* maxpwr[2] - CCK channels [11-14]
* maxpwr[3] - OFDM channels [1]
* maxpwr[4] - OFDM channels [2-10]
* maxpwr[5] - OFDM channels [11-14]
*/
/* macro to get 2.4 GHz channel group index for tx power */
#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) /* cck index */
#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) /* ofdm index */
/* macro to get 5 GHz channel group index for tx power */
#define CHANNEL_POWER_IDX_5G(c) \
(((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4))))
/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
#define BRCMS_MAXPWR_TBL_SIZE 6
/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14
#define NBANDS(wlc) ((wlc)->pub->_nbands)
#define NBANDS_PUB(pub) ((pub)->_nbands)
#define NBANDS_HW(hw) ((hw)->_nbands)
#define IS_SINGLEBAND_5G(device) 0
/* locale channel and power info. */
struct locale_info {
u32 valid_channels;
/* List of radar sensitive channels */
u8 radar_channels;
/* List of channels used only if APs are detected */
u8 restricted_channels;
/* Max tx pwr in qdBm for each sub-band */
s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
s8 pub_maxpwr[BAND_5G_PWR_LVLS]; /* Country IE advertised max tx pwr in dBm
* per sub-band
*/
u8 flags;
};
/* bits for locale_info flags */
#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */
#define BRCMS_EIRP 0x01 /* Flag for EIRP */
#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */
#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */
#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */
#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */
#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */
#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */
#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
/* locale per-channel tx power limits for MIMO frames
* maxpwr arrays are index by channel for 2.4 GHz limits, and
* by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
*/
struct locale_mimo_info {
/* tx 20 MHz power limits, qdBm units */
s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
/* tx 40 MHz power limits, qdBm units */
s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
u8 flags;
};
extern const chanvec_t chanvec_all_2G;
extern const chanvec_t chanvec_all_5G;
/*
* Country names and abbreviations with locale defined from ISO 3166
*/
struct country_info {
const u8 locale_2G; /* 2.4G band locale */
const u8 locale_5G; /* 5G band locale */
const u8 locale_mimo_2G; /* 2.4G mimo info */
const u8 locale_mimo_5G; /* 5G mimo info */
};
extern struct brcms_cm_info *
brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
uint bandunit);
extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
chanspec_t chspec);
extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
chanspec_t chanspec,
struct txpwr_limits *txpwr);
extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
chanspec_t chanspec,
u8 local_constraint_qdbm);
#endif /* _WLC_CHANNEL_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,250 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_DMA_H_
#define _BRCM_DMA_H_
#include "types.h" /* forward structure declarations */
/* DMA structure:
* support two DMA engines: 32 bits address or 64 bit addressing
* basic DMA register set is per channel(transmit or receive)
* a pair of channels is defined for convenience
*/
/* 32 bits addressing */
struct dma32diag { /* diag access */
u32 fifoaddr; /* diag address */
u32 fifodatalow; /* low 32bits of data */
u32 fifodatahigh; /* high 32bits of data */
u32 pad; /* reserved */
};
/* 64 bits addressing */
/* dma registers per channel(xmt or rcv) */
struct dma64regs {
u32 control; /* enable, et al */
u32 ptr; /* last descriptor posted to chip */
u32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */
u32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */
u32 status0; /* current descriptor, xmt state */
u32 status1; /* active descriptor, xmt error */
};
/* map/unmap direction */
#define DMA_TX 1 /* TX direction for DMA */
#define DMA_RX 2 /* RX direction for DMA */
#define BUS_SWAP32(v) (v)
/* range param for dma_getnexttxp() and dma_txreclaim */
enum txd_range {
DMA_RANGE_ALL = 1,
DMA_RANGE_TRANSMITTED,
DMA_RANGE_TRANSFERED
};
/* dma function type */
typedef void (*di_detach_t) (struct dma_pub *dmah);
typedef bool(*di_txreset_t) (struct dma_pub *dmah);
typedef bool(*di_rxreset_t) (struct dma_pub *dmah);
typedef bool(*di_rxidle_t) (struct dma_pub *dmah);
typedef void (*di_txinit_t) (struct dma_pub *dmah);
typedef bool(*di_txenabled_t) (struct dma_pub *dmah);
typedef void (*di_rxinit_t) (struct dma_pub *dmah);
typedef void (*di_txsuspend_t) (struct dma_pub *dmah);
typedef void (*di_txresume_t) (struct dma_pub *dmah);
typedef bool(*di_txsuspended_t) (struct dma_pub *dmah);
typedef bool(*di_txsuspendedidle_t) (struct dma_pub *dmah);
typedef int (*di_txfast_t) (struct dma_pub *dmah, struct sk_buff *p,
bool commit);
typedef int (*di_txunframed_t) (struct dma_pub *dmah, void *p, uint len,
bool commit);
typedef void *(*di_getpos_t) (struct dma_pub *di, bool direction);
typedef void (*di_fifoloopbackenable_t) (struct dma_pub *dmah);
typedef bool(*di_txstopped_t) (struct dma_pub *dmah);
typedef bool(*di_rxstopped_t) (struct dma_pub *dmah);
typedef bool(*di_rxenable_t) (struct dma_pub *dmah);
typedef bool(*di_rxenabled_t) (struct dma_pub *dmah);
typedef void *(*di_rx_t) (struct dma_pub *dmah);
typedef bool(*di_rxfill_t) (struct dma_pub *dmah);
typedef void (*di_txreclaim_t) (struct dma_pub *dmah, enum txd_range range);
typedef void (*di_rxreclaim_t) (struct dma_pub *dmah);
typedef unsigned long (*di_getvar_t) (struct dma_pub *dmah,
const char *name);
typedef void *(*di_getnexttxp_t) (struct dma_pub *dmah, enum txd_range range);
typedef void *(*di_getnextrxp_t) (struct dma_pub *dmah, bool forceall);
typedef void *(*di_peeknexttxp_t) (struct dma_pub *dmah);
typedef void *(*di_peeknextrxp_t) (struct dma_pub *dmah);
typedef void (*di_rxparam_get_t) (struct dma_pub *dmah, u16 *rxoffset,
u16 *rxbufsize);
typedef void (*di_txblock_t) (struct dma_pub *dmah);
typedef void (*di_txunblock_t) (struct dma_pub *dmah);
typedef uint(*di_txactive_t) (struct dma_pub *dmah);
typedef void (*di_txrotate_t) (struct dma_pub *dmah);
typedef void (*di_counterreset_t) (struct dma_pub *dmah);
typedef uint(*di_ctrlflags_t) (struct dma_pub *dmah, uint mask, uint flags);
typedef char *(*di_dump_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
bool dumpring);
typedef char *(*di_dumptx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
bool dumpring);
typedef char *(*di_dumprx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
bool dumpring);
typedef uint(*di_rxactive_t) (struct dma_pub *dmah);
typedef uint(*di_txpending_t) (struct dma_pub *dmah);
typedef uint(*di_txcommitted_t) (struct dma_pub *dmah);
/* dma opsvec */
struct di_fcn_s {
di_detach_t detach;
di_txinit_t txinit;
di_txreset_t txreset;
di_txenabled_t txenabled;
di_txsuspend_t txsuspend;
di_txresume_t txresume;
di_txsuspended_t txsuspended;
di_txsuspendedidle_t txsuspendedidle;
di_txfast_t txfast;
di_txunframed_t txunframed;
di_getpos_t getpos;
di_txstopped_t txstopped;
di_txreclaim_t txreclaim;
di_getnexttxp_t getnexttxp;
di_peeknexttxp_t peeknexttxp;
di_txblock_t txblock;
di_txunblock_t txunblock;
di_txactive_t txactive;
di_txrotate_t txrotate;
di_rxinit_t rxinit;
di_rxreset_t rxreset;
di_rxidle_t rxidle;
di_rxstopped_t rxstopped;
di_rxenable_t rxenable;
di_rxenabled_t rxenabled;
di_rx_t rx;
di_rxfill_t rxfill;
di_rxreclaim_t rxreclaim;
di_getnextrxp_t getnextrxp;
di_peeknextrxp_t peeknextrxp;
di_rxparam_get_t rxparam_get;
di_fifoloopbackenable_t fifoloopbackenable;
di_getvar_t d_getvar;
di_counterreset_t counterreset;
di_ctrlflags_t ctrlflags;
di_dump_t dump;
di_dumptx_t dumptx;
di_dumprx_t dumprx;
di_rxactive_t rxactive;
di_txpending_t txpending;
di_txcommitted_t txcommitted;
uint endnum;
};
/*
* Exported data structure (read-only)
*/
/* export structure */
struct dma_pub {
const struct di_fcn_s *di_fn; /* DMA function pointers */
uint txavail; /* # free tx descriptors */
uint dmactrlflags; /* dma control flags */
/* rx error counters */
uint rxgiants; /* rx giant frames */
uint rxnobuf; /* rx out of dma descriptors */
/* tx error counters */
uint txnobuf; /* tx out of dma descriptors */
};
extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
void *dmaregstx, void *dmaregsrx, uint ntxd,
uint nrxd, uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level);
extern const struct di_fcn_s dma64proc;
#define dma_detach(di) (dma64proc.detach(di))
#define dma_txreset(di) (dma64proc.txreset(di))
#define dma_rxreset(di) (dma64proc.rxreset(di))
#define dma_rxidle(di) (dma64proc.rxidle(di))
#define dma_txinit(di) (dma64proc.txinit(di))
#define dma_txenabled(di) (dma64proc.txenabled(di))
#define dma_rxinit(di) (dma64proc.rxinit(di))
#define dma_txsuspend(di) (dma64proc.txsuspend(di))
#define dma_txresume(di) (dma64proc.txresume(di))
#define dma_txsuspended(di) (dma64proc.txsuspended(di))
#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di))
#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit))
#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit))
#define dma_getpos(di, dir) (dma64proc.getpos(di, dir))
#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di))
#define dma_txstopped(di) (dma64proc.txstopped(di))
#define dma_rxstopped(di) (dma64proc.rxstopped(di))
#define dma_rxenable(di) (dma64proc.rxenable(di))
#define dma_rxenabled(di) (dma64proc.rxenabled(di))
#define dma_rx(di) (dma64proc.rx(di))
#define dma_rxfill(di) (dma64proc.rxfill(di))
#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range))
#define dma_rxreclaim(di) (dma64proc.rxreclaim(di))
#define dma_getvar(di, name) (dma64proc.d_getvar(di, name))
#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range))
#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall))
#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di))
#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di))
#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs))
#define dma_txblock(di) (dma64proc.txblock(di))
#define dma_txunblock(di) (dma64proc.txunblock(di))
#define dma_txactive(di) (dma64proc.txactive(di))
#define dma_rxactive(di) (dma64proc.rxactive(di))
#define dma_txrotate(di) (dma64proc.txrotate(di))
#define dma_counterreset(di) (dma64proc.counterreset(di))
#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags)))
#define dma_txpending(di) (dma64proc.txpending(di))
#define dma_txcommitted(di) (dma64proc.txcommitted(di))
/* return addresswidth allowed
* This needs to be done after SB attach but before dma attach.
* SB attach provides ability to probe backplane and dma core capabilities
* This info is needed by DMA_ALLOC_CONSISTENT in dma attach
*/
extern uint dma_addrwidth(struct si_pub *sih, void *dmaregs);
void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
(void *pkt, void *arg_a), void *arg_a);
/*
* DMA(Bug) on some chips seems to declare that the packet is ready, but the
* packet length is not updated yet (by DMA) on the expected time.
* Workaround is to hold processor till DMA updates the length, and stay off
* the bus to allow DMA update the length in buffer
*/
static inline void dma_spin_for_len(uint len, struct sk_buff *head)
{
#if defined(__mips__)
if (!len) {
while (!(len = *(u16 *) KSEG1ADDR(head->data)))
udelay(1);
*(u16 *) (head->data) = cpu_to_le16((u16) len);
}
#endif /* defined(__mips__) */
}
#endif /* _BRCM_DMA_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_MAC80211_IF_H_
#define _BRCM_MAC80211_IF_H_
#include <linux/timer.h>
#include <linux/interrupt.h>
/* softmac ioctl definitions */
#define BRCMS_SET_SHORTSLOT_OVERRIDE 146
/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
* sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
* submitted to workqueue instead of being on kernel timer
*/
struct brcms_timer {
struct timer_list timer;
struct brcms_info *wl;
void (*fn) (void *);
void *arg; /* argument to fn */
uint ms;
bool periodic;
bool set;
struct brcms_timer *next;
#ifdef BCMDBG
char *name; /* Description of the timer */
#endif
};
struct brcms_if {
uint subunit; /* WDS/BSS unit */
struct pci_dev *pci_dev;
};
#define MAX_FW_IMAGES 4
struct brcms_firmware {
u32 fw_cnt;
const struct firmware *fw_bin[MAX_FW_IMAGES];
const struct firmware *fw_hdr[MAX_FW_IMAGES];
u32 hdr_num_entries[MAX_FW_IMAGES];
};
struct brcms_info {
struct brcms_pub *pub; /* pointer to public wlc state */
void *wlc; /* pointer to private common os-independent data */
u32 magic;
int irq;
spinlock_t lock; /* per-device perimeter lock */
spinlock_t isr_lock; /* per-device ISR synchronization lock */
/* bus type and regsva for unmap in brcms_free() */
uint bcm_bustype; /* bus type */
void *regsva; /* opaque chip registers virtual address */
/* timer related fields */
atomic_t callbacks; /* # outstanding callback functions */
struct brcms_timer *timers; /* timer cleanup queue */
struct tasklet_struct tasklet; /* dpc tasklet */
bool resched; /* dpc needs to be and is rescheduled */
#ifdef LINUXSTA_PS
u32 pci_psstate[16]; /* pci ps-state save/restore */
#endif
struct brcms_firmware fw;
struct wiphy *wiphy;
};
/* misc callbacks */
extern void brcms_init(struct brcms_info *wl);
extern uint brcms_reset(struct brcms_info *wl);
extern void brcms_intrson(struct brcms_info *wl);
extern u32 brcms_intrsoff(struct brcms_info *wl);
extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask);
extern int brcms_up(struct brcms_info *wl);
extern void brcms_down(struct brcms_info *wl);
extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
bool state, int prio);
extern bool wl_alloc_dma_resources(struct brcms_info *wl, uint dmaddrwidth);
extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
/* timer functions */
extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
void (*fn) (void *arg), void *arg,
const char *name);
extern void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *timer);
extern void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *timer,
uint ms, int periodic);
extern bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *timer);
extern void brcms_msleep(struct brcms_info *wl, uint ms);
#endif /* _BRCM_MAC80211_IF_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,850 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <defs.h>
#include <soc.h>
#include <chipcommon.h>
#include "aiutils.h"
#include "pub.h"
#include "nicpci.h"
/* SPROM offsets */
#define SRSH_ASPM_OFFSET 4 /* word 4 */
#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */
#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */
#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */
#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */
#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */
#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */
#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */
#define SRSH_BD_OFFSET 6 /* word 6 */
/* chipcontrol */
#define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */
/* MDIO control */
#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
#define MDIOCTL_DIVISOR_VAL 0x2
#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */
#define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */
/* MDIO Data */
#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */
#define MDIODATA_TA 0x00020000 /* Turnaround */
#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */
#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */
#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */
#define MDIODATA_DEVADDR_MASK 0x0f800000
/* Physmedia devaddr Mask */
/* MDIO Data for older revisions < 10 */
#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */
#define MDIODATA_REGADDR_MASK_OLD 0x003c0000
/* Regaddr Mask */
#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */
#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000
/* Physmedia devaddr Mask */
/* Transactions flags */
#define MDIODATA_WRITE 0x10000000
#define MDIODATA_READ 0x20000000
#define MDIODATA_START 0x40000000
#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */
#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */
/* serdes regs (rev < 10) */
#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */
#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */
#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */
/* SERDES RX registers */
#define SERDES_RX_CTRL 1 /* Rx cntrl */
#define SERDES_RX_TIMER1 2 /* Rx Timer1 */
#define SERDES_RX_CDR 6 /* CDR */
#define SERDES_RX_CDRBW 7 /* CDR BW */
/* SERDES RX control register */
#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */
#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */
/* SERDES PLL registers */
#define SERDES_PLL_CTRL 1 /* PLL control reg */
#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */
/* Linkcontrol reg offset in PCIE Cap */
#define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */
#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */
#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */
#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */
#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */
#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */
/* Power management threshold */
#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */
#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */
#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */
#define PCIE_ASPMTIMER_EXTEND 0x01000000
/* > rev7:
* enable extend ASPM timer
*/
/* different register spaces to access thru pcie indirect access */
#define PCIE_CONFIGREGS 1 /* Access to config space */
#define PCIE_PCIEREGS 2 /* Access to pcie registers */
/* PCIE protocol PHY diagnostic registers */
#define PCIE_PLP_STATUSREG 0x204 /* Status */
/* Status reg PCIE_PLP_STATUSREG */
#define PCIE_PLP_POLARITYINV_STAT 0x10
/* PCIE protocol DLLP diagnostic registers */
#define PCIE_DLLP_LCREG 0x100 /* Link Control */
#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */
/* PCIE protocol TLP diagnostic registers */
#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */
/* Sonics side: PCI core and host control registers */
struct sbpciregs {
u32 control; /* PCI control */
u32 PAD[3];
u32 arbcontrol; /* PCI arbiter control */
u32 clkrun; /* Clkrun Control (>=rev11) */
u32 PAD[2];
u32 intstatus; /* Interrupt status */
u32 intmask; /* Interrupt mask */
u32 sbtopcimailbox; /* Sonics to PCI mailbox */
u32 PAD[9];
u32 bcastaddr; /* Sonics broadcast address */
u32 bcastdata; /* Sonics broadcast data */
u32 PAD[2];
u32 gpioin; /* ro: gpio input (>=rev2) */
u32 gpioout; /* rw: gpio output (>=rev2) */
u32 gpioouten; /* rw: gpio output enable (>= rev2) */
u32 gpiocontrol; /* rw: gpio control (>= rev2) */
u32 PAD[36];
u32 sbtopci0; /* Sonics to PCI translation 0 */
u32 sbtopci1; /* Sonics to PCI translation 1 */
u32 sbtopci2; /* Sonics to PCI translation 2 */
u32 PAD[189];
u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
u16 sprom[36]; /* SPROM shadow Area */
u32 PAD[46];
};
/* SB side: PCIE core and host control registers */
struct sbpcieregs {
u32 control; /* host mode only */
u32 PAD[2];
u32 biststatus; /* bist Status: 0x00C */
u32 gpiosel; /* PCIE gpio sel: 0x010 */
u32 gpioouten; /* PCIE gpio outen: 0x14 */
u32 PAD[2];
u32 intstatus; /* Interrupt status: 0x20 */
u32 intmask; /* Interrupt mask: 0x24 */
u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */
u32 PAD[53];
u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */
u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */
u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */
u32 PAD[5];
/* pcie core supports in direct access to config space */
u32 configaddr; /* pcie config space access: Address field: 0x120 */
u32 configdata; /* pcie config space access: Data field: 0x124 */
/* mdio access to serdes */
u32 mdiocontrol; /* controls the mdio access: 0x128 */
u32 mdiodata; /* Data to the mdio access: 0x12c */
/* pcie protocol phy/dllp/tlp register indirect access mechanism */
u32 pcieindaddr; /* indirect access to
* the internal register: 0x130
*/
u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */
u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */
u32 PAD[177];
u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */
u16 sprom[64]; /* SPROM shadow Area */
};
struct pcicore_info {
union {
struct sbpcieregs *pcieregs;
struct sbpciregs *pciregs;
} regs; /* Memory mapped register to the core */
struct si_pub *sih; /* System interconnect handle */
struct pci_dev *dev;
u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
* in the config space
*/
bool pcie_pr42767;
u8 pcie_polarity;
u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */
u8 pmecap_offset; /* PM Capability offset in the config space */
bool pmecap; /* Capable of generating PME */
};
/* debug/trace */
#define PCI_ERROR(args)
#define PCIE_PUB(sih) \
(((sih)->bustype == PCI_BUS) && \
((sih)->buscoretype == PCIE_CORE_ID))
/* routines to access mdio slave device registers */
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk);
static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr,
bool write, uint *val);
static int pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint readdr,
uint val);
static int pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint readdr,
uint *ret_val);
static void pcie_extendL1timer(struct pcicore_info *pi, bool extend);
static void pcie_clkreq_upd(struct pcicore_info *pi, uint state);
static void pcie_war_aspm_clkreq(struct pcicore_info *pi);
static void pcie_war_serdes(struct pcicore_info *pi);
static void pcie_war_noplldown(struct pcicore_info *pi);
static void pcie_war_polarity(struct pcicore_info *pi);
static void pcie_war_pci_setup(struct pcicore_info *pi);
#define PCIE_ASPM(sih) \
((PCIE_PUB(sih)) && \
(((sih)->buscorerev >= 3) && \
((sih)->buscorerev <= 5)))
/* delay needed between the mdio control/ mdiodata register data access */
#define PR28829_DELAY() udelay(10)
/* Initialize the PCI core.
* It's caller's responsibility to make sure that this is done only once
*/
void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
{
struct pcicore_info *pi;
/* alloc struct pcicore_info */
pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
if (pi == NULL) {
PCI_ERROR(("pci_attach: malloc failed!\n"));
return NULL;
}
pi->sih = sih;
pi->dev = pdev;
if (sih->buscoretype == PCIE_CORE_ID) {
u8 cap_ptr;
pi->regs.pcieregs = regs;
cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
NULL, NULL);
pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
} else
pi->regs.pciregs = regs;
return pi;
}
void pcicore_deinit(void *pch)
{
kfree(pch);
}
/* return cap_offset if requested capability exists in the PCI config space */
/* Note that it's caller's responsibility to make sure it's a pci bus */
u8
pcicore_find_pci_capability(void *dev, u8 req_cap_id,
unsigned char *buf, u32 *buflen)
{
u8 cap_id;
u8 cap_ptr = 0;
u32 bufsize;
u8 byte_val;
/* check for Header type 0 */
pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val);
if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
goto end;
/* check if the capability pointer field exists */
pci_read_config_byte(dev, PCI_STATUS, &byte_val);
if (!(byte_val & PCI_STATUS_CAP_LIST))
goto end;
pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
/* check if the capability pointer is 0x00 */
if (cap_ptr == 0x00)
goto end;
/* loop thru the capability list
* and see if the pcie capability exists
*/
pci_read_config_byte(dev, cap_ptr, &cap_id);
while (cap_id != req_cap_id) {
pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
if (cap_ptr == 0x00)
break;
pci_read_config_byte(dev, cap_ptr, &cap_id);
}
if (cap_id != req_cap_id)
goto end;
/* found the caller requested capability */
if (buf != NULL && buflen != NULL) {
u8 cap_data;
bufsize = *buflen;
if (!bufsize)
goto end;
*buflen = 0;
/* copy the capability data excluding cap ID and next ptr */
cap_data = cap_ptr + 2;
if ((bufsize + cap_data) > PCI_SZPCR)
bufsize = PCI_SZPCR - cap_data;
*buflen = bufsize;
while (bufsize--) {
pci_read_config_byte(dev, cap_data, buf);
cap_data++;
buf++;
}
}
end:
return cap_ptr;
}
/* ***** Register Access API */
static uint
pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
{
uint retval = 0xFFFFFFFF;
switch (addrtype) {
case PCIE_CONFIGREGS:
W_REG(&pcieregs->configaddr, offset);
(void)R_REG((&pcieregs->configaddr));
retval = R_REG(&pcieregs->configdata);
break;
case PCIE_PCIEREGS:
W_REG(&pcieregs->pcieindaddr, offset);
(void)R_REG(&pcieregs->pcieindaddr);
retval = R_REG(&pcieregs->pcieinddata);
break;
}
return retval;
}
static uint
pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
{
switch (addrtype) {
case PCIE_CONFIGREGS:
W_REG((&pcieregs->configaddr), offset);
W_REG((&pcieregs->configdata), val);
break;
case PCIE_PCIEREGS:
W_REG((&pcieregs->pcieindaddr), offset);
W_REG((&pcieregs->pcieinddata), val);
break;
default:
break;
}
return 0;
}
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
{
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
uint mdiodata, i = 0;
uint pcie_serdes_spinwait = 200;
mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
(MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
(MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
(blk << 4));
W_REG(&pcieregs->mdiodata, mdiodata);
PR28829_DELAY();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
break;
udelay(1000);
i++;
}
if (i >= pcie_serdes_spinwait) {
PCI_ERROR(("pcie_mdiosetblock: timed out\n"));
return false;
}
return true;
}
static int
pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
uint *val)
{
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
uint mdiodata;
uint i = 0;
uint pcie_serdes_spinwait = 10;
/* enable mdio access to SERDES */
W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
if (pi->sih->buscorerev >= 10) {
/* new serdes is slower in rw,
* using two layers of reg address mapping
*/
if (!pcie_mdiosetblock(pi, physmedia))
return 1;
mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
(regaddr << MDIODATA_REGADDR_SHF));
pcie_serdes_spinwait *= 20;
} else {
mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
(regaddr << MDIODATA_REGADDR_SHF_OLD));
}
if (!write)
mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
else
mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
*val);
W_REG(&pcieregs->mdiodata, mdiodata);
PR28829_DELAY();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
if (!write) {
PR28829_DELAY();
*val = (R_REG(&pcieregs->mdiodata) &
MDIODATA_MASK);
}
/* Disable mdio access to SERDES */
W_REG(&pcieregs->mdiocontrol, 0);
return 0;
}
udelay(1000);
i++;
}
PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
/* Disable mdio access to SERDES */
W_REG(&pcieregs->mdiocontrol, 0);
return 1;
}
/* use the mdio interface to read from mdio slaves */
static int
pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
uint *regval)
{
return pcie_mdioop(pi, physmedia, regaddr, false, regval);
}
/* use the mdio interface to write to mdio slaves */
static int
pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
{
return pcie_mdioop(pi, physmedia, regaddr, true, &val);
}
/* ***** Support functions ***** */
static u8 pcie_clkreq(void *pch, u32 mask, u32 val)
{
struct pcicore_info *pi = pch;
u32 reg_val;
u8 offset;
offset = pi->pciecap_lcreg_offset;
if (!offset)
return 0;
pci_read_config_dword(pi->dev, offset, &reg_val);
/* set operation */
if (mask) {
if (val)
reg_val |= PCIE_CLKREQ_ENAB;
else
reg_val &= ~PCIE_CLKREQ_ENAB;
pci_write_config_dword(pi->dev, offset, reg_val);
pci_read_config_dword(pi->dev, offset, &reg_val);
}
if (reg_val & PCIE_CLKREQ_ENAB)
return 1;
else
return 0;
}
static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
{
u32 w;
struct si_pub *sih = pi->sih;
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
if (!PCIE_PUB(sih) || sih->buscorerev < 7)
return;
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
if (extend)
w |= PCIE_ASPMTIMER_EXTEND;
else
w &= ~PCIE_ASPMTIMER_EXTEND;
pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
}
/* centralized clkreq control policy */
static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
{
struct si_pub *sih = pi->sih;
switch (state) {
case SI_DOATTACH:
if (PCIE_ASPM(sih))
pcie_clkreq((void *)pi, 1, 0);
break;
case SI_PCIDOWN:
if (sih->buscorerev == 6) { /* turn on serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, chipcontrol_data),
~0x40, 0);
} else if (pi->pcie_pr42767) {
pcie_clkreq((void *)pi, 1, 1);
}
break;
case SI_PCIUP:
if (sih->buscorerev == 6) { /* turn off serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, chipcontrol_data),
~0x40, 0x40);
} else if (PCIE_ASPM(sih)) { /* disable clkreq */
pcie_clkreq((void *)pi, 1, 0);
}
break;
}
}
/* ***** PCI core WARs ***** */
/* Done only once at attach time */
static void pcie_war_polarity(struct pcicore_info *pi)
{
u32 w;
if (pi->pcie_polarity != 0)
return;
w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
/* Detect the current polarity at attach and force that polarity and
* disable changing the polarity
*/
if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
else
pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
SERDES_RX_CTRL_POLARITY);
}
/* enable ASPM and CLKREQ if srom doesn't have it */
/* Needs to happen when update to shadow SROM is needed
* : Coming out of 'standby'/'hibernate'
* : If pcie_war_aspm_ovr state changed
*/
static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
{
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
struct si_pub *sih = pi->sih;
u16 val16, *reg16;
u32 w;
if (!PCIE_ASPM(sih))
return;
/* bypass this on QT or VSIM */
reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
val16 = R_REG(reg16);
val16 &= ~SRSH_ASPM_ENB;
if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
val16 |= SRSH_ASPM_ENB;
else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
val16 |= SRSH_ASPM_L1_ENB;
else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
val16 |= SRSH_ASPM_L0s_ENB;
W_REG(reg16, val16);
pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
w &= ~PCIE_ASPM_ENAB;
w |= pi->pcie_war_aspm_ovr;
pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
val16 = R_REG(reg16);
if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
val16 |= SRSH_CLKREQ_ENB;
pi->pcie_pr42767 = true;
} else
val16 &= ~SRSH_CLKREQ_ENB;
W_REG(reg16, val16);
}
/* Apply the polarity determined at the start */
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_serdes(struct pcicore_info *pi)
{
u32 w = 0;
if (pi->pcie_polarity != 0)
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL,
pi->pcie_polarity);
pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
if (w & PLL_CTRL_FREQDET_EN) {
w &= ~PLL_CTRL_FREQDET_EN;
pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
}
}
/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_misc_config_fixup(struct pcicore_info *pi)
{
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
u16 val16, *reg16;
reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
val16 = R_REG(reg16);
if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
val16 |= SRSH_L23READY_EXIT_NOPERST;
W_REG(reg16, val16);
}
}
/* quick hack for testing */
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_noplldown(struct pcicore_info *pi)
{
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
u16 *reg16;
/* turn off serdes PLL down */
ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol),
CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
/* clear srom shadow backdoor */
reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
W_REG(reg16, 0);
}
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_pci_setup(struct pcicore_info *pi)
{
struct si_pub *sih = pi->sih;
struct sbpcieregs *pcieregs = pi->regs.pcieregs;
u32 w;
if (sih->buscorerev == 0 || sih->buscorerev == 1) {
w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
PCIE_TLP_WORKAROUNDSREG);
w |= 0x8;
pcie_writereg(pcieregs, PCIE_PCIEREGS,
PCIE_TLP_WORKAROUNDSREG, w);
}
if (sih->buscorerev == 1) {
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
w |= 0x40;
pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
}
if (sih->buscorerev == 0) {
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
} else if (PCIE_ASPM(sih)) {
/* Change the L1 threshold for better performance */
w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
PCIE_DLLP_PMTHRESHREG);
w &= ~PCIE_L1THRESHOLDTIME_MASK;
w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
pcie_writereg(pcieregs, PCIE_PCIEREGS,
PCIE_DLLP_PMTHRESHREG, w);
pcie_war_serdes(pi);
pcie_war_aspm_clkreq(pi);
} else if (pi->sih->buscorerev == 7)
pcie_war_noplldown(pi);
/* Note that the fix is actually in the SROM,
* that's why this is open-ended
*/
if (pi->sih->buscorerev >= 6)
pcie_misc_config_fixup(pi);
}
/* ***** Functions called during driver state changes ***** */
void pcicore_attach(void *pch, char *pvars, int state)
{
struct pcicore_info *pi = pch;
struct si_pub *sih = pi->sih;
/* Determine if this board needs override */
if (PCIE_ASPM(sih)) {
if ((u32)getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR)
pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
else
pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
}
/* These need to happen in this order only */
pcie_war_polarity(pi);
pcie_war_serdes(pi);
pcie_war_aspm_clkreq(pi);
pcie_clkreq_upd(pi, state);
}
void pcicore_hwup(void *pch)
{
struct pcicore_info *pi = pch;
if (!pi || !PCIE_PUB(pi->sih))
return;
pcie_war_pci_setup(pi);
}
void pcicore_up(void *pch, int state)
{
struct pcicore_info *pi = pch;
if (!pi || !PCIE_PUB(pi->sih))
return;
/* Restore L1 timer for better performance */
pcie_extendL1timer(pi, true);
pcie_clkreq_upd(pi, state);
}
/* When the device is going to enter D3 state
* (or the system is going to enter S3/S4 states)
*/
void pcicore_sleep(void *pch)
{
struct pcicore_info *pi = pch;
u32 w;
if (!pi || !PCIE_ASPM(pi->sih))
return;
pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
w &= ~PCIE_CAP_LCREG_ASPML1;
pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
pi->pcie_pr42767 = false;
}
void pcicore_down(void *pch, int state)
{
struct pcicore_info *pi = pch;
if (!pi || !PCIE_PUB(pi->sih))
return;
pcie_clkreq_upd(pi, state);
/* Reduce L1 timer for better power savings */
pcie_extendL1timer(pi, false);
}
/* precondition: current core is sii->buscoretype */
void pcicore_fixcfg(void *pch, void *regs)
{
struct pcicore_info *pi = pch;
struct si_info *sii = SI_INFO(pi->sih);
struct sbpciregs *pciregs = regs;
struct sbpcieregs *pcieregs = regs;
u16 val16, *reg16 = NULL;
uint pciidx;
/* check 'pi' is correct and fix it if not */
if (sii->pub.buscoretype == PCIE_CORE_ID)
reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
else if (sii->pub.buscoretype == PCI_CORE_ID)
reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
pciidx = ai_coreidx(&sii->pub);
val16 = R_REG(reg16);
if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
(val16 & ~SRSH_PI_MASK);
W_REG(reg16, val16);
}
}
/* precondition: current core is pci core */
void pcicore_pci_setup(void *pch, void *regs)
{
struct pcicore_info *pi = pch;
struct sbpciregs *pciregs = regs;
u32 w;
OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
if (SI_INFO(pi->sih)->pub.buscorerev >= 11) {
OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
w = R_REG(&pciregs->clkrun);
W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
w = R_REG(&pciregs->clkrun);
}
}

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_NICPCI_H_
#define _BRCM_NICPCI_H_
#include "types.h"
/* PCI configuration address space size */
#define PCI_SZPCR 256
/* Brcm PCI configuration registers */
/* backplane address space accessed by BAR0 */
#define PCI_BAR0_WIN 0x80
/* sprom property control */
#define PCI_SPROM_CONTROL 0x88
/* mask of PCI and other cores interrupts */
#define PCI_INT_MASK 0x94
/* backplane core interrupt mask bits offset */
#define PCI_SBIM_SHIFT 8
/* backplane address space accessed by second 4KB of BAR0 */
#define PCI_BAR0_WIN2 0xac
/* pci config space gpio input (>=rev3) */
#define PCI_GPIO_IN 0xb0
/* pci config space gpio output (>=rev3) */
#define PCI_GPIO_OUT 0xb4
/* pci config space gpio output enable (>=rev3) */
#define PCI_GPIO_OUTEN 0xb8
/* bar0 + 4K accesses external sprom */
#define PCI_BAR0_SPROM_OFFSET (4 * 1024)
/* bar0 + 6K accesses pci core registers */
#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024)
/*
* pci core SB registers are at the end of the
* 8KB window, so their address is the "regular"
* address plus 4K
*/
#define PCI_BAR0_PCISBR_OFFSET (4 * 1024)
/* bar0 window size Match with corerev 13 */
#define PCI_BAR0_WINSZ (16 * 1024)
/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
/* bar0 + 8K accesses pci/pcie core registers */
#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)
/* bar0 + 12K accesses chipc core registers */
#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */
/* Sonics to PCI translation types */
#define SBTOPCI_PREF 0x4 /* prefetch enable */
#define SBTOPCI_BURST 0x8 /* burst enable */
#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */
/* PCI core index in SROM shadow area */
#define SRSH_PI_OFFSET 0 /* first word */
#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
#define SRSH_PI_SHIFT 12 /* bit 15:12 */
extern void *pcicore_init(struct si_pub *sih, void *pdev, void *regs);
extern void pcicore_deinit(void *pch);
extern void pcicore_attach(void *pch, char *pvars, int state);
extern void pcicore_hwup(void *pch);
extern void pcicore_up(void *pch, int state);
extern void pcicore_sleep(void *pch);
extern void pcicore_down(void *pch, int state);
extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
unsigned char *buf, u32 *buflen);
extern void pcicore_fixcfg(void *pch, void *regs);
extern void pcicore_pci_setup(void *pch, void *regs);
#endif /* _BRCM_NICPCI_H_ */

View File

@ -1,545 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <brcm_hw_ids.h>
#include <chipcommon.h>
#include "aiutils.h"
#include "otp.h"
#define OTPS_GUP_MASK 0x00000f00
#define OTPS_GUP_SHIFT 8
#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */
#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */
#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */
#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */
/* Fields in otpprog in rev >= 21 */
#define OTPP_COL_MASK 0x000000ff
#define OTPP_COL_SHIFT 0
#define OTPP_ROW_MASK 0x0000ff00
#define OTPP_ROW_SHIFT 8
#define OTPP_OC_MASK 0x0f000000
#define OTPP_OC_SHIFT 24
#define OTPP_READERR 0x10000000
#define OTPP_VALUE_MASK 0x20000000
#define OTPP_VALUE_SHIFT 29
#define OTPP_START_BUSY 0x80000000
#define OTPP_READ 0x40000000
/* Opcodes for OTPP_OC field */
#define OTPPOC_READ 0
#define OTPPOC_BIT_PROG 1
#define OTPPOC_VERIFY 3
#define OTPPOC_INIT 4
#define OTPPOC_SET 5
#define OTPPOC_RESET 6
#define OTPPOC_OCST 7
#define OTPPOC_ROW_LOCK 8
#define OTPPOC_PRESCN_TEST 9
#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23)
#define OTPP_TRIES 10000000 /* # of tries for OTPP */
#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
/* OTP common function type */
typedef int (*otp_status_t) (void *oh);
typedef int (*otp_size_t) (void *oh);
typedef void *(*otp_init_t) (struct si_pub *sih);
typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
typedef int (*otp_read_region_t) (struct si_pub *sih, int region, u16 *data,
uint *wlen);
typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
/* OTP function struct */
struct otp_fn_s {
otp_size_t size;
otp_read_bit_t read_bit;
otp_init_t init;
otp_read_region_t read_region;
otp_nvread_t nvread;
otp_status_t status;
};
struct otpinfo {
uint ccrev; /* chipc revision */
struct otp_fn_s *fn; /* OTP functions */
struct si_pub *sih; /* Saved sb handle */
/* IPX OTP section */
u16 wsize; /* Size of otp in words */
u16 rows; /* Geometry */
u16 cols; /* Geometry */
u32 status; /* Flag bits (lock/prog/rv).
* (Reflected only when OTP is power cycled)
*/
u16 hwbase; /* hardware subregion offset */
u16 hwlim; /* hardware subregion boundary */
u16 swbase; /* software subregion offset */
u16 swlim; /* software subregion boundary */
u16 fbase; /* fuse subregion offset */
u16 flim; /* fuse subregion boundary */
int otpgu_base; /* offset to General Use Region */
};
static struct otpinfo otpinfo;
/*
* IPX OTP Code
*
* Exported functions:
* ipxotp_status()
* ipxotp_size()
* ipxotp_init()
* ipxotp_read_bit()
* ipxotp_read_region()
* ipxotp_nvread()
*
*/
#define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
/* OTP layout */
/* CC revs 21, 24 and 27 OTP General Use Region word offset */
#define REVA4_OTPGU_BASE 12
/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
#define REVB8_OTPGU_BASE 20
/* CC rev 36 OTP General Use Region word offset */
#define REV36_OTPGU_BASE 12
/* Subregion word offsets in General Use region */
#define OTPGU_HSB_OFF 0
#define OTPGU_SFB_OFF 1
#define OTPGU_CI_OFF 2
#define OTPGU_P_OFF 3
#define OTPGU_SROM_OFF 4
/* Flag bit offsets in General Use region */
#define OTPGU_HWP_OFF 60
#define OTPGU_SWP_OFF 61
#define OTPGU_CIP_OFF 62
#define OTPGU_FUSEP_OFF 63
#define OTPGU_CIP_MSK 0x4000
#define OTPGU_P_MSK 0xf000
#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16)
/* OTP Size */
#define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */
#define OTP_SZ_FU_288 (288/8) /* 288 bits */
#define OTP_SZ_FU_216 (216/8) /* 216 bits */
#define OTP_SZ_FU_72 (72/8) /* 72 bits */
#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */
#define OTP4315_SWREG_SZ 178 /* 178 bytes */
#define OTP_SZ_FU_144 (144/8) /* 144 bits */
static int ipxotp_status(void *oh)
{
struct otpinfo *oi = (struct otpinfo *) oh;
return (int)(oi->status);
}
/* Return size in bytes */
static int ipxotp_size(void *oh)
{
struct otpinfo *oi = (struct otpinfo *) oh;
return (int)oi->wsize * 2;
}
static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
{
struct otpinfo *oi;
oi = (struct otpinfo *) oh;
return R_REG(&cc->sromotp[wn]);
}
static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
{
struct otpinfo *oi = (struct otpinfo *) oh;
uint k, row, col;
u32 otpp, st;
row = off / oi->cols;
col = off % oi->cols;
otpp = OTPP_START_BUSY |
((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
W_REG(&cc->otpprog, otpp);
for (k = 0;
((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
&& (k < OTPP_TRIES); k++)
;
if (k >= OTPP_TRIES) {
return 0xffff;
}
if (st & OTPP_READERR) {
return 0xffff;
}
st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
return (int)st;
}
/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
* osizew is oi->wsize (OTP size - GU size) in words
*/
static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
{
int ret = 0;
switch (sih->chip) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
break;
case BCM4313_CHIP_ID:
ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
break;
default:
break; /* Don't know about this chip */
}
return ret;
}
static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
{
uint k;
u32 otpp, st;
/* record word offset of General Use Region for various chipcommon revs */
if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
|| oi->sih->ccrev == 27) {
oi->otpgu_base = REVA4_OTPGU_BASE;
} else if (oi->sih->ccrev == 36) {
/* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
if (oi->wsize >= 128)
oi->otpgu_base = REVB8_OTPGU_BASE;
else
oi->otpgu_base = REV36_OTPGU_BASE;
} else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
oi->otpgu_base = REVB8_OTPGU_BASE;
}
/* First issue an init command so the status is up to date */
otpp =
OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
W_REG(&cc->otpprog, otpp);
for (k = 0;
((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
&& (k < OTPP_TRIES); k++)
;
if (k >= OTPP_TRIES) {
return;
}
/* Read OTP lock bits and subregion programmed indication bits */
oi->status = R_REG(&cc->otpstatus);
if ((oi->sih->chip == BCM43224_CHIP_ID)
|| (oi->sih->chip == BCM43225_CHIP_ID)) {
u32 p_bits;
p_bits =
(ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
OTPGU_P_MSK)
>> OTPGU_P_SHIFT;
oi->status |= (p_bits << OTPS_GUP_SHIFT);
}
/*
* h/w region base and fuse region limit are fixed to the top and
* the bottom of the general use region. Everything else can be flexible.
*/
oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
oi->hwlim = oi->wsize;
if (oi->status & OTPS_GUP_HW) {
oi->hwlim =
ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
oi->swbase = oi->hwlim;
} else
oi->swbase = oi->hwbase;
/* subtract fuse and checksum from beginning */
oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
if (oi->status & OTPS_GUP_SW) {
oi->swlim =
ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
oi->fbase = oi->swlim;
} else
oi->fbase = oi->swbase;
oi->flim = oi->wsize;
}
static void *ipxotp_init(struct si_pub *sih)
{
uint idx;
chipcregs_t *cc;
struct otpinfo *oi;
/* Make sure we're running IPX OTP */
if (!OTPTYPE_IPX(sih->ccrev))
return NULL;
/* Make sure OTP is not disabled */
if (ai_is_otp_disabled(sih))
return NULL;
/* OTP is always powered */
oi = &otpinfo;
/* Check for otp size */
switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
case 0:
/* Nothing there */
return NULL;
case 1: /* 32x64 */
oi->rows = 32;
oi->cols = 64;
oi->wsize = 128;
break;
case 2: /* 64x64 */
oi->rows = 64;
oi->cols = 64;
oi->wsize = 256;
break;
case 5: /* 96x64 */
oi->rows = 96;
oi->cols = 64;
oi->wsize = 384;
break;
case 7: /* 16x64 *//* 1024 bits */
oi->rows = 16;
oi->cols = 64;
oi->wsize = 64;
break;
default:
/* Don't know the geometry */
return NULL;
}
/* Retrieve OTP region info */
idx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
_ipxotp_init(oi, cc);
ai_setcoreidx(sih, idx);
return (void *)oi;
}
static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
{
struct otpinfo *oi = (struct otpinfo *) oh;
uint idx;
chipcregs_t *cc;
uint base, i, sz;
/* Validate region selection */
switch (region) {
case OTP_HW_RGN:
sz = (uint) oi->hwlim - oi->hwbase;
if (!(oi->status & OTPS_GUP_HW)) {
*wlen = sz;
return -ENODATA;
}
if (*wlen < sz) {
*wlen = sz;
return -EOVERFLOW;
}
base = oi->hwbase;
break;
case OTP_SW_RGN:
sz = ((uint) oi->swlim - oi->swbase);
if (!(oi->status & OTPS_GUP_SW)) {
*wlen = sz;
return -ENODATA;
}
if (*wlen < sz) {
*wlen = sz;
return -EOVERFLOW;
}
base = oi->swbase;
break;
case OTP_CI_RGN:
sz = OTPGU_CI_SZ;
if (!(oi->status & OTPS_GUP_CI)) {
*wlen = sz;
return -ENODATA;
}
if (*wlen < sz) {
*wlen = sz;
return -EOVERFLOW;
}
base = oi->otpgu_base + OTPGU_CI_OFF;
break;
case OTP_FUSE_RGN:
sz = (uint) oi->flim - oi->fbase;
if (!(oi->status & OTPS_GUP_FUSE)) {
*wlen = sz;
return -ENODATA;
}
if (*wlen < sz) {
*wlen = sz;
return -EOVERFLOW;
}
base = oi->fbase;
break;
case OTP_ALL_RGN:
sz = ((uint) oi->flim - oi->hwbase);
if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
*wlen = sz;
return -ENODATA;
}
if (*wlen < sz) {
*wlen = sz;
return -EOVERFLOW;
}
base = oi->hwbase;
break;
default:
return -EINVAL;
}
idx = ai_coreidx(oi->sih);
cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
/* Read the data */
for (i = 0; i < sz; i++)
data[i] = ipxotp_otpr(oh, cc, base + i);
ai_setcoreidx(oi->sih, idx);
*wlen = sz;
return 0;
}
static int ipxotp_nvread(void *oh, char *data, uint *len)
{
return -ENOTSUPP;
}
static struct otp_fn_s ipxotp_fn = {
(otp_size_t) ipxotp_size,
(otp_read_bit_t) ipxotp_read_bit,
(otp_init_t) ipxotp_init,
(otp_read_region_t) ipxotp_read_region,
(otp_nvread_t) ipxotp_nvread,
(otp_status_t) ipxotp_status
};
/*
* otp_status()
* otp_size()
* otp_read_bit()
* otp_init()
* otp_read_region()
* otp_nvread()
*/
int otp_status(void *oh)
{
struct otpinfo *oi = (struct otpinfo *) oh;
return oi->fn->status(oh);
}
int otp_size(void *oh)
{
struct otpinfo *oi = (struct otpinfo *) oh;
return oi->fn->size(oh);
}
u16 otp_read_bit(void *oh, uint offset)
{
struct otpinfo *oi = (struct otpinfo *) oh;
uint idx = ai_coreidx(oi->sih);
chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
ai_setcoreidx(oi->sih, idx);
return readBit;
}
void *otp_init(struct si_pub *sih)
{
struct otpinfo *oi;
void *ret = NULL;
oi = &otpinfo;
memset(oi, 0, sizeof(struct otpinfo));
oi->ccrev = sih->ccrev;
if (OTPTYPE_IPX(oi->ccrev))
oi->fn = &ipxotp_fn;
if (oi->fn == NULL) {
return NULL;
}
oi->sih = sih;
ret = (oi->fn->init) (sih);
return ret;
}
int
otp_read_region(struct si_pub *sih, int region, u16 *data,
uint *wlen) {
void *oh;
int err = 0;
if (ai_is_otp_disabled(sih)) {
err = -EPERM;
goto out;
}
oh = otp_init(sih);
if (oh == NULL) {
err = -EBADE;
goto out;
}
err = (((struct otpinfo *) oh)->fn->read_region)
(oh, region, data, wlen);
out:
return err;
}
int otp_nvread(void *oh, char *data, uint *len)
{
struct otpinfo *oi = (struct otpinfo *) oh;
return oi->fn->nvread(oh, data, len);
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_OTP_H_
#define _BRCM_OTP_H_
#include "types.h"
/* OTP regions */
#define OTP_HW_RGN 1
#define OTP_SW_RGN 2
#define OTP_CI_RGN 4
#define OTP_FUSE_RGN 8
#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */
/* OTP Size */
#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */
/* Fixed size subregions sizes in words */
#define OTPGU_CI_SZ 2
/* OTP usage */
#define OTP4325_FM_DISABLED_OFFSET 188
/* Exported functions */
extern int otp_status(void *oh);
extern int otp_size(void *oh);
extern u16 otp_read_bit(void *oh, uint offset);
extern void *otp_init(struct si_pub *sih);
extern int otp_read_region(struct si_pub *sih, int region, u16 *data,
uint *wlen);
extern int otp_nvread(void *oh, char *data, uint *len);
#endif /* _BRCM_OTP_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,294 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* phy_hal.h: functionality exported from the phy to higher layers
*/
#ifndef _BRCM_PHY_HAL_H_
#define _BRCM_PHY_HAL_H_
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
#include <phy_shim.h>
#define IDCODE_VER_MASK 0x0000000f
#define IDCODE_VER_SHIFT 0
#define IDCODE_MFG_MASK 0x00000fff
#define IDCODE_MFG_SHIFT 0
#define IDCODE_ID_MASK 0x0ffff000
#define IDCODE_ID_SHIFT 12
#define IDCODE_REV_MASK 0xf0000000
#define IDCODE_REV_SHIFT 28
#define NORADIO_ID 0xe4f5
#define NORADIO_IDCODE 0x4e4f5246
#define BCM2055_ID 0x2055
#define BCM2055_IDCODE 0x02055000
#define BCM2055A0_IDCODE 0x1205517f
#define BCM2056_ID 0x2056
#define BCM2056_IDCODE 0x02056000
#define BCM2056A0_IDCODE 0x1205617f
#define BCM2057_ID 0x2057
#define BCM2057_IDCODE 0x02057000
#define BCM2057A0_IDCODE 0x1205717f
#define BCM2064_ID 0x2064
#define BCM2064_IDCODE 0x02064000
#define BCM2064A0_IDCODE 0x0206417f
#define PHY_TPC_HW_OFF false
#define PHY_TPC_HW_ON true
#define PHY_PERICAL_DRIVERUP 1
#define PHY_PERICAL_WATCHDOG 2
#define PHY_PERICAL_PHYINIT 3
#define PHY_PERICAL_JOIN_BSS 4
#define PHY_PERICAL_START_IBSS 5
#define PHY_PERICAL_UP_BSS 6
#define PHY_PERICAL_CHAN 7
#define PHY_FULLCAL 8
#define PHY_PERICAL_DISABLE 0
#define PHY_PERICAL_SPHASE 1
#define PHY_PERICAL_MPHASE 2
#define PHY_PERICAL_MANUAL 3
#define PHY_HOLD_FOR_ASSOC 1
#define PHY_HOLD_FOR_SCAN 2
#define PHY_HOLD_FOR_RM 4
#define PHY_HOLD_FOR_PLT 8
#define PHY_HOLD_FOR_MUTE 16
#define PHY_HOLD_FOR_NOT_ASSOC 0x20
#define PHY_MUTE_FOR_PREISM 1
#define PHY_MUTE_ALL 0xffffffff
#define PHY_NOISE_FIXED_VAL (-95)
#define PHY_NOISE_FIXED_VAL_NPHY (-92)
#define PHY_NOISE_FIXED_VAL_LCNPHY (-92)
#define PHY_MODE_CAL 0x0002
#define PHY_MODE_NOISEM 0x0004
#define BRCMS_TXPWR_DB_FACTOR 4
/* a large TX Power as an init value to factor out of min() calculations,
* keep low enough to fit in an s8, units are .25 dBm
*/
#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
#define BRCMS_NUM_RATES_CCK 4
#define BRCMS_NUM_RATES_OFDM 8
#define BRCMS_NUM_RATES_MCS_1_STREAM 8
#define BRCMS_NUM_RATES_MCS_2_STREAM 8
#define BRCMS_NUM_RATES_MCS_3_STREAM 8
#define BRCMS_NUM_RATES_MCS_4_STREAM 8
#define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */
struct txpwr_limits {
u8 cck[BRCMS_NUM_RATES_CCK];
u8 ofdm[BRCMS_NUM_RATES_OFDM];
u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM];
u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM];
u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM];
u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
u8 mcs32;
};
struct tx_power {
u32 flags;
chanspec_t chanspec; /* txpwr report for this channel */
chanspec_t local_chanspec; /* channel on which we are associated */
u8 local_max; /* local max according to the AP */
u8 local_constraint; /* local constraint according to the AP */
s8 antgain[2]; /* Ant gain for each band - from SROM */
u8 rf_cores; /* count of RF Cores being reported */
u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */
u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain
* without adjustment
*/
u8 est_Pout_cck; /* Latest CCK tx power out estimate */
u8 tx_power_max[4]; /* Maximum target power among all rates */
u8 tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */
u8 user_limit[WL_TX_POWER_RATES]; /* User limit */
u8 reg_limit[WL_TX_POWER_RATES]; /* Regulatory power limit */
u8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */
u8 target[WL_TX_POWER_RATES]; /* Latest target power */
};
struct tx_inst_power {
u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */
u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */
};
struct chanvec {
u8 vec[MAXCHANNEL / NBBY];
};
struct shared_phy_params {
struct si_pub *sih;
void *physhim;
uint unit;
uint corerev;
uint bustype;
uint buscorerev;
char *vars;
u16 vid;
u16 did;
uint chip;
uint chiprev;
uint chippkg;
uint sromrev;
uint boardtype;
uint boardrev;
uint boardvendor;
u32 boardflags;
u32 boardflags2;
};
extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, void *regs,
int bandtype, char *vars, struct wiphy *wiphy);
extern void wlc_phy_detach(struct brcms_phy_pub *ppi);
extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
u16 *phyrev, u16 *radioid,
u16 *radiover);
extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih);
extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
extern void wlc_phy_init(struct brcms_phy_pub *ppi, chanspec_t chanspec);
extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
extern int wlc_phy_down(struct brcms_phy_pub *ppi);
extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi,
chanspec_t chanspec);
extern chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi,
chanspec_t newch);
extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
extern void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx);
extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag);
extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on);
extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on);
extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
bool wide_filter);
extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
chanvec_t *channels);
extern chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
uint band);
extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan,
u8 *_min_, u8 *_max_, int rate);
extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi,
uint chan, u8 *_max_, u8 *_min_);
extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi,
uint band, s32 *, s32 *, u32 *);
extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi,
struct txpwr_limits *,
chanspec_t chanspec);
extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm,
bool *override);
extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm,
bool override);
extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
struct txpwr_limits *);
extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi);
extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi,
bool hwpwrctrl);
extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi);
extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi);
extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih);
extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain,
u8 rxchain);
extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain,
u8 rxchain);
extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain,
u8 *rxchain);
extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih,
chanspec_t chanspec);
extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi);
extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock);
extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, mbool id, bool val);
extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, mbool flags);
extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi,
struct tx_power *power, uint channel);
extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal);
extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi);
extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi,
u8 txpwr_percent);
extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war);
extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih,
bool bf_preempt);
extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap);
extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end);
extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi);
extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
u8 mcs_offset);
extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
#endif /* _BRCM_PHY_HAL_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_PHY_LCN_H_
#define _BRCM_PHY_LCN_H_
#include <types.h>
struct brcms_phy_lcnphy {
int lcnphy_txrf_sp_9_override;
u8 lcnphy_full_cal_channel;
u8 lcnphy_cal_counter;
u16 lcnphy_cal_temper;
bool lcnphy_recal;
u8 lcnphy_rc_cap;
u32 lcnphy_mcs20_po;
u8 lcnphy_tr_isolation_mid;
u8 lcnphy_tr_isolation_low;
u8 lcnphy_tr_isolation_hi;
u8 lcnphy_bx_arch;
u8 lcnphy_rx_power_offset;
u8 lcnphy_rssi_vf;
u8 lcnphy_rssi_vc;
u8 lcnphy_rssi_gs;
u8 lcnphy_tssi_val;
u8 lcnphy_rssi_vf_lowtemp;
u8 lcnphy_rssi_vc_lowtemp;
u8 lcnphy_rssi_gs_lowtemp;
u8 lcnphy_rssi_vf_hightemp;
u8 lcnphy_rssi_vc_hightemp;
u8 lcnphy_rssi_gs_hightemp;
s16 lcnphy_pa0b0;
s16 lcnphy_pa0b1;
s16 lcnphy_pa0b2;
u16 lcnphy_rawtempsense;
u8 lcnphy_measPower;
u8 lcnphy_tempsense_slope;
u8 lcnphy_freqoffset_corr;
u8 lcnphy_tempsense_option;
u8 lcnphy_tempcorrx;
bool lcnphy_iqcal_swp_dis;
bool lcnphy_hw_iqcal_en;
uint lcnphy_bandedge_corr;
bool lcnphy_spurmod;
u16 lcnphy_tssi_tx_cnt;
u16 lcnphy_tssi_idx;
u16 lcnphy_tssi_npt;
u16 lcnphy_target_tx_freq;
s8 lcnphy_tx_power_idx_override;
u16 lcnphy_noise_samples;
u32 lcnphy_papdRxGnIdx;
u32 lcnphy_papd_rxGnCtrl_init;
u32 lcnphy_gain_idx_14_lowword;
u32 lcnphy_gain_idx_14_hiword;
u32 lcnphy_gain_idx_27_lowword;
u32 lcnphy_gain_idx_27_hiword;
s16 lcnphy_ofdmgainidxtableoffset;
s16 lcnphy_dsssgainidxtableoffset;
u32 lcnphy_tr_R_gain_val;
u32 lcnphy_tr_T_gain_val;
s8 lcnphy_input_pwr_offset_db;
u16 lcnphy_Med_Low_Gain_db;
u16 lcnphy_Very_Low_Gain_db;
s8 lcnphy_lastsensed_temperature;
s8 lcnphy_pkteng_rssi_slope;
u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
u8 lcnphy_volt_winner;
u8 lcnphy_volt_low;
u8 lcnphy_54_48_36_24mbps_backoff;
u8 lcnphy_11n_backoff;
u8 lcnphy_lowerofdm;
u8 lcnphy_cck;
u8 lcnphy_psat_2pt3_detected;
s32 lcnphy_lowest_Re_div_Im;
s8 lcnphy_final_papd_cal_idx;
u16 lcnphy_extstxctrl4;
u16 lcnphy_extstxctrl0;
u16 lcnphy_extstxctrl1;
s16 lcnphy_cck_dig_filt_type;
s16 lcnphy_ofdm_dig_filt_type;
struct lcnphy_cal_results lcnphy_cal_results;
u8 lcnphy_psat_pwr;
u8 lcnphy_psat_indx;
s32 lcnphy_min_phase;
u8 lcnphy_final_idx;
u8 lcnphy_start_idx;
u8 lcnphy_current_index;
u16 lcnphy_logen_buf_1;
u16 lcnphy_local_ovr_2;
u16 lcnphy_local_oval_6;
u16 lcnphy_local_oval_5;
u16 lcnphy_logen_mixer_1;
u8 lcnphy_aci_stat;
uint lcnphy_aci_start_time;
s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
};
#endif /* _BRCM_PHY_LCN_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,294 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "phy_qmath.h"
/*
Description: This function make 16 bit unsigned multiplication. To fit the output into
16 bits the 32 bit multiplication result is right shifted by 16 bits.
*/
u16 qm_mulu16(u16 op1, u16 op2)
{
return (u16) (((u32) op1 * (u32) op2) >> 16);
}
/*
Description: This function make 16 bit multiplication and return the result in 16 bits.
To fit the multiplication result into 16 bits the multiplication result is right shifted by
15 bits. Right shifting 15 bits instead of 16 bits is done to remove the extra sign bit formed
due to the multiplication.
When both the 16bit inputs are 0x8000 then the output is saturated to 0x7fffffff.
*/
s16 qm_muls16(s16 op1, s16 op2)
{
s32 result;
if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) {
result = 0x7fffffff;
} else {
result = ((s32) (op1) * (s32) (op2));
}
return (s16) (result >> 15);
}
/*
Description: This function add two 32 bit numbers and return the 32bit result.
If the result overflow 32 bits, the output will be saturated to 32bits.
*/
s32 qm_add32(s32 op1, s32 op2)
{
s32 result;
result = op1 + op2;
if (op1 < 0 && op2 < 0 && result > 0) {
result = 0x80000000;
} else if (op1 > 0 && op2 > 0 && result < 0) {
result = 0x7fffffff;
}
return result;
}
/*
Description: This function add two 16 bit numbers and return the 16bit result.
If the result overflow 16 bits, the output will be saturated to 16bits.
*/
s16 qm_add16(s16 op1, s16 op2)
{
s16 result;
s32 temp = (s32) op1 + (s32) op2;
if (temp > (s32) 0x7fff) {
result = (s16) 0x7fff;
} else if (temp < (s32) 0xffff8000) {
result = (s16) 0xffff8000;
} else {
result = (s16) temp;
}
return result;
}
/*
Description: This function make 16 bit subtraction and return the 16bit result.
If the result overflow 16 bits, the output will be saturated to 16bits.
*/
s16 qm_sub16(s16 op1, s16 op2)
{
s16 result;
s32 temp = (s32) op1 - (s32) op2;
if (temp > (s32) 0x7fff) {
result = (s16) 0x7fff;
} else if (temp < (s32) 0xffff8000) {
result = (s16) 0xffff8000;
} else {
result = (s16) temp;
}
return result;
}
/*
Description: This function make a 32 bit saturated left shift when the specified shift
is +ve. This function will make a 32 bit right shift when the specified shift is -ve.
This function return the result after shifting operation.
*/
s32 qm_shl32(s32 op, int shift)
{
int i;
s32 result;
result = op;
if (shift > 31)
shift = 31;
else if (shift < -31)
shift = -31;
if (shift >= 0) {
for (i = 0; i < shift; i++) {
result = qm_add32(result, result);
}
} else {
result = result >> (-shift);
}
return result;
}
/*
Description: This function make a 16 bit saturated left shift when the specified shift
is +ve. This function will make a 16 bit right shift when the specified shift is -ve.
This function return the result after shifting operation.
*/
s16 qm_shl16(s16 op, int shift)
{
int i;
s16 result;
result = op;
if (shift > 15)
shift = 15;
else if (shift < -15)
shift = -15;
if (shift > 0) {
for (i = 0; i < shift; i++) {
result = qm_add16(result, result);
}
} else {
result = result >> (-shift);
}
return result;
}
/*
Description: This function make a 16 bit right shift when shift is +ve.
This function make a 16 bit saturated left shift when shift is -ve. This function
return the result of the shift operation.
*/
s16 qm_shr16(s16 op, int shift)
{
return qm_shl16(op, -shift);
}
/*
Description: This function return the number of redundant sign bits in a 32 bit number.
Example: qm_norm32(0x00000080) = 23
*/
s16 qm_norm32(s32 op)
{
u16 u16extraSignBits;
if (op == 0) {
return 31;
} else {
u16extraSignBits = 0;
while ((op >> 31) == (op >> 30)) {
u16extraSignBits++;
op = op << 1;
}
}
return u16extraSignBits;
}
/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */
static const s16 log_table[] = {
0,
1455,
2866,
4236,
5568,
6863,
8124,
9352,
10549,
11716,
12855,
13968,
15055,
16117,
17156,
18173,
19168,
20143,
21098,
22034,
22952,
23852,
24736,
25604,
26455,
27292,
28114,
28922,
29717,
30498,
31267,
32024
};
#define LOG_TABLE_SIZE 32 /* log_table size */
#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */
#define Q_LOG_TABLE 15 /* qformat of log_table */
#define LOG10_2 19728 /* log10(2) in q.16 */
/*
Description:
This routine takes the input number N and its q format qN and compute
the log10(N). This routine first normalizes the input no N. Then N is in mag*(2^x) format.
mag is any number in the range 2^30-(2^31 - 1). Then log2(mag * 2^x) = log2(mag) + x is computed.
From that log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
This routine looks the log2 value in the table considering LOG2_LOG_TABLE_SIZE+1 MSBs.
As the MSB is always 1, only next LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup.
Next 16 MSBs are used for interpolation.
Inputs:
N - number to which log10 has to be found.
qN - q format of N
log10N - address where log10(N) will be written.
qLog10N - address where log10N qformat will be written.
Note/Problem:
For accurate results input should be in normalized or near normalized form.
*/
void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
{
s16 s16norm, s16tableIndex, s16errorApproximation;
u16 u16offset;
s32 s32log;
/* normalize the N. */
s16norm = qm_norm32(N);
N = N << s16norm;
/* The qformat of N after normalization.
* -30 is added to treat the no as between 1.0 to 2.0
* i.e. after adding the -30 to the qformat the decimal point will be
* just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
* at the right side of 30th bit.
*/
qN = qN + s16norm - 30;
/* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */
s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
/* remove the MSB. the MSB is always 1 after normalization. */
s16tableIndex =
s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
/* take the offset as the 16 MSBS after table index.
*/
u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
/* look the log value in the table. */
s32log = log_table[s16tableIndex]; /* q.15 format */
/* interpolate using the offset. */
s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex])); /* q.15 */
s32log = qm_add16((s16) s32log, s16errorApproximation); /* q.15 format */
/* adjust for the qformat of the N as
* log2(mag * 2^x) = log2(mag) + x
*/
s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */
/* normalize the result. */
s16norm = qm_norm32(s32log);
/* bring all the important bits into lower 16 bits */
s32log = qm_shl32(s32log, s16norm - 16); /* q.15+s16norm-16 format */
/* compute the log10(N) by multiplying log2(N) with log10(2).
* as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
* log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
*/
*log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
/* write the q format of the result. */
*qLog10N = 15 + s16norm - 16 + 1;
return;
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_QMATH_H_
#define _BRCM_QMATH_H_
#include <types.h>
u16 qm_mulu16(u16 op1, u16 op2);
s16 qm_muls16(s16 op1, s16 op2);
s32 qm_add32(s32 op1, s32 op2);
s16 qm_add16(s16 op1, s16 op2);
s16 qm_sub16(s16 op1, s16 op2);
s32 qm_shl32(s32 op, int shift);
s16 qm_shl16(s16 op, int shift);
s16 qm_shr16(s16 op, int shift);
s16 qm_norm32(s32 op);
void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N);
#endif /* #ifndef _BRCM_QMATH_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define NPHY_TBL_ID_GAIN1 0
#define NPHY_TBL_ID_GAIN2 1
#define NPHY_TBL_ID_GAINBITS1 2
#define NPHY_TBL_ID_GAINBITS2 3
#define NPHY_TBL_ID_GAINLIMIT 4
#define NPHY_TBL_ID_WRSSIGainLimit 5
#define NPHY_TBL_ID_RFSEQ 7
#define NPHY_TBL_ID_AFECTRL 8
#define NPHY_TBL_ID_ANTSWCTRLLUT 9
#define NPHY_TBL_ID_IQLOCAL 15
#define NPHY_TBL_ID_NOISEVAR 16
#define NPHY_TBL_ID_SAMPLEPLAY 17
#define NPHY_TBL_ID_CORE1TXPWRCTL 26
#define NPHY_TBL_ID_CORE2TXPWRCTL 27
#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL 30
#define NPHY_TBL_ID_EPSILONTBL0 31
#define NPHY_TBL_ID_SCALARTBL0 32
#define NPHY_TBL_ID_EPSILONTBL1 33
#define NPHY_TBL_ID_SCALARTBL1 34
#define NPHY_TO_BPHY_OFF 0xc00
#define NPHY_BandControl_currentBand 0x0001
#define RFCC_CHIP0_PU 0x0400
#define RFCC_POR_FORCE 0x0040
#define RFCC_OE_POR_FORCE 0x0080
#define NPHY_RfctrlIntc_override_OFF 0
#define NPHY_RfctrlIntc_override_TRSW 1
#define NPHY_RfctrlIntc_override_PA 2
#define NPHY_RfctrlIntc_override_EXT_LNA_PU 3
#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN 4
#define RIFS_ENABLE 0x80
#define BPHY_BAND_SEL_UP20 0x10
#define NPHY_MLenable 0x02
#define NPHY_RfseqMode_CoreActv_override 0x0001
#define NPHY_RfseqMode_Trigger_override 0x0002
#define NPHY_RfseqCoreActv_TxRxChain0 (0x11)
#define NPHY_RfseqCoreActv_TxRxChain1 (0x22)
#define NPHY_RfseqTrigger_rx2tx 0x0001
#define NPHY_RfseqTrigger_tx2rx 0x0002
#define NPHY_RfseqTrigger_updategainh 0x0004
#define NPHY_RfseqTrigger_updategainl 0x0008
#define NPHY_RfseqTrigger_updategainu 0x0010
#define NPHY_RfseqTrigger_reset2rx 0x0020
#define NPHY_RfseqStatus_rx2tx 0x0001
#define NPHY_RfseqStatus_tx2rx 0x0002
#define NPHY_RfseqStatus_updategainh 0x0004
#define NPHY_RfseqStatus_updategainl 0x0008
#define NPHY_RfseqStatus_updategainu 0x0010
#define NPHY_RfseqStatus_reset2rx 0x0020
#define NPHY_ClassifierCtrl_cck_en 0x1
#define NPHY_ClassifierCtrl_ofdm_en 0x2
#define NPHY_ClassifierCtrl_waited_en 0x4
#define NPHY_IQFlip_ADC1 0x0001
#define NPHY_IQFlip_ADC2 0x0010
#define NPHY_sampleCmd_STOP 0x0002
#define RX_GF_OR_MM 0x0004
#define RX_GF_MM_AUTO 0x0100
#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN 0x8000
#define NPHY_IqestCmd_iqstart 0x1
#define NPHY_IqestCmd_iqMode 0x2
#define NPHY_TxPwrCtrlCmd_pwrIndex_init 0x40
#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 0x19
#define PRIM_SEL_UP20 0x8000
#define NPHY_RFSEQ_RX2TX 0x0
#define NPHY_RFSEQ_TX2RX 0x1
#define NPHY_RFSEQ_RESET2RX 0x2
#define NPHY_RFSEQ_UPDATEGAINH 0x3
#define NPHY_RFSEQ_UPDATEGAINL 0x4
#define NPHY_RFSEQ_UPDATEGAINU 0x5
#define NPHY_RFSEQ_CMD_NOP 0x0
#define NPHY_RFSEQ_CMD_RXG_FBW 0x1
#define NPHY_RFSEQ_CMD_TR_SWITCH 0x2
#define NPHY_RFSEQ_CMD_EXT_PA 0x3
#define NPHY_RFSEQ_CMD_RXPD_TXPD 0x4
#define NPHY_RFSEQ_CMD_TX_GAIN 0x5
#define NPHY_RFSEQ_CMD_RX_GAIN 0x6
#define NPHY_RFSEQ_CMD_SET_HPF_BW 0x7
#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS 0x8
#define NPHY_RFSEQ_CMD_END 0xf
#define NPHY_REV3_RFSEQ_CMD_NOP 0x0
#define NPHY_REV3_RFSEQ_CMD_RXG_FBW 0x1
#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH 0x2
#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU 0x3
#define NPHY_REV3_RFSEQ_CMD_EXT_PA 0x4
#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD 0x5
#define NPHY_REV3_RFSEQ_CMD_TX_GAIN 0x6
#define NPHY_REV3_RFSEQ_CMD_RX_GAIN 0x7
#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS 0x8
#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC 0x9
#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC 0xa
#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC 0xb
#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC 0xc
#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC 0xd
#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC 0xe
#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS 0xf
#define NPHY_REV3_RFSEQ_CMD_END 0x1f
#define NPHY_RSSI_SEL_W1 0x0
#define NPHY_RSSI_SEL_W2 0x1
#define NPHY_RSSI_SEL_NB 0x2
#define NPHY_RSSI_SEL_IQ 0x3
#define NPHY_RSSI_SEL_TSSI_2G 0x4
#define NPHY_RSSI_SEL_TSSI_5G 0x5
#define NPHY_RSSI_SEL_TBD 0x6
#define NPHY_RAIL_I 0x0
#define NPHY_RAIL_Q 0x1
#define NPHY_FORCESIG_DECODEGATEDCLKS 0x8
#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
#define NPHY_REV7_RfctrlOverride_cmd_rx_pu 0x1
#define NPHY_REV7_RfctrlOverride_cmd_tx_pu 0x2
#define NPHY_REV7_RfctrlOverride_cmd_rxgain 0x3
#define NPHY_REV7_RfctrlOverride_cmd_txgain 0x4
#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK 0x0ff00
#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
#define NPHY_REV7_TXGAINCODE_TGAIN_MASK 0x7fff
#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK 0x8000
#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
#define NPHY_IqestIqAccLo(core) ((core == 0) ? 0x12c : 0x134)
#define NPHY_IqestIqAccHi(core) ((core == 0) ? 0x12d : 0x135)
#define NPHY_IqestipwrAccLo(core) ((core == 0) ? 0x12e : 0x136)
#define NPHY_IqestipwrAccHi(core) ((core == 0) ? 0x12f : 0x137)
#define NPHY_IqestqpwrAccLo(core) ((core == 0) ? 0x130 : 0x138)
#define NPHY_IqestqpwrAccHi(core) ((core == 0) ? 0x131 : 0x139)

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <types.h>
#include "phy_int.h"
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[];
extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
extern const struct phytbl_info dot11lcnphytbl_info_rev0[];
extern const u32 dot11lcnphytbl_info_sz_rev0;
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[];
extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[];
extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
struct lcnphy_tx_gain_tbl_entry {
unsigned char gm;
unsigned char pga;
unsigned char pad;
unsigned char dac;
unsigned char bb_mult;
};
extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
extern const struct
lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define ANT_SWCTRL_TBL_REV3_IDX (0)
#include <types.h>
#include "phy_int.h"
extern const struct phytbl_info mimophytbl_info_rev0[],
mimophytbl_info_rev0_volatile[];
extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile;
extern const struct phytbl_info mimophytbl_info_rev3[],
mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[],
mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[];
extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile,
mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2,
mimophytbl_info_sz_rev3_volatile3;
extern const u32 noise_var_tbl_rev3[];
extern const struct phytbl_info mimophytbl_info_rev7[];
extern const u32 mimophytbl_info_sz_rev7;
extern const u32 noise_var_tbl_rev7[];
extern const struct phytbl_info mimophytbl_info_rev16[];
extern const u32 mimophytbl_info_sz_rev16;

View File

@ -1,218 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
* WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
* On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
* access to wlc_hw pointer.
*/
#include <linux/slab.h>
#include <net/mac80211.h>
#include "bmac.h"
#include "main.h"
#include "mac80211_if.h"
#include "phy_shim.h"
/* PHY SHIM module specific state */
struct phy_shim_info {
struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */
void *wlc; /* pointer to main wlc structure */
void *wl; /* pointer to os-specific private state */
};
struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
void *wl, void *wlc) {
struct phy_shim_info *physhim = NULL;
physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC);
if (!physhim) {
wiphy_err(wlc_hw->wlc->wiphy,
"wl%d: wlc_phy_shim_attach: out of mem\n",
wlc_hw->unit);
return NULL;
}
physhim->wlc_hw = wlc_hw;
physhim->wlc = wlc;
physhim->wl = wl;
return physhim;
}
void wlc_phy_shim_detach(struct phy_shim_info *physhim)
{
kfree(physhim);
}
struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
void (*fn) (void *arg), void *arg,
const char *name)
{
return (struct wlapi_timer *)
brcms_init_timer(physhim->wl, fn, arg, name);
}
void wlapi_free_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
{
brcms_free_timer(physhim->wl, (struct brcms_timer *)t);
}
void
wlapi_add_timer(struct phy_shim_info *physhim, struct wlapi_timer *t, uint ms,
int periodic)
{
brcms_add_timer(physhim->wl, (struct brcms_timer *)t, ms, periodic);
}
bool wlapi_del_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
{
return brcms_del_timer(physhim->wl, (struct brcms_timer *)t);
}
void wlapi_intrson(struct phy_shim_info *physhim)
{
brcms_intrson(physhim->wl);
}
u32 wlapi_intrsoff(struct phy_shim_info *physhim)
{
return brcms_intrsoff(physhim->wl);
}
void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask)
{
brcms_intrsrestore(physhim->wl, macintmask);
}
void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v)
{
brcms_b_write_shm(physhim->wlc_hw, offset, v);
}
u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset)
{
return brcms_b_read_shm(physhim->wlc_hw, offset);
}
void
wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask,
u16 val, int bands)
{
brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands);
}
void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags)
{
brcms_b_corereset(physhim->wlc_hw, flags);
}
void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim)
{
brcms_c_suspend_mac_and_wait(physhim->wlc);
}
void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode)
{
brcms_b_switch_macfreq(physhim->wlc_hw, spurmode);
}
void wlapi_enable_mac(struct phy_shim_info *physhim)
{
brcms_c_enable_mac(physhim->wlc);
}
void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val)
{
brcms_b_mctrl(physhim->wlc_hw, mask, val);
}
void wlapi_bmac_phy_reset(struct phy_shim_info *physhim)
{
brcms_b_phy_reset(physhim->wlc_hw);
}
void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw)
{
brcms_b_bw_set(physhim->wlc_hw, bw);
}
u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim)
{
return brcms_b_get_txant(physhim->wlc_hw);
}
void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk)
{
brcms_b_phyclk_fgc(physhim->wlc_hw, clk);
}
void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk)
{
brcms_b_macphyclk_set(physhim->wlc_hw, clk);
}
void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on)
{
brcms_b_core_phypll_ctl(physhim->wlc_hw, on);
}
void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim)
{
brcms_b_core_phypll_reset(physhim->wlc_hw);
}
void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim)
{
brcms_c_ucode_wake_override_set(physhim->wlc_hw,
BRCMS_WAKE_OVERRIDE_PHYREG);
}
void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim)
{
brcms_c_ucode_wake_override_clear(physhim->wlc_hw,
BRCMS_WAKE_OVERRIDE_PHYREG);
}
void
wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset,
int len, void *buf)
{
brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf);
}
u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate)
{
return brcms_b_rate_shm_offset(physhim->wlc_hw, rate);
}
void wlapi_ucode_sample_init(struct phy_shim_info *physhim)
{
}
void
wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf,
int len, u32 sel)
{
brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
}
void
wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
int l, u32 sel)
{
brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
}

View File

@ -1,164 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* phy_shim.h: stuff defined in phy_shim.c and included only by the phy
*/
#ifndef _BRCM_PHY_SHIM_H_
#define _BRCM_PHY_SHIM_H_
#include "types.h"
#define RADAR_TYPE_NONE 0 /* Radar type None */
#define RADAR_TYPE_ETSI_1 1 /* ETSI 1 Radar type */
#define RADAR_TYPE_ETSI_2 2 /* ETSI 2 Radar type */
#define RADAR_TYPE_ETSI_3 3 /* ETSI 3 Radar type */
#define RADAR_TYPE_ITU_E 4 /* ITU E Radar type */
#define RADAR_TYPE_ITU_K 5 /* ITU K Radar type */
#define RADAR_TYPE_UNCLASSIFIED 6 /* Unclassified Radar type */
#define RADAR_TYPE_BIN5 7 /* long pulse radar type */
#define RADAR_TYPE_STG2 8 /* staggered-2 radar */
#define RADAR_TYPE_STG3 9 /* staggered-3 radar */
#define RADAR_TYPE_FRA 10 /* French radar */
/* French radar pulse widths */
#define FRA_T1_20MHZ 52770
#define FRA_T2_20MHZ 61538
#define FRA_T3_20MHZ 66002
#define FRA_T1_40MHZ 105541
#define FRA_T2_40MHZ 123077
#define FRA_T3_40MHZ 132004
#define FRA_ERR_20MHZ 60
#define FRA_ERR_40MHZ 120
#define ANTSEL_NA 0 /* No boardlevel selection available */
#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */
#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */
/* Rx Antenna diversity control values */
#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */
#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */
#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */
#define WL_ANT_IDX_1 0 /* antenna index 1 */
#define WL_ANT_IDX_2 1 /* antenna index 2 */
/* values for n_preamble_type */
#define BRCMS_N_PREAMBLE_MIXEDMODE 0
#define BRCMS_N_PREAMBLE_GF 1
#define BRCMS_N_PREAMBLE_GF_BRCM 2
#define WL_TX_POWER_RATES_LEGACY 45
#define WL_TX_POWER_MCS20_FIRST 12
#define WL_TX_POWER_MCS20_NUM 16
#define WL_TX_POWER_MCS40_FIRST 28
#define WL_TX_POWER_MCS40_NUM 17
#define WL_TX_POWER_RATES 101
#define WL_TX_POWER_CCK_FIRST 0
#define WL_TX_POWER_CCK_NUM 4
#define WL_TX_POWER_OFDM_FIRST 4 /* Index for first 20MHz OFDM SISO rate */
#define WL_TX_POWER_OFDM20_CDD_FIRST 12 /* Index for first 20MHz OFDM CDD rate */
#define WL_TX_POWER_OFDM40_SISO_FIRST 52 /* Index for first 40MHz OFDM SISO rate */
#define WL_TX_POWER_OFDM40_CDD_FIRST 60 /* Index for first 40MHz OFDM CDD rate */
#define WL_TX_POWER_OFDM_NUM 8
#define WL_TX_POWER_MCS20_SISO_FIRST 20 /* Index for first 20MHz MCS SISO rate */
#define WL_TX_POWER_MCS20_CDD_FIRST 28 /* Index for first 20MHz MCS CDD rate */
#define WL_TX_POWER_MCS20_STBC_FIRST 36 /* Index for first 20MHz MCS STBC rate */
#define WL_TX_POWER_MCS20_SDM_FIRST 44 /* Index for first 20MHz MCS SDM rate */
#define WL_TX_POWER_MCS40_SISO_FIRST 68 /* Index for first 40MHz MCS SISO rate */
#define WL_TX_POWER_MCS40_CDD_FIRST 76 /* Index for first 40MHz MCS CDD rate */
#define WL_TX_POWER_MCS40_STBC_FIRST 84 /* Index for first 40MHz MCS STBC rate */
#define WL_TX_POWER_MCS40_SDM_FIRST 92 /* Index for first 40MHz MCS SDM rate */
#define WL_TX_POWER_MCS_1_STREAM_NUM 8
#define WL_TX_POWER_MCS_2_STREAM_NUM 8
#define WL_TX_POWER_MCS_32 100 /* Index for 40MHz rate MCS 32 */
#define WL_TX_POWER_MCS_32_NUM 1
/* sslpnphy specifics */
#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 /* Index for first 20MHz MCS SISO rate */
/* struct tx_power::flags bits */
#define WL_TX_POWER_F_ENABLED 1
#define WL_TX_POWER_F_HW 2
#define WL_TX_POWER_F_MIMO 4
#define WL_TX_POWER_F_SISO 8
/* values to force tx/rx chain */
#define BRCMS_N_TXRX_CHAIN0 0
#define BRCMS_N_TXRX_CHAIN1 1
extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
void *wl, void *wlc);
extern void wlc_phy_shim_detach(struct phy_shim_info *physhim);
/* PHY to WL utility functions */
extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
void (*fn) (void *arg), void *arg,
const char *name);
extern void wlapi_free_timer(struct phy_shim_info *physhim,
struct wlapi_timer *t);
extern void wlapi_add_timer(struct phy_shim_info *physhim,
struct wlapi_timer *t, uint ms, int periodic);
extern bool wlapi_del_timer(struct phy_shim_info *physhim,
struct wlapi_timer *t);
extern void wlapi_intrson(struct phy_shim_info *physhim);
extern u32 wlapi_intrsoff(struct phy_shim_info *physhim);
extern void wlapi_intrsrestore(struct phy_shim_info *physhim,
u32 macintmask);
extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset,
u16 v);
extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset);
extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx,
u16 mask, u16 val, int bands);
extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags);
extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim);
extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode);
extern void wlapi_enable_mac(struct phy_shim_info *physhim);
extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask,
u32 val);
extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim);
extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw);
extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk);
extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk);
extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on);
extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim);
extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *
physhim);
extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *
physhim);
extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o,
int len, void *buf);
extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim,
u8 rate);
extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim);
extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint,
void *buf, int, u32 sel);
extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint,
const void *buf, int, u32);
extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim,
u32 phy_mode);
extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
#endif /* _BRCM_PHY_SHIM_H_ */

View File

@ -1,474 +0,0 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <brcm_hw_ids.h>
#include <chipcommon.h>
#include <brcmu_utils.h>
#include "pub.h"
#include "aiutils.h"
#include "pmu.h"
/*
* external LPO crystal frequency
*/
#define EXT_ILP_HZ 32768
/*
* Duration for ILP clock frequency measurment in milliseconds
*
* remark: 1000 must be an integer multiple of this duration
*/
#define ILP_CALC_DUR 10
/* Fields in pmucontrol */
#define PCTL_ILP_DIV_MASK 0xffff0000
#define PCTL_ILP_DIV_SHIFT 16
#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
#define PCTL_HT_REQ_EN 0x00000100
#define PCTL_ALP_REQ_EN 0x00000080
#define PCTL_XTALFREQ_MASK 0x0000007c
#define PCTL_XTALFREQ_SHIFT 2
#define PCTL_ILP_DIV_EN 0x00000002
#define PCTL_LPO_SEL 0x00000001
/* ILP clock */
#define ILP_CLOCK 32000
/* ALP clock on pre-PMU chips */
#define ALP_CLOCK 20000000
/* pmustatus */
#define PST_EXTLPOAVAIL 0x0100
#define PST_WDRESET 0x0080
#define PST_INTPEND 0x0040
#define PST_SBCLKST 0x0030
#define PST_SBCLKST_ILP 0x0010
#define PST_SBCLKST_ALP 0x0020
#define PST_SBCLKST_HT 0x0030
#define PST_ALPAVAIL 0x0008
#define PST_HTAVAIL 0x0004
#define PST_RESINIT 0x0003
/* PMU resource bit position */
#define PMURES_BIT(bit) (1 << (bit))
/* PMU corerev and chip specific PLL controls.
* PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
* to differentiate different PLLs controlled by the same PMU rev.
*/
/* pllcontrol registers */
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
#define PMU1_PLL0_PLLCTL0 0
#define PMU1_PLL0_PLLCTL1 1
#define PMU1_PLL0_PLLCTL2 2
#define PMU1_PLL0_PLLCTL3 3
#define PMU1_PLL0_PLLCTL4 4
#define PMU1_PLL0_PLLCTL5 5
/* pmu XtalFreqRatio */
#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31
/* 4313 resources */
#define RES4313_BB_PU_RSRC 0
#define RES4313_ILP_REQ_RSRC 1
#define RES4313_XTAL_PU_RSRC 2
#define RES4313_ALP_AVAIL_RSRC 3
#define RES4313_RADIO_PU_RSRC 4
#define RES4313_BG_PU_RSRC 5
#define RES4313_VREG1P4_PU_RSRC 6
#define RES4313_AFE_PWRSW_RSRC 7
#define RES4313_RX_PWRSW_RSRC 8
#define RES4313_TX_PWRSW_RSRC 9
#define RES4313_BB_PWRSW_RSRC 10
#define RES4313_SYNTH_PWRSW_RSRC 11
#define RES4313_MISC_PWRSW_RSRC 12
#define RES4313_BB_PLL_PWRSW_RSRC 13
#define RES4313_HT_AVAIL_RSRC 14
#define RES4313_MACPHY_CLK_AVAIL_RSRC 15
/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
{
u32 min_mask = 0, max_mask = 0;
uint rsrcs;
/* # resources */
rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
/* determine min/max rsrc masks */
switch (sih->chip) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
/* ??? */
break;
case BCM4313_CHIP_ID:
min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
PMURES_BIT(RES4313_XTAL_PU_RSRC) |
PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
max_mask = 0xffff;
break;
default:
break;
}
*pmin = min_mask;
*pmax = max_mask;
}
static void
si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
{
u32 tmp = 0;
switch (sih->chip) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
if (spuravoid == 1) {
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
W_REG(&cc->pllcontrol_data, 0x11500010);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
W_REG(&cc->pllcontrol_data, 0x000C0C06);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
W_REG(&cc->pllcontrol_data, 0x0F600a08);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
W_REG(&cc->pllcontrol_data, 0x00000000);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
W_REG(&cc->pllcontrol_data, 0x2001E920);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
W_REG(&cc->pllcontrol_data, 0x88888815);
} else {
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
W_REG(&cc->pllcontrol_data, 0x11100010);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
W_REG(&cc->pllcontrol_data, 0x000c0c06);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
W_REG(&cc->pllcontrol_data, 0x03000a08);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
W_REG(&cc->pllcontrol_data, 0x00000000);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
W_REG(&cc->pllcontrol_data, 0x200005c0);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
W_REG(&cc->pllcontrol_data, 0x88888815);
}
tmp = 1 << 10;
break;
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
W_REG(&cc->pllcontrol_data, 0x11100008);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
W_REG(&cc->pllcontrol_data, 0x0c000c06);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
W_REG(&cc->pllcontrol_data, 0x03000a08);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
W_REG(&cc->pllcontrol_data, 0x00000000);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
W_REG(&cc->pllcontrol_data, 0x200005c0);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
W_REG(&cc->pllcontrol_data, 0x88888855);
tmp = 1 << 10;
break;
default:
/* bail out */
return;
}
tmp |= R_REG(&cc->pmucontrol);
W_REG(&cc->pmucontrol, tmp);
}
u32 si_pmu_ilp_clock(struct si_pub *sih)
{
static u32 ilpcycles_per_sec;
if (!PMUCTL_ENAB(sih))
return ILP_CLOCK;
if (ilpcycles_per_sec == 0) {
u32 start, end, delta;
u32 origidx = ai_coreidx(sih);
chipcregs_t *cc = ai_setcoreidx(sih, SI_CC_IDX);
start = R_REG(&cc->pmutimer);
mdelay(ILP_CALC_DUR);
end = R_REG(&cc->pmutimer);
delta = end - start;
ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
ai_setcoreidx(sih, origidx);
}
return ilpcycles_per_sec;
}
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
{
uint delay = PMU_MAX_TRANSITION_DLY;
switch (sih->chip) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
case BCM4313_CHIP_ID:
delay = 3700;
break;
default:
break;
}
return (u16) delay;
}
void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
{
chipcregs_t *cc;
uint origidx;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* Read/write a chipcontrol reg */
u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol_addr), ~0,
reg);
return ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, chipcontrol_data), mask, val);
}
/* Read/write a regcontrol reg */
u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr), ~0,
reg);
return ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, regcontrol_data), mask, val);
}
/* Read/write a pllcontrol reg */
u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pllcontrol_addr), ~0,
reg);
return ai_corereg(sih, SI_CC_IDX,
offsetof(chipcregs_t, pllcontrol_data), mask, val);
}
/* PMU PLL update */
void si_pmu_pllupd(struct si_pub *sih)
{
ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmucontrol),
PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
}
/* query alp/xtal clock frequency */
u32 si_pmu_alp_clock(struct si_pub *sih)
{
u32 clock = ALP_CLOCK;
/* bail out with default */
if (!PMUCTL_ENAB(sih))
return clock;
switch (sih->chip) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
case BCM4313_CHIP_ID:
/* always 20Mhz */
clock = 20000 * 1000;
break;
default:
break;
}
return clock;
}
void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
{
chipcregs_t *cc;
uint origidx, intr_val;
/* Remember original core before switch to chipc */
cc = (chipcregs_t *) ai_switch_core(sih, CC_CORE_ID, &origidx,
&intr_val);
/* update the pll changes */
si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
/* Return to original core */
ai_restore_core(sih, origidx, intr_val);
}
/* initialize PMU */
void si_pmu_init(struct si_pub *sih)
{
chipcregs_t *cc;
uint origidx;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
if (sih->pmurev == 1)
AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
else if (sih->pmurev >= 2)
OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* initialize PMU chip controls and other chip level stuff */
void si_pmu_chip_init(struct si_pub *sih)
{
uint origidx;
/* Gate off SPROM clock and chip select signals */
si_pmu_sprom_enable(sih, false);
/* Remember original core */
origidx = ai_coreidx(sih);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* initialize PMU switch/regulators */
void si_pmu_swreg_init(struct si_pub *sih)
{
}
/* initialize PLL */
void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
{
chipcregs_t *cc;
uint origidx;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
switch (sih->chip) {
case BCM4313_CHIP_ID:
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
/* ??? */
break;
default:
break;
}
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* initialize PMU resources */
void si_pmu_res_init(struct si_pub *sih)
{
chipcregs_t *cc;
uint origidx;
u32 min_mask = 0, max_mask = 0;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
/* Determine min/max rsrc masks */
si_pmu_res_masks(sih, &min_mask, &max_mask);
/* It is required to program max_mask first and then min_mask */
/* Program max resource mask */
if (max_mask)
W_REG(&cc->max_res_mask, max_mask);
/* Program min resource mask */
if (min_mask)
W_REG(&cc->min_res_mask, min_mask);
/* Add some delay; allow resources to come up and settle. */
mdelay(2);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
chipcregs_t *cc;
uint origidx;
u32 alp_khz;
if (sih->pmurev < 10)
return 0;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) {
u32 ilp_ctr, alp_hz;
/*
* Enable the reg to measure the freq,
* in case it was disabled before
*/
W_REG(&cc->pmu_xtalfreq,
1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
/* Delay for well over 4 ILP clocks */
udelay(1000);
/* Read the latched number of ALP ticks per 4 ILP ticks */
ilp_ctr =
R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
/*
* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
* bit to save power
*/
W_REG(&cc->pmu_xtalfreq, 0);
/* Calculate ALP frequency */
alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
/*
* Round to nearest 100KHz, and at
* the same time convert to KHz
*/
alp_khz = (alp_hz + 50000) / 100000 * 100;
} else
alp_khz = 0;
/* Return to original core */
ai_setcoreidx(sih, origidx);
return alp_khz;
}

View File

@ -1,52 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_PMU_H_
#define _BRCM_PMU_H_
#include "types.h"
/*
* LDO selections used in si_pmu_set_ldo_voltage
*/
#define SET_LDO_VOLTAGE_LDO1 1
#define SET_LDO_VOLTAGE_LDO2 2
#define SET_LDO_VOLTAGE_LDO3 3
#define SET_LDO_VOLTAGE_PAREF 4
#define SET_LDO_VOLTAGE_CLDO_PWM 5
#define SET_LDO_VOLTAGE_CLDO_BURST 6
#define SET_LDO_VOLTAGE_CBUCK_PWM 7
#define SET_LDO_VOLTAGE_CBUCK_BURST 8
#define SET_LDO_VOLTAGE_LNLDO1 9
#define SET_LDO_VOLTAGE_LNLDO2_SEL 10
extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable);
extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_ilp_clock(struct si_pub *sih);
extern u32 si_pmu_alp_clock(struct si_pub *sih);
extern void si_pmu_pllupd(struct si_pub *sih);
extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid);
extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern void si_pmu_init(struct si_pub *sih);
extern void si_pmu_chip_init(struct si_pub *sih);
extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq);
extern void si_pmu_res_init(struct si_pub *sih);
extern void si_pmu_swreg_init(struct si_pub *sih);
extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
#endif /* _BRCM_PMU_H_ */

View File

@ -1,665 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_PUB_H_
#define _BRCM_PUB_H_
#include <brcmu_wifi.h>
#include "types.h"
#include "defs.h"
#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */
#define MAXMULTILIST 32 /* max # multicast addresses */
#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */
/* phy types */
#define PHY_TYPE_A 0 /* Phy type A */
#define PHY_TYPE_G 2 /* Phy type G */
#define PHY_TYPE_N 4 /* Phy type N */
#define PHY_TYPE_LP 5 /* Phy type Low Power A/B/G */
#define PHY_TYPE_SSN 6 /* Phy type Single Stream N */
#define PHY_TYPE_LCN 8 /* Phy type Single Stream N */
#define PHY_TYPE_LCNXN 9 /* Phy type 2-stream N */
#define PHY_TYPE_HT 7 /* Phy type 3-Stream N */
/* bw */
#define BRCMS_10_MHZ 10 /* 10Mhz nphy channel bandwidth */
#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */
#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */
#define CHSPEC_WLC_BW(chanspec) (CHSPEC_IS40(chanspec) ? BRCMS_40_MHZ : \
CHSPEC_IS20(chanspec) ? BRCMS_20_MHZ : \
BRCMS_10_MHZ)
#define BRCMS_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */
#define BRCMS_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */
#define BRCMS_RSSI_VERY_LOW -80 /* Very low quality cutoffs */
#define BRCMS_RSSI_LOW -70 /* Low quality cutoffs */
#define BRCMS_RSSI_GOOD -68 /* Good quality cutoffs */
#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */
#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */
/* macro to perform PHY -> D11 PHY TYPE, currently 1:1 */
#define BRCMS_PHYTYPE(_x) (_x)
#define MA_WINDOW_SZ 8 /* moving average window size */
#define BRCMS_SNR_INVALID 0 /* invalid SNR value */
/* a large TX Power as an init value to factor out of min() calculations,
* keep low enough to fit in an s8, units are .25 dBm
*/
#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */
/* rate related definitions */
#define BRCMS_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */
#define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */
/* legacy rx Antenna diversity for SISO rates */
#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */
#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */
#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */
#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */
#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */
#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */
/* legacy rx Antenna diversity for SISO rates */
#define ANT_TX_FORCE_0 0 /* Tx on antenna 0, "legacy term Main" */
#define ANT_TX_FORCE_1 1 /* Tx on antenna 1, "legacy term Aux" */
#define ANT_TX_LAST_RX 3 /* Tx on phy's last good Rx antenna */
#define ANT_TX_DEF 3 /* driver's default tx antenna setting */
#define TXCORE_POLICY_ALL 0x1 /* use all available core for transmit */
/* Tx Chain values */
#define TXCHAIN_DEF 0x1 /* def bitmap of txchain */
#define TXCHAIN_DEF_NPHY 0x3 /* default bitmap of tx chains for nphy */
#define TXCHAIN_DEF_HTPHY 0x7 /* default bitmap of tx chains for nphy */
#define RXCHAIN_DEF 0x1 /* def bitmap of rxchain */
#define RXCHAIN_DEF_NPHY 0x3 /* default bitmap of rx chains for nphy */
#define RXCHAIN_DEF_HTPHY 0x7 /* default bitmap of rx chains for nphy */
#define ANTSWITCH_NONE 0 /* no antenna switch */
#define ANTSWITCH_TYPE_1 1 /* antenna switch on 4321CB2, 2of3 */
#define ANTSWITCH_TYPE_2 2 /* antenna switch on 4321MPCI, 2of3 */
#define ANTSWITCH_TYPE_3 3 /* antenna switch on 4322, 2of3 */
#define RXBUFSZ PKTBUFSZ
#ifndef AIDMAPSZ
#define AIDMAPSZ (roundup(MAXSCB, NBBY)/NBBY) /* aid bitmap size in bytes */
#endif /* AIDMAPSZ */
#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */
#define WL_SPURAVOID_OFF 0
#define WL_SPURAVOID_ON1 1
#define WL_SPURAVOID_ON2 2
struct brcms_tunables {
int ntxd; /* size of tx descriptor table */
int nrxd; /* size of rx descriptor table */
int rxbufsz; /* size of rx buffers to post */
int nrxbufpost; /* # of rx buffers to post */
int maxscb; /* # of SCBs supported */
int ampdunummpdu; /* max number of mpdu in an ampdu */
int maxpktcb; /* max # of packet callbacks */
int maxucodebss; /* max # of BSS handled in ucode bcn/prb */
int maxucodebss4; /* max # of BSS handled in sw bcn/prb */
int maxbss; /* max # of bss info elements in scan list */
int datahiwat; /* data msg txq hiwat mark */
int ampdudatahiwat; /* AMPDU msg txq hiwat mark */
int rxbnd; /* max # of rx bufs to process before deferring to dpc */
int txsbnd; /* max # tx status to process in wlc_txstatus() */
int memreserved; /* memory reserved for BMAC's USB dma rx */
};
struct brcms_rateset {
uint count; /* number of rates in rates[] */
/* rates in 500kbps units w/hi bit set if basic */
u8 rates[BRCMS_NUMRATES];
u8 htphy_membership; /* HT PHY Membership */
u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */
};
struct rsn_parms {
u8 flags; /* misc booleans (e.g., supported) */
u8 multicast; /* multicast cipher */
u8 ucount; /* count of unicast ciphers */
u8 unicast[4]; /* unicast ciphers */
u8 acount; /* count of auth modes */
u8 auth[4]; /* Authentication modes */
u8 PAD[4]; /* padding for future growth */
};
/*
* 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
*/
#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
#define RSN_FLAGS_SUPPORTED 0x1 /* Flag for rsn_params */
#define RSN_FLAGS_PREAUTH 0x2 /* Flag for WPA2 rsn_params */
/* All the HT-specific default advertised capabilities (including AMPDU)
* should be grouped here at one place
*/
#define AMPDU_DEF_MPDU_DENSITY 6 /* default mpdu density (110 ==> 4us) */
/* defaults for the HT (MIMO) bss */
#define HT_CAP (IEEE80211_HT_CAP_SM_PS |\
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD |\
IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_DSSSCCK40)
/* wlc internal bss_info */
struct brcms_bss_info {
u8 BSSID[ETH_ALEN]; /* network BSSID */
u16 flags; /* flags for internal attributes */
u8 SSID_len; /* the length of SSID */
u8 SSID[32]; /* SSID string */
s16 RSSI; /* receive signal strength (in dBm) */
s16 SNR; /* receive signal SNR in dB */
u16 beacon_period; /* units are Kusec */
u16 atim_window; /* units are Kusec */
chanspec_t chanspec; /* Channel num, bw, ctrl_sb and band */
s8 infra; /* 0=IBSS, 1=infrastructure, 2=unknown */
wlc_rateset_t rateset; /* supported rates */
u8 dtim_period; /* DTIM period */
s8 phy_noise; /* noise right after tx (in dBm) */
u16 capability; /* Capability information */
u8 wme_qosinfo; /* QoS Info from WME IE; valid if BSS_WME flag set */
struct rsn_parms wpa;
struct rsn_parms wpa2;
u16 qbss_load_aac; /* qbss load available admission capacity */
/* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */
u8 qbss_load_chan_free; /* indicates how free the channel is */
u8 mcipher; /* multicast cipher */
u8 wpacfg; /* wpa config index */
};
/* IOVar flags for common error checks */
#define IOVF_MFG (1<<3) /* flag for mfgtest iovars */
#define IOVF_WHL (1<<4) /* value must be whole (0-max) */
#define IOVF_NTRL (1<<5) /* value must be natural (1-max) */
#define IOVF_SET_UP (1<<6) /* set requires driver be up */
#define IOVF_SET_DOWN (1<<7) /* set requires driver be down */
#define IOVF_SET_CLK (1<<8) /* set requires core clock */
#define IOVF_SET_BAND (1<<9) /* set requires fixed band */
#define IOVF_GET_UP (1<<10) /* get requires driver be up */
#define IOVF_GET_DOWN (1<<11) /* get requires driver be down */
#define IOVF_GET_CLK (1<<12) /* get requires core clock */
#define IOVF_GET_BAND (1<<13) /* get requires fixed band */
#define IOVF_OPEN_ALLOW (1<<14) /* set allowed iovar for opensrc */
/* watchdog down and dump callback function proto's */
typedef int (*watchdog_fn_t) (void *handle);
typedef int (*down_fn_t) (void *handle);
typedef int (*dump_fn_t) (void *handle, struct brcmu_strbuf *b);
/* IOVar handler
*
* handle - a pointer value registered with the function
* vi - iovar_info that was looked up
* actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid.
* name - the actual iovar name
* params/plen - parameters and length for a get, input only.
* arg/len - buffer and length for value to be set or retrieved, input or output.
* vsize - value size, valid for integer type only.
* wlcif - interface context (brcms_c_if pointer)
*
* All pointers may point into the same buffer.
*/
typedef int (*iovar_fn_t) (void *handle, const struct brcmu_iovar *vi,
u32 actionid, const char *name, void *params,
uint plen, void *arg, int alen, int vsize,
struct brcms_c_if *wlcif);
#define MAC80211_PROMISC_BCNS (1 << 0)
#define MAC80211_SCAN (1 << 1)
/*
* Public portion of "common" os-independent state structure.
* The wlc handle points at this.
*/
struct brcms_pub {
void *wlc;
struct ieee80211_hw *ieee_hw;
struct scb *global_scb;
struct scb_ampdu *global_ampdu;
uint mac80211_state;
uint unit; /* device instance number */
uint corerev; /* core revision */
struct si_pub *sih; /* SI handle (cookie for siutils calls) */
char *vars; /* "environment" name=value */
bool up; /* interface up and running */
bool hw_off; /* HW is off */
/* tunables: ntxd, nrxd, maxscb, etc. */
struct brcms_tunables *tunables;
bool hw_up; /* one time hw up/down(from boot or hibernation) */
bool _piomode; /* true if pio mode *//* BMAC_NOTE: NEED In both */
uint _nbands; /* # bands supported */
uint now; /* # elapsed seconds */
bool promisc; /* promiscuous destination address */
bool delayed_down; /* down delayed */
bool _ap; /* AP mode enabled */
bool _apsta; /* simultaneous AP/STA mode enabled */
bool _assoc_recreate; /* association recreation on up transitions */
int _wme; /* WME QoS mode */
u8 _mbss; /* MBSS mode on */
bool allmulti; /* enable all multicasts */
bool associated; /* true:part of [I]BSS, false: not */
/* (union of stas_associated, aps_associated) */
bool phytest_on; /* whether a PHY test is running */
bool bf_preempt_4306; /* True to enable 'darwin' mode */
bool _ampdu; /* ampdu enabled or not */
bool _cac; /* 802.11e CAC enabled */
u8 _n_enab; /* bitmap of 11N + HT support */
bool _n_reqd; /* N support required for clients */
s8 _coex; /* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */
bool _priofc; /* Priority-based flowcontrol */
u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */
u8 *multicast; /* ptr to list of multicast addresses */
uint nmulticast; /* # enabled multicast addresses */
u32 wlfeatureflag; /* Flags to control sw features from registry */
int psq_pkts_total; /* total num of ps pkts */
u16 txmaxpkts; /* max number of large pkts allowed to be pending */
/* s/w decryption counters */
u32 swdecrypt; /* s/w decrypt attempts */
int bcmerror; /* last bcm error */
mbool radio_disabled; /* bit vector for radio disabled reasons */
bool radio_active; /* radio on/off state */
u16 roam_time_thresh; /* Max. # secs. of not hearing beacons
* before roaming.
*/
bool align_wd_tbtt; /* Align watchdog with tbtt indication
* handling. This flag is cleared by default
* and is set by per port code explicitly and
* you need to make sure the OSL_SYSUPTIME()
* is implemented properly in osl of that port
* when it enables this Power Save feature.
*/
u16 boardrev; /* version # of particular board */
u8 sromrev; /* version # of the srom */
char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
u32 boardflags; /* Board specific flags from srom */
u32 boardflags2; /* More board flags if sromrev >= 4 */
bool tempsense_disable; /* disable periodic tempsense check */
bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */
bool _ampdumac; /* mac assist ampdu enabled or not */
struct wl_cnt *_cnt; /* low-level counters in driver */
};
/* wl_monitor rx status per packet */
struct wl_rxsts {
uint pkterror; /* error flags per pkt */
uint phytype; /* 802.11 A/B/G ... */
uint channel; /* channel */
uint datarate; /* rate in 500kbps */
uint antenna; /* antenna pkts received on */
uint pktlength; /* pkt length minus bcm phy hdr */
u32 mactime; /* time stamp from mac, count per 1us */
uint sq; /* signal quality */
s32 signal; /* in dbm */
s32 noise; /* in dbm */
uint preamble; /* Unknown, short, long */
uint encoding; /* Unknown, CCK, PBCC, OFDM */
uint nfrmtype; /* special 802.11n frames(AMPDU, AMSDU) */
struct brcms_if *wlif; /* wl interface */
};
/* status per error RX pkt */
#define WL_RXS_CRC_ERROR 0x00000001 /* CRC Error in packet */
#define WL_RXS_RUNT_ERROR 0x00000002 /* Runt packet */
#define WL_RXS_ALIGN_ERROR 0x00000004 /* Misaligned packet */
#define WL_RXS_OVERSIZE_ERROR 0x00000008 /* packet bigger than RX_LENGTH (usually 1518) */
#define WL_RXS_WEP_ICV_ERROR 0x00000010 /* Integrity Check Value error */
#define WL_RXS_WEP_ENCRYPTED 0x00000020 /* Encrypted with WEP */
#define WL_RXS_PLCP_SHORT 0x00000040 /* Short PLCP error */
#define WL_RXS_DECRYPT_ERR 0x00000080 /* Decryption error */
#define WL_RXS_OTHER_ERR 0x80000000 /* Other errors */
/* phy type */
#define WL_RXS_PHY_A 0x00000000 /* A phy type */
#define WL_RXS_PHY_B 0x00000001 /* B phy type */
#define WL_RXS_PHY_G 0x00000002 /* G phy type */
#define WL_RXS_PHY_N 0x00000004 /* N phy type */
/* encoding */
#define WL_RXS_ENCODING_CCK 0x00000000 /* CCK encoding */
#define WL_RXS_ENCODING_OFDM 0x00000001 /* OFDM encoding */
/* preamble */
#define WL_RXS_UNUSED_STUB 0x0 /* stub to match with wlc_ethereal.h */
#define WL_RXS_PREAMBLE_SHORT 0x00000001 /* Short preamble */
#define WL_RXS_PREAMBLE_LONG 0x00000002 /* Long preamble */
#define WL_RXS_PREAMBLE_MIMO_MM 0x00000003 /* MIMO mixed mode preamble */
#define WL_RXS_PREAMBLE_MIMO_GF 0x00000004 /* MIMO green field preamble */
#define WL_RXS_NFRM_AMPDU_FIRST 0x00000001 /* first MPDU in A-MPDU */
#define WL_RXS_NFRM_AMPDU_SUB 0x00000002 /* subsequent MPDU(s) in A-MPDU */
#define WL_RXS_NFRM_AMSDU_FIRST 0x00000004 /* first MSDU in A-MSDU */
#define WL_RXS_NFRM_AMSDU_SUB 0x00000008 /* subsequent MSDU(s) in A-MSDU */
enum wlc_par_id {
IOV_MPC = 1,
IOV_RTSTHRESH,
IOV_QTXPOWER,
IOV_BCN_LI_BCN /* Beacon listen interval in # of beacons */
};
/***********************************************
* Feature-related macros to optimize out code *
* *********************************************
*/
/* AP Support (versus STA) */
#define AP_ENAB(pub) (0)
/* Macro to check if APSTA mode enabled */
#define APSTA_ENAB(pub) (0)
/* Some useful combinations */
#define STA_ONLY(pub) (!AP_ENAB(pub))
#define AP_ONLY(pub) (AP_ENAB(pub) && !APSTA_ENAB(pub))
#define ENAB_1x1 0x01
#define ENAB_2x2 0x02
#define ENAB_3x3 0x04
#define ENAB_4x4 0x08
#define SUPPORT_11N (ENAB_1x1|ENAB_2x2)
#define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3)
/* WL11N Support */
#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \
(defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0)))
#define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N)
#define N_REQD(pub) ((pub)->_n_reqd)
#else
#define N_ENAB(pub) 0
#define N_REQD(pub) 0
#endif
#if (defined(HTCONF) && (HTCONF != 0))
#define HT_ENAB(pub) (((pub)->_n_enab & SUPPORT_HT) == SUPPORT_HT)
#else
#define HT_ENAB(pub) 0
#endif
#define AMPDU_AGG_HOST 1
#define AMPDU_ENAB(pub) ((pub)->_ampdu)
#define EDCF_ENAB(pub) (WME_ENAB(pub))
#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
#define MONITOR_ENAB(wlc) ((wlc)->monitor)
#define PROMISC_ENAB(wlc) ((wlc)->promisc)
#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */
/* pri is priority encoded in the packet. This maps the Packet priority to
* enqueue precedence as defined in wlc_prec_map
*/
extern const u8 wlc_prio2prec_map[];
#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7]
/* This maps priority to one precedence higher - Used by PS-Poll response packets to
* simulate enqueue-at-head operation, but still maintain the order on the queue
*/
#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\
BRCMS_PREC_COUNT - 1)
extern const u8 wme_fifo2ac[];
#define WME_PRIO2AC(prio) wme_fifo2ac[prio2fifo[(prio)]]
/* Mask to describe all precedence levels */
#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT)
/* Define a bitmap of precedences comprised by each AC */
#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \
NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \
NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
/* WME Support */
#define WME_ENAB(pub) ((pub)->_wme != OFF)
#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
/* invalid core flags, use the saved coreflags */
#define BRCMS_USE_COREFLAGS 0xffffffff
/* network protection config */
#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */
#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */
#define BRCMS_PROT_G_USER 3 /* gmode specified by user */
#define BRCMS_PROT_OVERLAP 4 /* overlap */
#define BRCMS_PROT_N_USER 10 /* nmode specified by user */
#define BRCMS_PROT_N_CFG 11 /* n protection */
#define BRCMS_PROT_N_CFG_OVR 12 /* n protection override */
#define BRCMS_PROT_N_NONGF 13 /* non-GF protection */
#define BRCMS_PROT_N_NONGF_OVR 14 /* non-GF protection override */
#define BRCMS_PROT_N_PAM_OVR 15 /* n preamble override */
#define BRCMS_PROT_N_OBSS 16 /* non-HT OBSS present */
/*
* 54g modes (basic bits may still be overridden)
*
* GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11
* Preamble: Long
* Shortslot: Off
* GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
* Extended Rateset: 6, 9, 12, 48
* Preamble: Long
* Shortslot: Auto
* GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
* Extended Rateset: 6b, 9, 12b, 48
* Preamble: Short required
* Shortslot: Auto
* GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
* Extended Rateset: 6, 9, 12, 48
* Preamble: Long
* Shortslot: On
* GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
* Preamble: Short required
* Shortslot: On and required
* GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b
* Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
* Preamble: Long
* Shortslot: Auto
*/
#define GMODE_LEGACY_B 0
#define GMODE_AUTO 1
#define GMODE_ONLY 2
#define GMODE_B_DEFERRED 3
#define GMODE_PERFORMANCE 4
#define GMODE_LRS 5
#define GMODE_MAX 6
/* values for PLCPHdr_override */
#define BRCMS_PLCP_AUTO -1
#define BRCMS_PLCP_SHORT 0
#define BRCMS_PLCP_LONG 1
/* values for g_protection_override and n_protection_override */
#define BRCMS_PROTECTION_AUTO -1
#define BRCMS_PROTECTION_OFF 0
#define BRCMS_PROTECTION_ON 1
#define BRCMS_PROTECTION_MMHDR_ONLY 2
#define BRCMS_PROTECTION_CTS_ONLY 3
/* values for g_protection_control and n_protection_control */
#define BRCMS_PROTECTION_CTL_OFF 0
#define BRCMS_PROTECTION_CTL_LOCAL 1
#define BRCMS_PROTECTION_CTL_OVERLAP 2
/* values for n_protection */
#define BRCMS_N_PROTECTION_OFF 0
#define BRCMS_N_PROTECTION_OPTIONAL 1
#define BRCMS_N_PROTECTION_20IN40 2
#define BRCMS_N_PROTECTION_MIXEDMODE 3
/* values for band specific 40MHz capabilities */
#define BRCMS_N_BW_20ALL 0
#define BRCMS_N_BW_40ALL 1
#define BRCMS_N_BW_20IN2G_40IN5G 2
/* bitflags for SGI support (sgi_rx iovar) */
#define BRCMS_N_SGI_20 0x01
#define BRCMS_N_SGI_40 0x02
/* defines used by the nrate iovar */
#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */
#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
#define NRATE_STF_SHIFT 8 /* stf mode shift */
#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */
#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */
#define NRATE_SGI_MASK 0x00800000 /* sgi mode */
#define NRATE_SGI_SHIFT 23 /* sgi mode */
#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */
#define NRATE_LDPC_SHIFT 22 /* ldpc shift */
#define NRATE_STF_SISO 0 /* stf mode SISO */
#define NRATE_STF_CDD 1 /* stf mode CDD */
#define NRATE_STF_STBC 2 /* stf mode STBC */
#define NRATE_STF_SDM 3 /* stf mode SDM */
#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */
#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */
struct brcms_antselcfg {
u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */
u8 num_antcfg; /* number of available antenna configurations */
};
/* common functions for every port */
extern void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device,
uint unit, bool piomode, void *regsva, uint bustype,
void *btparam, uint *perr);
extern uint brcms_c_detach(struct brcms_c_info *wlc);
extern int brcms_c_up(struct brcms_c_info *wlc);
extern uint brcms_c_down(struct brcms_c_info *wlc);
extern int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg);
extern int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg);
extern bool brcms_c_chipmatch(u16 vendor, u16 device);
extern void brcms_c_init(struct brcms_c_info *wlc);
extern void brcms_c_reset(struct brcms_c_info *wlc);
extern void brcms_c_intrson(struct brcms_c_info *wlc);
extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
extern bool brcms_c_intrsupd(struct brcms_c_info *wlc);
extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc);
extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
struct sk_buff *sdu,
struct ieee80211_hw *hw);
extern int brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
struct brcms_c_if *wlcif);
extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
/* helper functions */
extern void brcms_c_statsupd(struct brcms_c_info *wlc);
extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx,
int val);
extern int brcms_c_get_header_len(void);
extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
bool promisc);
extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc,
int match_reg_offset,
const u8 *addr);
extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
const struct ieee80211_tx_queue_params *arg,
bool suspend);
extern struct brcms_pub *brcms_c_pub(void *wlc);
/* common functions for every port */
extern void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val,
int bands);
extern void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
wlc_rateset_t *rateset);
extern void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs);
extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
struct ieee80211_sta *sta, u16 tid);
extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
u8 ba_wsize, uint max_rx_ampdu_bytes);
extern int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
int val);
extern int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
int *ret_int_ptr);
extern char *getvar(char *vars, const char *name);
extern int getintvar(char *vars, const char *name);
/* wlc_phy.c helper functions */
extern void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc);
extern void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val);
extern int brcms_c_module_register(struct brcms_pub *pub,
const char *name, void *hdl,
watchdog_fn_t watchdog_fn, down_fn_t down_fn);
extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
void *hdl);
extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
extern void brcms_c_enable_mac(struct brcms_c_info *wlc);
extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
extern void brcms_c_scan_start(struct brcms_c_info *wlc);
extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
extern int brcms_c_get_curband(struct brcms_c_info *wlc);
extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
bool drop);
/* helper functions */
extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
extern bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc);
#define MAXBANDS 2 /* Maximum #of bands */
/* bandstate array indices */
#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */
#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */
#define BAND_2G_NAME "2.4G"
#define BAND_5G_NAME "5G"
/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */
#define BRCMS_RPCTX_PARAMS 32
#endif /* _BRCM_PUB_H_ */

View File

@ -1,498 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "d11.h"
#include "pub.h"
#include "rate.h"
/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
const u8 rate_info[BRCM_MAXRATE + 1] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
/* 20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
};
/* rates are in units of Kbps */
const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
/* MCS 0: SS 1, MOD: BPSK, CR 1/2 */
{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
BRCM_RATE_6M},
/* MCS 1: SS 1, MOD: QPSK, CR 1/2 */
{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
BRCM_RATE_12M},
/* MCS 2: SS 1, MOD: QPSK, CR 3/4 */
{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
BRCM_RATE_18M},
/* MCS 3: SS 1, MOD: 16QAM, CR 1/2 */
{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
BRCM_RATE_24M},
/* MCS 4: SS 1, MOD: 16QAM, CR 3/4 */
{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
BRCM_RATE_36M},
/* MCS 5: SS 1, MOD: 64QAM, CR 2/3 */
{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
BRCM_RATE_48M},
/* MCS 6: SS 1, MOD: 64QAM, CR 3/4 */
{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
BRCM_RATE_54M},
/* MCS 7: SS 1, MOD: 64QAM, CR 5/6 */
{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
BRCM_RATE_54M},
/* MCS 8: SS 2, MOD: BPSK, CR 1/2 */
{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
BRCM_RATE_6M},
/* MCS 9: SS 2, MOD: QPSK, CR 1/2 */
{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
BRCM_RATE_12M},
/* MCS 10: SS 2, MOD: QPSK, CR 3/4 */
{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
BRCM_RATE_18M},
/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
BRCM_RATE_24M},
/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
BRCM_RATE_36M},
/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
BRCM_RATE_48M},
/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
BRCM_RATE_54M},
/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
BRCM_RATE_54M},
/* MCS 16: SS 3, MOD: BPSK, CR 1/2 */
{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
BRCM_RATE_6M},
/* MCS 17: SS 3, MOD: QPSK, CR 1/2 */
{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
BRCM_RATE_12M},
/* MCS 18: SS 3, MOD: QPSK, CR 3/4 */
{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
BRCM_RATE_18M},
/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
BRCM_RATE_24M},
/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
BRCM_RATE_36M},
/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
BRCM_RATE_48M},
/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
BRCM_RATE_54M},
/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
BRCM_RATE_54M},
/* MCS 24: SS 4, MOD: BPSK, CR 1/2 */
{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
BRCM_RATE_6M},
/* MCS 25: SS 4, MOD: QPSK, CR 1/2 */
{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
BRCM_RATE_12M},
/* MCS 26: SS 4, MOD: QPSK, CR 3/4 */
{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
BRCM_RATE_18M},
/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
BRCM_RATE_24M},
/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
BRCM_RATE_36M},
/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
BRCM_RATE_48M},
/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
BRCM_RATE_54M},
/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
BRCM_RATE_54M},
/* MCS 32: SS 1, MOD: BPSK, CR 1/2 */
{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M},
};
/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
* Number of spatial streams: always 1
* other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
*/
struct legacy_phycfg {
u32 rate_ofdm; /* ofdm mac rate */
u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */
};
#define LEGACY_PHYCFG_TABLE_SIZE 12 /* Number of legacy_rate_cfg entries in the table */
/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
/* Eventually MIMOPHY would also be converted to this format */
/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
static const struct
legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
{BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */
{BRCM_RATE_2M, 0x08}, /* CCK 2Mbps, data rate 1 */
{BRCM_RATE_5M5, 0x10}, /* CCK 5.5Mbps, data rate 2 */
{BRCM_RATE_11M, 0x18}, /* CCK 11Mbps, data rate 3 */
/* OFDM 6Mbps, code rate 1/2, BPSK, 1 spatial stream */
{BRCM_RATE_6M, 0x00},
/* OFDM 9Mbps, code rate 3/4, BPSK, 1 spatial stream */
{BRCM_RATE_9M, 0x02},
/* OFDM 12Mbps, code rate 1/2, QPSK, 1 spatial stream */
{BRCM_RATE_12M, 0x08},
/* OFDM 18Mbps, code rate 3/4, QPSK, 1 spatial stream */
{BRCM_RATE_18M, 0x0A},
/* OFDM 24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
{BRCM_RATE_24M, 0x10},
/* OFDM 36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
{BRCM_RATE_36M, 0x12},
/* OFDM 48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
{BRCM_RATE_48M, 0x19},
/* OFDM 54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
{BRCM_RATE_54M, 0x1A},
};
/* Hardware rates (also encodes default basic rates) */
const wlc_rateset_t cck_ofdm_mimo_rates = {
12,
{ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
0x6c},
0x00,
{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
const wlc_rateset_t ofdm_mimo_rates = {
8,
{ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
/* Default ratesets that include MCS32 for 40BW channels */
const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
12,
{ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
0x6c},
0x00,
{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
const wlc_rateset_t ofdm_40bw_mimo_rates = {
8,
{ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
const wlc_rateset_t cck_ofdm_rates = {
12,
{ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */
0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
0x6c},
0x00,
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
const wlc_rateset_t gphy_legacy_rates = {
4,
{ /* 1b, 2b, 5.5b, 11b Mbps */
0x82, 0x84, 0x8b, 0x96},
0x00,
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
const wlc_rateset_t ofdm_rates = {
8,
{ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */
0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0x00,
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
const wlc_rateset_t cck_rates = {
4,
{ /* 1b, 2b, 5.5, 11 Mbps */
0x82, 0x84, 0x0b, 0x16},
0x00,
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}
};
/* check if rateset is valid.
* if check_brate is true, rateset without a basic rate is considered NOT valid.
*/
static bool brcms_c_rateset_valid(wlc_rateset_t *rs, bool check_brate)
{
uint idx;
if (!rs->count)
return false;
if (!check_brate)
return true;
/* error if no basic rates */
for (idx = 0; idx < rs->count; idx++) {
if (rs->rates[idx] & BRCMS_RATE_FLAG)
return true;
}
return false;
}
void brcms_c_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
{
int i;
for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
rs->mcs[i] = 0;
}
/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
* and check if resulting rateset is valid.
*/
bool
brcms_c_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
const wlc_rateset_t *hw_rs,
bool check_brate, u8 txstreams)
{
u8 rateset[BRCM_MAXRATE + 1];
u8 r;
uint count;
uint i;
memset(rateset, 0, sizeof(rateset));
count = rs->count;
for (i = 0; i < count; i++) {
/* mask off "basic rate" bit, BRCMS_RATE_FLAG */
r = (int)rs->rates[i] & BRCMS_RATE_MASK;
if ((r > BRCM_MAXRATE) || (rate_info[r] == 0))
continue;
rateset[r] = rs->rates[i]; /* preserve basic bit! */
}
/* fill out the rates in order, looking at only supported rates */
count = 0;
for (i = 0; i < hw_rs->count; i++) {
r = hw_rs->rates[i] & BRCMS_RATE_MASK;
if (rateset[r])
rs->rates[count++] = rateset[r];
}
rs->count = count;
/* only set the mcs rate bit if the equivalent hw mcs bit is set */
for (i = 0; i < MCSSET_LEN; i++)
rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
if (brcms_c_rateset_valid(rs, check_brate))
return true;
else
return false;
}
/* calculate the rate of a rx'd frame and return it as a ratespec */
ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
{
int phy_type;
ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
phy_type =
((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
(phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
case PRXS0_CCK:
rspec =
CCK_PHY2MAC_RATE(
((struct cck_phy_hdr *) plcp)->signal);
break;
case PRXS0_OFDM:
rspec =
OFDM_PHY2MAC_RATE(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
break;
case PRXS0_PREN:
rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
if (plcp[0] & MIMO_PLCP_40MHZ) {
/* indicate rspec is for 40 MHz mode */
rspec &= ~RSPEC_BW_MASK;
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
}
break;
case PRXS0_STDN:
/* fallthru */
default:
/* not supported, error condition */
break;
}
if (PLCP3_ISSGI(plcp[3]))
rspec |= RSPEC_SHORT_GI;
} else
if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
rspec = OFDM_PHY2MAC_RATE(
((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
else
rspec = CCK_PHY2MAC_RATE(
((struct cck_phy_hdr *) plcp)->signal);
return rspec;
}
/* copy rateset src to dst as-is (no masking or sorting) */
void brcms_c_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
{
memcpy(dst, src, sizeof(wlc_rateset_t));
}
/*
* Copy and selectively filter one rateset to another.
* 'basic_only' means only copy basic rates.
* 'rates' indicates cck (11b) and ofdm rates combinations.
* - 0: cck and ofdm
* - 1: cck only
* - 2: ofdm only
* 'xmask' is the copy mask (typically 0x7f or 0xff).
*/
void
brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
u8 rates, uint xmask, bool mcsallow)
{
uint i;
uint r;
uint count;
count = 0;
for (i = 0; i < src->count; i++) {
r = src->rates[i];
if (basic_only && !(r & BRCMS_RATE_FLAG))
continue;
if (rates == BRCMS_RATES_CCK && IS_OFDM((r & BRCMS_RATE_MASK)))
continue;
if (rates == BRCMS_RATES_OFDM && IS_CCK((r & BRCMS_RATE_MASK)))
continue;
dst->rates[count++] = r & xmask;
}
dst->count = count;
dst->htphy_membership = src->htphy_membership;
if (mcsallow && rates != BRCMS_RATES_CCK)
memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
else
brcms_c_rateset_mcs_clear(dst);
}
/* select rateset for a given phy_type and bandtype and filter it, sort it
* and fill rs_tgt with result
*/
void
brcms_c_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
uint phy_type, int bandtype, bool cck_only, uint rate_mask,
bool mcsallow, u8 bw, u8 txstreams)
{
const wlc_rateset_t *rs_dflt;
wlc_rateset_t rs_sel;
if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
(PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
if (BAND_5G(bandtype)) {
rs_dflt = (bw == BRCMS_20_MHZ ?
&ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
} else {
rs_dflt = (bw == BRCMS_20_MHZ ?
&cck_ofdm_mimo_rates :
&cck_ofdm_40bw_mimo_rates);
}
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
rs_dflt = &ofdm_rates;
} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
rs_dflt = &cck_ofdm_rates;
} else {
/* should not happen, error condition */
rs_dflt = &cck_rates; /* force cck */
}
/* if hw rateset is not supplied, assign selected rateset to it */
if (!rs_hw)
rs_hw = rs_dflt;
brcms_c_rateset_copy(rs_dflt, &rs_sel);
brcms_c_rateset_mcs_upd(&rs_sel, txstreams);
brcms_c_rateset_filter(&rs_sel, rs_tgt, false,
cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM,
rate_mask, mcsallow);
brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
mcsallow ? txstreams : 1);
}
s16 brcms_c_rate_legacy_phyctl(uint rate)
{
uint i;
for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
if (rate == legacy_phycfg_table[i].rate_ofdm)
return legacy_phycfg_table[i].tx_phy_ctl3;
return -1;
}
void brcms_c_rateset_mcs_clear(wlc_rateset_t *rateset)
{
uint i;
for (i = 0; i < MCSSET_LEN; i++)
rateset->mcs[i] = 0;
}
void brcms_c_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
{
memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
brcms_c_rateset_mcs_upd(rateset, txstreams);
}
/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
void brcms_c_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
{
if (bw == BRCMS_40_MHZ)
setbit(rateset->mcs, 32);
else
clrbit(rateset->mcs, 32);
}

View File

@ -1,173 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_RATE_H_
#define _BRCM_RATE_H_
#include "types.h"
extern const u8 rate_info[];
extern const struct brcms_rateset cck_ofdm_mimo_rates;
extern const struct brcms_rateset ofdm_mimo_rates;
extern const struct brcms_rateset cck_ofdm_rates;
extern const struct brcms_rateset ofdm_rates;
extern const struct brcms_rateset cck_rates;
extern const struct brcms_rateset gphy_legacy_rates;
extern const struct brcms_rateset wlc_lrs_rates;
extern const struct brcms_rateset rate_limit_1_2;
struct brcms_mcs_info {
u32 phy_rate_20; /* phy rate in kbps [20Mhz] */
u32 phy_rate_40; /* phy rate in kbps [40Mhz] */
u32 phy_rate_20_sgi; /* phy rate in kbps [20Mhz] with SGI */
u32 phy_rate_40_sgi; /* phy rate in kbps [40Mhz] with SGI */
u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */
u8 leg_ofdm; /* matching legacy ofdm rate in 500bkps */
};
#define BRCMS_MAXMCS 32 /* max valid mcs index */
#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */
extern const struct brcms_mcs_info mcs_table[];
#define MCS_INVALID 0xFF
#define MCS_CR_MASK 0x07 /* Code Rate bit mask */
#define MCS_MOD_MASK 0x38 /* Modulation bit shift */
#define MCS_MOD_SHIFT 3 /* MOdulation bit shift */
#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */
#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */
#define MCS_CR(_mcs) (mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK)
#define MCS_MOD(_mcs) ((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT)
#define MCS_TXS(_mcs) ((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT)
#define MCS_RATE(_mcs, _is40, _sgi) (_sgi ? \
(_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \
(_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
#define VALID_MCS(_mcs) ((_mcs < MCS_TABLE_SIZE))
/* Macro to use the rate_info table */
#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
/* convert 500kbps to bps */
#define BRCMS_RATE_500K_TO_BPS(rate) ((rate) * 500000)
/* rate spec : holds rate and mode specific information required to generate a tx frame. */
/* Legacy CCK and OFDM information is held in the same manner as was done in the past */
/* (in the lower byte) the upper 3 bytes primarily hold MIMO specific information */
/* rate spec bit fields */
#define RSPEC_RATE_MASK 0x0000007F /* Either 500Kbps units or MIMO MCS idx */
#define RSPEC_MIMORATE 0x08000000 /* mimo MCS is stored in RSPEC_RATE_MASK */
#define RSPEC_BW_MASK 0x00000700 /* mimo bw mask */
#define RSPEC_BW_SHIFT 8 /* mimo bw shift */
#define RSPEC_STF_MASK 0x00003800 /* mimo Space/Time/Frequency mode mask */
#define RSPEC_STF_SHIFT 11 /* mimo Space/Time/Frequency mode shift */
#define RSPEC_CT_MASK 0x0000C000 /* mimo coding type mask */
#define RSPEC_CT_SHIFT 14 /* mimo coding type shift */
#define RSPEC_STC_MASK 0x00300000 /* mimo num STC streams per PLCP defn. */
#define RSPEC_STC_SHIFT 20 /* mimo num STC streams per PLCP defn. */
#define RSPEC_LDPC_CODING 0x00400000 /* mimo bit indicates adv coding in use */
#define RSPEC_SHORT_GI 0x00800000 /* mimo bit indicates short GI in use */
#define RSPEC_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */
#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicates override rate only */
#define BRCMS_HTPHY 127 /* HT PHY Membership */
#define RSPEC_ACTIVE(rspec) (rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE))
#define RSPEC2RATE(rspec) ((rspec & RSPEC_MIMORATE) ? \
MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \
(rspec & RSPEC_RATE_MASK))
/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
#define RSPEC2RATE500K(rspec) ((rspec & RSPEC_MIMORATE) ? \
MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \
(rspec & RSPEC_RATE_MASK))
#define CRSPEC2RATE500K(rspec) ((rspec & RSPEC_MIMORATE) ? \
MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\
(rspec & RSPEC_RATE_MASK))
#define RSPEC2KBPS(rspec) (IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500)
#define RSPEC_PHYTXBYTE2(rspec) ((rspec & 0xff00) >> 8)
#define RSPEC_GET_BW(rspec) ((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT)
#define RSPEC_IS40MHZ(rspec) ((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \
PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \
RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP))
#define RSPEC_ISSGI(rspec) ((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI)
#define RSPEC_MIMOPLCP3(rspec) ((rspec & 0xf00000) >> 16)
#define PLCP3_ISSGI(plcp) (plcp & (RSPEC_SHORT_GI >> 16))
#define RSPEC_STC(rspec) ((rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT)
#define RSPEC_STF(rspec) ((rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT)
#define PLCP3_ISSTBC(plcp) ((plcp & (RSPEC_STC_MASK) >> 16) == 0x10)
#define PLCP3_STC_MASK 0x30
#define PLCP3_STC_SHIFT 4
/* Rate info table; takes a legacy rate or ratespec_t */
#define IS_MCS(r) (r & RSPEC_MIMORATE)
#define IS_OFDM(r) (!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & \
BRCMS_RATE_FLAG))
#define IS_CCK(r) (!IS_MCS(r) && ( \
((r) & BRCMS_RATE_MASK) == BRCM_RATE_1M || \
((r) & BRCMS_RATE_MASK) == BRCM_RATE_2M || \
((r) & BRCMS_RATE_MASK) == BRCM_RATE_5M5 || \
((r) & BRCMS_RATE_MASK) == BRCM_RATE_11M))
#define IS_SINGLE_STREAM(mcs) (((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32))
#define CCK_RSPEC(cck) ((cck) & RSPEC_RATE_MASK)
#define OFDM_RSPEC(ofdm) (((ofdm) & RSPEC_RATE_MASK) |\
(PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT))
#define LEGACY_RSPEC(rate) (IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate))
#define MCS_RSPEC(mcs) (((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \
(IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \
(PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT)))
/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */
extern const u8 ofdm_rate_lookup[];
#define OFDM_PHY2MAC_RATE(rlpt) (ofdm_rate_lookup[rlpt & 0x7])
#define CCK_PHY2MAC_RATE(signal) (signal/5)
/* Rates specified in brcms_c_rateset_filter() */
#define BRCMS_RATES_CCK_OFDM 0
#define BRCMS_RATES_CCK 1
#define BRCMS_RATES_OFDM 2
/* sanitize, and sort a rateset with the basic bit(s) preserved, validate rateset */
extern bool
brcms_c_rate_hwrs_filter_sort_validate(struct brcms_rateset *rs,
const struct brcms_rateset *hw_rs,
bool check_brate, u8 txstreams);
/* copy rateset src to dst as-is (no masking or sorting) */
extern void brcms_c_rateset_copy(const struct brcms_rateset *src,
struct brcms_rateset *dst);
/* would be nice to have these documented ... */
extern ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
extern void brcms_c_rateset_filter(struct brcms_rateset *src,
struct brcms_rateset *dst, bool basic_only, u8 rates, uint xmask,
bool mcsallow);
extern void
brcms_c_rateset_default(struct brcms_rateset *rs_tgt,
const struct brcms_rateset *rs_hw, uint phy_type,
int bandtype, bool cck_only, uint rate_mask,
bool mcsallow, u8 bw, u8 txstreams);
extern s16 brcms_c_rate_legacy_phyctl(uint rate);
extern void brcms_c_rateset_mcs_upd(struct brcms_rateset *rs, u8 txstreams);
extern void brcms_c_rateset_mcs_clear(struct brcms_rateset *rateset);
extern void brcms_c_rateset_mcs_build(struct brcms_rateset *rateset,
u8 txstreams);
extern void brcms_c_rateset_bw_mcs_filter(struct brcms_rateset *rateset, u8 bw);
#endif /* _BRCM_RATE_H_ */

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_SCB_H_
#define _BRCM_SCB_H_
#include <linux/if_ether.h>
#include <brcmu_utils.h>
#include <defs.h>
#include "types.h"
#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
/* structure to store per-tid state for the ampdu initiator */
struct scb_ampdu_tid_ini {
u8 tx_in_transit; /* number of pending mpdus in transit in driver */
u8 tid; /* initiator tid for easy lookup */
u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; /* tx retry count; indexed by seq modulo */
struct scb *scb; /* backptr for easy lookup */
u8 ba_wsize; /* negotiated ba window size (in pdu) */
};
#define AMPDU_MAX_SCB_TID NUMPRIO
struct scb_ampdu {
struct scb *scb; /* back pointer for easy reference */
u8 mpdu_density; /* mpdu density */
u8 max_pdu; /* max pdus allowed in ampdu */
u8 release; /* # of mpdus released at a time */
u16 min_len; /* min mpdu len to support the density */
u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */
struct pktq txq; /* sdu transmit queue pending aggregation */
/* This could easily be a ini[] pointer and we keep this info in wl itself instead
* of having mac80211 hold it for us. Also could be made dynamic per tid instead of
* static.
*/
/* initiator info - per tid (NUMPRIO): */
struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID];
};
#define SCB_MAGIC 0xbeefcafe
/* station control block - one per remote MAC address */
struct scb {
u32 magic;
u32 flags; /* various bit flags as defined below */
u32 flags2; /* various bit flags2 as defined below */
u8 state; /* current state bitfield of auth/assoc process */
u8 ea[ETH_ALEN]; /* station address */
void *fragbuf[NUMPRIO]; /* defragmentation buffer per prio */
uint fragresid[NUMPRIO]; /* #bytes unused in frag buffer per prio */
u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */
u16 seqctl_nonqos; /* seqctl of last received frame (for dups) for
* non-QoS data and management
*/
u16 seqnum[NUMPRIO]; /* WME: driver maintained sw seqnum per priority */
struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */
};
/* scb flags */
#define SCB_WMECAP 0x0040 /* may ONLY be set if WME_ENAB(wlc) */
#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */
#define SCB_IS40 0x80000 /* 40MHz capable */
#define SCB_STBCCAP 0x40000000 /* STBC Capable */
#define SCB_WME(a) ((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
#define SCB_SEQNUM(scb, prio) ((scb)->seqnum[(prio)])
#define SCB_PS(a) NULL
#define SCB_STBC_CAP(a) ((a)->flags & SCB_STBCCAP)
#define SCB_AMPDU(a) true
#endif /* _BRCM_SCB_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_SROM_H_
#define _BRCM_SROM_H_
#include "types.h"
/* Prototypes */
extern int srom_var_init(struct si_pub *sih, uint bus, void *curmap,
char **vars, uint *count);
extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
uint byteoff, uint nbytes, u16 *buf, bool check_crc);
/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP
* and extract from it into name=value pairs
*/
extern int srom_parsecis(u8 **pcis, uint ciscnt,
char **vars, uint *count);
#endif /* _BRCM_SROM_H_ */

View File

@ -1,477 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <net/mac80211.h>
#include "types.h"
#include "d11.h"
#include "rate.h"
#include "phy/phy_hal.h"
#include "channel.h"
#include "main.h"
#include "bmac.h"
#include "stf.h"
#define MIN_SPATIAL_EXPANSION 0
#define MAX_SPATIAL_EXPANSION 1
#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val);
static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, u8 val);
static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val);
static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val);
static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
ratespec_t rspec);
#define NSTS_1 1
#define NSTS_2 2
#define NSTS_3 3
#define NSTS_4 4
const u8 txcore_default[5] = {
(0), /* bitmap of the core enabled */
(0x01), /* For Nsts = 1, enable core 1 */
(0x03), /* For Nsts = 2, enable core 1 & 2 */
(0x07), /* For Nsts = 3, enable core 1, 2 & 3 */
(0x0f) /* For Nsts = 4, enable all cores */
};
static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val)
{
/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
if (BRCMS_STF_SS_STBC_RX(wlc)) {
if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
return;
}
wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_RX_STBC;
wlc->ht_cap.cap_info |= (val << IEEE80211_HT_CAP_RX_STBC_SHIFT);
if (wlc->pub->up) {
brcms_c_update_beacon(wlc);
brcms_c_update_probe_resp(wlc, true);
}
}
/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */
void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
{
struct brcms_phy_pub *pi = wlc->band->pi;
uint active_chains, txchain;
/* Check if the chip is too hot. Disable one Tx chain, if it is */
/* high 4 bits are for Rx chain, low 4 bits are for Tx chain */
active_chains = wlc_phy_stf_chain_active_get(pi);
txchain = active_chains & 0xf;
if (wlc->stf->txchain == wlc->stf->hw_txchain) {
if (txchain && (txchain < wlc->stf->hw_txchain)) {
/* turn off 1 tx chain */
brcms_c_stf_txchain_set(wlc, txchain, true);
}
} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
if (txchain == wlc->stf->hw_txchain) {
/* turn back on txchain */
brcms_c_stf_txchain_set(wlc, txchain, true);
}
}
}
void
brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
chanspec_t chanspec)
{
struct tx_power power;
u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
/* Clear previous settings */
*ss_algo_channel = 0;
if (!wlc->pub->up) {
*ss_algo_channel = (u16) -1;
return;
}
wlc_phy_txpower_get_current(wlc->band->pi, &power,
CHSPEC_CHANNEL(chanspec));
siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
/* criteria to choose stf mode */
/* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs
* on both chains
*/
if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
else
setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
/* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check
* so cannot be default mode of operation. One of SISO, CDD have to be set
*/
if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
}
static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
{
if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) {
return false;
}
if ((int_val == ON) && (wlc->stf->txstreams == 1))
return false;
if ((int_val == OFF) || (wlc->stf->txstreams == 1)
|| !BRCMS_STBC_CAP_PHY(wlc))
wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
else
wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_TX_STBC;
wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
return true;
}
bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
{
if ((int_val != HT_CAP_RX_STBC_NO)
&& (int_val != HT_CAP_RX_STBC_ONE_STREAM)) {
return false;
}
if (BRCMS_STF_SS_STBC_RX(wlc)) {
if ((int_val != HT_CAP_RX_STBC_NO)
&& (wlc->stf->rxstreams == 1))
return false;
}
brcms_c_stf_stbc_rx_ht_update(wlc, int_val);
return true;
}
static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
u8 core_mask)
{
BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
wlc->pub->unit, Nsts, core_mask);
if (BRCMS_BITSCNT(core_mask) > wlc->stf->txstreams) {
core_mask = 0;
}
if ((BRCMS_BITSCNT(core_mask) == wlc->stf->txstreams) &&
((core_mask & ~wlc->stf->txchain)
|| !(core_mask & wlc->stf->txchain))) {
core_mask = wlc->stf->txchain;
}
wlc->stf->txcore[Nsts] = core_mask;
/* Nsts = 1..4, txcore index = 1..4 */
if (Nsts == 1) {
/* Needs to update beacon and ucode generated response
* frames when 1 stream core map changed
*/
wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
if (wlc->clk) {
brcms_c_suspend_mac_and_wait(wlc);
brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
brcms_c_enable_mac(wlc);
}
}
return 0;
}
static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
{
int i;
u8 core_mask = 0;
BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val);
wlc->stf->spatial_policy = (s8) val;
for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
core_mask = (val == MAX_SPATIAL_EXPANSION) ?
wlc->stf->txchain : txcore_default[i];
brcms_c_stf_txcore_set(wlc, (u8) i, core_mask);
}
return 0;
}
int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
{
u8 txchain = (u8) int_val;
u8 txstreams;
uint i;
if (wlc->stf->txchain == txchain)
return 0;
if ((txchain & ~wlc->stf->hw_txchain)
|| !(txchain & wlc->stf->hw_txchain))
return -EINVAL;
/* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */
txstreams = (u8) BRCMS_BITSCNT(txchain);
if (txstreams > MAX_STREAMS_SUPPORTED)
return -EINVAL;
if (txstreams == 1) {
for (i = 0; i < NBANDS(wlc); i++)
if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
PHY_TXC1_MODE_SISO)
|| (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
PHY_TXC1_MODE_SISO)) {
if (!force)
return -EBADE;
/* over-write the override rspec */
if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
!= PHY_TXC1_MODE_SISO) {
wlc->bandstate[i]->rspec_override = 0;
wiphy_err(wlc->wiphy, "%s(): temp "
"sense override non-SISO "
"rspec_override\n",
__func__);
}
if (RSPEC_STF
(wlc->bandstate[i]->mrspec_override) !=
PHY_TXC1_MODE_SISO) {
wlc->bandstate[i]->mrspec_override = 0;
wiphy_err(wlc->wiphy, "%s(): temp "
"sense override non-SISO "
"mrspec_override\n",
__func__);
}
}
}
wlc->stf->txchain = txchain;
wlc->stf->txstreams = txstreams;
brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
wlc->stf->txant =
(wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
_brcms_c_stf_phy_txant_upd(wlc);
wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
wlc->stf->rxchain);
for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
return 0;
}
/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
{
int ret_code = 0;
u8 prev_stf_ss;
u8 upd_stf_ss;
prev_stf_ss = wlc->stf->ss_opmode;
/* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
if (BRCMS_STBC_CAP_PHY(wlc) &&
wlc->stf->ss_algosel_auto
&& (wlc->stf->ss_algo_channel != (u16) -1)) {
upd_stf_ss = (wlc->stf->no_cddstbc || (wlc->stf->txstreams == 1)
|| isset(&wlc->stf->ss_algo_channel,
PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
: PHY_TXC1_MODE_CDD;
} else {
if (wlc->band != band)
return ret_code;
upd_stf_ss = (wlc->stf->no_cddstbc
|| (wlc->stf->txstreams ==
1)) ? PHY_TXC1_MODE_SISO : band->
band_stf_ss_mode;
}
if (prev_stf_ss != upd_stf_ss) {
wlc->stf->ss_opmode = upd_stf_ss;
brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss);
}
return ret_code;
}
int brcms_c_stf_attach(struct brcms_c_info *wlc)
{
wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
if (BRCMS_ISNPHY(wlc->band) &&
(wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
PHY_TXC1_MODE_CDD;
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
if (BRCMS_STBC_CAP_PHY(wlc)) {
wlc->stf->ss_algosel_auto = true;
wlc->stf->ss_algo_channel = (u16) -1; /* Init the default value */
}
return 0;
}
void brcms_c_stf_detach(struct brcms_c_info *wlc)
{
}
/*
* Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain
* change
*
* Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
* achieve various tx/rx antenna selection schemes
*
* legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx)
* for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and
* do tx-antenna selection for SISO transmissions
* for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and
* do tx-antenna selection for SISO transmissions
* for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active
*/
static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
s8 txant;
txant = (s8) wlc->stf->txant;
if (BRCMS_PHY_11N_CAP(wlc->band)) {
if (txant == ANT_TX_FORCE_0) {
wlc->stf->phytxant = PHY_TXC_ANT_0;
} else if (txant == ANT_TX_FORCE_1) {
wlc->stf->phytxant = PHY_TXC_ANT_1;
if (BRCMS_ISNPHY(wlc->band) &&
NREV_GE(wlc->band->phyrev, 3)
&& NREV_LT(wlc->band->phyrev, 7)) {
wlc->stf->phytxant = PHY_TXC_ANT_2;
}
} else {
if (BRCMS_ISLCNPHY(wlc->band) ||
BRCMS_ISSSLPNPHY(wlc->band))
wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
else {
/* catch out of sync wlc->stf->txcore */
WARN_ON(wlc->stf->txchain <= 0);
wlc->stf->phytxant =
wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
}
}
} else {
if (txant == ANT_TX_FORCE_0)
wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
else if (txant == ANT_TX_FORCE_1)
wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
else
wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
}
brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
}
void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
{
_brcms_c_stf_phy_txant_upd(wlc);
}
void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
{
/* get available rx/tx chains */
wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
/* these parameter are intended to be used for all PHY types */
if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
if (BRCMS_ISNPHY(wlc->band)) {
wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
} else {
wlc->stf->hw_txchain = TXCHAIN_DEF;
}
}
wlc->stf->txchain = wlc->stf->hw_txchain;
wlc->stf->txstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_txchain);
if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
if (BRCMS_ISNPHY(wlc->band)) {
wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
} else {
wlc->stf->hw_rxchain = RXCHAIN_DEF;
}
}
wlc->stf->rxchain = wlc->stf->hw_rxchain;
wlc->stf->rxstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_rxchain);
/* initialize the txcore table */
memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
/* default spatial_policy */
wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
}
static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
ratespec_t rspec)
{
u16 phytxant = wlc->stf->phytxant;
if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
} else if (wlc->stf->txant == ANT_TX_DEF)
phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
phytxant &= PHY_TXC_ANT_MASK;
return phytxant;
}
u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ratespec_t rspec)
{
return _brcms_c_stf_phytxchain_sel(wlc, rspec);
}
u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, ratespec_t rspec)
{
u16 phytxant = wlc->stf->phytxant;
u16 mask = PHY_TXC_ANT_MASK;
/* for non-siso rates or default setting, use the available chains */
if (BRCMS_ISNPHY(wlc->band)) {
phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec);
mask = PHY_TXC_HTANT_MASK;
}
phytxant |= phytxant & mask;
return phytxant;
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_STF_H_
#define _BRCM_STF_H_
#include "types.h"
extern int brcms_c_stf_attach(struct brcms_c_info *wlc);
extern void brcms_c_stf_detach(struct brcms_c_info *wlc);
extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
u16 *ss_algo_channel,
chanspec_t chanspec);
extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc,
struct brcms_band *band);
extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val,
bool force);
extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
ratespec_t rspec);
extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc,
ratespec_t rspec);
#endif /* _BRCM_STF_H_ */

View File

@ -1,399 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCM_TYPES_H_
#define _BRCM_TYPES_H_
#include <linux/types.h>
#include <linux/io.h>
/* Bus types */
#define SI_BUS 0 /* SOC Interconnect */
#define PCI_BUS 1 /* PCI target */
#define SDIO_BUS 3 /* SDIO target */
#define JTAG_BUS 4 /* JTAG */
#define USB_BUS 5 /* USB (does not support R/W REG) */
#define SPI_BUS 6 /* gSPI target */
#define RPC_BUS 7 /* RPC target */
#define WL_CHAN_FREQ_RANGE_2G 0
#define WL_CHAN_FREQ_RANGE_5GL 1
#define WL_CHAN_FREQ_RANGE_5GM 2
#define WL_CHAN_FREQ_RANGE_5GH 3
#define MAX_DMA_SEGS 4
/* boardflags */
#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */
#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */
#define BFL_FEM 0x00000800 /* Board supports the Front End Module */
#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */
#define BFL_NOPA 0x00010000 /* Board has no PA */
#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */
#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */
#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */
#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */
#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */
/* boardflags2 */
#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */
#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */
#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */
#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */
#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */
#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */
#define BFL2_LEGACY 0x00000080
#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */
#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */
#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */
#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */
#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */
#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */
#define BFL2_IPALVLSHIFT_3P3 0x00020000
#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */
#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio "ON"
* Most drivers will turn it off without this flag
* to save power.
*/
/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */
#define BOARD_GPIO_12 0x1000 /* gpio 12 */
#define BOARD_GPIO_13 0x2000 /* gpio 13 */
/* **** Core type/rev defaults **** */
#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27
* also need to update wlc.h MAXCOREREV
*/
#define NCONF 0x000001ff /* Supported nphy revs:
* 0 4321a0
* 1 4321a1
* 2 4321b0/b1/c0/c1
* 3 4322a0
* 4 4322a1
* 5 4716a0
* 6 43222a0, 43224a0
* 7 43226a0
* 8 5357a0, 43236a0
*/
#define LCNCONF 0x00000007 /* Supported lcnphy revs:
* 0 4313a0, 4336a0, 4330a0
* 1
* 2 4330a0
*/
#define SSLPNCONF 0x0000000f /* Supported sslpnphy revs:
* 0 4329a0/k0
* 1 4329b0/4329C0
* 2 4319a0
* 3 5356a0
*/
/********************************************************************
* Phy/Core Configuration. Defines macros to to check core phy/rev *
* compile-time configuration. Defines default core support. *
* ******************************************************************
*/
/* Basic macros to check a configuration bitmask */
#define CONF_HAS(config, val) ((config) & (1 << (val)))
#define CONF_MSK(config, mask) ((config) & (mask))
#define MSK_RANGE(low, hi) ((1 << ((hi)+1)) - (1 << (low)))
#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
#define CONF_IS(config, val) ((config) == (1 << (val)))
#define CONF_GE(config, val) ((config) & (0-(1 << (val))))
#define CONF_GT(config, val) ((config) & (0-2*(1 << (val))))
#define CONF_LT(config, val) ((config) & ((1 << (val))-1))
#define CONF_LE(config, val) ((config) & (2*(1 << (val))-1))
/* Wrappers for some of the above, specific to config constants */
#define NCONF_HAS(val) CONF_HAS(NCONF, val)
#define NCONF_MSK(mask) CONF_MSK(NCONF, mask)
#define NCONF_IS(val) CONF_IS(NCONF, val)
#define NCONF_GE(val) CONF_GE(NCONF, val)
#define NCONF_GT(val) CONF_GT(NCONF, val)
#define NCONF_LT(val) CONF_LT(NCONF, val)
#define NCONF_LE(val) CONF_LE(NCONF, val)
#define LCNCONF_HAS(val) CONF_HAS(LCNCONF, val)
#define LCNCONF_MSK(mask) CONF_MSK(LCNCONF, mask)
#define LCNCONF_IS(val) CONF_IS(LCNCONF, val)
#define LCNCONF_GE(val) CONF_GE(LCNCONF, val)
#define LCNCONF_GT(val) CONF_GT(LCNCONF, val)
#define LCNCONF_LT(val) CONF_LT(LCNCONF, val)
#define LCNCONF_LE(val) CONF_LE(LCNCONF, val)
#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
#define D11CONF_IS(val) CONF_IS(D11CONF, val)
#define D11CONF_GE(val) CONF_GE(D11CONF, val)
#define D11CONF_GT(val) CONF_GT(D11CONF, val)
#define D11CONF_LT(val) CONF_LT(D11CONF, val)
#define D11CONF_LE(val) CONF_LE(D11CONF, val)
#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
#define PHYCONF_IS(val) CONF_IS(PHYTYPE, val)
#define NREV_IS(var, val) (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
#define NREV_GE(var, val) (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
#define NREV_GT(var, val) (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
#define NREV_LT(var, val) (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
#define NREV_LE(var, val) (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
#define LCNREV_IS(var, val) (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
#define LCNREV_GE(var, val) (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
#define LCNREV_GT(var, val) (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
#define LCNREV_LT(var, val) (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
#define LCNREV_LE(var, val) (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
#define D11REV_IS(var, val) (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
#define D11REV_GE(var, val) (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
#define D11REV_GT(var, val) (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
#define D11REV_LT(var, val) (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
#define D11REV_LE(var, val) (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
#define PHYTYPE_IS(var, val) (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
/* Finally, early-exit from switch case if anyone wants it... */
#define CASECHECK(config, val) if (!(CONF_HAS(config, val))) break
#define CASEMSK(config, mask) if (!(CONF_MSK(config, mask))) break
/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
#define _PHYCONF_N (1 << PHY_TYPE_N)
#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
/* Utility macro to identify 802.11n (HT) capable PHYs */
#define PHYTYPE_11N_CAP(phytype) \
(PHYTYPE_IS(phytype, PHY_TYPE_N) || \
PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
PHYTYPE_IS(phytype, PHY_TYPE_SSN))
/* Last but not least: shorter wlc-specific var checks */
#define BRCMS_ISNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
#define BRCMS_ISLCNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
#define BRCMS_ISSSLPNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
#define BRCMS_PHY_11N_CAP(band) PHYTYPE_11N_CAP((band)->phytype)
/**********************************************************************
* ------------- End of Core phy/rev configuration. ----------------- *
* ********************************************************************
*/
/*************************************************
* Defaults for tunables (e.g. sizing constants)
*
* For each new tunable, add a member to the end
* of struct brcms_tunables in brcms_c_pub.h to enable
* runtime checks of tunable values. (Directly
* using the macros in code invalidates ROM code)
*
* ***********************************************
*/
#define NTXD 256 /* Max # of entries in Tx FIFO based on 4kb page size */
#define NRXD 256 /* Max # of entries in Rx FIFO based on 4kb page size */
#define NRXBUFPOST 32 /* try to keep this # rbufs posted to the chip */
#define MAXSCB 32 /* Maximum SCBs in cache for STA */
#define AMPDU_NUM_MPDU 16 /* max allowed number of mpdus in an ampdu (2 streams) */
/* Count of packet callback structures. either of following
* 1. Set to the number of SCBs since a STA
* can queue up a rate callback for each IBSS STA it knows about, and an AP can
* queue up an "are you there?" Null Data callback for each associated STA
* 2. controlled by tunable config file
*/
#define MAXPKTCB MAXSCB /* Max number of packet callbacks */
/* NetBSD also needs to keep track of this */
/* Number of BSS handled in ucode bcn/prb */
#define BRCMS_MAX_UCODE_BSS (16)
/* Number of BSS handled in sw bcn/prb */
#define BRCMS_MAX_UCODE_BSS4 (4)
/* max # BSS configs */
#define BRCMS_MAXBSSCFG (1)
/* max # available networks */
#define MAXBSS 64
/* data msg txq hiwat mark */
#define BRCMS_DATAHIWAT 50
#define BRCMS_AMPDUDATAHIWAT 255
/* bounded rx loops */
#define RXBND 8 /* max # frames to process in brcms_c_recv() */
#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */
#define BAND_5G(bt) ((bt) == BRCM_BAND_5G)
#define BAND_2G(bt) ((bt) == BRCM_BAND_2G)
#define BCMMSG(dev, fmt, args...) \
do { \
if (brcm_msg_level & LOG_TRACE_VAL) \
wiphy_err(dev, "%s: " fmt, __func__, ##args); \
} while (0)
#define WL_ERROR_ON() (brcm_msg_level & LOG_ERROR_VAL)
/* register access macros */
#ifndef __BIG_ENDIAN
#ifndef __mips__
#define R_REG(r) \
({\
sizeof(*(r)) == sizeof(u8) ? \
readb((u8 *)(r)) : \
sizeof(*(r)) == sizeof(u16) ? readw((u16 *)(r)) : \
readl((u32 *)(r)); \
})
#else /* __mips__ */
#define R_REG(r) \
({ \
__typeof(*(r)) __osl_v; \
__asm__ __volatile__("sync"); \
switch (sizeof(*(r))) { \
case sizeof(u8): \
__osl_v = readb((u8 *)(r)); \
break; \
case sizeof(u16): \
__osl_v = readw((u16 *)(r)); \
break; \
case sizeof(u32): \
__osl_v = \
readl((u32 *)(r)); \
break; \
} \
__asm__ __volatile__("sync"); \
__osl_v; \
})
#endif /* __mips__ */
#define W_REG(r, v) do { \
switch (sizeof(*(r))) { \
case sizeof(u8): \
writeb((u8)(v), (u8 *)(r)); break; \
case sizeof(u16): \
writew((u16)(v), (u16 *)(r)); break; \
case sizeof(u32): \
writel((u32)(v), (u32 *)(r)); break; \
}; \
} while (0)
#else /* __BIG_ENDIAN */
#define R_REG(r) \
({ \
__typeof(*(r)) __osl_v; \
switch (sizeof(*(r))) { \
case sizeof(u8): \
__osl_v = \
readb((u8 *)((r)^3)); \
break; \
case sizeof(u16): \
__osl_v = \
readw((u16 *)((r)^2)); \
break; \
case sizeof(u32): \
__osl_v = readl((u32 *)(r)); \
break; \
} \
__osl_v; \
})
#define W_REG(r, v) do { \
switch (sizeof(*(r))) { \
case sizeof(u8): \
writeb((u8)(v), \
(u8 *)((r)^3)); break; \
case sizeof(u16): \
writew((u16)(v), \
(u16 *)((r)^2)); break; \
case sizeof(u32): \
writel((u32)(v), \
(u32 *)(r)); break; \
} \
} while (0)
#endif /* __BIG_ENDIAN */
#ifdef __mips__
/*
* bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
* transactions. As a fix, a read after write is performed on certain places
* in the code. Older chips and the newer 5357 family don't require this fix.
*/
#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); })
#else
#define W_REG_FLUSH(r, v) W_REG((r), (v))
#endif /* __mips__ */
#define AND_REG(r, v) W_REG((r), R_REG(r) & (v))
#define OR_REG(r, v) W_REG((r), R_REG(r) | (v))
#define SET_REG(r, mask, val) \
W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
/* multi-bool data type: set of bools, mbool is true if any is set */
typedef u32 mbool;
#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */
#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */
#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* true if one bool is set */
#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
/* forward declarations */
struct wiphy;
struct ieee80211_sta;
struct ieee80211_tx_queue_params;
struct brcms_info;
struct brcms_c_info;
struct brcms_hardware;
struct brcms_c_if;
struct brcmu_iovar;
struct brcmu_strbuf;
struct brcms_txq_info;
struct brcms_band;
struct dma_pub;
struct si_pub;
struct tx_status;
struct d11rxhdr;
struct brcms_d11rxhdr;
struct txpwr_limits;
struct brcms_phy;
typedef volatile struct intctrlregs intctrlregs_t;
typedef volatile struct pio2regs pio2regs_t;
typedef volatile struct pio2regp pio2regp_t;
typedef volatile struct pio4regs pio4regs_t;
typedef volatile struct pio4regp pio4regp_t;
typedef volatile struct fifo64 fifo64_t;
typedef volatile struct d11regs d11regs_t;
typedef volatile struct dma32diag dma32diag_t;
typedef volatile struct dma64regs dma64regs_t;
typedef struct brcms_rateset wlc_rateset_t;
typedef u32 ratespec_t;
typedef struct chanvec chanvec_t;
typedef s32 fixed;
typedef struct _cs32 cs32;
typedef volatile union pmqreg pmqreg_t;
/* brcm_msg_level is a bit vector with defs in defs.h */
extern u32 brcm_msg_level;
#endif /* _BRCM_TYPES_H_ */

View File

@ -1,115 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <defs.h>
#include "types.h"
#include <ucode_loader.h>
enum {
D11UCODE_NAMETAG_START = 0,
D11LCN0BSINITVALS24,
D11LCN0INITVALS24,
D11LCN1BSINITVALS24,
D11LCN1INITVALS24,
D11LCN2BSINITVALS24,
D11LCN2INITVALS24,
D11N0ABSINITVALS16,
D11N0BSINITVALS16,
D11N0INITVALS16,
D11UCODE_OVERSIGHT16_MIMO,
D11UCODE_OVERSIGHT16_MIMOSZ,
D11UCODE_OVERSIGHT24_LCN,
D11UCODE_OVERSIGHT24_LCNSZ,
D11UCODE_OVERSIGHT_BOMMAJOR,
D11UCODE_OVERSIGHT_BOMMINOR
};
struct d11init *d11lcn0bsinitvals24;
struct d11init *d11lcn0initvals24;
struct d11init *d11lcn1bsinitvals24;
struct d11init *d11lcn1initvals24;
struct d11init *d11lcn2bsinitvals24;
struct d11init *d11lcn2initvals24;
struct d11init *d11n0absinitvals16;
struct d11init *d11n0bsinitvals16;
struct d11init *d11n0initvals16;
u32 *bcm43xx_16_mimo;
u32 bcm43xx_16_mimosz;
u32 *bcm43xx_24_lcn;
u32 bcm43xx_24_lcnsz;
u32 *bcm43xx_bommajor;
u32 *bcm43xx_bomminor;
int brcms_ucode_data_init(struct brcms_info *wl)
{
int rc;
rc = brcms_check_firmwares(wl);
rc = rc < 0 ? rc :
brcms_ucode_init_buf(wl, (void **)&d11lcn0bsinitvals24,
D11LCN0BSINITVALS24);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn0initvals24,
D11LCN0INITVALS24);
rc = rc < 0 ? rc :
brcms_ucode_init_buf(wl, (void **)&d11lcn1bsinitvals24,
D11LCN1BSINITVALS24);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn1initvals24,
D11LCN1INITVALS24);
rc = rc < 0 ? rc :
brcms_ucode_init_buf(wl, (void **)&d11lcn2bsinitvals24,
D11LCN2BSINITVALS24);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn2initvals24,
D11LCN2INITVALS24);
rc = rc < 0 ? rc :
brcms_ucode_init_buf(wl, (void **)&d11n0absinitvals16,
D11N0ABSINITVALS16);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11n0bsinitvals16,
D11N0BSINITVALS16);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11n0initvals16,
D11N0INITVALS16);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_16_mimo,
D11UCODE_OVERSIGHT16_MIMO);
rc = rc < 0 ? rc : brcms_ucode_init_uint(wl, &bcm43xx_16_mimosz,
D11UCODE_OVERSIGHT16_MIMOSZ);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_24_lcn,
D11UCODE_OVERSIGHT24_LCN);
rc = rc < 0 ? rc : brcms_ucode_init_uint(wl, &bcm43xx_24_lcnsz,
D11UCODE_OVERSIGHT24_LCNSZ);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_bommajor,
D11UCODE_OVERSIGHT_BOMMAJOR);
rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_bomminor,
D11UCODE_OVERSIGHT_BOMMINOR);
return rc;
}
void brcms_ucode_data_free(void)
{
brcms_ucode_free_buf((void *)d11lcn0bsinitvals24);
brcms_ucode_free_buf((void *)d11lcn0initvals24);
brcms_ucode_free_buf((void *)d11lcn1bsinitvals24);
brcms_ucode_free_buf((void *)d11lcn1initvals24);
brcms_ucode_free_buf((void *)d11lcn2bsinitvals24);
brcms_ucode_free_buf((void *)d11lcn2initvals24);
brcms_ucode_free_buf((void *)d11n0absinitvals16);
brcms_ucode_free_buf((void *)d11n0bsinitvals16);
brcms_ucode_free_buf((void *)d11n0initvals16);
brcms_ucode_free_buf((void *)bcm43xx_16_mimo);
brcms_ucode_free_buf((void *)bcm43xx_24_lcn);
brcms_ucode_free_buf((void *)bcm43xx_bommajor);
brcms_ucode_free_buf((void *)bcm43xx_bomminor);
return;
}

View File

@ -1,52 +0,0 @@
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "types.h" /* forward structure declarations */
#define MIN_FW_SIZE 40000 /* minimum firmware file size in bytes */
#define MAX_FW_SIZE 150000
#define UCODE_LOADER_API_VER 0
struct d11init {
u16 addr;
u16 size;
u32 value;
};
extern struct d11init *d11lcn0bsinitvals24;
extern struct d11init *d11lcn0initvals24;
extern struct d11init *d11lcn1bsinitvals24;
extern struct d11init *d11lcn1initvals24;
extern struct d11init *d11lcn2bsinitvals24;
extern struct d11init *d11lcn2initvals24;
extern struct d11init *d11n0absinitvals16;
extern struct d11init *d11n0bsinitvals16;
extern struct d11init *d11n0initvals16;
extern u32 *bcm43xx_16_mimo;
extern u32 bcm43xx_16_mimosz;
extern u32 *bcm43xx_24_lcn;
extern u32 bcm43xx_24_lcnsz;
extern int brcms_ucode_data_init(struct brcms_info *wl);
extern void brcms_ucode_data_free(void);
extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf,
unsigned int idx);
extern int brcms_ucode_init_uint(struct brcms_info *wl, unsigned *data,
unsigned int idx);
extern void brcms_ucode_free_buf(void *);
extern int brcms_check_firmwares(struct brcms_info *wl);

Some files were not shown because too many files have changed in this diff Show More