diff options
Diffstat (limited to 'drivers/staging/sbe-2t3e3/intr.c')
-rw-r--r-- | drivers/staging/sbe-2t3e3/intr.c | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/drivers/staging/sbe-2t3e3/intr.c b/drivers/staging/sbe-2t3e3/intr.c new file mode 100644 index 000000000000..7ad1a8382037 --- /dev/null +++ b/drivers/staging/sbe-2t3e3/intr.c @@ -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); + } +} |