diff options
author | Krzysztof Halasa <khc@pm.waw.pl> | 2010-08-12 17:14:07 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-30 20:36:50 -0400 |
commit | 921a86e0e306e42452e16894f2cc792659ede16b (patch) | |
tree | 3c3709b0ad5c9a324db7a56530675b9d9f2198c1 /drivers/staging/sbe-2t3e3/dc.c | |
parent | b0b57633089ee4726aefe20760132c41bbd83fff (diff) |
Staging: Add SBE 2T3E3 WAN driver
This is a driver for SBE Inc.'s dual port T3/E3 WAN cards. Based on
their original GPLed driver.
The original driver tarball is now accessible at
http://userweb.kernel.org/~chris/SBE_2T3_Linux_2.0c.tgz
It needs at least a new generic HDLC setup code (not yet written) before
moving to drivers/net/wan.
Signed-off-by: Krzysztof HaĆasa <khc@pm.waw.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/sbe-2t3e3/dc.c')
-rw-r--r-- | drivers/staging/sbe-2t3e3/dc.c | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/drivers/staging/sbe-2t3e3/dc.c b/drivers/staging/sbe-2t3e3/dc.c new file mode 100644 index 00000000000..126a9720c6b --- /dev/null +++ b/drivers/staging/sbe-2t3e3/dc.c | |||
@@ -0,0 +1,502 @@ | |||
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) { | ||
344 | #ifdef T3E3_USE_CONTIGMALLOC | ||
345 | t3e3_contigmemory_size = SBE_2T3E3_RX_DESC_RING_SIZE * | ||
346 | sizeof(t3e3_rx_desc_t); | ||
347 | #endif | ||
348 | kfree(sc->ether.rx_ring); | ||
349 | sc->ether.rx_ring = NULL; | ||
350 | dev_err(&sc->pdev->dev, "SBE 2T3E3: no buffer space for RX ring\n"); | ||
351 | return ENOMEM; | ||
352 | } | ||
353 | |||
354 | |||
355 | /* | ||
356 | * Receive ring | ||
357 | */ | ||
358 | for (i = 0; i < SBE_2T3E3_RX_DESC_RING_SIZE; i++) { | ||
359 | sc->ether.rx_ring[i].rdes0 = SBE_2T3E3_RX_DESC_21143_OWN; | ||
360 | sc->ether.rx_ring[i].rdes1 = | ||
361 | SBE_2T3E3_RX_DESC_SECOND_ADDRESS_CHAINED | SBE_2T3E3_MTU; | ||
362 | |||
363 | if (sc->ether.rx_data[i] == NULL) { | ||
364 | if (!(m = dev_alloc_skb(MCLBYTES))) { | ||
365 | for (j = 0; j < i; j++) { | ||
366 | dev_kfree_skb_any(sc->ether.rx_data[j]); | ||
367 | sc->ether.rx_data[j] = NULL; | ||
368 | } | ||
369 | #ifdef T3E3_USE_CONTIGMALLOC | ||
370 | t3e3_contigmemory_size = SBE_2T3E3_RX_DESC_RING_SIZE * | ||
371 | sizeof(t3e3_rx_desc_t); | ||
372 | #endif | ||
373 | kfree(sc->ether.rx_ring); | ||
374 | sc->ether.rx_ring = NULL; | ||
375 | #ifdef T3E3_USE_CONTIGMALLOC | ||
376 | t3e3_contigmemory_size = SBE_2T3E3_TX_DESC_RING_SIZE * | ||
377 | sizeof(t3e3_tx_desc_t); | ||
378 | #endif | ||
379 | kfree(sc->ether.tx_ring); | ||
380 | sc->ether.tx_ring = NULL; | ||
381 | dev_err(&sc->pdev->dev, "SBE 2T3E3: token_alloc err:" | ||
382 | " no buffer space for RX ring\n"); | ||
383 | return ENOBUFS; | ||
384 | } | ||
385 | sc->ether.rx_data[i] = m; | ||
386 | } | ||
387 | sc->ether.rx_ring[i].rdes2 = virt_to_phys(sc->ether.rx_data[i]->data); | ||
388 | |||
389 | sc->ether.rx_ring[i].rdes3 = virt_to_phys( | ||
390 | &sc->ether.rx_ring[(i + 1) % SBE_2T3E3_RX_DESC_RING_SIZE]); | ||
391 | } | ||
392 | sc->ether.rx_ring[SBE_2T3E3_RX_DESC_RING_SIZE - 1].rdes1 |= | ||
393 | SBE_2T3E3_RX_DESC_END_OF_RING; | ||
394 | sc->ether.rx_ring_current_read = 0; | ||
395 | |||
396 | dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS, | ||
397 | virt_to_phys(&sc->ether.rx_ring[0])); | ||
398 | |||
399 | /* | ||
400 | * Transmit ring | ||
401 | */ | ||
402 | for (i = 0; i < SBE_2T3E3_TX_DESC_RING_SIZE; i++) { | ||
403 | sc->ether.tx_ring[i].tdes0 = 0; | ||
404 | sc->ether.tx_ring[i].tdes1 = SBE_2T3E3_TX_DESC_SECOND_ADDRESS_CHAINED | | ||
405 | SBE_2T3E3_TX_DESC_DISABLE_PADDING; | ||
406 | |||
407 | sc->ether.tx_ring[i].tdes2 = 0; | ||
408 | sc->ether.tx_data[i] = NULL; | ||
409 | |||
410 | sc->ether.tx_ring[i].tdes3 = virt_to_phys( | ||
411 | &sc->ether.tx_ring[(i + 1) % SBE_2T3E3_TX_DESC_RING_SIZE]); | ||
412 | } | ||
413 | sc->ether.tx_ring[SBE_2T3E3_TX_DESC_RING_SIZE - 1].tdes1 |= | ||
414 | SBE_2T3E3_TX_DESC_END_OF_RING; | ||
415 | |||
416 | dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS, | ||
417 | virt_to_phys(&sc->ether.tx_ring[0])); | ||
418 | sc->ether.tx_ring_current_read = 0; | ||
419 | sc->ether.tx_ring_current_write = 0; | ||
420 | sc->ether.tx_free_cnt = SBE_2T3E3_TX_DESC_RING_SIZE; | ||
421 | spin_lock_init(&sc->ether.tx_lock); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | void dc_clear_descriptor_list(struct channel *sc) | ||
427 | { | ||
428 | u32 i; | ||
429 | |||
430 | /* clear CSR3 and CSR4 */ | ||
431 | dc_write(sc->addr, SBE_2T3E3_21143_REG_RECEIVE_LIST_BASE_ADDRESS, 0); | ||
432 | dc_write(sc->addr, SBE_2T3E3_21143_REG_TRANSMIT_LIST_BASE_ADDRESS, 0); | ||
433 | |||
434 | /* free all data buffers on TX ring */ | ||
435 | for (i = 0; i < SBE_2T3E3_TX_DESC_RING_SIZE; i++) { | ||
436 | if (sc->ether.tx_data[i] != NULL) { | ||
437 | dev_kfree_skb_any(sc->ether.tx_data[i]); | ||
438 | sc->ether.tx_data[i] = NULL; | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | void dc_drop_descriptor_list(struct channel *sc) | ||
444 | { | ||
445 | u32 i; | ||
446 | |||
447 | dc_clear_descriptor_list(sc); | ||
448 | |||
449 | /* free all data buffers on RX ring */ | ||
450 | for (i = 0; i < SBE_2T3E3_RX_DESC_RING_SIZE; i++) { | ||
451 | if (sc->ether.rx_data[i] != NULL) { | ||
452 | dev_kfree_skb_any(sc->ether.rx_data[i]); | ||
453 | sc->ether.rx_data[i] = NULL; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | if (sc->ether.rx_ring != NULL) { | ||
458 | #ifdef T3E3_USE_CONTIGMALLOC | ||
459 | t3e3_contigmemory_size = SBE_2T3E3_RX_DESC_RING_SIZE * | ||
460 | sizeof(t3e3_rx_desc_t); | ||
461 | #endif | ||
462 | kfree(sc->ether.rx_ring); | ||
463 | sc->ether.rx_ring = NULL; | ||
464 | } | ||
465 | |||
466 | if (sc->ether.tx_ring != NULL) { | ||
467 | #ifdef T3E3_USE_CONTIGMALLOC | ||
468 | t3e3_contigmemory_size = SBE_2T3E3_TX_DESC_RING_SIZE * | ||
469 | sizeof(t3e3_tx_desc_t); | ||
470 | #endif | ||
471 | kfree(sc->ether.tx_ring); | ||
472 | sc->ether.tx_ring = NULL; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | |||
477 | void dc_set_output_port(struct channel *sc) | ||
478 | { | ||
479 | dc_clear_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | ||
480 | SBE_2T3E3_21143_VAL_PORT_SELECT); | ||
481 | |||
482 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_STATUS, 0x00000301); | ||
483 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_CONNECTIVITY, 0); | ||
484 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_TRANSMIT_AND_RECEIVE, 0); | ||
485 | dc_write(sc->addr, SBE_2T3E3_21143_REG_SIA_AND_GENERAL_PURPOSE_PORT, 0x08000011); | ||
486 | |||
487 | dc_set_bits(sc->addr, SBE_2T3E3_21143_REG_OPERATION_MODE, | ||
488 | SBE_2T3E3_21143_VAL_TRANSMIT_THRESHOLD_MODE_100Mbs | | ||
489 | SBE_2T3E3_21143_VAL_HEARTBEAT_DISABLE | | ||
490 | SBE_2T3E3_21143_VAL_PORT_SELECT | | ||
491 | SBE_2T3E3_21143_VAL_FULL_DUPLEX_MODE); | ||
492 | } | ||
493 | |||
494 | void dc_restart(struct channel *sc) | ||
495 | { | ||
496 | dev_warn(&sc->pdev->dev, "SBE 2T3E3: 21143 restart\n"); | ||
497 | |||
498 | dc_stop(sc); | ||
499 | dc_reset(sc); | ||
500 | dc_init(sc); /* stop + reset + init */ | ||
501 | dc_start(sc); | ||
502 | } | ||