Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
main.c
Go to the documentation of this file.
1 /*
2  * SBE 2T3E3 synchronous serial card driver for Linux
3  *
4  * Copyright (C) 2009-2010 Krzysztof Halasa <[email protected]>
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 
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 &
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 &=
91 /* DISABLE_PADDING sometimes gets lost somehow, hands off... */
92  sc->ether.tx_ring[current_write].tdes1 |=
94 
95  if (current_write == sc->ether.tx_ring_current_write) {
96  sc->ether.tx_ring[current_write].tdes1 |=
98  } else {
99  sc->ether.tx_ring[current_write].tdes0 =
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 |=
115  sc->ether.tx_ring[sc->ether.tx_ring_current_write].tdes0 |=
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 
124  0xffffffff);
125 
126  spin_unlock_irqrestore(&sc->ether.tx_lock, flags);
127  return 0;
128 }
129 
130 
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  printk(KERN_INFO "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
139  sc->ether.card_serial_number[0], sc->ether.card_serial_number[1],
140  sc->ether.card_serial_number[2]);
141 }
142 
143 /*
144  bit 0 led1 (green)
145  bit 1 led1 (yellow)
146 
147  bit 2 led2 (green)
148  bit 3 led2 (yellow)
149 
150  bit 4 led3 (green)
151  bit 5 led3 (yellow)
152 
153  bit 6 led4 (green)
154  bit 7 led4 (yellow)
155 */
156 
157 void update_led(struct channel *sc, int blinker)
158 {
159  int leds;
160  if (sc->s.LOS)
161  leds = 0; /* led1 = off */
162  else if (sc->s.OOF)
163  leds = 2; /* led1 = yellow */
164  else if ((blinker & 1) && sc->rcv_count) {
165  leds = 0; /* led1 = off */
166  sc->rcv_count = 0;
167  } else
168  leds = 1; /* led1 = green */
169  cpld_write(sc, SBE_2T3E3_CPLD_REG_LEDR, leds);
170  sc->leds = leds;
171 }