adds dsl support, thank you infineon/lantiq

SVN-Revision: 18259
This commit is contained in:
John Crispin 2009-11-01 18:52:35 +00:00
parent eff68fb14b
commit 976d1a1024
34 changed files with 8430 additions and 3351 deletions

View file

@ -1,49 +0,0 @@
# Copyright (C) 2009 OpenWrt.org
# All rights reserved.
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# blogic@openwrt.org
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=ifxmips-atm
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define KernelPackage/ifxmips-atm
SUBMENU:=Network Devices
DEPENDS:=@BROKEN @TARGET_ifxmips +kmod-atm
TITLE:=ifxmips atm driver
FILES:=$(PKG_BUILD_DIR)/ifx-atm.$(LINUX_KMOD_SUFFIX)
AUTOLOAD:=$(call AutoLoad,50,ifx-atm)
endef
define Kernel/Package/ifxmips-atm/description
This package provides the atm driver needed to make dsl work on ifxmips based boards
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
ARCH="$(LINUX_KARCH)" \
SUBDIRS="$(PKG_BUILD_DIR)" \
modules
endef
define KernelPackage/ifxmips-atm/install
$(INSTALL_DIR) $(1)/lib/modules/$(LINUX_VERSION)
$(CP) $(PKG_BUILD_DIR)/ifx-atm.ko $(1)/lib/modules/$(LINUX_VERSION)
endef
$(eval $(call KernelPackage,ifxmips-atm))

View file

@ -1,4 +0,0 @@
obj-m += ifx-atm.o
ifx-atm-objs := skb.o irq.o proc.o core.o ppe.o
EXTRA_CFLAGS += -DENABLE_RX_QOS=1

View file

@ -1,896 +0,0 @@
#include <linux/atmdev.h>
#include <asm/ifxmips/ifxmips_irq.h>
#include <linux/irq.h>
#include <linux/sem.h>
#include <linux/coda.h>
#define RX_DMA_CH_CBR 0
#define RX_DMA_CH_VBR_RT 1
#define RX_DMA_CH_VBR_NRT 2
#define RX_DMA_CH_AVR 3
#define RX_DMA_CH_UBR 4
#define RX_DMA_CH_OAM 5
#define RX_DMA_CH_TOTAL 6
#define WRX_DMA_CHANNEL_INTERRUPT_MODE 0x00
#define WRX_DMA_CHANNEL_POLLING_MODE 0x01
//#define WRX_DMA_CHANNEL_COUNTER_MODE 0x02
#define WRX_DMA_CHANNEL_COUNTER_MODE WRX_DMA_CHANNEL_INTERRUPT_MODE
#define WRX_DMA_BUF_LEN_PER_DESCRIPTOR 0x00
#define WRX_DMA_BUF_LEN_PER_CHANNEL 0x01
#define ATM_VBR_RT 6
#define ATM_VBR_NRT ATM_VBR
#define ATM_UBR_PLUS 7
#define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
#define GET_ATM_PRIV(dev) ((Atm_Priv *)dev->priv)
#define CDM_CFG PPE_REG_ADDR(0x0100)
#define CDM_CFG_RAM1 GET_BITS(*CDM_CFG, 3, 2)
#define CDM_CFG_RAM0 (*CDM_CFG & (1 << 1))
#define CDM_CFG_RAM1_SET(value) SET_BITS(0, 3, 2, value)
#define CDM_CFG_RAM0_SET(value) ((value) ? (1 << 1) : 0)
/*
* EMA Registers
*/
#define EMA_CMDCFG PPE_REG_ADDR(0x0A00)
#define EMA_DATACFG PPE_REG_ADDR(0x0A01)
#define EMA_CMDCNT PPE_REG_ADDR(0x0A02)
#define EMA_DATACNT PPE_REG_ADDR(0x0A03)
#define EMA_ISR PPE_REG_ADDR(0x0A04)
#define EMA_IER PPE_REG_ADDR(0x0A05)
#define EMA_CFG PPE_REG_ADDR(0x0A06)
#define EMA_SUBID PPE_REG_ADDR(0x0A07)
/*
* QSB RAM Access Register
*/
#define QSB_RAMAC QSB_CONF_REG(0x000D)
#define QSB_RAMAC_RW (*QSB_RAMAC & (1 << 31))
#define QSB_RAMAC_TSEL GET_BITS(*QSB_RAMAC, 27, 24)
#define QSB_RAMAC_LH (*QSB_RAMAC & (1 << 16))
#define QSB_RAMAC_TESEL GET_BITS(*QSB_RAMAC, 9, 0)
#define QSB_RAMAC_RW_SET(value) ((value) ? (1 << 31) : 0)
#define QSB_RAMAC_TSEL_SET(value) SET_BITS(0, 27, 24, value)
#define QSB_RAMAC_LH_SET(value) ((value) ? (1 << 16) : 0)
#define QSB_RAMAC_TESEL_SET(value) SET_BITS(0, 9, 0, value)
/* QSB */
#define QSB_RAMAC_RW_READ 0
#define QSB_RAMAC_RW_WRITE 1
#define QSB_RAMAC_TSEL_QPT 0x01
#define QSB_RAMAC_TSEL_SCT 0x02
#define QSB_RAMAC_TSEL_SPT 0x03
#define QSB_RAMAC_TSEL_VBR 0x08
#define QSB_RAMAC_LH_LOW 0
#define QSB_RAMAC_LH_HIGH 1
#define QSB_QPT_SET_MASK 0x0
#define QSB_QVPT_SET_MASK 0x0
#define QSB_SET_SCT_MASK 0x0
#define QSB_SET_SPT_MASK 0x0
#define QSB_SET_SPT_SBVALID_MASK 0x7FFFFFFF
#define QSB_SPT_SBV_VALID (1 << 31)
#define QSB_SPT_PN_SET(value) (((value) & 0x01) ? (1 << 16) : 0)
#define QSB_SPT_INTRATE_SET(value) SET_BITS(0, 13, 0, value)
/*
* QSB Internal Cell Delay Variation Register
*/
#define QSB_ICDV QSB_CONF_REG(0x0007)
#define QSB_ICDV_TAU GET_BITS(*QSB_ICDV, 5, 0)
#define QSB_ICDV_TAU_SET(value) SET_BITS(0, 5, 0, value)
/*
* QSB Scheduler Burst Limit Register
*/
#define QSB_SBL QSB_CONF_REG(0x0009)
#define QSB_SBL_SBL GET_BITS(*QSB_SBL, 3, 0)
#define QSB_SBL_SBL_SET(value) SET_BITS(0, 3, 0, value)
/*
* QSB Configuration Register
*/
#define QSB_CFG QSB_CONF_REG(0x000A)
#define QSB_CFG_TSTEPC GET_BITS(*QSB_CFG, 1, 0)
#define QSB_CFG_TSTEPC_SET(value) SET_BITS(0, 1, 0, value)
/*
* QSB RAM Transfer Table Register
*/
#define QSB_RTM QSB_CONF_REG(0x000B)
#define QSB_RTM_DM (*QSB_RTM)
#define QSB_RTM_DM_SET(value) ((value) & 0xFFFFFFFF)
/*
* QSB RAM Transfer Data Register
*/
#define QSB_RTD QSB_CONF_REG(0x000C)
#define QSB_RTD_TTV (*QSB_RTD)
#define QSB_RTD_TTV_SET(value) ((value) & 0xFFFFFFFF)
/*
* PP32 Debug Control Register
*/
#define PP32_DBG_CTRL PP32_DEBUG_REG_ADDR(0x0000)
#define DBG_CTRL_START_SET(value) ((value) ? (1 << 0) : 0)
#define DBG_CTRL_STOP_SET(value) ((value) ? (1 << 1) : 0)
#define DBG_CTRL_STEP_SET(value) ((value) ? (1 << 2) : 0)
#define SB_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x8000) << 2)))
#define UPDATE_VCC_STAT(conn, item, num) do { ppe_dev.connection[conn].item += num; } while (0)
/*
* EMA Settings
*/
#define EMA_CMD_BUF_LEN 0x0040
#define EMA_CMD_BASE_ADDR (0x00001580 << 2)
#define EMA_DATA_BUF_LEN 0x0100
#define EMA_DATA_BASE_ADDR (0x00001900 << 2)
#define EMA_WRITE_BURST 0x2
#define EMA_READ_BURST 0x2
#define CELL_SIZE ATM_AAL0_SDU
#define IDLE_CYCLE_NUMBER 30000
#define MBOX_IGU1_ISR PPE_REG_ADDR(0x0206)
#define MBOX_IGU3_ISRS PPE_REG_ADDR(0x0214)
#define MBOX_IGU1_ISRC PPE_REG_ADDR(0x0205)
#define MBOX_IGU3_ISR PPE_REG_ADDR(0x0216)
#define MBOX_IGU3_ISRS_SET(n) (1 << (n))
#define MBOX_IGU3_ISR_ISR(n) (*MBOX_IGU3_ISR & (1 << (n)))
/*
* * Mailbox IGU1 Registers
* */
#define MBOX_IGU1_ISRS PPE_REG_ADDR(0x0204)
#define MBOX_IGU1_IER PPE_REG_ADDR(0x0207)
#define MBOX_IGU1_ISRS_SET(n) (1 << (n))
#define MBOX_IGU1_ISRC_CLEAR(n) (1 << (n))
#define MBOX_IGU1_ISR_ISR(n) (*MBOX_IGU1_ISR & (1 << (n)))
#define MBOX_IGU1_IER_EN(n) (*MBOX_IGU1_IER & (1 << (n)))
#define MBOX_IGU1_IER_EN_SET(n) (1 << (n))
/*
* * Mailbox IGU3 Registers
* */
#define MBOX_IGU3_ISRC PPE_REG_ADDR(0x0215)
#define MBOX_IGU3_IER PPE_REG_ADDR(0x0217)
#define MBOX_IGU3_ISRS_SET(n) (1 << (n))
#define MBOX_IGU3_ISRC_CLEAR(n) (1 << (n))
#define MBOX_IGU3_ISR_ISR(n) (*MBOX_IGU3_ISR & (1 << (n)))
#define MBOX_IGU3_IER_EN(n) (*MBOX_IGU3_IER & (1 << (n)))
#define MBOX_IGU3_IER_EN_SET(n) (1 << (n))
// RX Frame Definitions
#define MAX_RX_PACKET_ALIGN_BYTES 3
#define MAX_RX_PACKET_PADDING_BYTES 3
#define RX_INBAND_TRAILER_LENGTH 8
#define MAX_RX_FRAME_EXTRA_BYTES (RX_INBAND_TRAILER_LENGTH + MAX_RX_PACKET_ALIGN_BYTES + MAX_RX_PACKET_PADDING_BYTES)
// TX Frame Definitions
#define MAX_TX_HEADER_ALIGN_BYTES 12
#define MAX_TX_PACKET_ALIGN_BYTES 3
#define MAX_TX_PACKET_PADDING_BYTES 3
#define TX_INBAND_HEADER_LENGTH 8
#define MAX_TX_FRAME_EXTRA_BYTES (TX_INBAND_HEADER_LENGTH + MAX_TX_HEADER_ALIGN_BYTES + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES)
// DWORD-Length of Memory Blocks
#define PP32_DEBUG_REG_DWLEN 0x0030
#define PPM_INT_REG_DWLEN 0x0010
#define PP32_INTERNAL_RES_DWLEN 0x00C0
#define PPE_CLOCK_CONTROL_DWLEN 0x0F00
#define CDM_CODE_MEMORY_RAM0_DWLEN 0x1000
#define CDM_CODE_MEMORY_RAM1_DWLEN 0x0800
#define PPE_REG_DWLEN 0x1000
#define PP32_DATA_MEMORY_RAM1_DWLEN 0x0800
#define PPM_INT_UNIT_DWLEN 0x0100
#define PPM_TIMER0_DWLEN 0x0100
#define PPM_TASK_IND_REG_DWLEN 0x0100
#define PPS_BRK_DWLEN 0x0100
#define PPM_TIMER1_DWLEN 0x0100
#define SB_RAM0_DWLEN 0x0400
#define SB_RAM1_DWLEN 0x0800
#define SB_RAM2_DWLEN 0x0A00
#define SB_RAM3_DWLEN 0x0400
#define QSB_CONF_REG_DWLEN 0x0100
/*
* QSB Queue Scheduling and Shaping Definitions
*/
#define QSB_WFQ_NONUBR_MAX 0x3f00
#define QSB_WFQ_UBR_BYPASS 0x3fff
#define QSB_TP_TS_MAX 65472
#define QSB_TAUS_MAX 64512
#define QSB_GCR_MIN 18
// OAM Definitions
#define OAM_RX_QUEUE_NUMBER 1
#define OAM_TX_QUEUE_NUMBER_PER_PORT 0
#define OAM_RX_DMA_CHANNEL_NUMBER OAM_RX_QUEUE_NUMBER
#define OAM_HTU_ENTRY_NUMBER 3
#define OAM_F4_SEG_HTU_ENTRY 0
#define OAM_F4_TOT_HTU_ENTRY 1
#define OAM_F5_HTU_ENTRY 2
#define OAM_F4_CELL_ID 0
#define OAM_F5_CELL_ID 15
// ATM Port, QSB Queue, DMA RX/TX Channel Parameters
#define ATM_PORT_NUMBER 2
#define MAX_QUEUE_NUMBER 16
#define QSB_QUEUE_NUMBER_BASE 1
#define MAX_QUEUE_NUMBER_PER_PORT (MAX_QUEUE_NUMBER - QSB_QUEUE_NUMBER_BASE)
#define MAX_CONNECTION_NUMBER MAX_QUEUE_NUMBER
#define MAX_RX_DMA_CHANNEL_NUMBER 8
#define MAX_TX_DMA_CHANNEL_NUMBER 16
#define DMA_ALIGNMENT 4
#define DEFAULT_RX_HUNT_BITTH 4
/*
* FPI Configuration Bus Register and Memory Address Mapping
*/
#define DANUBE_PPE (KSEG1 + 0x1E180000)
#define PP32_DEBUG_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x0000) << 2)))
#define PPM_INT_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x0030) << 2)))
#define PP32_INTERNAL_RES_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x0040) << 2)))
#define PPE_CLOCK_CONTROL_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x0100) << 2)))
#define CDM_CODE_MEMORY_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x1000) << 2)))
#define CDM_CODE_MEMORY_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x2000) << 2)))
#define PPE_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x4000) << 2)))
#define PP32_DATA_MEMORY_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x5000) << 2)))
#define PPM_INT_UNIT_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x6000) << 2)))
#define PPM_TIMER0_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x6100) << 2)))
#define PPM_TASK_IND_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x6200) << 2)))
#define PPS_BRK_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x6300) << 2)))
#define PPM_TIMER1_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x6400) << 2)))
#define SB_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x8000) << 2)))
#define SB_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x8400) << 2)))
#define SB_RAM2_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x8C00) << 2)))
#define SB_RAM3_ADDR(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0x9600) << 2)))
#define QSB_CONF_REG(x) ((volatile u32*)(DANUBE_PPE + (((x) + 0xC000) << 2)))
/*
* Host-PPE Communication Data Address Mapping
*/
#define CFG_WRX_HTUTS PPM_INT_UNIT_ADDR(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */
#define CFG_WRX_QNUM PPM_INT_UNIT_ADDR(0x2401) /* WAN RX Queue Number */
#define CFG_WRX_DCHNUM PPM_INT_UNIT_ADDR(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */
#define CFG_WTX_DCHNUM PPM_INT_UNIT_ADDR(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */
#define CFG_WRDES_DELAY PPM_INT_UNIT_ADDR(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */
#define WRX_DMACH_ON PPM_INT_UNIT_ADDR(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */
#define WTX_DMACH_ON PPM_INT_UNIT_ADDR(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */
#define WRX_HUNT_BITTH PPM_INT_UNIT_ADDR(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */
#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*)PPM_INT_UNIT_ADDR(0x2500 + (i) * 20))
#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*)PPM_INT_UNIT_ADDR(0x2640 + (i) * 7))
#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*)PPM_INT_UNIT_ADDR(0x2440 + (i)))
#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*)PPM_INT_UNIT_ADDR(0x2710 + (i) * 27))
#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*)PPM_INT_UNIT_ADDR(0x2711 + (i) * 27))
#define WAN_MIB_TABLE ((struct wan_mib_table*)PPM_INT_UNIT_ADDR(0x2410))
#define HTU_ENTRY(i) ((struct htu_entry*)PPM_INT_UNIT_ADDR(0x2000 + (i)))
#define HTU_MASK(i) ((struct htu_mask*)PPM_INT_UNIT_ADDR(0x2020 + (i)))
#define HTU_RESULT(i) ((struct htu_result*)PPM_INT_UNIT_ADDR(0x2040 + (i)))
// DREG Idle Counters
#define DREG_AT_CELL0 PPE_REG_ADDR(0x0D24)
#define DREG_AT_CELL1 PPE_REG_ADDR(0x0D25)
#define DREG_AT_IDLE_CNT0 PPE_REG_ADDR(0x0D26)
#define DREG_AT_IDLE_CNT1 PPE_REG_ADDR(0x0D27)
#define DREG_AR_CELL0 PPE_REG_ADDR(0x0D68)
#define DREG_AR_CELL1 PPE_REG_ADDR(0x0D69)
#define DREG_AR_IDLE_CNT0 PPE_REG_ADDR(0x0D6A)
#define DREG_AR_IDLE_CNT1 PPE_REG_ADDR(0x0D6B)
#define DREG_AR_AIIDLE_CNT0 PPE_REG_ADDR(0x0D6C)
#define DREG_AR_AIIDLE_CNT1 PPE_REG_ADDR(0x0D6D)
#define DREG_AR_BE_CNT0 PPE_REG_ADDR(0x0D6E)
#define DREG_AR_BE_CNT1 PPE_REG_ADDR(0x0D6F)
/*
* 64-bit Data Type
*/
typedef struct {
unsigned int h: 32;
unsigned int l: 32;
} ppe_u64_t;
/*
* PPE ATM Cell Header
*/
#if defined(__BIG_ENDIAN)
struct uni_cell_header {
unsigned int gfc :4;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int clp :1;
};
#else
struct uni_cell_header {
unsigned int clp :1;
unsigned int pti :3;
unsigned int vci :16;
unsigned int vpi :8;
unsigned int gfc :4;
};
#endif // defined(__BIG_ENDIAN)
/*
* Inband Header and Trailer
*/
#if defined(__BIG_ENDIAN)
struct rx_inband_trailer {
/* 0 - 3h */
unsigned int uu :8;
unsigned int cpi :8;
unsigned int stw_res1:4;
unsigned int stw_clp :1;
unsigned int stw_ec :1;
unsigned int stw_uu :1;
unsigned int stw_cpi :1;
unsigned int stw_ovz :1;
unsigned int stw_mfl :1;
unsigned int stw_usz :1;
unsigned int stw_crc :1;
unsigned int stw_il :1;
unsigned int stw_ra :1;
unsigned int stw_res2:2;
/* 4 - 7h */
unsigned int gfc :4;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int clp :1;
};
struct tx_inband_header {
/* 0 - 3h */
unsigned int gfc :4;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int clp :1;
/* 4 - 7h */
unsigned int uu :8;
unsigned int cpi :8;
unsigned int pad :8;
unsigned int res1 :8;
};
#else
struct rx_inband_trailer {
/* 0 - 3h */
unsigned int stw_res2:2;
unsigned int stw_ra :1;
unsigned int stw_il :1;
unsigned int stw_crc :1;
unsigned int stw_usz :1;
unsigned int stw_mfl :1;
unsigned int stw_ovz :1;
unsigned int stw_cpi :1;
unsigned int stw_uu :1;
unsigned int stw_ec :1;
unsigned int stw_clp :1;
unsigned int stw_res1:4;
unsigned int cpi :8;
unsigned int uu :8;
/* 4 - 7h */
unsigned int clp :1;
unsigned int pti :3;
unsigned int vci :16;
unsigned int vpi :8;
unsigned int gfc :4;
};
struct tx_inband_header {
/* 0 - 3h */
unsigned int clp :1;
unsigned int pti :3;
unsigned int vci :16;
unsigned int vpi :8;
unsigned int gfc :4;
/* 4 - 7h */
unsigned int res1 :8;
unsigned int pad :8;
unsigned int cpi :8;
unsigned int uu :8;
};
#endif // defined(__BIG_ENDIAN)
struct wan_mib_table {
unsigned int res1;
unsigned int wrx_drophtu_cell;
unsigned int wrx_dropdes_pdu;
unsigned int wrx_correct_pdu;
unsigned int wrx_err_pdu;
unsigned int wrx_dropdes_cell;
unsigned int wrx_correct_cell;
unsigned int wrx_err_cell;
unsigned int wrx_total_byte;
unsigned int wtx_total_pdu;
unsigned int wtx_total_cell;
unsigned int wtx_total_byte;
};
/*
* Internal Structure of Device
*/
struct port {
int connection_base; /* first connection ID (RX/TX queue ID) */
unsigned int max_connections; /* maximum connection number */
unsigned int connection_table; /* connection opened status, every bit */
unsigned int tx_max_cell_rate; /* maximum cell rate */
unsigned int tx_current_cell_rate; /* currently used cell rate */
#if !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS
int rx_dma_channel_base; /* first RX DMA channel ID */
unsigned int rx_dma_channel_assigned;/* totally RX DMA channels used */
#endif // !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS
int oam_tx_queue; /* first TX queue ID of OAM cell */
struct atm_dev *dev;
};
struct connection {
struct atm_vcc *vcc; /* opened VCC */
struct timespec access_time; /* time when last F4/F5 user cell arrives */
unsigned int aal5_vcc_crc_err; /* number of packets with CRC error */
unsigned int aal5_vcc_oversize_sdu; /* number of packets with oversize error */
int rx_dma_channel; /* RX DMA channel ID assigned */
int port; /* to which port the connection belongs */
unsigned int rx_pdu;
unsigned int rx_err_pdu;
unsigned int rx_sw_drop_pdu;
unsigned int tx_pdu;
unsigned int tx_err_pdu;
unsigned int tx_hw_drop_pdu;
unsigned int tx_sw_drop_pdu;
};
struct ppe_dev {
struct connection connection[MAX_CONNECTION_NUMBER];
struct port port[ATM_PORT_NUMBER];
struct aal5 {
unsigned char padding_byte; /* padding byte pattern of AAL5 packet */
unsigned int rx_max_packet_size; /* max AAL5 packet length */
unsigned int rx_min_packet_size; /* min AAL5 packet length */
unsigned int rx_buffer_size; /* max memory allocated for a AAL5 packet */
unsigned int tx_max_packet_size; /* max AAL5 packet length */
unsigned int tx_min_packet_size; /* min AAL5 packet length */
unsigned int tx_buffer_size; /* max memory allocated for a AAL5 packet */
unsigned int rx_drop_error_packet; /* 1: drop error packet, 0: ignore errors */
} aal5;
struct qsb {
unsigned int tau; /* cell delay variation due to concurrency */
unsigned int tstepc; /* shceduler burst length */
unsigned int sbl; /* time step */
} qsb;
struct dma {
unsigned int rx_descriptor_number; /* number of RX descriptors */
unsigned int tx_descriptor_number; /* number of TX descriptors */
unsigned int rx_clp1_desc_threshold; /* threshold to drop cells with CLP1 */
unsigned int write_descriptor_delay; /* delay on descriptor write path */
unsigned int rx_total_channel_used; /* total RX channel used */
void *rx_descriptor_addr; /* base address of memory allocated for */
struct rx_descriptor
*rx_descriptor_base; /* base address of RX descriptors */
int rx_desc_read_pos[MAX_RX_DMA_CHANNEL_NUMBER]; /* first RX descriptor */
/* to be read */
// struct sk_buff **rx_skb_pointers; /* base address of RX sk_buff pointers */
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
long rx_weight[MAX_RX_DMA_CHANNEL_NUMBER]; /* RX schedule weight */
long rx_default_weight[MAX_RX_DMA_CHANNEL_NUMBER]; /* default weight */
#endif
unsigned int tx_total_channel_used; /* total TX channel used */
void *tx_descriptor_addr; /* base address of memory allocated for */
/* TX descriptors */
struct tx_descriptor
*tx_descriptor_base; /* base address of TX descriptors */
int tx_desc_alloc_pos[MAX_TX_DMA_CHANNEL_NUMBER]; /* first TX descriptor */
/* could be allocated */
// int tx_desc_alloc_num[MAX_TX_DMA_CHANNEL_NUMBER]; /* number of allocated */
// /* TX descriptors */
int tx_desc_alloc_flag[MAX_TX_DMA_CHANNEL_NUMBER]; /* at least one TX */
/* descriptor is alloc */
// int tx_desc_send_pos[MAX_TX_DMA_CHANNEL_NUMBER]; /* first TX descriptor */
// /* to be send */
int tx_desc_release_pos[MAX_TX_DMA_CHANNEL_NUMBER]; /* first TX descriptor */
/* to be released */
struct sk_buff **tx_skb_pointers; /* base address of TX sk_buff pointers */
} dma;
struct mib {
ppe_u64_t wrx_total_byte; /* bit-64 extention of MIB table member */
ppe_u64_t wtx_total_byte; /* bit-64 extention of MIB talbe member */
unsigned int wrx_pdu; /* successfully received AAL5 packet */
unsigned int wrx_drop_pdu; /* AAL5 packet dropped by driver on RX */
unsigned int wtx_err_pdu; /* error AAL5 packet */
unsigned int wtx_drop_pdu; /* AAL5 packet dropped by driver on TX */
} mib;
struct wan_mib_table prev_mib;
int oam_rx_queue; /* RX queue ID of OAM cell */
int oam_rx_dma_channel; /* RX DMA channel ID of OAM cell */
int max_connections; /* total connections available */
struct semaphore sem; /* lock used by open/close function */
};
/*
* Host-PPE Communication Data Structure
*/
#if defined(__BIG_ENDIAN)
struct wrx_queue_config {
/* 0h */
unsigned int res2 :27;
unsigned int dmach :4;
unsigned int errdp :1;
/* 1h */
unsigned int oversize :16;
unsigned int undersize :16;
/* 2h */
unsigned int res1 :16;
unsigned int mfs :16;
/* 3h */
unsigned int uumask :8;
unsigned int cpimask :8;
unsigned int uuexp :8;
unsigned int cpiexp :8;
};
struct wtx_port_config {
unsigned int res1 :27;
unsigned int qid :4;
unsigned int qsben :1;
};
struct wtx_queue_config {
unsigned int res1 :25;
unsigned int sbid :1;
unsigned int res2 :3;
unsigned int type :2;
unsigned int qsben :1;
};
struct wrx_dma_channel_config {
/* 0h */
unsigned int res1 :1;
unsigned int mode :2;
unsigned int rlcfg :1;
unsigned int desba :28;
/* 1h */
unsigned int chrl :16;
unsigned int clp1th :16;
/* 2h */
unsigned int deslen :16;
unsigned int vlddes :16;
};
struct wtx_dma_channel_config {
/* 0h */
unsigned int res2 :1;
unsigned int mode :2;
unsigned int res3 :1;
unsigned int desba :28;
/* 1h */
unsigned int res1 :32;
/* 2h */
unsigned int deslen :16;
unsigned int vlddes :16;
};
struct htu_entry {
unsigned int res1 :2;
unsigned int pid :2;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int vld :1;
};
struct htu_mask {
unsigned int set :2;
unsigned int pid_mask :2;
unsigned int vpi_mask :8;
unsigned int vci_mask :16;
unsigned int pti_mask :3;
unsigned int clear :1;
};
struct htu_result {
unsigned int res1 :12;
unsigned int cellid :4;
unsigned int res2 :5;
unsigned int type :1;
unsigned int ven :1;
unsigned int res3 :5;
unsigned int qid :4;
};
struct rx_descriptor {
/* 0 - 3h */
unsigned int own :1;
unsigned int c :1;
unsigned int sop :1;
unsigned int eop :1;
unsigned int res1 :3;
unsigned int byteoff :2;
unsigned int res2 :2;
unsigned int id :4;
unsigned int err :1;
unsigned int datalen :16;
/* 4 - 7h */
unsigned int res3 :4;
unsigned int dataptr :28;
};
struct tx_descriptor {
/* 0 - 3h */
unsigned int own :1;
unsigned int c :1;
unsigned int sop :1;
unsigned int eop :1;
unsigned int byteoff :5;
unsigned int res1 :5;
unsigned int iscell :1;
unsigned int clp :1;
unsigned int datalen :16;
/* 4 - 7h */
unsigned int res2 :4;
unsigned int dataptr :28;
};
#else
struct wrx_queue_config {
/* 0h */
unsigned int errdp :1;
unsigned int dmach :4;
unsigned int res2 :27;
/* 1h */
unsigned int undersize :16;
unsigned int oversize :16;
/* 2h */
unsigned int mfs :16;
unsigned int res1 :16;
/* 3h */
unsigned int cpiexp :8;
unsigned int uuexp :8;
unsigned int cpimask :8;
unsigned int uumask :8;
};
struct wtx_port_config {
unsigned int qsben :1;
unsigned int qid :4;
unsigned int res1 :27;
};
struct wtx_queue_config {
unsigned int qsben :1;
unsigned int type :2;
unsigned int res2 :3;
unsigned int sbid :1;
unsigned int res1 :25;
};
struct wrx_dma_channel_config
{
/* 0h */
unsigned int desba :28;
unsigned int rlcfg :1;
unsigned int mode :2;
unsigned int res1 :1;
/* 1h */
unsigned int clp1th :16;
unsigned int chrl :16;
/* 2h */
unsigned int vlddes :16;
unsigned int deslen :16;
};
struct wtx_dma_channel_config {
/* 0h */
unsigned int desba :28;
unsigned int res3 :1;
unsigned int mode :2;
unsigned int res2 :1;
/* 1h */
unsigned int res1 :32;
/* 2h */
unsigned int vlddes :16;
unsigned int deslen :16;
};
struct rx_descriptor {
/* 4 - 7h */
unsigned int dataptr :28;
unsigned int res3 :4;
/* 0 - 3h */
unsigned int datalen :16;
unsigned int err :1;
unsigned int id :4;
unsigned int res2 :2;
unsigned int byteoff :2;
unsigned int res1 :3;
unsigned int eop :1;
unsigned int sop :1;
unsigned int c :1;
unsigned int own :1;
};
struct tx_descriptor {
/* 4 - 7h */
unsigned int dataptr :28;
unsigned int res2 :4;
/* 0 - 3h */
unsigned int datalen :16;
unsigned int clp :1;
unsigned int iscell :1;
unsigned int res1 :5;
unsigned int byteoff :5;
unsigned int eop :1;
unsigned int sop :1;
unsigned int c :1;
unsigned int own :1;
};
#endif // defined(__BIG_ENDIAN)
/*
* QSB Queue Parameter Table Entry and Queue VBR Parameter Table Entry
*/
#if defined(__BIG_ENDIAN)
union qsb_queue_parameter_table {
struct {
unsigned int res1 :1;
unsigned int vbr :1;
unsigned int wfqf :14;
unsigned int tp :16;
} bit;
unsigned int dword;
};
union qsb_queue_vbr_parameter_table {
struct {
unsigned int taus :16;
unsigned int ts :16;
} bit;
unsigned int dword;
};
#else
union qsb_queue_parameter_table {
struct {
unsigned int tp :16;
unsigned int wfqf :14;
unsigned int vbr :1;
unsigned int res1 :1;
} bit;
unsigned int dword;
};
union qsb_queue_vbr_parameter_table {
struct {
unsigned int ts :16;
unsigned int taus :16;
} bit;
unsigned int dword;
};
#endif // defined(__BIG_ENDIAN)
typedef enum
{
IAD_ATM_CBR = 6, /* IAD_ATM_PRI_HIGH, */
IAD_ATM_VBR_RT = 4, /* IAD_ATM_PRI_MED_HIGH, VBR, Real-Time */
IAD_ATM_VBR_NRT = 2, /* IAD_ATM_PRI_MED_LOW, VBR, Non-Real-Time */
IAD_ATM_UBR = 0, /* IAD_ATM_PRI_LOW */
} iad_atmServiceCategory;
typedef unsigned int iad_atmDiffServCategory;
typedef struct
{
int cellRate;
int round; /* IAD_ATM_RATE_CEILING, IAD_ATM_RATE_FLOOR */
} iad_atmCellRateDesc;
typedef struct
{
unsigned int phyID; /* IAD_ATM_PHY0, IAD_ATM_PHY1 */
unsigned int txQHnd; /* Tx HW Q */
union _pri
{
int priority; /* TS Q: 4 priorities: IAD_ATM_PRI_HIGH, IAD_ATM_PRI_MED_HIGH, IAD_ATM_PRI_MED_LOW, IAD_ATM_PRI_LOW
non-TS Q: 8 priorities: IAD_ATM_PRI_LEVEL_7, IAD_ATM_PRI_LEVEL_6,..., IAD_ATM_PRI_LEVEL_0 */
iad_atmServiceCategory qosClass; /* IAD_ATM_CBR, IAD_ATM_VBR_RT, IAD_ATM_VBR_NRT, IAD_ATM_UBR */
iad_atmDiffServCategory diffServClass; /* IP_QOS */
} srvCat; /* service category */
iad_atmCellRateDesc pcr; /* Peak Cell Rate */
iad_atmCellRateDesc scr; /* Sustained Cell Rate. */
iad_atmCellRateDesc mcr; /* Minimum Cell Rate, not used */
int mbs; /* maximum bursting size in cells */
int isPrioritize; /* TRUE: This flow is of the higher priority than the flows of the same QOS category.(Use MCR to boost priority) */
} iad_atmTrfPar; /* Tx Traffic Parameters */
typedef struct
{
unsigned int txGrpId;
unsigned int flowId;
iad_atmTrfPar trfPar;
} Atm_Ictl_Flow_Set;
typedef struct
{
unsigned int txGrpId;
unsigned int vpi;
unsigned int vci;
unsigned int encaps;
unsigned int proto;
} Atm_Ictl_Open_Vcc;
typedef struct
{
struct atm_vcc vcc;
unsigned int valid;
unsigned int on;
unsigned int vccIndex; /* 0~7 */
unsigned int itf;
struct net_device_stats stats;
} Atm_Priv;
extern struct ppe_dev ppe_dev;
int pp32_start(void);
void pp32_stop(void);
void init_rx_tables(void);
void init_tx_tables(void);
struct sk_buff* alloc_skb_rx(void);
struct sk_buff* alloc_skb_tx(unsigned int);
void resize_skb_rx(struct sk_buff *, unsigned int, int);
struct sk_buff* atm_alloc_tx(struct atm_vcc *, unsigned int);
void atm_free_tx_skb_vcc(struct sk_buff *);
int alloc_tx_connection(int);
int ppe_open(struct atm_vcc *vcc);
void ppe_close(struct atm_vcc *vcc);
int ppe_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb);
int ppe_send_oam(struct atm_vcc *vcc, void *cell, int flags);
int ppe_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags);
irqreturn_t mailbox_irq_handler(int, void *);
int find_vcc(struct atm_vcc *vcc);
int find_vpi(unsigned int vpi);
int find_vpivci(unsigned int vpi, unsigned int vci);
void mailbox_signal(unsigned int channel, int is_tx);

View file

@ -1,800 +0,0 @@
#include <asm/mach-ifxmips/cgu.h>
#include <linux/module.h>
#include <linux/atmdev.h>
#include <linux/irq.h>
#include "common.h"
#include "proc.h"
// our main struct
struct ppe_dev ppe_dev;
static int port_max_connection[2] = {7, 7}; /* Maximum number of connections for ports (0-14) */
static int port_cell_rate_up[2] = {3200, 3200}; /* Maximum TX cell rate for ports */
static int qsb_tau = 1;
static int qsb_srvm = 0x0f;
static int qsb_tstep = 4;
static int write_descriptor_delay = 0x20;
static int aal5_fill_pattern = 0x007E;
static int aal5r_max_packet_size = 0x0700;
static int aal5r_min_packet_size = 0x0000;
static int aal5s_max_packet_size = 0x0700;
static int aal5s_min_packet_size = 0x0000;
static int aal5r_drop_error_packet = 1;
static int dma_rx_descriptor_length = 48;
static int dma_tx_descriptor_length = 64;
static int dma_rx_clp1_descriptor_threshold = 38;
//module_param(port_max_connection, "2-2i");
//module_param(port_cell_rate_up, "2-2i");
module_param(qsb_tau, int, 0);
module_param(qsb_srvm, int, 0);
module_param(qsb_tstep, int, 0);
module_param(write_descriptor_delay, int, 0);
module_param(aal5_fill_pattern, int, 0);
module_param(aal5r_max_packet_size, int, 0);
module_param(aal5r_min_packet_size, int, 0);
module_param(aal5s_max_packet_size, int, 0);
module_param(aal5s_min_packet_size, int, 0);
module_param(aal5r_drop_error_packet, int, 0);
module_param(dma_rx_descriptor_length, int, 0);
module_param(dma_tx_descriptor_length, int, 0);
module_param(dma_rx_clp1_descriptor_threshold, int, 0);
MODULE_PARM_DESC(port_cell_rate_up, "ATM port upstream rate in cells/s");
MODULE_PARM_DESC(port_max_connection, "Maximum atm connection for port (0-1)");
MODULE_PARM_DESC(qsb_tau, "Cell delay variation. Value must be > 0");
MODULE_PARM_DESC(qsb_srvm, "Maximum burst size");
MODULE_PARM_DESC(qsb_tstep, "n*32 cycles per sbs cycles n=1,2,4");
MODULE_PARM_DESC(write_descriptor_delay, "PPE core clock cycles between descriptor write and effectiveness in external RAM");
MODULE_PARM_DESC(a5_fill_pattern, "Filling pattern (PAD) for AAL5 frames");
MODULE_PARM_DESC(aal5r_max_packet_size, "Max packet size in byte for downstream AAL5 frames");
MODULE_PARM_DESC(aal5r_min_packet_size, "Min packet size in byte for downstream AAL5 frames");
MODULE_PARM_DESC(aal5s_max_packet_size, "Max packet size in byte for upstream AAL5 frames");
MODULE_PARM_DESC(aal5s_min_packet_size, "Min packet size in byte for upstream AAL5 frames");
MODULE_PARM_DESC(aal5r_drop_error_packet, "Non-zero value to drop error packet for downstream");
MODULE_PARM_DESC(dma_rx_descriptor_length, "Number of descriptor assigned to DMA RX channel (>16)");
MODULE_PARM_DESC(dma_tx_descriptor_length, "Number of descriptor assigned to DMA TX channel (>16)");
MODULE_PARM_DESC(dma_rx_clp1_descriptor_threshold, "Descriptor threshold for cells with cell loss priority 1");
void init_rx_tables(void)
{
int i, j;
struct wrx_queue_config wrx_queue_config = {0};
struct wrx_dma_channel_config wrx_dma_channel_config = {0};
struct htu_entry htu_entry = {0};
struct htu_result htu_result = {0};
struct htu_mask htu_mask = { set: 0x03,
pid_mask: 0x00,
vpi_mask: 0x00,
vci_mask: 0x00,
pti_mask: 0x00,
clear: 0x00};
/*
* General Registers
*/
*CFG_WRX_HTUTS = ppe_dev.max_connections + OAM_HTU_ENTRY_NUMBER;
*CFG_WRX_QNUM = ppe_dev.max_connections + OAM_RX_QUEUE_NUMBER + QSB_QUEUE_NUMBER_BASE;
*CFG_WRX_DCHNUM = ppe_dev.dma.rx_total_channel_used;
*WRX_DMACH_ON = (1 << ppe_dev.dma.rx_total_channel_used) - 1;
*WRX_HUNT_BITTH = DEFAULT_RX_HUNT_BITTH;
/*
* WRX Queue Configuration Table
*/
wrx_queue_config.uumask = 0;
wrx_queue_config.cpimask = 0;
wrx_queue_config.uuexp = 0;
wrx_queue_config.cpiexp = 0;
wrx_queue_config.mfs = ppe_dev.aal5.rx_max_packet_size; // rx_buffer_size
wrx_queue_config.oversize = ppe_dev.aal5.rx_max_packet_size;
wrx_queue_config.undersize = ppe_dev.aal5.rx_min_packet_size;
wrx_queue_config.errdp = ppe_dev.aal5.rx_drop_error_packet;
for ( i = 0; i < QSB_QUEUE_NUMBER_BASE; i++ )
*WRX_QUEUE_CONFIG(i) = wrx_queue_config;
for ( j = 0; j < ppe_dev.max_connections; j++ )
{
#if !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS
/* If RX QoS is disabled, the DMA channel must be fixed. */
wrx_queue_config.dmach = ppe_dev.connection[i].rx_dma_channel;
#endif // !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS
*WRX_QUEUE_CONFIG(i++) = wrx_queue_config;
}
/* OAM RX Queue */
for ( j = 0; j < OAM_RX_DMA_CHANNEL_NUMBER; j++ )
{
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
wrx_queue_config.dmach = RX_DMA_CH_OAM;
#else
wrx_queue_config.dmach = ppe_dev.oam_rx_dma_channel + j;
#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
*WRX_QUEUE_CONFIG(i++) = wrx_queue_config;
}
wrx_dma_channel_config.deslen = ppe_dev.dma.rx_descriptor_number;
wrx_dma_channel_config.chrl = 0;
wrx_dma_channel_config.clp1th = ppe_dev.dma.rx_clp1_desc_threshold;
wrx_dma_channel_config.mode = WRX_DMA_CHANNEL_COUNTER_MODE;
wrx_dma_channel_config.rlcfg = WRX_DMA_BUF_LEN_PER_DESCRIPTOR;
for ( i = 0; i < ppe_dev.dma.rx_total_channel_used; i++ )
{
wrx_dma_channel_config.desba = (((u32)ppe_dev.dma.rx_descriptor_base >> 2) & 0x0FFFFFFF) + ppe_dev.dma.rx_descriptor_number * i * (sizeof(struct rx_descriptor) >> 2);
*WRX_DMA_CHANNEL_CONFIG(i) = wrx_dma_channel_config;
}
/*
* HTU Tables
*/
for ( i = 0; i < ppe_dev.max_connections; i++ )
{
htu_result.qid = (unsigned int)i;
*HTU_ENTRY(i + OAM_HTU_ENTRY_NUMBER) = htu_entry;
*HTU_MASK(i + OAM_HTU_ENTRY_NUMBER) = htu_mask;
*HTU_RESULT(i + OAM_HTU_ENTRY_NUMBER) = htu_result;
}
/* OAM HTU Entry */
htu_entry.vci = 0x03;
htu_mask.pid_mask = 0x03;
htu_mask.vpi_mask = 0xFF;
htu_mask.vci_mask = 0x0000;
htu_mask.pti_mask = 0x07;
htu_result.cellid = ppe_dev.oam_rx_queue;
htu_result.type = 1;
htu_result.ven = 1;
htu_result.qid = ppe_dev.oam_rx_queue;
*HTU_RESULT(OAM_F4_SEG_HTU_ENTRY) = htu_result;
*HTU_MASK(OAM_F4_SEG_HTU_ENTRY) = htu_mask;
*HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY) = htu_entry;
htu_entry.vci = 0x04;
htu_result.cellid = ppe_dev.oam_rx_queue;
htu_result.type = 1;
htu_result.ven = 1;
htu_result.qid = ppe_dev.oam_rx_queue;
*HTU_RESULT(OAM_F4_TOT_HTU_ENTRY) = htu_result;
*HTU_MASK(OAM_F4_TOT_HTU_ENTRY) = htu_mask;
*HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY) = htu_entry;
htu_entry.vci = 0x00;
htu_entry.pti = 0x04;
htu_mask.vci_mask = 0xFFFF;
htu_mask.pti_mask = 0x01;
htu_result.cellid = ppe_dev.oam_rx_queue;
htu_result.type = 1;
htu_result.ven = 1;
htu_result.qid = ppe_dev.oam_rx_queue;
*HTU_RESULT(OAM_F5_HTU_ENTRY) = htu_result;
*HTU_MASK(OAM_F5_HTU_ENTRY) = htu_mask;
*HTU_ENTRY(OAM_F5_HTU_ENTRY) = htu_entry;
}
void init_tx_tables(void)
{
int i, j;
struct wtx_queue_config wtx_queue_config = {0};
struct wtx_dma_channel_config wtx_dma_channel_config = {0};
struct wtx_port_config wtx_port_config = { res1: 0,
qid: 0,
qsben: 1};
/*
* General Registers
*/
*CFG_WTX_DCHNUM = ppe_dev.dma.tx_total_channel_used + QSB_QUEUE_NUMBER_BASE;
*WTX_DMACH_ON = ((1 << (ppe_dev.dma.tx_total_channel_used + QSB_QUEUE_NUMBER_BASE)) - 1) ^ ((1 << QSB_QUEUE_NUMBER_BASE) - 1);
*CFG_WRDES_DELAY = ppe_dev.dma.write_descriptor_delay;
/*
* WTX Port Configuration Table
*/
#if !defined(DISABLE_QSB) || !DISABLE_QSB
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
*WTX_PORT_CONFIG(i) = wtx_port_config;
#else
wtx_port_config.qsben = 0;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
{
wtx_port_config.qid = ppe_dev.port[i].connection_base;
*WTX_PORT_CONFIG(i) = wtx_port_config;
printk("port %d: qid = %d, qsb disabled\n", i, wtx_port_config.qid);
}
#endif
/*
* WTX Queue Configuration Table
*/
wtx_queue_config.res1 = 0;
wtx_queue_config.res2 = 0;
// wtx_queue_config.type = 0x03;
wtx_queue_config.type = 0x0;
#if !defined(DISABLE_QSB) || !DISABLE_QSB
wtx_queue_config.qsben = 1;
#else
wtx_queue_config.qsben = 0;
#endif
wtx_queue_config.sbid = 0;
for ( i = 0; i < QSB_QUEUE_NUMBER_BASE; i++ )
*WTX_QUEUE_CONFIG(i) = wtx_queue_config;
for ( j = 0; j < ppe_dev.max_connections; j++ )
{
wtx_queue_config.sbid = ppe_dev.connection[i].port & 0x01; /* assign QSB to TX queue */
*WTX_QUEUE_CONFIG(i) = wtx_queue_config;
i++;
}
/* OAM TX Queue */
// wtx_queue_config.type = 0x01;
wtx_queue_config.type = 0x00;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
{
wtx_queue_config.sbid = i & 0x01;
for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ )
*WTX_QUEUE_CONFIG(ppe_dev.port[i].oam_tx_queue + j) = wtx_queue_config;
}
wtx_dma_channel_config.mode = WRX_DMA_CHANNEL_COUNTER_MODE;
wtx_dma_channel_config.deslen = 0;
wtx_dma_channel_config.desba = 0;
for ( i = 0; i < QSB_QUEUE_NUMBER_BASE; i++ )
*WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config;
/* normal connection and OAM channel */
wtx_dma_channel_config.deslen = ppe_dev.dma.tx_descriptor_number;
for ( j = 0; j < ppe_dev.dma.tx_total_channel_used; j++ )
{
wtx_dma_channel_config.desba = (((u32)ppe_dev.dma.tx_descriptor_base >> 2) & 0x0FFFFFFF) + ppe_dev.dma.tx_descriptor_number * j * (sizeof(struct tx_descriptor) >> 2);
*WTX_DMA_CHANNEL_CONFIG(i++) = wtx_dma_channel_config;
}
}
static inline void qsb_global_set(void)
{
int i, j;
u32 qsb_clk = cgu_get_fpi_bus_clock(2);
u32 tmp1, tmp2, tmp3;
union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}};
union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}};
int qsb_qid;
*QSB_ICDV = QSB_ICDV_TAU_SET(ppe_dev.qsb.tau);
*QSB_SBL = QSB_SBL_SBL_SET(ppe_dev.qsb.sbl);
*QSB_CFG = QSB_CFG_TSTEPC_SET(ppe_dev.qsb.tstepc >> 1);
/*
* set SCT and SPT per port
*/
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( ppe_dev.port[i].max_connections != 0 && ppe_dev.port[i].tx_max_cell_rate != 0 )
{
tmp1 = ((qsb_clk * ppe_dev.qsb.tstepc) >> 1) / ppe_dev.port[i].tx_max_cell_rate;
tmp2 = tmp1 >> 6; /* integer value of Tsb */
tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /* fractional part of Tsb */
/* carry over to integer part (?) */
if ( tmp3 == (1 << 6) )
{
tmp3 = 0;
tmp2++;
}
if ( tmp2 == 0 )
tmp2 = tmp3 = 1;
/* 1. set mask */
/* 2. write value to data transfer register */
/* 3. start the tranfer */
/* SCT (FracRate) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SCT_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(tmp3);
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SCT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01);
/* SPT (SBV + PN + IntRage) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SPT_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2));
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01);
}
/*
* set OAM TX queue
*/
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( ppe_dev.port[i].max_connections != 0 )
{
tmp1 = ((qsb_clk * ppe_dev.qsb.tstepc) >> 1) / ppe_dev.port[i].tx_max_cell_rate;
tmp2 = tmp1 >> 6; /* integer value of Tsb */
tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /* fractional part of Tsb */
/* carry over to integer part (?) */
if ( tmp3 == (1 << 6) )
{
tmp3 = 0;
tmp2++;
}
if ( tmp2 == 0 )
tmp2 = tmp3 = 1;
/* 1. set mask */
/* 2. write value to data transfer register */
/* 3. start the tranfer */
/* SCT (FracRate) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SCT_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(tmp3);
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SCT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01);
/* SPT (SBV + PN + IntRage) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SPT_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2));
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01);
}
/*
* * set OAM TX queue
* */
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( ppe_dev.port[i].max_connections != 0 )
for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ )
{
qsb_qid = ppe_dev.port[i].oam_tx_queue + j;
/* disable PCR limiter */
qsb_queue_parameter_table.bit.tp = 0;
/* set WFQ as real time queue */
qsb_queue_parameter_table.bit.wfqf = 0;
/* disable leaky bucket shaper */
qsb_queue_vbr_parameter_table.bit.taus = 0;
qsb_queue_vbr_parameter_table.bit.ts = 0;
/* Queue Parameter Table (QPT) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_QPT_SET_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_parameter_table.dword);
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_QPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid);
/* Queue VBR Paramter Table (QVPT) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_QVPT_SET_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_vbr_parameter_table.dword);
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_VBR) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid);
}
}
static inline void clear_ppe_dev(void)
{
int i;
for (i = 0; i < ppe_dev.dma.tx_total_channel_used; i++ )
{
int conn = i + QSB_QUEUE_NUMBER_BASE;
int desc_base;
struct sk_buff *skb;
while(ppe_dev.dma.tx_desc_release_pos[conn] != ppe_dev.dma.tx_desc_alloc_pos[conn])
{
desc_base = ppe_dev.dma.tx_descriptor_number * (conn - QSB_QUEUE_NUMBER_BASE) + ppe_dev.dma.tx_desc_release_pos[conn];
if(!ppe_dev.dma.tx_descriptor_base[desc_base].own)
{
skb = ppe_dev.dma.tx_skb_pointers[desc_base];
atm_free_tx_skb_vcc(skb);
// pretend PP32 hold owner bit, so that won't be released more than once, so allocation process don't check this bit
ppe_dev.dma.tx_descriptor_base[desc_base].own = 1;
}
if (++ppe_dev.dma.tx_desc_release_pos[conn] == ppe_dev.dma.tx_descriptor_number)
ppe_dev.dma.tx_desc_release_pos[conn] = 0;
}
}
for (i = ppe_dev.dma.rx_total_channel_used * ppe_dev.dma.rx_descriptor_number - 1; i >= 0; i--)
dev_kfree_skb_any(*(struct sk_buff **)(((ppe_dev.dma.rx_descriptor_base[i].dataptr << 2) | KSEG0) - 4));
kfree(ppe_dev.dma.tx_skb_pointers);
kfree(ppe_dev.dma.tx_descriptor_addr);
kfree(ppe_dev.dma.rx_descriptor_addr);
}
static inline int init_ppe_dev(void)
{
int i, j;
int rx_desc, tx_desc;
int conn;
int oam_tx_queue;
#if !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS
int rx_dma_channel_base;
int rx_dma_channel_assigned;
#endif // !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS
struct rx_descriptor rx_descriptor = { own: 1,
c: 0,
sop: 1,
eop: 1,
res1: 0,
byteoff:0,
res2: 0,
id: 0,
err: 0,
datalen:0,
res3: 0,
dataptr:0};
struct tx_descriptor tx_descriptor = { own: 1, // pretend it's hold by PP32
c: 0,
sop: 1,
eop: 1,
byteoff:0,
res1: 0,
iscell: 0,
clp: 0,
datalen:0,
res2: 0,
dataptr:0};
memset(&ppe_dev, 0, sizeof(ppe_dev));
/*
* Setup AAL5 members, buffer size must be larger than max packet size plus overhead.
*/
ppe_dev.aal5.padding_byte = (u8)aal5_fill_pattern;
ppe_dev.aal5.rx_max_packet_size = (u32)aal5r_max_packet_size;
ppe_dev.aal5.rx_min_packet_size = (u32)aal5r_min_packet_size;
ppe_dev.aal5.rx_buffer_size = ((u32)(aal5r_max_packet_size > CELL_SIZE ? aal5r_max_packet_size + MAX_RX_FRAME_EXTRA_BYTES : CELL_SIZE + MAX_RX_FRAME_EXTRA_BYTES) + DMA_ALIGNMENT - 1) & ~(DMA_ALIGNMENT - 1);
ppe_dev.aal5.tx_max_packet_size = (u32)aal5s_max_packet_size;
ppe_dev.aal5.tx_min_packet_size = (u32)aal5s_min_packet_size;
ppe_dev.aal5.tx_buffer_size = ((u32)(aal5s_max_packet_size > CELL_SIZE ? aal5s_max_packet_size + MAX_TX_FRAME_EXTRA_BYTES : CELL_SIZE + MAX_TX_FRAME_EXTRA_BYTES) + DMA_ALIGNMENT - 1) & ~(DMA_ALIGNMENT - 1);
ppe_dev.aal5.rx_drop_error_packet = aal5r_drop_error_packet ? 1 : 0;
/*
* Setup QSB members, please refer to Amazon spec 15.4 to get the value calculation formula.
*/
ppe_dev.qsb.tau = (u32)qsb_tau;
ppe_dev.qsb.tstepc = (u32)qsb_tstep;
ppe_dev.qsb.sbl = (u32)qsb_srvm;
/*
* Setup port, connection, other members.
*/
conn = 0;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
{
/* first connection ID of port */
ppe_dev.port[i].connection_base = conn + QSB_QUEUE_NUMBER_BASE;
/* max number of connections of port */
ppe_dev.port[i].max_connections = (u32)port_max_connection[i];
/* max cell rate the port has */
ppe_dev.port[i].tx_max_cell_rate = (u32)port_cell_rate_up[i];
/* link connection ID to port ID */
for ( j = port_max_connection[i] - 1; j >= 0; j-- )
ppe_dev.connection[conn++ + QSB_QUEUE_NUMBER_BASE].port = i;
}
/* total connection numbers of all ports */
ppe_dev.max_connections = conn;
/* OAM RX queue ID, which is the first available connection ID after */
/* connections assigned to ports. */
ppe_dev.oam_rx_queue = conn + QSB_QUEUE_NUMBER_BASE;
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
oam_tx_queue = conn;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( port_max_connection[i] != 0 )
{
ppe_dev.port[i].oam_tx_queue = oam_tx_queue + QSB_QUEUE_NUMBER_BASE;
for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ )
/* Since connection ID is one to one mapped to RX/TX queue ID, the connection */
/* structure must be reserved for OAM RX/TX queues, and member "port" is set */
/* according to port to which OAM TX queue is connected. */
ppe_dev.connection[oam_tx_queue++ + QSB_QUEUE_NUMBER_BASE].port = i;
}
/* DMA RX channel assigned to OAM RX queue */
ppe_dev.oam_rx_dma_channel = RX_DMA_CH_OAM;
/* DMA RX channel will be assigned dynamically when VCC is open. */
#else // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
rx_dma_channel_base = 0;
oam_tx_queue = conn;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( port_max_connection[i] != 0 )
{
/* Calculate the number of DMA RX channels could be assigned to port. */
rx_dma_channel_assigned = i == ATM_PORT_NUMBER - 1
? (MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER) - rx_dma_channel_base
: (ppe_dev.port[i].max_connections * (MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER) + ppe_dev.max_connections / 2) / ppe_dev.max_connections;
/* Amend the number, which could be zero. */
if ( rx_dma_channel_assigned == 0 )
rx_dma_channel_assigned = 1;
/* Calculate the first DMA RX channel ID could be assigned to port. */
if ( rx_dma_channel_base + rx_dma_channel_assigned > MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER )
rx_dma_channel_base = MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER - rx_dma_channel_assigned;
/* first DMA RX channel ID */
ppe_dev.port[i].rx_dma_channel_base = rx_dma_channel_base;
/* number of DMA RX channels assigned to this port */
ppe_dev.port[i].rx_dma_channel_assigned = rx_dma_channel_assigned;
/* OAM TX queue ID, which must be assigned after connections assigned to ports */
ppe_dev.port[i].oam_tx_queue = oam_tx_queue + QSB_QUEUE_NUMBER_BASE;
rx_dma_channel_base += rx_dma_channel_assigned;
for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ )
/* Since connection ID is one to one mapped to RX/TX queue ID, the connection */
/* structure must be reserved for OAM RX/TX queues, and member "port" is set */
/* according to port to which OAM TX queue is connected. */
ppe_dev.connection[oam_tx_queue++ + QSB_QUEUE_NUMBER_BASE].port = i;
}
/* DMA RX channel assigned to OAM RX queue */
ppe_dev.oam_rx_dma_channel = rx_dma_channel_base;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
for ( j = 0; j < port_max_connection[i]; j++ )
/* Assign DMA RX channel to RX queues. One channel could be assigned to more than one queue. */
ppe_dev.connection[ppe_dev.port[i].connection_base + j].rx_dma_channel = ppe_dev.port[i].rx_dma_channel_base + j % ppe_dev.port[i].rx_dma_channel_assigned;
#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
/* initialize semaphore used by open and close */
sema_init(&ppe_dev.sem, 1);
/* descriptor number of RX DMA channel */
ppe_dev.dma.rx_descriptor_number = dma_rx_descriptor_length;
/* descriptor number of TX DMA channel */
ppe_dev.dma.tx_descriptor_number = dma_tx_descriptor_length;
/* If used descriptors are more than this value, cell with CLP1 is dropped. */
ppe_dev.dma.rx_clp1_desc_threshold = dma_rx_clp1_descriptor_threshold;
/* delay on descriptor write path */
ppe_dev.dma.write_descriptor_delay = write_descriptor_delay;
/* total DMA RX channel used */
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
ppe_dev.dma.rx_total_channel_used = RX_DMA_CH_TOTAL;
#else
ppe_dev.dma.rx_total_channel_used = rx_dma_channel_base + OAM_RX_DMA_CHANNEL_NUMBER;
#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
/* total DMA TX channel used (exclude channel reserved by QSB) */
ppe_dev.dma.tx_total_channel_used = oam_tx_queue;
/* allocate memory for RX descriptors */
ppe_dev.dma.rx_descriptor_addr = kmalloc(ppe_dev.dma.rx_total_channel_used * ppe_dev.dma.rx_descriptor_number * sizeof(struct rx_descriptor) + 4, GFP_KERNEL | GFP_DMA);
if ( !ppe_dev.dma.rx_descriptor_addr )
goto RX_DESCRIPTOR_BASE_ALLOCATE_FAIL;
/* do alignment (DWORD) */
ppe_dev.dma.rx_descriptor_base = (struct rx_descriptor *)(((u32)ppe_dev.dma.rx_descriptor_addr + 0x03) & ~0x03);
ppe_dev.dma.rx_descriptor_base = (struct rx_descriptor *)((u32)ppe_dev.dma.rx_descriptor_base | KSEG1); // no cache
/* allocate memory for TX descriptors */
ppe_dev.dma.tx_descriptor_addr = kmalloc(ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number * sizeof(struct tx_descriptor) + 4, GFP_KERNEL | GFP_DMA);
if ( !ppe_dev.dma.tx_descriptor_addr )
goto TX_DESCRIPTOR_BASE_ALLOCATE_FAIL;
/* do alignment (DWORD) */
ppe_dev.dma.tx_descriptor_base = (struct tx_descriptor *)(((u32)ppe_dev.dma.tx_descriptor_addr + 0x03) & ~0x03);
ppe_dev.dma.tx_descriptor_base = (struct tx_descriptor *)((u32)ppe_dev.dma.tx_descriptor_base | KSEG1); // no cache
/* allocate pointers to TX sk_buff */
ppe_dev.dma.tx_skb_pointers = kmalloc(ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number * sizeof(struct sk_buff *), GFP_KERNEL);
if ( !ppe_dev.dma.tx_skb_pointers )
goto TX_SKB_POINTER_ALLOCATE_FAIL;
memset(ppe_dev.dma.tx_skb_pointers, 0, ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number * sizeof(struct sk_buff *));
/* Allocate RX sk_buff and fill up RX descriptors. */
rx_descriptor.datalen = ppe_dev.aal5.rx_buffer_size;
for ( rx_desc = ppe_dev.dma.rx_total_channel_used * ppe_dev.dma.rx_descriptor_number - 1; rx_desc >= 0; rx_desc-- )
{
struct sk_buff *skb;
skb = alloc_skb_rx();
if ( skb == NULL )
panic("sk buffer is used up\n");
rx_descriptor.dataptr = (u32)skb->data >> 2;
ppe_dev.dma.rx_descriptor_base[rx_desc] = rx_descriptor;
}
/* Fill up TX descriptors. */
tx_descriptor.datalen = ppe_dev.aal5.tx_buffer_size;
for ( tx_desc = ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number - 1; tx_desc >= 0; tx_desc-- )
ppe_dev.dma.tx_descriptor_base[tx_desc] = tx_descriptor;
return 0;
TX_SKB_POINTER_ALLOCATE_FAIL:
kfree(ppe_dev.dma.tx_descriptor_addr);
TX_DESCRIPTOR_BASE_ALLOCATE_FAIL:
kfree(ppe_dev.dma.rx_descriptor_addr);
RX_DESCRIPTOR_BASE_ALLOCATE_FAIL:
return -ENOMEM;
}
static inline void clear_share_buffer(void)
{
volatile u32 *p = SB_RAM0_ADDR(0);
unsigned int i;
/* write all zeros only */
for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ )
*p++ = 0;
}
static inline void check_parameters(void)
{
int i;
int enabled_port_number;
int unassigned_queue_number;
int assigned_queue_number;
enabled_port_number = 0;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( port_max_connection[i] < 1 )
port_max_connection[i] = 0;
else
enabled_port_number++;
/* If the max connection number of a port is not 0, the port is enabled */
/* and at lease two connection ID must be reserved for this port. One of */
/* them is used as OAM TX path. */
unassigned_queue_number = MAX_QUEUE_NUMBER - QSB_QUEUE_NUMBER_BASE;
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( port_max_connection[i] > 0 )
{
enabled_port_number--;
assigned_queue_number = unassigned_queue_number - enabled_port_number * (1 + OAM_TX_QUEUE_NUMBER_PER_PORT) - OAM_TX_QUEUE_NUMBER_PER_PORT;
if ( assigned_queue_number > MAX_QUEUE_NUMBER_PER_PORT - OAM_TX_QUEUE_NUMBER_PER_PORT )
assigned_queue_number = MAX_QUEUE_NUMBER_PER_PORT - OAM_TX_QUEUE_NUMBER_PER_PORT;
if ( port_max_connection[i] > assigned_queue_number )
{
port_max_connection[i] = assigned_queue_number;
unassigned_queue_number -= assigned_queue_number;
}
else
unassigned_queue_number -= port_max_connection[i];
}
/* Please refer to Amazon spec 15.4 for setting these values. */
if ( qsb_tau < 1 )
qsb_tau = 1;
if ( qsb_tstep < 1 )
qsb_tstep = 1;
else if ( qsb_tstep > 4 )
qsb_tstep = 4;
else if ( qsb_tstep == 3 )
qsb_tstep = 2;
/* There is a delay between PPE write descriptor and descriptor is */
/* really stored in memory. Host also has this delay when writing */
/* descriptor. So PPE will use this value to determine if the write */
/* operation makes effect. */
if ( write_descriptor_delay < 0 )
write_descriptor_delay = 0;
if ( aal5_fill_pattern < 0 )
aal5_fill_pattern = 0;
else
aal5_fill_pattern &= 0xFF;
/* Because of the limitation of length field in descriptors, the packet */
/* size could not be larger than 64K minus overhead size. */
if ( aal5r_max_packet_size < 0 )
aal5r_max_packet_size = 0;
else if ( aal5r_max_packet_size >= 65536 - MAX_RX_FRAME_EXTRA_BYTES )
aal5r_max_packet_size = 65536 - MAX_RX_FRAME_EXTRA_BYTES;
if ( aal5r_min_packet_size < 0 )
aal5r_min_packet_size = 0;
else if ( aal5r_min_packet_size > aal5r_max_packet_size )
aal5r_min_packet_size = aal5r_max_packet_size;
if ( aal5s_max_packet_size < 0 )
aal5s_max_packet_size = 0;
else if ( aal5s_max_packet_size >= 65536 - MAX_TX_FRAME_EXTRA_BYTES )
aal5s_max_packet_size = 65536 - MAX_TX_FRAME_EXTRA_BYTES;
if ( aal5s_min_packet_size < 0 )
aal5s_min_packet_size = 0;
else if ( aal5s_min_packet_size > aal5s_max_packet_size )
aal5s_min_packet_size = aal5s_max_packet_size;
if ( dma_rx_descriptor_length < 2 )
dma_rx_descriptor_length = 2;
if ( dma_tx_descriptor_length < 2 )
dma_tx_descriptor_length = 2;
if ( dma_rx_clp1_descriptor_threshold < 0 )
dma_rx_clp1_descriptor_threshold = 0;
else if ( dma_rx_clp1_descriptor_threshold > dma_rx_descriptor_length )
dma_rx_clp1_descriptor_threshold = dma_rx_descriptor_length;
}
static struct atmdev_ops ppe_atm_ops = {
owner: THIS_MODULE,
open: ppe_open,
close: ppe_close,
ioctl: ppe_ioctl,
send: ppe_send,
send_oam: ppe_send_oam,
change_qos: ppe_change_qos,
};
int __init danube_ppe_init(void)
{
int ret;
int port_num;
check_parameters();
ret = init_ppe_dev();
if ( ret )
goto INIT_PPE_DEV_FAIL;
clear_share_buffer();
init_rx_tables();
init_tx_tables();
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ )
if ( ppe_dev.port[port_num].max_connections != 0 )
{
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
ppe_dev.port[port_num].dev = atm_dev_register("danube_atm", &ppe_atm_ops, -1, 0UL);
if ( !ppe_dev.port[port_num].dev )
{
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
ret = -EIO;
goto ATM_DEV_REGISTER_FAIL;
}
else
{
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
ppe_dev.port[port_num].dev->ci_range.vpi_bits = 8;
ppe_dev.port[port_num].dev->ci_range.vci_bits = 16;
ppe_dev.port[port_num].dev->link_rate = ppe_dev.port[port_num].tx_max_cell_rate;
ppe_dev.port[port_num].dev->dev_data = (void*)port_num;
}
}
/* register interrupt handler */
ret = request_irq(IFXMIPS_PPE_MBOX_INT, mailbox_irq_handler, IRQF_DISABLED, "ppe_mailbox_isr", NULL);
if ( ret )
{
if ( ret == -EBUSY )
printk("ppe: IRQ may be occupied by ETH2 driver, please reconfig to disable it.\n");
goto REQUEST_IRQ_IFXMIPS_PPE_MBOX_INT_FAIL;
}
disable_irq(IFXMIPS_PPE_MBOX_INT);
#if defined(CONFIG_PCI) && defined(USE_FIX_FOR_PCI_PPE) && USE_FIX_FOR_PCI_PPE
ret = request_irq(PPE_MAILBOX_IGU0_INT, pci_fix_irq_handler, SA_INTERRUPT, "ppe_pci_fix_isr", NULL);
if ( ret )
printk("failed in registering mailbox 0 interrupt (pci fix)\n");
#endif // defined(CONFIG_PCI) && defined(USE_FIX_FOR_PCI_PPE) && USE_FIX_FOR_PCI_PPE
ret = pp32_start();
if ( ret )
goto PP32_START_FAIL;
qsb_global_set();
HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 1;
HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 1;
HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 1;
/* create proc file */
proc_file_create();
printk("ppe: ATM init succeeded (firmware version 1.1.0.2.1.13\n");
return 0;
PP32_START_FAIL:
free_irq(IFXMIPS_PPE_MBOX_INT, NULL);
REQUEST_IRQ_IFXMIPS_PPE_MBOX_INT_FAIL:
ATM_DEV_REGISTER_FAIL:
clear_ppe_dev();
INIT_PPE_DEV_FAIL:
printk("ppe: ATM init failed\n");
return ret;
}
void __exit danube_ppe_exit(void)
{
int port_num;
register int l;
proc_file_delete();
HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 0;
HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 0;
HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 0;
/* idle for a while to finish running HTU search */
for (l = 0; l < IDLE_CYCLE_NUMBER; l++ );
pp32_stop();
free_irq(IFXMIPS_PPE_MBOX_INT, NULL);
for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ )
if ( ppe_dev.port[port_num].max_connections != 0 )
atm_dev_deregister(ppe_dev.port[port_num].dev);
clear_ppe_dev();
}
module_init(danube_ppe_init);
module_exit(danube_ppe_exit);
MODULE_LICENSE("GPL");

View file

@ -1,506 +0,0 @@
#include <linux/atmdev.h>
#include <linux/irq.h>
#include "common.h"
void mailbox_signal(unsigned int channel, int is_tx)
{
if(is_tx)
{
while(MBOX_IGU3_ISR_ISR(channel + 16));
*MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(channel + 16);
} else {
while(MBOX_IGU3_ISR_ISR(channel));
*MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(channel);
}
}
static int mailbox_rx_irq_handler(unsigned int channel, unsigned int *len)
{
int conn;
int skb_base;
register struct rx_descriptor reg_desc;
struct rx_descriptor *desc;
struct sk_buff *skb;
struct atm_vcc *vcc;
struct rx_inband_trailer *trailer;
/* get sk_buff pointer and descriptor */
skb_base = ppe_dev.dma.rx_descriptor_number * channel + ppe_dev.dma.rx_desc_read_pos[channel];
desc = &ppe_dev.dma.rx_descriptor_base[skb_base];
reg_desc = *desc;
if ( reg_desc.own || !reg_desc.c )
return -EAGAIN;
if ( ++ppe_dev.dma.rx_desc_read_pos[channel] == ppe_dev.dma.rx_descriptor_number )
ppe_dev.dma.rx_desc_read_pos[channel] = 0;
skb = *(struct sk_buff **)((((u32)reg_desc.dataptr << 2) | KSEG0) - 4);
if ( (u32)skb <= 0x80000000 )
{
int key = 0;
printk("skb problem: skb = %08X, system is panic!\n", (u32)skb);
for ( ; !key; );
}
conn = reg_desc.id;
if ( conn == ppe_dev.oam_rx_queue )
{
/* OAM */
struct uni_cell_header *header = (struct uni_cell_header *)skb->data;
if ( header->pti == ATM_PTI_SEGF5 || header->pti == ATM_PTI_E2EF5 )
conn = find_vpivci(header->vpi, header->vci);
else if ( header->vci == 0x03 || header->vci == 0x04 )
conn = find_vpi(header->vpi);
else
conn = -1;
if ( conn >= 0 && ppe_dev.connection[conn].vcc != NULL )
{
vcc = ppe_dev.connection[conn].vcc;
ppe_dev.connection[conn].access_time = xtime;
if ( vcc->push_oam != NULL )
vcc->push_oam(vcc, skb->data);
}
/* don't need resize */
}
else
{
if ( len )
*len = 0;
if ( ppe_dev.connection[conn].vcc != NULL )
{
vcc = ppe_dev.connection[conn].vcc;
if ( !reg_desc.err )
if ( vcc->qos.aal == ATM_AAL5 )
{
/* AAL5 packet */
resize_skb_rx(skb, reg_desc.datalen + reg_desc.byteoff, 0);
skb_reserve(skb, reg_desc.byteoff);
skb_put(skb, reg_desc.datalen);
if ( (u32)ATM_SKB(skb) <= 0x80000000 )
{
int key = 0;
printk("ATM_SKB(skb) problem: ATM_SKB(skb) = %08X, system is panic!\n", (u32)ATM_SKB(skb));
for ( ; !key; );
}
ATM_SKB(skb)->vcc = vcc;
ppe_dev.connection[conn].access_time = xtime;
if ( atm_charge(vcc, skb->truesize) )
{
struct sk_buff *new_skb;
new_skb = alloc_skb_rx();
if ( new_skb )
{
UPDATE_VCC_STAT(conn, rx_pdu, 1);
ppe_dev.mib.wrx_pdu++;
if ( vcc->stats )
atomic_inc(&vcc->stats->rx);
vcc->push(vcc, skb);
{
struct k_atm_aal_stats stats = *vcc->stats;
int flag = 0;
vcc->push(vcc, skb);
if ( vcc->stats->rx.counter != stats.rx.counter )
{
printk("vcc->stats->rx (diff) = %d", vcc->stats->rx.counter - stats.rx.counter);
flag++;
}
if ( vcc->stats->rx_err.counter != stats.rx_err.counter )
{
printk("vcc->stats->rx_err (diff) = %d", vcc->stats->rx_err.counter - stats.rx_err.counter);
flag++;
}
if ( vcc->stats->rx_drop.counter != stats.rx_drop.counter )
{
printk("vcc->stats->rx_drop (diff) = %d", vcc->stats->rx_drop.counter - stats.rx_drop.counter);
flag++;
}
if ( vcc->stats->tx.counter != stats.tx.counter )
{
printk("vcc->stats->tx (diff) = %d", vcc->stats->tx.counter - stats.tx.counter);
flag++;
}
if ( vcc->stats->tx_err.counter != stats.tx_err.counter )
{
printk("vcc->stats->tx_err (diff) = %d", vcc->stats->tx_err.counter - stats.tx_err.counter);
flag++;
}
if ( !flag )
printk("vcc->stats not changed");
}
reg_desc.dataptr = (u32)new_skb->data >> 2;
if ( len )
*len = reg_desc.datalen;
}
else
{
/* no sk buffer */
UPDATE_VCC_STAT(conn, rx_sw_drop_pdu, 1);
ppe_dev.mib.wrx_drop_pdu++;
if ( vcc->stats )
atomic_inc(&vcc->stats->rx_drop);
resize_skb_rx(skb, ppe_dev.aal5.rx_buffer_size, 0);
}
}
else
{
/* no enough space */
UPDATE_VCC_STAT(conn, rx_sw_drop_pdu, 1);
ppe_dev.mib.wrx_drop_pdu++;
if ( vcc->stats )
atomic_inc(&vcc->stats->rx_drop);
resize_skb_rx(skb, ppe_dev.aal5.rx_buffer_size, 0);
}
}
else
{
/* AAL0 cell */
resize_skb_rx(skb, CELL_SIZE, 1);
skb_put(skb, CELL_SIZE);
ATM_SKB(skb)->vcc = vcc;
ppe_dev.connection[conn].access_time = xtime;
if ( atm_charge(vcc, skb->truesize) )
{
struct sk_buff *new_skb;
new_skb = alloc_skb_rx();
if ( new_skb )
{
if ( vcc->stats )
atomic_inc(&vcc->stats->rx);
vcc->push(vcc, skb);
reg_desc.dataptr = (u32)new_skb->data >> 2;
if ( len )
*len = CELL_SIZE;
}
else
{
if ( vcc->stats )
atomic_inc(&vcc->stats->rx_drop);
resize_skb_rx(skb, ppe_dev.aal5.rx_buffer_size, 0);
}
}
else
{
if ( vcc->stats )
atomic_inc(&vcc->stats->rx_drop);
resize_skb_rx(skb, ppe_dev.aal5.rx_buffer_size, 0);
}
}
else
{
printk("reg_desc.err\n");
/* drop packet/cell */
if ( vcc->qos.aal == ATM_AAL5 )
{
UPDATE_VCC_STAT(conn, rx_err_pdu, 1);
trailer = (struct rx_inband_trailer *)((u32)skb->data + ((reg_desc.byteoff + reg_desc.datalen + DMA_ALIGNMENT - 1) & ~ (DMA_ALIGNMENT - 1)));
if ( trailer->stw_crc )
ppe_dev.connection[conn].aal5_vcc_crc_err++;
if ( trailer->stw_ovz )
ppe_dev.connection[conn].aal5_vcc_oversize_sdu++;
}
if ( vcc->stats )
atomic_inc(&vcc->stats->rx_err);
/* don't need resize */
}
}
else
{
printk("ppe_dev.connection[%d].vcc == NULL\n", conn);
ppe_dev.mib.wrx_drop_pdu++;
/* don't need resize */
}
}
reg_desc.byteoff = 0;
reg_desc.datalen = ppe_dev.aal5.rx_buffer_size;
reg_desc.own = 1;
reg_desc.c = 0;
/* write discriptor to memory */
*desc = reg_desc;
printk("leave mailbox_rx_irq_handler");
return 0;
}
static inline void mailbox_tx_irq_handler(unsigned int conn)
{
if ( ppe_dev.dma.tx_desc_alloc_flag[conn] )
{
int desc_base;
int *release_pos;
struct sk_buff *skb;
release_pos = &ppe_dev.dma.tx_desc_release_pos[conn];
desc_base = ppe_dev.dma.tx_descriptor_number * (conn - QSB_QUEUE_NUMBER_BASE) + *release_pos;
while ( !ppe_dev.dma.tx_descriptor_base[desc_base].own )
{
skb = ppe_dev.dma.tx_skb_pointers[desc_base];
ppe_dev.dma.tx_descriptor_base[desc_base].own = 1; // pretend PP32 hold owner bit, so that won't be released more than once, so allocation process don't check this bit
if ( ++*release_pos == ppe_dev.dma.tx_descriptor_number )
*release_pos = 0;
if ( *release_pos == ppe_dev.dma.tx_desc_alloc_pos[conn] )
{
ppe_dev.dma.tx_desc_alloc_flag[conn] = 0;
atm_free_tx_skb_vcc(skb);
break;
}
if ( *release_pos == 0 )
desc_base = ppe_dev.dma.tx_descriptor_number * (conn - QSB_QUEUE_NUMBER_BASE);
else
desc_base++;
atm_free_tx_skb_vcc(skb);
}
}
}
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
static inline int check_desc_valid(unsigned int channel)
{
int skb_base;
struct rx_descriptor *desc;
skb_base = ppe_dev.dma.rx_descriptor_number * channel + ppe_dev.dma.rx_desc_read_pos[channel];
desc = &ppe_dev.dma.rx_descriptor_base[skb_base];
return !desc->own && desc->c ? 1 : 0;
}
#endif
irqreturn_t mailbox_irq_handler(int irq, void *dev_id)
{
int channel_mask; /* DMA channel accordant IRQ bit mask */
int channel;
unsigned int rx_irq_number[MAX_RX_DMA_CHANNEL_NUMBER] = {0};
unsigned int total_rx_irq_number = 0;
printk("mailbox_irq_handler");
if ( !*MBOX_IGU1_ISR )
return IRQ_RETVAL(1);
channel_mask = 1;
channel = 0;
while ( channel < ppe_dev.dma.rx_total_channel_used )
{
if ( (*MBOX_IGU1_ISR & channel_mask) )
{
/* RX */
/* clear IRQ */
*MBOX_IGU1_ISRC = channel_mask;
printk(" RX: *MBOX_IGU1_ISR = 0x%08X\n", *MBOX_IGU1_ISR);
/* wait for mailbox cleared */
while ( (*MBOX_IGU3_ISR & channel_mask) );
/* shadow the number of valid descriptor */
rx_irq_number[channel] = WRX_DMA_CHANNEL_CONFIG(channel)->vlddes;
total_rx_irq_number += rx_irq_number[channel];
printk("total_rx_irq_number = %d", total_rx_irq_number);
printk("vlddes = %d, rx_irq_number[%d] = %d, total_rx_irq_number = %d\n", WRX_DMA_CHANNEL_CONFIG(channel)->vlddes, channel, rx_irq_number[channel], total_rx_irq_number);
}
channel_mask <<= 1;
channel++;
}
channel_mask = 1 << (16 + QSB_QUEUE_NUMBER_BASE);
channel = QSB_QUEUE_NUMBER_BASE;
while ( channel - QSB_QUEUE_NUMBER_BASE < ppe_dev.dma.tx_total_channel_used )
{
if ( (*MBOX_IGU1_ISR & channel_mask) )
{
// if ( channel != 1 )
// {
printk("TX irq error\n");
// while ( 1 )
// {
// }
// }
/* TX */
/* clear IRQ */
*MBOX_IGU1_ISRC = channel_mask;
printk(" TX: *MBOX_IGU1_ISR = 0x%08X\n", *MBOX_IGU1_ISR);
mailbox_tx_irq_handler(channel);
}
channel_mask <<= 1;
channel++;
}
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
channel = 0;
while ( total_rx_irq_number )
{
switch ( channel )
{
case RX_DMA_CH_CBR:
case RX_DMA_CH_OAM:
/* handle it as soon as possible */
while ( rx_irq_number[channel] != 0 && mailbox_rx_irq_handler(channel, NULL) == 0 )
{
rx_irq_number[channel]--;
total_rx_irq_number--;
printk("RX_DMA_CH_CBR, total_rx_irq_number = %d", total_rx_irq_number);
printk("RX_DMA_CH_CBR, total_rx_irq_number = %d, rx_irq_number[%d] = %d\n", total_rx_irq_number, channel, rx_irq_number[channel]);
/* signal firmware that descriptor is updated */
mailbox_signal(channel, 0);
}
// if ( rx_irq_number[channel] != 0 )
printk("RX_DMA_CH_CBR, rx_irq_number[channel] = %d", rx_irq_number[channel]);
break;
case RX_DMA_CH_VBR_RT:
/* WFQ */
if ( rx_irq_number[RX_DMA_CH_VBR_RT] != 0
&& (rx_irq_number[RX_DMA_CH_VBR_NRT] == 0 || !check_desc_valid(RX_DMA_CH_VBR_NRT) || ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] < ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT])
&& (rx_irq_number[RX_DMA_CH_AVR] == 0 || !check_desc_valid(RX_DMA_CH_AVR) || ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] < ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT])
)
{
unsigned int len;
if ( mailbox_rx_irq_handler(RX_DMA_CH_VBR_RT, &len) == 0 )
{
rx_irq_number[RX_DMA_CH_VBR_RT]--;
total_rx_irq_number--;
printk("RX_DMA_CH_VBR_RT, total_rx_irq_number = %d", total_rx_irq_number);
printk("RX_DMA_CH_VBR_RT, total_rx_irq_number = %d, rx_irq_number[%d] = %d\n", total_rx_irq_number, channel, rx_irq_number[channel]);
/* signal firmware that descriptor is updated */
mailbox_signal(channel, 0);
len = (len + CELL_SIZE - 1) / CELL_SIZE;
if ( ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] <= len )
ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] = ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_RT] + ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] - len;
}
}
// if ( rx_irq_number[channel] != 0 )
// {
printk("RX_DMA_CH_VBR_RT, rx_irq_number[channel] = %d, total_rx_irq_number = %d", rx_irq_number[channel], total_rx_irq_number);
// rx_irq_number[channel] = 0;
// total_rx_irq_number = 0;
// }
break;
case RX_DMA_CH_VBR_NRT:
/* WFQ */
if ( rx_irq_number[RX_DMA_CH_VBR_NRT] != 0
&& (rx_irq_number[RX_DMA_CH_VBR_RT] == 0 || !check_desc_valid(RX_DMA_CH_VBR_RT) || ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] < ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT])
&& (rx_irq_number[RX_DMA_CH_AVR] == 0 || !check_desc_valid(RX_DMA_CH_AVR) || ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] < ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT])
)
{
unsigned int len;
if ( mailbox_rx_irq_handler(RX_DMA_CH_VBR_NRT, &len) == 0 )
{
rx_irq_number[RX_DMA_CH_VBR_NRT]--;
total_rx_irq_number--;
printk("RX_DMA_CH_VBR_NRT, total_rx_irq_number = %d", total_rx_irq_number);
printk("RX_DMA_CH_VBR_NRT, total_rx_irq_number = %d, rx_irq_number[%d] = %d\n", total_rx_irq_number, channel, rx_irq_number[channel]);
/* signal firmware that descriptor is updated */
mailbox_signal(channel, 0);
len = (len + CELL_SIZE - 1) / CELL_SIZE;
if ( ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] <= len )
ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] = ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_NRT] + ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] - len;
}
}
// if ( rx_irq_number[channel] != 0 )
printk("RX_DMA_CH_VBR_NRT, rx_irq_number[channel] = %d", rx_irq_number[channel]);
break;
case RX_DMA_CH_AVR:
/* WFQ */
if ( rx_irq_number[RX_DMA_CH_AVR] != 0
&& (rx_irq_number[RX_DMA_CH_VBR_RT] == 0 || !check_desc_valid(RX_DMA_CH_VBR_RT) || ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] < ppe_dev.dma.rx_weight[RX_DMA_CH_AVR])
&& (rx_irq_number[RX_DMA_CH_VBR_NRT] == 0 || !check_desc_valid(RX_DMA_CH_VBR_NRT) || ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] < ppe_dev.dma.rx_weight[RX_DMA_CH_AVR])
)
{
unsigned int len;
if ( mailbox_rx_irq_handler(RX_DMA_CH_AVR, &len) == 0 )
{
rx_irq_number[RX_DMA_CH_AVR]--;
total_rx_irq_number--;
printk("RX_DMA_CH_AVR, total_rx_irq_number = %d", total_rx_irq_number);
printk("RX_DMA_CH_AVR, total_rx_irq_number = %d, rx_irq_number[%d] = %d\n", total_rx_irq_number, channel, rx_irq_number[channel]);
/* signal firmware that descriptor is updated */
mailbox_signal(channel, 0);
len = (len + CELL_SIZE - 1) / CELL_SIZE;
if ( ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] <= len )
ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] = ppe_dev.dma.rx_default_weight[RX_DMA_CH_AVR] + ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] - len;
}
}
// if ( rx_irq_number[channel] != 0 )
printk("RX_DMA_CH_AVR, rx_irq_number[channel] = %d", rx_irq_number[channel]);
break;
case RX_DMA_CH_UBR:
default:
/* Handle it when all others are handled or others are not available to handle. */
if ( rx_irq_number[channel] != 0
&& (rx_irq_number[RX_DMA_CH_VBR_RT] == 0 || !check_desc_valid(RX_DMA_CH_VBR_RT))
&& (rx_irq_number[RX_DMA_CH_VBR_NRT] == 0 || !check_desc_valid(RX_DMA_CH_VBR_NRT))
&& (rx_irq_number[RX_DMA_CH_AVR] == 0 || !check_desc_valid(RX_DMA_CH_AVR)) )
if ( mailbox_rx_irq_handler(channel, NULL) == 0 )
{
rx_irq_number[channel]--;
total_rx_irq_number--;
printk("RX_DMA_CH_UBR, total_rx_irq_number = %d, rx_irq_number[%d] = %d", total_rx_irq_number, channel, rx_irq_number[channel]);
printk("RX_DMA_CH_UBR, total_rx_irq_number = %d, rx_irq_number[%d] = %d\n", total_rx_irq_number, channel, rx_irq_number[channel]);
/* signal firmware that descriptor is updated */
mailbox_signal(channel, 0);
}
printk("RX_DMA_CH_UBR, rx_irq_number[channel] = %d", rx_irq_number[channel]);
}
if ( ++channel == ppe_dev.dma.rx_total_channel_used )
channel = 0;
}
#else
channel = 0;
while ( total_rx_irq_number )
{
while ( rx_irq_number[channel] != 0 && mailbox_rx_irq_handler(channel, NULL) == 0 )
{
rx_irq_number[channel]--;
total_rx_irq_number--;
/* signal firmware that descriptor is updated */
mailbox_signal(channel, 0);
}
if ( ++channel == ppe_dev.dma.rx_total_channel_used )
channel = 0;
}
#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
return IRQ_RETVAL(1);
}

View file

@ -1,838 +0,0 @@
#include <asm/mach-ifxmips/cgu.h>
#include "common.h"
#include "ifx_ppe_fw.h"
static void set_qsb(struct atm_vcc *vcc, struct atm_qos *qos, unsigned int connection)
{
u32 qsb_clk = cgu_get_fpi_bus_clock(2); /* FPI configuration 2 (slow FPI bus) */
union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}};
union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}};
u32 tmp;
/*
* Peak Cell Rate (PCR) Limiter
*/
if ( qos->txtp.max_pcr == 0 )
qsb_queue_parameter_table.bit.tp = 0; /* disable PCR limiter */
else
{
/* peak cell rate would be slightly lower than requested [maximum_rate / pcr = (qsb_clock / 8) * (time_step / 4) / pcr] */
tmp = ((qsb_clk * ppe_dev.qsb.tstepc) >> 5) / qos->txtp.max_pcr + 1;
/* check if overflow takes place */
qsb_queue_parameter_table.bit.tp = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp;
}
/*
* Weighted Fair Queueing Factor (WFQF)
*/
switch ( qos->txtp.traffic_class )
{
case ATM_CBR:
case ATM_VBR_RT:
/* real time queue gets weighted fair queueing bypass */
qsb_queue_parameter_table.bit.wfqf = 0;
break;
case ATM_VBR_NRT:
case ATM_UBR_PLUS:
/* WFQF calculation here is based on virtual cell rates, to reduce granularity for high rates */
/* WFQF is maximum cell rate / garenteed cell rate */
/* wfqf = qsb_minimum_cell_rate * QSB_WFQ_NONUBR_MAX / requested_minimum_peak_cell_rate */
if ( qos->txtp.min_pcr == 0 )
qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX;
else
{
tmp = QSB_GCR_MIN * QSB_WFQ_NONUBR_MAX / qos->txtp.min_pcr;
if ( tmp == 0 )
qsb_queue_parameter_table.bit.wfqf = 1;
else if ( tmp > QSB_WFQ_NONUBR_MAX )
qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX;
else
qsb_queue_parameter_table.bit.wfqf = tmp;
}
break;
default:
case ATM_UBR:
qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_UBR_BYPASS;
}
/*
* Sustained Cell Rate (SCR) Leaky Bucket Shaper VBR.0/VBR.1
*/
if ( qos->txtp.traffic_class == ATM_VBR_RT || qos->txtp.traffic_class == ATM_VBR_NRT )
{
if ( qos->txtp.scr == 0 )
{
/* disable shaper */
qsb_queue_vbr_parameter_table.bit.taus = 0;
qsb_queue_vbr_parameter_table.bit.ts = 0;
}
else
{
/* Cell Loss Priority (CLP) */
if ( (vcc->atm_options & ATM_ATMOPT_CLP) )
/* CLP1 */
qsb_queue_parameter_table.bit.vbr = 1;
else
/* CLP0 */
qsb_queue_parameter_table.bit.vbr = 0;
/* Rate Shaper Parameter (TS) and Burst Tolerance Parameter for SCR (tauS) */
tmp = ((qsb_clk * ppe_dev.qsb.tstepc) >> 5) / qos->txtp.scr + 1;
qsb_queue_vbr_parameter_table.bit.ts = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp;
tmp = (qos->txtp.mbs - 1) * (qsb_queue_vbr_parameter_table.bit.ts - qsb_queue_parameter_table.bit.tp) / 64;
if ( tmp == 0 )
qsb_queue_vbr_parameter_table.bit.taus = 1;
else if ( tmp > QSB_TAUS_MAX )
qsb_queue_vbr_parameter_table.bit.taus = QSB_TAUS_MAX;
else
qsb_queue_vbr_parameter_table.bit.taus = tmp;
}
}
else
{
qsb_queue_vbr_parameter_table.bit.taus = 0;
qsb_queue_vbr_parameter_table.bit.ts = 0;
}
/* Queue Parameter Table (QPT) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_QPT_SET_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_parameter_table.dword);
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_QPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(connection);
/* Queue VBR Paramter Table (QVPT) */
*QSB_RTM = QSB_RTM_DM_SET(QSB_QVPT_SET_MASK);
*QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_vbr_parameter_table.dword);
*QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_VBR) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(connection);
}
static inline void u64_add_u32(ppe_u64_t opt1, u32 opt2,ppe_u64_t *ret)
{
ret->l = opt1.l + opt2;
if ( ret->l < opt1.l || ret->l < opt2 )
ret->h++;
}
int find_vcc(struct atm_vcc *vcc)
{
int i;
struct connection *connection = ppe_dev.connection;
int max_connections = ppe_dev.port[(int)vcc->dev->dev_data].max_connections;
u32 occupation_table = ppe_dev.port[(int)vcc->dev->dev_data].connection_table;
int base = ppe_dev.port[(int)vcc->dev->dev_data].connection_base;
for ( i = 0; i < max_connections; i++, base++ )
if ( (occupation_table & (1 << i))
&& connection[base].vcc == vcc )
return base;
return -1;
}
int find_vpi(unsigned int vpi)
{
int i, j;
struct connection *connection = ppe_dev.connection;
struct port *port;
int base;
port = ppe_dev.port;
for ( i = 0; i < ATM_PORT_NUMBER; i++, port++ )
{
base = port->connection_base;
for ( j = 0; j < port->max_connections; j++, base++ )
if ( (port->connection_table & (1 << j))
&& connection[base].vcc != NULL
&& vpi == connection[base].vcc->vpi )
return base;
}
return -1;
}
int find_vpivci(unsigned int vpi, unsigned int vci)
{
int i, j;
struct connection *connection = ppe_dev.connection;
struct port *port;
int base;
port = ppe_dev.port;
for ( i = 0; i < ATM_PORT_NUMBER; i++, port++ )
{
base = port->connection_base;
for ( j = 0; j < port->max_connections; j++, base++ )
if ( (port->connection_table & (1 << j))
&& connection[base].vcc != NULL
&& vpi == connection[base].vcc->vpi
&& vci == connection[base].vcc->vci )
return base;
}
return -1;
}
static inline void clear_htu_entry(unsigned int connection)
{
HTU_ENTRY(connection - QSB_QUEUE_NUMBER_BASE + OAM_HTU_ENTRY_NUMBER)->vld = 0;
}
static inline void set_htu_entry(unsigned int vpi, unsigned int vci, unsigned int connection, int aal5)
{
struct htu_entry htu_entry = { res1: 0x00,
pid: ppe_dev.connection[connection].port & 0x01,
vpi: vpi,
vci: vci,
pti: 0x00,
vld: 0x01};
struct htu_mask htu_mask = { set: 0x03,
pid_mask: 0x02,
vpi_mask: 0x00,
vci_mask: 0x0000,
pti_mask: 0x03, // 0xx, user data
clear: 0x00};
struct htu_result htu_result = {res1: 0x00,
cellid: connection,
res2: 0x00,
type: aal5 ? 0x00 : 0x01,
ven: 0x01,
res3: 0x00,
qid: connection};
*HTU_RESULT(connection - QSB_QUEUE_NUMBER_BASE + OAM_HTU_ENTRY_NUMBER) = htu_result;
*HTU_MASK(connection - QSB_QUEUE_NUMBER_BASE + OAM_HTU_ENTRY_NUMBER) = htu_mask;
*HTU_ENTRY(connection - QSB_QUEUE_NUMBER_BASE + OAM_HTU_ENTRY_NUMBER) = htu_entry;
}
int alloc_tx_connection(int connection)
{
unsigned long sys_flag;
int desc_base;
if ( ppe_dev.dma.tx_desc_alloc_pos[connection] == ppe_dev.dma.tx_desc_release_pos[connection] && ppe_dev.dma.tx_desc_alloc_flag[connection] )
return -1;
/* amend descriptor pointer and allocation number */
local_irq_save(sys_flag);
desc_base = ppe_dev.dma.tx_descriptor_number * (connection - QSB_QUEUE_NUMBER_BASE) + ppe_dev.dma.tx_desc_alloc_pos[connection];
if ( ++ppe_dev.dma.tx_desc_alloc_pos[connection] == ppe_dev.dma.tx_descriptor_number )
ppe_dev.dma.tx_desc_alloc_pos[connection] = 0;
ppe_dev.dma.tx_desc_alloc_flag[connection] = 1;
local_irq_restore(sys_flag);
return desc_base;
}
int ppe_open(struct atm_vcc *vcc)
{
int ret;
struct port *port = &ppe_dev.port[(int)vcc->dev->dev_data];
int conn;
int f_enable_irq = 0;
int i;
printk("%s:%s[%d] removed 2 args from signature\n", __FILE__, __func__, __LINE__);
printk("ppe_open");
if ( vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0 )
return -EPROTONOSUPPORT;
down(&ppe_dev.sem);
/* check bandwidth */
if ( (vcc->qos.txtp.traffic_class == ATM_CBR && vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
|| (vcc->qos.txtp.traffic_class == ATM_VBR_RT && vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
|| (vcc->qos.txtp.traffic_class == ATM_VBR_NRT && vcc->qos.txtp.pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
|| (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS && vcc->qos.txtp.min_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) )
{
ret = -EINVAL;
goto PPE_OPEN_EXIT;
}
printk("alloc vpi = %d, vci = %d\n", vcc->vpi, vcc->vci);
/* check existing vpi,vci */
conn = find_vpivci(vcc->vpi, vcc->vci);
if ( conn >= 0 )
{
ret = -EADDRINUSE;
goto PPE_OPEN_EXIT;
}
/* check whether it need to enable irq */
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( ppe_dev.port[i].max_connections != 0 && ppe_dev.port[i].connection_table != 0 )
break;
if ( i == ATM_PORT_NUMBER )
f_enable_irq = 1;
/* allocate connection */
for ( i = 0, conn = port->connection_base; i < port->max_connections; i++, conn++ )
if ( !(port->connection_table & (1 << i)) )
{
port->connection_table |= 1 << i;
ppe_dev.connection[conn].vcc = vcc;
break;
}
if ( i == port->max_connections )
{
ret = -EINVAL;
goto PPE_OPEN_EXIT;
}
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
/* assign DMA channel and setup weight value for RX QoS */
switch ( vcc->qos.rxtp.traffic_class )
{
case ATM_CBR:
ppe_dev.connection[conn].rx_dma_channel = RX_DMA_CH_CBR;
break;
case ATM_VBR_RT:
ppe_dev.connection[conn].rx_dma_channel = RX_DMA_CH_VBR_RT;
ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_RT] += vcc->qos.rxtp.max_pcr;
ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] += vcc->qos.rxtp.max_pcr;
break;
case ATM_VBR_NRT:
ppe_dev.connection[conn].rx_dma_channel = RX_DMA_CH_VBR_NRT;
ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_NRT] += vcc->qos.rxtp.pcr;
ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] += vcc->qos.rxtp.pcr;
break;
case ATM_ABR:
ppe_dev.connection[conn].rx_dma_channel = RX_DMA_CH_AVR;
ppe_dev.dma.rx_default_weight[RX_DMA_CH_AVR] += vcc->qos.rxtp.min_pcr;
ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] += vcc->qos.rxtp.min_pcr;
break;
case ATM_UBR_PLUS:
default:
ppe_dev.connection[conn].rx_dma_channel = RX_DMA_CH_UBR;
break;
}
/* update RX queue configuration table */
WRX_QUEUE_CONFIG(conn)->dmach = ppe_dev.connection[conn].rx_dma_channel;
printk("ppe_open: QID %d, DMA %d\n", conn, WRX_QUEUE_CONFIG(conn)->dmach);
printk("conn = %d, dmach = %d", conn, WRX_QUEUE_CONFIG(conn)->dmach);
#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
/* reserve bandwidth */
switch ( vcc->qos.txtp.traffic_class )
{
case ATM_CBR:
case ATM_VBR_RT:
port->tx_current_cell_rate += vcc->qos.txtp.max_pcr;
break;
case ATM_VBR_NRT:
port->tx_current_cell_rate += vcc->qos.txtp.pcr;
break;
case ATM_UBR_PLUS:
port->tx_current_cell_rate += vcc->qos.txtp.min_pcr;
break;
}
/* set qsb */
set_qsb(vcc, &vcc->qos, conn);
/* update atm_vcc structure */
vcc->itf = (int)vcc->dev->dev_data;
set_bit(ATM_VF_READY, &vcc->flags);
/* enable irq */
printk("ppe_open: enable_irq\n");
if ( f_enable_irq )
enable_irq(IFXMIPS_PPE_MBOX_INT);
/* enable mailbox */
*MBOX_IGU1_ISRC = (1 << conn) | (1 << (conn + 16));
*MBOX_IGU1_IER |= (1 << conn) | (1 << (conn + 16));
*MBOX_IGU3_ISRC = (1 << conn) | (1 << (conn + 16));
*MBOX_IGU3_IER |= (1 << conn) | (1 << (conn + 16));
/* set htu entry */
set_htu_entry(vcc->vpi, vcc->vci, conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0);
ret = 0;
printk("ppe_open(%d.%d): conn = %d, ppe_dev.dma = %08X\n", vcc->vpi, vcc->vci, conn, (u32)&ppe_dev.dma.rx_descriptor_number);
PPE_OPEN_EXIT:
up(&ppe_dev.sem);
printk("open ATM itf = %d, vpi = %d, vci = %d, ret = %d", (int)vcc->dev->dev_data, (int)vcc->vpi, vcc->vci, ret);
return ret;
}
void ppe_close(struct atm_vcc *vcc)
{
int conn;
struct port *port;
struct connection *connection;
int i;
if ( vcc == NULL )
return;
down(&ppe_dev.sem);
/* get connection id */
conn = find_vcc(vcc);
if ( conn < 0 )
{
printk("can't find vcc\n");
goto PPE_CLOSE_EXIT;
}
if(!((Atm_Priv *)vcc)->on)
goto PPE_CLOSE_EXIT;
connection = &ppe_dev.connection[conn];
port = &ppe_dev.port[connection->port];
/* clear htu */
clear_htu_entry(conn);
/* release connection */
port->connection_table &= ~(1 << (conn - port->connection_base));
connection->vcc = NULL;
connection->access_time.tv_sec = 0;
connection->access_time.tv_nsec = 0;
connection->aal5_vcc_crc_err = 0;
connection->aal5_vcc_oversize_sdu = 0;
/* disable irq */
for ( i = 0; i < ATM_PORT_NUMBER; i++ )
if ( ppe_dev.port[i].max_connections != 0 && ppe_dev.port[i].connection_table != 0 )
break;
if ( i == ATM_PORT_NUMBER )
disable_irq(IFXMIPS_PPE_MBOX_INT);
*MBOX_IGU1_ISRC = (1 << conn) | (1 << (conn + 16));
#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
/* remove weight value from RX DMA channel */
switch ( vcc->qos.rxtp.traffic_class )
{
case ATM_VBR_RT:
ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_RT] -= vcc->qos.rxtp.max_pcr;
if ( ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] > ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_RT] )
ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_RT] = ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_RT];
break;
case ATM_VBR_NRT:
ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_NRT] -= vcc->qos.rxtp.pcr;
if ( ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] > ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_NRT] )
ppe_dev.dma.rx_weight[RX_DMA_CH_VBR_NRT] = ppe_dev.dma.rx_default_weight[RX_DMA_CH_VBR_NRT];
break;
case ATM_ABR:
ppe_dev.dma.rx_default_weight[RX_DMA_CH_AVR] -= vcc->qos.rxtp.min_pcr;
if ( ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] > ppe_dev.dma.rx_default_weight[RX_DMA_CH_AVR] )
ppe_dev.dma.rx_weight[RX_DMA_CH_AVR] = ppe_dev.dma.rx_default_weight[RX_DMA_CH_AVR];
break;
case ATM_CBR:
case ATM_UBR_PLUS:
default:
break;
}
#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS
/* release bandwidth */
switch ( vcc->qos.txtp.traffic_class )
{
case ATM_CBR:
case ATM_VBR_RT:
port->tx_current_cell_rate -= vcc->qos.txtp.max_pcr;
break;
case ATM_VBR_NRT:
port->tx_current_cell_rate -= vcc->qos.txtp.pcr;
break;
case ATM_UBR_PLUS:
port->tx_current_cell_rate -= vcc->qos.txtp.min_pcr;
break;
}
/* idle for a while to let parallel operation finish */
for ( i = 0; i < IDLE_CYCLE_NUMBER; i++ );
((Atm_Priv *)vcc)->on = 0;
PPE_CLOSE_EXIT:
up(&ppe_dev.sem);
}
int ppe_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg)
{
return -ENOTTY;
}
int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb)
{
int ret;
int conn;
int desc_base;
register struct tx_descriptor reg_desc;
struct tx_descriptor *desc;
printk("ppe_send");
printk("ppe_send\n");
printk("skb->users = %d\n", skb->users.counter);
if ( vcc == NULL || skb == NULL )
return -EINVAL;
// down(&ppe_dev.sem);
ATM_SKB(skb)->vcc = vcc;
conn = find_vcc(vcc);
// if ( conn != 1 )
printk("ppe_send: conn = %d\n", conn);
if ( conn < 0 )
{
ret = -EINVAL;
goto FIND_VCC_FAIL;
}
printk("find_vcc");
if ( vcc->qos.aal == ATM_AAL5 )
{
int byteoff;
int datalen;
struct tx_inband_header *header;
/* allocate descriptor */
desc_base = alloc_tx_connection(conn);
if ( desc_base < 0 )
{
ret = -EIO;
//goto ALLOC_TX_CONNECTION_FAIL;
}
desc = &ppe_dev.dma.tx_descriptor_base[desc_base];
/* load descriptor from memory */
reg_desc = *desc;
datalen = skb->len;
byteoff = (u32)skb->data & (DMA_ALIGNMENT - 1);
if ( skb_headroom(skb) < byteoff + TX_INBAND_HEADER_LENGTH )
{
struct sk_buff *new_skb;
printk("skb_headroom(skb) < byteoff + TX_INBAND_HEADER_LENGTH");
printk("skb_headroom(skb 0x%08X, skb->data 0x%08X) (%d) < byteoff (%d) + TX_INBAND_HEADER_LENGTH (%d)\n", (u32)skb, (u32)skb->data, skb_headroom(skb), byteoff, TX_INBAND_HEADER_LENGTH);
new_skb = alloc_skb_tx(datalen);
if ( new_skb == NULL )
{
printk("alloc_skb_tx: fail\n");
ret = -ENOMEM;
goto ALLOC_SKB_TX_FAIL;
}
ATM_SKB(new_skb)->vcc = NULL;
skb_put(new_skb, datalen);
memcpy(new_skb->data, skb->data, datalen);
atm_free_tx_skb_vcc(skb);
skb = new_skb;
byteoff = (u32)skb->data & (DMA_ALIGNMENT - 1);
}
else
{
printk("skb_headroom(skb) >= byteoff + TX_INBAND_HEADER_LENGTH");
}
printk("before skb_push, skb->data = 0x%08X", (u32)skb->data);
skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH);
printk("after skb_push, skb->data = 0x%08X", (u32)skb->data);
header = (struct tx_inband_header *)(u32)skb->data;
printk("header = 0x%08X", (u32)header);
/* setup inband trailer */
header->uu = 0;
header->cpi = 0;
header->pad = ppe_dev.aal5.padding_byte;
header->res1 = 0;
/* setup cell header */
header->clp = (vcc->atm_options & ATM_ATMOPT_CLP) ? 1 : 0;
header->pti = ATM_PTI_US0;
header->vci = vcc->vci;
header->vpi = vcc->vpi;
header->gfc = 0;
/* setup descriptor */
reg_desc.dataptr = (u32)skb->data >> 2;
reg_desc.datalen = datalen;
reg_desc.byteoff = byteoff;
reg_desc.iscell = 0;
printk("setup header, datalen = %d, byteoff = %d", reg_desc.datalen, reg_desc.byteoff);
UPDATE_VCC_STAT(conn, tx_pdu, 1);
if ( vcc->stats )
atomic_inc(&vcc->stats->tx);
}
else
{
/* allocate descriptor */
desc_base = alloc_tx_connection(conn);
if ( desc_base < 0 )
{
ret = -EIO;
goto ALLOC_TX_CONNECTION_FAIL;
}
desc = &ppe_dev.dma.tx_descriptor_base[desc_base];
/* load descriptor from memory */
reg_desc = *desc;
/* if data pointer is not aligned, allocate new sk_buff */
if ( ((u32)skb->data & (DMA_ALIGNMENT - 1)) )
{
struct sk_buff *new_skb;
printk("skb->data not aligned\n");
new_skb = alloc_skb_tx(skb->len);
if ( new_skb == NULL )
{
ret = -ENOMEM;
goto ALLOC_SKB_TX_FAIL;
}
ATM_SKB(new_skb)->vcc = NULL;
skb_put(new_skb, skb->len);
memcpy(new_skb->data, skb->data, skb->len);
atm_free_tx_skb_vcc(skb);
skb = new_skb;
}
reg_desc.dataptr = (u32)skb->data >> 2;
reg_desc.datalen = skb->len;
reg_desc.byteoff = 0;
reg_desc.iscell = 1;
if ( vcc->stats )
atomic_inc(&vcc->stats->tx);
}
reg_desc.own = 1;
reg_desc.c = 1;
printk("update descriptor send pointer, desc = 0x%08X", (u32)desc);
ppe_dev.dma.tx_skb_pointers[desc_base] = skb;
*desc = reg_desc;
dma_cache_wback((unsigned long)skb->data, skb->len);
mailbox_signal(conn, 1);
printk("ppe_send: success");
// up(&ppe_dev.sem);
return 0;
FIND_VCC_FAIL:
printk("FIND_VCC_FAIL\n");
// up(&ppe_dev.sem);
ppe_dev.mib.wtx_err_pdu++;
atm_free_tx_skb_vcc(skb);
return ret;
ALLOC_SKB_TX_FAIL:
printk("ALLOC_SKB_TX_FAIL\n");
// up(&ppe_dev.sem);
if ( vcc->qos.aal == ATM_AAL5 )
{
UPDATE_VCC_STAT(conn, tx_err_pdu, 1);
ppe_dev.mib.wtx_err_pdu++;
}
if ( vcc->stats )
atomic_inc(&vcc->stats->tx_err);
atm_free_tx_skb_vcc(skb);
return ret;
ALLOC_TX_CONNECTION_FAIL:
printk("ALLOC_TX_CONNECTION_FAIL\n");
// up(&ppe_dev.sem);
if ( vcc->qos.aal == ATM_AAL5 )
{
UPDATE_VCC_STAT(conn, tx_sw_drop_pdu, 1);
ppe_dev.mib.wtx_drop_pdu++;
}
if ( vcc->stats )
atomic_inc(&vcc->stats->tx_err);
atm_free_tx_skb_vcc(skb);
return ret;
}
int ppe_send_oam(struct atm_vcc *vcc, void *cell, int flags)
{
int conn;
struct uni_cell_header *uni_cell_header = (struct uni_cell_header *)cell;
int desc_base;
struct sk_buff *skb;
register struct tx_descriptor reg_desc;
struct tx_descriptor *desc;
printk("ppe_send_oam");
if ( ((uni_cell_header->pti == ATM_PTI_SEGF5 || uni_cell_header->pti == ATM_PTI_E2EF5)
&& find_vpivci(uni_cell_header->vpi, uni_cell_header->vci) < 0)
|| ((uni_cell_header->vci == 0x03 || uni_cell_header->vci == 0x04)
&& find_vpi(uni_cell_header->vpi) < 0) )
return -EINVAL;
#if OAM_TX_QUEUE_NUMBER_PER_PORT != 0
/* get queue ID of OAM TX queue, and the TX DMA channel ID is the same as queue ID */
conn = ppe_dev.port[(int)vcc->dev->dev_data].oam_tx_queue;
#else
/* find queue ID */
conn = find_vcc(vcc);
if ( conn < 0 )
{
printk("OAM not find queue\n");
// up(&ppe_dev.sem);
return -EINVAL;
}
#endif // OAM_TX_QUEUE_NUMBER_PER_PORT != 0
/* allocate descriptor */
desc_base = alloc_tx_connection(conn);
if ( desc_base < 0 )
{
printk("OAM not alloc tx connection\n");
// up(&ppe_dev.sem);
return -EIO;
}
desc = &ppe_dev.dma.tx_descriptor_base[desc_base];
/* load descriptor from memory */
reg_desc = *(struct tx_descriptor *)desc;
/* allocate sk_buff */
skb = alloc_skb_tx(CELL_SIZE);
if ( skb == NULL )
{
// up(&ppe_dev.sem);
return -ENOMEM;
}
#if OAM_TX_QUEUE_NUMBER_PER_PORT != 0
ATM_SKB(skb)->vcc = NULL;
#else
ATM_SKB(skb)->vcc = vcc;
#endif // OAM_TX_QUEUE_NUMBER_PER_PORT != 0
/* copy data */
skb_put(skb, CELL_SIZE);
memcpy(skb->data, cell, CELL_SIZE);
/* setup descriptor */
reg_desc.dataptr = (u32)skb->data >> 2;
reg_desc.datalen = CELL_SIZE;
reg_desc.byteoff = 0;
reg_desc.iscell = 1;
reg_desc.own = 1;
reg_desc.c = 1;
/* update descriptor send pointer */
ppe_dev.dma.tx_skb_pointers[desc_base] = skb;
/* write discriptor to memory and write back cache */
*(struct tx_descriptor *)desc = reg_desc;
dma_cache_wback((unsigned long)skb->data, skb->len);
/* signal PPE */
mailbox_signal(conn, 1);
return 0;
}
int ppe_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
{
int conn;
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
if(vcc == NULL || qos == NULL )
return -EINVAL;
conn = find_vcc(vcc);
if ( conn < 0 )
return -EINVAL;
set_qsb(vcc, qos, conn);
return 0;
}
static inline void init_chip(void)
{
/* enable PPE module in PMU */
*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9));
*EMA_CMDCFG = (EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2);
*EMA_DATACFG = (EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2);
*EMA_IER = 0x000000FF;
*EMA_CFG = EMA_READ_BURST | (EMA_WRITE_BURST << 2);
/* enable mailbox */
*MBOX_IGU1_ISRC = 0xFFFFFFFF;
*MBOX_IGU1_IER = 0x00000000;
*MBOX_IGU3_ISRC = 0xFFFFFFFF;
*MBOX_IGU3_IER = 0x00000000;
}
int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len)
{
u32 reg_old_value;
volatile u32 *dest;
if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0
|| data_src == 0 || ((unsigned long)data_src & 0x03) )
return -EINVAL;
/* save the old value of CDM_CFG and set PPE code memory to FPI bus access mode */
reg_old_value = *CDM_CFG;
if ( code_dword_len <= 4096 )
*CDM_CFG = CDM_CFG_RAM1_SET(0x00) | CDM_CFG_RAM0_SET(0x00);
else
*CDM_CFG = CDM_CFG_RAM1_SET(0x01) | CDM_CFG_RAM0_SET(0x00);
/* copy code */
dest = CDM_CODE_MEMORY_RAM0_ADDR(0);
while ( code_dword_len-- > 0 )
*dest++ = *code_src++;
/* copy data */
dest = PP32_DATA_MEMORY_RAM1_ADDR(0);
while ( data_dword_len-- > 0 )
*dest++ = *data_src++;
return 0;
}
int pp32_start(void)
{
int ret;
register int i;
init_chip();
/* download firmware */
ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data));
if ( ret )
return ret;
/* run PP32 */
*PP32_DBG_CTRL = DBG_CTRL_START_SET(1);
/* idle for a while to let PP32 init itself */
for ( i = 0; i < IDLE_CYCLE_NUMBER; i++ );
return 0;
}
void pp32_stop(void)
{
/* halt PP32 */
*PP32_DBG_CTRL = DBG_CTRL_STOP_SET(1);
}

View file

@ -1,98 +0,0 @@
#include <linux/atm.h>
#include <linux/proc_fs.h>
#include "proc.h"
#include "common.h"
struct proc_dir_entry *ppe_proc_dir;
int proc_read_idle_counter(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
len += sprintf(page + off, "Channel 0\n");
len += sprintf(page + off + len, " TX\n");
len += sprintf(page + off + len,
" DREG_AT_CELL0 = %d\n", *DREG_AT_CELL0 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AT_IDLE_CNT0 = %d\n", *DREG_AT_IDLE_CNT0 & 0xFFFF);
len += sprintf(page + off + len, " RX\n");
len += sprintf(page + off + len,
" DREG_AR_CELL0 = %d\n", *DREG_AR_CELL0 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AR_IDLE_CNT0 = %d\n", *DREG_AR_IDLE_CNT0 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AR_AIIDLE_CNT0 = %d\n", *DREG_AR_AIIDLE_CNT0 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AR_BE_CNT0 = %d\n", *DREG_AR_BE_CNT0 & 0xFFFF);
len += sprintf(page + off + len, "Channel 1\n");
len += sprintf(page + off + len, " TX\n");
len += sprintf(page + off + len,
" DREG_AT_CELL1 = %d\n", *DREG_AT_CELL1 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AT_IDLE_CNT1 = %d\n", *DREG_AT_IDLE_CNT1 & 0xFFFF);
len += sprintf(page + off + len, " RX\n");
len += sprintf(page + off + len,
" DREG_AR_CELL1 = %d\n", *DREG_AR_CELL1 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AR_IDLE_CNT1 = %d\n", *DREG_AR_IDLE_CNT1 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AR_AIIDLE_CNT1 = %d\n", *DREG_AR_AIIDLE_CNT1 & 0xFFFF);
len += sprintf(page + off + len,
" DREG_AR_BE_CNT1 = %d\n", *DREG_AR_BE_CNT1 & 0xFFFF);
return len;
}
int proc_read_stats(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
int i, j;
struct connection *connection;
struct port *port;
int base;
len += sprintf(page + off, "ATM Stats:\n");
connection = ppe_dev.connection;
port = ppe_dev.port;
for ( i = 0; i < ATM_PORT_NUMBER; i++, port++ )
{
base = port->connection_base;
for ( j = 0; j < port->max_connections; j++, base++ )
if ( (port->connection_table & (1 << j))
&& connection[base].vcc != NULL )
{
if ( connection[base].vcc->stats )
{
struct k_atm_aal_stats *stats = connection[base].vcc->stats;
len += sprintf(page + off + len, " VCC %d.%d.%d (stats)\n", i, connection[base].vcc->vpi, connection[base].vcc->vci);
len += sprintf(page + off + len, " rx = %d\n", stats->rx.counter);
len += sprintf(page + off + len, " rx_err = %d\n", stats->rx_err.counter);
len += sprintf(page + off + len, " rx_drop = %d\n", stats->rx_drop.counter);
len += sprintf(page + off + len, " tx = %d\n", stats->tx.counter);
len += sprintf(page + off + len, " tx_err = %d\n", stats->tx_err.counter);
}
else
len += sprintf(page + off + len, " VCC %d.%d.%d\n", i, connection[base].vcc->vpi, connection[base].vcc->vci);
}
}
return len;
}
void proc_file_create(void)
{
ppe_proc_dir = proc_mkdir("ppe", NULL);
create_proc_read_entry("idle_counter", 0, ppe_proc_dir, proc_read_idle_counter, NULL);
create_proc_read_entry("stats", 0, ppe_proc_dir, proc_read_stats, NULL);
}
void proc_file_delete(void)
{
remove_proc_entry("idle_counter", ppe_proc_dir);
remove_proc_entry("stats", ppe_proc_dir);
remove_proc_entry("ppe", NULL);
}

View file

@ -1,9 +0,0 @@
#ifndef _IFXMIPS_PPE_PROC_H__
#define _IFXMIPS_PPE_PROC_H__
void proc_file_create(void);
void proc_file_delete(void);
int proc_read_idle_counter(char *page, char **start, off_t off, int count, int *eof, void *data);
int proc_read_stats(char *page, char **start, off_t off, int count, int *eof, void *data);
#endif

View file

@ -1,128 +0,0 @@
#include <linux/skbuff.h>
#include "common.h"
void resize_skb_rx(struct sk_buff *skb, unsigned int size, int is_cell)
{
if((u32)skb < 0x80000000)
{
int key = 0;
printk("resize_skb_rx problem: skb = %08X, size = %d, is_cell = %d\n", (u32)skb, size, is_cell);
while(!key){}
}
skb->data = (unsigned char*)(((u32)skb->head + 16 + (DMA_ALIGNMENT - 1)) & ~(DMA_ALIGNMENT - 1));
skb->tail = skb->data;
/* Set up other state */
skb->len = 0;
skb->cloned = 0;
#if defined(CONFIG_IMQ) || defined (CONFIG_IMQ_MODULE)
skb->imq_flags = 0;
skb->nf_info = NULL;
#endif
skb->data_len = 0;
}
struct sk_buff* alloc_skb_rx(void)
{
struct sk_buff *skb;
/* allocate memroy including trailer and padding */
skb = dev_alloc_skb(ppe_dev.aal5.rx_buffer_size + DMA_ALIGNMENT);
if (skb)
{
/* must be burst length alignment */
if ( ((u32)skb->data & (DMA_ALIGNMENT - 1)) != 0 )
skb_reserve(skb, ~((u32)skb->data + (DMA_ALIGNMENT - 1)) & (DMA_ALIGNMENT - 1));
/* put skb in reserved area "skb->data - 4" */
*((u32*)skb->data - 1) = (u32)skb;
/* invalidate cache */
dma_cache_inv((unsigned long)skb->head, (u32)skb->end - (u32)skb->head);
}
return skb;
}
void atm_free_tx_skb_vcc(struct sk_buff *skb)
{
struct atm_vcc* vcc;
if ( (u32)skb <= 0x80000000 )
{
volatile int key = 0;
printk("atm_free_tx_skb_vcc: skb = %08X\n", (u32)skb);
for ( ; !key; );
}
vcc = ATM_SKB(skb)->vcc;
if ( vcc != NULL && vcc->pop != NULL )
{
if ( atomic_read(&skb->users) == 0 )
{
volatile int key = 0;
printk("atm_free_tx_skb_vcc(vcc->pop): skb->users == 0, skb = %08X\n", (u32)skb);
for ( ; !key; );
}
vcc->pop(vcc, skb);
}
else
{
if ( atomic_read(&skb->users) == 0 )
{
volatile int key = 0;
printk("atm_free_tx_skb_vcc(dev_kfree_skb_any): skb->users == 0, skb = %08X\n", (u32)skb);
for ( ; !key; );
}
dev_kfree_skb_any(skb);
}
}
struct sk_buff* alloc_skb_tx(unsigned int size)
{
struct sk_buff *skb;
/* allocate memory including header and padding */
size += TX_INBAND_HEADER_LENGTH + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES;
size &= ~(DMA_ALIGNMENT - 1);
skb = dev_alloc_skb(size + DMA_ALIGNMENT);
/* must be burst length alignment */
if ( skb )
skb_reserve(skb, (~((u32)skb->data + (DMA_ALIGNMENT - 1)) & (DMA_ALIGNMENT - 1)) + TX_INBAND_HEADER_LENGTH);
return skb;
}
struct sk_buff* atm_alloc_tx(struct atm_vcc *vcc, unsigned int size)
{
int conn;
struct sk_buff *skb;
/* oversize packet */
if ( ((size + TX_INBAND_HEADER_LENGTH + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES) & ~(DMA_ALIGNMENT - 1)) > ppe_dev.aal5.tx_max_packet_size )
{
printk("atm_alloc_tx: oversize packet\n");
return NULL;
}
/* send buffer overflow */
if ( atomic_read(&vcc->sk.sk_wmem_alloc) && !atm_may_send(vcc, size) )
{
printk("atm_alloc_tx: send buffer overflow\n");
return NULL;
}
conn = find_vcc(vcc);
if ( conn < 0 )
{
printk("atm_alloc_tx: unknown VCC\n");
return NULL;
}
skb = dev_alloc_skb(size);
if ( skb == NULL )
{
printk("atm_alloc_tx: sk buffer is used up\n");
return NULL;
}
#define ATM_PDU_OVHD 0
atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->sk.sk_wmem_alloc);
return skb;
}

View file

@ -0,0 +1,18 @@
choice
prompt "Firmware"
depends on PACKAGE_kmod-ifxmips-dsl-api
default IFXMIPS_ANNEX_B
help
This option controls which firmware is loaded
config IFXMIPS_ANNEX_A
bool "Annex-A"
help
Annex-A
config IFXMIPS_ANNEX_B
bool "Annex-B"
help
Annex-B
endchoice

View file

@ -0,0 +1,140 @@
#
# Copyright (C) 2009 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# ralph / blogic
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=ifxmips-dsl-api
PKG_BASE_NAME:=drv_dsl_cpe_api_danube
PKG_VERSION:=3.24.4.4
PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/drv_dsl_cpe_api-$(PKG_VERSION)
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
PKG_MD5SUM:=c45bc531c1ed2ac80f68fb986b63bb87
FW_BASE_NAME:=dsl_danube_firmware_adsl
FW_A_VER:=02.04.04.00.00.01
FW_B_VER:=02.04.01.07.00.02
FW_A_FILE_VER:=244001
FW_B_FILE_VER:=241702
FW_A_MD5:=f717db3067a0049a26e233ab11238710
FW_B_MD5:=349de7cd20368f4ac9b7e8322114a512
include $(INCLUDE_DIR)/package.mk
define KernelPackage/ifxmips-dsl-api
SECTION:=driver
CATEGORY:=Infineon
TITLE:=DSL CPE API driver
URL:=http://www.infineon.com/
MAINTAINER:=Infineon Technologies AG / Lantiq / blogic@openwrt.org
DEPENDS:=@TARGET_ifxmips
FILES:=$(PKG_BUILD_DIR)/src/mei/ifxmips_mei.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/src/mei/ifxmips_atm.$(LINUX_KMOD_SUFFIX)
AUTOLOAD:=$(call AutoLoad,50,ifxmips_mei drv_dsl_cpe_api ifxmips_atm)
endef
define KernelPackage/ifxmips-dsl-api/description
Infineon DSL CPE API for Amazon SE, Danube and Vinax.
This package contains the DSL CPE API driver for Amazon SE & Danube.
Supported Devices:
- Amazon SE
- Danube
This package was kindly contributed to openwrt by Infineon/Lantiq
endef
define KernelPackage/ifxmips-dsl-api/config
source "$(SOURCE)/Config.in"
endef
define Download/annex-a
FILE:=$(FW_BASE_NAME)_a-$(FW_A_VER).tar.gz
URL:=http://mirror2.openwrt.org/sources/
MD5SUM:=$(FW_A_MD5)
endef
$(eval $(call Download,annex-a))
define Download/annex-b
FILE:=$(FW_BASE_NAME)_b-$(FW_B_VER).tar.gz
URL:=http://mirror2.openwrt.org/sources/
MD5SUM:=$(FW_B_MD5)
endef
$(eval $(call Download,annex-b))
IFX_DSL_MAX_DEVICE=1
IFX_DSL_LINES_PER_DEVICE=1
IFX_DSL_CHANNELS_PER_LINE=1
CONFIGURE_ARGS += --enable-kernel-include="$(LINUX_DIR)/include" \
--with-max-device="$(IFX_DSL_MAX_DEVICE)" \
--with-lines-per-device="$(IFX_DSL_LINES_PER_DEVICE)" \
--with-channels-per-line="$(IFX_DSL_CHANNELS_PER_LINE)" \
--enable-danube \
--enable-add-drv-cflags="-DMODULE" \
--enable-debug=yes \
--enable-debug-prints=yes \
--disable-dsl-delt-static \
--disable-adsl-led \
--enable-dsl-ceoc \
--enable-dsl-pm \
--enable-dsl-pm-total \
--enable-dsl-pm-history \
--enable-dsl-pm-showtime \
--enable-dsl-pm-channel-counters \
--enable-dsl-pm-datapath-counters \
--enable-dsl-pm-line-counters \
--enable-dsl-pm-channel-thresholds \
--enable-dsl-pm-datapath-thresholds \
--enable-dsl-pm-line-thresholds \
--enable-dsl-pm-optional-parameters \
--enable-linux-26 \
--enable-kernelbuild="$(LINUX_DIR)" \
ARCH=$(LINUX_KARCH)
EXTRA_CFLAGS = -fno-pic -mno-abicalls -mlong-calls -G 0
define Build/Prepare
$(PKG_UNPACK)
$(INSTALL_DIR) $(PKG_BUILD_DIR)/src/mei/
$(CP) ./src/* $(PKG_BUILD_DIR)/src/mei/
$(Build/Patch)
$(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(FW_BASE_NAME)_a-$(FW_A_VER).tar.gz
$(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(FW_BASE_NAME)_b-$(FW_B_VER).tar.gz
endef
define Build/Compile
cd $(LINUX_DIR); \
ARCH=mips CROSS_COMPILE="$(KERNEL_CROSS)" \
$(MAKE) M=$(PKG_BUILD_DIR)/src/mei/ V=1 modules
$(call Build/Compile/Default)
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_ioctl.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_adslmib.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_adslmib_ioctl.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_g997.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_types.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_pm.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_error.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_danube_ctx.h $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_cmv_danube.h $(1)/usr/include
endef
define KernelPackage/ifxmips-dsl-api/install
$(INSTALL_DIR) $(1)/lib/firmware/
$(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_$(if $(CONFIG_IFXMIPS_ANNEX_A),a_$(FW_A_FILE_VER),b_$(FW_B_FILE_VER)).bin $(1)/lib/firmware/ModemHWE.bin
endef
$(eval $(call KernelPackage,ifxmips-dsl-api))

View file

@ -0,0 +1,43 @@
Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_device_danube.h
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_device_danube.h 2009-05-12 20:02:16.000000000 +0200
+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_device_danube.h 2009-11-01 00:57:23.000000000 +0100
@@ -24,7 +24,7 @@
#include "drv_dsl_cpe_simulator_danube.h"
#else
/* Include for the low level driver interface header file */
-#include "asm/ifx/ifx_mei_bsp.h"
+#include "mei/ifxmips_mei_interface.h"
#endif /* defined(DSL_CPE_SIMULATOR_DRIVER) && defined(WIN32)*/
#define DSL_MAX_LINE_NUMBER 1
Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/common/drv_dsl_cpe_os_linux.c 2009-11-01 01:00:08.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c 2009-11-01 01:03:51.000000000 +0100
@@ -11,6 +11,7 @@
#ifdef __LINUX__
#define DSL_INTERN
+#include <linux/device.h>
#include "drv_dsl_cpe_api.h"
#include "drv_dsl_cpe_api_ioctl.h"
@@ -1058,6 +1059,7 @@
/* Entry point of driver */
int __init DSL_ModuleInit(void)
{
+ struct class *dsl_class;
DSL_int_t i;
printk(DSL_DRV_CRLF DSL_DRV_CRLF "Infineon CPE API Driver version: %s" DSL_DRV_CRLF,
@@ -1104,7 +1106,8 @@
}
DSL_DRV_DevNodeInit();
-
+ dsl_class = class_create(THIS_MODULE, "dsl_cpe_api");
+ device_create(dsl_class, NULL, MKDEV(DRV_DSL_CPE_API_DEV_MAJOR, 0), NULL, "dsl_cpe_api");
return 0;
}

View file

@ -0,0 +1,95 @@
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_mei.c
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/mei/ifxmips_mei.c 2009-10-31 23:30:20.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_mei.c 2009-11-01 04:41:58.000000000 +0100
@@ -41,18 +41,19 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
-#include <asm/ifx/ifx_regs.h>
-#include <asm/ifx/irq.h>
-#include <asm/ifx/ifx_gpio.h>
-//#include <asm/ifx/ifx_led.h>
-#include <asm/ifx/ifx_pmu.h>
-#include <asm/ifx/ifx_atm.h>
+
+#include <ifxmips.h>
+#include <ifxmips_irq.h>
+#include <ifxmips_gpio.h>
+#include <ifxmips_pmu.h>
+#include "ifxmips_atm.h"
#define IFX_MEI_BSP
#include "ifxmips_mei_interface.h"
-#define IFXMIPS_RCU_RST IFX_RCU_RST_REQ
+/*#define IFXMIPS_RCU_RST IFX_RCU_RST_REQ
#define IFXMIPS_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG
#define IFXMIPS_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE
#define IFXMIPS_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE
@@ -76,7 +77,7 @@
#define ifxmips_r32(reg) __raw_readl(reg)
#define ifxmips_w32(val, reg) __raw_writel(val, reg)
#define ifxmips_w32_mask(clear, set, reg) ifxmips_w32((ifxmips_r32(reg) & ~clear) | set, reg)
-
+*/
#define IFX_MEI_EMSG(fmt, args...) printk(KERN_ERR "[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
#define IFX_MEI_DMSG(fmt, args...) printk(KERN_INFO "[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
@@ -173,7 +174,8 @@
extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr);
#define MEI_MASK_AND_ACK_IRQ ifxmips_mask_and_ack_irq
-static int dev_major = 105;
+#define MEI_MAJOR 105
+static int dev_major = MEI_MAJOR;
static struct file_operations bsp_mei_operations = {
owner:THIS_MODULE,
@@ -2294,10 +2296,10 @@
IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DFEIR]);
return -1;
}
- if (request_irq (pDev->nIrq[IFX_DYING_GASP], IFX_MEI_Dying_Gasp_IrqHandle, 0, "DYING_GASP", pDev) != 0) {
+ /*if (request_irq (pDev->nIrq[IFX_DYING_GASP], IFX_MEI_Dying_Gasp_IrqHandle, 0, "DYING_GASP", pDev) != 0) {
IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DYING_GASP]);
return -1;
- }
+ }*/
// IFX_MEI_DMSG("Device %d initialized. IER %#x\n", num, bsp_get_irq_ier(pDev->nIrq[IFX_DYING_GASP]));
return 0;
}
@@ -2922,6 +2924,7 @@
IFX_MEI_ModuleInit (void)
{
int i = 0;
+ static struct class *dsl_class;
printk ("IFX MEI Version %ld.%02ld.%02ld", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
@@ -2935,14 +2938,15 @@
IFX_MEI_InitProcFS (i);
#endif
}
- for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
+ for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
dsl_bsp_event_callback[i].function = NULL;
#ifdef CONFIG_IFXMIPS_MEI_FW_LOOPBACK
printk(KERN_INFO "[%s %s %d]: Start loopback test...\n", __FILE__, __func__, __LINE__);
DFE_Loopback_Test ();
#endif
-
+ dsl_class = class_create(THIS_MODULE, "ifx_mei");
+ device_create(dsl_class, NULL, MKDEV(MEI_MAJOR, 0), NULL, "ifx_mei");
return 0;
}
@@ -2996,3 +3000,5 @@
module_init (IFX_MEI_ModuleInit);
module_exit (IFX_MEI_ModuleExit);
+
+MODULE_LICENSE("Dual BSD/GPL");

View file

@ -0,0 +1,168 @@
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_core.c
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/mei/ifxmips_atm_core.c 2009-11-01 14:29:05.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_core.c 2009-11-01 16:07:46.000000000 +0100
@@ -58,9 +58,8 @@
/*
* Chip Specific Head File
*/
-#include <asm/ifx/ifx_types.h>
-#include <asm/ifx/ifx_regs.h>
-#include <asm/ifx/common_routines.h>
+#include <ifxmips.h>
+#include <ifxmips_cgu.h>
#include "ifxmips_atm_core.h"
@@ -1146,7 +1145,7 @@
static void set_qsb(struct atm_vcc *vcc, struct atm_qos *qos, unsigned int queue)
{
- unsigned int qsb_clk = ifx_get_fpi_hz();
+ unsigned int qsb_clk = ifxmips_get_fpi_hz();
unsigned int qsb_qid = queue + FIRST_QSB_QID;
union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}};
union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}};
@@ -1318,7 +1317,7 @@
static void qsb_global_set(void)
{
- unsigned int qsb_clk = ifx_get_fpi_hz();
+ unsigned int qsb_clk = ifxmips_get_fpi_hz();
int i;
unsigned int tmp1, tmp2, tmp3;
@@ -2505,3 +2504,4 @@
module_init(ifx_atm_init);
module_exit(ifx_atm_exit);
+MODULE_LICENSE("Dual BSD/GPL");
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_ppe_common.h
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/mei/ifxmips_atm_ppe_common.h 2009-11-01 14:30:55.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_ppe_common.h 2009-11-01 15:58:50.000000000 +0100
@@ -1,9 +1,10 @@
#ifndef IFXMIPS_ATM_PPE_COMMON_H
#define IFXMIPS_ATM_PPE_COMMON_H
-
-
-#if defined(CONFIG_DANUBE)
+#if defined(CONFIG_IFXMIPS)
+ #include "ifxmips_atm_ppe_danube.h"
+ #define CONFIG_DANUBE
+#elif defined(CONFIG_DANUBE)
#include "ifxmips_atm_ppe_danube.h"
#elif defined(CONFIG_AMAZON_SE)
#include "ifxmips_atm_ppe_amazon_se.h"
@@ -16,7 +17,6 @@
#endif
-
/*
* Code/Data Memory (CDM) Interface Configuration Register
*/
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_core.h
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/mei/ifxmips_atm_core.h 2009-11-01 14:30:55.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_core.h 2009-11-01 15:58:50.000000000 +0100
@@ -25,8 +25,8 @@
#define IFXMIPS_ATM_CORE_H
-
-#include <asm/ifx/ifx_atm.h>
+#include "ifxmips_compat.h"
+#include "ifx_atm.h"
#include "ifxmips_atm_ppe_common.h"
#include "ifxmips_atm_fw_regs_common.h"
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_compat.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_compat.h 2009-11-01 15:58:50.000000000 +0100
@@ -0,0 +1,43 @@
+#ifndef _IFXMIPS_COMPAT_H__
+#define _IFXMIPS_COMPAT_H__
+
+#define IFX_SUCCESS 0
+#define IFX_ERROR (-1)
+
+#define ATM_VBR_NRT ATM_VBR
+#define ATM_VBR_RT 6
+#define ATM_UBR_PLUS 7
+#define ATM_GFR 8
+
+#define NUM_ENTITY(x) (sizeof(x) / sizeof(*(x)))
+
+#define SET_BITS(x, msb, lsb, value) \
+ (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
+
+
+#define IFX_PMU_ENABLE 1
+#define IFX_PMU_DISABLE 0
+
+#define IFX_PMU_MODULE_DSL_DFE (1 << 9)
+#define IFX_PMU_MODULE_AHBS (1 << 13)
+#define IFX_PMU_MODULE_PPE_QSB (1 << 18)
+#define IFX_PMU_MODULE_PPE_SLL01 (1 << 19)
+#define IFX_PMU_MODULE_PPE_TC (1 << 21)
+#define IFX_PMU_MODULE_PPE_EMA (1 << 22)
+#define IFX_PMU_MODULE_PPE_TOP (1 << 29)
+
+#define ifx_pmu_set(a,b) {if(a == IFX_PMU_ENABLE) ifxmips_pmu_enable(b); else ifxmips_pmu_disable(b);}
+
+#define PPE_TOP_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TOP, (__x))
+#define PPE_SLL01_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_SLL01, (__x))
+#define PPE_TC_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TC, (__x))
+#define PPE_EMA_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_EMA, (__x))
+#define PPE_QSB_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_QSB, (__x))
+#define PPE_TPE_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_AHBS, (__x))
+#define DSL_DFE_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_DSL_DFE, (__x))
+
+#define IFX_REG_W32(_v, _r) __raw_writel((_v), (_r))
+
+#define CONFIG_IFXMIPS_DSL_CPE_MEI y
+
+#endif
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_ppe_danube.h
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/mei/ifxmips_atm_ppe_danube.h 2009-11-01 14:30:55.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_ppe_danube.h 2009-11-01 15:58:50.000000000 +0100
@@ -1,7 +1,7 @@
#ifndef IFXMIPS_ATM_PPE_DANUBE_H
#define IFXMIPS_ATM_PPE_DANUBE_H
-
+#include <ifxmips_irq.h>
/*
* FPI Configuration Bus Register and Memory Address Mapping
@@ -93,7 +93,7 @@
/*
* Mailbox IGU1 Interrupt
*/
-#define PPE_MAILBOX_IGU1_INT INT_NUM_IM2_IRL24
+#define PPE_MAILBOX_IGU1_INT IFXMIPS_PPE_MBOX_INT
Index: drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_danube.c
===================================================================
--- drv_dsl_cpe_api-3.24.4.4.orig/src/mei/ifxmips_atm_danube.c 2009-11-01 14:29:18.000000000 +0100
+++ drv_dsl_cpe_api-3.24.4.4/src/mei/ifxmips_atm_danube.c 2009-11-01 15:58:50.000000000 +0100
@@ -45,10 +45,9 @@
/*
* Chip Specific Head File
*/
-#include <asm/ifx/ifx_types.h>
-#include <asm/ifx/ifx_regs.h>
-#include <asm/ifx/common_routines.h>
-#include <asm/ifx/ifx_pmu.h>
+#include <ifxmips.h>
+#include <ifxmips_pmu.h>
+#include "ifxmips_compat.h"
#include "ifxmips_atm_core.h"
#include "ifxmips_atm_fw_danube.h"

View file

@ -0,0 +1,3 @@
obj-m = ifxmips_mei.o ifxmips_atm.o
ifxmips_atm-objs := ifxmips_atm_core.o ifxmips_atm_danube.o

View file

@ -0,0 +1,172 @@
/******************************************************************************
**
** FILE NAME : ifx_atm.h
** PROJECT : UEIP
** MODULES : ATM
**
** DATE : 17 Jun 2009
** AUTHOR : Xu Liang
** DESCRIPTION : Global ATM driver header file
** COPYRIGHT : Copyright (c) 2006
** Infineon Technologies AG
** Am Campeon 1-12, 85579 Neubiberg, Germany
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** HISTORY
** $Date $Author $Comment
** 07 JUL 2009 Xu Liang Init Version
*******************************************************************************/
#ifndef IFX_ATM_H
#define IFX_ATM_H
/*!
\defgroup IFX_ATM UEIP Project - ATM driver module
\brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9.
*/
/*!
\defgroup IFX_ATM_IOCTL IOCTL Commands
\ingroup IFX_ATM
\brief IOCTL Commands used by user application.
*/
/*!
\defgroup IFX_ATM_STRUCT Structures
\ingroup IFX_ATM
\brief Structures used by user application.
*/
/*!
\file ifx_atm.h
\ingroup IFX_ATM
\brief ATM driver header file
*/
/*
* ####################################
* Definition
* ####################################
*/
/*!
\addtogroup IFX_ATM_STRUCT
*/
/*@{*/
/*
* ATM MIB
*/
typedef struct {
__u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */
__u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */
__u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */
__u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */
__u32 ifInErrors; /*!< counter of error ingress cells */
__u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */
__u32 ifOutErrors; /*!< counter of error egress cells */
} atm_cell_ifEntry_t;
typedef struct {
__u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */
__u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */
__u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */
__u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */
__u32 ifInUcastPkts; /*!< counter of ingress packets */
__u32 ifOutUcastPkts; /*!< counter of egress packets */
__u32 ifInErrors; /*!< counter of error ingress packets */
__u32 ifInDiscards; /*!< counter of dropped ingress packets */
__u32 ifOutErros; /*!< counter of error egress packets */
__u32 ifOutDiscards; /*!< counter of dropped egress packets */
} atm_aal5_ifEntry_t;
typedef struct {
__u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */
__u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet
__u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */
} atm_aal5_vcc_t;
typedef struct {
int vpi; /*!< VPI of the VCC to get MIB counters */
int vci; /*!< VCI of the VCC to get MIB counters */
atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */
} atm_aal5_vcc_x_t;
/*@}*/
/*
* ####################################
* IOCTL
* ####################################
*/
/*!
\addtogroup IFX_ATM_IOCTL
*/
/*@{*/
/*
* ioctl Command
*/
/*!
\brief ATM IOCTL Magic Number
*/
#define PPE_ATM_IOC_MAGIC 'o'
/*!
\brief ATM IOCTL Command - Get Cell Level MIB Counters
This command is obsolete. User can get cell level MIB from DSL API.
This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters.
*/
#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t)
/*!
\brief ATM IOCTL Command - Get AAL5 Level MIB Counters
Get AAL5 packet counters.
This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters.
*/
#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t)
/*!
\brief ATM IOCTL Command - Get Per PVC MIB Counters
Get AAL5 packet counters for each PVC.
This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters.
*/
#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t)
/*!
\brief Total Number of ATM IOCTL Commands
*/
#define PPE_ATM_IOC_MAXNR 3
/*@}*/
/*
* ####################################
* API
* ####################################
*/
#ifdef __KERNEL__
struct port_cell_info {
unsigned int port_num;
unsigned int tx_link_rate[2];
};
#endif
#endif // IFX_ATM_H

View file

@ -0,0 +1,172 @@
/******************************************************************************
**
** FILE NAME : ifx_atm.h
** PROJECT : UEIP
** MODULES : ATM
**
** DATE : 17 Jun 2009
** AUTHOR : Xu Liang
** DESCRIPTION : Global ATM driver header file
** COPYRIGHT : Copyright (c) 2006
** Infineon Technologies AG
** Am Campeon 1-12, 85579 Neubiberg, Germany
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** HISTORY
** $Date $Author $Comment
** 07 JUL 2009 Xu Liang Init Version
*******************************************************************************/
#ifndef IFX_ATM_H
#define IFX_ATM_H
/*!
\defgroup IFX_ATM UEIP Project - ATM driver module
\brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9.
*/
/*!
\defgroup IFX_ATM_IOCTL IOCTL Commands
\ingroup IFX_ATM
\brief IOCTL Commands used by user application.
*/
/*!
\defgroup IFX_ATM_STRUCT Structures
\ingroup IFX_ATM
\brief Structures used by user application.
*/
/*!
\file ifx_atm.h
\ingroup IFX_ATM
\brief ATM driver header file
*/
/*
* ####################################
* Definition
* ####################################
*/
/*!
\addtogroup IFX_ATM_STRUCT
*/
/*@{*/
/*
* ATM MIB
*/
typedef struct {
__u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */
__u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */
__u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */
__u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */
__u32 ifInErrors; /*!< counter of error ingress cells */
__u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */
__u32 ifOutErrors; /*!< counter of error egress cells */
} atm_cell_ifEntry_t;
typedef struct {
__u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */
__u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */
__u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */
__u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */
__u32 ifInUcastPkts; /*!< counter of ingress packets */
__u32 ifOutUcastPkts; /*!< counter of egress packets */
__u32 ifInErrors; /*!< counter of error ingress packets */
__u32 ifInDiscards; /*!< counter of dropped ingress packets */
__u32 ifOutErros; /*!< counter of error egress packets */
__u32 ifOutDiscards; /*!< counter of dropped egress packets */
} atm_aal5_ifEntry_t;
typedef struct {
__u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */
__u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet
__u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */
} atm_aal5_vcc_t;
typedef struct {
int vpi; /*!< VPI of the VCC to get MIB counters */
int vci; /*!< VCI of the VCC to get MIB counters */
atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */
} atm_aal5_vcc_x_t;
/*@}*/
/*
* ####################################
* IOCTL
* ####################################
*/
/*!
\addtogroup IFX_ATM_IOCTL
*/
/*@{*/
/*
* ioctl Command
*/
/*!
\brief ATM IOCTL Magic Number
*/
#define PPE_ATM_IOC_MAGIC 'o'
/*!
\brief ATM IOCTL Command - Get Cell Level MIB Counters
This command is obsolete. User can get cell level MIB from DSL API.
This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters.
*/
#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t)
/*!
\brief ATM IOCTL Command - Get AAL5 Level MIB Counters
Get AAL5 packet counters.
This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters.
*/
#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t)
/*!
\brief ATM IOCTL Command - Get Per PVC MIB Counters
Get AAL5 packet counters for each PVC.
This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters.
*/
#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t)
/*!
\brief Total Number of ATM IOCTL Commands
*/
#define PPE_ATM_IOC_MAXNR 3
/*@}*/
/*
* ####################################
* API
* ####################################
*/
#ifdef __KERNEL__
struct port_cell_info {
unsigned int port_num;
unsigned int tx_link_rate[2];
};
#endif
#endif // IFX_ATM_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,249 @@
/******************************************************************************
**
** FILE NAME : ifxmips_atm_core.h
** PROJECT : UEIP
** MODULES : ATM
**
** DATE : 7 Jul 2009
** AUTHOR : Xu Liang
** DESCRIPTION : ATM driver header file (core functions)
** COPYRIGHT : Copyright (c) 2006
** Infineon Technologies AG
** Am Campeon 1-12, 85579 Neubiberg, Germany
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** HISTORY
** $Date $Author $Comment
** 17 JUN 2009 Xu Liang Init Version
*******************************************************************************/
#ifndef IFXMIPS_ATM_CORE_H
#define IFXMIPS_ATM_CORE_H
#include <asm/ifx/ifx_atm.h>
#include "ifxmips_atm_ppe_common.h"
#include "ifxmips_atm_fw_regs_common.h"
/*
* ####################################
* Definition
* ####################################
*/
/*
* Compile Options
*/
#define ENABLE_DEBUG 1
#define ENABLE_ASSERT 1
#define INLINE
#define DEBUG_DUMP_SKB 1
#define DEBUG_QOS 1
#define ENABLE_DBG_PROC 1
#define ENABLE_FW_PROC 1
#ifdef CONFIG_IFX_ATM_TASKLET
#define ENABLE_TASKLET 1
#endif
/*
* Debug/Assert/Error Message
*/
#define DBG_ENABLE_MASK_ERR (1 << 0)
#define DBG_ENABLE_MASK_DEBUG_PRINT (1 << 1)
#define DBG_ENABLE_MASK_ASSERT (1 << 2)
#define DBG_ENABLE_MASK_DUMP_SKB_RX (1 << 8)
#define DBG_ENABLE_MASK_DUMP_SKB_TX (1 << 9)
#define DBG_ENABLE_MASK_DUMP_QOS (1 << 10)
#define DBG_ENABLE_MASK_DUMP_INIT (1 << 11)
#define DBG_ENABLE_MASK_ALL (DBG_ENABLE_MASK_ERR | DBG_ENABLE_MASK_DEBUG_PRINT | DBG_ENABLE_MASK_ASSERT | DBG_ENABLE_MASK_DUMP_SKB_RX | DBG_ENABLE_MASK_DUMP_SKB_TX | DBG_ENABLE_MASK_DUMP_QOS | DBG_ENABLE_MASK_DUMP_INIT)
#define err(format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ERR) ) printk(KERN_ERR __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 )
#if defined(ENABLE_DEBUG) && ENABLE_DEBUG
#undef dbg
#define dbg(format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DEBUG_PRINT) ) printk(KERN_WARNING __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 )
#else
#if !defined(dbg)
#define dbg(format, arg...)
#endif
#endif
#if defined(ENABLE_ASSERT) && ENABLE_ASSERT
#define ASSERT(cond, format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ASSERT) && !(cond) ) printk(KERN_ERR __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 )
#else
#define ASSERT(cond, format, arg...)
#endif
/*
* Constants
*/
#define DEFAULT_TX_LINK_RATE 3200 // in cells
/*
* ATM Port, QSB Queue, DMA RX/TX Channel Parameters
*/
#define ATM_PORT_NUMBER 2
#define MAX_QUEUE_NUMBER 16
#define OAM_RX_QUEUE 15
#define QSB_RESERVE_TX_QUEUE 0
#define FIRST_QSB_QID 1
#define MAX_PVC_NUMBER (MAX_QUEUE_NUMBER - FIRST_QSB_QID)
#define MAX_RX_DMA_CHANNEL_NUMBER 8
#define MAX_TX_DMA_CHANNEL_NUMBER 16
#define DATA_BUFFER_ALIGNMENT EMA_ALIGNMENT
#define DESC_ALIGNMENT 8
#define DEFAULT_RX_HUNT_BITTH 4
/*
* RX DMA Channel Allocation
*/
#define RX_DMA_CH_OAM 0
#define RX_DMA_CH_AAL 1
#define RX_DMA_CH_TOTAL 2
#define RX_DMA_CH_OAM_DESC_LEN 32
#define RX_DMA_CH_OAM_BUF_SIZE (CELL_SIZE & ~15)
#define RX_DMA_CH_AAL_BUF_SIZE (2048 - 48)
/*
* OAM Constants
*/
#define OAM_HTU_ENTRY_NUMBER 3
#define OAM_F4_SEG_HTU_ENTRY 0
#define OAM_F4_TOT_HTU_ENTRY 1
#define OAM_F5_HTU_ENTRY 2
#define OAM_F4_CELL_ID 0
#define OAM_F5_CELL_ID 15
//#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
// #undef OAM_HTU_ENTRY_NUMBER
// #define OAM_HTU_ENTRY_NUMBER 4
// #define OAM_ARQ_HTU_ENTRY 3
//#endif
/*
* RX Frame Definitions
*/
#define MAX_RX_PACKET_ALIGN_BYTES 3
#define MAX_RX_PACKET_PADDING_BYTES 3
#define RX_INBAND_TRAILER_LENGTH 8
#define MAX_RX_FRAME_EXTRA_BYTES (RX_INBAND_TRAILER_LENGTH + MAX_RX_PACKET_ALIGN_BYTES + MAX_RX_PACKET_PADDING_BYTES)
/*
* TX Frame Definitions
*/
#define MAX_TX_HEADER_ALIGN_BYTES 12
#define MAX_TX_PACKET_ALIGN_BYTES 3
#define MAX_TX_PACKET_PADDING_BYTES 3
#define TX_INBAND_HEADER_LENGTH 8
#define MAX_TX_FRAME_EXTRA_BYTES (TX_INBAND_HEADER_LENGTH + MAX_TX_HEADER_ALIGN_BYTES + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES)
/*
* Cell Constant
*/
#define CELL_SIZE ATM_AAL0_SDU
/*
* ####################################
* Data Type
* ####################################
*/
typedef struct {
unsigned int h;
unsigned int l;
} ppe_u64_t;
struct port {
unsigned int tx_max_cell_rate;
unsigned int tx_current_cell_rate;
struct atm_dev *dev;
};
struct connection {
struct atm_vcc *vcc;
volatile struct tx_descriptor
*tx_desc;
unsigned int tx_desc_pos;
struct sk_buff **tx_skb;
unsigned int aal5_vcc_crc_err; /* number of packets with CRC error */
unsigned int aal5_vcc_oversize_sdu; /* number of packets with oversize error */
unsigned int port;
};
struct atm_priv_data {
unsigned long conn_table;
struct connection conn[MAX_PVC_NUMBER];
volatile struct rx_descriptor
*aal_desc;
unsigned int aal_desc_pos;
volatile struct rx_descriptor
*oam_desc;
unsigned char *oam_buf;
unsigned int oam_desc_pos;
struct port port[ATM_PORT_NUMBER];
unsigned int wrx_pdu; /* successfully received AAL5 packet */
unsigned int wrx_drop_pdu; /* AAL5 packet dropped by driver on RX */
unsigned int wtx_pdu; /* successfully tranmitted AAL5 packet */
unsigned int wtx_err_pdu; /* error AAL5 packet */
unsigned int wtx_drop_pdu; /* AAL5 packet dropped by driver on TX */
ppe_u64_t wrx_total_byte;
ppe_u64_t wtx_total_byte;
unsigned int prev_wrx_total_byte;
unsigned int prev_wtx_total_byte;
void *aal_desc_base;
void *oam_desc_base;
void *oam_buf_base;
void *tx_desc_base;
void *tx_skb_base;
};
/*
* ####################################
* Declaration
* ####################################
*/
extern unsigned int ifx_atm_dbg_enable;
extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor);
extern void ifx_atm_init_chip(void);
extern void ifx_atm_uninit_chip(void);
extern int ifx_pp32_start(int pp32);
extern void ifx_pp32_stop(int pp32);
#endif // IFXMIPS_ATM_CORE_H

View file

@ -0,0 +1,272 @@
/******************************************************************************
**
** FILE NAME : ifxmips_atm_danube.c
** PROJECT : UEIP
** MODULES : ATM
**
** DATE : 7 Jul 2009
** AUTHOR : Xu Liang
** DESCRIPTION : ATM driver common source file (core functions)
** COPYRIGHT : Copyright (c) 2006
** Infineon Technologies AG
** Am Campeon 1-12, 85579 Neubiberg, Germany
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** HISTORY
** $Date $Author $Comment
** 07 JUL 2009 Xu Liang Init Version
*******************************************************************************/
/*
* ####################################
* Head File
* ####################################
*/
/*
* Common Head File
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <asm/delay.h>
/*
* Chip Specific Head File
*/
#include <asm/ifx/ifx_types.h>
#include <asm/ifx/ifx_regs.h>
#include <asm/ifx/common_routines.h>
#include <asm/ifx/ifx_pmu.h>
#include "ifxmips_atm_core.h"
#include "ifxmips_atm_fw_danube.h"
/*
* ####################################
* Definition
* ####################################
*/
/*
* EMA Settings
*/
#define EMA_CMD_BUF_LEN 0x0040
#define EMA_CMD_BASE_ADDR (0x00001580 << 2)
#define EMA_DATA_BUF_LEN 0x0100
#define EMA_DATA_BASE_ADDR (0x00001900 << 2)
#define EMA_WRITE_BURST 0x2
#define EMA_READ_BURST 0x2
/*
* ####################################
* Declaration
* ####################################
*/
/*
* Hardware Init/Uninit Functions
*/
static inline void init_pmu(void);
static inline void uninit_pmu(void);
static inline void init_ema(void);
static inline void init_mailbox(void);
static inline void init_atm_tc(void);
static inline void clear_share_buffer(void);
/*
* ####################################
* Local Variable
* ####################################
*/
/*
* ####################################
* Local Function
* ####################################
*/
static inline void init_pmu(void)
{
//*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9));
PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE);
PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE);
PPE_TC_PMU_SETUP(IFX_PMU_ENABLE);
PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE);
PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE);
PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE);
DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);
}
static inline void uninit_pmu(void)
{
PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE);
PPE_TC_PMU_SETUP(IFX_PMU_DISABLE);
PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE);
PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE);
PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE);
DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);
PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE);
}
static inline void init_ema(void)
{
IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG);
IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG);
IFX_REG_W32(0x000000FF, EMA_IER);
IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG);
}
static inline void init_mailbox(void)
{
IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC);
IFX_REG_W32(0x00000000, MBOX_IGU1_IER);
IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC);
IFX_REG_W32(0x00000000, MBOX_IGU3_IER);
}
static inline void init_atm_tc(void)
{
// for ReTX expansion in future
//*FFSM_CFG0 = SET_BITS(*FFSM_CFG0, 5, 0, 6); // pnum = 6
//*FFSM_CFG1 = SET_BITS(*FFSM_CFG1, 5, 0, 6); // pnum = 6
}
static inline void clear_share_buffer(void)
{
volatile u32 *p = SB_RAM0_ADDR(0);
unsigned int i;
for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ )
IFX_REG_W32(0, p++);
}
/*
* Description:
* Download PPE firmware binary code.
* Input:
* src --- u32 *, binary code buffer
* dword_len --- unsigned int, binary code length in DWORD (32-bit)
* Output:
* int --- IFX_SUCCESS: Success
* else: Error Code
*/
static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len)
{
volatile u32 *dest;
if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0
|| data_src == 0 || ((unsigned long)data_src & 0x03) != 0 )
return IFX_ERROR;
if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) )
IFX_REG_W32(0x00, CDM_CFG);
else
IFX_REG_W32(0x02, CDM_CFG);
/* copy code */
dest = CDM_CODE_MEMORY(0, 0);
while ( code_dword_len-- > 0 )
IFX_REG_W32(*code_src++, dest++);
/* copy data */
dest = CDM_DATA_MEMORY(0, 0);
while ( data_dword_len-- > 0 )
IFX_REG_W32(*data_src++, dest++);
return IFX_SUCCESS;
}
/*
* ####################################
* Global Function
* ####################################
*/
extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor)
{
ASSERT(major != NULL, "pointer is NULL");
ASSERT(minor != NULL, "pointer is NULL");
*major = ATM_FW_VER_MAJOR;
*minor = ATM_FW_VER_MINOR;
}
void ifx_atm_init_chip(void)
{
init_pmu();
init_ema();
init_mailbox();
init_atm_tc();
clear_share_buffer();
}
void ifx_atm_uninit_chip(void)
{
uninit_pmu();
}
/*
* Description:
* Initialize and start up PP32.
* Input:
* none
* Output:
* int --- IFX_SUCCESS: Success
* else: Error Code
*/
int ifx_pp32_start(int pp32)
{
int ret;
/* download firmware */
ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data));
if ( ret != IFX_SUCCESS )
return ret;
/* run PP32 */
IFX_REG_W32(DBG_CTRL_START_SET(1), PP32_DBG_CTRL);
/* idle for a while to let PP32 init itself */
udelay(10);
return IFX_SUCCESS;
}
/*
* Description:
* Halt PP32.
* Input:
* none
* Output:
* none
*/
void ifx_pp32_stop(int pp32)
{
/* halt PP32 */
IFX_REG_W32(DBG_CTRL_STOP_SET(1), PP32_DBG_CTRL);
}

View file

@ -1,10 +1,10 @@
#ifndef __DANUBE_PPE_FW_H__2005_08_04__12_00__
#define __DANUBE_PPE_FW_H__2005_08_04__12_00__
#ifndef IFXMIPS_ATM_FW_DANUBE_H
#define IFXMIPS_ATM_FW_DANUBE_H
/******************************************************************************
**
** FILE NAME : danube_ppe_fw.h
** FILE NAME : ifxmips_atm_fw_danube.h
** PROJECT : Danube
** MODULES : ATM (ADSL)
**
@ -27,7 +27,11 @@
*******************************************************************************/
static u32 firmware_binary_code[] = {
#define ATM_FW_VER_MAJOR 0
#define ATM_FW_VER_MINOR 1
static unsigned int firmware_binary_code[] = {
0x800004A0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFC8, 0x00000000, 0x00000000, 0x00000000,
0xC1000002, 0xD90C0000, 0xC2000002, 0xDA080001, 0x80004710, 0xC2000000, 0xDA080001, 0x80003D98,
@ -418,9 +422,8 @@ static u32 firmware_binary_code[] = {
0x00000000,
};
static u32 firmware_binary_data[] = {
static unsigned int firmware_binary_data[] = {
};
#endif // __DANUBE_PPE_FW_H__2005_08_04__12_00__
#endif // IFXMIPS_ATM_FW_DANUBE_H

View file

@ -0,0 +1,364 @@
#ifndef IFXMIPS_ATM_FW_REGS_COMMON_H
#define IFXMIPS_ATM_FW_REGS_COMMON_H
#if defined(CONFIG_DANUBE)
#include "ifxmips_atm_fw_regs_danube.h"
#elif defined(CONFIG_AMAZON_SE)
#include "ifxmips_atm_fw_regs_amazon_se.h"
#elif defined(CONFIG_AR9)
#include "ifxmips_atm_fw_regs_ar9.h"
#elif defined(CONFIG_VR9)
#include "ifxmips_atm_fw_regs_vr9.h"
#else
#error Platform is not specified!
#endif
/*
* PPE ATM Cell Header
*/
#if defined(__BIG_ENDIAN)
struct uni_cell_header {
unsigned int gfc :4;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int clp :1;
};
#else
struct uni_cell_header {
unsigned int clp :1;
unsigned int pti :3;
unsigned int vci :16;
unsigned int vpi :8;
unsigned int gfc :4;
};
#endif // defined(__BIG_ENDIAN)
/*
* Inband Header and Trailer
*/
#if defined(__BIG_ENDIAN)
struct rx_inband_trailer {
/* 0 - 3h */
unsigned int uu :8;
unsigned int cpi :8;
unsigned int stw_res1:4;
unsigned int stw_clp :1;
unsigned int stw_ec :1;
unsigned int stw_uu :1;
unsigned int stw_cpi :1;
unsigned int stw_ovz :1;
unsigned int stw_mfl :1;
unsigned int stw_usz :1;
unsigned int stw_crc :1;
unsigned int stw_il :1;
unsigned int stw_ra :1;
unsigned int stw_res2:2;
/* 4 - 7h */
unsigned int gfc :4;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int clp :1;
};
struct tx_inband_header {
/* 0 - 3h */
unsigned int gfc :4;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int clp :1;
/* 4 - 7h */
unsigned int uu :8;
unsigned int cpi :8;
unsigned int pad :8;
unsigned int res1 :8;
};
#else
struct rx_inband_trailer {
/* 0 - 3h */
unsigned int stw_res2:2;
unsigned int stw_ra :1;
unsigned int stw_il :1;
unsigned int stw_crc :1;
unsigned int stw_usz :1;
unsigned int stw_mfl :1;
unsigned int stw_ovz :1;
unsigned int stw_cpi :1;
unsigned int stw_uu :1;
unsigned int stw_ec :1;
unsigned int stw_clp :1;
unsigned int stw_res1:4;
unsigned int cpi :8;
unsigned int uu :8;
/* 4 - 7h */
unsigned int clp :1;
unsigned int pti :3;
unsigned int vci :16;
unsigned int vpi :8;
unsigned int gfc :4;
};
struct tx_inband_header {
/* 0 - 3h */
unsigned int clp :1;
unsigned int pti :3;
unsigned int vci :16;
unsigned int vpi :8;
unsigned int gfc :4;
/* 4 - 7h */
unsigned int res1 :8;
unsigned int pad :8;
unsigned int cpi :8;
unsigned int uu :8;
};
#endif // defined(__BIG_ENDIAN)
/*
* MIB Table Maintained by Firmware
*/
struct wan_mib_table {
u32 res1;
u32 wrx_drophtu_cell;
u32 wrx_dropdes_pdu;
u32 wrx_correct_pdu;
u32 wrx_err_pdu;
u32 wrx_dropdes_cell;
u32 wrx_correct_cell;
u32 wrx_err_cell;
u32 wrx_total_byte;
u32 res2;
u32 wtx_total_pdu;
u32 wtx_total_cell;
u32 wtx_total_byte;
};
/*
* Host-PPE Communication Data Structure
*/
#if defined(__BIG_ENDIAN)
struct wrx_queue_config {
/* 0h */
unsigned int res2 :27;
unsigned int dmach :4;
unsigned int errdp :1;
/* 1h */
unsigned int oversize :16;
unsigned int undersize :16;
/* 2h */
unsigned int res1 :16;
unsigned int mfs :16;
/* 3h */
unsigned int uumask :8;
unsigned int cpimask :8;
unsigned int uuexp :8;
unsigned int cpiexp :8;
};
struct wtx_port_config {
unsigned int res1 :27;
unsigned int qid :4;
unsigned int qsben :1;
};
struct wtx_queue_config {
unsigned int res1 :25;
unsigned int sbid :1;
unsigned int res2 :3;
unsigned int type :2;
unsigned int qsben :1;
};
struct wrx_dma_channel_config {
/* 0h */
unsigned int res1 :1;
unsigned int mode :2;
unsigned int rlcfg :1;
unsigned int desba :28;
/* 1h */
unsigned int chrl :16;
unsigned int clp1th :16;
/* 2h */
unsigned int deslen :16;
unsigned int vlddes :16;
};
struct wtx_dma_channel_config {
/* 0h */
unsigned int res2 :1;
unsigned int mode :2;
unsigned int res3 :1;
unsigned int desba :28;
/* 1h */
unsigned int res1 :32;
/* 2h */
unsigned int deslen :16;
unsigned int vlddes :16;
};
struct htu_entry {
unsigned int res1 :1;
unsigned int clp :1;
unsigned int pid :2;
unsigned int vpi :8;
unsigned int vci :16;
unsigned int pti :3;
unsigned int vld :1;
};
struct htu_mask {
unsigned int set :1;
unsigned int clp :1;
unsigned int pid_mask :2;
unsigned int vpi_mask :8;
unsigned int vci_mask :16;
unsigned int pti_mask :3;
unsigned int clear :1;
};
struct htu_result {
unsigned int res1 :12;
unsigned int cellid :4;
unsigned int res2 :5;
unsigned int type :1;
unsigned int ven :1;
unsigned int res3 :5;
unsigned int qid :4;
};
struct rx_descriptor {
/* 0 - 3h */
unsigned int own :1;
unsigned int c :1;
unsigned int sop :1;
unsigned int eop :1;
unsigned int res1 :3;
unsigned int byteoff :2;
unsigned int res2 :2;
unsigned int id :4;
unsigned int err :1;
unsigned int datalen :16;
/* 4 - 7h */
unsigned int res3 :4;
unsigned int dataptr :28;
};
struct tx_descriptor {
/* 0 - 3h */
unsigned int own :1;
unsigned int c :1;
unsigned int sop :1;
unsigned int eop :1;
unsigned int byteoff :5;
unsigned int res1 :5;
unsigned int iscell :1;
unsigned int clp :1;
unsigned int datalen :16;
/* 4 - 7h */
unsigned int res2 :4;
unsigned int dataptr :28;
};
#else
struct wrx_queue_config {
/* 0h */
unsigned int errdp :1;
unsigned int dmach :4;
unsigned int res2 :27;
/* 1h */
unsigned int undersize :16;
unsigned int oversize :16;
/* 2h */
unsigned int mfs :16;
unsigned int res1 :16;
/* 3h */
unsigned int cpiexp :8;
unsigned int uuexp :8;
unsigned int cpimask :8;
unsigned int uumask :8;
};
struct wtx_port_config {
unsigned int qsben :1;
unsigned int qid :4;
unsigned int res1 :27;
};
struct wtx_queue_config {
unsigned int qsben :1;
unsigned int type :2;
unsigned int res2 :3;
unsigned int sbid :1;
unsigned int res1 :25;
};
struct wrx_dma_channel_config
{
/* 0h */
unsigned int desba :28;
unsigned int rlcfg :1;
unsigned int mode :2;
unsigned int res1 :1;
/* 1h */
unsigned int clp1th :16;
unsigned int chrl :16;
/* 2h */
unsigned int vlddes :16;
unsigned int deslen :16;
};
struct wtx_dma_channel_config {
/* 0h */
unsigned int desba :28;
unsigned int res3 :1;
unsigned int mode :2;
unsigned int res2 :1;
/* 1h */
unsigned int res1 :32;
/* 2h */
unsigned int vlddes :16;
unsigned int deslen :16;
};
struct rx_descriptor {
/* 4 - 7h */
unsigned int dataptr :28;
unsigned int res3 :4;
/* 0 - 3h */
unsigned int datalen :16;
unsigned int err :1;
unsigned int id :4;
unsigned int res2 :2;
unsigned int byteoff :2;
unsigned int res1 :3;
unsigned int eop :1;
unsigned int sop :1;
unsigned int c :1;
unsigned int own :1;
};
struct tx_descriptor {
/* 4 - 7h */
unsigned int dataptr :28;
unsigned int res2 :4;
/* 0 - 3h */
unsigned int datalen :16;
unsigned int clp :1;
unsigned int iscell :1;
unsigned int res1 :5;
unsigned int byteoff :5;
unsigned int eop :1;
unsigned int sop :1;
unsigned int c :1;
unsigned int own :1;
};
#endif // defined(__BIG_ENDIAN)
#endif // IFXMIPS_ATM_FW_REGS_COMMON_H

View file

@ -0,0 +1,30 @@
#ifndef IFXMIPS_ATM_FW_REGS_DANUBE_H
#define IFXMIPS_ATM_FW_REGS_DANUBE_H
/*
* Host-PPE Communication Data Address Mapping
*/
#define FW_VER_ID SB_BUFFER(0x2001)
#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */
#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */
#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */
#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */
#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */
#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */
#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */
#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */
#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20))
#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7))
#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i)))
#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x2710 + (i) * 27))
#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x2711 + (i) * 27))
#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410))
#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2000 + (i)))
#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2020 + (i)))
#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2040 + (i)))
#endif // IFXMIPS_ATM_FW_REGS_DANUBE_H

View file

@ -0,0 +1,231 @@
#ifndef IFXMIPS_ATM_PPE_COMMON_H
#define IFXMIPS_ATM_PPE_COMMON_H
#if defined(CONFIG_DANUBE)
#include "ifxmips_atm_ppe_danube.h"
#elif defined(CONFIG_AMAZON_SE)
#include "ifxmips_atm_ppe_amazon_se.h"
#elif defined(CONFIG_AR9)
#include "ifxmips_atm_ppe_ar9.h"
#elif defined(CONFIG_VR9)
#include "ifxmips_atm_ppe_vr9.h"
#else
#error Platform is not specified!
#endif
/*
* Code/Data Memory (CDM) Interface Configuration Register
*/
#define CDM_CFG PPE_REG_ADDR(0x0100)
#define CDM_CFG_RAM1 GET_BITS(*CDM_CFG, 3, 2)
#define CDM_CFG_RAM0 (*CDM_CFG & (1 << 1))
#define CDM_CFG_RAM1_SET(value) SET_BITS(0, 3, 2, value)
#define CDM_CFG_RAM0_SET(value) ((value) ? (1 << 1) : 0)
/*
* QSB Internal Cell Delay Variation Register
*/
#define QSB_ICDV QSB_CONF_REG_ADDR(0x0007)
#define QSB_ICDV_TAU GET_BITS(*QSB_ICDV, 5, 0)
#define QSB_ICDV_TAU_SET(value) SET_BITS(0, 5, 0, value)
/*
* QSB Scheduler Burst Limit Register
*/
#define QSB_SBL QSB_CONF_REG_ADDR(0x0009)
#define QSB_SBL_SBL GET_BITS(*QSB_SBL, 3, 0)
#define QSB_SBL_SBL_SET(value) SET_BITS(0, 3, 0, value)
/*
* QSB Configuration Register
*/
#define QSB_CFG QSB_CONF_REG_ADDR(0x000A)
#define QSB_CFG_TSTEPC GET_BITS(*QSB_CFG, 1, 0)
#define QSB_CFG_TSTEPC_SET(value) SET_BITS(0, 1, 0, value)
/*
* QSB RAM Transfer Table Register
*/
#define QSB_RTM QSB_CONF_REG_ADDR(0x000B)
#define QSB_RTM_DM (*QSB_RTM)
#define QSB_RTM_DM_SET(value) ((value) & 0xFFFFFFFF)
/*
* QSB RAM Transfer Data Register
*/
#define QSB_RTD QSB_CONF_REG_ADDR(0x000C)
#define QSB_RTD_TTV (*QSB_RTD)
#define QSB_RTD_TTV_SET(value) ((value) & 0xFFFFFFFF)
/*
* QSB RAM Access Register
*/
#define QSB_RAMAC QSB_CONF_REG_ADDR(0x000D)
#define QSB_RAMAC_RW (*QSB_RAMAC & (1 << 31))
#define QSB_RAMAC_TSEL GET_BITS(*QSB_RAMAC, 27, 24)
#define QSB_RAMAC_LH (*QSB_RAMAC & (1 << 16))
#define QSB_RAMAC_TESEL GET_BITS(*QSB_RAMAC, 9, 0)
#define QSB_RAMAC_RW_SET(value) ((value) ? (1 << 31) : 0)
#define QSB_RAMAC_TSEL_SET(value) SET_BITS(0, 27, 24, value)
#define QSB_RAMAC_LH_SET(value) ((value) ? (1 << 16) : 0)
#define QSB_RAMAC_TESEL_SET(value) SET_BITS(0, 9, 0, value)
/*
* QSB Queue Scheduling and Shaping Definitions
*/
#define QSB_WFQ_NONUBR_MAX 0x3f00
#define QSB_WFQ_UBR_BYPASS 0x3fff
#define QSB_TP_TS_MAX 65472
#define QSB_TAUS_MAX 64512
#define QSB_GCR_MIN 18
/*
* QSB Constant
*/
#define QSB_RAMAC_RW_READ 0
#define QSB_RAMAC_RW_WRITE 1
#define QSB_RAMAC_TSEL_QPT 0x01
#define QSB_RAMAC_TSEL_SCT 0x02
#define QSB_RAMAC_TSEL_SPT 0x03
#define QSB_RAMAC_TSEL_VBR 0x08
#define QSB_RAMAC_LH_LOW 0
#define QSB_RAMAC_LH_HIGH 1
#define QSB_QPT_SET_MASK 0x0
#define QSB_QVPT_SET_MASK 0x0
#define QSB_SET_SCT_MASK 0x0
#define QSB_SET_SPT_MASK 0x0
#define QSB_SET_SPT_SBVALID_MASK 0x7FFFFFFF
#define QSB_SPT_SBV_VALID (1 << 31)
#define QSB_SPT_PN_SET(value) (((value) & 0x01) ? (1 << 16) : 0)
#define QSB_SPT_INTRATE_SET(value) SET_BITS(0, 13, 0, value)
/*
* QSB Queue Parameter Table Entry and Queue VBR Parameter Table Entry
*/
#if defined(__BIG_ENDIAN)
union qsb_queue_parameter_table {
struct {
unsigned int res1 :1;
unsigned int vbr :1;
unsigned int wfqf :14;
unsigned int tp :16;
} bit;
u32 dword;
};
union qsb_queue_vbr_parameter_table {
struct {
unsigned int taus :16;
unsigned int ts :16;
} bit;
u32 dword;
};
#else
union qsb_queue_parameter_table {
struct {
unsigned int tp :16;
unsigned int wfqf :14;
unsigned int vbr :1;
unsigned int res1 :1;
} bit;
u32 dword;
};
union qsb_queue_vbr_parameter_table {
struct {
unsigned int ts :16;
unsigned int taus :16;
} bit;
u32 dword;
};
#endif // defined(__BIG_ENDIAN)
/*
* Mailbox IGU0 Registers
*/
#define MBOX_IGU0_ISRS PPE_REG_ADDR(0x0200)
#define MBOX_IGU0_ISRC PPE_REG_ADDR(0x0201)
#define MBOX_IGU0_ISR PPE_REG_ADDR(0x0202)
#define MBOX_IGU0_IER PPE_REG_ADDR(0x0203)
#define MBOX_IGU0_ISRS_SET(n) (1 << (n))
#define MBOX_IGU0_ISRC_CLEAR(n) (1 << (n))
#define MBOX_IGU0_ISR_ISR(n) (*MBOX_IGU0_ISR & (1 << (n)))
#define MBOX_IGU0_IER_EN(n) (*MBOX_IGU0_IER & (1 << (n)))
#define MBOX_IGU0_IER_EN_SET(n) (1 << (n))
/*
* Mailbox IGU1 Registers
*/
#define MBOX_IGU1_ISRS PPE_REG_ADDR(0x0204)
#define MBOX_IGU1_ISRC PPE_REG_ADDR(0x0205)
#define MBOX_IGU1_ISR PPE_REG_ADDR(0x0206)
#define MBOX_IGU1_IER PPE_REG_ADDR(0x0207)
#define MBOX_IGU1_ISRS_SET(n) (1 << (n))
#define MBOX_IGU1_ISRC_CLEAR(n) (1 << (n))
#define MBOX_IGU1_ISR_ISR(n) (*MBOX_IGU1_ISR & (1 << (n)))
#define MBOX_IGU1_IER_EN(n) (*MBOX_IGU1_IER & (1 << (n)))
#define MBOX_IGU1_IER_EN_SET(n) (1 << (n))
/*
* Mailbox IGU3 Registers
*/
#define MBOX_IGU3_ISRS PPE_REG_ADDR(0x0214)
#define MBOX_IGU3_ISRC PPE_REG_ADDR(0x0215)
#define MBOX_IGU3_ISR PPE_REG_ADDR(0x0216)
#define MBOX_IGU3_IER PPE_REG_ADDR(0x0217)
#define MBOX_IGU3_ISRS_SET(n) (1 << (n))
#define MBOX_IGU3_ISRC_CLEAR(n) (1 << (n))
#define MBOX_IGU3_ISR_ISR(n) (*MBOX_IGU3_ISR & (1 << (n)))
#define MBOX_IGU3_IER_EN(n) (*MBOX_IGU3_IER & (1 << (n)))
#define MBOX_IGU3_IER_EN_SET(n) (1 << (n))
/*
* RTHA/TTHA Registers
*/
#define SFSM_STATE0 PPE_REG_ADDR(0x0410)
#define SFSM_STATE1 PPE_REG_ADDR(0x0411)
#define SFSM_DBA0 PPE_REG_ADDR(0x0412)
#define SFSM_DBA1 PPE_REG_ADDR(0x0413)
#define SFSM_CBA0 PPE_REG_ADDR(0x0414)
#define SFSM_CBA1 PPE_REG_ADDR(0x0415)
#define SFSM_CFG0 PPE_REG_ADDR(0x0416)
#define SFSM_CFG1 PPE_REG_ADDR(0x0417)
#define SFSM_PGCNT0 PPE_REG_ADDR(0x041C)
#define SFSM_PGCNT1 PPE_REG_ADDR(0x041D)
#define FFSM_DBA0 PPE_REG_ADDR(0x0508)
#define FFSM_DBA1 PPE_REG_ADDR(0x0509)
#define FFSM_CFG0 PPE_REG_ADDR(0x050A)
#define FFSM_CFG1 PPE_REG_ADDR(0x050B)
#define FFSM_IDLE_HEAD_BC0 PPE_REG_ADDR(0x050E)
#define FFSM_IDLE_HEAD_BC1 PPE_REG_ADDR(0x050F)
#define FFSM_PGCNT0 PPE_REG_ADDR(0x0514)
#define FFSM_PGCNT1 PPE_REG_ADDR(0x0515)
#endif // IFXMIPS_ATM_PPE_COMMON_H

View file

@ -0,0 +1,100 @@
#ifndef IFXMIPS_ATM_PPE_DANUBE_H
#define IFXMIPS_ATM_PPE_DANUBE_H
/*
* FPI Configuration Bus Register and Memory Address Mapping
*/
#define IFX_PPE (KSEG1 | 0x1E180000)
#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2)))
#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2)))
#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2)))
#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2)))
#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2)))
#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2)))
#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2)))
#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2)))
#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2)))
#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2)))
#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2)))
#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8000) << 2)))
#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8400) << 2)))
#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8C00) << 2)))
#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9600) << 2)))
#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2)))
/*
* DWORD-Length of Memory Blocks
*/
#define PP32_DEBUG_REG_DWLEN 0x0030
#define PPM_INT_REG_DWLEN 0x0010
#define PP32_INTERNAL_RES_DWLEN 0x00C0
#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800)
#define PPE_REG_DWLEN 0x1000
#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1)
#define PPM_INT_UNIT_DWLEN 0x0100
#define PPM_TIMER0_DWLEN 0x0100
#define PPM_TASK_IND_REG_DWLEN 0x0100
#define PPS_BRK_DWLEN 0x0100
#define PPM_TIMER1_DWLEN 0x0100
#define SB_RAM0_DWLEN 0x0400
#define SB_RAM1_DWLEN 0x0800
#define SB_RAM2_DWLEN 0x0A00
#define SB_RAM3_DWLEN 0x0400
#define QSB_CONF_REG_DWLEN 0x0100
/*
* PP32 to FPI Address Mapping
*/
#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x23FF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \
(((__sb_addr) >= 0x2400) && ((__sb_addr) <= 0x2BFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2400) : \
(((__sb_addr) >= 0x2C00) && ((__sb_addr) <= 0x35FF)) ? SB_RAM2_ADDR((__sb_addr) - 0x2C00) : \
(((__sb_addr) >= 0x3600) && ((__sb_addr) <= 0x39FF)) ? SB_RAM3_ADDR((__sb_addr) - 0x3600) : \
0))
/*
* PP32 Debug Control Register
*/
#define PP32_DBG_CTRL PP32_DEBUG_REG_ADDR(0, 0x0000)
#define DBG_CTRL_START_SET(value) ((value) ? (1 << 0) : 0)
#define DBG_CTRL_STOP_SET(value) ((value) ? (1 << 1) : 0)
#define DBG_CTRL_STEP_SET(value) ((value) ? (1 << 2) : 0)
#define PP32_HALT_STAT PP32_DEBUG_REG_ADDR(0, 0x0001)
#define PP32_BRK_SRC PP32_DEBUG_REG_ADDR(0, 0x0002)
#define PP32_DBG_PC_MIN(i) PP32_DEBUG_REG_ADDR(0, 0x0010 + (i))
#define PP32_DBG_PC_MAX(i) PP32_DEBUG_REG_ADDR(0, 0x0014 + (i))
#define PP32_DBG_DATA_MIN(i) PP32_DEBUG_REG_ADDR(0, 0x0018 + (i))
#define PP32_DBG_DATA_MAX(i) PP32_DEBUG_REG_ADDR(0, 0x001A + (i))
#define PP32_DBG_DATA_VAL(i) PP32_DEBUG_REG_ADDR(0, 0x001C + (i))
#define PP32_DBG_CUR_PC PP32_DEBUG_REG_ADDR(0, 0x0080)
#define PP32_DBG_TASK_NO PP32_DEBUG_REG_ADDR(0, 0x0081)
/*
* EMA Registers
*/
#define EMA_CMDCFG PPE_REG_ADDR(0x0A00)
#define EMA_DATACFG PPE_REG_ADDR(0x0A01)
#define EMA_CMDCNT PPE_REG_ADDR(0x0A02)
#define EMA_DATACNT PPE_REG_ADDR(0x0A03)
#define EMA_ISR PPE_REG_ADDR(0x0A04)
#define EMA_IER PPE_REG_ADDR(0x0A05)
#define EMA_CFG PPE_REG_ADDR(0x0A06)
#define EMA_SUBID PPE_REG_ADDR(0x0A07)
#define EMA_ALIGNMENT 4
/*
* Mailbox IGU1 Interrupt
*/
#define PPE_MAILBOX_IGU1_INT INT_NUM_IM2_IRL24
#endif // IFXMIPS_ATM_PPE_DANUBE_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,700 @@
/******************************************************************************
Copyright (c) 2009
Infineon Technologies AG
Am Campeon 1-12; 81726 Munich, Germany
For licensing information, see the file 'LICENSE' in the root folder of
this software module.
******************************************************************************/
#ifndef IFXMIPS_MEI_H
#define IFXMIPS_MEI_H
#define CONFIG_DANUBE 1
#if !defined(CONFIG_DANUBE) && !defined(CONFIG_AMAZON_SE) && !defined(CONFIG_AR9) && !defined(CONFIG_VR9)
#error Platform undefined!!!
#endif
#ifdef IFX_MEI_BSP
/** This is the character datatype. */
typedef char DSL_char_t;
/** This is the unsigned 8-bit datatype. */
typedef unsigned char DSL_uint8_t;
/** This is the signed 8-bit datatype. */
typedef signed char DSL_int8_t;
/** This is the unsigned 16-bit datatype. */
typedef unsigned short DSL_uint16_t;
/** This is the signed 16-bit datatype. */
typedef signed short DSL_int16_t;
/** This is the unsigned 32-bit datatype. */
typedef unsigned long DSL_uint32_t;
/** This is the signed 32-bit datatype. */
typedef signed long DSL_int32_t;
/** This is the float datatype. */
typedef float DSL_float_t;
/** This is the void datatype. */
typedef void DSL_void_t;
/** integer type, width is depending on processor arch */
typedef int DSL_int_t;
/** unsigned integer type, width is depending on processor arch */
typedef unsigned int DSL_uint_t;
typedef struct file DSL_DRV_file_t;
typedef struct inode DSL_DRV_inode_t;
/**
* Defines all possible CMV groups
* */
typedef enum {
DSL_CMV_GROUP_CNTL = 1,
DSL_CMV_GROUP_STAT = 2,
DSL_CMV_GROUP_INFO = 3,
DSL_CMV_GROUP_TEST = 4,
DSL_CMV_GROUP_OPTN = 5,
DSL_CMV_GROUP_RATE = 6,
DSL_CMV_GROUP_PLAM = 7,
DSL_CMV_GROUP_CNFG = 8
} DSL_CmvGroup_t;
/**
* Defines all opcode types
* */
typedef enum {
H2D_CMV_READ = 0x00,
H2D_CMV_WRITE = 0x04,
H2D_CMV_INDICATE_REPLY = 0x10,
H2D_ERROR_OPCODE_UNKNOWN =0x20,
H2D_ERROR_CMV_UNKNOWN =0x30,
D2H_CMV_READ_REPLY =0x01,
D2H_CMV_WRITE_REPLY = 0x05,
D2H_CMV_INDICATE = 0x11,
D2H_ERROR_OPCODE_UNKNOWN = 0x21,
D2H_ERROR_CMV_UNKNOWN = 0x31,
D2H_ERROR_CMV_READ_NOT_AVAILABLE = 0x41,
D2H_ERROR_CMV_WRITE_ONLY = 0x51,
D2H_ERROR_CMV_READ_ONLY = 0x61,
H2D_DEBUG_READ_DM = 0x02,
H2D_DEBUG_READ_PM = 0x06,
H2D_DEBUG_WRITE_DM = 0x0a,
H2D_DEBUG_WRITE_PM = 0x0e,
D2H_DEBUG_READ_DM_REPLY = 0x03,
D2H_DEBUG_READ_FM_REPLY = 0x07,
D2H_DEBUG_WRITE_DM_REPLY = 0x0b,
D2H_DEBUG_WRITE_FM_REPLY = 0x0f,
D2H_ERROR_ADDR_UNKNOWN = 0x33,
D2H_AUTONOMOUS_MODEM_READY_MSG = 0xf1
} DSL_CmvOpcode_t;
/* mutex macros */
#define MEI_MUTEX_INIT(id,flag) \
sema_init(&id,flag)
#define MEI_MUTEX_LOCK(id) \
down_interruptible(&id)
#define MEI_MUTEX_UNLOCK(id) \
up(&id)
#define MEI_WAIT(ms) \
{\
set_current_state(TASK_INTERRUPTIBLE);\
schedule_timeout(ms);\
}
#define MEI_INIT_WAKELIST(name,queue) \
init_waitqueue_head(&queue)
/* wait for an event, timeout is measured in ms */
#define MEI_WAIT_EVENT_TIMEOUT(ev,timeout)\
interruptible_sleep_on_timeout(&ev,timeout * HZ / 1000)
#define MEI_WAKEUP_EVENT(ev)\
wake_up_interruptible(&ev)
#endif /* IFX_MEI_BSP */
/*** Register address offsets, relative to MEI_SPACE_ADDRESS ***/
#define ME_DX_DATA (0x0000)
#define ME_VERSION (0x0004)
#define ME_ARC_GP_STAT (0x0008)
#define ME_DX_STAT (0x000C)
#define ME_DX_AD (0x0010)
#define ME_DX_MWS (0x0014)
#define ME_ME2ARC_INT (0x0018)
#define ME_ARC2ME_STAT (0x001C)
#define ME_ARC2ME_MASK (0x0020)
#define ME_DBG_WR_AD (0x0024)
#define ME_DBG_RD_AD (0x0028)
#define ME_DBG_DATA (0x002C)
#define ME_DBG_DECODE (0x0030)
#define ME_CONFIG (0x0034)
#define ME_RST_CTRL (0x0038)
#define ME_DBG_MASTER (0x003C)
#define ME_CLK_CTRL (0x0040)
#define ME_BIST_CTRL (0x0044)
#define ME_BIST_STAT (0x0048)
#define ME_XDATA_BASE_SH (0x004c)
#define ME_XDATA_BASE (0x0050)
#define ME_XMEM_BAR_BASE (0x0054)
#define ME_XMEM_BAR0 (0x0054)
#define ME_XMEM_BAR1 (0x0058)
#define ME_XMEM_BAR2 (0x005C)
#define ME_XMEM_BAR3 (0x0060)
#define ME_XMEM_BAR4 (0x0064)
#define ME_XMEM_BAR5 (0x0068)
#define ME_XMEM_BAR6 (0x006C)
#define ME_XMEM_BAR7 (0x0070)
#define ME_XMEM_BAR8 (0x0074)
#define ME_XMEM_BAR9 (0x0078)
#define ME_XMEM_BAR10 (0x007C)
#define ME_XMEM_BAR11 (0x0080)
#define ME_XMEM_BAR12 (0x0084)
#define ME_XMEM_BAR13 (0x0088)
#define ME_XMEM_BAR14 (0x008C)
#define ME_XMEM_BAR15 (0x0090)
#define ME_XMEM_BAR16 (0x0094)
#define WHILE_DELAY 20000
/*
** Define where in ME Processor's memory map the Stratify chip lives
*/
#define MAXSWAPSIZE (8 * 1024) //8k *(32bits)
// Mailboxes
#define MSG_LENGTH 16 // x16 bits
#define YES_REPLY 1
#define NO_REPLY 0
#define CMV_TIMEOUT 1000 //jiffies
// Block size per BAR
#define SDRAM_SEGMENT_SIZE (64*1024)
// Number of Bar registers
#define MAX_BAR_REGISTERS (17)
#define XDATA_REGISTER (15)
// ARC register addresss
#define ARC_STATUS 0x0
#define ARC_LP_START 0x2
#define ARC_LP_END 0x3
#define ARC_DEBUG 0x5
#define ARC_INT_MASK 0x10A
#define IRAM0_BASE (0x00000)
#define IRAM1_BASE (0x04000)
#if defined(CONFIG_DANUBE)
#define BRAM_BASE (0x0A000)
#elif defined(CONFIG_AMAZON_SE) || defined(CONFIG_AR9) || defined(CONFIG_VR9)
#define BRAM_BASE (0x08000)
#endif
#define XRAM_BASE (0x18000)
#define YRAM_BASE (0x1A000)
#define EXT_MEM_BASE (0x80000)
#define ARC_GPIO_CTRL (0xC030)
#define ARC_GPIO_DATA (0xC034)
#define IRAM0_SIZE (16*1024)
#define IRAM1_SIZE (16*1024)
#define BRAM_SIZE (12*1024)
#define XRAM_SIZE (8*1024)
#define YRAM_SIZE (8*1024)
#define EXT_MEM_SIZE (1536*1024)
#define ADSL_BASE (0x20000)
#define CRI_BASE (ADSL_BASE + 0x11F00)
#define CRI_CCR0 (CRI_BASE + 0x00)
#define CRI_RST (CRI_BASE + 0x04*4)
#define ADSL_DILV_BASE (ADSL_BASE+0x20000)
//
#define IRAM0_ADDR_BIT_MASK 0xFFF
#define IRAM1_ADDR_BIT_MASK 0xFFF
#define BRAM_ADDR_BIT_MASK 0xFFF
#define RX_DILV_ADDR_BIT_MASK 0x1FFF
/*** Bit definitions ***/
#define ARC_AUX_HALT (1 << 25)
#define ARC_DEBUG_HALT (1 << 1)
#define FALSE 0
#define TRUE 1
#define BIT0 (1<<0)
#define BIT1 (1<<1)
#define BIT2 (1<<2)
#define BIT3 (1<<3)
#define BIT4 (1<<4)
#define BIT5 (1<<5)
#define BIT6 (1<<6)
#define BIT7 (1<<7)
#define BIT8 (1<<8)
#define BIT9 (1<<9)
#define BIT10 (1<<10)
#define BIT11 (1<<11)
#define BIT12 (1<<12)
#define BIT13 (1<<13)
#define BIT14 (1<<14)
#define BIT15 (1<<15)
#define BIT16 (1<<16)
#define BIT17 (1<<17)
#define BIT18 (1<<18)
#define BIT19 (1<<19)
#define BIT20 (1<<20)
#define BIT21 (1<<21)
#define BIT22 (1<<22)
#define BIT23 (1<<23)
#define BIT24 (1<<24)
#define BIT25 (1<<25)
#define BIT26 (1<<26)
#define BIT27 (1<<27)
#define BIT28 (1<<28)
#define BIT29 (1<<29)
#define BIT30 (1<<30)
#define BIT31 (1<<31)
// CRI_CCR0 Register definitions
#define CLK_2M_MODE_ENABLE BIT6
#define ACL_CLK_MODE_ENABLE BIT4
#define FDF_CLK_MODE_ENABLE BIT2
#define STM_CLK_MODE_ENABLE BIT0
// CRI_RST Register definitions
#define FDF_SRST BIT3
#define MTE_SRST BIT2
#define FCI_SRST BIT1
#define AAI_SRST BIT0
// MEI_TO_ARC_INTERRUPT Register definitions
#define MEI_TO_ARC_INT1 BIT3
#define MEI_TO_ARC_INT0 BIT2
#define MEI_TO_ARC_CS_DONE BIT1 //need to check
#define MEI_TO_ARC_MSGAV BIT0
// ARC_TO_MEI_INTERRUPT Register definitions
#define ARC_TO_MEI_INT1 BIT8
#define ARC_TO_MEI_INT0 BIT7
#define ARC_TO_MEI_CS_REQ BIT6
#define ARC_TO_MEI_DBG_DONE BIT5
#define ARC_TO_MEI_MSGACK BIT4
#define ARC_TO_MEI_NO_ACCESS BIT3
#define ARC_TO_MEI_CHECK_AAITX BIT2
#define ARC_TO_MEI_CHECK_AAIRX BIT1
#define ARC_TO_MEI_MSGAV BIT0
// ARC_TO_MEI_INTERRUPT_MASK Register definitions
#define GP_INT1_EN BIT8
#define GP_INT0_EN BIT7
#define CS_REQ_EN BIT6
#define DBG_DONE_EN BIT5
#define MSGACK_EN BIT4
#define NO_ACC_EN BIT3
#define AAITX_EN BIT2
#define AAIRX_EN BIT1
#define MSGAV_EN BIT0
#define MEI_SOFT_RESET BIT0
#define HOST_MSTR BIT0
#define JTAG_MASTER_MODE 0x0
#define MEI_MASTER_MODE HOST_MSTR
// MEI_DEBUG_DECODE Register definitions
#define MEI_DEBUG_DEC_MASK (0x3)
#define MEI_DEBUG_DEC_AUX_MASK (0x0)
#define ME_DBG_DECODE_DMP1_MASK (0x1)
#define MEI_DEBUG_DEC_DMP2_MASK (0x2)
#define MEI_DEBUG_DEC_CORE_MASK (0x3)
#define AUX_STATUS (0x0)
#define AUX_ARC_GPIO_CTRL (0x10C)
#define AUX_ARC_GPIO_DATA (0x10D)
// ARC_TO_MEI_MAILBOX[11] is a special location used to indicate
// page swap requests.
#if defined(CONFIG_DANUBE)
#define OMBOX_BASE 0xDF80
#define ARC_TO_MEI_MAILBOX 0xDFA0
#define IMBOX_BASE 0xDFC0
#define MEI_TO_ARC_MAILBOX 0xDFD0
#elif defined(CONFIG_AMAZON_SE) || defined(CONFIG_AR9) || defined(CONFIG_VR9)
#define OMBOX_BASE 0xAF80
#define ARC_TO_MEI_MAILBOX 0xAFA0
#define IMBOX_BASE 0xAFC0
#define MEI_TO_ARC_MAILBOX 0xAFD0
#endif
#define MEI_TO_ARC_MAILBOXR (MEI_TO_ARC_MAILBOX + 0x2C)
#define ARC_MEI_MAILBOXR (ARC_TO_MEI_MAILBOX + 0x2C)
#define OMBOX1 (OMBOX_BASE+0x4)
// Codeswap request messages are indicated by setting BIT31
#define OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK (0x80000000)
// Clear Eoc messages received are indicated by setting BIT17
#define OMB_CLEAREOC_INTERRUPT_CODE (0x00020000)
#define OMB_REBOOT_INTERRUPT_CODE (1 << 18)
/*
** Swap page header
*/
// Page must be loaded at boot time if size field has BIT31 set
#define BOOT_FLAG (BIT31)
#define BOOT_FLAG_MASK ~BOOT_FLAG
#define FREE_RELOAD 1
#define FREE_SHOWTIME 2
#define FREE_ALL 3
// marcos
#define IFX_MEI_WRITE_REGISTER_L(data,addr) *((volatile u32*)(addr)) = (u32)(data)
#define IFX_MEI_READ_REGISTER_L(addr) (*((volatile u32*)(addr)))
#define SET_BIT(reg, mask) reg |= (mask)
#define CLEAR_BIT(reg, mask) reg &= (~mask)
#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
//#define SET_BITS(reg, mask) SET_BIT(reg, mask)
#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
#define ALIGN_SIZE ( 1L<<10 ) //1K size align
#define MEM_ALIGN(addr) (((addr) + ALIGN_SIZE - 1) & ~ (ALIGN_SIZE -1) )
// swap marco
#define MEI_HALF_WORD_SWAP(data) {data = ((data & 0xffff)<<16) + ((data & 0xffff0000)>>16);}
#define MEI_BYTE_SWAP(data) {data = ((data & 0xff)<<24) + ((data & 0xff00)<<8)+ ((data & 0xff0000)>>8)+ ((data & 0xff000000)>>24);}
#ifdef CONFIG_PROC_FS
typedef struct reg_entry
{
int *flag;
char name[30]; /* big enough to hold names */
char description[100]; /* big enough to hold description */
unsigned short low_ino;
} reg_entry_t;
#endif
// Swap page header describes size in 32-bit words, load location, and image offset
// for program and/or data segments
typedef struct _arc_swp_page_hdr {
u32 p_offset; //Offset bytes of progseg from beginning of image
u32 p_dest; //Destination addr of progseg on processor
u32 p_size; //Size in 32-bitwords of program segment
u32 d_offset; //Offset bytes of dataseg from beginning of image
u32 d_dest; //Destination addr of dataseg on processor
u32 d_size; //Size in 32-bitwords of data segment
} ARC_SWP_PAGE_HDR;
/*
** Swap image header
*/
#define GET_PROG 0 // Flag used for program mem segment
#define GET_DATA 1 // Flag used for data mem segment
// Image header contains size of image, checksum for image, and count of
// page headers. Following that are 'count' page headers followed by
// the code and/or data segments to be loaded
typedef struct _arc_img_hdr {
u32 size; // Size of binary image in bytes
u32 checksum; // Checksum for image
u32 count; // Count of swp pages in image
ARC_SWP_PAGE_HDR page[1]; // Should be "count" pages - '1' to make compiler happy
} ARC_IMG_HDR;
typedef struct smmu_mem_info {
int type;
int boot;
unsigned long nCopy;
unsigned long size;
unsigned char *address;
unsigned char *org_address;
} smmu_mem_info_t;
#ifdef __KERNEL__
typedef struct ifx_mei_device_private {
int modem_ready;
int arcmsgav;
int cmv_reply;
int cmv_waiting;
// Mei to ARC CMV count, reply count, ARC Indicator count
int modem_ready_cnt;
int cmv_count;
int reply_count;
unsigned long image_size;
int nBar;
u16 Recent_indicator[MSG_LENGTH];
u16 CMV_RxMsg[MSG_LENGTH] __attribute__ ((aligned (4)));
smmu_mem_info_t adsl_mem_info[MAX_BAR_REGISTERS];
ARC_IMG_HDR *img_hdr;
// to wait for arc cmv reply, sleep on wait_queue_arcmsgav;
wait_queue_head_t wait_queue_arcmsgav;
wait_queue_head_t wait_queue_modemready;
struct semaphore mei_cmv_sema;
} ifx_mei_device_private_t;
#endif
typedef struct winhost_message {
union {
u16 RxMessage[MSG_LENGTH] __attribute__ ((aligned (4)));
u16 TxMessage[MSG_LENGTH] __attribute__ ((aligned (4)));
} msg;
} DSL_DEV_WinHost_Message_t;
/********************************************************************************************************
* DSL CPE API Driver Stack Interface Definitions
* *****************************************************************************************************/
/** IOCTL codes for bsp driver */
#define DSL_IOC_MEI_BSP_MAGIC 's'
#define DSL_FIO_BSP_DSL_START _IO (DSL_IOC_MEI_BSP_MAGIC, 0)
#define DSL_FIO_BSP_RUN _IO (DSL_IOC_MEI_BSP_MAGIC, 1)
#define DSL_FIO_BSP_FREE_RESOURCE _IO (DSL_IOC_MEI_BSP_MAGIC, 2)
#define DSL_FIO_BSP_RESET _IO (DSL_IOC_MEI_BSP_MAGIC, 3)
#define DSL_FIO_BSP_REBOOT _IO (DSL_IOC_MEI_BSP_MAGIC, 4)
#define DSL_FIO_BSP_HALT _IO (DSL_IOC_MEI_BSP_MAGIC, 5)
#define DSL_FIO_BSP_BOOTDOWNLOAD _IO (DSL_IOC_MEI_BSP_MAGIC, 6)
#define DSL_FIO_BSP_JTAG_ENABLE _IO (DSL_IOC_MEI_BSP_MAGIC, 7)
#define DSL_FIO_FREE_RESOURCE _IO (DSL_IOC_MEI_BSP_MAGIC, 8)
#define DSL_FIO_ARC_MUX_TEST _IO (DSL_IOC_MEI_BSP_MAGIC, 9)
#define DSL_FIO_BSP_REMOTE _IOW (DSL_IOC_MEI_BSP_MAGIC, 10, u32)
#define DSL_FIO_BSP_GET_BASE_ADDRESS _IOR (DSL_IOC_MEI_BSP_MAGIC, 11, u32)
#define DSL_FIO_BSP_IS_MODEM_READY _IOR (DSL_IOC_MEI_BSP_MAGIC, 12, u32)
#define DSL_FIO_BSP_GET_VERSION _IOR (DSL_IOC_MEI_BSP_MAGIC, 13, DSL_DEV_Version_t)
#define DSL_FIO_BSP_CMV_WINHOST _IOWR(DSL_IOC_MEI_BSP_MAGIC, 14, DSL_DEV_WinHost_Message_t)
#define DSL_FIO_BSP_CMV_READ _IOWR(DSL_IOC_MEI_BSP_MAGIC, 15, DSL_DEV_MeiReg_t)
#define DSL_FIO_BSP_CMV_WRITE _IOW (DSL_IOC_MEI_BSP_MAGIC, 16, DSL_DEV_MeiReg_t)
#define DSL_FIO_BSP_DEBUG_READ _IOWR(DSL_IOC_MEI_BSP_MAGIC, 17, DSL_DEV_MeiDebug_t)
#define DSL_FIO_BSP_DEBUG_WRITE _IOWR(DSL_IOC_MEI_BSP_MAGIC, 18, DSL_DEV_MeiDebug_t)
#define DSL_FIO_BSP_GET_CHIP_INFO _IOR (DSL_IOC_MEI_BSP_MAGIC, 19, DSL_DEV_HwVersion_t)
#define DSL_DEV_MEIDEBUG_BUFFER_SIZES 512
typedef struct DSL_DEV_MeiDebug
{
DSL_uint32_t iAddress;
DSL_uint32_t iCount;
DSL_uint32_t buffer[DSL_DEV_MEIDEBUG_BUFFER_SIZES];
} DSL_DEV_MeiDebug_t; /* meidebug */
/**
* Structure is used for debug access only.
* Refer to configure option INCLUDE_ADSL_WINHOST_DEBUG */
typedef struct struct_meireg
{
/*
* Specifies that address for debug access */
unsigned long iAddress;
/*
* Specifies the pointer to the data that has to be written or returns a
* pointer to the data that has been read out*/
unsigned long iData;
} DSL_DEV_MeiReg_t; /* meireg */
typedef struct DSL_DEV_Device
{
DSL_int_t nInUse; /* modem state, update by bsp driver, */
DSL_void_t *pPriv;
DSL_uint32_t base_address; /* mei base address */
DSL_int_t nIrq[2]; /* irq number */
#define IFX_DFEIR 0
#define IFX_DYING_GASP 1
DSL_DEV_MeiDebug_t lop_debugwr; /* dying gasp */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
struct module *owner;
#endif
} DSL_DEV_Device_t; /* ifx_adsl_device_t */
#define DSL_DEV_PRIVATE(dev) ((ifx_mei_device_private_t*)(dev->pPriv))
typedef struct DSL_DEV_Version /* ifx_adsl_bsp_version */
{
unsigned long major;
unsigned long minor;
unsigned long revision;
} DSL_DEV_Version_t; /* ifx_adsl_bsp_version_t */
typedef struct DSL_DEV_ChipInfo
{
unsigned long major;
unsigned long minor;
} DSL_DEV_HwVersion_t;
typedef struct
{
DSL_uint8_t dummy;
} DSL_DEV_DeviceConfig_t;
/** error code definitions */
typedef enum DSL_DEV_MeiError
{
DSL_DEV_MEI_ERR_SUCCESS = 0,
DSL_DEV_MEI_ERR_FAILURE = -1,
DSL_DEV_MEI_ERR_MAILBOX_FULL = -2,
DSL_DEV_MEI_ERR_MAILBOX_EMPTY = -3,
DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT = -4
} DSL_DEV_MeiError_t; /* MEI_ERROR */
typedef enum {
DSL_BSP_MEMORY_READ=0,
DSL_BSP_MEMORY_WRITE,
} DSL_BSP_MemoryAccessType_t; /* ifx_adsl_memory_access_type_t */
typedef enum
{
DSL_LED_LINK_ID=0,
DSL_LED_DATA_ID
} DSL_DEV_LedId_t; /* ifx_adsl_led_id_t */
typedef enum
{
DSL_LED_LINK_TYPE=0,
DSL_LED_DATA_TYPE
} DSL_DEV_LedType_t; /* ifx_adsl_led_type_t */
typedef enum
{
DSL_LED_HD_CPU=0,
DSL_LED_HD_FW
} DSL_DEV_LedHandler_t; /* ifx_adsl_led_handler_t */
typedef enum {
DSL_LED_ON=0,
DSL_LED_OFF,
DSL_LED_FLASH,
} DSL_DEV_LedMode_t; /* ifx_adsl_led_mode_t */
typedef enum {
DSL_CPU_HALT=0,
DSL_CPU_RUN,
DSL_CPU_RESET,
} DSL_DEV_CpuMode_t; /* ifx_adsl_cpu_mode_t */
#if 0
typedef enum {
DSL_BSP_EVENT_DYING_GASP = 0,
DSL_BSP_EVENT_CEOC_IRQ,
} DSL_BSP_Event_id_t; /* ifx_adsl_event_id_t */
typedef union DSL_BSP_CB_Param
{
DSL_uint32_t nIrqMessage;
} DSL_BSP_CB_Param_t; /* ifx_adsl_cbparam_t */
typedef struct DSL_BSP_CB_Event
{
DSL_BSP_Event_id_t nID;
DSL_DEV_Device_t *pDev;
DSL_BSP_CB_Param_t *pParam;
} DSL_BSP_CB_Event_t; /* ifx_adsl_cb_event_t */
#endif
/* external functions (from the BSP Driver) */
extern DSL_DEV_Device_t* DSL_BSP_DriverHandleGet(int, int);
extern DSL_int_t DSL_BSP_DriverHandleDelete(DSL_DEV_Device_t *);
extern DSL_DEV_MeiError_t DSL_BSP_FWDownload(DSL_DEV_Device_t *, const DSL_char_t *, DSL_uint32_t, DSL_int32_t *, DSL_int32_t *);
extern int DSL_BSP_KernelIoctls(DSL_DEV_Device_t *, unsigned int, unsigned long);
extern DSL_DEV_MeiError_t DSL_BSP_SendCMV(DSL_DEV_Device_t *, DSL_uint16_t *, DSL_int_t, DSL_uint16_t *);
extern DSL_DEV_MeiError_t DSL_BSP_AdslLedInit(DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t);
extern DSL_DEV_MeiError_t DSL_BSP_Showtime(DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t);
extern int DSL_BSP_ATMLedCBRegister( int (*ifx_adsl_ledcallback)(void));
extern DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess(DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t *, DSL_uint32_t);
extern volatile DSL_DEV_Device_t *adsl_dev;
/**
* Dummy structure by now to show mechanism of extended data that will be
* provided within event callback itself.
* */
typedef struct
{
/**
* Dummy value */
DSL_uint32_t nDummy1;
} DSL_BSP_CB_Event1DataDummy_t;
/**
* Dummy structure by now to show mechanism of extended data that will be
* provided within event callback itself.
* */
typedef struct
{
/**
* Dummy value */
DSL_uint32_t nDummy2;
} DSL_BSP_CB_Event2DataDummy_t;
/**
* encapsulate all data structures that are necessary for status event
* callbacks.
* */
typedef union
{
DSL_BSP_CB_Event1DataDummy_t dataEvent1;
DSL_BSP_CB_Event2DataDummy_t dataEvent2;
} DSL_BSP_CB_DATA_Union_t;
typedef enum
{
/**
* Informs the upper layer driver (DSL CPE API) about a reboot request from the
* firmware.
* \note This event does NOT include any additional data.
* More detailed information upon reboot reason has to be requested from
* upper layer software via CMV (INFO 109) if necessary. */
DSL_BSP_CB_FIRST = 0,
DSL_BSP_CB_DYING_GASP,
DSL_BSP_CB_CEOC_IRQ,
DSL_BSP_CB_FIRMWARE_REBOOT,
/**
* Delimiter only */
DSL_BSP_CB_LAST
} DSL_BSP_CB_Type_t;
/**
* Specifies the common event type that has to be used for registering and
* signalling of interrupts/autonomous status events from MEI BSP Driver.
*
* \param pDev
* Context pointer from MEI BSP Driver.
*
* \param IFX_ADSL_BSP_CallbackType_t
* Specifies the event callback type (reason of callback). Regrading to the
* setting of this value the data which is included in the following union
* might have different meanings.
* Please refer to the description of the union to get information about the
* meaning of the included data.
*
* \param pData
* Data according to \ref DSL_BSP_CB_DATA_Union_t.
* If this pointer is NULL there is no additional data available.
*
* \return depending on event
*/
typedef int (*DSL_BSP_EventCallback_t)
(
DSL_DEV_Device_t *pDev,
DSL_BSP_CB_Type_t nCallbackType,
DSL_BSP_CB_DATA_Union_t *pData
);
typedef struct {
DSL_BSP_EventCallback_t function;
DSL_BSP_CB_Type_t event;
DSL_BSP_CB_DATA_Union_t *pData;
} DSL_BSP_EventCallBack_t;
extern int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *);
extern int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *);
/** Modem states */
#define DSL_DEV_STAT_InitState 0x0000
#define DSL_DEV_STAT_ReadyState 0x0001
#define DSL_DEV_STAT_FailState 0x0002
#define DSL_DEV_STAT_IdleState 0x0003
#define DSL_DEV_STAT_QuietState 0x0004
#define DSL_DEV_STAT_GhsState 0x0005
#define DSL_DEV_STAT_FullInitState 0x0006
#define DSL_DEV_STAT_ShowTimeState 0x0007
#define DSL_DEV_STAT_FastRetrainState 0x0008
#define DSL_DEV_STAT_LoopDiagMode 0x0009
#define DSL_DEV_STAT_ShortInit 0x000A /* Bis short initialization */
#define DSL_DEV_STAT_CODESWAP_COMPLETE 0x0002
#endif //IFXMIPS_MEI_H

View file

@ -0,0 +1,84 @@
#
# Copyright (C) 2009 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# ralph / blogic
include $(TOPDIR)/rules.mk
PKG_BASE_NAME:=dsl_cpe_control_danube
PKG_VERSION:=3.24.4.4
PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz
PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION)
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
PKG_MD5SUM:=ee315306626b68794d3d3636dabfe161
include $(INCLUDE_DIR)/package.mk
define Package/ifxmips-dsl-control
SECTION:=application
CATEGORY:=Infineon
TITLE:=DSL CPE control application
URL:=http://www.infineon.com/
MAINTAINER:=Infineon Technologies AG / Lantiq / blogic@openwrt.org
DEPENDS:=+kmod-ifxmips-dsl-api +libpthread
endef
define Package/ifxmips-dsl-control/description
Infineon DSL CPE API for Amazon SE, Danube and Vinax.
This package contains the DSL CPE control application for Amazon SE & Danube.
Supported Devices:
- Amazon SE
- Danube
This package was kindly contributed to openwrt by Infineon/Lantiq
endef
IFX_DSL_MAX_DEVICE=1
IFX_DSL_LINES_PER_DEVICE=1
IFX_DSL_CHANNELS_PER_LINE=1
#CONFIG_IFX_CLI=y
CONFIGURE_ARGS += \
--with-max-device="$(IFX_DSL_MAX_DEVICE)" \
--with-lines-per-device="$(IFX_DSL_LINES_PER_DEVICE)" \
--with-channels-per-line="$(IFX_DSL_CHANNELS_PER_LINE)" \
--enable-danube \
--enable-driver-include="-I$(STAGING_DIR)/usr/include" \
--enable-debug-prints \
--enable-add-appl-cflags="-DMAX_CLI_PIPES=2" \
--enable-cmv-scripts \
--enable-debug-tool-interface \
--enable-adsl-led \
--enable-dsl-ceoc \
--enable-script-notification \
--enable-dsl-pm \
--enable-dsl-pm-total \
--enable-dsl-pm-history \
--enable-dsl-pm-showtime \
--enable-dsl-pm-channel-counters \
--enable-dsl-pm-datapath-counters \
--enable-dsl-pm-line-counters \
--enable-dsl-pm-channel-thresholds \
--enable-dsl-pm-datapath-thresholds \
--enable-dsl-pm-line-thresholds \
--enable-dsl-pm-optional-parameters
ifeq ($(CONFIG_IFX_CLI),y)
CONFIGURE_ARGS += \
--enable-cli-support \
--enable-soap-support
endif
define Package/ifxmips-dsl-control/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/ifx_cpe_control_init.sh $(1)/etc/init.d/
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin
endef
$(eval $(call BuildPackage,ifxmips-dsl-control))

View file

@ -0,0 +1,21 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2008 OpenWrt.org
START=99
start() {
# start CPE dsl daemon in the background
/sbin/dsl_cpe_control -i -f /lib/firmware/ModemHWE.bin &
# PS=`ps`
# echo $PS | grep -q dsl_cpe_control && {
# # workaround for nfs: allow write to pipes for non-root
# while [ ! -e /tmp/pipe/dsl_cpe1_ack ] ; do sleep 1; done
# chmod a+w /tmp/pipe/dsl_*
# }
echo $PS | grep -q dsl_cpe_control || {
echo "Start of dsl_cpe_control failed!!!"
false
}
}

View file

@ -12,15 +12,3 @@ Index: linux-2.6.28.10/include/linux/atm.h
/* extra params for ABR */
unsigned int icr; /* Initial Cell Rate (24-bit) */
unsigned int tbe; /* Transient Buffer Exposure (24-bit) */
Index: linux-2.6.28.10/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.28.10.orig/kernel/time/timekeeping.c 2009-09-02 15:41:06.000000000 +0200
+++ linux-2.6.28.10/kernel/time/timekeeping.c 2009-09-02 15:41:23.000000000 +0200
@@ -43,6 +43,7 @@
* used instead.
*/
struct timespec xtime __attribute__ ((aligned (16)));
+EXPORT_SYMBOL(xtime);
struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
static unsigned long total_sleep_time; /* seconds */

View file

@ -13,9 +13,10 @@ FEATURES:=squashfs jffs2 atm
LINUX_VERSION:=2.6.30.9
CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES+=uboot-ifxmips
#kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl kmod-ifxmips-atm
DEFAULT_PACKAGES+=kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl ifxmips-dsl-api ifxmips-dsl-control
define Target/Description
Build firmware images for Infineon Mips Controllers

View file

@ -23,5 +23,4 @@ config interface wan
option proto pppoe
option username ""
option password ""
option defaultroute 0
option unit 1
option unit 0

View file

@ -35,6 +35,7 @@
#define IFXMIPS_SSC_RIR (INT_NUM_IM0_IRL0 + 14)
#define IFXMIPS_SSC_EIR (INT_NUM_IM0_IRL0 + 16)
#define IFXMIPS_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)
#define IFXMIPS_MEI_INT (INT_NUM_IM1_IRL0 + 23)
#define IFXMIPS_TIMER6_INT (INT_NUM_IM1_IRL0 + 23)

View file

@ -0,0 +1,48 @@
Index: linux-2.6.30.9/arch/mips/mm/cache.c
===================================================================
--- linux-2.6.30.9.orig/arch/mips/mm/cache.c 2009-11-01 16:10:29.000000000 +0100
+++ linux-2.6.30.9/arch/mips/mm/cache.c 2009-11-01 16:11:56.000000000 +0100
@@ -52,6 +52,8 @@
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_wback);
+EXPORT_SYMBOL(_dma_cache_inv);
#endif /* CONFIG_DMA_NONCOHERENT */
Index: linux-2.6.30.9/net/atm/proc.c
===================================================================
--- linux-2.6.30.9.orig/net/atm/proc.c 2009-11-01 16:34:42.000000000 +0100
+++ linux-2.6.30.9/net/atm/proc.c 2009-11-01 16:35:59.000000000 +0100
@@ -151,7 +151,7 @@
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
- static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" };
+ static const char *class_name[] = { "off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR" };
static const char *aal_name[] = {
"---", "1", "2", "3/4", /* 0- 3 */
"???", "5", "???", "???", /* 4- 7 */
Index: linux-2.6.30.9/net/atm/common.c
===================================================================
--- linux-2.6.30.9.orig/net/atm/common.c 2009-11-01 16:38:12.000000000 +0100
+++ linux-2.6.30.9/net/atm/common.c 2009-11-01 16:47:06.000000000 +0100
@@ -56,12 +56,17 @@
write_unlock_irq(&vcc_sklist_lock);
}
+struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL;
+EXPORT_SYMBOL(ifx_atm_alloc_tx);
static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
{
struct sk_buff *skb;
struct sock *sk = sk_atm(vcc);
+ if (ifx_atm_alloc_tx != NULL)
+ return ifx_atm_alloc_tx(vcc, size);
+
if (atomic_read(&sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) {
pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
atomic_read(&sk->sk_wmem_alloc), size,