Commit a7fa5e4e authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

staging: remove sbe-2t3e3 driver.

It never really got cleaned up properly, and no one is working on it, so
remove it.  If someone wants to pick it up, this can be easily reverted.

Cc: Krzysztof Halasa <khc@pm.waw.pl>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ebb657ba
......@@ -90,8 +90,6 @@ source "drivers/staging/tidspbridge/Kconfig"
source "drivers/staging/quickstart/Kconfig"
source "drivers/staging/sbe-2t3e3/Kconfig"
source "drivers/staging/keucr/Kconfig"
source "drivers/staging/bcm/Kconfig"
......
......@@ -39,7 +39,6 @@ obj-$(CONFIG_CXT1E1) += cxt1e1/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
obj-$(CONFIG_USB_ENESTORAGE) += keucr/
obj-$(CONFIG_BCM_WIMAX) += bcm/
obj-$(CONFIG_FT1000) += ft1000/
......
This diff is collapsed.
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.
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3.o
sbe-2t3e3-y := module.o netdev.o maps.o \
main.o cpld.o intr.o ctrl.o io.o dc.o exar7250.o exar7300.o
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>.
\ No newline at end of file
/*
* 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;
/* 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);
}
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;
}
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:
netdev_err(sc->dev, "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;
}
/*
* 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;
}
static 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);
}
static 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;
}
}
static 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;
}
}
static void t3e3_port_get(struct channel *sc, struct t3e3_param *param)
{
memcpy(param, &(sc->p), sizeof(struct t3e3_param));
}
static void t3e3_port_set(struct channel *sc, struct t3e3_param *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);
}
static void t3e3_port_get_stats(struct channel *sc, struct t3e3_stats *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;
cpld_LOS_update(sc);
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;
cpld_LOS_update(sc);
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(struct t3e3_stats));
}
static void t3e3_port_del_stats(struct channel *sc)
{
memset(&(sc->s), 0, sizeof(struct t3e3_stats));
}
void t3e3_if_config(struct channel *sc, u32 cmd, char *set,
struct t3e3_resp *ret, int *rlen)
{
struct t3e3_param *param = (struct t3e3_param *)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:
t3e3_reg_write(sc, data);
*rlen = 0;
break;
case SBE_2T3E3_LOG_LEVEL:
*rlen = 0;
break;
default:
*rlen = 0;
break;
}
}
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;
}
/*
* 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
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 */
};
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;
};
struct t3e3_resp {
union {
struct t3e3_param param;
struct t3e3_stats stats;
u32 data;
} u;
};
#endif /* CTRL_H */
This diff is collapsed.
/*
* 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);
cpld_LOS_update(sc);
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);
exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_2);
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);
cpld_LOS_update(sc);
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);
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);
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;
}
}
/*
* 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);
}
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;
}
}
This diff is collapsed.
This diff is collapsed.
/*
* 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);
netdev_info(sc->dev, "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;
}
/*
* 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 */
};
/*
* 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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#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 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) {
pr_err("Out of memory\n");
err = -ENOMEM;
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;
err = setup_device(dev, channel);
if (err)
goto free_dev;
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);
err = request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev);
if (err) {
netdev_warn(channel->dev, "%s: could not get irq: %d\n",
dev->name, dev->irq);
goto unregister_dev;
}
pci_set_drvdata(pdev, channel);
return 0;
unregister_dev:
unregister_hdlc_device(dev);
free_dev:
free_netdev(dev);
free_regions:
pci_release_regions(pdev);
disable:
pci_disable_device(pdev);
return err;
}
static void t3e3_remove_card(struct pci_dev *pdev)
{
struct channel *channel0 = pci_get_drvdata(pdev);
struct card *card = channel0->card;
del_timer_sync(&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 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) {
dev_err(&pdev->dev, "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)
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[] = {
{ 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,
};
module_pci_driver(t3e3_pci_driver);
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl);
/*
* 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"
static int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct channel *sc = dev_to_priv(dev);
int cmd_2t3e3, len, rlen;
struct t3e3_param param;
struct t3e3_resp resp;
void __user *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(&param, data, len))
return -EFAULT;
t3e3_if_config(sc, cmd_2t3e3, (char *)&param, &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);
struct t3e3_stats *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;
}
static 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;
}
static 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;
retval = register_hdlc_device(dev);
if (retval) {
dev_err(&sc->pdev->dev, "error registering HDLC device\n");
return retval;
}
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment