]>
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/netdevice.h> | |
14 | #include <linux/types.h> | |
15 | #include <linux/errno.h> | |
16 | #include <linux/io.h> | |
17 | #include "2t3e3.h" | |
18 | #include "ctrl.h" | |
19 | ||
20 | void dc_init(struct channel *sc) | |
21 | { | |
22 | u32 val; | |
23 | ||
24 | dc_stop(sc); | |
25 | /*dc_reset(sc);*/ /* do not want to reset here */ | |
26 | ||
27 | /* | |
28 | * BUS_MODE (CSR0) | |
29 | */ | |
30 | val = SBE_2T3E3_21143_VAL_READ_LINE_ENABLE | | |
31 | SBE_2T3E3_21143_VAL_READ_MULTIPLE_ENABLE | | |
32 | SBE_2T3E3_21143_VAL_TRANSMIT_AUTOMATIC_POLLING_200us | | |
33 | SBE_2T3E3_21143_VAL_BUS_ARBITRATION_RR; | |
34 | ||
35 | if (sc->h.command & 16) | |
36 | val |= SBE_2T3E3_21143_VAL_WRITE_AND_INVALIDATE_ENABLE; | |
37 | ||
38 | switch (sc->h.cache_size) { | |
39 | case 32: | |
40 | val |= SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_32; | |
41 | break; | |
42 | case 16: | |
43 | val |= SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_16; | |
44 | break; | |
45 | case 8: | |
46 | val |= SBE_2T3E3_21143_VAL_CACHE_ALIGNMENT_8; | |
47 | break; | |
48 | default: | |
49 | break; | |
50 | } | |
51 | ||
52 | dc_write(sc->addr, SBE_2T3E3_21143_REG_BUS_MODE, val); | |
53 | ||
54 | /* OPERATION_MODE (CSR6) */ | |
55 | val = SBE_2T3E3_21143_VAL_RECEIVE_ALL | | |
56 | SBE_2T3E3_21143_VAL_MUST_BE_ONE | | |
57 | SBE_2T3E3_21143_VAL_THRESHOLD_CONTROL_BITS_1 | | |
58 | SBE_2T3E3_21143_VAL_LOOPBACK_OFF | | |
59 | SBE_2T3E3_21143_VAL_PASS_ALL_MULTICAST | | |
60 | SBE_2T3E3_21143_VAL_PROMISCUOUS_MODE | | |
61 | SBE_2T3E3_21143_VAL_PASS_BAD_FRAMES; | |
62 | dc_write(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, val); | |
63 | if (sc->p.loopback == SBE_2T3E3_LOOPBACK_ETHERNET) | |
64 | sc->p.loopback = SBE_2T3E3_LOOPBACK_NONE; | |
65 | ||
66 | #if 0 /* No need to clear this register - and it may be in use */ | |
67 | /* | |
68 | * BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT (CSR9) | |
69 | */ | |
70 | val = 0; | |
71 | dc_write(sc->addr, SBE_2T3E3_21143_REG_BOOT_ROM_SERIAL_ROM_AND_MII_MANAGEMENT, val); | |
72 | #endif | |
73 | ||
74 | /* | |
75 | * GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL (CSR11) | |
76 | */ | |
77 | val = SBE_2T3E3_21143_VAL_CYCLE_SIZE | | |
78 | SBE_2T3E3_21143_VAL_TRANSMIT_TIMER | | |
79 | SBE_2T3E3_21143_VAL_NUMBER_OF_TRANSMIT_PACKETS | | |
80 | SBE_2T3E3_21143_VAL_RECEIVE_TIMER | | |
81 | SBE_2T3E3_21143_VAL_NUMBER_OF_RECEIVE_PACKETS; | |
82 | dc_write(sc->addr, SBE_2T3E3_21143_REG_GENERAL_PURPOSE_TIMER_AND_INTERRUPT_MITIGATION_CONTROL, val); | |
83 | ||
84 | /* prepare descriptors and data for receive and transmit procecsses */ | |
85 | if (dc_init_descriptor_list(sc) != 0) | |
86 | return; | |
87 | ||
88 | /* clear ethernet interrupts status */ | |
89 | dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, 0xFFFFFFFF); | |
90 | ||
91 | /* SIA mode registers */ | |
92 | dc_set_output_port(sc); | |
93 | } | |
94 | ||
95 | void dc_start(struct channel *sc) | |
96 | { | |
97 | u32 val; | |
98 | ||
99 | if (!(sc->r.flags & SBE_2T3E3_FLAG_NETWORK_UP)) | |
100 | return; | |
101 | ||
102 | dc_init(sc); | |
103 | ||
104 | /* get actual LOS and OOF status */ | |
105 | switch (sc->p.frame_type) { | |
106 | case SBE_2T3E3_FRAME_TYPE_E3_G751: | |
107 | case SBE_2T3E3_FRAME_TYPE_E3_G832: | |
108 | val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2); | |
109 | dev_dbg(&sc->pdev->dev, "Start Framer Rx Status = %02X\n", val); | |
110 | sc->s.OOF = val & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0; | |
111 | break; | |
112 | case SBE_2T3E3_FRAME_TYPE_T3_CBIT: | |
113 | case SBE_2T3E3_FRAME_TYPE_T3_M13: | |
114 | val = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS); | |
115 | dev_dbg(&sc->pdev->dev, "Start Framer Rx Status = %02X\n", val); | |
116 | sc->s.OOF = val & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0; | |
117 | break; | |
118 | default: | |
119 | break; | |
120 | } | |
121 | cpld_LOS_update(sc); | |
122 | ||
123 | /* start receive and transmit processes */ | |
124 | dc_transmitter_onoff(sc, SBE_2T3E3_ON); | |
125 | dc_receiver_onoff(sc, SBE_2T3E3_ON); | |
126 | ||
127 | /* start interrupts */ | |
128 | dc_start_intr(sc); | |
129 | } | |
130 | ||
131 | #define MAX_INT_WAIT_CNT 12000 | |
132 | void dc_stop(struct channel *sc) | |
133 | { | |
134 | int wcnt; | |
135 | ||
136 | /* stop receive and transmit processes */ | |
137 | dc_receiver_onoff(sc, SBE_2T3E3_OFF); | |
138 | dc_transmitter_onoff(sc, SBE_2T3E3_OFF); | |
139 | ||
140 | /* turn off ethernet interrupts */ | |
141 | dc_stop_intr(sc); | |
142 | ||
143 | /* wait to ensure the interrupts have been completed */ | |
144 | for (wcnt = 0; wcnt < MAX_INT_WAIT_CNT; wcnt++) { | |
145 | udelay(5); | |
146 | if (!sc->interrupt_active) | |
147 | break; | |
148 | } | |
149 | if (wcnt >= MAX_INT_WAIT_CNT) | |
150 | dev_warn(&sc->pdev->dev, "SBE 2T3E3: Interrupt active too long\n"); | |
151 | ||
152 | /* clear all receive/transmit data */ | |
153 | dc_drop_descriptor_list(sc); | |
154 | } | |
155 | ||
156 | void dc_start_intr(struct channel *sc) | |
157 | { | |
158 | if (sc->p.loopback == SBE_2T3E3_LOOPBACK_NONE && sc->s.OOF) | |
159 | return; | |
160 | ||
161 | if (sc->p.receiver_on || sc->p.transmitter_on) { | |
162 | if (!sc->ether.interrupt_enable_mask) | |
163 | dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, 0xFFFFFFFF); | |
164 | ||
165 | sc->ether.interrupt_enable_mask = | |
166 | SBE_2T3E3_21143_VAL_NORMAL_INTERRUPT_SUMMARY_ENABLE | | |
167 | SBE_2T3E3_21143_VAL_ABNORMAL_INTERRUPT_SUMMARY_ENABLE | | |
168 | SBE_2T3E3_21143_VAL_RECEIVE_STOPPED_ENABLE | | |
169 | SBE_2T3E3_21143_VAL_RECEIVE_BUFFER_UNAVAILABLE_ENABLE | | |
170 | SBE_2T3E3_21143_VAL_RECEIVE_INTERRUPT_ENABLE | | |
171 | SBE_2T3E3_21143_VAL_TRANSMIT_UNDERFLOW_INTERRUPT_ENABLE | | |
172 | SBE_2T3E3_21143_VAL_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE | | |
173 | SBE_2T3E3_21143_VAL_TRANSMIT_STOPPED_ENABLE | | |
174 | SBE_2T3E3_21143_VAL_TRANSMIT_INTERRUPT_ENABLE; | |
175 | ||
176 | dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, | |
177 | sc->ether.interrupt_enable_mask); | |
178 | } | |
179 | } | |
180 | ||
181 | void dc_stop_intr(struct channel *sc) | |
182 | { | |
183 | sc->ether.interrupt_enable_mask = 0; | |
184 | dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, 0); | |
185 | } | |
186 | ||
187 | void dc_reset(struct channel *sc) | |
188 | { | |
189 | /* turn off ethernet interrupts */ | |
190 | dc_write(sc->addr, SBE_2T3E3_21143_REG_INTERRUPT_ENABLE, 0); | |
191 | dc_write(sc->addr, SBE_2T3E3_21143_REG_STATUS, 0xFFFFFFFF); | |
192 | ||
193 | /* software reset */ | |
194 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_BUS_MODE, | |
195 | SBE_2T3E3_21143_VAL_SOFTWARE_RESET); | |
196 | udelay(4); /* 50 PCI cycles < 2us */ | |
197 | ||
198 | /* clear hardware configuration */ | |
199 | dc_write(sc->addr, SBE_2T3E3_21143_REG_BUS_MODE, 0); | |
200 | ||
201 | /* clear software configuration */ | |
202 | dc_write(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, 0); | |
203 | ||
204 | /* turn off SIA reset */ | |
205 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY, | |
206 | SBE_2T3E3_21143_VAL_SIA_RESET); | |
207 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_TRANSMIT_AND_RECEIVE, 0); | |
208 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_AND_GENERAL_PURPOSE_PORT, 0); | |
209 | } | |
210 | ||
211 | ||
212 | void dc_receiver_onoff(struct channel *sc, u32 mode) | |
213 | { | |
214 | u32 i, state = 0; | |
215 | ||
216 | if (sc->p.receiver_on == mode) | |
217 | return; | |
218 | ||
219 | switch (mode) { | |
220 | case SBE_2T3E3_OFF: | |
221 | if (dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE) & | |
222 | SBE_2T3E3_21143_VAL_RECEIVE_START) { | |
223 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
224 | SBE_2T3E3_21143_VAL_RECEIVE_START); | |
225 | ||
226 | for (i = 0; i < 16; i++) { | |
227 | state = dc_read(sc->addr, SBE_2T3E3_21143_REG_STATUS) & | |
228 | SBE_2T3E3_21143_VAL_RECEIVE_PROCESS_STATE; | |
229 | if (state == SBE_2T3E3_21143_VAL_RX_STOPPED) | |
230 | break; | |
231 | udelay(5); | |
232 | } | |
233 | if (state != SBE_2T3E3_21143_VAL_RX_STOPPED) | |
234 | dev_warn(&sc->pdev->dev, "SBE 2T3E3: Rx failed to stop\n"); | |
235 | else | |
236 | dev_info(&sc->pdev->dev, "SBE 2T3E3: Rx off\n"); | |
237 | } | |
238 | break; | |
239 | case SBE_2T3E3_ON: | |
240 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
241 | SBE_2T3E3_21143_VAL_RECEIVE_START); | |
242 | udelay(100); | |
243 | dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_POLL_DEMAND, 0xFFFFFFFF); | |
244 | break; | |
245 | default: | |
246 | return; | |
247 | } | |
248 | ||
249 | sc->p.receiver_on = mode; | |
250 | } | |
251 | ||
252 | void dc_transmitter_onoff(struct channel *sc, u32 mode) | |
253 | { | |
254 | u32 i, state = 0; | |
255 | ||
256 | if (sc->p.transmitter_on == mode) | |
257 | return; | |
258 | ||
259 | switch (mode) { | |
260 | case SBE_2T3E3_OFF: | |
261 | if (dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE) & | |
262 | SBE_2T3E3_21143_VAL_TRANSMISSION_START) { | |
263 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
264 | SBE_2T3E3_21143_VAL_TRANSMISSION_START); | |
265 | ||
266 | for (i = 0; i < 16; i++) { | |
267 | state = dc_read(sc->addr, SBE_2T3E3_21143_REG_STATUS) & | |
268 | SBE_2T3E3_21143_VAL_TRANSMISSION_PROCESS_STATE; | |
269 | if (state == SBE_2T3E3_21143_VAL_TX_STOPPED) | |
270 | break; | |
271 | udelay(5); | |
272 | } | |
273 | if (state != SBE_2T3E3_21143_VAL_TX_STOPPED) | |
274 | dev_warn(&sc->pdev->dev, "SBE 2T3E3: Tx failed to stop\n"); | |
275 | } | |
276 | break; | |
277 | case SBE_2T3E3_ON: | |
278 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
279 | SBE_2T3E3_21143_VAL_TRANSMISSION_START); | |
280 | udelay(100); | |
281 | dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_POLL_DEMAND, 0xFFFFFFFF); | |
282 | break; | |
283 | default: | |
284 | return; | |
285 | } | |
286 | ||
287 | sc->p.transmitter_on = mode; | |
288 | } | |
289 | ||
290 | ||
291 | ||
292 | void dc_set_loopback(struct channel *sc, u32 mode) | |
293 | { | |
294 | u32 val; | |
295 | ||
296 | switch (mode) { | |
297 | case SBE_2T3E3_21143_VAL_LOOPBACK_OFF: | |
298 | case SBE_2T3E3_21143_VAL_LOOPBACK_INTERNAL: | |
299 | break; | |
300 | default: | |
301 | return; | |
302 | } | |
303 | ||
304 | #if 0 | |
305 | /* restart SIA */ | |
306 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY, | |
307 | SBE_2T3E3_21143_VAL_SIA_RESET); | |
308 | udelay(1000); | |
309 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY, | |
310 | SBE_2T3E3_21143_VAL_SIA_RESET); | |
311 | #endif | |
312 | ||
313 | /* select loopback mode */ | |
314 | val = dc_read(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE) & | |
315 | ~SBE_2T3E3_21143_VAL_OPERATING_MODE; | |
316 | val |= mode; | |
317 | dc_write(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, val); | |
318 | ||
319 | if (mode == SBE_2T3E3_21143_VAL_LOOPBACK_OFF) | |
320 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
321 | SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE); | |
322 | else | |
323 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
324 | SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE); | |
325 | } | |
326 | ||
327 | u32 dc_init_descriptor_list(struct channel *sc) | |
328 | { | |
329 | u32 i, j; | |
330 | struct sk_buff *m; | |
331 | ||
332 | if (sc->ether.rx_ring == NULL) | |
333 | sc->ether.rx_ring = kzalloc(SBE_2T3E3_RX_DESC_RING_SIZE * | |
334 | sizeof(t3e3_rx_desc_t), GFP_KERNEL); | |
335 | if (sc->ether.rx_ring == NULL) { | |
336 | dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); | |
337 | return ENOMEM; | |
338 | } | |
339 | ||
340 | if (sc->ether.tx_ring == NULL) | |
341 | sc->ether.tx_ring = kzalloc(SBE_2T3E3_TX_DESC_RING_SIZE * | |
342 | sizeof(t3e3_tx_desc_t), GFP_KERNEL); | |
343 | if (sc->ether.tx_ring == NULL) { | |
921a86e0 KH |
344 | kfree(sc->ether.rx_ring); |
345 | sc->ether.rx_ring = NULL; | |
346 | dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); | |
347 | return ENOMEM; | |
348 | } | |
349 | ||
350 | ||
351 | /* | |
352 | * Receive ring | |
353 | */ | |
354 | for (i = 0; i < SBE_2T3E3_RX_DESC_RING_SIZE; i++) { | |
355 | sc->ether.rx_ring[i].rdes0 = SBE_2T3E3_RX_DESC_21143_OWN; | |
356 | sc->ether.rx_ring[i].rdes1 = | |
357 | SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED | SBE_2T3E3_MTU; | |
358 | ||
359 | if (sc->ether.rx_data[i] == NULL) { | |
360 | if (!(m = dev_alloc_skb(MCLBYTES))) { | |
361 | for (j = 0; j < i; j++) { | |
362 | dev_kfree_skb_any(sc->ether.rx_data[j]); | |
363 | sc->ether.rx_data[j] = NULL; | |
364 | } | |
921a86e0 KH |
365 | kfree(sc->ether.rx_ring); |
366 | sc->ether.rx_ring = NULL; | |
921a86e0 KH |
367 | kfree(sc->ether.tx_ring); |
368 | sc->ether.tx_ring = NULL; | |
369 | dev_err(&sc->pdev->dev, "SBE 2T3E3: token_alloc err:" | |
370 | " no buffer space for RX ring\n"); | |
371 | return ENOBUFS; | |
372 | } | |
373 | sc->ether.rx_data[i] = m; | |
374 | } | |
375 | sc->ether.rx_ring[i].rdes2 = virt_to_phys(sc->ether.rx_data[i]->data); | |
376 | ||
377 | sc->ether.rx_ring[i].rdes3 = virt_to_phys( | |
378 | &sc->ether.rx_ring[(i + 1) % SBE_2T3E3_RX_DESC_RING_SIZE]); | |
379 | } | |
380 | sc->ether.rx_ring[SBE_2T3E3_RX_DESC_RING_SIZE - 1].rdes1 |= | |
381 | SBE_2T3E3_RX_DESC_END_OF_RING; | |
382 | sc->ether.rx_ring_current_read = 0; | |
383 | ||
384 | dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS, | |
385 | virt_to_phys(&sc->ether.rx_ring[0])); | |
386 | ||
387 | /* | |
388 | * Transmit ring | |
389 | */ | |
390 | for (i = 0; i < SBE_2T3E3_TX_DESC_RING_SIZE; i++) { | |
391 | sc->ether.tx_ring[i].tdes0 = 0; | |
392 | sc->ether.tx_ring[i].tdes1 = SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED | | |
393 | SBE_2T3E3_TX_DESC_DISABLE_PADDING; | |
394 | ||
395 | sc->ether.tx_ring[i].tdes2 = 0; | |
396 | sc->ether.tx_data[i] = NULL; | |
397 | ||
398 | sc->ether.tx_ring[i].tdes3 = virt_to_phys( | |
399 | &sc->ether.tx_ring[(i + 1) % SBE_2T3E3_TX_DESC_RING_SIZE]); | |
400 | } | |
401 | sc->ether.tx_ring[SBE_2T3E3_TX_DESC_RING_SIZE - 1].tdes1 |= | |
402 | SBE_2T3E3_TX_DESC_END_OF_RING; | |
403 | ||
404 | dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS, | |
405 | virt_to_phys(&sc->ether.tx_ring[0])); | |
406 | sc->ether.tx_ring_current_read = 0; | |
407 | sc->ether.tx_ring_current_write = 0; | |
408 | sc->ether.tx_free_cnt = SBE_2T3E3_TX_DESC_RING_SIZE; | |
409 | spin_lock_init(&sc->ether.tx_lock); | |
410 | ||
411 | return 0; | |
412 | } | |
413 | ||
414 | void dc_clear_descriptor_list(struct channel *sc) | |
415 | { | |
416 | u32 i; | |
417 | ||
418 | /* clear CSR3 and CSR4 */ | |
419 | dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS, 0); | |
420 | dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS, 0); | |
421 | ||
422 | /* free all data buffers on TX ring */ | |
423 | for (i = 0; i < SBE_2T3E3_TX_DESC_RING_SIZE; i++) { | |
424 | if (sc->ether.tx_data[i] != NULL) { | |
425 | dev_kfree_skb_any(sc->ether.tx_data[i]); | |
426 | sc->ether.tx_data[i] = NULL; | |
427 | } | |
428 | } | |
429 | } | |
430 | ||
431 | void dc_drop_descriptor_list(struct channel *sc) | |
432 | { | |
433 | u32 i; | |
434 | ||
435 | dc_clear_descriptor_list(sc); | |
436 | ||
437 | /* free all data buffers on RX ring */ | |
438 | for (i = 0; i < SBE_2T3E3_RX_DESC_RING_SIZE; i++) { | |
439 | if (sc->ether.rx_data[i] != NULL) { | |
440 | dev_kfree_skb_any(sc->ether.rx_data[i]); | |
441 | sc->ether.rx_data[i] = NULL; | |
442 | } | |
443 | } | |
444 | ||
24c92eac AB |
445 | kfree(sc->ether.rx_ring); |
446 | sc->ether.rx_ring = NULL; | |
447 | kfree(sc->ether.tx_ring); | |
448 | sc->ether.tx_ring = NULL; | |
921a86e0 KH |
449 | } |
450 | ||
451 | ||
452 | void dc_set_output_port(struct channel *sc) | |
453 | { | |
454 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
455 | SBE_2T3E3_21143_VAL_PORT_SELECT); | |
456 | ||
457 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_STATUS, 0x00000301); | |
458 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY, 0); | |
459 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_TRANSMIT_AND_RECEIVE, 0); | |
460 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_AND_GENERAL_PURPOSE_PORT, 0x08000011); | |
461 | ||
462 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | |
463 | SBE_2T3E3_21143_VAL_TRANSMIT_THRESHOLD_MODE_100Mbs | | |
464 | SBE_2T3E3_21143_VAL_HEARTBEAT_DISABLE | | |
465 | SBE_2T3E3_21143_VAL_PORT_SELECT | | |
466 | SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE); | |
467 | } | |
468 | ||
469 | void dc_restart(struct channel *sc) | |
470 | { | |
471 | dev_warn(&sc->pdev->dev, "SBE 2T3E3: 21143 restart\n"); | |
472 | ||
473 | dc_stop(sc); | |
474 | dc_reset(sc); | |
475 | dc_init(sc); /* stop + reset + init */ | |
476 | dc_start(sc); | |
477 | } |