Commit | Line | Data |
---|---|---|
921a86e0 KH |
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/hdlc.h> | |
14 | #include <linux/interrupt.h> | |
15 | #include <linux/netdevice.h> | |
16 | #include "2t3e3.h" | |
17 | ||
18 | irqreturn_t t3e3_intr(int irq, void *dev_instance) | |
19 | { | |
20 | struct channel *sc = dev_to_priv(dev_instance); | |
21 | u32 val; | |
22 | irqreturn_t ret = IRQ_NONE; | |
23 | ||
24 | sc->interrupt_active = 1; | |
25 | ||
26 | val = cpld_read(sc, SBE_2T3E3_CPLD_REG_PICSR); | |
27 | ||
28 | if (val & SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_CHANGE) { | |
29 | dev_dbg(&sc->pdev->dev, | |
30 | "Rx LOS Chng Int r=%02x (LOS|OOF=%02x)\n", | |
31 | val, (sc->s.LOS << 4) | sc->s.OOF); | |
32 | cpld_LOS_update(sc); | |
33 | ret = IRQ_HANDLED; | |
34 | } | |
35 | ||
36 | if (val & SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ASSERTED) { | |
37 | dc_intr(sc); | |
38 | ret = IRQ_HANDLED; | |
39 | } | |
40 | ||
41 | if (val & SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ASSERTED) { | |
42 | exar7250_intr(sc); | |
43 | ret = IRQ_HANDLED; | |
44 | } | |
45 | ||
46 | /* | |
47 | we don't care about other interrupt sources (DMO, LOS, LCV) because | |
48 | they are handled by Framer too | |
49 | */ | |
50 | ||
51 | sc->interrupt_active = 0; | |
52 | return ret; | |
53 | } | |
54 | ||
55 | void dc_intr(struct channel *sc) | |
56 | { | |
57 | u32 val; | |
58 | ||
59 | /* disable ethernet interrupts */ | |
60 | /* grrr this clears interrupt summary bits !!! */ | |
61 | dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, 0); | |
62 | ||
63 | while ((val = dc_read(sc->addr, SBE_2T3E3_21143_REG_STATUS)) & | |
64 | (SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED | | |
65 | SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE | | |
66 | SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT | | |
67 | SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW | | |
68 | SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE | | |
69 | SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED | | |
70 | SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT)) { | |
71 | dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, val); | |
72 | ||
73 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Ethernet controller interrupt! (CSR5 = %08X)\n", | |
74 | val); | |
75 | ||
76 | if (val & (SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT | | |
77 | SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE | | |
78 | SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED)) { | |
79 | if (val & SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT) | |
80 | dev_dbg(&sc->pdev->dev, | |
81 | "Receive interrupt (LOS=%d, OOF=%d)\n", | |
82 | sc->s.LOS, sc->s.OOF); | |
83 | if (val & SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE) | |
84 | dev_dbg(&sc->pdev->dev, | |
85 | "Receive buffer unavailable\n"); | |
86 | if (val & SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STOPPED) | |
87 | dev_dbg(&sc->pdev->dev, | |
88 | "Receive process stopped\n"); | |
89 | dc_intr_rx(sc); | |
90 | } | |
91 | ||
92 | if (val & SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW) { | |
93 | dev_dbg(&sc->pdev->dev, "Transmit underflow\n"); | |
94 | dc_intr_tx_underflow(sc); | |
95 | } | |
96 | ||
97 | if (val & (SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE | | |
98 | SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT | | |
99 | SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED)) { | |
100 | if (val & SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT) | |
101 | dev_dbg(&sc->pdev->dev, "Transmit interrupt\n"); | |
102 | if (val & SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE) | |
103 | dev_dbg(&sc->pdev->dev, | |
104 | "Transmit buffer unavailable\n"); | |
105 | if (val & SBE_2T3E3_21143_VAL_TRANSMIT_PROCESS_STOPPED) | |
106 | dev_dbg(&sc->pdev->dev, | |
107 | "Transmit process stopped\n"); | |
108 | dc_intr_tx(sc); | |
109 | } | |
110 | } | |
111 | ||
112 | /* enable ethernet interrupts */ | |
113 | dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, | |
114 | sc->ether.interrupt_enable_mask); | |
115 | } | |
116 | ||
117 | void dc_intr_rx(struct channel *sc) | |
118 | { | |
119 | u32 current_read; | |
120 | u32 error_mask, error; | |
121 | t3e3_rx_desc_t *current_desc; | |
122 | struct sk_buff *m, *m2; | |
123 | unsigned rcv_len; | |
124 | ||
125 | sc->rcv_count++; /* for the activity LED */ | |
126 | ||
127 | current_read = sc->ether.rx_ring_current_read; | |
128 | dev_dbg(&sc->pdev->dev, "intr_rx current_read = %d\n", current_read); | |
129 | ||
130 | /* when ethernet loopback is set, ignore framer signals */ | |
131 | if ((sc->p.loopback != SBE_2T3E3_LOOPBACK_ETHERNET) && sc->s.OOF) { | |
132 | while (!(sc->ether.rx_ring[current_read].rdes0 & | |
133 | SBE_2T3E3_RX_DESC_21143_OWN)) { | |
134 | current_desc = &sc->ether.rx_ring[current_read]; | |
135 | current_desc->rdes1 &= SBE_2T3E3_RX_DESC_END_OF_RING | | |
136 | SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED; | |
137 | current_desc->rdes1 |= SBE_2T3E3_MTU; | |
138 | current_desc->rdes0 = SBE_2T3E3_RX_DESC_21143_OWN; | |
139 | current_read = (current_read + 1) % SBE_2T3E3_RX_DESC_RING_SIZE; | |
140 | } | |
141 | sc->ether.rx_ring_current_read = current_read; | |
142 | return; | |
143 | } | |
144 | ||
145 | while (!(sc->ether.rx_ring[current_read].rdes0 & | |
146 | SBE_2T3E3_RX_DESC_21143_OWN)) { | |
147 | current_desc = &sc->ether.rx_ring[current_read]; | |
148 | ||
149 | dev_dbg(&sc->pdev->dev, "rdes0: %08X rdes1: %08X\n", | |
150 | current_desc->rdes0, current_desc->rdes1); | |
151 | ||
152 | m = sc->ether.rx_data[current_read]; | |
153 | rcv_len = (current_desc->rdes0 & SBE_2T3E3_RX_DESC_FRAME_LENGTH) >> | |
154 | SBE_2T3E3_RX_DESC_FRAME_LENGTH_SHIFT; | |
155 | ||
156 | dev_dbg(&sc->pdev->dev, "mbuf was received (mbuf len = %d)\n", | |
157 | rcv_len); | |
158 | ||
159 | switch (sc->p.crc) { | |
160 | case SBE_2T3E3_CRC_16: | |
161 | rcv_len -= SBE_2T3E3_CRC16_LENGTH; | |
162 | break; | |
163 | case SBE_2T3E3_CRC_32: | |
164 | rcv_len -= SBE_2T3E3_CRC32_LENGTH; | |
165 | break; | |
166 | default: | |
167 | break; | |
168 | } | |
169 | ||
170 | if (current_desc->rdes0 & SBE_2T3E3_RX_DESC_LAST_DESC) { | |
171 | ||
172 | /* TODO: is collision possible? */ | |
173 | error_mask = SBE_2T3E3_RX_DESC_DESC_ERROR | | |
174 | SBE_2T3E3_RX_DESC_COLLISION_SEEN | | |
175 | SBE_2T3E3_RX_DESC_DRIBBLING_BIT; | |
176 | ||
177 | switch (sc->p.frame_mode) { | |
178 | case SBE_2T3E3_FRAME_MODE_HDLC: | |
179 | error_mask |= SBE_2T3E3_RX_DESC_MII_ERROR; | |
180 | if (sc->p.crc == SBE_2T3E3_CRC_32) | |
181 | error_mask |= SBE_2T3E3_RX_DESC_CRC_ERROR; | |
182 | break; | |
183 | case SBE_2T3E3_FRAME_MODE_TRANSPARENT: | |
184 | case SBE_2T3E3_FRAME_MODE_RAW: | |
185 | break; | |
186 | default: | |
187 | error_mask = 0; | |
188 | } | |
189 | ||
190 | if (sc->s.LOS) { | |
3e150cf5 | 191 | error_mask &= ~(SBE_2T3E3_RX_DESC_DRIBBLING_BIT | |
921a86e0 KH |
192 | SBE_2T3E3_RX_DESC_MII_ERROR); |
193 | } | |
194 | ||
195 | error = current_desc->rdes0 & error_mask; | |
196 | if (error) { | |
197 | sc->s.in_errors++; | |
198 | dev_dbg(&sc->pdev->dev, | |
199 | "error interrupt: NO_ERROR_MESSAGE = %d\n", | |
200 | sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES ? 1 : 0); | |
201 | ||
202 | current_desc->rdes1 &= SBE_2T3E3_RX_DESC_END_OF_RING | | |
203 | SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED; | |
204 | current_desc->rdes1 |= SBE_2T3E3_MTU; | |
205 | current_desc->rdes0 = SBE_2T3E3_RX_DESC_21143_OWN; | |
206 | ||
207 | if (error & SBE_2T3E3_RX_DESC_DESC_ERROR) { | |
208 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES)) | |
209 | dev_err(&sc->pdev->dev, | |
210 | "SBE 2T3E3: descriptor error\n"); | |
211 | sc->s.in_error_desc++; | |
212 | } | |
213 | ||
214 | if (error & SBE_2T3E3_RX_DESC_COLLISION_SEEN) { | |
215 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES)) | |
216 | dev_err(&sc->pdev->dev, | |
217 | "SBE 2T3E3: collision seen\n"); | |
218 | sc->s.in_error_coll++; | |
219 | } else { | |
220 | if (error & SBE_2T3E3_RX_DESC_DRIBBLING_BIT) { | |
221 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES)) | |
222 | dev_err(&sc->pdev->dev, | |
223 | "SBE 2T3E3: dribbling bits error\n"); | |
224 | sc->s.in_error_drib++; | |
225 | } | |
226 | ||
227 | if (error & SBE_2T3E3_RX_DESC_CRC_ERROR) { | |
228 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES)) | |
229 | dev_err(&sc->pdev->dev, | |
230 | "SBE 2T3E3: crc error\n"); | |
231 | sc->s.in_error_crc++; | |
232 | } | |
233 | } | |
234 | ||
235 | if (error & SBE_2T3E3_RX_DESC_MII_ERROR) { | |
236 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES)) | |
237 | dev_err(&sc->pdev->dev, "SBE 2T3E3: mii error\n"); | |
238 | sc->s.in_error_mii++; | |
239 | } | |
240 | ||
241 | current_read = (current_read + 1) % SBE_2T3E3_RX_DESC_RING_SIZE; | |
242 | sc->r.flags |= SBE_2T3E3_FLAG_NO_ERROR_MESSAGES; | |
243 | continue; | |
244 | } | |
245 | } | |
246 | ||
247 | current_desc->rdes1 &= SBE_2T3E3_RX_DESC_END_OF_RING | | |
248 | SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED; | |
249 | current_desc->rdes1 |= SBE_2T3E3_MTU; | |
250 | ||
251 | if (rcv_len > 1600) { | |
252 | sc->s.in_errors++; | |
253 | sc->s.in_dropped++; | |
254 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES)) | |
255 | dev_err(&sc->pdev->dev, "SBE 2T3E3: oversized rx: rdes0 = %08X\n", | |
256 | current_desc->rdes0); | |
257 | } else { | |
258 | m2 = dev_alloc_skb(MCLBYTES); | |
259 | if (m2 != NULL) { | |
260 | current_desc->rdes2 = virt_to_phys(m2->data); | |
261 | sc->ether.rx_data[current_read] = m2; | |
262 | sc->s.in_packets++; | |
263 | sc->s.in_bytes += rcv_len; | |
264 | m->dev = sc->dev; | |
265 | skb_put(m, rcv_len); | |
266 | skb_reset_mac_header(m); | |
267 | m->protocol = hdlc_type_trans(m, m->dev); | |
268 | netif_rx(m); | |
269 | ||
270 | /* good packet was received so we will show error messages again... */ | |
271 | if (sc->r.flags & SBE_2T3E3_FLAG_NO_ERROR_MESSAGES) { | |
272 | dev_dbg(&sc->pdev->dev, | |
273 | "setting ERROR_MESSAGES->0\n"); | |
274 | sc->r.flags &= ~SBE_2T3E3_FLAG_NO_ERROR_MESSAGES; | |
275 | } | |
276 | ||
277 | } else { | |
278 | sc->s.in_errors++; | |
279 | sc->s.in_dropped++; | |
280 | } | |
281 | } | |
282 | current_desc->rdes0 = SBE_2T3E3_RX_DESC_21143_OWN; | |
283 | current_read = (current_read + 1) % SBE_2T3E3_RX_DESC_RING_SIZE; | |
284 | } | |
285 | ||
286 | sc->ether.rx_ring_current_read = current_read; | |
287 | ||
288 | dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_POLL_DEMAND, 0xFFFFFFFF); | |
289 | } | |
290 | ||
291 | void dc_intr_tx(struct channel *sc) | |
292 | { | |
293 | u32 current_read, current_write; | |
294 | u32 last_segment, error; | |
295 | t3e3_tx_desc_t *current_desc; | |
296 | ||
297 | spin_lock(&sc->ether.tx_lock); | |
298 | ||
299 | current_read = sc->ether.tx_ring_current_read; | |
300 | current_write = sc->ether.tx_ring_current_write; | |
301 | ||
302 | while (current_read != current_write) { | |
303 | current_desc = &sc->ether.tx_ring[current_read]; | |
304 | ||
305 | if (current_desc->tdes0 & SBE_2T3E3_RX_DESC_21143_OWN) | |
306 | break; | |
307 | ||
308 | dev_dbg(&sc->pdev->dev, | |
309 | "txeof: tdes0 = %08X tdes1 = %08X\n", | |
310 | current_desc->tdes0, current_desc->tdes1); | |
311 | ||
312 | error = current_desc->tdes0 & (SBE_2T3E3_TX_DESC_ERROR_SUMMARY | | |
313 | SBE_2T3E3_TX_DESC_TRANSMIT_JABBER_TIMEOUT | | |
314 | SBE_2T3E3_TX_DESC_LOSS_OF_CARRIER | | |
315 | SBE_2T3E3_TX_DESC_NO_CARRIER | | |
316 | SBE_2T3E3_TX_DESC_LINK_FAIL_REPORT | | |
317 | SBE_2T3E3_TX_DESC_UNDERFLOW_ERROR | | |
318 | SBE_2T3E3_TX_DESC_DEFFERED); | |
319 | ||
320 | last_segment = current_desc->tdes1 & SBE_2T3E3_TX_DESC_LAST_SEGMENT; | |
321 | ||
322 | current_desc->tdes0 = 0; | |
323 | current_desc->tdes1 &= SBE_2T3E3_TX_DESC_END_OF_RING | | |
324 | SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED; | |
325 | current_desc->tdes2 = 0; | |
326 | sc->ether.tx_free_cnt++; | |
327 | ||
328 | if (last_segment != SBE_2T3E3_TX_DESC_LAST_SEGMENT) { | |
329 | current_read = (current_read + 1) % SBE_2T3E3_TX_DESC_RING_SIZE; | |
330 | continue; | |
331 | } | |
332 | ||
333 | ||
334 | if (sc->ether.tx_data[current_read]) { | |
335 | sc->s.out_packets++; | |
336 | sc->s.out_bytes += sc->ether.tx_data[current_read]->len; | |
337 | dev_kfree_skb_any(sc->ether.tx_data[current_read]); | |
338 | sc->ether.tx_data[current_read] = NULL; | |
339 | } | |
340 | ||
341 | if (error > 0) { | |
342 | sc->s.out_errors++; | |
343 | ||
344 | if (error & SBE_2T3E3_TX_DESC_TRANSMIT_JABBER_TIMEOUT) { | |
345 | dev_err(&sc->pdev->dev, "SBE 2T3E3: transmit jabber timeout\n"); | |
346 | sc->s.out_error_jab++; | |
347 | } | |
348 | ||
349 | if (sc->p.loopback != SBE_2T3E3_LOOPBACK_ETHERNET) { | |
350 | if (error & SBE_2T3E3_TX_DESC_LOSS_OF_CARRIER) { | |
351 | dev_err(&sc->pdev->dev, "SBE 2T3E3: loss of carrier\n"); | |
352 | sc->s.out_error_lost_carr++; | |
353 | } | |
354 | ||
355 | if (error & SBE_2T3E3_TX_DESC_NO_CARRIER) { | |
356 | dev_err(&sc->pdev->dev, "SBE 2T3E3: no carrier\n"); | |
357 | sc->s.out_error_no_carr++; | |
358 | } | |
359 | } | |
360 | ||
361 | if (error & SBE_2T3E3_TX_DESC_LINK_FAIL_REPORT) { | |
362 | dev_err(&sc->pdev->dev, "SBE 2T3E3: link fail report\n"); | |
363 | sc->s.out_error_link_fail++; | |
364 | } | |
365 | ||
366 | if (error & SBE_2T3E3_TX_DESC_UNDERFLOW_ERROR) { | |
367 | dev_err(&sc->pdev->dev, "SBE 2T3E3:" | |
368 | " transmission underflow error\n"); | |
369 | sc->s.out_error_underflow++; | |
370 | spin_unlock(&sc->ether.tx_lock); | |
371 | ||
372 | dc_restart(sc); | |
373 | return; | |
374 | } | |
375 | ||
376 | if (error & SBE_2T3E3_TX_DESC_DEFFERED) { | |
377 | dev_err(&sc->pdev->dev, "SBE 2T3E3: transmission deferred\n"); | |
378 | sc->s.out_error_dereferred++; | |
379 | } | |
380 | } | |
381 | ||
382 | current_read = (current_read + 1) % SBE_2T3E3_TX_DESC_RING_SIZE; | |
383 | } | |
384 | ||
385 | sc->ether.tx_ring_current_read = current_read; | |
386 | ||
387 | /* Relieve flow control when the TX queue is drained at least half way */ | |
388 | if (sc->ether.tx_full && | |
389 | (sc->ether.tx_free_cnt >= (SBE_2T3E3_TX_DESC_RING_SIZE / 2))) { | |
390 | sc->ether.tx_full = 0; | |
391 | netif_wake_queue(sc->dev); | |
392 | } | |
393 | spin_unlock(&sc->ether.tx_lock); | |
394 | } | |
395 | ||
396 | ||
397 | void dc_intr_tx_underflow(struct channel *sc) | |
398 | { | |
399 | u32 val; | |
400 | ||
401 | dc_transmitter_onoff(sc, SBE_2T3E3_OFF); | |
402 | ||
403 | val = dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE); | |
404 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
405 | SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS); | |
406 | ||
407 | switch (val & SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS) { | |
408 | case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_1: | |
409 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
410 | SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_2); | |
411 | break; | |
412 | case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_2: | |
413 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
414 | SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_3); | |
415 | break; | |
416 | case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_3: | |
417 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
418 | SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_4); | |
419 | break; | |
420 | case SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_4: | |
421 | default: | |
422 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
423 | SBE_2T3E3_21143_VAL_STORE_AND_FORWARD); | |
424 | break; | |
425 | } | |
426 | ||
427 | dc_transmitter_onoff(sc, SBE_2T3E3_ON); | |
428 | } | |
429 | ||
430 | ||
431 | ||
432 | ||
433 | void exar7250_intr(struct channel *sc) | |
434 | { | |
435 | u32 status, old_OOF; | |
436 | ||
921a86e0 KH |
437 | old_OOF = sc->s.OOF; |
438 | ||
439 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_BLOCK_INTERRUPT_STATUS); | |
440 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt! (REG[0x05] = %02X)\n", status); | |
441 | ||
442 | switch (sc->p.frame_type) { | |
443 | case SBE_2T3E3_FRAME_TYPE_E3_G751: | |
444 | case SBE_2T3E3_FRAME_TYPE_E3_G832: | |
445 | exar7250_E3_intr(sc, status); | |
446 | break; | |
447 | ||
448 | case SBE_2T3E3_FRAME_TYPE_T3_CBIT: | |
449 | case SBE_2T3E3_FRAME_TYPE_T3_M13: | |
450 | exar7250_T3_intr(sc, status); | |
451 | break; | |
452 | ||
453 | default: | |
454 | break; | |
455 | } | |
456 | ||
457 | if (sc->s.OOF != old_OOF) { | |
458 | if (sc->s.OOF) { | |
459 | if (sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE) { | |
460 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Disabling eth interrupts\n"); | |
461 | /* turn off ethernet interrupts */ | |
462 | dc_stop_intr(sc); | |
463 | } | |
464 | } else if (sc->r.flags & SBE_2T3E3_FLAG_NETWORK_UP) { | |
465 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Enabling eth interrupts\n"); | |
466 | /* start interrupts */ | |
467 | sc->s.OOF = 1; | |
468 | dc_intr_rx(sc); | |
469 | sc->s.OOF = 0; | |
470 | if (sc->p.receiver_on) { | |
471 | dc_receiver_onoff(sc, SBE_2T3E3_OFF); | |
472 | dc_receiver_onoff(sc, SBE_2T3E3_ON); | |
473 | } | |
474 | dc_start_intr(sc); | |
475 | } | |
476 | } | |
921a86e0 KH |
477 | } |
478 | ||
479 | ||
480 | void exar7250_T3_intr(struct channel *sc, u32 block_status) | |
481 | { | |
482 | u32 status, result; | |
483 | ||
484 | if (block_status & SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_STATUS) { | |
485 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_STATUS); | |
486 | ||
487 | if (status) { | |
488 | dev_dbg(&sc->pdev->dev, | |
489 | "Framer interrupt T3 RX (REG[0x13] = %02X)\n", | |
490 | status); | |
491 | ||
492 | result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS); | |
493 | ||
921a86e0 | 494 | cpld_LOS_update(sc); |
12f3f21d | 495 | |
921a86e0 KH |
496 | if (status & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_STATUS) { |
497 | sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0; | |
498 | dev_dbg(&sc->pdev->dev, | |
499 | "Framer interrupt T3: OOF (%d)\n", | |
500 | sc->s.OOF); | |
501 | } | |
502 | ||
503 | exar7250_write(sc, SBE_2T3E3_FRAMER_REG_T3_RX_INTERRUPT_ENABLE, | |
504 | SBE_2T3E3_FRAMER_VAL_T3_RX_LOS_INTERRUPT_ENABLE | | |
505 | SBE_2T3E3_FRAMER_VAL_T3_RX_OOF_INTERRUPT_ENABLE); | |
921a86e0 KH |
506 | } |
507 | ||
508 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC_INTERRUPT_ENABLE_STATUS); | |
509 | if (status) { | |
510 | dev_dbg(&sc->pdev->dev, | |
511 | "Framer interrupt T3 RX (REG[0x17] = %02X)\n", | |
512 | status); | |
921a86e0 KH |
513 | } |
514 | ||
515 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_LAPD_CONTROL); | |
516 | if (status) | |
517 | dev_dbg(&sc->pdev->dev, | |
518 | "Framer interrupt T3 RX (REG[0x18] = %02X)\n", | |
519 | status); | |
520 | } | |
521 | ||
522 | ||
523 | if (block_status & SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_STATUS) { | |
524 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_TX_FEAC_CONFIGURATION_STATUS); | |
525 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt T3 TX (REG[0x31] = %02X)\n", | |
526 | status); | |
527 | ||
528 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_TX_LAPD_STATUS); | |
529 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt T3 TX (REG[0x34] = %02X)\n", | |
530 | status); | |
531 | } | |
532 | } | |
533 | ||
534 | ||
535 | void exar7250_E3_intr(struct channel *sc, u32 block_status) | |
536 | { | |
537 | u32 status, result; | |
538 | ||
539 | if (block_status & SBE_2T3E3_FRAMER_VAL_RX_INTERRUPT_STATUS) { | |
540 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_1); | |
541 | ||
542 | if (status) { | |
543 | dev_dbg(&sc->pdev->dev, | |
544 | "Framer interrupt E3 RX (REG[0x14] = %02X)\n", | |
545 | status); | |
546 | ||
547 | result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2); | |
548 | ||
921a86e0 | 549 | cpld_LOS_update(sc); |
12f3f21d | 550 | |
921a86e0 KH |
551 | if (status & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_STATUS) { |
552 | sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0; | |
553 | dev_dbg(&sc->pdev->dev, | |
554 | "Framer interrupt E3: OOF (%d)\n", | |
555 | sc->s.OOF); | |
556 | } | |
557 | ||
558 | exar7250_write(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_ENABLE_1, | |
559 | SBE_2T3E3_FRAMER_VAL_E3_RX_OOF_INTERRUPT_ENABLE | | |
560 | SBE_2T3E3_FRAMER_VAL_E3_RX_LOS_INTERRUPT_ENABLE | |
561 | ); | |
921a86e0 KH |
562 | } |
563 | ||
564 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_INTERRUPT_STATUS_2); | |
565 | if (status) { | |
566 | dev_dbg(&sc->pdev->dev, | |
567 | "Framer interrupt E3 RX (REG[0x15] = %02X)\n", | |
568 | status); | |
569 | ||
921a86e0 KH |
570 | } |
571 | ||
572 | } | |
573 | ||
574 | if (block_status & SBE_2T3E3_FRAMER_VAL_TX_INTERRUPT_STATUS) { | |
575 | status = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_TX_LAPD_STATUS); | |
576 | dev_dbg(&sc->pdev->dev, "SBE 2T3E3: Framer interrupt E3 TX (REG[0x34] = %02X)\n", | |
577 | status); | |
578 | } | |
579 | } |