Staging: Add SBE 2T3E3 WAN driver
This is a driver for SBE Inc.'s dual port T3/E3 WAN cards. Based on their original GPLed driver. The original driver tarball is now accessible at http://userweb.kernel.org/~chris/SBE_2T3_Linux_2.0c.tgz It needs at least a new generic HDLC setup code (not yet written) before moving to drivers/net/wan. Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
b0b5763308
commit
921a86e0e3
|
@ -155,5 +155,7 @@ source "drivers/staging/quickstart/Kconfig"
|
|||
|
||||
source "drivers/staging/westbridge/Kconfig"
|
||||
|
||||
source "drivers/staging/sbe-2t3e3/Kconfig"
|
||||
|
||||
endif # !STAGING_EXCLUDE_BUILD
|
||||
endif # STAGING
|
||||
|
|
|
@ -58,3 +58,4 @@ obj-$(CONFIG_SOLO6X10) += solo6x10/
|
|||
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
|
||||
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
|
||||
obj-$(CONFIG_WESTBRIDGE_ASTORIA) += westbridge/astoria/
|
||||
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
|
||||
|
|
|
@ -0,0 +1,894 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#ifndef T3E3_H
|
||||
#define T3E3_H
|
||||
|
||||
#include <linux/hdlc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include "ctrl.h"
|
||||
|
||||
/**************************************************************
|
||||
* 21143
|
||||
**************************************************************/
|
||||
|
||||
/* CSR */
|
||||
#define SBE_2T3E3_21143_REG_BUS_MODE 0
|
||||
#define SBE_2T3E3_21143_REG_TRANSMIT_POLL_DEMAND 1
|
||||
#define SBE_2T3E3_21143_REG_RECEIVE_POLL_DEMAND 2
|
||||
#define SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS 3
|
||||
#define SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS 4
|
||||
#define SBE_2T3E3_21143_REG_STATUS 5
|
||||
#define SBE_2T3E3_21143_REG_OPERATION_MODE 6
|
||||
#define SBE_2T3E3_21143_REG_INTERRUPT_ENABLE 7
|
||||
#define SBE_2T3E3_21143_REG_MISSED_FRAMES_AND_OVERFLOW_COUNTER 8
|
||||
#define SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT 9
|
||||
#define SBE_2T3E3_21143_REG_BOOT_ROM_PROGRAMMING_ADDRESS 10
|
||||
#define SBE_2T3E3_21143_REG_GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL 11
|
||||
#define SBE_2T3E3_21143_REG_SIA_STATUS 12
|
||||
#define SBE_2T3E3_21143_REG_SIA_CONNECTIVITY 13
|
||||
#define SBE_2T3E3_21143_REG_SIA_TRANSMIT_AND_RECEIVE 14
|
||||
#define SBE_2T3E3_21143_REG_SIA_AND_GENERAL_PURPOSE_PORT 15
|
||||
#define SBE_2T3E3_21143_REG_MAX 16
|
||||
|
||||
/* CSR0 - BUS_MODE */
|
||||
#define SBE_2T3E3_21143_VAL_WRITE_AND_INVALIDATE_ENABLE 0x01000000
|
||||
#define SBE_2T3E3_21143_VAL_READ_LINE_ENABLE 0x00800000
|
||||
#define SBE_2T3E3_21143_VAL_READ_MULTIPLE_ENABLE 0x00200000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_AUTOMATIC_POLLING_200us 0x00020000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_AUTOMATIC_POLLING_DISABLED 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_32 0x0000c000
|
||||
#define SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_16 0x00008000
|
||||
#define SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_8 0x00004000
|
||||
#define SBE_2T3E3_21143_VAL_BUS_ARBITRATION_RR 0x00000002
|
||||
#define SBE_2T3E3_21143_VAL_SOFTWARE_RESET 0x00000001
|
||||
|
||||
/* CSR5 - STATUS */
|
||||
#define SBE_2T3E3_21143_VAL_GENERAL_PURPOSE_PORT_INTERRUPT 0x04000000
|
||||
#define SBE_2T3E3_21143_VAL_ERROR_BITS 0x03800000
|
||||
#define SBE_2T3E3_21143_VAL_PARITY_ERROR 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_MASTER_ABORT 0x00800000
|
||||
#define SBE_2T3E3_21143_VAL_TARGET_ABORT 0x01000000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMISSION_PROCESS_STATE 0x00700000
|
||||
#define SBE_2T3E3_21143_VAL_TX_STOPPED 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_TX_SUSPENDED 0x00600000
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STATE 0x000e0000
|
||||
#define SBE_2T3E3_21143_VAL_RX_STOPPED 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_RX_SUSPENDED 0x000a0000
|
||||
#define SBE_2T3E3_21143_VAL_NORMAL_INTERRUPT_SUMMARY 0x00010000
|
||||
#define SBE_2T3E3_21143_VAL_ABNORMAL_INTERRUPT_SUMMARY 0x00008000
|
||||
#define SBE_2T3E3_21143_VAL_EARLY_RECEIVE_INTERRUPT 0x00004000
|
||||
#define SBE_2T3E3_21143_VAL_FATAL_BUS_ERROR 0x00002000
|
||||
#define SBE_2T3E3_21143_VAL_GENERAL_PURPOSE_TIMER_EXPIRED 0x00000800
|
||||
#define SBE_2T3E3_21143_VAL_EARLY_TRANSMIT_INTERRUPT 0x00000400
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_WATCHDOG_TIMEOUT 0x00000200
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED 0x00000100
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE 0x00000080
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT 0x00000040
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW 0x00000020
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_JABBER_TIMEOUT 0x00000008
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE 0x00000004
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED 0x00000002
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT 0x00000001
|
||||
|
||||
/* CSR6 - OPERATION_MODE */
|
||||
#define SBE_2T3E3_21143_VAL_SPECIAL_CAPTURE_EFFECT_ENABLE 0x80000000
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_ALL 0x40000000
|
||||
#define SBE_2T3E3_21143_VAL_MUST_BE_ONE 0x02000000
|
||||
#define SBE_2T3E3_21143_VAL_SCRAMBLER_MODE 0x01000000
|
||||
#define SBE_2T3E3_21143_VAL_PCS_FUNCTION 0x00800000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_THRESHOLD_MODE_10Mbs 0x00400000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_THRESHOLD_MODE_100Mbs 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_STORE_AND_FORWARD 0x00200000
|
||||
#define SBE_2T3E3_21143_VAL_HEARTBEAT_DISABLE 0x00080000
|
||||
#define SBE_2T3E3_21143_VAL_PORT_SELECT 0x00040000
|
||||
#define SBE_2T3E3_21143_VAL_CAPTURE_EFFECT_ENABLE 0x00020000
|
||||
#define SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS 0x0000c000
|
||||
#define SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_1 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_2 0x00004000
|
||||
#define SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_3 0x00008000
|
||||
#define SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_4 0x0000c000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMISSION_START 0x00002000
|
||||
#define SBE_2T3E3_21143_VAL_OPERATING_MODE 0x00000c00
|
||||
#define SBE_2T3E3_21143_VAL_LOOPBACK_OFF 0x00000000
|
||||
#define SBE_2T3E3_21143_VAL_LOOPBACK_EXTERNAL 0x00000800
|
||||
#define SBE_2T3E3_21143_VAL_LOOPBACK_INTERNAL 0x00000400
|
||||
#define SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE 0x00000200
|
||||
#define SBE_2T3E3_21143_VAL_PASS_ALL_MULTICAST 0x00000080
|
||||
#define SBE_2T3E3_21143_VAL_PROMISCUOUS_MODE 0x00000040
|
||||
#define SBE_2T3E3_21143_VAL_PASS_BAD_FRAMES 0x00000008
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_START 0x00000002
|
||||
|
||||
/* CSR7 - INTERRUPT_ENABLE */
|
||||
#define SBE_2T3E3_21143_VAL_LINK_CHANGED_ENABLE 0x08000000
|
||||
#define SBE_2T3E3_21143_VAL_GENERAL_PURPOSE_PORT_ENABLE 0x04000000
|
||||
#define SBE_2T3E3_21143_VAL_NORMAL_INTERRUPT_SUMMARY_ENABLE 0x00010000
|
||||
#define SBE_2T3E3_21143_VAL_ABNORMAL_INTERRUPT_SUMMARY_ENABLE 0x00008000
|
||||
#define SBE_2T3E3_21143_VAL_EARLY_RECEIVE_INTERRUPT_ENABLE 0x00004000
|
||||
#define SBE_2T3E3_21143_VAL_FATAL_BUS_ERROR_ENABLE 0x00002000
|
||||
#define SBE_2T3E3_21143_VAL_LINK_FAIL_ENABLE 0x00001000
|
||||
#define SBE_2T3E3_21143_VAL_GENERAL_PURPOSE_TIMER_ENABLE 0x00000800
|
||||
#define SBE_2T3E3_21143_VAL_EARLY_TRANSMIT_INTERRUPT_ENABLE 0x00000400
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_WATCHDOG_TIMEOUT_ENABLE 0x00000200
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_STOPPED_ENABLE 0x00000100
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE_ENABLE 0x00000080
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT_ENABLE 0x00000040
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW_INTERRUPT_ENABLE 0x00000020
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_JABBER_TIMEOUT_ENABLE 0x00000008
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE 0x00000004
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_STOPPED_ENABLE 0x00000002
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT_ENABLE 0x00000001
|
||||
|
||||
/* CSR8 - MISSED_FRAMES_AND_OVERFLOW_COUNTER */
|
||||
#define SBE_2T3E3_21143_VAL_OVERFLOW_COUNTER_OVERFLOW 0x10000000
|
||||
#define SBE_2T3E3_21143_VAL_OVERFLOW_COUNTER 0x0ffe0000
|
||||
#define SBE_2T3E3_21143_VAL_MISSED_FRAME_OVERFLOW 0x00010000
|
||||
#define SBE_2T3E3_21143_VAL_MISSED_FRAMES_COUNTER 0x0000ffff
|
||||
|
||||
/* CSR9 - BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT */
|
||||
#define SBE_2T3E3_21143_VAL_MII_MANAGEMENT_DATA_IN 0x00080000
|
||||
#define SBE_2T3E3_21143_VAL_MII_MANAGEMENT_READ_MODE 0x00040000
|
||||
#define SBE_2T3E3_21143_VAL_MII_MANAGEMENT_DATA_OUT 0x00020000
|
||||
#define SBE_2T3E3_21143_VAL_MII_MANAGEMENT_CLOCK 0x00010000
|
||||
#define SBE_2T3E3_21143_VAL_READ_OPERATION 0x00004000
|
||||
#define SBE_2T3E3_21143_VAL_WRITE_OPERATION 0x00002000
|
||||
#define SBE_2T3E3_21143_VAL_BOOT_ROM_SELECT 0x00001000
|
||||
#define SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT 0x00000800
|
||||
#define SBE_2T3E3_21143_VAL_BOOT_ROM_DATA 0x000000ff
|
||||
#define SBE_2T3E3_21143_VAL_SERIAL_ROM_DATA_OUT 0x00000008
|
||||
#define SBE_2T3E3_21143_VAL_SERIAL_ROM_DATA_IN 0x00000004
|
||||
#define SBE_2T3E3_21143_VAL_SERIAL_ROM_CLOCK 0x00000002
|
||||
#define SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT 0x00000001
|
||||
|
||||
/* CSR11 - GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL */
|
||||
#define SBE_2T3E3_21143_VAL_CYCLE_SIZE 0x80000000
|
||||
#define SBE_2T3E3_21143_VAL_TRANSMIT_TIMER 0x78000000
|
||||
#define SBE_2T3E3_21143_VAL_NUMBER_OF_TRANSMIT_PACKETS 0x07000000
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_TIMER 0x00f00000
|
||||
#define SBE_2T3E3_21143_VAL_NUMBER_OF_RECEIVE_PACKETS 0x000e0000
|
||||
#define SBE_2T3E3_21143_VAL_CONTINUOUS_MODE 0x00010000
|
||||
#define SBE_2T3E3_21143_VAL_TIMER_VALUE 0x0000ffff
|
||||
|
||||
/* CSR12 - SIA_STATUS */
|
||||
#define SBE_2T3E3_21143_VAL_10BASE_T_RECEIVE_PORT_ACTIVITY 0x00000200
|
||||
#define SBE_2T3E3_21143_VAL_AUI_RECEIVE_PORT_ACTIVITY 0x00000100
|
||||
#define SBE_2T3E3_21143_VAL_10Mbs_LINK_STATUS 0x00000004
|
||||
#define SBE_2T3E3_21143_VAL_100Mbs_LINK_STATUS 0x00000002
|
||||
#define SBE_2T3E3_21143_VAL_MII_RECEIVE_PORT_ACTIVITY 0x00000001
|
||||
|
||||
/* CSR13 - SIA_CONNECTIVITY */
|
||||
#define SBE_2T3E3_21143_VAL_10BASE_T_OR_AUI 0x00000008
|
||||
#define SBE_2T3E3_21143_VAL_SIA_RESET 0x00000001
|
||||
|
||||
/* CSR14 - SIA_TRANSMIT_AND_RECEIVE */
|
||||
#define SBE_2T3E3_21143_VAL_100BASE_TX_FULL_DUPLEX 0x00020000
|
||||
#define SBE_2T3E3_21143_VAL_COLLISION_DETECT_ENABLE 0x00000400
|
||||
#define SBE_2T3E3_21143_VAL_COLLISION_SQUELCH_ENABLE 0x00000200
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_SQUELCH_ENABLE 0x00000100
|
||||
#define SBE_2T3E3_21143_VAL_LINK_PULSE_SEND_ENABLE 0x00000004
|
||||
#define SBE_2T3E3_21143_VAL_ENCODER_ENABLE 0x00000001
|
||||
|
||||
/* CSR15 - SIA_AND_GENERAL_PURPOSE_PORT */
|
||||
#define SBE_2T3E3_21143_VAL_RECEIVE_WATCHDOG_DISABLE 0x00000010
|
||||
#define SBE_2T3E3_21143_VAL_AUI_BNC_MODE 0x00000008
|
||||
#define SBE_2T3E3_21143_VAL_HOST_UNJAB 0x00000002
|
||||
#define SBE_2T3E3_21143_VAL_JABBER_DISABLE 0x00000001
|
||||
|
||||
/**************************************************************
|
||||
* CPLD
|
||||
**************************************************************/
|
||||
|
||||
/* reg_map indexes */
|
||||
#define SBE_2T3E3_CPLD_REG_PCRA 0
|
||||
#define SBE_2T3E3_CPLD_REG_PCRB 1
|
||||
#define SBE_2T3E3_CPLD_REG_PLCR 2
|
||||
#define SBE_2T3E3_CPLD_REG_PLTR 3
|
||||
#define SBE_2T3E3_CPLD_REG_PPFR 4
|
||||
#define SBE_2T3E3_CPLD_REG_BOARD_ID 5
|
||||
#define SBE_2T3E3_CPLD_REG_FPGA_VERSION 6
|
||||
#define SBE_2T3E3_CPLD_REG_FRAMER_BASE_ADDRESS 7
|
||||
#define SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT 8
|
||||
#define SBE_2T3E3_CPLD_REG_STATIC_RESET 9
|
||||
#define SBE_2T3E3_CPLD_REG_PULSE_RESET 10
|
||||
#define SBE_2T3E3_CPLD_REG_FPGA_RECONFIGURATION 11
|
||||
#define SBE_2T3E3_CPLD_REG_LEDR 12
|
||||
#define SBE_2T3E3_CPLD_REG_PICSR 13
|
||||
#define SBE_2T3E3_CPLD_REG_PIER 14
|
||||
#define SBE_2T3E3_CPLD_REG_PCRC 15
|
||||
#define SBE_2T3E3_CPLD_REG_PBWF 16
|
||||
#define SBE_2T3E3_CPLD_REG_PBWL 17
|
||||
|
||||
#define SBE_2T3E3_CPLD_REG_MAX 18
|
||||
|
||||
/**********/
|
||||
|
||||
/* val_map indexes */
|
||||
#define SBE_2T3E3_CPLD_VAL_LIU_SELECT 0
|
||||
#define SBE_2T3E3_CPLD_VAL_DAC_SELECT 1
|
||||
#define SBE_2T3E3_CPLD_VAL_LOOP_TIMING_SOURCE 2
|
||||
#define SBE_2T3E3_CPLD_VAL_LIU_FRAMER_RESET 3
|
||||
|
||||
/* PCRA */
|
||||
#define SBE_2T3E3_CPLD_VAL_CRC32 0x40
|
||||
#define SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE 0x20
|
||||
#define SBE_2T3E3_CPLD_VAL_REAR_PANEL 0x10
|
||||
#define SBE_2T3E3_CPLD_VAL_RAW_MODE 0x08
|
||||
#define SBE_2T3E3_CPLD_VAL_ALT 0x04
|
||||
#define SBE_2T3E3_CPLD_VAL_LOOP_TIMING 0x02
|
||||
#define SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3 0x01
|
||||
|
||||
/* PCRB */
|
||||
#define SBE_2T3E3_CPLD_VAL_PAD_COUNT 0x30
|
||||
#define SBE_2T3E3_CPLD_VAL_PAD_COUNT_1 0x00
|
||||
#define SBE_2T3E3_CPLD_VAL_PAD_COUNT_2 0x10
|
||||
#define SBE_2T3E3_CPLD_VAL_PAD_COUNT_3 0x20
|
||||
#define SBE_2T3E3_CPLD_VAL_PAD_COUNT_4 0x30
|
||||
#define SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE 0x02
|
||||
#define SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE 0x01
|
||||
|
||||
/* PCRC */
|
||||
#define SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_NONE 0x00
|
||||
#define SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_0 0x01
|
||||
#define SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_1 0x11
|
||||
#define SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_2 0x21
|
||||
|
||||
/* PLTR */
|
||||
#define SBE_2T3E3_CPLD_VAL_LCV_COUNTER 0xff
|
||||
|
||||
/* SCSR */
|
||||
#define SBE_2T3E3_CPLD_VAL_EEPROM_SELECT 0x10
|
||||
|
||||
/* PICSR */
|
||||
#define SBE_2T3E3_CPLD_VAL_LOSS_OF_SIGNAL_THRESHOLD_LEVEL_1 0x80
|
||||
#define SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_CHANGE 0x40
|
||||
#define SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ASSERTED 0x20
|
||||
#define SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ASSERTED 0x10
|
||||
#define SBE_2T3E3_CPLD_VAL_LCV_LIMIT_EXCEEDED 0x08
|
||||
#define SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED 0x04
|
||||
#define SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED 0x02
|
||||
#define SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED 0x01
|
||||
|
||||
/* PIER */
|
||||
#define SBE_2T3E3_CPLD_VAL_RECEIVE_LOS_CHANGE_ENABLE 0x40
|
||||
#define SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ENABLE 0x20
|
||||
#define SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ENABLE 0x10
|
||||
#define SBE_2T3E3_CPLD_VAL_LCV_INTERRUPT_ENABLE 0x08
|
||||
#define SBE_2T3E3_CPLD_VAL_DMO_ENABLE 0x04
|
||||
#define SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_ENABLE 0x02
|
||||
#define SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_ENABLE 0x01
|
||||
|
||||
/**************************************************************
|
||||
* Framer
|
||||
**************************************************************/
|
||||
|
||||
/* reg_map indexes */
|
||||
/* common */
|
||||
#define SBE_2T3E3_FRAMER_REG_OPERATING_MODE 0
|
||||
#define SBE_2T3E3_FRAMER_REG_IO_CONTROL 1
|
||||
#define SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_ENABLE 2
|
||||
#define SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_STATUS 3
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_LCV_EVENT_COUNT_MSB 28
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_LCV_EVENT_COUNT_LSB 29
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_FRAMING_BIT_ERROR_EVENT_COUNT_MSB 30
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_FRAMING_BIT_ERROR_EVENT_COUNT_LSB 31
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_PARITY_ERROR_EVENT_COUNT_MSB 32
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_PARITY_ERROR_EVENT_COUNT_LSB 33
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_FEBE_EVENT_COUNT_MSB 34
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_FEBE_EVENT_COUNT_LSB 35
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_CP_BIT_ERROR_EVENT_COUNT_MSB 36
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_CP_BIT_ERROR_EVENT_COUNT_LSB 37
|
||||
#define SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER 38
|
||||
#define SBE_2T3E3_FRAMER_REG_ONE_SECOND_ERROR_STATUS 39
|
||||
#define SBE_2T3E3_FRAMER_REG_LCV_ONE_SECOND_ACCUMULATOR_MSB 40
|
||||
#define SBE_2T3E3_FRAMER_REG_LCV_ONE_SECOND_ACCUMULATOR_LSB 41
|
||||
#define SBE_2T3E3_FRAMER_REG_FRAME_PARITY_ERROR_ONE_SECOND_ACCUMULATOR_MSB 42
|
||||
#define SBE_2T3E3_FRAMER_REG_FRAME_PARITY_ERROR_ONE_SECOND_ACCUMULATOR_LSB 43
|
||||
#define SBE_2T3E3_FRAMER_REG_FRAME_CP_BIT_ERROR_ONE_SECOND_ACCUMULATOR_MSB 44
|
||||
#define SBE_2T3E3_FRAMER_REG_FRAME_CP_BIT_ERROR_ONE_SECOND_ACCUMULATOR_LSB 45
|
||||
#define SBE_2T3E3_FRAMER_REG_LINE_INTERFACE_DRIVE 46
|
||||
#define SBE_2T3E3_FRAMER_REG_LINE_INTERFACE_SCAN 47
|
||||
|
||||
/* T3 */
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS 4
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_STATUS 5
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_ENABLE 6
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_STATUS 7
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_SYNC_DETECT_ENABLE 8
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_FEAC 10
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS 11
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_CONTROL 12
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_STATUS 13
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_CONFIGURATION 16
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_FEAC_CONFIGURATION_STATUS 17
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_FEAC 18
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_LAPD_CONFIGURATION 19
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_LAPD_STATUS 20
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_MBIT_MASK 21
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_FBIT_MASK 22
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_FBIT_MASK_2 23
|
||||
#define SBE_2T3E3_FRAMER_REG_T3_TX_FBIT_MASK_3 24
|
||||
|
||||
/* E3 */
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_1 4
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2 5
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_1 6
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_2 7
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_1 8
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_2 9
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_LAPD_CONTROL 12
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_LAPD_STATUS 13
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_NR_BYTE 14
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_SERVICE_BITS 14
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_RX_GC_BYTE 15
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_CONFIGURATION 16
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_LAPD_CONFIGURATION 19
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_LAPD_STATUS 19
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_GC_BYTE 21
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_SERVICE_BITS 21
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_MA_BYTE 22
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_NR_BYTE 23
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_FA1_ERROR_MASK 25
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_FAS_ERROR_MASK_UPPER 25
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_FA2_ERROR_MASK 26
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_FAS_ERROR_MASK_LOWER 26
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_BIP8_MASK 27
|
||||
#define SBE_2T3E3_FRAMER_REG_E3_TX_BIP4_MASK 27
|
||||
|
||||
#define SBE_2T3E3_FRAMER_REG_MAX 48
|
||||
|
||||
/**********/
|
||||
|
||||
/* OPERATING_MODE */
|
||||
#define SBE_2T3E3_FRAMER_VAL_LOCAL_LOOPBACK_MODE 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_E3_SELECT 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_INTERNAL_LOS_ENABLE 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_RESET 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_INTERRUPT_ENABLE_RESET 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_FRAME_FORMAT_SELECT 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_TIMING_ASYNCH_TXINCLK 0x03
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_G751 0x00
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_G832 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_CBIT 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_M13 0x44
|
||||
#define SBE_2T3E3_FRAMER_VAL_LOOPBACK_ON 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_LOOPBACK_OFF 0x00
|
||||
|
||||
/* IO_CONTROL */
|
||||
#define SBE_2T3E3_FRAMER_VAL_DISABLE_TX_LOSS_OF_CLOCK 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_LOSS_OF_CLOCK_STATUS 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_DISABLE_RX_LOSS_OF_CLOCK 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_AMI_LINE_CODE 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_UNIPOLAR 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_TX_LINE_CLOCK_INVERT 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_RX_LINE_CLOCK_INVERT 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_REFRAME 0x01
|
||||
|
||||
/* BLOCK_INTERRUPT_ENABLE */
|
||||
#define SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_ENABLE 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_ONE_SECOND_INTERRUPT_ENABLE 0x01
|
||||
|
||||
/* BLOCK_INTERRUPT_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_STATUS 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_STATUS 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_ONE_SECOND_INTERRUPT_STATUS 0x01
|
||||
|
||||
/**********/
|
||||
|
||||
/* T3_RX_CONFIGURATION_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_AIS 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LOS 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_OOF 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FRAMING_ON_PARITY 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_F_SYNC_ALGO 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_M_SYNC_ALGO 0x01
|
||||
|
||||
/* T3_RX_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FERF 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_AIC 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FEBE 0x07
|
||||
|
||||
/* T3_RX_INTERRUPT_ENABLE */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_CP_BIT_ERROR_INTERRUPT_ENABLE 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_ENABLE 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_AIS_INTERRUPT_ENABLE 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE_INTERRUPT_ENABLE 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FERF_INTERRUPT_ENABLE 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_AIC_INTERRUPT_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_P_BIT_INTERRUPT_ENABLE 0x01
|
||||
|
||||
/* T3_RX_INTERRUPT_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_CP_BIT_ERROR_INTERRUPT_STATUS 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_STATUS 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_AIS_INTERRUPT_STATUS 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE_INTERRUPT_STATUS 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FERF_INTERRUPT_STATUS 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_AIC_INTERRUPT_STATUS 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_STATUS 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_P_BIT_INTERRUPT_STATUS 0x01
|
||||
|
||||
/* T3_RX_FEAC_INTERRUPT_ENABLE_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_VALID 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_REMOVE_INTERRUPT_ENABLE 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_REMOVE_INTERRUPT_STATUS 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_VALID_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_VALID_INTERRUPT_STATUS 0x01
|
||||
|
||||
/* T3_RX_LAPD_CONTROL */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LAPD_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LAPD_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LAPD_INTERRUPT_STATUS 0x01
|
||||
|
||||
/* T3_RX_LAPD_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_ABORT 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_LAPD_TYPE 0x30
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_CR_TYPE 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FCS_ERROR 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_END_OF_MESSAGE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_RX_FLAG_PRESENT 0x01
|
||||
|
||||
/* T3_TX_CONFIGURATION */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_YELLOW_ALARM 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_X_BIT 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_IDLE 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_AIS 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_LOS 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FERF_ON_LOS 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FERF_ON_OOF 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FERF_ON_AIS 0x01
|
||||
|
||||
/* T3_TX_FEAC_CONFIGURATION_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FEAC_INTERRUPT_ENABLE 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FEAC_INTERRUPT_STATUS 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FEAC_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FEAC_GO 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_FEAC_BUSY 0x01
|
||||
|
||||
/* T3_TX_LAPD_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_DL_START 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_DL_BUSY 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_LAPD_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_T3_TX_LAPD_INTERRUPT_STATUS 0x01
|
||||
|
||||
/**********/
|
||||
|
||||
/* E3_RX_CONFIGURATION_STATUS_1 */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_PAYLOAD_TYPE 0xe0
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FERF_ALGO 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_T_MARK_ALGO 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_PAYLOAD_EXPECTED 0x07
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_BIP4 0x01
|
||||
|
||||
/* E3_RX_CONFIGURATION_STATUS_2 */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOF_ALGO 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOF 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_OOF 0x20
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOS 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_AIS 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_PAYLOAD_UNSTABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_T_MARK 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FERF 0x01
|
||||
|
||||
/* E3_RX_INTERRUPT_ENABLE_1 */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_COFA_INTERRUPT_ENABLE 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_ENABLE 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOF_INTERRUPT_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_AIS_INTERRUPT_ENABLE 0x01
|
||||
|
||||
/* E3_RX_INTERRUPT_ENABLE_2 */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_TTB_CHANGE_INTERRUPT_ENABLE 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FEBE_INTERRUPT_ENABLE 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FERF_INTERRUPT_ENABLE 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_BIP8_ERROR_INTERRUPT_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_BIP4_ERROR_INTERRUPT_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FRAMING_BYTE_ERROR_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_PAYLOAD_MISMATCH_INTERRUPT_ENABLE 0x01
|
||||
|
||||
/* E3_RX_INTERRUPT_STATUS_1 */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_COFA_INTERRUPT_STATUS 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_STATUS 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOF_INTERRUPT_STATUS 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_STATUS 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_AIS_INTERRUPT_STATUS 0x01
|
||||
|
||||
/* E3_RX_INTERRUPT_STATUS_2 */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_TTB_CHANGE_INTERRUPT_STATUS 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FEBE_INTERRUPT_STATUS 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FERF_INTERRUPT_STATUS 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_BIP8_ERROR_INTERRUPT_STATUS 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_BIP4_ERROR_INTERRUPT_STATUS 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FRAMING_BYTE_ERROR_INTERRUPT_STATUS 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_PAYLOAD_MISMATCH_INTERRUPT_STATUS 0x01
|
||||
|
||||
/* E3_RX_LAPD_CONTROL */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_DL_FROM_NR 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LAPD_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LAPD_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LAPD_INTERRUPT_STATUS 0x01
|
||||
|
||||
/* E3_RX_LAPD_STATUS */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_ABORT 0x40
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_LAPD_TYPE 0x30
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_CR_TYPE 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FCS_ERROR 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_END_OF_MESSAGE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_RX_FLAG_PRESENT 0x01
|
||||
|
||||
/* E3_TX_CONFIGURATION */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_BIP4_ENABLE 0x80
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_A_SOURCE_SELECT 0x60
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_DL_IN_NR 0x10
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_N_SOURCE_SELECT 0x18
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_AIS_ENABLE 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_LOS_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_MA_RX 0x01
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_FAS_SOURCE_SELECT 0x01
|
||||
|
||||
/* E3_TX_LAPD_CONFIGURATION */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_AUTO_RETRANSMIT 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_LAPD_MESSAGE_LENGTH 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_LAPD_ENABLE 0x01
|
||||
|
||||
/* E3_TX_LAPD_STATUS_INTERRUPT */
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_DL_START 0x08
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_DL_BUSY 0x04
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_LAPD_INTERRUPT_ENABLE 0x02
|
||||
#define SBE_2T3E3_FRAMER_VAL_E3_TX_LAPD_INTERRUPT_STATUS 0x01
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* LIU
|
||||
**************************************************************/
|
||||
|
||||
/* reg_map indexes */
|
||||
#define SBE_2T3E3_LIU_REG_REG0 0
|
||||
#define SBE_2T3E3_LIU_REG_REG1 1
|
||||
#define SBE_2T3E3_LIU_REG_REG2 2
|
||||
#define SBE_2T3E3_LIU_REG_REG3 3
|
||||
#define SBE_2T3E3_LIU_REG_REG4 4
|
||||
|
||||
#define SBE_2T3E3_LIU_REG_MAX 5
|
||||
|
||||
/**********/
|
||||
|
||||
/* REG0 */
|
||||
#define SBE_2T3E3_LIU_VAL_RECEIVE_LOSS_OF_LOCK_STATUS 0x10
|
||||
#define SBE_2T3E3_LIU_VAL_RECEIVE_LOSS_OF_SIGNAL_STATUS 0x08
|
||||
#define SBE_2T3E3_LIU_VAL_ANALOG_LOSS_OF_SIGNAL_STATUS 0x04
|
||||
#define SBE_2T3E3_LIU_VAL_DIGITAL_LOSS_OF_SIGNAL_STATUS 0x02
|
||||
#define SBE_2T3E3_LIU_VAL_DMO_STATUS 0x01
|
||||
|
||||
/* REG1 */
|
||||
#define SBE_2T3E3_LIU_VAL_TRANSMITTER_OFF 0x10
|
||||
#define SBE_2T3E3_LIU_VAL_TRANSMIT_ALL_ONES 0x08
|
||||
#define SBE_2T3E3_LIU_VAL_TRANSMIT_CLOCK_INVERT 0x04
|
||||
#define SBE_2T3E3_LIU_VAL_TRANSMIT_LEVEL_SELECT 0x02
|
||||
#define SBE_2T3E3_LIU_VAL_TRANSMIT_BINARY_DATA 0x01
|
||||
|
||||
/* REG2 */
|
||||
#define SBE_2T3E3_LIU_VAL_DECODER_DISABLE 0x10
|
||||
#define SBE_2T3E3_LIU_VAL_ENCODER_DISABLE 0x08
|
||||
#define SBE_2T3E3_LIU_VAL_ANALOG_LOSS_OF_SIGNAL_DISABLE 0x04
|
||||
#define SBE_2T3E3_LIU_VAL_DIGITAL_LOSS_OF_SIGNAL_DISABLE 0x02
|
||||
#define SBE_2T3E3_LIU_VAL_RECEIVE_EQUALIZATION_DISABLE 0x01
|
||||
|
||||
/* REG3 */
|
||||
#define SBE_2T3E3_LIU_VAL_RECEIVE_BINARY_DATA 0x10
|
||||
#define SBE_2T3E3_LIU_VAL_RECOVERED_DATA_MUTING 0x08
|
||||
#define SBE_2T3E3_LIU_VAL_RECEIVE_CLOCK_OUTPUT_2 0x04
|
||||
#define SBE_2T3E3_LIU_VAL_INVERT_RECEIVE_CLOCK_2 0x02
|
||||
#define SBE_2T3E3_LIU_VAL_INVERT_RECEIVE_CLOCK_1 0x01
|
||||
|
||||
/* REG4 */
|
||||
#define SBE_2T3E3_LIU_VAL_T3_MODE_SELECT 0x00
|
||||
#define SBE_2T3E3_LIU_VAL_E3_MODE_SELECT 0x04
|
||||
#define SBE_2T3E3_LIU_VAL_LOCAL_LOOPBACK 0x02
|
||||
#define SBE_2T3E3_LIU_VAL_REMOTE_LOOPBACK 0x01
|
||||
#define SBE_2T3E3_LIU_VAL_LOOPBACK_OFF 0x00
|
||||
#define SBE_2T3E3_LIU_VAL_LOOPBACK_REMOTE 0x01
|
||||
#define SBE_2T3E3_LIU_VAL_LOOPBACK_ANALOG 0x02
|
||||
#define SBE_2T3E3_LIU_VAL_LOOPBACK_DIGITAL 0x03
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* descriptor list and data buffer
|
||||
*
|
||||
**********************************************************************/
|
||||
typedef struct {
|
||||
u32 rdes0;
|
||||
u32 rdes1;
|
||||
u32 rdes2;
|
||||
u32 rdes3;
|
||||
} t3e3_rx_desc_t;
|
||||
|
||||
#define SBE_2T3E3_RX_DESC_RING_SIZE 64
|
||||
|
||||
/* RDES0 */
|
||||
#define SBE_2T3E3_RX_DESC_21143_OWN 0X80000000
|
||||
#define SBE_2T3E3_RX_DESC_FRAME_LENGTH 0x3fff0000
|
||||
#define SBE_2T3E3_RX_DESC_FRAME_LENGTH_SHIFT 16
|
||||
#define SBE_2T3E3_RX_DESC_ERROR_SUMMARY 0x00008000
|
||||
#define SBE_2T3E3_RX_DESC_DESC_ERROR 0x00004000
|
||||
#define SBE_2T3E3_RX_DESC_DATA_TYPE 0x00003000
|
||||
#define SBE_2T3E3_RX_DESC_RUNT_FRAME 0x00000800
|
||||
#define SBE_2T3E3_RX_DESC_FIRST_DESC 0x00000200
|
||||
#define SBE_2T3E3_RX_DESC_LAST_DESC 0x00000100
|
||||
#define SBE_2T3E3_RX_DESC_FRAME_TOO_LONG 0x00000080
|
||||
#define SBE_2T3E3_RX_DESC_COLLISION_SEEN 0x00000040
|
||||
#define SBE_2T3E3_RX_DESC_FRAME_TYPE 0x00000020
|
||||
#define SBE_2T3E3_RX_DESC_RECEIVE_WATCHDOG 0x00000010
|
||||
#define SBE_2T3E3_RX_DESC_MII_ERROR 0x00000008
|
||||
#define SBE_2T3E3_RX_DESC_DRIBBLING_BIT 0x00000004
|
||||
#define SBE_2T3E3_RX_DESC_CRC_ERROR 0x00000002
|
||||
|
||||
/* RDES1 */
|
||||
#define SBE_2T3E3_RX_DESC_END_OF_RING 0x02000000
|
||||
#define SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED 0x01000000
|
||||
#define SBE_2T3E3_RX_DESC_BUFFER_2_SIZE 0x003ff800
|
||||
#define SBE_2T3E3_RX_DESC_BUFFER_1_SIZE 0x000007ff
|
||||
|
||||
/*********************/
|
||||
|
||||
typedef struct {
|
||||
u32 tdes0;
|
||||
u32 tdes1;
|
||||
u32 tdes2;
|
||||
u32 tdes3;
|
||||
} t3e3_tx_desc_t;
|
||||
|
||||
#define SBE_2T3E3_TX_DESC_RING_SIZE 256
|
||||
|
||||
/* TDES0 */
|
||||
#define SBE_2T3E3_TX_DESC_21143_OWN 0x80000000
|
||||
#define SBE_2T3E3_TX_DESC_ERROR_SUMMARY 0x00008000
|
||||
#define SBE_2T3E3_TX_DESC_TRANSMIT_JABBER_TIMEOUT 0x00004000
|
||||
#define SBE_2T3E3_TX_DESC_LOSS_OF_CARRIER 0x00000800
|
||||
#define SBE_2T3E3_TX_DESC_NO_CARRIER 0x00000400
|
||||
#define SBE_2T3E3_TX_DESC_LINK_FAIL_REPORT 0x00000004
|
||||
#define SBE_2T3E3_TX_DESC_UNDERFLOW_ERROR 0x00000002
|
||||
#define SBE_2T3E3_TX_DESC_DEFFERED 0x00000001
|
||||
|
||||
/* TDES1 */
|
||||
#define SBE_2T3E3_TX_DESC_INTERRUPT_ON_COMPLETION 0x80000000
|
||||
#define SBE_2T3E3_TX_DESC_LAST_SEGMENT 0x40000000
|
||||
#define SBE_2T3E3_TX_DESC_FIRST_SEGMENT 0x20000000
|
||||
#define SBE_2T3E3_TX_DESC_CRC_DISABLE 0x04000000
|
||||
#define SBE_2T3E3_TX_DESC_END_OF_RING 0x02000000
|
||||
#define SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED 0x01000000
|
||||
#define SBE_2T3E3_TX_DESC_DISABLE_PADDING 0x00800000
|
||||
#define SBE_2T3E3_TX_DESC_BUFFER_2_SIZE 0x003ff800
|
||||
#define SBE_2T3E3_TX_DESC_BUFFER_1_SIZE 0x000007ff
|
||||
|
||||
|
||||
#define SBE_2T3E3_MTU 1600
|
||||
#define SBE_2T3E3_CRC16_LENGTH 2
|
||||
#define SBE_2T3E3_CRC32_LENGTH 4
|
||||
|
||||
#define MCLBYTES (SBE_2T3E3_MTU + 128)
|
||||
|
||||
struct channel {
|
||||
struct pci_dev *pdev;
|
||||
struct net_device *dev;
|
||||
struct card *card;
|
||||
unsigned long addr; /* DECchip */
|
||||
|
||||
int leds;
|
||||
|
||||
/* pci specific */
|
||||
struct {
|
||||
u32 slot; /* should be 0 or 1 */
|
||||
u32 command;
|
||||
u8 cache_size;
|
||||
} h;
|
||||
|
||||
/* statistics */
|
||||
t3e3_stats_t s;
|
||||
|
||||
/* running */
|
||||
struct {
|
||||
u32 flags;
|
||||
} r;
|
||||
|
||||
/* parameters */
|
||||
t3e3_param_t p;
|
||||
|
||||
u32 liu_regs[SBE_2T3E3_LIU_REG_MAX]; /* LIU registers */
|
||||
u32 framer_regs[SBE_2T3E3_FRAMER_REG_MAX]; /* Framer registers */
|
||||
|
||||
/* Ethernet Controller */
|
||||
struct {
|
||||
u_int16_t card_serial_number[3];
|
||||
|
||||
u32 reg[SBE_2T3E3_21143_REG_MAX]; /* registers i.e. CSR */
|
||||
|
||||
u32 interrupt_enable_mask;
|
||||
|
||||
/* receive chain/ring */
|
||||
t3e3_rx_desc_t *rx_ring;
|
||||
struct sk_buff *rx_data[SBE_2T3E3_RX_DESC_RING_SIZE];
|
||||
u32 rx_ring_current_read;
|
||||
|
||||
/* transmit chain/ring */
|
||||
t3e3_tx_desc_t *tx_ring;
|
||||
struct sk_buff *tx_data[SBE_2T3E3_TX_DESC_RING_SIZE];
|
||||
u32 tx_ring_current_read;
|
||||
u32 tx_ring_current_write;
|
||||
int tx_full;
|
||||
int tx_free_cnt;
|
||||
spinlock_t tx_lock;
|
||||
} ether;
|
||||
|
||||
int32_t interrupt_active;
|
||||
int32_t rcv_count;
|
||||
};
|
||||
|
||||
struct card {
|
||||
spinlock_t bootrom_lock;
|
||||
unsigned long bootrom_addr;
|
||||
struct timer_list timer; /* for updating LEDs */
|
||||
struct channel channels[0];
|
||||
};
|
||||
|
||||
#define SBE_2T3E3_FLAG_NETWORK_UP 0x00000001
|
||||
#define SBE_2T3E3_FLAG_NO_ERROR_MESSAGES 0x00000002
|
||||
|
||||
extern const u32 cpld_reg_map[][2];
|
||||
extern const u32 cpld_val_map[][2];
|
||||
extern const u32 t3e3_framer_reg_map[];
|
||||
extern const u32 t3e3_liu_reg_map[];
|
||||
|
||||
void t3e3_init(struct channel *);
|
||||
void t3e3_if_up(struct channel *);
|
||||
void t3e3_if_down(struct channel *);
|
||||
int t3e3_if_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
void t3e3_if_config(struct channel *, u32, char *,
|
||||
t3e3_resp_t *, int *);
|
||||
void t3e3_set_frame_type(struct channel *, u32);
|
||||
u32 t3e3_eeprom_read_word(struct channel *, u32);
|
||||
void t3e3_read_card_serial_number(struct channel *);
|
||||
|
||||
/* interrupt handlers */
|
||||
irqreturn_t t3e3_intr(int irq, void *dev_instance);
|
||||
void dc_intr(struct channel *);
|
||||
void dc_intr_rx(struct channel *);
|
||||
void dc_intr_tx(struct channel *);
|
||||
void dc_intr_tx_underflow(struct channel *);
|
||||
void exar7250_intr(struct channel *);
|
||||
void exar7250_E3_intr(struct channel *, u32);
|
||||
void exar7250_T3_intr(struct channel *, u32);
|
||||
|
||||
/* Ethernet controller */
|
||||
u32 bootrom_read(struct channel *, u32);
|
||||
void bootrom_write(struct channel *, u32, u32);
|
||||
void dc_init(struct channel *);
|
||||
void dc_start(struct channel *);
|
||||
void dc_stop(struct channel *);
|
||||
void dc_start_intr(struct channel *);
|
||||
void dc_stop_intr(struct channel *);
|
||||
void dc_reset(struct channel *);
|
||||
void dc_restart(struct channel *);
|
||||
void dc_receiver_onoff(struct channel *, u32);
|
||||
void dc_transmitter_onoff(struct channel *, u32);
|
||||
void dc_set_loopback(struct channel *, u32);
|
||||
u32 dc_init_descriptor_list(struct channel *);
|
||||
void dc_clear_descriptor_list(struct channel *);
|
||||
void dc_drop_descriptor_list(struct channel *);
|
||||
void dc_set_output_port(struct channel *);
|
||||
void t3e3_sc_init(struct channel *);
|
||||
|
||||
/* CPLD */
|
||||
void cpld_init(struct channel *sc);
|
||||
u32 cpld_read(struct channel *sc, u32 reg);
|
||||
void cpld_set_crc(struct channel *, u32);
|
||||
void cpld_start_intr(struct channel *);
|
||||
void cpld_stop_intr(struct channel *);
|
||||
#if 0
|
||||
void cpld_led_onoff(struct channel *, u32, u32, u32, u32);
|
||||
#endif
|
||||
void cpld_set_clock(struct channel *sc, u32 mode);
|
||||
void cpld_set_scrambler(struct channel *, u32);
|
||||
void cpld_select_panel(struct channel *, u32);
|
||||
void cpld_set_frame_mode(struct channel *, u32);
|
||||
void cpld_set_frame_type(struct channel *, u32);
|
||||
void cpld_set_pad_count(struct channel *, u32);
|
||||
void cpld_set_fractional_mode(struct channel *, u32, u32, u32);
|
||||
void cpld_LOS_update(struct channel *);
|
||||
|
||||
/* Framer */
|
||||
extern u32 exar7250_read(struct channel *, u32);
|
||||
extern void exar7250_write(struct channel *, u32, u32);
|
||||
void exar7250_init(struct channel *);
|
||||
void exar7250_start_intr(struct channel *, u32);
|
||||
void exar7250_stop_intr(struct channel *, u32);
|
||||
void exar7250_set_frame_type(struct channel *, u32);
|
||||
void exar7250_set_loopback(struct channel *, u32);
|
||||
void exar7250_unipolar_onoff(struct channel *, u32);
|
||||
|
||||
/* LIU */
|
||||
u32 exar7300_read(struct channel *, u32);
|
||||
void exar7300_write(struct channel *, u32, u32);
|
||||
void exar7300_init(struct channel *);
|
||||
void exar7300_line_build_out_onoff(struct channel *, u32);
|
||||
void exar7300_set_frame_type(struct channel *, u32);
|
||||
void exar7300_set_loopback(struct channel *, u32);
|
||||
void exar7300_transmit_all_ones_onoff(struct channel *, u32);
|
||||
void exar7300_receive_equalization_onoff(struct channel *, u32);
|
||||
void exar7300_unipolar_onoff(struct channel *, u32);
|
||||
|
||||
void update_led(struct channel *, int);
|
||||
int setup_device(struct net_device *dev, struct channel *sc);
|
||||
|
||||
static inline int has_two_ports(struct pci_dev *pdev)
|
||||
{
|
||||
return pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P0;
|
||||
}
|
||||
|
||||
#define dev_to_priv(dev) (*(struct channel **) ((hdlc_device*)(dev) + 1))
|
||||
|
||||
static inline u32 dc_read(unsigned long addr, u32 reg)
|
||||
{
|
||||
return inl(addr + (reg << 3));
|
||||
}
|
||||
|
||||
static inline void dc_write(unsigned long addr, u32 reg, u32 val)
|
||||
{
|
||||
outl(val, addr + (reg << 3));
|
||||
}
|
||||
|
||||
static inline void dc_set_bits(unsigned long addr, u32 reg, u32 bits)
|
||||
{
|
||||
dc_write(addr, reg, dc_read(addr, reg) | bits);
|
||||
}
|
||||
|
||||
static inline void dc_clear_bits(unsigned long addr, u32 reg, u32 bits)
|
||||
{
|
||||
dc_write(addr, reg, dc_read(addr, reg) & ~bits);
|
||||
}
|
||||
|
||||
#define CPLD_MAP_REG(reg, sc) (cpld_reg_map[(reg)][(sc)->h.slot])
|
||||
|
||||
static inline void cpld_write(struct channel *channel, unsigned reg, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
bootrom_write(channel, CPLD_MAP_REG(reg, channel), val);
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
}
|
||||
|
||||
#define exar7250_set_bit(sc, reg, bit) \
|
||||
exar7250_write((sc), (reg), \
|
||||
exar7250_read(sc, reg) | (bit))
|
||||
|
||||
#define exar7250_clear_bit(sc, reg, bit) \
|
||||
exar7250_write((sc), (reg), \
|
||||
exar7250_read(sc, reg) & ~(bit))
|
||||
|
||||
#define exar7300_set_bit(sc, reg, bit) \
|
||||
exar7300_write((sc), (reg), \
|
||||
exar7300_read(sc, reg) | (bit))
|
||||
|
||||
#define exar7300_clear_bit(sc, reg, bit) \
|
||||
exar7300_write((sc), (reg), \
|
||||
exar7300_read(sc, reg) & ~(bit))
|
||||
|
||||
|
||||
#endif /* T3E3_H */
|
|
@ -0,0 +1,13 @@
|
|||
config SBE_2T3E3
|
||||
tristate "SBE wanPMC-2T3E3 support"
|
||||
depends on HDLC && PCI
|
||||
help
|
||||
Driver for wanPMC-2T3E3 cards by SBE Inc.
|
||||
|
||||
If you have such a card, say Y here and see
|
||||
<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
|
||||
|
||||
To compile this as a module, choose M here: the
|
||||
module will be called sbe-2t3e3.
|
||||
|
||||
If unsure, say N.
|
|
@ -0,0 +1,4 @@
|
|||
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3.o
|
||||
|
||||
sbe-2t3e3-objs := module.o netdev.o maps.o \
|
||||
main.o cpld.o intr.o ctrl.o io.o dc.o exar7250.o exar7300.o
|
|
@ -0,0 +1,6 @@
|
|||
TODO:
|
||||
- additional cleaning and tests
|
||||
- wait for the new configuration interface in generic HDLC layer and
|
||||
when available, convert the driver to it
|
||||
|
||||
Please send patches to Krzysztof Halasa <khc@pm.waw.pl>.
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include "2t3e3.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
#define bootrom_set_bit(sc, reg, bit) \
|
||||
bootrom_write((sc), (reg), \
|
||||
bootrom_read((sc), (reg)) | (bit))
|
||||
|
||||
#define bootrom_clear_bit(sc, reg, bit) \
|
||||
bootrom_write((sc), (reg), \
|
||||
bootrom_read((sc), (reg)) & ~(bit))
|
||||
|
||||
static inline void cpld_set_bit(struct channel *channel, unsigned reg, u32 bit)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
bootrom_set_bit(channel, CPLD_MAP_REG(reg, channel), bit);
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
}
|
||||
|
||||
static inline void cpld_clear_bit(struct channel *channel, unsigned reg, u32 bit)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
bootrom_clear_bit(channel, CPLD_MAP_REG(reg, channel), bit);
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
}
|
||||
|
||||
void cpld_init(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
#if 0
|
||||
/* reset LIU and Framer */
|
||||
val = cpld_val_map[SBE_2T3E3_CPLD_VAL_LIU_FRAMER_RESET][sc->h.slot];
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_STATIC_RESET, val);
|
||||
udelay(10000); /* TODO - how long? */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_STATIC_RESET, val);
|
||||
#endif
|
||||
|
||||
/* PCRA */
|
||||
val = SBE_2T3E3_CPLD_VAL_CRC32 |
|
||||
cpld_val_map[SBE_2T3E3_CPLD_VAL_LOOP_TIMING_SOURCE][sc->h.slot];
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRA, val);
|
||||
|
||||
/* PCRB */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRB, val);
|
||||
|
||||
/* PCRC */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC, val);
|
||||
|
||||
/* PBWF */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWF, val);
|
||||
|
||||
/* PBWL */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWL, val);
|
||||
|
||||
/* PLTR */
|
||||
val = SBE_2T3E3_CPLD_VAL_LCV_COUNTER;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PLTR, val);
|
||||
udelay(1000);
|
||||
|
||||
/* PLCR */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PLCR, val);
|
||||
udelay(1000);
|
||||
|
||||
/* PPFR */
|
||||
val = 0x55;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PPFR, val);
|
||||
/* TODO: this doesn't work!!! */
|
||||
|
||||
/* SERIAL_CHIP_SELECT */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT, val);
|
||||
|
||||
/* PICSR */
|
||||
val = SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED |
|
||||
SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED |
|
||||
SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PICSR, val);
|
||||
|
||||
cpld_start_intr(sc);
|
||||
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
void cpld_start_intr(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* PIER */
|
||||
val = SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ENABLE |
|
||||
SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ENABLE;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PIER, val);
|
||||
#if 0
|
||||
/*
|
||||
do you want to hang up your computer?
|
||||
ENABLE REST OF INTERRUPTS !!!
|
||||
you have been warned :).
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void cpld_stop_intr(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* PIER */
|
||||
val = 0;
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PIER, val);
|
||||
}
|
||||
|
||||
void cpld_set_frame_mode(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.frame_mode == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_FRAME_MODE_HDLC:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE |
|
||||
SBE_2T3E3_CPLD_VAL_RAW_MODE);
|
||||
exar7250_unipolar_onoff(sc, SBE_2T3E3_OFF);
|
||||
exar7300_unipolar_onoff(sc, SBE_2T3E3_OFF);
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_MODE_TRANSPARENT:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_RAW_MODE);
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE);
|
||||
exar7250_unipolar_onoff(sc, SBE_2T3E3_OFF);
|
||||
exar7300_unipolar_onoff(sc, SBE_2T3E3_OFF);
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_MODE_RAW:
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_RAW_MODE);
|
||||
exar7250_unipolar_onoff(sc, SBE_2T3E3_ON);
|
||||
exar7300_unipolar_onoff(sc, SBE_2T3E3_ON);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.frame_mode = mode;
|
||||
}
|
||||
|
||||
/* set rate of the local clock */
|
||||
void cpld_set_frame_type(struct channel *sc, u32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3);
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cpld_set_scrambler(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.scrambler == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_SCRAMBLER_OFF:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
|
||||
SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
|
||||
break;
|
||||
case SBE_2T3E3_SCRAMBLER_LARSCOM:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
|
||||
SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE);
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
|
||||
SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
|
||||
break;
|
||||
case SBE_2T3E3_SCRAMBLER_ADC_KENTROX_DIGITAL:
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
|
||||
SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE);
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
|
||||
SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.scrambler = mode;
|
||||
}
|
||||
|
||||
|
||||
void cpld_set_crc(struct channel *sc, u32 crc)
|
||||
{
|
||||
if (sc->p.crc == crc)
|
||||
return;
|
||||
|
||||
switch (crc) {
|
||||
case SBE_2T3E3_CRC_16:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_CRC32);
|
||||
break;
|
||||
case SBE_2T3E3_CRC_32:
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_CRC32);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.crc = crc;
|
||||
}
|
||||
|
||||
|
||||
void cpld_select_panel(struct channel *sc, u32 panel)
|
||||
{
|
||||
if (sc->p.panel == panel)
|
||||
return;
|
||||
switch (panel) {
|
||||
case SBE_2T3E3_PANEL_FRONT:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_REAR_PANEL);
|
||||
break;
|
||||
case SBE_2T3E3_PANEL_REAR:
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_REAR_PANEL);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
|
||||
sc->p.panel = panel;
|
||||
}
|
||||
|
||||
|
||||
extern void cpld_set_clock(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.clock_source == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_TIMING_LOCAL:
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_ALT);
|
||||
break;
|
||||
case SBE_2T3E3_TIMING_LOOP:
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
|
||||
SBE_2T3E3_CPLD_VAL_ALT);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.clock_source = mode;
|
||||
}
|
||||
|
||||
void cpld_set_pad_count(struct channel *sc, u32 count)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (sc->p.pad_count == count)
|
||||
return;
|
||||
|
||||
switch (count) {
|
||||
case SBE_2T3E3_PAD_COUNT_1:
|
||||
val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_1;
|
||||
break;
|
||||
case SBE_2T3E3_PAD_COUNT_2:
|
||||
val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_2;
|
||||
break;
|
||||
case SBE_2T3E3_PAD_COUNT_3:
|
||||
val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_3;
|
||||
break;
|
||||
case SBE_2T3E3_PAD_COUNT_4:
|
||||
val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
|
||||
SBE_2T3E3_CPLD_VAL_PAD_COUNT);
|
||||
cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB, val);
|
||||
sc->p.pad_count = count;
|
||||
}
|
||||
|
||||
void cpld_LOS_update(struct channel *sc)
|
||||
{
|
||||
u_int8_t los;
|
||||
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PICSR,
|
||||
SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED |
|
||||
SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED |
|
||||
SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED);
|
||||
los = cpld_read(sc, SBE_2T3E3_CPLD_REG_PICSR) &
|
||||
SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED;
|
||||
|
||||
if (los != sc->s.LOS)
|
||||
dev_info(&sc->pdev->dev, "SBE 2T3E3: LOS status: %s\n",
|
||||
los ? "Loss of signal" : "Signal OK");
|
||||
sc->s.LOS = los;
|
||||
}
|
||||
|
||||
void cpld_set_fractional_mode(struct channel *sc, u32 mode,
|
||||
u32 start, u32 stop)
|
||||
{
|
||||
if (mode == SBE_2T3E3_FRACTIONAL_MODE_NONE) {
|
||||
start = 0;
|
||||
stop = 0;
|
||||
}
|
||||
|
||||
if (sc->p.fractional_mode == mode && sc->p.bandwidth_start == start &&
|
||||
sc->p.bandwidth_stop == stop)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_FRACTIONAL_MODE_NONE:
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
|
||||
SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_NONE);
|
||||
break;
|
||||
case SBE_2T3E3_FRACTIONAL_MODE_0:
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
|
||||
SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_0);
|
||||
break;
|
||||
case SBE_2T3E3_FRACTIONAL_MODE_1:
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
|
||||
SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_1);
|
||||
break;
|
||||
case SBE_2T3E3_FRACTIONAL_MODE_2:
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
|
||||
SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_2);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "wrong mode in set_fractional_mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWF, start);
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWL, stop);
|
||||
|
||||
sc->p.fractional_mode = mode;
|
||||
sc->p.bandwidth_start = start;
|
||||
sc->p.bandwidth_stop = stop;
|
||||
}
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "2t3e3.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
void t3e3_set_frame_type(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.frame_type == mode)
|
||||
return;
|
||||
|
||||
if (sc->r.flags & SBE_2T3E3_FLAG_NETWORK_UP) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: changing frame type during active connection\n");
|
||||
return;
|
||||
}
|
||||
|
||||
exar7300_set_frame_type(sc, mode);
|
||||
exar7250_set_frame_type(sc, mode);
|
||||
cpld_set_frame_type(sc, mode);
|
||||
|
||||
sc->p.frame_type = mode;
|
||||
}
|
||||
|
||||
void t3e3_set_loopback(struct channel *sc, u32 mode)
|
||||
{
|
||||
u32 tx, rx;
|
||||
|
||||
if (sc->p.loopback == mode)
|
||||
return;
|
||||
|
||||
tx = sc->p.transmitter_on;
|
||||
rx = sc->p.receiver_on;
|
||||
if (tx == SBE_2T3E3_ON)
|
||||
dc_transmitter_onoff(sc, SBE_2T3E3_OFF);
|
||||
if (rx == SBE_2T3E3_ON)
|
||||
dc_receiver_onoff(sc, SBE_2T3E3_OFF);
|
||||
|
||||
/* stop current loopback if any exists */
|
||||
switch (sc->p.loopback) {
|
||||
case SBE_2T3E3_LOOPBACK_NONE:
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_ETHERNET:
|
||||
dc_set_loopback(sc, SBE_2T3E3_21143_VAL_LOOPBACK_OFF);
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_FRAMER:
|
||||
exar7250_set_loopback(sc, SBE_2T3E3_FRAMER_VAL_LOOPBACK_OFF);
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_LIU_DIGITAL:
|
||||
case SBE_2T3E3_LOOPBACK_LIU_ANALOG:
|
||||
case SBE_2T3E3_LOOPBACK_LIU_REMOTE:
|
||||
exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_OFF);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_LOOPBACK_NONE:
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_ETHERNET:
|
||||
dc_set_loopback(sc, SBE_2T3E3_21143_VAL_LOOPBACK_INTERNAL);
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_FRAMER:
|
||||
exar7250_set_loopback(sc, SBE_2T3E3_FRAMER_VAL_LOOPBACK_ON);
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_LIU_DIGITAL:
|
||||
exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_DIGITAL);
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_LIU_ANALOG:
|
||||
exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_ANALOG);
|
||||
break;
|
||||
case SBE_2T3E3_LOOPBACK_LIU_REMOTE:
|
||||
exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_REMOTE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.loopback = mode;
|
||||
|
||||
if (tx == SBE_2T3E3_ON)
|
||||
dc_transmitter_onoff(sc, SBE_2T3E3_ON);
|
||||
if (rx == SBE_2T3E3_ON)
|
||||
dc_receiver_onoff(sc, SBE_2T3E3_ON);
|
||||
}
|
||||
|
||||
|
||||
void t3e3_reg_read(struct channel *sc, u32 *reg, u32 *val)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
*val = 0;
|
||||
|
||||
switch (reg[0]) {
|
||||
case SBE_2T3E3_CHIP_21143:
|
||||
if (!(reg[1] & 7))
|
||||
*val = dc_read(sc->addr, reg[1] / 8);
|
||||
break;
|
||||
case SBE_2T3E3_CHIP_CPLD:
|
||||
for (i = 0; i < SBE_2T3E3_CPLD_REG_MAX; i++)
|
||||
if (cpld_reg_map[i][sc->h.slot] == reg[1]) {
|
||||
*val = cpld_read(sc, i);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SBE_2T3E3_CHIP_FRAMER:
|
||||
for (i = 0; i < SBE_2T3E3_FRAMER_REG_MAX; i++)
|
||||
if (t3e3_framer_reg_map[i] == reg[1]) {
|
||||
*val = exar7250_read(sc, i);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SBE_2T3E3_CHIP_LIU:
|
||||
for (i = 0; i < SBE_2T3E3_LIU_REG_MAX; i++)
|
||||
if (t3e3_liu_reg_map[i] == reg[1]) {
|
||||
*val = exar7300_read(sc, i);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void t3e3_reg_write(struct channel *sc, u32 *reg)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
switch (reg[0]) {
|
||||
case SBE_2T3E3_CHIP_21143:
|
||||
dc_write(sc->addr, reg[1], reg[2]);
|
||||
break;
|
||||
case SBE_2T3E3_CHIP_CPLD:
|
||||
for (i = 0; i < SBE_2T3E3_CPLD_REG_MAX; i++)
|
||||
if (cpld_reg_map[i][sc->h.slot] == reg[1]) {
|
||||
cpld_write(sc, i, reg[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SBE_2T3E3_CHIP_FRAMER:
|
||||
for (i = 0; i < SBE_2T3E3_FRAMER_REG_MAX; i++)
|
||||
if (t3e3_framer_reg_map[i] == reg[1]) {
|
||||
exar7250_write(sc, i, reg[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SBE_2T3E3_CHIP_LIU:
|
||||
for (i = 0; i < SBE_2T3E3_LIU_REG_MAX; i++)
|
||||
if (t3e3_liu_reg_map[i] == reg[1]) {
|
||||
exar7300_write(sc, i, reg[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void t3e3_port_get(struct channel *sc, t3e3_param_t *param)
|
||||
{
|
||||
memcpy(param, &(sc->p), sizeof(t3e3_param_t));
|
||||
}
|
||||
|
||||
void t3e3_port_set(struct channel *sc, t3e3_param_t *param)
|
||||
{
|
||||
if (param->frame_mode != 0xff)
|
||||
cpld_set_frame_mode(sc, param->frame_mode);
|
||||
|
||||
if (param->fractional_mode != 0xff)
|
||||
cpld_set_fractional_mode(sc, param->fractional_mode,
|
||||
param->bandwidth_start,
|
||||
param->bandwidth_stop);
|
||||
|
||||
if (param->pad_count != 0xff)
|
||||
cpld_set_pad_count(sc, param->pad_count);
|
||||
|
||||
if (param->crc != 0xff)
|
||||
cpld_set_crc(sc, param->crc);
|
||||
|
||||
if (param->receiver_on != 0xff)
|
||||
dc_receiver_onoff(sc, param->receiver_on);
|
||||
|
||||
if (param->transmitter_on != 0xff)
|
||||
dc_transmitter_onoff(sc, param->transmitter_on);
|
||||
|
||||
if (param->frame_type != 0xff)
|
||||
t3e3_set_frame_type(sc, param->frame_type);
|
||||
|
||||
if (param->panel != 0xff)
|
||||
cpld_select_panel(sc, param->panel);
|
||||
|
||||
if (param->line_build_out != 0xff)
|
||||
exar7300_line_build_out_onoff(sc, param->line_build_out);
|
||||
|
||||
if (param->receive_equalization != 0xff)
|
||||
exar7300_receive_equalization_onoff(sc, param->receive_equalization);
|
||||
|
||||
if (param->transmit_all_ones != 0xff)
|
||||
exar7300_transmit_all_ones_onoff(sc, param->transmit_all_ones);
|
||||
|
||||
if (param->loopback != 0xff)
|
||||
t3e3_set_loopback(sc, param->loopback);
|
||||
|
||||
if (param->clock_source != 0xff)
|
||||
cpld_set_clock(sc, param->clock_source);
|
||||
|
||||
if (param->scrambler != 0xff)
|
||||
cpld_set_scrambler(sc, param->scrambler);
|
||||
}
|
||||
|
||||
void t3e3_port_get_stats(struct channel *sc,
|
||||
t3e3_stats_t *stats)
|
||||
{
|
||||
u32 result;
|
||||
|
||||
sc->s.LOC = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_IO_CONTROL)
|
||||
& SBE_2T3E3_FRAMER_VAL_LOSS_OF_CLOCK_STATUS ? 1 : 0;
|
||||
|
||||
switch (sc->p.frame_type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2);
|
||||
sc->s.LOF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_LOF ? 1 : 0;
|
||||
sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0;
|
||||
#if 0
|
||||
sc->s.LOS = result & SBE_2T3E3_FRAMER_VAL_E3_RX_LOS ? 1 : 0;
|
||||
#else
|
||||
cpld_LOS_update(sc);
|
||||
#endif
|
||||
sc->s.AIS = result & SBE_2T3E3_FRAMER_VAL_E3_RX_AIS ? 1 : 0;
|
||||
sc->s.FERF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_FERF ? 1 : 0;
|
||||
break;
|
||||
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS);
|
||||
sc->s.AIS = result & SBE_2T3E3_FRAMER_VAL_T3_RX_AIS ? 1 : 0;
|
||||
#if 0
|
||||
sc->s.LOS = result & SBE_2T3E3_FRAMER_VAL_T3_RX_LOS ? 1 : 0;
|
||||
#else
|
||||
cpld_LOS_update(sc);
|
||||
#endif
|
||||
sc->s.IDLE = result & SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE ? 1 : 0;
|
||||
sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0;
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_STATUS);
|
||||
sc->s.FERF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_FERF ? 1 : 0;
|
||||
sc->s.AIC = result & SBE_2T3E3_FRAMER_VAL_T3_RX_AIC ? 1 : 0;
|
||||
sc->s.FEBE_code = result & SBE_2T3E3_FRAMER_VAL_T3_RX_FEBE;
|
||||
|
||||
sc->s.FEAC = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_LCV_EVENT_COUNT_MSB) << 8;
|
||||
result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
|
||||
sc->s.LCV += result;
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_FRAMING_BIT_ERROR_EVENT_COUNT_MSB) << 8;
|
||||
result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
|
||||
sc->s.FRAMING_BIT += result;
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_PARITY_ERROR_EVENT_COUNT_MSB) << 8;
|
||||
result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
|
||||
sc->s.PARITY_ERROR += result;
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_FEBE_EVENT_COUNT_MSB) << 8;
|
||||
result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
|
||||
sc->s.FEBE_count += result;
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_CP_BIT_ERROR_EVENT_COUNT_MSB) << 8;
|
||||
result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
|
||||
sc->s.CP_BIT += result;
|
||||
|
||||
memcpy(stats, &(sc->s), sizeof(t3e3_stats_t));
|
||||
}
|
||||
|
||||
void t3e3_port_del_stats(struct channel *sc)
|
||||
{
|
||||
memset(&(sc->s), 0, sizeof(t3e3_stats_t));
|
||||
}
|
||||
|
||||
void t3e3_if_config(struct channel *sc, u32 cmd, char *set,
|
||||
t3e3_resp_t *ret, int *rlen)
|
||||
{
|
||||
t3e3_param_t *param = (t3e3_param_t *)set;
|
||||
u32 *data = (u32 *)set;
|
||||
|
||||
/* turn off all interrupt */
|
||||
/* cpld_stop_intr(sc); */
|
||||
|
||||
switch (cmd) {
|
||||
case SBE_2T3E3_PORT_GET:
|
||||
t3e3_port_get(sc, &(ret->u.param));
|
||||
*rlen = sizeof(ret->u.param);
|
||||
break;
|
||||
case SBE_2T3E3_PORT_SET:
|
||||
t3e3_port_set(sc, param);
|
||||
*rlen = 0;
|
||||
break;
|
||||
case SBE_2T3E3_PORT_GET_STATS:
|
||||
t3e3_port_get_stats(sc, &(ret->u.stats));
|
||||
*rlen = sizeof(ret->u.stats);
|
||||
break;
|
||||
case SBE_2T3E3_PORT_DEL_STATS:
|
||||
t3e3_port_del_stats(sc);
|
||||
*rlen = 0;
|
||||
break;
|
||||
case SBE_2T3E3_PORT_READ_REGS:
|
||||
t3e3_reg_read(sc, data, &(ret->u.data));
|
||||
*rlen = sizeof(ret->u.data);
|
||||
break;
|
||||
case SBE_2T3E3_PORT_WRITE_REGS:
|
||||
#if 0
|
||||
printk(KERN_DEBUG "SBE_2T3E3_PORT_WRITE_REGS, 0x%x, 0x%x, 0x%x\n",
|
||||
((int*)data)[0], ((int*)data)[1], ((int*)data)[2]);
|
||||
#endif
|
||||
t3e3_reg_write(sc, data);
|
||||
*rlen = 0;
|
||||
break;
|
||||
case SBE_2T3E3_LOG_LEVEL:
|
||||
*rlen = 0;
|
||||
break;
|
||||
default:
|
||||
*rlen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* turn on interrupt */
|
||||
/* cpld_start_intr(sc); */
|
||||
}
|
||||
|
||||
void t3e3_sc_init(struct channel *sc)
|
||||
{
|
||||
memset(sc, 0, sizeof(*sc));
|
||||
|
||||
sc->p.frame_mode = SBE_2T3E3_FRAME_MODE_HDLC;
|
||||
sc->p.fractional_mode = SBE_2T3E3_FRACTIONAL_MODE_NONE;
|
||||
sc->p.crc = SBE_2T3E3_CRC_32;
|
||||
sc->p.receiver_on = SBE_2T3E3_OFF;
|
||||
sc->p.transmitter_on = SBE_2T3E3_OFF;
|
||||
sc->p.frame_type = SBE_2T3E3_FRAME_TYPE_T3_CBIT;
|
||||
sc->p.panel = SBE_2T3E3_PANEL_FRONT;
|
||||
sc->p.line_build_out = SBE_2T3E3_OFF;
|
||||
sc->p.receive_equalization = SBE_2T3E3_OFF;
|
||||
sc->p.transmit_all_ones = SBE_2T3E3_OFF;
|
||||
sc->p.loopback = SBE_2T3E3_LOOPBACK_NONE;
|
||||
sc->p.clock_source = SBE_2T3E3_TIMING_LOCAL;
|
||||
sc->p.scrambler = SBE_2T3E3_SCRAMBLER_OFF;
|
||||
sc->p.pad_count = SBE_2T3E3_PAD_COUNT_1;
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#ifndef CTRL_H
|
||||
#define CTRL_H
|
||||
|
||||
#define SBE_2T3E3_OFF 0
|
||||
#define SBE_2T3E3_ON 1
|
||||
|
||||
#define SBE_2T3E3_LED_NONE 0
|
||||
#define SBE_2T3E3_LED_GREEN 1
|
||||
#define SBE_2T3E3_LED_YELLOW 2
|
||||
|
||||
#define SBE_2T3E3_CABLE_LENGTH_LESS_THAN_255_FEET 0
|
||||
#define SBE_2T3E3_CABLE_LENGTH_GREATER_THAN_255_FEET 1
|
||||
|
||||
#define SBE_2T3E3_CRC_16 0
|
||||
#define SBE_2T3E3_CRC_32 1
|
||||
|
||||
#define SBE_2T3E3_PANEL_FRONT 0
|
||||
#define SBE_2T3E3_PANEL_REAR 1
|
||||
|
||||
#define SBE_2T3E3_FRAME_MODE_HDLC 0
|
||||
#define SBE_2T3E3_FRAME_MODE_TRANSPARENT 1
|
||||
#define SBE_2T3E3_FRAME_MODE_RAW 2
|
||||
|
||||
#define SBE_2T3E3_FRAME_TYPE_E3_G751 0
|
||||
#define SBE_2T3E3_FRAME_TYPE_E3_G832 1
|
||||
#define SBE_2T3E3_FRAME_TYPE_T3_CBIT 2
|
||||
#define SBE_2T3E3_FRAME_TYPE_T3_M13 3
|
||||
|
||||
#define SBE_2T3E3_FRACTIONAL_MODE_NONE 0
|
||||
#define SBE_2T3E3_FRACTIONAL_MODE_0 1
|
||||
#define SBE_2T3E3_FRACTIONAL_MODE_1 2
|
||||
#define SBE_2T3E3_FRACTIONAL_MODE_2 3
|
||||
|
||||
#define SBE_2T3E3_SCRAMBLER_OFF 0
|
||||
#define SBE_2T3E3_SCRAMBLER_LARSCOM 1
|
||||
#define SBE_2T3E3_SCRAMBLER_ADC_KENTROX_DIGITAL 2
|
||||
|
||||
#define SBE_2T3E3_TIMING_LOCAL 0
|
||||
#define SBE_2T3E3_TIMING_LOOP 1
|
||||
|
||||
#define SBE_2T3E3_LOOPBACK_NONE 0
|
||||
#define SBE_2T3E3_LOOPBACK_ETHERNET 1
|
||||
#define SBE_2T3E3_LOOPBACK_FRAMER 2
|
||||
#define SBE_2T3E3_LOOPBACK_LIU_DIGITAL 3
|
||||
#define SBE_2T3E3_LOOPBACK_LIU_ANALOG 4
|
||||
#define SBE_2T3E3_LOOPBACK_LIU_REMOTE 5
|
||||
|
||||
#define SBE_2T3E3_PAD_COUNT_1 1
|
||||
#define SBE_2T3E3_PAD_COUNT_2 2
|
||||
#define SBE_2T3E3_PAD_COUNT_3 3
|
||||
#define SBE_2T3E3_PAD_COUNT_4 4
|
||||
|
||||
#define SBE_2T3E3_CHIP_21143 0
|
||||
#define SBE_2T3E3_CHIP_CPLD 1
|
||||
#define SBE_2T3E3_CHIP_FRAMER 2
|
||||
#define SBE_2T3E3_CHIP_LIU 3
|
||||
|
||||
#define SBE_2T3E3_LOG_LEVEL_NONE 0
|
||||
#define SBE_2T3E3_LOG_LEVEL_ERROR 1
|
||||
#define SBE_2T3E3_LOG_LEVEL_WARNING 2
|
||||
#define SBE_2T3E3_LOG_LEVEL_INFO 3
|
||||
|
||||
/* commands */
|
||||
#define SBE_2T3E3_PORT_GET 0
|
||||
#define SBE_2T3E3_PORT_SET 1
|
||||
#define SBE_2T3E3_PORT_GET_STATS 2
|
||||
#define SBE_2T3E3_PORT_DEL_STATS 3
|
||||
#define SBE_2T3E3_PORT_READ_REGS 4
|
||||
#define SBE_2T3E3_LOG_LEVEL 5
|
||||
#define SBE_2T3E3_PORT_WRITE_REGS 6
|
||||
|
||||
#define NG_SBE_2T3E3_NODE_TYPE "sbe2T3E3"
|
||||
#define NG_SBE_2T3E3_COOKIE 0x03800891
|
||||
|
||||
typedef struct t3e3_param {
|
||||
u_int8_t frame_mode; /* FRAME_MODE_* */
|
||||
u_int8_t crc; /* CRC_* */
|
||||
u_int8_t receiver_on; /* ON/OFF */
|
||||
u_int8_t transmitter_on; /* ON/OFF */
|
||||
u_int8_t frame_type; /* FRAME_TYPE_* */
|
||||
u_int8_t panel; /* PANEL_* */
|
||||
u_int8_t line_build_out; /* ON/OFF */
|
||||
u_int8_t receive_equalization; /* ON/OFF */
|
||||
u_int8_t transmit_all_ones; /* ON/OFF */
|
||||
u_int8_t loopback; /* LOOPBACK_* */
|
||||
u_int8_t clock_source; /* TIMING_* */
|
||||
u_int8_t scrambler; /* SCRAMBLER_* */
|
||||
u_int8_t pad_count; /* PAD_COUNT_* */
|
||||
u_int8_t log_level; /* LOG_LEVEL_* - unused */
|
||||
u_int8_t fractional_mode; /* FRACTIONAL_MODE_* */
|
||||
u_int8_t bandwidth_start; /* 0-255 */
|
||||
u_int8_t bandwidth_stop; /* 0-255 */
|
||||
} t3e3_param_t;
|
||||
|
||||
typedef struct t3e3_stats {
|
||||
u_int64_t in_bytes;
|
||||
u32 in_packets, in_dropped;
|
||||
u32 in_errors, in_error_desc, in_error_coll, in_error_drib,
|
||||
in_error_crc, in_error_mii;
|
||||
u_int64_t out_bytes;
|
||||
u32 out_packets, out_dropped;
|
||||
u32 out_errors, out_error_jab, out_error_lost_carr,
|
||||
out_error_no_carr, out_error_link_fail, out_error_underflow,
|
||||
out_error_dereferred;
|
||||
u_int8_t LOC, LOF, OOF, LOS, AIS, FERF, IDLE, AIC, FEAC;
|
||||
u_int16_t FEBE_code;
|
||||
u32 LCV, FRAMING_BIT, PARITY_ERROR, FEBE_count, CP_BIT;
|
||||
} t3e3_stats_t;
|
||||
|
||||
|
||||
typedef struct t3e3_resp {
|
||||
union {
|
||||
t3e3_param_t param;
|
||||
t3e3_stats_t stats;
|
||||
u32 data;
|
||||
} u;
|
||||
} t3e3_resp_t;
|
||||
|
||||
#endif /* CTRL_H */
|
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include "2t3e3.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
void dc_init(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
dc_stop(sc);
|
||||
/*dc_reset(sc);*/ /* do not want to reset here */
|
||||
|
||||
/*
|
||||
* BUS_MODE (CSR0)
|
||||
*/
|
||||
val = SBE_2T3E3_21143_VAL_READ_LINE_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_READ_MULTIPLE_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_AUTOMATIC_POLLING_200us |
|
||||
SBE_2T3E3_21143_VAL_BUS_ARBITRATION_RR;
|
||||
|
||||
if (sc->h.command & 16)
|
||||
val |= SBE_2T3E3_21143_VAL_WRITE_AND_INVALIDATE_ENABLE;
|
||||
|
||||
switch (sc->h.cache_size) {
|
||||
case 32:
|
||||
val |= SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_32;
|
||||
break;
|
||||
case 16:
|
||||
val |= SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_16;
|
||||
break;
|
||||
case 8:
|
||||
val |= SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_BUS_MODE, val);
|
||||
|
||||
/* OPERATION_MODE (CSR6) */
|
||||
val = SBE_2T3E3_21143_VAL_RECEIVE_ALL |
|
||||
SBE_2T3E3_21143_VAL_MUST_BE_ONE |
|
||||
SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_1 |
|
||||
SBE_2T3E3_21143_VAL_LOOPBACK_OFF |
|
||||
SBE_2T3E3_21143_VAL_PASS_ALL_MULTICAST |
|
||||
SBE_2T3E3_21143_VAL_PROMISCUOUS_MODE |
|
||||
SBE_2T3E3_21143_VAL_PASS_BAD_FRAMES;
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, val);
|
||||
if (sc->p.loopback == SBE_2T3E3_LOOPBACK_ETHERNET)
|
||||
sc->p.loopback = SBE_2T3E3_LOOPBACK_NONE;
|
||||
|
||||
#if 0 /* No need to clear this register - and it may be in use */
|
||||
/*
|
||||
* BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT (CSR9)
|
||||
*/
|
||||
val = 0;
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, val);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL (CSR11)
|
||||
*/
|
||||
val = SBE_2T3E3_21143_VAL_CYCLE_SIZE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_TIMER |
|
||||
SBE_2T3E3_21143_VAL_NUMBER_OF_TRANSMIT_PACKETS |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_TIMER |
|
||||
SBE_2T3E3_21143_VAL_NUMBER_OF_RECEIVE_PACKETS;
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL, val);
|
||||
|
||||
/* prepare descriptors and data for receive and transmit procecsses */
|
||||
if (dc_init_descriptor_list(sc) != 0)
|
||||
return;
|
||||
|
||||
/* clear ethernet interrupts status */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, 0xFFFFFFFF);
|
||||
|
||||
/* SIA mode registers */
|
||||
dc_set_output_port(sc);
|
||||
}
|
||||
|
||||
void dc_start(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NETWORK_UP))
|
||||
return;
|
||||
|
||||
dc_init(sc);
|
||||
|
||||
/* get actual LOS and OOF status */
|
||||
switch (sc->p.frame_type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2);
|
||||
dev_dbg(&sc->pdev->dev, "Start Framer Rx Status = %02X\n", val);
|
||||
sc->s.OOF = val & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0;
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS);
|
||||
dev_dbg(&sc->pdev->dev, "Start Framer Rx Status = %02X\n", val);
|
||||
sc->s.OOF = val & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cpld_LOS_update(sc);
|
||||
|
||||
/* start receive and transmit processes */
|
||||
dc_transmitter_onoff(sc, SBE_2T3E3_ON);
|
||||
dc_receiver_onoff(sc, SBE_2T3E3_ON);
|
||||
|
||||
/* start interrupts */
|
||||
dc_start_intr(sc);
|
||||
}
|
||||
|
||||
#define MAX_INT_WAIT_CNT 12000
|
||||
void dc_stop(struct channel *sc)
|
||||
{
|
||||
int wcnt;
|
||||
|
||||
/* stop receive and transmit processes */
|
||||
dc_receiver_onoff(sc, SBE_2T3E3_OFF);
|
||||
dc_transmitter_onoff(sc, SBE_2T3E3_OFF);
|
||||
|
||||
/* turn off ethernet interrupts */
|
||||
dc_stop_intr(sc);
|
||||
|
||||
/* wait to ensure the interrupts have been completed */
|
||||
for (wcnt = 0; wcnt < MAX_INT_WAIT_CNT; wcnt++) {
|
||||
udelay(5);
|
||||
if (!sc->interrupt_active)
|
||||
break;
|
||||
}
|
||||
if (wcnt >= MAX_INT_WAIT_CNT)
|
||||
dev_warn(&sc->pdev->dev, "SBE 2T3E3: Interrupt active too long\n");
|
||||
|
||||
/* clear all receive/transmit data */
|
||||
dc_drop_descriptor_list(sc);
|
||||
}
|
||||
|
||||
void dc_start_intr(struct channel *sc)
|
||||
{
|
||||
if (sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE && sc->s.OOF)
|
||||
return;
|
||||
|
||||
if (sc->p.receiver_on || sc->p.transmitter_on) {
|
||||
if (!sc->ether.interrupt_enable_mask)
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, 0xFFFFFFFF);
|
||||
|
||||
sc->ether.interrupt_enable_mask =
|
||||
SBE_2T3E3_21143_VAL_NORMAL_INTERRUPT_SUMMARY_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_ABNORMAL_INTERRUPT_SUMMARY_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_STOPPED_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_STOPPED_ENABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT_ENABLE;
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE,
|
||||
sc->ether.interrupt_enable_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void dc_stop_intr(struct channel *sc)
|
||||
{
|
||||
sc->ether.interrupt_enable_mask = 0;
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, 0);
|
||||
}
|
||||
|
||||
void dc_reset(struct channel *sc)
|
||||
{
|
||||
/* turn off ethernet interrupts */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, 0);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, 0xFFFFFFFF);
|
||||
|
||||
/* software reset */
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_BUS_MODE,
|
||||
SBE_2T3E3_21143_VAL_SOFTWARE_RESET);
|
||||
udelay(4); /* 50 PCI cycles < 2us */
|
||||
|
||||
/* clear hardware configuration */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_BUS_MODE, 0);
|
||||
|
||||
/* clear software configuration */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, 0);
|
||||
|
||||
/* turn off SIA reset */
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY,
|
||||
SBE_2T3E3_21143_VAL_SIA_RESET);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_TRANSMIT_AND_RECEIVE, 0);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_AND_GENERAL_PURPOSE_PORT, 0);
|
||||
}
|
||||
|
||||
|
||||
void dc_receiver_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
u32 i, state = 0;
|
||||
|
||||
if (sc->p.receiver_on == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_OFF:
|
||||
if (dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE) &
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_START) {
|
||||
dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_START);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
state = dc_read(sc->addr, SBE_2T3E3_21143_REG_STATUS) &
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STATE;
|
||||
if (state == SBE_2T3E3_21143_VAL_RX_STOPPED)
|
||||
break;
|
||||
udelay(5);
|
||||
}
|
||||
if (state != SBE_2T3E3_21143_VAL_RX_STOPPED)
|
||||
dev_warn(&sc->pdev->dev, "SBE 2T3E3: Rx failed to stop\n");
|
||||
else
|
||||
dev_info(&sc->pdev->dev, "SBE 2T3E3: Rx off\n");
|
||||
}
|
||||
break;
|
||||
case SBE_2T3E3_ON:
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_START);
|
||||
udelay(100);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_POLL_DEMAND, 0xFFFFFFFF);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.receiver_on = mode;
|
||||
}
|
||||
|
||||
void dc_transmitter_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
u32 i, state = 0;
|
||||
|
||||
if (sc->p.transmitter_on == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_OFF:
|
||||
if (dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE) &
|
||||
SBE_2T3E3_21143_VAL_TRANSMISSION_START) {
|
||||
dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_TRANSMISSION_START);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
state = dc_read(sc->addr, SBE_2T3E3_21143_REG_STATUS) &
|
||||
SBE_2T3E3_21143_VAL_TRANSMISSION_PROCESS_STATE;
|
||||
if (state == SBE_2T3E3_21143_VAL_TX_STOPPED)
|
||||
break;
|
||||
udelay(5);
|
||||
}
|
||||
if (state != SBE_2T3E3_21143_VAL_TX_STOPPED)
|
||||
dev_warn(&sc->pdev->dev, "SBE 2T3E3: Tx failed to stop\n");
|
||||
}
|
||||
break;
|
||||
case SBE_2T3E3_ON:
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_TRANSMISSION_START);
|
||||
udelay(100);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_POLL_DEMAND, 0xFFFFFFFF);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.transmitter_on = mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dc_set_loopback(struct channel *sc, u32 mode)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_21143_VAL_LOOPBACK_OFF:
|
||||
case SBE_2T3E3_21143_VAL_LOOPBACK_INTERNAL:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* restart SIA */
|
||||
dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY,
|
||||
SBE_2T3E3_21143_VAL_SIA_RESET);
|
||||
udelay(1000);
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY,
|
||||
SBE_2T3E3_21143_VAL_SIA_RESET);
|
||||
#endif
|
||||
|
||||
/* select loopback mode */
|
||||
val = dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE) &
|
||||
~SBE_2T3E3_21143_VAL_OPERATING_MODE;
|
||||
val |= mode;
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, val);
|
||||
|
||||
if (mode == SBE_2T3E3_21143_VAL_LOOPBACK_OFF)
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE);
|
||||
else
|
||||
dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE);
|
||||
}
|
||||
|
||||
u32 dc_init_descriptor_list(struct channel *sc)
|
||||
{
|
||||
u32 i, j;
|
||||
struct sk_buff *m;
|
||||
|
||||
if (sc->ether.rx_ring == NULL)
|
||||
sc->ether.rx_ring = kzalloc(SBE_2T3E3_RX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_rx_desc_t), GFP_KERNEL);
|
||||
if (sc->ether.rx_ring == NULL) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (sc->ether.tx_ring == NULL)
|
||||
sc->ether.tx_ring = kzalloc(SBE_2T3E3_TX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_tx_desc_t), GFP_KERNEL);
|
||||
if (sc->ether.tx_ring == NULL) {
|
||||
#ifdef T3E3_USE_CONTIGMALLOC
|
||||
t3e3_contigmemory_size = SBE_2T3E3_RX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_rx_desc_t);
|
||||
#endif
|
||||
kfree(sc->ether.rx_ring);
|
||||
sc->ether.rx_ring = NULL;
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Receive ring
|
||||
*/
|
||||
for (i = 0; i < SBE_2T3E3_RX_DESC_RING_SIZE; i++) {
|
||||
sc->ether.rx_ring[i].rdes0 = SBE_2T3E3_RX_DESC_21143_OWN;
|
||||
sc->ether.rx_ring[i].rdes1 =
|
||||
SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED | SBE_2T3E3_MTU;
|
||||
|
||||
if (sc->ether.rx_data[i] == NULL) {
|
||||
if (!(m = dev_alloc_skb(MCLBYTES))) {
|
||||
for (j = 0; j < i; j++) {
|
||||
dev_kfree_skb_any(sc->ether.rx_data[j]);
|
||||
sc->ether.rx_data[j] = NULL;
|
||||
}
|
||||
#ifdef T3E3_USE_CONTIGMALLOC
|
||||
t3e3_contigmemory_size = SBE_2T3E3_RX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_rx_desc_t);
|
||||
#endif
|
||||
kfree(sc->ether.rx_ring);
|
||||
sc->ether.rx_ring = NULL;
|
||||
#ifdef T3E3_USE_CONTIGMALLOC
|
||||
t3e3_contigmemory_size = SBE_2T3E3_TX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_tx_desc_t);
|
||||
#endif
|
||||
kfree(sc->ether.tx_ring);
|
||||
sc->ether.tx_ring = NULL;
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: token_alloc err:"
|
||||
" no buffer space for RX ring\n");
|
||||
return ENOBUFS;
|
||||
}
|
||||
sc->ether.rx_data[i] = m;
|
||||
}
|
||||
sc->ether.rx_ring[i].rdes2 = virt_to_phys(sc->ether.rx_data[i]->data);
|
||||
|
||||
sc->ether.rx_ring[i].rdes3 = virt_to_phys(
|
||||
&sc->ether.rx_ring[(i + 1) % SBE_2T3E3_RX_DESC_RING_SIZE]);
|
||||
}
|
||||
sc->ether.rx_ring[SBE_2T3E3_RX_DESC_RING_SIZE - 1].rdes1 |=
|
||||
SBE_2T3E3_RX_DESC_END_OF_RING;
|
||||
sc->ether.rx_ring_current_read = 0;
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS,
|
||||
virt_to_phys(&sc->ether.rx_ring[0]));
|
||||
|
||||
/*
|
||||
* Transmit ring
|
||||
*/
|
||||
for (i = 0; i < SBE_2T3E3_TX_DESC_RING_SIZE; i++) {
|
||||
sc->ether.tx_ring[i].tdes0 = 0;
|
||||
sc->ether.tx_ring[i].tdes1 = SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED |
|
||||
SBE_2T3E3_TX_DESC_DISABLE_PADDING;
|
||||
|
||||
sc->ether.tx_ring[i].tdes2 = 0;
|
||||
sc->ether.tx_data[i] = NULL;
|
||||
|
||||
sc->ether.tx_ring[i].tdes3 = virt_to_phys(
|
||||
&sc->ether.tx_ring[(i + 1) % SBE_2T3E3_TX_DESC_RING_SIZE]);
|
||||
}
|
||||
sc->ether.tx_ring[SBE_2T3E3_TX_DESC_RING_SIZE - 1].tdes1 |=
|
||||
SBE_2T3E3_TX_DESC_END_OF_RING;
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS,
|
||||
virt_to_phys(&sc->ether.tx_ring[0]));
|
||||
sc->ether.tx_ring_current_read = 0;
|
||||
sc->ether.tx_ring_current_write = 0;
|
||||
sc->ether.tx_free_cnt = SBE_2T3E3_TX_DESC_RING_SIZE;
|
||||
spin_lock_init(&sc->ether.tx_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dc_clear_descriptor_list(struct channel *sc)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
/* clear CSR3 and CSR4 */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS, 0);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS, 0);
|
||||
|
||||
/* free all data buffers on TX ring */
|
||||
for (i = 0; i < SBE_2T3E3_TX_DESC_RING_SIZE; i++) {
|
||||
if (sc->ether.tx_data[i] != NULL) {
|
||||
dev_kfree_skb_any(sc->ether.tx_data[i]);
|
||||
sc->ether.tx_data[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dc_drop_descriptor_list(struct channel *sc)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
dc_clear_descriptor_list(sc);
|
||||
|
||||
/* free all data buffers on RX ring */
|
||||
for (i = 0; i < SBE_2T3E3_RX_DESC_RING_SIZE; i++) {
|
||||
if (sc->ether.rx_data[i] != NULL) {
|
||||
dev_kfree_skb_any(sc->ether.rx_data[i]);
|
||||
sc->ether.rx_data[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->ether.rx_ring != NULL) {
|
||||
#ifdef T3E3_USE_CONTIGMALLOC
|
||||
t3e3_contigmemory_size = SBE_2T3E3_RX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_rx_desc_t);
|
||||
#endif
|
||||
kfree(sc->ether.rx_ring);
|
||||
sc->ether.rx_ring = NULL;
|
||||
}
|
||||
|
||||
if (sc->ether.tx_ring != NULL) {
|
||||
#ifdef T3E3_USE_CONTIGMALLOC
|
||||
t3e3_contigmemory_size = SBE_2T3E3_TX_DESC_RING_SIZE *
|
||||
sizeof(t3e3_tx_desc_t);
|
||||
#endif
|
||||
kfree(sc->ether.tx_ring);
|
||||
sc->ether.tx_ring = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dc_set_output_port(struct channel *sc)
|
||||
{
|
||||
dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_PORT_SELECT);
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_STATUS, 0x00000301);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY, 0);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_TRANSMIT_AND_RECEIVE, 0);
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_AND_GENERAL_PURPOSE_PORT, 0x08000011);
|
||||
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_THRESHOLD_MODE_100Mbs |
|
||||
SBE_2T3E3_21143_VAL_HEARTBEAT_DISABLE |
|
||||
SBE_2T3E3_21143_VAL_PORT_SELECT |
|
||||
SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE);
|
||||
}
|
||||
|
||||
void dc_restart(struct channel *sc)
|
||||
{
|
||||
dev_warn(&sc->pdev->dev, "SBE 2T3E3: 21143 restart\n");
|
||||
|
||||
dc_stop(sc);
|
||||
dc_reset(sc);
|
||||
dc_init(sc); /* stop + reset + init */
|
||||
dc_start(sc);
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include "2t3e3.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
void exar7250_init(struct channel *sc)
|
||||
{
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_OPERATING_MODE,
|
||||
SBE_2T3E3_FRAMER_VAL_T3_CBIT |
|
||||
SBE_2T3E3_FRAMER_VAL_INTERRUPT_ENABLE_RESET |
|
||||
SBE_2T3E3_FRAMER_VAL_TIMING_ASYNCH_TXINCLK);
|
||||
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_IO_CONTROL,
|
||||
SBE_2T3E3_FRAMER_VAL_DISABLE_TX_LOSS_OF_CLOCK |
|
||||
SBE_2T3E3_FRAMER_VAL_DISABLE_RX_LOSS_OF_CLOCK |
|
||||
SBE_2T3E3_FRAMER_VAL_AMI_LINE_CODE |
|
||||
SBE_2T3E3_FRAMER_VAL_RX_LINE_CLOCK_INVERT);
|
||||
|
||||
exar7250_set_frame_type(sc, SBE_2T3E3_FRAME_TYPE_T3_CBIT);
|
||||
}
|
||||
|
||||
void exar7250_set_frame_type(struct channel *sc, u32 type)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
exar7250_stop_intr(sc, type);
|
||||
|
||||
val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_OPERATING_MODE);
|
||||
val &= ~(SBE_2T3E3_FRAMER_VAL_LOCAL_LOOPBACK_MODE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_E3_SELECT |
|
||||
SBE_2T3E3_FRAMER_VAL_FRAME_FORMAT_SELECT);
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
val |= SBE_2T3E3_FRAMER_VAL_E3_G751;
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
val |= SBE_2T3E3_FRAMER_VAL_E3_G832;
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
val |= SBE_2T3E3_FRAMER_VAL_T3_CBIT;
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
val |= SBE_2T3E3_FRAMER_VAL_T3_M13;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_OPERATING_MODE, val);
|
||||
exar7250_start_intr(sc, type);
|
||||
}
|
||||
|
||||
|
||||
void exar7250_start_intr(struct channel *sc, u32 type)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2);
|
||||
#if 0
|
||||
sc->s.LOS = val & SBE_2T3E3_FRAMER_VAL_E3_RX_LOS ? 1 : 0;
|
||||
#else
|
||||
cpld_LOS_update(sc);
|
||||
#endif
|
||||
sc->s.OOF = val & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0;
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_1);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_1,
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_ENABLE);
|
||||
#if 0
|
||||
/*SBE_2T3E3_FRAMER_VAL_E3_RX_COFA_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_LOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_AIS_INTERRUPT_ENABLE);*/
|
||||
#endif
|
||||
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_2);
|
||||
#if 0
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_2,
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_FEBE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_FERF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_FRAMING_BYTE_ERROR_INTERRUPT_ENABLE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS);
|
||||
#if 0
|
||||
sc->s.LOS = val & SBE_2T3E3_FRAMER_VAL_T3_RX_LOS ? 1 : 0;
|
||||
#else
|
||||
cpld_LOS_update(sc);
|
||||
#endif
|
||||
sc->s.OOF = val & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0;
|
||||
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_STATUS);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_ENABLE,
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_ENABLE);
|
||||
#if 0
|
||||
/* SBE_2T3E3_FRAMER_VAL_T3_RX_CP_BIT_ERROR_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_AIS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_FERF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_AIC_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_P_BIT_INTERRUPT_ENABLE);*/
|
||||
#endif
|
||||
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS);
|
||||
#if 0
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS,
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_REMOVE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_VALID_INTERRUPT_ENABLE);
|
||||
#endif
|
||||
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_CONTROL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_STATUS);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_ENABLE,
|
||||
SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_ENABLE);
|
||||
}
|
||||
|
||||
|
||||
void exar7250_stop_intr(struct channel *sc, u32 type)
|
||||
{
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_ENABLE, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_STATUS);
|
||||
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_1, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_1);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_2, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_2);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_LAPD_CONTROL, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_LAPD_CONTROL);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_TX_LAPD_STATUS, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_TX_LAPD_STATUS);
|
||||
break;
|
||||
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_ENABLE, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_STATUS);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_CONTROL, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_CONTROL);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_TX_FEAC_CONFIGURATION_STATUS, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_TX_FEAC_CONFIGURATION_STATUS);
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_TX_LAPD_STATUS, 0);
|
||||
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_TX_LAPD_STATUS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exar7250_unipolar_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_OFF:
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_FRAMER_REG_IO_CONTROL,
|
||||
SBE_2T3E3_FRAMER_VAL_UNIPOLAR);
|
||||
break;
|
||||
case SBE_2T3E3_ON:
|
||||
exar7300_set_bit(sc, SBE_2T3E3_FRAMER_REG_IO_CONTROL,
|
||||
SBE_2T3E3_FRAMER_VAL_UNIPOLAR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void exar7250_set_loopback(struct channel *sc, u32 mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_FRAMER_VAL_LOOPBACK_OFF:
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_FRAMER_REG_OPERATING_MODE,
|
||||
SBE_2T3E3_FRAMER_VAL_LOCAL_LOOPBACK_MODE);
|
||||
break;
|
||||
case SBE_2T3E3_FRAMER_VAL_LOOPBACK_ON:
|
||||
exar7300_set_bit(sc, SBE_2T3E3_FRAMER_REG_OPERATING_MODE,
|
||||
SBE_2T3E3_FRAMER_VAL_LOCAL_LOOPBACK_MODE);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include "2t3e3.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
void exar7300_init(struct channel *sc)
|
||||
{
|
||||
exar7300_write(sc, SBE_2T3E3_LIU_REG_REG1, 0);
|
||||
|
||||
/* enable line decodeer and encoder */
|
||||
exar7300_write(sc, SBE_2T3E3_LIU_REG_REG2, 0);
|
||||
exar7300_write(sc, SBE_2T3E3_LIU_REG_REG3, 0);
|
||||
exar7300_write(sc, SBE_2T3E3_LIU_REG_REG4,
|
||||
SBE_2T3E3_LIU_VAL_T3_MODE_SELECT |
|
||||
SBE_2T3E3_LIU_VAL_LOOPBACK_OFF);
|
||||
}
|
||||
|
||||
void exar7300_set_loopback(struct channel *sc, u32 mode)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_OFF:
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_REMOTE:
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_ANALOG:
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_DIGITAL:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
val = exar7300_read(sc, SBE_2T3E3_LIU_REG_REG4);
|
||||
val &= ~(SBE_2T3E3_LIU_VAL_LOCAL_LOOPBACK | SBE_2T3E3_LIU_VAL_REMOTE_LOOPBACK);
|
||||
val |= mode;
|
||||
exar7300_write(sc, SBE_2T3E3_LIU_REG_REG4, val);
|
||||
|
||||
#if 0
|
||||
/* TODO - is it necessary? idea from 2T3E3_HW_Test_code */
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_OFF:
|
||||
break;
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_REMOTE:
|
||||
exar7300_receive_equalization_onoff(sc, SBE_2T3E3_ON);
|
||||
break;
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_ANALOG:
|
||||
exar7300_receive_equalization_onoff(sc, SBE_2T3E3_OFF);
|
||||
break;
|
||||
case SBE_2T3E3_LIU_VAL_LOOPBACK_DIGITAL:
|
||||
exar7300_receive_equalization_onoff(sc, SBE_2T3E3_ON);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void exar7300_set_frame_type(struct channel *sc, u32 type)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
val = exar7300_read(sc, SBE_2T3E3_LIU_REG_REG4);
|
||||
val &= ~(SBE_2T3E3_LIU_VAL_T3_MODE_SELECT |
|
||||
SBE_2T3E3_LIU_VAL_E3_MODE_SELECT);
|
||||
|
||||
switch (type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
val |= SBE_2T3E3_LIU_VAL_T3_MODE_SELECT;
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
val |= SBE_2T3E3_LIU_VAL_E3_MODE_SELECT;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
exar7300_write(sc, SBE_2T3E3_LIU_REG_REG4, val);
|
||||
}
|
||||
|
||||
|
||||
void exar7300_transmit_all_ones_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.transmit_all_ones == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_ON:
|
||||
exar7300_set_bit(sc, SBE_2T3E3_LIU_REG_REG1,
|
||||
SBE_2T3E3_LIU_VAL_TRANSMIT_ALL_ONES);
|
||||
break;
|
||||
case SBE_2T3E3_OFF:
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_LIU_REG_REG1,
|
||||
SBE_2T3E3_LIU_VAL_TRANSMIT_ALL_ONES);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.transmit_all_ones = mode;
|
||||
}
|
||||
|
||||
void exar7300_receive_equalization_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.receive_equalization == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_OFF:
|
||||
exar7300_set_bit(sc, SBE_2T3E3_LIU_REG_REG2,
|
||||
SBE_2T3E3_LIU_VAL_RECEIVE_EQUALIZATION_DISABLE);
|
||||
break;
|
||||
case SBE_2T3E3_ON:
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_LIU_REG_REG2,
|
||||
SBE_2T3E3_LIU_VAL_RECEIVE_EQUALIZATION_DISABLE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.receive_equalization = mode;
|
||||
}
|
||||
|
||||
void exar7300_line_build_out_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
if (sc->p.line_build_out == mode)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_OFF:
|
||||
exar7300_set_bit(sc, SBE_2T3E3_LIU_REG_REG1,
|
||||
SBE_2T3E3_LIU_VAL_TRANSMIT_LEVEL_SELECT);
|
||||
exar7300_receive_equalization_onoff(sc, SBE_2T3E3_OFF);
|
||||
break;
|
||||
case SBE_2T3E3_ON:
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_LIU_REG_REG1,
|
||||
SBE_2T3E3_LIU_VAL_TRANSMIT_LEVEL_SELECT);
|
||||
exar7300_receive_equalization_onoff(sc, SBE_2T3E3_ON);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
sc->p.line_build_out = mode;
|
||||
}
|
||||
|
||||
/* TODO - what about encoder in raw mode??? disable it too? */
|
||||
void exar7300_unipolar_onoff(struct channel *sc, u32 mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case SBE_2T3E3_OFF:
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_LIU_REG_REG3,
|
||||
SBE_2T3E3_LIU_VAL_DECODER_DISABLE);
|
||||
exar7300_clear_bit(sc, SBE_2T3E3_LIU_REG_REG1,
|
||||
SBE_2T3E3_LIU_VAL_TRANSMIT_BINARY_DATA);
|
||||
break;
|
||||
case SBE_2T3E3_ON:
|
||||
exar7300_set_bit(sc, SBE_2T3E3_LIU_REG_REG3,
|
||||
SBE_2T3E3_LIU_VAL_DECODER_DISABLE);
|
||||
exar7300_set_bit(sc, SBE_2T3E3_LIU_REG_REG1,
|
||||
SBE_2T3E3_LIU_VAL_TRANSMIT_BINARY_DATA);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,635 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/hdlc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "2t3e3.h"
|
||||
|
||||
irqreturn_t t3e3_intr(int irq, void *dev_instance)
|
||||
{
|
||||
struct channel *sc = dev_to_priv(dev_instance);
|
||||
u32 val;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
sc->interrupt_active = 1;
|
||||
|
||||
val = cpld_read(sc, SBE_2T3E3_CPLD_REG_PICSR);
|
||||
|
||||
if (val & SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_CHANGE) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Rx LOS Chng Int r=%02x (LOS|OOF=%02x)\n",
|
||||
val, (sc->s.LOS << 4) | sc->s.OOF);
|
||||
cpld_LOS_update(sc);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (val & SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ASSERTED) {
|
||||
dc_intr(sc);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (val & SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ASSERTED) {
|
||||
exar7250_intr(sc);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
we don't care about other interrupt sources (DMO, LOS, LCV) because
|
||||
they are handled by Framer too
|
||||
*/
|
||||
|
||||
sc->interrupt_active = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dc_intr(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* disable ethernet interrupts */
|
||||
/* grrr this clears interrupt summary bits !!! */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, 0);
|
||||
|
||||
while ((val = dc_read(sc->addr, SBE_2T3E3_21143_REG_STATUS)) &
|
||||
(SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT)) {
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, val);
|
||||
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Ethernet controller interrupt! (CSR5 = %08X)\n",
|
||||
val);
|
||||
|
||||
if (val & (SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE |
|
||||
SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED)) {
|
||||
if (val & SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT)
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Receive interrupt (LOS=%d, OOF=%d)\n",
|
||||
sc->s.LOS, sc->s.OOF);
|
||||
if (val & SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE)
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Receive buffer unavailable\n");
|
||||
if (val & SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED)
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Receive process stopped\n");
|
||||
dc_intr_rx(sc);
|
||||
}
|
||||
|
||||
if (val & SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW) {
|
||||
dev_dbg(&sc->pdev->dev, "Transmit underflow\n");
|
||||
dc_intr_tx_underflow(sc);
|
||||
}
|
||||
|
||||
if (val & (SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT |
|
||||
SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED)) {
|
||||
if (val & SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT)
|
||||
dev_dbg(&sc->pdev->dev, "Transmit interrupt\n");
|
||||
if (val & SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE)
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Transmit buffer unavailable\n");
|
||||
if (val & SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED)
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Transmit process stopped\n");
|
||||
dc_intr_tx(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* enable ethernet interrupts */
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE,
|
||||
sc->ether.interrupt_enable_mask);
|
||||
}
|
||||
|
||||
void dc_intr_rx(struct channel *sc)
|
||||
{
|
||||
u32 current_read;
|
||||
u32 error_mask, error;
|
||||
t3e3_rx_desc_t *current_desc;
|
||||
struct sk_buff *m, *m2;
|
||||
unsigned rcv_len;
|
||||
|
||||
sc->rcv_count++; /* for the activity LED */
|
||||
|
||||
current_read = sc->ether.rx_ring_current_read;
|
||||
dev_dbg(&sc->pdev->dev, "intr_rx current_read = %d\n", current_read);
|
||||
|
||||
/* when ethernet loopback is set, ignore framer signals */
|
||||
if ((sc->p.loopback != SBE_2T3E3_LOOPBACK_ETHERNET) && sc->s.OOF) {
|
||||
while (!(sc->ether.rx_ring[current_read].rdes0 &
|
||||
SBE_2T3E3_RX_DESC_21143_OWN)) {
|
||||
current_desc = &sc->ether.rx_ring[current_read];
|
||||
current_desc->rdes1 &= SBE_2T3E3_RX_DESC_END_OF_RING |
|
||||
SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED;
|
||||
current_desc->rdes1 |= SBE_2T3E3_MTU;
|
||||
current_desc->rdes0 = SBE_2T3E3_RX_DESC_21143_OWN;
|
||||
current_read = (current_read + 1) % SBE_2T3E3_RX_DESC_RING_SIZE;
|
||||
}
|
||||
sc->ether.rx_ring_current_read = current_read;
|
||||
return;
|
||||
}
|
||||
|
||||
while (!(sc->ether.rx_ring[current_read].rdes0 &
|
||||
SBE_2T3E3_RX_DESC_21143_OWN)) {
|
||||
current_desc = &sc->ether.rx_ring[current_read];
|
||||
|
||||
dev_dbg(&sc->pdev->dev, "rdes0: %08X rdes1: %08X\n",
|
||||
current_desc->rdes0, current_desc->rdes1);
|
||||
|
||||
m = sc->ether.rx_data[current_read];
|
||||
rcv_len = (current_desc->rdes0 & SBE_2T3E3_RX_DESC_FRAME_LENGTH) >>
|
||||
SBE_2T3E3_RX_DESC_FRAME_LENGTH_SHIFT;
|
||||
|
||||
dev_dbg(&sc->pdev->dev, "mbuf was received (mbuf len = %d)\n",
|
||||
rcv_len);
|
||||
|
||||
switch (sc->p.crc) {
|
||||
case SBE_2T3E3_CRC_16:
|
||||
rcv_len -= SBE_2T3E3_CRC16_LENGTH;
|
||||
break;
|
||||
case SBE_2T3E3_CRC_32:
|
||||
rcv_len -= SBE_2T3E3_CRC32_LENGTH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_desc->rdes0 & SBE_2T3E3_RX_DESC_LAST_DESC) {
|
||||
|
||||
/* TODO: is collision possible? */
|
||||
error_mask = SBE_2T3E3_RX_DESC_DESC_ERROR |
|
||||
SBE_2T3E3_RX_DESC_COLLISION_SEEN |
|
||||
SBE_2T3E3_RX_DESC_DRIBBLING_BIT;
|
||||
|
||||
switch (sc->p.frame_mode) {
|
||||
case SBE_2T3E3_FRAME_MODE_HDLC:
|
||||
error_mask |= SBE_2T3E3_RX_DESC_MII_ERROR;
|
||||
if (sc->p.crc == SBE_2T3E3_CRC_32)
|
||||
error_mask |= SBE_2T3E3_RX_DESC_CRC_ERROR;
|
||||
break;
|
||||
case SBE_2T3E3_FRAME_MODE_TRANSPARENT:
|
||||
case SBE_2T3E3_FRAME_MODE_RAW:
|
||||
break;
|
||||
default:
|
||||
error_mask = 0;
|
||||
}
|
||||
|
||||
if (sc->s.LOS) {
|
||||
error_mask &= ~(SBE_2T3E3_RX_DESC_DRIBBLING_BIT ||
|
||||
SBE_2T3E3_RX_DESC_MII_ERROR);
|
||||
}
|
||||
|
||||
error = current_desc->rdes0 & error_mask;
|
||||
if (error) {
|
||||
sc->s.in_errors++;
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"error interrupt: NO_ERROR_MESSAGE = %d\n",
|
||||
sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES ? 1 : 0);
|
||||
|
||||
current_desc->rdes1 &= SBE_2T3E3_RX_DESC_END_OF_RING |
|
||||
SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED;
|
||||
current_desc->rdes1 |= SBE_2T3E3_MTU;
|
||||
current_desc->rdes0 = SBE_2T3E3_RX_DESC_21143_OWN;
|
||||
|
||||
if (error & SBE_2T3E3_RX_DESC_DESC_ERROR) {
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES))
|
||||
dev_err(&sc->pdev->dev,
|
||||
"SBE 2T3E3: descriptor error\n");
|
||||
sc->s.in_error_desc++;
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_RX_DESC_COLLISION_SEEN) {
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES))
|
||||
dev_err(&sc->pdev->dev,
|
||||
"SBE 2T3E3: collision seen\n");
|
||||
sc->s.in_error_coll++;
|
||||
} else {
|
||||
if (error & SBE_2T3E3_RX_DESC_DRIBBLING_BIT) {
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES))
|
||||
dev_err(&sc->pdev->dev,
|
||||
"SBE 2T3E3: dribbling bits error\n");
|
||||
sc->s.in_error_drib++;
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_RX_DESC_CRC_ERROR) {
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES))
|
||||
dev_err(&sc->pdev->dev,
|
||||
"SBE 2T3E3: crc error\n");
|
||||
sc->s.in_error_crc++;
|
||||
}
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_RX_DESC_MII_ERROR) {
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES))
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: mii error\n");
|
||||
sc->s.in_error_mii++;
|
||||
}
|
||||
|
||||
current_read = (current_read + 1) % SBE_2T3E3_RX_DESC_RING_SIZE;
|
||||
sc->r.flags |= SBE_2T3E3_FLAG_NO_ERROR_MESSAGES;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
current_desc->rdes1 &= SBE_2T3E3_RX_DESC_END_OF_RING |
|
||||
SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED;
|
||||
current_desc->rdes1 |= SBE_2T3E3_MTU;
|
||||
|
||||
if (rcv_len > 1600) {
|
||||
sc->s.in_errors++;
|
||||
sc->s.in_dropped++;
|
||||
if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES))
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: oversized rx: rdes0 = %08X\n",
|
||||
current_desc->rdes0);
|
||||
} else {
|
||||
m2 = dev_alloc_skb(MCLBYTES);
|
||||
if (m2 != NULL) {
|
||||
current_desc->rdes2 = virt_to_phys(m2->data);
|
||||
sc->ether.rx_data[current_read] = m2;
|
||||
sc->s.in_packets++;
|
||||
sc->s.in_bytes += rcv_len;
|
||||
m->dev = sc->dev;
|
||||
skb_put(m, rcv_len);
|
||||
skb_reset_mac_header(m);
|
||||
m->protocol = hdlc_type_trans(m, m->dev);
|
||||
netif_rx(m);
|
||||
|
||||
/* good packet was received so we will show error messages again... */
|
||||
if (sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"setting ERROR_MESSAGES->0\n");
|
||||
sc->r.flags &= ~SBE_2T3E3_FLAG_NO_ERROR_MESSAGES;
|
||||
}
|
||||
|
||||
} else {
|
||||
sc->s.in_errors++;
|
||||
sc->s.in_dropped++;
|
||||
}
|
||||
}
|
||||
current_desc->rdes0 = SBE_2T3E3_RX_DESC_21143_OWN;
|
||||
current_read = (current_read + 1) % SBE_2T3E3_RX_DESC_RING_SIZE;
|
||||
}
|
||||
|
||||
sc->ether.rx_ring_current_read = current_read;
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_POLL_DEMAND, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void dc_intr_tx(struct channel *sc)
|
||||
{
|
||||
u32 current_read, current_write;
|
||||
u32 last_segment, error;
|
||||
t3e3_tx_desc_t *current_desc;
|
||||
|
||||
spin_lock(&sc->ether.tx_lock);
|
||||
|
||||
current_read = sc->ether.tx_ring_current_read;
|
||||
current_write = sc->ether.tx_ring_current_write;
|
||||
|
||||
while (current_read != current_write) {
|
||||
current_desc = &sc->ether.tx_ring[current_read];
|
||||
|
||||
if (current_desc->tdes0 & SBE_2T3E3_RX_DESC_21143_OWN)
|
||||
break;
|
||||
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"txeof: tdes0 = %08X tdes1 = %08X\n",
|
||||
current_desc->tdes0, current_desc->tdes1);
|
||||
|
||||
error = current_desc->tdes0 & (SBE_2T3E3_TX_DESC_ERROR_SUMMARY |
|
||||
SBE_2T3E3_TX_DESC_TRANSMIT_JABBER_TIMEOUT |
|
||||
SBE_2T3E3_TX_DESC_LOSS_OF_CARRIER |
|
||||
SBE_2T3E3_TX_DESC_NO_CARRIER |
|
||||
SBE_2T3E3_TX_DESC_LINK_FAIL_REPORT |
|
||||
SBE_2T3E3_TX_DESC_UNDERFLOW_ERROR |
|
||||
SBE_2T3E3_TX_DESC_DEFFERED);
|
||||
|
||||
last_segment = current_desc->tdes1 & SBE_2T3E3_TX_DESC_LAST_SEGMENT;
|
||||
|
||||
current_desc->tdes0 = 0;
|
||||
current_desc->tdes1 &= SBE_2T3E3_TX_DESC_END_OF_RING |
|
||||
SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED;
|
||||
current_desc->tdes2 = 0;
|
||||
sc->ether.tx_free_cnt++;
|
||||
|
||||
if (last_segment != SBE_2T3E3_TX_DESC_LAST_SEGMENT) {
|
||||
current_read = (current_read + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (sc->ether.tx_data[current_read]) {
|
||||
sc->s.out_packets++;
|
||||
sc->s.out_bytes += sc->ether.tx_data[current_read]->len;
|
||||
dev_kfree_skb_any(sc->ether.tx_data[current_read]);
|
||||
sc->ether.tx_data[current_read] = NULL;
|
||||
}
|
||||
|
||||
if (error > 0) {
|
||||
sc->s.out_errors++;
|
||||
|
||||
if (error & SBE_2T3E3_TX_DESC_TRANSMIT_JABBER_TIMEOUT) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: transmit jabber timeout\n");
|
||||
sc->s.out_error_jab++;
|
||||
}
|
||||
|
||||
if (sc->p.loopback != SBE_2T3E3_LOOPBACK_ETHERNET) {
|
||||
if (error & SBE_2T3E3_TX_DESC_LOSS_OF_CARRIER) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: loss of carrier\n");
|
||||
sc->s.out_error_lost_carr++;
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_TX_DESC_NO_CARRIER) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: no carrier\n");
|
||||
sc->s.out_error_no_carr++;
|
||||
}
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_TX_DESC_LINK_FAIL_REPORT) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: link fail report\n");
|
||||
sc->s.out_error_link_fail++;
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_TX_DESC_UNDERFLOW_ERROR) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3:"
|
||||
" transmission underflow error\n");
|
||||
sc->s.out_error_underflow++;
|
||||
spin_unlock(&sc->ether.tx_lock);
|
||||
|
||||
dc_restart(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error & SBE_2T3E3_TX_DESC_DEFFERED) {
|
||||
dev_err(&sc->pdev->dev, "SBE 2T3E3: transmission deferred\n");
|
||||
sc->s.out_error_dereferred++;
|
||||
}
|
||||
}
|
||||
|
||||
current_read = (current_read + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
|
||||
}
|
||||
|
||||
sc->ether.tx_ring_current_read = current_read;
|
||||
|
||||
/* Relieve flow control when the TX queue is drained at least half way */
|
||||
if (sc->ether.tx_full &&
|
||||
(sc->ether.tx_free_cnt >= (SBE_2T3E3_TX_DESC_RING_SIZE / 2))) {
|
||||
sc->ether.tx_full = 0;
|
||||
netif_wake_queue(sc->dev);
|
||||
}
|
||||
spin_unlock(&sc->ether.tx_lock);
|
||||
}
|
||||
|
||||
|
||||
void dc_intr_tx_underflow(struct channel *sc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
dc_transmitter_onoff(sc, SBE_2T3E3_OFF);
|
||||
|
||||
val = dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE);
|
||||
dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS);
|
||||
|
||||
switch (val & SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS) {
|
||||
case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_1:
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_2);
|
||||
break;
|
||||
case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_2:
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_3);
|
||||
break;
|
||||
case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_3:
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_4);
|
||||
break;
|
||||
case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_4:
|
||||
default:
|
||||
dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE,
|
||||
SBE_2T3E3_21143_VAL_STORE_AND_FORWARD);
|
||||
break;
|
||||
}
|
||||
|
||||
dc_transmitter_onoff(sc, SBE_2T3E3_ON);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void exar7250_intr(struct channel *sc)
|
||||
{
|
||||
u32 status, old_OOF;
|
||||
|
||||
#if 0
|
||||
/* disable interrupts */
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_ENABLE, 0);
|
||||
#endif
|
||||
|
||||
old_OOF = sc->s.OOF;
|
||||
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_STATUS);
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt! (REG[0x05] = %02X)\n", status);
|
||||
|
||||
switch (sc->p.frame_type) {
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G751:
|
||||
case SBE_2T3E3_FRAME_TYPE_E3_G832:
|
||||
exar7250_E3_intr(sc, status);
|
||||
break;
|
||||
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
|
||||
case SBE_2T3E3_FRAME_TYPE_T3_M13:
|
||||
exar7250_T3_intr(sc, status);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc->s.OOF != old_OOF) {
|
||||
if (sc->s.OOF) {
|
||||
if (sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE) {
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Disabling eth interrupts\n");
|
||||
/* turn off ethernet interrupts */
|
||||
dc_stop_intr(sc);
|
||||
}
|
||||
} else if (sc->r.flags & SBE_2T3E3_FLAG_NETWORK_UP) {
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Enabling eth interrupts\n");
|
||||
/* start interrupts */
|
||||
sc->s.OOF = 1;
|
||||
dc_intr_rx(sc);
|
||||
sc->s.OOF = 0;
|
||||
if (sc->p.receiver_on) {
|
||||
dc_receiver_onoff(sc, SBE_2T3E3_OFF);
|
||||
dc_receiver_onoff(sc, SBE_2T3E3_ON);
|
||||
}
|
||||
dc_start_intr(sc);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* reenable interrupts */
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_ENABLE,
|
||||
SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_ENABLE
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void exar7250_T3_intr(struct channel *sc, u32 block_status)
|
||||
{
|
||||
u32 status, result;
|
||||
|
||||
if (block_status & SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_STATUS) {
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_STATUS);
|
||||
|
||||
if (status) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt T3 RX (REG[0x13] = %02X)\n",
|
||||
status);
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS);
|
||||
|
||||
#if 0
|
||||
if (status & SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_STATUS) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt T3: LOS\n");
|
||||
sc->s.LOS = result & SBE_2T3E3_FRAMER_VAL_T3_RX_LOS ? 1 : 0;
|
||||
|
||||
}
|
||||
#else
|
||||
cpld_LOS_update(sc);
|
||||
#endif
|
||||
if (status & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_STATUS) {
|
||||
sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0;
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt T3: OOF (%d)\n",
|
||||
sc->s.OOF);
|
||||
}
|
||||
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_ENABLE,
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_ENABLE);
|
||||
#if 0
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_CP_BIT_ERROR_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_AIS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_FERF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_AIC_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_P_BIT_INTERRUPT_ENABLE
|
||||
#endif
|
||||
}
|
||||
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS);
|
||||
if (status) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt T3 RX (REG[0x17] = %02X)\n",
|
||||
status);
|
||||
#if 0
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS,
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_REMOVE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_T3_RX_FEAC_VALID_INTERRUPT_ENABLE
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_CONTROL);
|
||||
if (status)
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt T3 RX (REG[0x18] = %02X)\n",
|
||||
status);
|
||||
}
|
||||
|
||||
|
||||
if (block_status & SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_STATUS) {
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_TX_FEAC_CONFIGURATION_STATUS);
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt T3 TX (REG[0x31] = %02X)\n",
|
||||
status);
|
||||
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_TX_LAPD_STATUS);
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt T3 TX (REG[0x34] = %02X)\n",
|
||||
status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void exar7250_E3_intr(struct channel *sc, u32 block_status)
|
||||
{
|
||||
u32 status, result;
|
||||
|
||||
if (block_status & SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_STATUS) {
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_1);
|
||||
|
||||
if (status) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt E3 RX (REG[0x14] = %02X)\n",
|
||||
status);
|
||||
|
||||
result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2);
|
||||
|
||||
#if 0
|
||||
if (status & SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_STATUS) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt E3: LOS\n");
|
||||
sc->s.LOS = result & SBE_2T3E3_FRAMER_VAL_E3_RX_LOS ? 1 : 0;
|
||||
}
|
||||
#else
|
||||
cpld_LOS_update(sc);
|
||||
#endif
|
||||
if (status & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_STATUS) {
|
||||
sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0;
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt E3: OOF (%d)\n",
|
||||
sc->s.OOF);
|
||||
}
|
||||
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_1,
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_ENABLE
|
||||
);
|
||||
#if 0
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_COFA_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_LOF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_AIS_INTERRUPT_ENABLE
|
||||
#endif
|
||||
}
|
||||
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_2);
|
||||
if (status) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"Framer interrupt E3 RX (REG[0x15] = %02X)\n",
|
||||
status);
|
||||
|
||||
#if 0
|
||||
exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_2,
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_FEBE_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_FERF_INTERRUPT_ENABLE |
|
||||
SBE_2T3E3_FRAMER_VAL_E3_RX_FRAMING_BYTE_ERROR_INTERRUPT_ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (block_status & SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_STATUS) {
|
||||
status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_TX_LAPD_STATUS);
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt E3 TX (REG[0x34] = %02X)\n",
|
||||
status);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <asm/system.h>
|
||||
#include "2t3e3.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
/* All access to registers done via the 21143 on port 0 must be
|
||||
* protected via the card->bootrom_lock. */
|
||||
|
||||
/* priviate define to be used here only - must be protected by card->bootrom_lock */
|
||||
#define cpld_write_nolock(channel, reg, val) \
|
||||
bootrom_write((channel), CPLD_MAP_REG(reg, channel), val)
|
||||
|
||||
u32 cpld_read(struct channel *channel, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
val = bootrom_read((channel), CPLD_MAP_REG(reg, channel));
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
return val;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Access via BootROM port
|
||||
****************************************/
|
||||
|
||||
u32 bootrom_read(struct channel *channel, u32 reg)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr;
|
||||
u32 result;
|
||||
|
||||
/* select BootROM address */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_PROGRAMMING_ADDRESS, reg & 0x3FFFF);
|
||||
|
||||
/* select reading from BootROM */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_BOOT_ROM_SELECT);
|
||||
|
||||
udelay(2); /* 20 PCI cycles */
|
||||
|
||||
/* read from BootROM */
|
||||
result = dc_read(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT) & 0xff;
|
||||
|
||||
/* reset CSR9 */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void bootrom_write(struct channel *channel, u32 reg, u32 val)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr;
|
||||
|
||||
/* select BootROM address */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_PROGRAMMING_ADDRESS, reg & 0x3FFFF);
|
||||
|
||||
/* select writting to BootROM */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_WRITE_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_BOOT_ROM_SELECT |
|
||||
(val & 0xff));
|
||||
|
||||
udelay(2); /* 20 PCI cycles */
|
||||
|
||||
/* reset CSR9 */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, 0);
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* Access via Serial I/O port
|
||||
****************************************/
|
||||
|
||||
static u32 serialrom_read_bit(struct channel *channel)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr;
|
||||
u32 bit;
|
||||
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CLOCK |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock high */
|
||||
|
||||
bit = (dc_read(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT) &
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_DATA_OUT) > 0 ? 1 : 0;
|
||||
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
static void serialrom_write_bit(struct channel *channel, u32 bit)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr;
|
||||
u32 lastbit = -1;
|
||||
|
||||
bit &= 1;
|
||||
|
||||
if (bit != lastbit) {
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_WRITE_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT |
|
||||
(bit << 2)); /* clock low */
|
||||
|
||||
lastbit = bit;
|
||||
}
|
||||
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_WRITE_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CLOCK |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT |
|
||||
(bit << 2)); /* clock high */
|
||||
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_WRITE_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT |
|
||||
(bit << 2)); /* clock low */
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Access to SerialROM (eeprom)
|
||||
****************************************/
|
||||
|
||||
u32 t3e3_eeprom_read_word(struct channel *channel, u32 address)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr;
|
||||
u32 i, val;
|
||||
unsigned long flags;
|
||||
|
||||
address &= 0x3f;
|
||||
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
|
||||
/* select correct Serial Chip */
|
||||
cpld_write_nolock(channel, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT,
|
||||
SBE_2T3E3_CPLD_VAL_EEPROM_SELECT);
|
||||
|
||||
/* select reading from Serial I/O Bus */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
|
||||
/* select read operation */
|
||||
serialrom_write_bit(channel, 0);
|
||||
serialrom_write_bit(channel, 1);
|
||||
serialrom_write_bit(channel, 1);
|
||||
serialrom_write_bit(channel, 0);
|
||||
|
||||
for (i = 0x20; i; i >>= 1)
|
||||
serialrom_write_bit(channel, address & i ? 1 : 0);
|
||||
|
||||
val = 0;
|
||||
for (i = 0x8000; i; i >>= 1)
|
||||
val |= (serialrom_read_bit(channel) ? i : 0);
|
||||
|
||||
/* Reset 21143's CSR9 */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, 0);
|
||||
|
||||
/* Unselect Serial Chip */
|
||||
cpld_write_nolock(channel, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT, 0);
|
||||
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
|
||||
return ntohs(val);
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* Access to Framer
|
||||
****************************************/
|
||||
|
||||
u32 exar7250_read(struct channel *channel, u32 reg)
|
||||
{
|
||||
u32 result;
|
||||
unsigned long flags;
|
||||
|
||||
#if 0
|
||||
switch (reg) {
|
||||
case SBE_2T3E3_FRAMER_REG_OPERATING_MODE:
|
||||
return channel->framer_regs[reg];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
|
||||
result = bootrom_read(channel, cpld_reg_map[SBE_2T3E3_CPLD_REG_FRAMER_BASE_ADDRESS]
|
||||
[channel->h.slot] + (t3e3_framer_reg_map[reg] << 2));
|
||||
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void exar7250_write(struct channel *channel, u32 reg, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
val &= 0xff;
|
||||
channel->framer_regs[reg] = val;
|
||||
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
|
||||
bootrom_write(channel, cpld_reg_map[SBE_2T3E3_CPLD_REG_FRAMER_BASE_ADDRESS]
|
||||
[channel->h.slot] + (t3e3_framer_reg_map[reg] << 2), val);
|
||||
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* Access to LIU
|
||||
****************************************/
|
||||
|
||||
u32 exar7300_read(struct channel *channel, u32 reg)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr, flags;
|
||||
u32 i, val;
|
||||
|
||||
#if 0
|
||||
switch (reg) {
|
||||
case SBE_2T3E3_LIU_REG_REG1:
|
||||
case SBE_2T3E3_LIU_REG_REG2:
|
||||
case SBE_2T3E3_LIU_REG_REG3:
|
||||
case SBE_2T3E3_LIU_REG_REG4:
|
||||
return channel->liu_regs[reg];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
#endif
|
||||
|
||||
/* select correct Serial Chip */
|
||||
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
|
||||
cpld_write_nolock(channel, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT,
|
||||
cpld_val_map[SBE_2T3E3_CPLD_VAL_LIU_SELECT][channel->h.slot]);
|
||||
|
||||
/* select reading from Serial I/O Bus */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
|
||||
/* select read operation */
|
||||
serialrom_write_bit(channel, 1);
|
||||
|
||||
/* Exar7300 register address is 4 bit long */
|
||||
reg = t3e3_liu_reg_map[reg];
|
||||
for (i = 0; i < 4; i++, reg >>= 1) /* 4 bits of SerialROM address */
|
||||
serialrom_write_bit(channel, reg & 1);
|
||||
for (i = 0; i < 3; i++) /* remaining 3 bits of SerialROM address */
|
||||
serialrom_write_bit(channel, 0);
|
||||
|
||||
val = 0; /* Exar7300 register value is 5 bit long */
|
||||
for (i = 0; i < 8; i++) /* 8 bits of SerialROM value */
|
||||
val += (serialrom_read_bit(channel) << i);
|
||||
|
||||
/* Reset 21143's CSR9 */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_READ_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, 0);
|
||||
|
||||
/* Unselect Serial Chip */
|
||||
cpld_write_nolock(channel, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT, 0);
|
||||
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void exar7300_write(struct channel *channel, u32 reg, u32 val)
|
||||
{
|
||||
unsigned long addr = channel->card->bootrom_addr, flags;
|
||||
u32 i;
|
||||
|
||||
channel->liu_regs[reg] = val;
|
||||
|
||||
/* select correct Serial Chip */
|
||||
|
||||
spin_lock_irqsave(&channel->card->bootrom_lock, flags);
|
||||
|
||||
cpld_write_nolock(channel, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT,
|
||||
cpld_val_map[SBE_2T3E3_CPLD_VAL_LIU_SELECT][channel->h.slot]);
|
||||
|
||||
/* select writting to Serial I/O Bus */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_WRITE_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
|
||||
/* select write operation */
|
||||
serialrom_write_bit(channel, 0);
|
||||
|
||||
/* Exar7300 register address is 4 bit long */
|
||||
reg = t3e3_liu_reg_map[reg];
|
||||
for (i = 0; i < 4; i++) { /* 4 bits */
|
||||
serialrom_write_bit(channel, reg & 1);
|
||||
reg >>= 1;
|
||||
}
|
||||
for (i = 0; i < 3; i++) /* remaining 3 bits of SerialROM address */
|
||||
serialrom_write_bit(channel, 0);
|
||||
|
||||
/* Exar7300 register value is 5 bit long */
|
||||
for (i = 0; i < 5; i++) {
|
||||
serialrom_write_bit(channel, val & 1);
|
||||
val >>= 1;
|
||||
}
|
||||
for (i = 0; i < 3; i++) /* remaining 3 bits of SerialROM value */
|
||||
serialrom_write_bit(channel, 0);
|
||||
|
||||
/* Reset 21143_CSR9 */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT,
|
||||
SBE_2T3E3_21143_VAL_WRITE_OPERATION |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_SELECT |
|
||||
SBE_2T3E3_21143_VAL_SERIAL_ROM_CHIP_SELECT); /* clock low */
|
||||
dc_write(addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, 0);
|
||||
|
||||
/* Unselect Serial Chip */
|
||||
cpld_write_nolock(channel, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT, 0);
|
||||
|
||||
spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "2t3e3.h"
|
||||
|
||||
void t3e3_init(struct channel *sc)
|
||||
{
|
||||
cpld_init(sc);
|
||||
dc_reset(sc);
|
||||
dc_init(sc);
|
||||
exar7250_init(sc);
|
||||
exar7300_init(sc);
|
||||
}
|
||||
|
||||
int t3e3_if_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct channel *sc = dev_to_priv(dev);
|
||||
u32 current_write, last_write;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb2;
|
||||
|
||||
if (skb == NULL) {
|
||||
sc->s.out_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sc->p.transmitter_on != SBE_2T3E3_ON) {
|
||||
sc->s.out_errors++;
|
||||
sc->s.out_dropped++;
|
||||
dev_kfree_skb_any(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sc->s.OOF && sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE) {
|
||||
sc->s.out_dropped++;
|
||||
dev_kfree_skb_any(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sc->ether.tx_lock, flags);
|
||||
|
||||
current_write = sc->ether.tx_ring_current_write;
|
||||
for (skb2 = skb; skb2 != NULL; skb2 = NULL) {
|
||||
if (skb2->len) {
|
||||
if ((sc->ether.tx_ring[current_write].tdes1 &
|
||||
SBE_2T3E3_TX_DESC_BUFFER_1_SIZE) > 0)
|
||||
break;
|
||||
current_write = (current_write + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
|
||||
/*
|
||||
* Leave at least 1 tx desc free so that dc_intr_tx() can
|
||||
* identify empty list
|
||||
*/
|
||||
if (current_write == sc->ether.tx_ring_current_read)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skb2 != NULL) {
|
||||
netif_stop_queue(sc->dev);
|
||||
sc->ether.tx_full = 1;
|
||||
dev_dbg(&sc->pdev->dev, "SBE 2T3E3: out of descriptors\n");
|
||||
spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
current_write = last_write = sc->ether.tx_ring_current_write;
|
||||
dev_dbg(&sc->pdev->dev, "sending mbuf (current_write = %d)\n",
|
||||
current_write);
|
||||
|
||||
for (skb2 = skb; skb2 != NULL; skb2 = NULL) {
|
||||
if (skb2->len) {
|
||||
dev_dbg(&sc->pdev->dev,
|
||||
"sending mbuf (len = %d, next = %p)\n",
|
||||
skb2->len, NULL);
|
||||
|
||||
sc->ether.tx_free_cnt--;
|
||||
sc->ether.tx_ring[current_write].tdes0 = 0;
|
||||
sc->ether.tx_ring[current_write].tdes1 &=
|
||||
SBE_2T3E3_TX_DESC_END_OF_RING |
|
||||
SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED;
|
||||
/* DISABLE_PADDING sometimes gets lost somehow, hands off... */
|
||||
sc->ether.tx_ring[current_write].tdes1 |=
|
||||
SBE_2T3E3_TX_DESC_DISABLE_PADDING | skb2->len;
|
||||
|
||||
if (current_write == sc->ether.tx_ring_current_write) {
|
||||
sc->ether.tx_ring[current_write].tdes1 |=
|
||||
SBE_2T3E3_TX_DESC_FIRST_SEGMENT;
|
||||
} else {
|
||||
sc->ether.tx_ring[current_write].tdes0 =
|
||||
SBE_2T3E3_TX_DESC_21143_OWN;
|
||||
}
|
||||
|
||||
sc->ether.tx_ring[current_write].tdes2 = virt_to_phys(skb2->data);
|
||||
sc->ether.tx_data[current_write] = NULL;
|
||||
|
||||
last_write = current_write;
|
||||
current_write = (current_write + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
sc->ether.tx_data[last_write] = skb;
|
||||
sc->ether.tx_ring[last_write].tdes1 |=
|
||||
SBE_2T3E3_TX_DESC_LAST_SEGMENT |
|
||||
SBE_2T3E3_TX_DESC_INTERRUPT_ON_COMPLETION;
|
||||
sc->ether.tx_ring[sc->ether.tx_ring_current_write].tdes0 |=
|
||||
SBE_2T3E3_TX_DESC_21143_OWN;
|
||||
sc->ether.tx_ring_current_write = current_write;
|
||||
|
||||
dev_dbg(&sc->pdev->dev, "txput: tdes0 = %08X tdes1 = %08X\n",
|
||||
sc->ether.tx_ring[last_write].tdes0,
|
||||
sc->ether.tx_ring[last_write].tdes1);
|
||||
|
||||
dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_POLL_DEMAND,
|
||||
0xffffffff);
|
||||
|
||||
spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void t3e3_read_card_serial_number(struct channel *sc)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
sc->ether.card_serial_number[i] = t3e3_eeprom_read_word(sc, 10 + i);
|
||||
|
||||
printk(KERN_INFO "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
|
||||
sc->ether.card_serial_number[0], sc->ether.card_serial_number[1],
|
||||
sc->ether.card_serial_number[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
bit 0 led1 (green)
|
||||
bit 1 led1 (yellow)
|
||||
|
||||
bit 2 led2 (green)
|
||||
bit 3 led2 (yellow)
|
||||
|
||||
bit 4 led3 (green)
|
||||
bit 5 led3 (yellow)
|
||||
|
||||
bit 6 led4 (green)
|
||||
bit 7 led4 (yellow)
|
||||
*/
|
||||
|
||||
void update_led(struct channel *sc, int blinker)
|
||||
{
|
||||
int leds;
|
||||
if (sc->s.LOS)
|
||||
leds = 0; /* led1 = off */
|
||||
else if (sc->s.OOF)
|
||||
leds = 2; /* led1 = yellow */
|
||||
else if ((blinker & 1) && sc->rcv_count) {
|
||||
leds = 0; /* led1 = off */
|
||||
sc->rcv_count = 0;
|
||||
} else
|
||||
leds = 1; /* led1 = green */
|
||||
cpld_write(sc, SBE_2T3E3_CPLD_REG_LEDR, leds);
|
||||
sc->leds = leds;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "2t3e3.h"
|
||||
|
||||
const u32 cpld_reg_map[][2] =
|
||||
{
|
||||
{ 0x0000, 0x0080 }, /* 0 - Port Control Register A (PCRA) */
|
||||
{ 0x0004, 0x0084 }, /* 1 - Port Control Register B (PCRB) */
|
||||
{ 0x0008, 0x0088 }, /* 2 - LCV Count Register (PLCR) */
|
||||
{ 0x000c, 0x008c }, /* 3 - LCV Threshold register (PLTR) */
|
||||
{ 0x0010, 0x0090 }, /* 4 - Payload Fill Register (PPFR) */
|
||||
{ 0x0200, 0x0200 }, /* 5 - Board ID / FPGA Programming Status Register */
|
||||
{ 0x0204, 0x0204 }, /* 6 - FPGA Version Register */
|
||||
{ 0x0800, 0x1000 }, /* 7 - Framer Registers Base Address */
|
||||
{ 0x2000, 0x2000 }, /* 8 - Serial Chip Select Register */
|
||||
{ 0x2004, 0x2004 }, /* 9 - Static Reset Register */
|
||||
{ 0x2008, 0x2008 }, /* 10 - Pulse Reset Register */
|
||||
{ 0x200c, 0x200c }, /* 11 - FPGA Reconfiguration Register */
|
||||
{ 0x2010, 0x2014 }, /* 12 - LED Register (LEDR) */
|
||||
{ 0x2018, 0x201c }, /* 13 - LIU Control and Status Register (PISCR) */
|
||||
{ 0x2020, 0x2024 }, /* 14 - Interrupt Enable Register (PIER) */
|
||||
{ 0x0068, 0x00e8 }, /* 15 - Port Control Register C (PCRC) */
|
||||
{ 0x006c, 0x00ec }, /* 16 - Port Bandwidth Start (PBWF) */
|
||||
{ 0x0070, 0x00f0 }, /* 17 - Port Bandwidth Stop (PBWL) */
|
||||
};
|
||||
|
||||
const u32 cpld_val_map[][2] =
|
||||
{
|
||||
{ 0x01, 0x02 }, /* LIU1 / LIU2 select for Serial Chip Select */
|
||||
{ 0x04, 0x08 }, /* DAC1 / DAC2 select for Serial Chip Select */
|
||||
{ 0x00, 0x04 }, /* LOOP1 / LOOP2 - select of loop timing source */
|
||||
{ 0x01, 0x02 } /* PORT1 / PORT2 - select LIU and Framer for reset */
|
||||
};
|
||||
|
||||
const u32 t3e3_framer_reg_map[] = {
|
||||
0x00, /* 0 - OPERATING_MODE */
|
||||
0x01, /* 1 - IO_CONTROL */
|
||||
0x04, /* 2 - BLOCK_INTERRUPT_ENABLE */
|
||||
0x05, /* 3 - BLOCK_INTERRUPT_STATUS */
|
||||
0x10, /* 4 - T3_RX_CONFIGURATION_STATUS, E3_RX_CONFIGURATION_STATUS_1 */
|
||||
0x11, /* 5 - T3_RX_STATUS, E3_RX_CONFIGURATION_STATUS_2 */
|
||||
0x12, /* 6 - T3_RX_INTERRUPT_ENABLE, E3_RX_INTERRUPT_ENABLE_1 */
|
||||
0x13, /* 7 - T3_RX_INTERRUPT_STATUS, E3_RX_INTERRUPT_ENABLE_2 */
|
||||
0x14, /* 8 - T3_RX_SYNC_DETECT_ENABLE, E3_RX_INTERRUPT_STATUS_1 */
|
||||
0x15, /* 9 - E3_RX_INTERRUPT_STATUS_2 */
|
||||
0x16, /* 10 - T3_RX_FEAC */
|
||||
0x17, /* 11 - T3_RX_FEAC_INTERRUPT_ENABLE_STATUS */
|
||||
0x18, /* 12 - T3_RX_LAPD_CONTROL, E3_RX_LAPD_CONTROL */
|
||||
0x19, /* 13 - T3_RX_LAPD_STATUS, E3_RX_LAPD_STATUS */
|
||||
0x1a, /* 14 - E3_RX_NR_BYTE, E3_RX_SERVICE_BITS */
|
||||
0x1b, /* 15 - E3_RX_GC_BYTE */
|
||||
0x30, /* 16 - T3_TX_CONFIGURATION, E3_TX_CONFIGURATION */
|
||||
0x31, /* 17 - T3_TX_FEAC_CONFIGURATION_STATUS */
|
||||
0x32, /* 18 - T3_TX_FEAC */
|
||||
0x33, /* 19 - T3_TX_LAPD_CONFIGURATION, E3_TX_LAPD_CONFIGURATION */
|
||||
0x34, /* 20 - T3_TX_LAPD_STATUS, E3_TX_LAPD_STATUS_INTERRUPT */
|
||||
0x35, /* 21 - T3_TX_MBIT_MASK, E3_TX_GC_BYTE, E3_TX_SERVICE_BITS */
|
||||
0x36, /* 22 - T3_TX_FBIT_MASK, E3_TX_MA_BYTE */
|
||||
0x37, /* 23 - T3_TX_FBIT_MASK_2, E3_TX_NR_BYTE */
|
||||
0x38, /* 24 - T3_TX_FBIT_MASK_3 */
|
||||
0x48, /* 25 - E3_TX_FA1_ERROR_MASK, E3_TX_FAS_ERROR_MASK_UPPER */
|
||||
0x49, /* 26 - E3_TX_FA2_ERROR_MASK, E3_TX_FAS_ERROR_MASK_LOWER */
|
||||
0x4a, /* 27 - E3_TX_BIP8_MASK, E3_TX_BIP4_MASK */
|
||||
0x50, /* 28 - PMON_LCV_EVENT_COUNT_MSB */
|
||||
0x51, /* 29 - PMON_LCV_EVENT_COUNT_LSB */
|
||||
0x52, /* 30 - PMON_FRAMING_BIT_ERROR_EVENT_COUNT_MSB */
|
||||
0x53, /* 31 - PMON_FRAMING_BIT_ERROR_EVENT_COUNT_LSB */
|
||||
0x54, /* 32 - PMON_PARITY_ERROR_EVENT_COUNT_MSB */
|
||||
0x55, /* 33 - PMON_PARITY_ERROR_EVENT_COUNT_LSB */
|
||||
0x56, /* 34 - PMON_FEBE_EVENT_COUNT_MSB */
|
||||
0x57, /* 35 - PMON_FEBE_EVENT_COUNT_LSB */
|
||||
0x58, /* 36 - PMON_CP_BIT_ERROR_EVENT_COUNT_MSB */
|
||||
0x59, /* 37 - PMON_CP_BIT_ERROR_EVENT_COUNT_LSB */
|
||||
0x6c, /* 38 - PMON_HOLDING_REGISTER */
|
||||
0x6d, /* 39 - ONE_SECOND_ERROR_STATUS */
|
||||
0x6e, /* 40 - LCV_ONE_SECOND_ACCUMULATOR_MSB */
|
||||
0x6f, /* 41 - LCV_ONE_SECOND_ACCUMULATOR_LSB */
|
||||
0x70, /* 42 - FRAME_PARITY_ERROR_ONE_SECOND_ACCUMULATOR_MSB */
|
||||
0x71, /* 43 - FRAME_PARITY_ERROR_ONE_SECOND_ACCUMULATOR_LSB */
|
||||
0x72, /* 44 - FRAME_CP_BIT_ERROR_ONE_SECOND_ACCUMULATOR_MSB */
|
||||
0x73, /* 45 - FRAME_CP_BIT_ERROR_ONE_SECOND_ACCUMULATOR_LSB */
|
||||
0x80, /* 46 - LINE_INTERFACE_DRIVE */
|
||||
0x81 /* 47 - LINE_INTERFACE_SCAN */
|
||||
};
|
||||
|
||||
const u32 t3e3_liu_reg_map[] =
|
||||
{
|
||||
0x00, /* REG0 */
|
||||
0x01, /* REG1 */
|
||||
0x02, /* REG2 */
|
||||
0x03, /* REG3 */
|
||||
0x04 /* REG4 */
|
||||
};
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/hdlc.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include "2t3e3.h"
|
||||
|
||||
static void check_leds(unsigned long arg)
|
||||
{
|
||||
struct card *card = (struct card *)arg;
|
||||
struct channel *channel0 = &card->channels[0];
|
||||
static int blinker;
|
||||
|
||||
update_led(channel0, ++blinker);
|
||||
if (has_two_ports(channel0->pdev))
|
||||
update_led(&card->channels[1], blinker);
|
||||
|
||||
card->timer.expires = jiffies + HZ / 10;
|
||||
add_timer(&card->timer);
|
||||
}
|
||||
|
||||
static void t3e3_remove_channel(struct channel *channel)
|
||||
{
|
||||
struct pci_dev *pdev = channel->pdev;
|
||||
struct net_device *dev = channel->dev;
|
||||
|
||||
/* system hangs if board asserts irq while module is unloaded */
|
||||
cpld_stop_intr(channel);
|
||||
free_irq(dev->irq, dev);
|
||||
dc_drop_descriptor_list(channel);
|
||||
unregister_hdlc_device(dev);
|
||||
free_netdev(dev);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
|
||||
{
|
||||
struct net_device *dev;
|
||||
unsigned int val;
|
||||
int err;
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = pci_request_regions(pdev, "SBE 2T3E3");
|
||||
if (err)
|
||||
goto disable;
|
||||
|
||||
dev = alloc_hdlcdev(channel);
|
||||
if (!dev) {
|
||||
printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
|
||||
goto free_regions;
|
||||
}
|
||||
|
||||
t3e3_sc_init(channel);
|
||||
dev_to_priv(dev) = channel;
|
||||
|
||||
channel->pdev = pdev;
|
||||
channel->dev = dev;
|
||||
channel->card = card;
|
||||
channel->addr = pci_resource_start(pdev, 0);
|
||||
if (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)
|
||||
channel->h.slot = 1;
|
||||
else
|
||||
channel->h.slot = 0;
|
||||
|
||||
if (setup_device(dev, channel))
|
||||
goto free_regions;
|
||||
|
||||
pci_read_config_dword(channel->pdev, 0x40, &val); /* mask sleep mode */
|
||||
pci_write_config_dword(channel->pdev, 0x40, val & 0x3FFFFFFF);
|
||||
|
||||
pci_read_config_byte(channel->pdev, PCI_CACHE_LINE_SIZE, &channel->h.cache_size);
|
||||
pci_read_config_dword(channel->pdev, PCI_COMMAND, &channel->h.command);
|
||||
t3e3_init(channel);
|
||||
|
||||
if (request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev)) {
|
||||
printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
|
||||
goto free_regions;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, channel);
|
||||
return 0;
|
||||
|
||||
free_regions:
|
||||
pci_release_regions(pdev);
|
||||
disable:
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit t3e3_remove_card(struct pci_dev *pdev)
|
||||
{
|
||||
struct channel *channel0 = pci_get_drvdata(pdev);
|
||||
struct card *card = channel0->card;
|
||||
|
||||
del_timer(&card->timer);
|
||||
if (has_two_ports(channel0->pdev)) {
|
||||
t3e3_remove_channel(&card->channels[1]);
|
||||
pci_dev_put(card->channels[1].pdev);
|
||||
}
|
||||
t3e3_remove_channel(channel0);
|
||||
kfree(card);
|
||||
}
|
||||
|
||||
static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
/* pdev points to channel #0 */
|
||||
struct pci_dev *pdev1 = NULL;
|
||||
struct card *card;
|
||||
int channels = 1, err;
|
||||
|
||||
if (has_two_ports(pdev)) {
|
||||
while ((pdev1 = pci_get_subsys(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
|
||||
PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P1,
|
||||
pdev1)))
|
||||
if (pdev1->bus == pdev->bus &&
|
||||
pdev1->devfn == pdev->devfn + 8 /* next device on the same bus */)
|
||||
break; /* found the second channel */
|
||||
|
||||
if (!pdev1) {
|
||||
printk(KERN_ERR "SBE 2T3E3" ": Can't find the second channel\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
channels = 2;
|
||||
/* holds the reference for pdev1 */
|
||||
}
|
||||
|
||||
card = kzalloc(sizeof(struct card) + channels * sizeof(struct channel), GFP_KERNEL);
|
||||
if (!card) {
|
||||
printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
spin_lock_init(&card->bootrom_lock);
|
||||
card->bootrom_addr = pci_resource_start(pdev, 0);
|
||||
|
||||
err = t3e3_init_channel(&card->channels[0], pdev, card);
|
||||
if (err)
|
||||
goto free_card;
|
||||
|
||||
if (channels == 2) {
|
||||
err = t3e3_init_channel(&card->channels[1], pdev1, card);
|
||||
if (err) {
|
||||
t3e3_remove_channel(&card->channels[0]);
|
||||
goto free_card;
|
||||
}
|
||||
}
|
||||
|
||||
/* start LED timer */
|
||||
init_timer(&card->timer);
|
||||
card->timer.function = check_leds;
|
||||
card->timer.expires = jiffies + HZ / 10;
|
||||
card->timer.data = (unsigned long)card;
|
||||
add_timer(&card->timer);
|
||||
return 0;
|
||||
|
||||
free_card:
|
||||
kfree(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct pci_device_id t3e3_pci_tbl[] __devinitdata = {
|
||||
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
|
||||
PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_T3E3, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
|
||||
PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P0, 0, 0, 0 },
|
||||
/* channel 1 will be initialized after channel 0 */
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static struct pci_driver t3e3_pci_driver = {
|
||||
.name = "SBE T3E3",
|
||||
.id_table = t3e3_pci_tbl,
|
||||
.probe = t3e3_init_card,
|
||||
.remove = t3e3_remove_card,
|
||||
};
|
||||
|
||||
static int __init t3e3_init_module(void)
|
||||
{
|
||||
return pci_register_driver(&t3e3_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit t3e3_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&t3e3_pci_driver);
|
||||
}
|
||||
|
||||
module_init(t3e3_init_module);
|
||||
module_exit(t3e3_cleanup_module);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl);
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* SBE 2T3E3 synchronous serial card driver for Linux
|
||||
*
|
||||
* Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This code is based on a driver written by SBE Inc.
|
||||
*/
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/hdlc.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include "2t3e3.h"
|
||||
|
||||
int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct channel *sc = dev_to_priv(dev);
|
||||
int cmd_2t3e3, len, rlen;
|
||||
t3e3_param_t param;
|
||||
t3e3_resp_t resp;
|
||||
void *data = ifr->ifr_data + sizeof(cmd_2t3e3) + sizeof(len);
|
||||
|
||||
if (cmd == SIOCWANDEV)
|
||||
return hdlc_ioctl(dev, ifr, cmd);
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
if (cmd != SIOCDEVPRIVATE + 15)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&cmd_2t3e3, ifr->ifr_data, sizeof(cmd_2t3e3)))
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&len, ifr->ifr_data + sizeof(cmd_2t3e3), sizeof(len)))
|
||||
return -EFAULT;
|
||||
|
||||
if (len > sizeof(param))
|
||||
return -EFAULT;
|
||||
|
||||
if (len)
|
||||
if (copy_from_user(¶m, data, len))
|
||||
return -EFAULT;
|
||||
|
||||
t3e3_if_config(sc, cmd_2t3e3, (char *)¶m, &resp, &rlen);
|
||||
|
||||
if (rlen)
|
||||
if (copy_to_user(data, &resp, rlen))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device_stats* t3e3_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *nstats = &dev->stats;
|
||||
struct channel *sc = dev_to_priv(dev);
|
||||
t3e3_stats_t *stats = &sc->s;
|
||||
|
||||
memset(nstats, 0, sizeof(struct net_device_stats));
|
||||
nstats->rx_packets = stats->in_packets;
|
||||
nstats->tx_packets = stats->out_packets;
|
||||
nstats->rx_bytes = stats->in_bytes;
|
||||
nstats->tx_bytes = stats->out_bytes;
|
||||
|
||||
nstats->rx_errors = stats->in_errors;
|
||||
nstats->tx_errors = stats->out_errors;
|
||||
nstats->rx_crc_errors = stats->in_error_crc;
|
||||
|
||||
|
||||
nstats->rx_dropped = stats->in_dropped;
|
||||
nstats->tx_dropped = stats->out_dropped;
|
||||
nstats->tx_carrier_errors = stats->out_error_lost_carr +
|
||||
stats->out_error_no_carr;
|
||||
|
||||
return nstats;
|
||||
}
|
||||
|
||||
int t3e3_open(struct net_device *dev)
|
||||
{
|
||||
struct channel *sc = dev_to_priv(dev);
|
||||
int ret = hdlc_open(dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sc->r.flags |= SBE_2T3E3_FLAG_NETWORK_UP;
|
||||
dc_start(dev_to_priv(dev));
|
||||
netif_start_queue(dev);
|
||||
try_module_get(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t3e3_close(struct net_device *dev)
|
||||
{
|
||||
struct channel *sc = dev_to_priv(dev);
|
||||
hdlc_close(dev);
|
||||
netif_stop_queue(dev);
|
||||
dc_stop(sc);
|
||||
sc->r.flags &= ~SBE_2T3E3_FLAG_NETWORK_UP;
|
||||
module_put(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t3e3_attach(struct net_device *dev, unsigned short foo1,
|
||||
unsigned short foo2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops t3e3_ops = {
|
||||
.ndo_open = t3e3_open,
|
||||
.ndo_stop = t3e3_close,
|
||||
.ndo_change_mtu = hdlc_change_mtu,
|
||||
.ndo_start_xmit = hdlc_start_xmit,
|
||||
.ndo_do_ioctl = t3e3_ioctl,
|
||||
.ndo_get_stats = t3e3_get_stats,
|
||||
};
|
||||
|
||||
int setup_device(struct net_device *dev, struct channel *sc)
|
||||
{
|
||||
hdlc_device *hdlc = dev_to_hdlc(dev);
|
||||
int retval;
|
||||
|
||||
dev->base_addr = pci_resource_start(sc->pdev, 0);
|
||||
dev->irq = sc->pdev->irq;
|
||||
dev->netdev_ops = &t3e3_ops;
|
||||
dev->tx_queue_len = 100;
|
||||
hdlc->xmit = t3e3_if_start_xmit;
|
||||
hdlc->attach = t3e3_attach;
|
||||
if ((retval = register_hdlc_device(dev))) {
|
||||
dev_err(&sc->pdev->dev, "error registering HDLC device\n");
|
||||
return retval;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue