linux/drivers/staging/sbe-2t3e3/main.c
<<
>>
Prefs
   1/*
   2 * SBE 2T3E3 synchronous serial card driver for Linux
   3 *
   4 * Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of version 2 of the GNU General Public License
   8 * as published by the Free Software Foundation.
   9 *
  10 * This code is based on a driver written by SBE Inc.
  11 */
  12
  13#include <linux/interrupt.h>
  14#include <linux/netdevice.h>
  15#include "2t3e3.h"
  16
  17void t3e3_init(struct channel *sc)
  18{
  19        cpld_init(sc);
  20        dc_reset(sc);
  21        dc_init(sc);
  22        exar7250_init(sc);
  23        exar7300_init(sc);
  24}
  25
  26int t3e3_if_start_xmit(struct sk_buff *skb, struct net_device *dev)
  27{
  28        struct channel *sc = dev_to_priv(dev);
  29        u32 current_write, last_write;
  30        unsigned long flags;
  31        struct sk_buff *skb2;
  32
  33        if (skb == NULL) {
  34                sc->s.out_errors++;
  35                return 0;
  36        }
  37
  38        if (sc->p.transmitter_on != SBE_2T3E3_ON) {
  39                sc->s.out_errors++;
  40                sc->s.out_dropped++;
  41                dev_kfree_skb_any(skb);
  42                return 0;
  43        }
  44
  45        if (sc->s.OOF && sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE) {
  46                sc->s.out_dropped++;
  47                dev_kfree_skb_any(skb);
  48                return 0;
  49        }
  50
  51        spin_lock_irqsave(&sc->ether.tx_lock, flags);
  52
  53        current_write = sc->ether.tx_ring_current_write;
  54        for (skb2 = skb; skb2 != NULL; skb2 = NULL) {
  55                if (skb2->len) {
  56                        if ((sc->ether.tx_ring[current_write].tdes1 &
  57                             SBE_2T3E3_TX_DESC_BUFFER_1_SIZE) > 0)
  58                                break;
  59                        current_write = (current_write + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
  60                        /*
  61                         * Leave at least 1 tx desc free so that dc_intr_tx() can
  62                         * identify empty list
  63                         */
  64                        if (current_write == sc->ether.tx_ring_current_read)
  65                                break;
  66                }
  67        }
  68        if (skb2 != NULL) {
  69                netif_stop_queue(sc->dev);
  70                sc->ether.tx_full = 1;
  71                dev_dbg(&sc->pdev->dev, "SBE 2T3E3: out of descriptors\n");
  72                spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
  73                return NETDEV_TX_BUSY;
  74        }
  75
  76        current_write = last_write = sc->ether.tx_ring_current_write;
  77        dev_dbg(&sc->pdev->dev, "sending mbuf (current_write = %d)\n",
  78                current_write);
  79
  80        for (skb2 = skb; skb2 != NULL; skb2 = NULL) {
  81                if (skb2->len) {
  82                        dev_dbg(&sc->pdev->dev,
  83                                "sending mbuf (len = %d, next = %p)\n",
  84                                skb2->len, NULL);
  85
  86                        sc->ether.tx_free_cnt--;
  87                        sc->ether.tx_ring[current_write].tdes0 = 0;
  88                        sc->ether.tx_ring[current_write].tdes1 &=
  89                                SBE_2T3E3_TX_DESC_END_OF_RING |
  90                                SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED;
  91/* DISABLE_PADDING sometimes gets lost somehow, hands off... */
  92                        sc->ether.tx_ring[current_write].tdes1 |=
  93                                SBE_2T3E3_TX_DESC_DISABLE_PADDING | skb2->len;
  94
  95                        if (current_write == sc->ether.tx_ring_current_write) {
  96                                sc->ether.tx_ring[current_write].tdes1 |=
  97                                        SBE_2T3E3_TX_DESC_FIRST_SEGMENT;
  98                        } else {
  99                                sc->ether.tx_ring[current_write].tdes0 =
 100                                        SBE_2T3E3_TX_DESC_21143_OWN;
 101                        }
 102
 103                        sc->ether.tx_ring[current_write].tdes2 = virt_to_phys(skb2->data);
 104                        sc->ether.tx_data[current_write] = NULL;
 105
 106                        last_write = current_write;
 107                        current_write = (current_write + 1) % SBE_2T3E3_TX_DESC_RING_SIZE;
 108                }
 109        }
 110
 111        sc->ether.tx_data[last_write] = skb;
 112        sc->ether.tx_ring[last_write].tdes1 |=
 113                SBE_2T3E3_TX_DESC_LAST_SEGMENT |
 114                SBE_2T3E3_TX_DESC_INTERRUPT_ON_COMPLETION;
 115        sc->ether.tx_ring[sc->ether.tx_ring_current_write].tdes0 |=
 116                SBE_2T3E3_TX_DESC_21143_OWN;
 117        sc->ether.tx_ring_current_write = current_write;
 118
 119        dev_dbg(&sc->pdev->dev, "txput: tdes0 = %08X        tdes1 = %08X\n",
 120                sc->ether.tx_ring[last_write].tdes0,
 121                sc->ether.tx_ring[last_write].tdes1);
 122
 123        dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_POLL_DEMAND,
 124                 0xffffffff);
 125
 126        spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
 127        return 0;
 128}
 129
 130
 131void t3e3_read_card_serial_number(struct channel *sc)
 132{
 133        u32 i;
 134
 135        for (i = 0; i < 3; i++)
 136                sc->ether.card_serial_number[i] = t3e3_eeprom_read_word(sc, 10 + i);
 137
 138        netdev_info(sc->dev, "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
 139                    sc->ether.card_serial_number[0],
 140                    sc->ether.card_serial_number[1],
 141                    sc->ether.card_serial_number[2]);
 142}
 143
 144/*
 145  bit 0 led1 (green)
 146  bit 1 led1 (yellow)
 147
 148  bit 2 led2 (green)
 149  bit 3 led2 (yellow)
 150
 151  bit 4 led3 (green)
 152  bit 5 led3 (yellow)
 153
 154  bit 6 led4 (green)
 155  bit 7 led4 (yellow)
 156*/
 157
 158void update_led(struct channel *sc, int blinker)
 159{
 160        int leds;
 161        if (sc->s.LOS)
 162                leds = 0; /* led1 = off */
 163        else if (sc->s.OOF)
 164                leds = 2; /* led1 = yellow */
 165        else if ((blinker & 1) && sc->rcv_count) {
 166                leds = 0; /* led1 = off */
 167                sc->rcv_count = 0;
 168        } else
 169                leds = 1; /* led1 = green */
 170        cpld_write(sc, SBE_2T3E3_CPLD_REG_LEDR, leds);
 171        sc->leds = leds;
 172}
 173