Linux-libre 3.10.48-gnu
[librecmc/linux-libre.git] / drivers / staging / sbe-2t3e3 / main.c
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
17 void 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
26 int 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
131 void 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
158 void 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 }