diff options
Diffstat (limited to 'drivers/atm')
46 files changed, 46840 insertions, 0 deletions
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig new file mode 100644 index 000000000000..489de81ea609 --- /dev/null +++ b/drivers/atm/Kconfig | |||
@@ -0,0 +1,448 @@ | |||
1 | # | ||
2 | # ATM device configuration | ||
3 | # | ||
4 | |||
5 | menu "ATM drivers" | ||
6 | depends on NETDEVICES && ATM | ||
7 | |||
8 | config ATM_TCP | ||
9 | tristate "ATM over TCP" | ||
10 | depends on INET && ATM | ||
11 | help | ||
12 | ATM over TCP driver. Useful mainly for development and for | ||
13 | experiments. If unsure, say N. | ||
14 | |||
15 | config ATM_LANAI | ||
16 | tristate "Efficient Networks Speedstream 3010" | ||
17 | depends on PCI && ATM | ||
18 | help | ||
19 | Supports ATM cards based on the Efficient Networks "Lanai" | ||
20 | chipset such as the Speedstream 3010 and the ENI-25p. The | ||
21 | Speedstream 3060 is currently not supported since we don't | ||
22 | have the code to drive the on-board Alcatel DSL chipset (yet). | ||
23 | |||
24 | config ATM_ENI | ||
25 | tristate "Efficient Networks ENI155P" | ||
26 | depends on PCI && ATM | ||
27 | ---help--- | ||
28 | Driver for the Efficient Networks ENI155p series and SMC ATM | ||
29 | Power155 155 Mbps ATM adapters. Both, the versions with 512KB and | ||
30 | 2MB on-board RAM (Efficient calls them "C" and "S", respectively), | ||
31 | and the FPGA and the ASIC Tonga versions of the board are supported. | ||
32 | The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D) | ||
33 | adapters. | ||
34 | |||
35 | To compile this driver as a module, choose M here: the module will | ||
36 | be called eni. | ||
37 | |||
38 | config ATM_ENI_DEBUG | ||
39 | bool "Enable extended debugging" | ||
40 | depends on ATM_ENI | ||
41 | help | ||
42 | Extended debugging records various events and displays that list | ||
43 | when an inconsistency is detected. This mechanism is faster than | ||
44 | generally using printks, but still has some impact on performance. | ||
45 | Note that extended debugging may create certain race conditions | ||
46 | itself. Enable this ONLY if you suspect problems with the driver. | ||
47 | |||
48 | config ATM_ENI_TUNE_BURST | ||
49 | bool "Fine-tune burst settings" | ||
50 | depends on ATM_ENI | ||
51 | ---help--- | ||
52 | In order to obtain good throughput, the ENI NIC can transfer | ||
53 | multiple words of data per PCI bus access cycle. Such a multi-word | ||
54 | transfer is called a burst. | ||
55 | |||
56 | The default settings for the burst sizes are suitable for most PCI | ||
57 | chipsets. However, in some cases, large bursts may overrun buffers | ||
58 | in the PCI chipset and cause data corruption. In such cases, large | ||
59 | bursts must be disabled and only (slower) small bursts can be used. | ||
60 | The burst sizes can be set independently in the send (TX) and | ||
61 | receive (RX) direction. | ||
62 | |||
63 | Note that enabling many different burst sizes in the same direction | ||
64 | may increase the cost of setting up a transfer such that the | ||
65 | resulting throughput is lower than when using only the largest | ||
66 | available burst size. | ||
67 | |||
68 | Also, sometimes larger bursts lead to lower throughput, e.g. on an | ||
69 | Intel 440FX board, a drop from 135 Mbps to 103 Mbps was observed | ||
70 | when going from 8W to 16W bursts. | ||
71 | |||
72 | config ATM_ENI_BURST_TX_16W | ||
73 | bool "Enable 16W TX bursts (discouraged)" | ||
74 | depends on ATM_ENI_TUNE_BURST | ||
75 | help | ||
76 | Burst sixteen words at once in the send direction. This may work | ||
77 | with recent PCI chipsets, but is known to fail with older chipsets. | ||
78 | |||
79 | config ATM_ENI_BURST_TX_8W | ||
80 | bool "Enable 8W TX bursts (recommended)" | ||
81 | depends on ATM_ENI_TUNE_BURST | ||
82 | help | ||
83 | Burst eight words at once in the send direction. This is the default | ||
84 | setting. | ||
85 | |||
86 | config ATM_ENI_BURST_TX_4W | ||
87 | bool "Enable 4W TX bursts (optional)" | ||
88 | depends on ATM_ENI_TUNE_BURST | ||
89 | help | ||
90 | Burst four words at once in the send direction. You may want to try | ||
91 | this if you have disabled 8W bursts. Enabling 4W if 8W is also set | ||
92 | may or may not improve throughput. | ||
93 | |||
94 | config ATM_ENI_BURST_TX_2W | ||
95 | bool "Enable 2W TX bursts (optional)" | ||
96 | depends on ATM_ENI_TUNE_BURST | ||
97 | help | ||
98 | Burst two words at once in the send direction. You may want to try | ||
99 | this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or 8W | ||
100 | are also set may or may not improve throughput. | ||
101 | |||
102 | config ATM_ENI_BURST_RX_16W | ||
103 | bool "Enable 16W RX bursts (discouraged)" | ||
104 | depends on ATM_ENI_TUNE_BURST | ||
105 | help | ||
106 | Burst sixteen words at once in the receive direction. This may work | ||
107 | with recent PCI chipsets, but is known to fail with older chipsets. | ||
108 | |||
109 | config ATM_ENI_BURST_RX_8W | ||
110 | bool "Enable 8W RX bursts (discouraged)" | ||
111 | depends on ATM_ENI_TUNE_BURST | ||
112 | help | ||
113 | Burst eight words at once in the receive direction. This may work | ||
114 | with recent PCI chipsets, but is known to fail with older chipsets, | ||
115 | such as the Intel Neptune series. | ||
116 | |||
117 | config ATM_ENI_BURST_RX_4W | ||
118 | bool "Enable 4W RX bursts (recommended)" | ||
119 | depends on ATM_ENI_TUNE_BURST | ||
120 | help | ||
121 | Burst four words at once in the receive direction. This is the | ||
122 | default setting. Enabling 4W if 8W is also set may or may not | ||
123 | improve throughput. | ||
124 | |||
125 | config ATM_ENI_BURST_RX_2W | ||
126 | bool "Enable 2W RX bursts (optional)" | ||
127 | depends on ATM_ENI_TUNE_BURST | ||
128 | help | ||
129 | Burst two words at once in the receive direction. You may want to | ||
130 | try this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or | ||
131 | 8W are also set may or may not improve throughput. | ||
132 | |||
133 | config ATM_FIRESTREAM | ||
134 | tristate "Fujitsu FireStream (FS50/FS155) " | ||
135 | depends on PCI && ATM | ||
136 | help | ||
137 | Driver for the Fujitsu FireStream 155 (MB86697) and | ||
138 | FireStream 50 (MB86695) ATM PCI chips. | ||
139 | |||
140 | To compile this driver as a module, choose M here: the module will | ||
141 | be called firestream. | ||
142 | |||
143 | config ATM_ZATM | ||
144 | tristate "ZeitNet ZN1221/ZN1225" | ||
145 | depends on PCI && ATM | ||
146 | help | ||
147 | Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM | ||
148 | adapters. | ||
149 | |||
150 | To compile this driver as a module, choose M here: the module will | ||
151 | be called zatm. | ||
152 | |||
153 | config ATM_ZATM_DEBUG | ||
154 | bool "Enable extended debugging" | ||
155 | depends on ATM_ZATM | ||
156 | help | ||
157 | Extended debugging records various events and displays that list | ||
158 | when an inconsistency is detected. This mechanism is faster than | ||
159 | generally using printks, but still has some impact on performance. | ||
160 | Note that extended debugging may create certain race conditions | ||
161 | itself. Enable this ONLY if you suspect problems with the driver. | ||
162 | |||
163 | # bool 'Rolfs TI TNETA1570' CONFIG_ATM_TNETA1570 y | ||
164 | # if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then | ||
165 | # bool ' Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n | ||
166 | # fi | ||
167 | config ATM_NICSTAR | ||
168 | tristate "IDT 77201 (NICStAR) (ForeRunnerLE)" | ||
169 | depends on PCI && ATM && !64BIT | ||
170 | help | ||
171 | The NICStAR chipset family is used in a large number of ATM NICs for | ||
172 | 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE | ||
173 | series. Say Y if you have one of those. | ||
174 | |||
175 | To compile this driver as a module, choose M here: the module will | ||
176 | be called nicstar. | ||
177 | |||
178 | config ATM_NICSTAR_USE_SUNI | ||
179 | bool "Use suni PHY driver (155Mbps)" | ||
180 | depends on ATM_NICSTAR | ||
181 | help | ||
182 | Support for the S-UNI and compatible PHYsical layer chips. These are | ||
183 | found in most 155Mbps NICStAR based ATM cards, namely in the | ||
184 | ForeRunner LE155 cards. This driver provides detection of cable~ | ||
185 | removal and reinsertion and provides some statistics. This driver | ||
186 | doesn't have removal capability when compiled as a module, so if you | ||
187 | need that capability don't include S-UNI support (it's not needed to | ||
188 | make the card work). | ||
189 | |||
190 | config ATM_NICSTAR_USE_IDT77105 | ||
191 | bool "Use IDT77015 PHY driver (25Mbps)" | ||
192 | depends on ATM_NICSTAR | ||
193 | help | ||
194 | Support for the PHYsical layer chip in ForeRunner LE25 cards. In | ||
195 | addition to cable removal/reinsertion detection, this driver allows | ||
196 | you to control the loopback mode of the chip via a dedicated IOCTL. | ||
197 | This driver is required for proper handling of temporary carrier | ||
198 | loss, so if you have a 25Mbps NICStAR based ATM card you must say Y. | ||
199 | |||
200 | config ATM_IDT77252 | ||
201 | tristate "IDT 77252 (NICStAR II)" | ||
202 | depends on PCI && ATM | ||
203 | help | ||
204 | Driver for the IDT 77252 ATM PCI chips. | ||
205 | |||
206 | To compile this driver as a module, choose M here: the module will | ||
207 | be called idt77252. | ||
208 | |||
209 | config ATM_IDT77252_DEBUG | ||
210 | bool "Enable debugging messages" | ||
211 | depends on ATM_IDT77252 | ||
212 | help | ||
213 | Somewhat useful debugging messages are available. The choice of | ||
214 | messages is controlled by a bitmap. This may be specified as a | ||
215 | module argument. See the file <file:drivers/atm/idt77252.h> for | ||
216 | the meanings of the bits in the mask. | ||
217 | |||
218 | When active, these messages can have a significant impact on the | ||
219 | speed of the driver, and the size of your syslog files! When | ||
220 | inactive, they will have only a modest impact on performance. | ||
221 | |||
222 | config ATM_IDT77252_RCV_ALL | ||
223 | bool "Receive ALL cells in raw queue" | ||
224 | depends on ATM_IDT77252 | ||
225 | help | ||
226 | Enable receiving of all cells on the ATM link, that do not match | ||
227 | an open connection in the raw cell queue of the driver. Useful | ||
228 | for debugging or special applications only, so the safe answer is N. | ||
229 | |||
230 | config ATM_IDT77252_USE_SUNI | ||
231 | bool | ||
232 | depends on ATM_IDT77252 | ||
233 | default y | ||
234 | |||
235 | config ATM_AMBASSADOR | ||
236 | tristate "Madge Ambassador (Collage PCI 155 Server)" | ||
237 | depends on PCI && ATM | ||
238 | help | ||
239 | This is a driver for ATMizer based ATM card produced by Madge | ||
240 | Networks Ltd. Say Y (or M to compile as a module named ambassador) | ||
241 | here if you have one of these cards. | ||
242 | |||
243 | config ATM_AMBASSADOR_DEBUG | ||
244 | bool "Enable debugging messages" | ||
245 | depends on ATM_AMBASSADOR | ||
246 | ---help--- | ||
247 | Somewhat useful debugging messages are available. The choice of | ||
248 | messages is controlled by a bitmap. This may be specified as a | ||
249 | module argument (kernel command line argument as well?), changed | ||
250 | dynamically using an ioctl (not yet) or changed by sending the | ||
251 | string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file | ||
252 | <file:drivers/atm/ambassador.h> for the meanings of the bits in the | ||
253 | mask. | ||
254 | |||
255 | When active, these messages can have a significant impact on the | ||
256 | speed of the driver, and the size of your syslog files! When | ||
257 | inactive, they will have only a modest impact on performance. | ||
258 | |||
259 | config ATM_HORIZON | ||
260 | tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)" | ||
261 | depends on PCI && ATM | ||
262 | help | ||
263 | This is a driver for the Horizon chipset ATM adapter cards once | ||
264 | produced by Madge Networks Ltd. Say Y (or M to compile as a module | ||
265 | named horizon) here if you have one of these cards. | ||
266 | |||
267 | config ATM_HORIZON_DEBUG | ||
268 | bool "Enable debugging messages" | ||
269 | depends on ATM_HORIZON | ||
270 | ---help--- | ||
271 | Somewhat useful debugging messages are available. The choice of | ||
272 | messages is controlled by a bitmap. This may be specified as a | ||
273 | module argument (kernel command line argument as well?), changed | ||
274 | dynamically using an ioctl (not yet) or changed by sending the | ||
275 | string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file | ||
276 | <file:drivers/atm/horizon.h> for the meanings of the bits in the | ||
277 | mask. | ||
278 | |||
279 | When active, these messages can have a significant impact on the | ||
280 | speed of the driver, and the size of your syslog files! When | ||
281 | inactive, they will have only a modest impact on performance. | ||
282 | |||
283 | config ATM_IA | ||
284 | tristate "Interphase ATM PCI x575/x525/x531" | ||
285 | depends on PCI && ATM && !64BIT | ||
286 | ---help--- | ||
287 | This is a driver for the Interphase (i)ChipSAR adapter cards | ||
288 | which include a variety of variants in term of the size of the | ||
289 | control memory (128K-1KVC, 512K-4KVC), the size of the packet | ||
290 | memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3, | ||
291 | UTP155, UTP25, DS3 and E3). Go to: | ||
292 | <http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM> | ||
293 | for more info about the cards. Say Y (or M to compile as a module | ||
294 | named iphase) here if you have one of these cards. | ||
295 | |||
296 | See the file <file:Documentation/networking/iphase.txt> for further | ||
297 | details. | ||
298 | |||
299 | config ATM_IA_DEBUG | ||
300 | bool "Enable debugging messages" | ||
301 | depends on ATM_IA | ||
302 | ---help--- | ||
303 | Somewhat useful debugging messages are available. The choice of | ||
304 | messages is controlled by a bitmap. This may be specified as a | ||
305 | module argument (kernel command line argument as well?), changed | ||
306 | dynamically using an ioctl (Get the debug utility, iadbg, from | ||
307 | <ftp://ftp.iphase.com/pub/atm/pci/>). | ||
308 | |||
309 | See the file <file:drivers/atm/iphase.h> for the meanings of the | ||
310 | bits in the mask. | ||
311 | |||
312 | When active, these messages can have a significant impact on the | ||
313 | speed of the driver, and the size of your syslog files! When | ||
314 | inactive, they will have only a modest impact on performance. | ||
315 | |||
316 | config ATM_FORE200E_MAYBE | ||
317 | tristate "FORE Systems 200E-series" | ||
318 | depends on (PCI || SBUS) && ATM | ||
319 | ---help--- | ||
320 | This is a driver for the FORE Systems 200E-series ATM adapter | ||
321 | cards. It simultaneously supports PCA-200E and SBA-200E models | ||
322 | on PCI and SBUS hosts. Say Y (or M to compile as a module | ||
323 | named fore_200e) here if you have one of these ATM adapters. | ||
324 | |||
325 | Note that the driver will actually be compiled only if you | ||
326 | additionally enable the support for PCA-200E and/or SBA-200E | ||
327 | cards. | ||
328 | |||
329 | See the file <file:Documentation/networking/fore200e.txt> for | ||
330 | further details. | ||
331 | |||
332 | config ATM_FORE200E_PCA | ||
333 | bool "PCA-200E support" | ||
334 | depends on ATM_FORE200E_MAYBE && PCI | ||
335 | help | ||
336 | Say Y here if you want your PCA-200E cards to be probed. | ||
337 | |||
338 | config ATM_FORE200E_PCA_DEFAULT_FW | ||
339 | bool "Use default PCA-200E firmware (normally enabled)" | ||
340 | depends on ATM_FORE200E_PCA | ||
341 | help | ||
342 | Use the default PCA-200E firmware data shipped with the driver. | ||
343 | |||
344 | Normal users do not have to deal with the firmware stuff, so | ||
345 | they should say Y here. | ||
346 | |||
347 | config ATM_FORE200E_PCA_FW | ||
348 | string "Pathname of user-supplied binary firmware" | ||
349 | depends on ATM_FORE200E_PCA && !ATM_FORE200E_PCA_DEFAULT_FW | ||
350 | default "" | ||
351 | help | ||
352 | This defines the pathname of an alternative PCA-200E binary | ||
353 | firmware image supplied by the user. This pathname may be | ||
354 | absolute or relative to the drivers/atm directory. | ||
355 | |||
356 | The driver comes with an adequate firmware image, so normal users do | ||
357 | not have to supply an alternative one. They just say Y to "Use | ||
358 | default PCA-200E firmware" instead. | ||
359 | |||
360 | config ATM_FORE200E_SBA | ||
361 | bool "SBA-200E support" | ||
362 | depends on ATM_FORE200E_MAYBE && SBUS | ||
363 | help | ||
364 | Say Y here if you want your SBA-200E cards to be probed. | ||
365 | |||
366 | config ATM_FORE200E_SBA_DEFAULT_FW | ||
367 | bool "Use default SBA-200E firmware (normally enabled)" | ||
368 | depends on ATM_FORE200E_SBA | ||
369 | help | ||
370 | Use the default SBA-200E firmware data shipped with the driver. | ||
371 | |||
372 | Normal users do not have to deal with the firmware stuff, so | ||
373 | they should say Y here. | ||
374 | |||
375 | config ATM_FORE200E_SBA_FW | ||
376 | string "Pathname of user-supplied binary firmware" | ||
377 | depends on ATM_FORE200E_SBA && !ATM_FORE200E_SBA_DEFAULT_FW | ||
378 | default "" | ||
379 | help | ||
380 | This defines the pathname of an alternative SBA-200E binary | ||
381 | firmware image supplied by the user. This pathname may be | ||
382 | absolute or relative to the drivers/atm directory. | ||
383 | |||
384 | The driver comes with an adequate firmware image, so normal users do | ||
385 | not have to supply an alternative one. They just say Y to "Use | ||
386 | default SBA-200E firmware", above. | ||
387 | |||
388 | config ATM_FORE200E_USE_TASKLET | ||
389 | bool "Defer interrupt work to a tasklet" | ||
390 | depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) | ||
391 | default n | ||
392 | help | ||
393 | This defers work to be done by the interrupt handler to a | ||
394 | tasklet instead of hanlding everything at interrupt time. This | ||
395 | may improve the responsive of the host. | ||
396 | |||
397 | config ATM_FORE200E_TX_RETRY | ||
398 | int "Maximum number of tx retries" | ||
399 | depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) | ||
400 | default "16" | ||
401 | ---help--- | ||
402 | Specifies the number of times the driver attempts to transmit | ||
403 | a message before giving up, if the transmit queue of the ATM card | ||
404 | is transiently saturated. | ||
405 | |||
406 | Saturation of the transmit queue may occur only under extreme | ||
407 | conditions, e.g. when a fast host continuously submits very small | ||
408 | frames (<64 bytes) or raw AAL0 cells (48 bytes) to the ATM adapter. | ||
409 | |||
410 | Note that under common conditions, it is unlikely that you encounter | ||
411 | a saturation of the transmit queue, so the retry mechanism never | ||
412 | comes into play. | ||
413 | |||
414 | config ATM_FORE200E_DEBUG | ||
415 | int "Debugging level (0-3)" | ||
416 | depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) | ||
417 | default "0" | ||
418 | help | ||
419 | Specifies the level of debugging messages issued by the driver. | ||
420 | The verbosity of the driver increases with the value of this | ||
421 | parameter. | ||
422 | |||
423 | When active, these messages can have a significant impact on | ||
424 | the performances of the driver, and the size of your syslog files! | ||
425 | Keep the debugging level to 0 during normal operations. | ||
426 | |||
427 | config ATM_FORE200E | ||
428 | tristate | ||
429 | depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) | ||
430 | default m if ATM_FORE200E_MAYBE!=y | ||
431 | default y if ATM_FORE200E_MAYBE=y | ||
432 | |||
433 | config ATM_HE | ||
434 | tristate "ForeRunner HE Series" | ||
435 | depends on PCI && ATM | ||
436 | help | ||
437 | This is a driver for the Marconi ForeRunner HE-series ATM adapter | ||
438 | cards. It simultaneously supports the 155 and 622 versions. | ||
439 | |||
440 | config ATM_HE_USE_SUNI | ||
441 | bool "Use S/UNI PHY driver" | ||
442 | depends on ATM_HE | ||
443 | help | ||
444 | Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner | ||
445 | HE cards. This driver provides carrier detection some statistics. | ||
446 | |||
447 | endmenu | ||
448 | |||
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile new file mode 100644 index 000000000000..d1dcd8eae3c9 --- /dev/null +++ b/drivers/atm/Makefile | |||
@@ -0,0 +1,71 @@ | |||
1 | # | ||
2 | # Makefile for the Linux network (ATM) device drivers. | ||
3 | # | ||
4 | |||
5 | fore_200e-objs := fore200e.o | ||
6 | hostprogs-y := fore200e_mkfirm | ||
7 | |||
8 | # Files generated that shall be removed upon make clean | ||
9 | clean-files := atmsar11.bin atmsar11.bin1 atmsar11.bin2 pca200e.bin \ | ||
10 | pca200e.bin1 pca200e.bin2 pca200e_ecd.bin pca200e_ecd.bin1 \ | ||
11 | pca200e_ecd.bin2 sba200e_ecd.bin sba200e_ecd.bin1 sba200e_ecd.bin2 | ||
12 | # Firmware generated that shall be removed upon make clean | ||
13 | clean-files += fore200e_pca_fw.c fore200e_sba_fw.c | ||
14 | |||
15 | obj-$(CONFIG_ATM_ZATM) += zatm.o uPD98402.o | ||
16 | obj-$(CONFIG_ATM_NICSTAR) += nicstar.o | ||
17 | obj-$(CONFIG_ATM_AMBASSADOR) += ambassador.o | ||
18 | obj-$(CONFIG_ATM_HORIZON) += horizon.o | ||
19 | obj-$(CONFIG_ATM_IA) += iphase.o suni.o | ||
20 | obj-$(CONFIG_ATM_FORE200E) += fore_200e.o | ||
21 | obj-$(CONFIG_ATM_ENI) += eni.o suni.o | ||
22 | obj-$(CONFIG_ATM_IDT77252) += idt77252.o | ||
23 | |||
24 | ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y) | ||
25 | obj-$(CONFIG_ATM_NICSTAR) += suni.o | ||
26 | endif | ||
27 | ifeq ($(CONFIG_ATM_NICSTAR_USE_IDT77105),y) | ||
28 | obj-$(CONFIG_ATM_NICSTAR) += idt77105.o | ||
29 | endif | ||
30 | ifeq ($(CONFIG_ATM_IDT77252_USE_SUNI),y) | ||
31 | obj-$(CONFIG_ATM_IDT77252) += suni.o | ||
32 | endif | ||
33 | |||
34 | obj-$(CONFIG_ATM_TCP) += atmtcp.o | ||
35 | obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o | ||
36 | obj-$(CONFIG_ATM_LANAI) += lanai.o | ||
37 | |||
38 | ifeq ($(CONFIG_ATM_FORE200E_PCA),y) | ||
39 | fore_200e-objs += fore200e_pca_fw.o | ||
40 | # guess the target endianess to choose the right PCA-200E firmware image | ||
41 | ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y) | ||
42 | CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo $(obj)/pca200e.bin; else echo $(obj)/pca200e_ecd.bin2; fi) | ||
43 | endif | ||
44 | endif | ||
45 | |||
46 | ifeq ($(CONFIG_ATM_FORE200E_SBA),y) | ||
47 | fore_200e-objs += fore200e_sba_fw.o | ||
48 | ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y) | ||
49 | CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 | ||
50 | endif | ||
51 | endif | ||
52 | obj-$(CONFIG_ATM_HE) += he.o | ||
53 | ifeq ($(CONFIG_ATM_HE_USE_SUNI),y) | ||
54 | obj-$(CONFIG_ATM_HE) += suni.o | ||
55 | endif | ||
56 | |||
57 | # FORE Systems 200E-series firmware magic | ||
58 | $(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \ | ||
59 | $(obj)/fore200e_mkfirm | ||
60 | $(obj)/fore200e_mkfirm -k -b _fore200e_pca_fw \ | ||
61 | -i $(CONFIG_ATM_FORE200E_PCA_FW) -o $@ | ||
62 | |||
63 | $(obj)/fore200e_sba_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_SBA_FW)) \ | ||
64 | $(obj)/fore200e_mkfirm | ||
65 | $(obj)/fore200e_mkfirm -k -b _fore200e_sba_fw \ | ||
66 | -i $(CONFIG_ATM_FORE200E_SBA_FW) -o $@ | ||
67 | |||
68 | # deal with the various suffixes of the binary firmware images | ||
69 | $(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(src)/%.data | ||
70 | objcopy -Iihex $< -Obinary $@.gz | ||
71 | gzip -n -df $@.gz | ||
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c new file mode 100644 index 000000000000..c46d9520c5a7 --- /dev/null +++ b/drivers/atm/ambassador.c | |||
@@ -0,0 +1,2463 @@ | |||
1 | /* | ||
2 | Madge Ambassador ATM Adapter driver. | ||
3 | Copyright (C) 1995-1999 Madge Networks Ltd. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian | ||
20 | system and in the file COPYING in the Linux kernel source. | ||
21 | */ | ||
22 | |||
23 | /* * dedicated to the memory of Graham Gordon 1971-1998 * */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/ioport.h> | ||
31 | #include <linux/atmdev.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | |||
35 | #include <asm/atomic.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <asm/byteorder.h> | ||
38 | |||
39 | #include "ambassador.h" | ||
40 | |||
41 | #define maintainer_string "Giuliano Procida at Madge Networks <gprocida@madge.com>" | ||
42 | #define description_string "Madge ATM Ambassador driver" | ||
43 | #define version_string "1.2.4" | ||
44 | |||
45 | static inline void __init show_version (void) { | ||
46 | printk ("%s version %s\n", description_string, version_string); | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | |||
51 | Theory of Operation | ||
52 | |||
53 | I Hardware, detection, initialisation and shutdown. | ||
54 | |||
55 | 1. Supported Hardware | ||
56 | |||
57 | This driver is for the PCI ATMizer-based Ambassador card (except | ||
58 | very early versions). It is not suitable for the similar EISA "TR7" | ||
59 | card. Commercially, both cards are known as Collage Server ATM | ||
60 | adapters. | ||
61 | |||
62 | The loader supports image transfer to the card, image start and few | ||
63 | other miscellaneous commands. | ||
64 | |||
65 | Only AAL5 is supported with vpi = 0 and vci in the range 0 to 1023. | ||
66 | |||
67 | The cards are big-endian. | ||
68 | |||
69 | 2. Detection | ||
70 | |||
71 | Standard PCI stuff, the early cards are detected and rejected. | ||
72 | |||
73 | 3. Initialisation | ||
74 | |||
75 | The cards are reset and the self-test results are checked. The | ||
76 | microcode image is then transferred and started. This waits for a | ||
77 | pointer to a descriptor containing details of the host-based queues | ||
78 | and buffers and various parameters etc. Once they are processed | ||
79 | normal operations may begin. The BIA is read using a microcode | ||
80 | command. | ||
81 | |||
82 | 4. Shutdown | ||
83 | |||
84 | This may be accomplished either by a card reset or via the microcode | ||
85 | shutdown command. Further investigation required. | ||
86 | |||
87 | 5. Persistent state | ||
88 | |||
89 | The card reset does not affect PCI configuration (good) or the | ||
90 | contents of several other "shared run-time registers" (bad) which | ||
91 | include doorbell and interrupt control as well as EEPROM and PCI | ||
92 | control. The driver must be careful when modifying these registers | ||
93 | not to touch bits it does not use and to undo any changes at exit. | ||
94 | |||
95 | II Driver software | ||
96 | |||
97 | 0. Generalities | ||
98 | |||
99 | The adapter is quite intelligent (fast) and has a simple interface | ||
100 | (few features). VPI is always zero, 1024 VCIs are supported. There | ||
101 | is limited cell rate support. UBR channels can be capped and ABR | ||
102 | (explicit rate, but not EFCI) is supported. There is no CBR or VBR | ||
103 | support. | ||
104 | |||
105 | 1. Driver <-> Adapter Communication | ||
106 | |||
107 | Apart from the basic loader commands, the driver communicates | ||
108 | through three entities: the command queue (CQ), the transmit queue | ||
109 | pair (TXQ) and the receive queue pairs (RXQ). These three entities | ||
110 | are set up by the host and passed to the microcode just after it has | ||
111 | been started. | ||
112 | |||
113 | All queues are host-based circular queues. They are contiguous and | ||
114 | (due to hardware limitations) have some restrictions as to their | ||
115 | locations in (bus) memory. They are of the "full means the same as | ||
116 | empty so don't do that" variety since the adapter uses pointers | ||
117 | internally. | ||
118 | |||
119 | The queue pairs work as follows: one queue is for supply to the | ||
120 | adapter, items in it are pending and are owned by the adapter; the | ||
121 | other is the queue for return from the adapter, items in it have | ||
122 | been dealt with by the adapter. The host adds items to the supply | ||
123 | (TX descriptors and free RX buffer descriptors) and removes items | ||
124 | from the return (TX and RX completions). The adapter deals with out | ||
125 | of order completions. | ||
126 | |||
127 | Interrupts (card to host) and the doorbell (host to card) are used | ||
128 | for signalling. | ||
129 | |||
130 | 1. CQ | ||
131 | |||
132 | This is to communicate "open VC", "close VC", "get stats" etc. to | ||
133 | the adapter. At most one command is retired every millisecond by the | ||
134 | card. There is no out of order completion or notification. The | ||
135 | driver needs to check the return code of the command, waiting as | ||
136 | appropriate. | ||
137 | |||
138 | 2. TXQ | ||
139 | |||
140 | TX supply items are of variable length (scatter gather support) and | ||
141 | so the queue items are (more or less) pointers to the real thing. | ||
142 | Each TX supply item contains a unique, host-supplied handle (the skb | ||
143 | bus address seems most sensible as this works for Alphas as well, | ||
144 | there is no need to do any endian conversions on the handles). | ||
145 | |||
146 | TX return items consist of just the handles above. | ||
147 | |||
148 | 3. RXQ (up to 4 of these with different lengths and buffer sizes) | ||
149 | |||
150 | RX supply items consist of a unique, host-supplied handle (the skb | ||
151 | bus address again) and a pointer to the buffer data area. | ||
152 | |||
153 | RX return items consist of the handle above, the VC, length and a | ||
154 | status word. This just screams "oh so easy" doesn't it? | ||
155 | |||
156 | Note on RX pool sizes: | ||
157 | |||
158 | Each pool should have enough buffers to handle a back-to-back stream | ||
159 | of minimum sized frames on a single VC. For example: | ||
160 | |||
161 | frame spacing = 3us (about right) | ||
162 | |||
163 | delay = IRQ lat + RX handling + RX buffer replenish = 20 (us) (a guess) | ||
164 | |||
165 | min number of buffers for one VC = 1 + delay/spacing (buffers) | ||
166 | |||
167 | delay/spacing = latency = (20+2)/3 = 7 (buffers) (rounding up) | ||
168 | |||
169 | The 20us delay assumes that there is no need to sleep; if we need to | ||
170 | sleep to get buffers we are going to drop frames anyway. | ||
171 | |||
172 | In fact, each pool should have enough buffers to support the | ||
173 | simultaneous reassembly of a separate frame on each VC and cope with | ||
174 | the case in which frames complete in round robin cell fashion on | ||
175 | each VC. | ||
176 | |||
177 | Only one frame can complete at each cell arrival, so if "n" VCs are | ||
178 | open, the worst case is to have them all complete frames together | ||
179 | followed by all starting new frames together. | ||
180 | |||
181 | desired number of buffers = n + delay/spacing | ||
182 | |||
183 | These are the extreme requirements, however, they are "n+k" for some | ||
184 | "k" so we have only the constant to choose. This is the argument | ||
185 | rx_lats which current defaults to 7. | ||
186 | |||
187 | Actually, "n ? n+k : 0" is better and this is what is implemented, | ||
188 | subject to the limit given by the pool size. | ||
189 | |||
190 | 4. Driver locking | ||
191 | |||
192 | Simple spinlocks are used around the TX and RX queue mechanisms. | ||
193 | Anyone with a faster, working method is welcome to implement it. | ||
194 | |||
195 | The adapter command queue is protected with a spinlock. We always | ||
196 | wait for commands to complete. | ||
197 | |||
198 | A more complex form of locking is used around parts of the VC open | ||
199 | and close functions. There are three reasons for a lock: 1. we need | ||
200 | to do atomic rate reservation and release (not used yet), 2. Opening | ||
201 | sometimes involves two adapter commands which must not be separated | ||
202 | by another command on the same VC, 3. the changes to RX pool size | ||
203 | must be atomic. The lock needs to work over context switches, so we | ||
204 | use a semaphore. | ||
205 | |||
206 | III Hardware Features and Microcode Bugs | ||
207 | |||
208 | 1. Byte Ordering | ||
209 | |||
210 | *%^"$&%^$*&^"$(%^$#&^%$(&#%$*(&^#%!"!"!*! | ||
211 | |||
212 | 2. Memory access | ||
213 | |||
214 | All structures that are not accessed using DMA must be 4-byte | ||
215 | aligned (not a problem) and must not cross 4MB boundaries. | ||
216 | |||
217 | There is a DMA memory hole at E0000000-E00000FF (groan). | ||
218 | |||
219 | TX fragments (DMA read) must not cross 4MB boundaries (would be 16MB | ||
220 | but for a hardware bug). | ||
221 | |||
222 | RX buffers (DMA write) must not cross 16MB boundaries and must | ||
223 | include spare trailing bytes up to the next 4-byte boundary; they | ||
224 | will be written with rubbish. | ||
225 | |||
226 | The PLX likes to prefetch; if reading up to 4 u32 past the end of | ||
227 | each TX fragment is not a problem, then TX can be made to go a | ||
228 | little faster by passing a flag at init that disables a prefetch | ||
229 | workaround. We do not pass this flag. (new microcode only) | ||
230 | |||
231 | Now we: | ||
232 | . Note that alloc_skb rounds up size to a 16byte boundary. | ||
233 | . Ensure all areas do not traverse 4MB boundaries. | ||
234 | . Ensure all areas do not start at a E00000xx bus address. | ||
235 | (I cannot be certain, but this may always hold with Linux) | ||
236 | . Make all failures cause a loud message. | ||
237 | . Discard non-conforming SKBs (causes TX failure or RX fill delay). | ||
238 | . Discard non-conforming TX fragment descriptors (the TX fails). | ||
239 | In the future we could: | ||
240 | . Allow RX areas that traverse 4MB (but not 16MB) boundaries. | ||
241 | . Segment TX areas into some/more fragments, when necessary. | ||
242 | . Relax checks for non-DMA items (ignore hole). | ||
243 | . Give scatter-gather (iovec) requirements using ???. (?) | ||
244 | |||
245 | 3. VC close is broken (only for new microcode) | ||
246 | |||
247 | The VC close adapter microcode command fails to do anything if any | ||
248 | frames have been received on the VC but none have been transmitted. | ||
249 | Frames continue to be reassembled and passed (with IRQ) to the | ||
250 | driver. | ||
251 | |||
252 | IV To Do List | ||
253 | |||
254 | . Fix bugs! | ||
255 | |||
256 | . Timer code may be broken. | ||
257 | |||
258 | . Deal with buggy VC close (somehow) in microcode 12. | ||
259 | |||
260 | . Handle interrupted and/or non-blocking writes - is this a job for | ||
261 | the protocol layer? | ||
262 | |||
263 | . Add code to break up TX fragments when they span 4MB boundaries. | ||
264 | |||
265 | . Add SUNI phy layer (need to know where SUNI lives on card). | ||
266 | |||
267 | . Implement a tx_alloc fn to (a) satisfy TX alignment etc. and (b) | ||
268 | leave extra headroom space for Ambassador TX descriptors. | ||
269 | |||
270 | . Understand these elements of struct atm_vcc: recvq (proto?), | ||
271 | sleep, callback, listenq, backlog_quota, reply and user_back. | ||
272 | |||
273 | . Adjust TX/RX skb allocation to favour IP with LANE/CLIP (configurable). | ||
274 | |||
275 | . Impose a TX-pending limit (2?) on each VC, help avoid TX q overflow. | ||
276 | |||
277 | . Decide whether RX buffer recycling is or can be made completely safe; | ||
278 | turn it back on. It looks like Werner is going to axe this. | ||
279 | |||
280 | . Implement QoS changes on open VCs (involves extracting parts of VC open | ||
281 | and close into separate functions and using them to make changes). | ||
282 | |||
283 | . Hack on command queue so that someone can issue multiple commands and wait | ||
284 | on the last one (OR only "no-op" or "wait" commands are waited for). | ||
285 | |||
286 | . Eliminate need for while-schedule around do_command. | ||
287 | |||
288 | */ | ||
289 | |||
290 | /********** microcode **********/ | ||
291 | |||
292 | #ifdef AMB_NEW_MICROCODE | ||
293 | #define UCODE(x) UCODE2(atmsar12.x) | ||
294 | #else | ||
295 | #define UCODE(x) UCODE2(atmsar11.x) | ||
296 | #endif | ||
297 | #define UCODE2(x) #x | ||
298 | |||
299 | static u32 __devinitdata ucode_start = | ||
300 | #include UCODE(start) | ||
301 | ; | ||
302 | |||
303 | static region __devinitdata ucode_regions[] = { | ||
304 | #include UCODE(regions) | ||
305 | { 0, 0 } | ||
306 | }; | ||
307 | |||
308 | static u32 __devinitdata ucode_data[] = { | ||
309 | #include UCODE(data) | ||
310 | 0xdeadbeef | ||
311 | }; | ||
312 | |||
313 | static void do_housekeeping (unsigned long arg); | ||
314 | /********** globals **********/ | ||
315 | |||
316 | static unsigned short debug = 0; | ||
317 | static unsigned int cmds = 8; | ||
318 | static unsigned int txs = 32; | ||
319 | static unsigned int rxs[NUM_RX_POOLS] = { 64, 64, 64, 64 }; | ||
320 | static unsigned int rxs_bs[NUM_RX_POOLS] = { 4080, 12240, 36720, 65535 }; | ||
321 | static unsigned int rx_lats = 7; | ||
322 | static unsigned char pci_lat = 0; | ||
323 | |||
324 | static const unsigned long onegigmask = -1 << 30; | ||
325 | |||
326 | /********** access to adapter **********/ | ||
327 | |||
328 | static inline void wr_plain (const amb_dev * dev, size_t addr, u32 data) { | ||
329 | PRINTD (DBG_FLOW|DBG_REGS, "wr: %08zx <- %08x", addr, data); | ||
330 | #ifdef AMB_MMIO | ||
331 | dev->membase[addr / sizeof(u32)] = data; | ||
332 | #else | ||
333 | outl (data, dev->iobase + addr); | ||
334 | #endif | ||
335 | } | ||
336 | |||
337 | static inline u32 rd_plain (const amb_dev * dev, size_t addr) { | ||
338 | #ifdef AMB_MMIO | ||
339 | u32 data = dev->membase[addr / sizeof(u32)]; | ||
340 | #else | ||
341 | u32 data = inl (dev->iobase + addr); | ||
342 | #endif | ||
343 | PRINTD (DBG_FLOW|DBG_REGS, "rd: %08zx -> %08x", addr, data); | ||
344 | return data; | ||
345 | } | ||
346 | |||
347 | static inline void wr_mem (const amb_dev * dev, size_t addr, u32 data) { | ||
348 | __be32 be = cpu_to_be32 (data); | ||
349 | PRINTD (DBG_FLOW|DBG_REGS, "wr: %08zx <- %08x b[%08x]", addr, data, be); | ||
350 | #ifdef AMB_MMIO | ||
351 | dev->membase[addr / sizeof(u32)] = be; | ||
352 | #else | ||
353 | outl (be, dev->iobase + addr); | ||
354 | #endif | ||
355 | } | ||
356 | |||
357 | static inline u32 rd_mem (const amb_dev * dev, size_t addr) { | ||
358 | #ifdef AMB_MMIO | ||
359 | __be32 be = dev->membase[addr / sizeof(u32)]; | ||
360 | #else | ||
361 | __be32 be = inl (dev->iobase + addr); | ||
362 | #endif | ||
363 | u32 data = be32_to_cpu (be); | ||
364 | PRINTD (DBG_FLOW|DBG_REGS, "rd: %08zx -> %08x b[%08x]", addr, data, be); | ||
365 | return data; | ||
366 | } | ||
367 | |||
368 | /********** dump routines **********/ | ||
369 | |||
370 | static inline void dump_registers (const amb_dev * dev) { | ||
371 | #ifdef DEBUG_AMBASSADOR | ||
372 | if (debug & DBG_REGS) { | ||
373 | size_t i; | ||
374 | PRINTD (DBG_REGS, "reading PLX control: "); | ||
375 | for (i = 0x00; i < 0x30; i += sizeof(u32)) | ||
376 | rd_mem (dev, i); | ||
377 | PRINTD (DBG_REGS, "reading mailboxes: "); | ||
378 | for (i = 0x40; i < 0x60; i += sizeof(u32)) | ||
379 | rd_mem (dev, i); | ||
380 | PRINTD (DBG_REGS, "reading doorb irqev irqen reset:"); | ||
381 | for (i = 0x60; i < 0x70; i += sizeof(u32)) | ||
382 | rd_mem (dev, i); | ||
383 | } | ||
384 | #else | ||
385 | (void) dev; | ||
386 | #endif | ||
387 | return; | ||
388 | } | ||
389 | |||
390 | static inline void dump_loader_block (volatile loader_block * lb) { | ||
391 | #ifdef DEBUG_AMBASSADOR | ||
392 | unsigned int i; | ||
393 | PRINTDB (DBG_LOAD, "lb @ %p; res: %d, cmd: %d, pay:", | ||
394 | lb, be32_to_cpu (lb->result), be32_to_cpu (lb->command)); | ||
395 | for (i = 0; i < MAX_COMMAND_DATA; ++i) | ||
396 | PRINTDM (DBG_LOAD, " %08x", be32_to_cpu (lb->payload.data[i])); | ||
397 | PRINTDE (DBG_LOAD, ", vld: %08x", be32_to_cpu (lb->valid)); | ||
398 | #else | ||
399 | (void) lb; | ||
400 | #endif | ||
401 | return; | ||
402 | } | ||
403 | |||
404 | static inline void dump_command (command * cmd) { | ||
405 | #ifdef DEBUG_AMBASSADOR | ||
406 | unsigned int i; | ||
407 | PRINTDB (DBG_CMD, "cmd @ %p, req: %08x, pars:", | ||
408 | cmd, /*be32_to_cpu*/ (cmd->request)); | ||
409 | for (i = 0; i < 3; ++i) | ||
410 | PRINTDM (DBG_CMD, " %08x", /*be32_to_cpu*/ (cmd->args.par[i])); | ||
411 | PRINTDE (DBG_CMD, ""); | ||
412 | #else | ||
413 | (void) cmd; | ||
414 | #endif | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | static inline void dump_skb (char * prefix, unsigned int vc, struct sk_buff * skb) { | ||
419 | #ifdef DEBUG_AMBASSADOR | ||
420 | unsigned int i; | ||
421 | unsigned char * data = skb->data; | ||
422 | PRINTDB (DBG_DATA, "%s(%u) ", prefix, vc); | ||
423 | for (i=0; i<skb->len && i < 256;i++) | ||
424 | PRINTDM (DBG_DATA, "%02x ", data[i]); | ||
425 | PRINTDE (DBG_DATA,""); | ||
426 | #else | ||
427 | (void) prefix; | ||
428 | (void) vc; | ||
429 | (void) skb; | ||
430 | #endif | ||
431 | return; | ||
432 | } | ||
433 | |||
434 | /********** check memory areas for use by Ambassador **********/ | ||
435 | |||
436 | /* see limitations under Hardware Features */ | ||
437 | |||
438 | static inline int check_area (void * start, size_t length) { | ||
439 | // assumes length > 0 | ||
440 | const u32 fourmegmask = -1 << 22; | ||
441 | const u32 twofivesixmask = -1 << 8; | ||
442 | const u32 starthole = 0xE0000000; | ||
443 | u32 startaddress = virt_to_bus (start); | ||
444 | u32 lastaddress = startaddress+length-1; | ||
445 | if ((startaddress ^ lastaddress) & fourmegmask || | ||
446 | (startaddress & twofivesixmask) == starthole) { | ||
447 | PRINTK (KERN_ERR, "check_area failure: [%x,%x] - mail maintainer!", | ||
448 | startaddress, lastaddress); | ||
449 | return -1; | ||
450 | } else { | ||
451 | return 0; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | /********** free an skb (as per ATM device driver documentation) **********/ | ||
456 | |||
457 | static inline void amb_kfree_skb (struct sk_buff * skb) { | ||
458 | if (ATM_SKB(skb)->vcc->pop) { | ||
459 | ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb); | ||
460 | } else { | ||
461 | dev_kfree_skb_any (skb); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | /********** TX completion **********/ | ||
466 | |||
467 | static inline void tx_complete (amb_dev * dev, tx_out * tx) { | ||
468 | tx_simple * tx_descr = bus_to_virt (tx->handle); | ||
469 | struct sk_buff * skb = tx_descr->skb; | ||
470 | |||
471 | PRINTD (DBG_FLOW|DBG_TX, "tx_complete %p %p", dev, tx); | ||
472 | |||
473 | // VC layer stats | ||
474 | atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); | ||
475 | |||
476 | // free the descriptor | ||
477 | kfree (tx_descr); | ||
478 | |||
479 | // free the skb | ||
480 | amb_kfree_skb (skb); | ||
481 | |||
482 | dev->stats.tx_ok++; | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | /********** RX completion **********/ | ||
487 | |||
488 | static void rx_complete (amb_dev * dev, rx_out * rx) { | ||
489 | struct sk_buff * skb = bus_to_virt (rx->handle); | ||
490 | u16 vc = be16_to_cpu (rx->vc); | ||
491 | // unused: u16 lec_id = be16_to_cpu (rx->lec_id); | ||
492 | u16 status = be16_to_cpu (rx->status); | ||
493 | u16 rx_len = be16_to_cpu (rx->length); | ||
494 | |||
495 | PRINTD (DBG_FLOW|DBG_RX, "rx_complete %p %p (len=%hu)", dev, rx, rx_len); | ||
496 | |||
497 | // XXX move this in and add to VC stats ??? | ||
498 | if (!status) { | ||
499 | struct atm_vcc * atm_vcc = dev->rxer[vc]; | ||
500 | dev->stats.rx.ok++; | ||
501 | |||
502 | if (atm_vcc) { | ||
503 | |||
504 | if (rx_len <= atm_vcc->qos.rxtp.max_sdu) { | ||
505 | |||
506 | if (atm_charge (atm_vcc, skb->truesize)) { | ||
507 | |||
508 | // prepare socket buffer | ||
509 | ATM_SKB(skb)->vcc = atm_vcc; | ||
510 | skb_put (skb, rx_len); | ||
511 | |||
512 | dump_skb ("<<<", vc, skb); | ||
513 | |||
514 | // VC layer stats | ||
515 | atomic_inc(&atm_vcc->stats->rx); | ||
516 | do_gettimeofday(&skb->stamp); | ||
517 | // end of our responsability | ||
518 | atm_vcc->push (atm_vcc, skb); | ||
519 | return; | ||
520 | |||
521 | } else { | ||
522 | // someone fix this (message), please! | ||
523 | PRINTD (DBG_INFO|DBG_RX, "dropped thanks to atm_charge (vc %hu, truesize %u)", vc, skb->truesize); | ||
524 | // drop stats incremented in atm_charge | ||
525 | } | ||
526 | |||
527 | } else { | ||
528 | PRINTK (KERN_INFO, "dropped over-size frame"); | ||
529 | // should we count this? | ||
530 | atomic_inc(&atm_vcc->stats->rx_drop); | ||
531 | } | ||
532 | |||
533 | } else { | ||
534 | PRINTD (DBG_WARN|DBG_RX, "got frame but RX closed for channel %hu", vc); | ||
535 | // this is an adapter bug, only in new version of microcode | ||
536 | } | ||
537 | |||
538 | } else { | ||
539 | dev->stats.rx.error++; | ||
540 | if (status & CRC_ERR) | ||
541 | dev->stats.rx.badcrc++; | ||
542 | if (status & LEN_ERR) | ||
543 | dev->stats.rx.toolong++; | ||
544 | if (status & ABORT_ERR) | ||
545 | dev->stats.rx.aborted++; | ||
546 | if (status & UNUSED_ERR) | ||
547 | dev->stats.rx.unused++; | ||
548 | } | ||
549 | |||
550 | dev_kfree_skb_any (skb); | ||
551 | return; | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | |||
556 | Note on queue handling. | ||
557 | |||
558 | Here "give" and "take" refer to queue entries and a queue (pair) | ||
559 | rather than frames to or from the host or adapter. Empty frame | ||
560 | buffers are given to the RX queue pair and returned unused or | ||
561 | containing RX frames. TX frames (well, pointers to TX fragment | ||
562 | lists) are given to the TX queue pair, completions are returned. | ||
563 | |||
564 | */ | ||
565 | |||
566 | /********** command queue **********/ | ||
567 | |||
568 | // I really don't like this, but it's the best I can do at the moment | ||
569 | |||
570 | // also, the callers are responsible for byte order as the microcode | ||
571 | // sometimes does 16-bit accesses (yuk yuk yuk) | ||
572 | |||
573 | static int command_do (amb_dev * dev, command * cmd) { | ||
574 | amb_cq * cq = &dev->cq; | ||
575 | volatile amb_cq_ptrs * ptrs = &cq->ptrs; | ||
576 | command * my_slot; | ||
577 | |||
578 | PRINTD (DBG_FLOW|DBG_CMD, "command_do %p", dev); | ||
579 | |||
580 | if (test_bit (dead, &dev->flags)) | ||
581 | return 0; | ||
582 | |||
583 | spin_lock (&cq->lock); | ||
584 | |||
585 | // if not full... | ||
586 | if (cq->pending < cq->maximum) { | ||
587 | // remember my slot for later | ||
588 | my_slot = ptrs->in; | ||
589 | PRINTD (DBG_CMD, "command in slot %p", my_slot); | ||
590 | |||
591 | dump_command (cmd); | ||
592 | |||
593 | // copy command in | ||
594 | *ptrs->in = *cmd; | ||
595 | cq->pending++; | ||
596 | ptrs->in = NEXTQ (ptrs->in, ptrs->start, ptrs->limit); | ||
597 | |||
598 | // mail the command | ||
599 | wr_mem (dev, offsetof(amb_mem, mb.adapter.cmd_address), virt_to_bus (ptrs->in)); | ||
600 | |||
601 | if (cq->pending > cq->high) | ||
602 | cq->high = cq->pending; | ||
603 | spin_unlock (&cq->lock); | ||
604 | |||
605 | // these comments were in a while-loop before, msleep removes the loop | ||
606 | // go to sleep | ||
607 | // PRINTD (DBG_CMD, "wait: sleeping %lu for command", timeout); | ||
608 | msleep(cq->pending); | ||
609 | |||
610 | // wait for my slot to be reached (all waiters are here or above, until...) | ||
611 | while (ptrs->out != my_slot) { | ||
612 | PRINTD (DBG_CMD, "wait: command slot (now at %p)", ptrs->out); | ||
613 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
614 | schedule(); | ||
615 | } | ||
616 | |||
617 | // wait on my slot (... one gets to its slot, and... ) | ||
618 | while (ptrs->out->request != cpu_to_be32 (SRB_COMPLETE)) { | ||
619 | PRINTD (DBG_CMD, "wait: command slot completion"); | ||
620 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
621 | schedule(); | ||
622 | } | ||
623 | |||
624 | PRINTD (DBG_CMD, "command complete"); | ||
625 | // update queue (... moves the queue along to the next slot) | ||
626 | spin_lock (&cq->lock); | ||
627 | cq->pending--; | ||
628 | // copy command out | ||
629 | *cmd = *ptrs->out; | ||
630 | ptrs->out = NEXTQ (ptrs->out, ptrs->start, ptrs->limit); | ||
631 | spin_unlock (&cq->lock); | ||
632 | |||
633 | return 0; | ||
634 | } else { | ||
635 | cq->filled++; | ||
636 | spin_unlock (&cq->lock); | ||
637 | return -EAGAIN; | ||
638 | } | ||
639 | |||
640 | } | ||
641 | |||
642 | /********** TX queue pair **********/ | ||
643 | |||
644 | static inline int tx_give (amb_dev * dev, tx_in * tx) { | ||
645 | amb_txq * txq = &dev->txq; | ||
646 | unsigned long flags; | ||
647 | |||
648 | PRINTD (DBG_FLOW|DBG_TX, "tx_give %p", dev); | ||
649 | |||
650 | if (test_bit (dead, &dev->flags)) | ||
651 | return 0; | ||
652 | |||
653 | spin_lock_irqsave (&txq->lock, flags); | ||
654 | |||
655 | if (txq->pending < txq->maximum) { | ||
656 | PRINTD (DBG_TX, "TX in slot %p", txq->in.ptr); | ||
657 | |||
658 | *txq->in.ptr = *tx; | ||
659 | txq->pending++; | ||
660 | txq->in.ptr = NEXTQ (txq->in.ptr, txq->in.start, txq->in.limit); | ||
661 | // hand over the TX and ring the bell | ||
662 | wr_mem (dev, offsetof(amb_mem, mb.adapter.tx_address), virt_to_bus (txq->in.ptr)); | ||
663 | wr_mem (dev, offsetof(amb_mem, doorbell), TX_FRAME); | ||
664 | |||
665 | if (txq->pending > txq->high) | ||
666 | txq->high = txq->pending; | ||
667 | spin_unlock_irqrestore (&txq->lock, flags); | ||
668 | return 0; | ||
669 | } else { | ||
670 | txq->filled++; | ||
671 | spin_unlock_irqrestore (&txq->lock, flags); | ||
672 | return -EAGAIN; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | static inline int tx_take (amb_dev * dev) { | ||
677 | amb_txq * txq = &dev->txq; | ||
678 | unsigned long flags; | ||
679 | |||
680 | PRINTD (DBG_FLOW|DBG_TX, "tx_take %p", dev); | ||
681 | |||
682 | spin_lock_irqsave (&txq->lock, flags); | ||
683 | |||
684 | if (txq->pending && txq->out.ptr->handle) { | ||
685 | // deal with TX completion | ||
686 | tx_complete (dev, txq->out.ptr); | ||
687 | // mark unused again | ||
688 | txq->out.ptr->handle = 0; | ||
689 | // remove item | ||
690 | txq->pending--; | ||
691 | txq->out.ptr = NEXTQ (txq->out.ptr, txq->out.start, txq->out.limit); | ||
692 | |||
693 | spin_unlock_irqrestore (&txq->lock, flags); | ||
694 | return 0; | ||
695 | } else { | ||
696 | |||
697 | spin_unlock_irqrestore (&txq->lock, flags); | ||
698 | return -1; | ||
699 | } | ||
700 | } | ||
701 | |||
702 | /********** RX queue pairs **********/ | ||
703 | |||
704 | static inline int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) { | ||
705 | amb_rxq * rxq = &dev->rxq[pool]; | ||
706 | unsigned long flags; | ||
707 | |||
708 | PRINTD (DBG_FLOW|DBG_RX, "rx_give %p[%hu]", dev, pool); | ||
709 | |||
710 | spin_lock_irqsave (&rxq->lock, flags); | ||
711 | |||
712 | if (rxq->pending < rxq->maximum) { | ||
713 | PRINTD (DBG_RX, "RX in slot %p", rxq->in.ptr); | ||
714 | |||
715 | *rxq->in.ptr = *rx; | ||
716 | rxq->pending++; | ||
717 | rxq->in.ptr = NEXTQ (rxq->in.ptr, rxq->in.start, rxq->in.limit); | ||
718 | // hand over the RX buffer | ||
719 | wr_mem (dev, offsetof(amb_mem, mb.adapter.rx_address[pool]), virt_to_bus (rxq->in.ptr)); | ||
720 | |||
721 | spin_unlock_irqrestore (&rxq->lock, flags); | ||
722 | return 0; | ||
723 | } else { | ||
724 | spin_unlock_irqrestore (&rxq->lock, flags); | ||
725 | return -1; | ||
726 | } | ||
727 | } | ||
728 | |||
729 | static inline int rx_take (amb_dev * dev, unsigned char pool) { | ||
730 | amb_rxq * rxq = &dev->rxq[pool]; | ||
731 | unsigned long flags; | ||
732 | |||
733 | PRINTD (DBG_FLOW|DBG_RX, "rx_take %p[%hu]", dev, pool); | ||
734 | |||
735 | spin_lock_irqsave (&rxq->lock, flags); | ||
736 | |||
737 | if (rxq->pending && (rxq->out.ptr->status || rxq->out.ptr->length)) { | ||
738 | // deal with RX completion | ||
739 | rx_complete (dev, rxq->out.ptr); | ||
740 | // mark unused again | ||
741 | rxq->out.ptr->status = 0; | ||
742 | rxq->out.ptr->length = 0; | ||
743 | // remove item | ||
744 | rxq->pending--; | ||
745 | rxq->out.ptr = NEXTQ (rxq->out.ptr, rxq->out.start, rxq->out.limit); | ||
746 | |||
747 | if (rxq->pending < rxq->low) | ||
748 | rxq->low = rxq->pending; | ||
749 | spin_unlock_irqrestore (&rxq->lock, flags); | ||
750 | return 0; | ||
751 | } else { | ||
752 | if (!rxq->pending && rxq->buffers_wanted) | ||
753 | rxq->emptied++; | ||
754 | spin_unlock_irqrestore (&rxq->lock, flags); | ||
755 | return -1; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | /********** RX Pool handling **********/ | ||
760 | |||
761 | /* pre: buffers_wanted = 0, post: pending = 0 */ | ||
762 | static inline void drain_rx_pool (amb_dev * dev, unsigned char pool) { | ||
763 | amb_rxq * rxq = &dev->rxq[pool]; | ||
764 | |||
765 | PRINTD (DBG_FLOW|DBG_POOL, "drain_rx_pool %p %hu", dev, pool); | ||
766 | |||
767 | if (test_bit (dead, &dev->flags)) | ||
768 | return; | ||
769 | |||
770 | /* we are not quite like the fill pool routines as we cannot just | ||
771 | remove one buffer, we have to remove all of them, but we might as | ||
772 | well pretend... */ | ||
773 | if (rxq->pending > rxq->buffers_wanted) { | ||
774 | command cmd; | ||
775 | cmd.request = cpu_to_be32 (SRB_FLUSH_BUFFER_Q); | ||
776 | cmd.args.flush.flags = cpu_to_be32 (pool << SRB_POOL_SHIFT); | ||
777 | while (command_do (dev, &cmd)) | ||
778 | schedule(); | ||
779 | /* the pool may also be emptied via the interrupt handler */ | ||
780 | while (rxq->pending > rxq->buffers_wanted) | ||
781 | if (rx_take (dev, pool)) | ||
782 | schedule(); | ||
783 | } | ||
784 | |||
785 | return; | ||
786 | } | ||
787 | |||
788 | static void drain_rx_pools (amb_dev * dev) { | ||
789 | unsigned char pool; | ||
790 | |||
791 | PRINTD (DBG_FLOW|DBG_POOL, "drain_rx_pools %p", dev); | ||
792 | |||
793 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
794 | drain_rx_pool (dev, pool); | ||
795 | } | ||
796 | |||
797 | static inline void fill_rx_pool (amb_dev * dev, unsigned char pool, int priority) { | ||
798 | rx_in rx; | ||
799 | amb_rxq * rxq; | ||
800 | |||
801 | PRINTD (DBG_FLOW|DBG_POOL, "fill_rx_pool %p %hu %x", dev, pool, priority); | ||
802 | |||
803 | if (test_bit (dead, &dev->flags)) | ||
804 | return; | ||
805 | |||
806 | rxq = &dev->rxq[pool]; | ||
807 | while (rxq->pending < rxq->maximum && rxq->pending < rxq->buffers_wanted) { | ||
808 | |||
809 | struct sk_buff * skb = alloc_skb (rxq->buffer_size, priority); | ||
810 | if (!skb) { | ||
811 | PRINTD (DBG_SKB|DBG_POOL, "failed to allocate skb for RX pool %hu", pool); | ||
812 | return; | ||
813 | } | ||
814 | if (check_area (skb->data, skb->truesize)) { | ||
815 | dev_kfree_skb_any (skb); | ||
816 | return; | ||
817 | } | ||
818 | // cast needed as there is no %? for pointer differences | ||
819 | PRINTD (DBG_SKB, "allocated skb at %p, head %p, area %li", | ||
820 | skb, skb->head, (long) (skb->end - skb->head)); | ||
821 | rx.handle = virt_to_bus (skb); | ||
822 | rx.host_address = cpu_to_be32 (virt_to_bus (skb->data)); | ||
823 | if (rx_give (dev, &rx, pool)) | ||
824 | dev_kfree_skb_any (skb); | ||
825 | |||
826 | } | ||
827 | |||
828 | return; | ||
829 | } | ||
830 | |||
831 | // top up all RX pools (can also be called as a bottom half) | ||
832 | static void fill_rx_pools (amb_dev * dev) { | ||
833 | unsigned char pool; | ||
834 | |||
835 | PRINTD (DBG_FLOW|DBG_POOL, "fill_rx_pools %p", dev); | ||
836 | |||
837 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
838 | fill_rx_pool (dev, pool, GFP_ATOMIC); | ||
839 | |||
840 | return; | ||
841 | } | ||
842 | |||
843 | /********** enable host interrupts **********/ | ||
844 | |||
845 | static inline void interrupts_on (amb_dev * dev) { | ||
846 | wr_plain (dev, offsetof(amb_mem, interrupt_control), | ||
847 | rd_plain (dev, offsetof(amb_mem, interrupt_control)) | ||
848 | | AMB_INTERRUPT_BITS); | ||
849 | } | ||
850 | |||
851 | /********** disable host interrupts **********/ | ||
852 | |||
853 | static inline void interrupts_off (amb_dev * dev) { | ||
854 | wr_plain (dev, offsetof(amb_mem, interrupt_control), | ||
855 | rd_plain (dev, offsetof(amb_mem, interrupt_control)) | ||
856 | &~ AMB_INTERRUPT_BITS); | ||
857 | } | ||
858 | |||
859 | /********** interrupt handling **********/ | ||
860 | |||
861 | static irqreturn_t interrupt_handler(int irq, void *dev_id, | ||
862 | struct pt_regs *pt_regs) { | ||
863 | amb_dev * dev = (amb_dev *) dev_id; | ||
864 | (void) pt_regs; | ||
865 | |||
866 | PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler: %p", dev_id); | ||
867 | |||
868 | if (!dev_id) { | ||
869 | PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq); | ||
870 | return IRQ_NONE; | ||
871 | } | ||
872 | |||
873 | { | ||
874 | u32 interrupt = rd_plain (dev, offsetof(amb_mem, interrupt)); | ||
875 | |||
876 | // for us or someone else sharing the same interrupt | ||
877 | if (!interrupt) { | ||
878 | PRINTD (DBG_IRQ, "irq not for me: %d", irq); | ||
879 | return IRQ_NONE; | ||
880 | } | ||
881 | |||
882 | // definitely for us | ||
883 | PRINTD (DBG_IRQ, "FYI: interrupt was %08x", interrupt); | ||
884 | wr_plain (dev, offsetof(amb_mem, interrupt), -1); | ||
885 | } | ||
886 | |||
887 | { | ||
888 | unsigned int irq_work = 0; | ||
889 | unsigned char pool; | ||
890 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
891 | while (!rx_take (dev, pool)) | ||
892 | ++irq_work; | ||
893 | while (!tx_take (dev)) | ||
894 | ++irq_work; | ||
895 | |||
896 | if (irq_work) { | ||
897 | #ifdef FILL_RX_POOLS_IN_BH | ||
898 | schedule_work (&dev->bh); | ||
899 | #else | ||
900 | fill_rx_pools (dev); | ||
901 | #endif | ||
902 | |||
903 | PRINTD (DBG_IRQ, "work done: %u", irq_work); | ||
904 | } else { | ||
905 | PRINTD (DBG_IRQ|DBG_WARN, "no work done"); | ||
906 | } | ||
907 | } | ||
908 | |||
909 | PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler done: %p", dev_id); | ||
910 | return IRQ_HANDLED; | ||
911 | } | ||
912 | |||
913 | /********** make rate (not quite as much fun as Horizon) **********/ | ||
914 | |||
915 | static unsigned int make_rate (unsigned int rate, rounding r, | ||
916 | u16 * bits, unsigned int * actual) { | ||
917 | unsigned char exp = -1; // hush gcc | ||
918 | unsigned int man = -1; // hush gcc | ||
919 | |||
920 | PRINTD (DBG_FLOW|DBG_QOS, "make_rate %u", rate); | ||
921 | |||
922 | // rates in cells per second, ITU format (nasty 16-bit floating-point) | ||
923 | // given 5-bit e and 9-bit m: | ||
924 | // rate = EITHER (1+m/2^9)*2^e OR 0 | ||
925 | // bits = EITHER 1<<14 | e<<9 | m OR 0 | ||
926 | // (bit 15 is "reserved", bit 14 "non-zero") | ||
927 | // smallest rate is 0 (special representation) | ||
928 | // largest rate is (1+511/512)*2^31 = 4290772992 (< 2^32-1) | ||
929 | // smallest non-zero rate is (1+0/512)*2^0 = 1 (> 0) | ||
930 | // simple algorithm: | ||
931 | // find position of top bit, this gives e | ||
932 | // remove top bit and shift (rounding if feeling clever) by 9-e | ||
933 | |||
934 | // ucode bug: please don't set bit 14! so 0 rate not representable | ||
935 | |||
936 | if (rate > 0xffc00000U) { | ||
937 | // larger than largest representable rate | ||
938 | |||
939 | if (r == round_up) { | ||
940 | return -EINVAL; | ||
941 | } else { | ||
942 | exp = 31; | ||
943 | man = 511; | ||
944 | } | ||
945 | |||
946 | } else if (rate) { | ||
947 | // representable rate | ||
948 | |||
949 | exp = 31; | ||
950 | man = rate; | ||
951 | |||
952 | // invariant: rate = man*2^(exp-31) | ||
953 | while (!(man & (1<<31))) { | ||
954 | exp = exp - 1; | ||
955 | man = man<<1; | ||
956 | } | ||
957 | |||
958 | // man has top bit set | ||
959 | // rate = (2^31+(man-2^31))*2^(exp-31) | ||
960 | // rate = (1+(man-2^31)/2^31)*2^exp | ||
961 | man = man<<1; | ||
962 | man &= 0xffffffffU; // a nop on 32-bit systems | ||
963 | // rate = (1+man/2^32)*2^exp | ||
964 | |||
965 | // exp is in the range 0 to 31, man is in the range 0 to 2^32-1 | ||
966 | // time to lose significance... we want m in the range 0 to 2^9-1 | ||
967 | // rounding presents a minor problem... we first decide which way | ||
968 | // we are rounding (based on given rounding direction and possibly | ||
969 | // the bits of the mantissa that are to be discarded). | ||
970 | |||
971 | switch (r) { | ||
972 | case round_down: { | ||
973 | // just truncate | ||
974 | man = man>>(32-9); | ||
975 | break; | ||
976 | } | ||
977 | case round_up: { | ||
978 | // check all bits that we are discarding | ||
979 | if (man & (-1>>9)) { | ||
980 | man = (man>>(32-9)) + 1; | ||
981 | if (man == (1<<9)) { | ||
982 | // no need to check for round up outside of range | ||
983 | man = 0; | ||
984 | exp += 1; | ||
985 | } | ||
986 | } else { | ||
987 | man = (man>>(32-9)); | ||
988 | } | ||
989 | break; | ||
990 | } | ||
991 | case round_nearest: { | ||
992 | // check msb that we are discarding | ||
993 | if (man & (1<<(32-9-1))) { | ||
994 | man = (man>>(32-9)) + 1; | ||
995 | if (man == (1<<9)) { | ||
996 | // no need to check for round up outside of range | ||
997 | man = 0; | ||
998 | exp += 1; | ||
999 | } | ||
1000 | } else { | ||
1001 | man = (man>>(32-9)); | ||
1002 | } | ||
1003 | break; | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | } else { | ||
1008 | // zero rate - not representable | ||
1009 | |||
1010 | if (r == round_down) { | ||
1011 | return -EINVAL; | ||
1012 | } else { | ||
1013 | exp = 0; | ||
1014 | man = 0; | ||
1015 | } | ||
1016 | |||
1017 | } | ||
1018 | |||
1019 | PRINTD (DBG_QOS, "rate: man=%u, exp=%hu", man, exp); | ||
1020 | |||
1021 | if (bits) | ||
1022 | *bits = /* (1<<14) | */ (exp<<9) | man; | ||
1023 | |||
1024 | if (actual) | ||
1025 | *actual = (exp >= 9) | ||
1026 | ? (1 << exp) + (man << (exp-9)) | ||
1027 | : (1 << exp) + ((man + (1<<(9-exp-1))) >> (9-exp)); | ||
1028 | |||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
1032 | /********** Linux ATM Operations **********/ | ||
1033 | |||
1034 | // some are not yet implemented while others do not make sense for | ||
1035 | // this device | ||
1036 | |||
1037 | /********** Open a VC **********/ | ||
1038 | |||
1039 | static int amb_open (struct atm_vcc * atm_vcc) | ||
1040 | { | ||
1041 | int error; | ||
1042 | |||
1043 | struct atm_qos * qos; | ||
1044 | struct atm_trafprm * txtp; | ||
1045 | struct atm_trafprm * rxtp; | ||
1046 | u16 tx_rate_bits; | ||
1047 | u16 tx_vc_bits = -1; // hush gcc | ||
1048 | u16 tx_frame_bits = -1; // hush gcc | ||
1049 | |||
1050 | amb_dev * dev = AMB_DEV(atm_vcc->dev); | ||
1051 | amb_vcc * vcc; | ||
1052 | unsigned char pool = -1; // hush gcc | ||
1053 | short vpi = atm_vcc->vpi; | ||
1054 | int vci = atm_vcc->vci; | ||
1055 | |||
1056 | PRINTD (DBG_FLOW|DBG_VCC, "amb_open %x %x", vpi, vci); | ||
1057 | |||
1058 | #ifdef ATM_VPI_UNSPEC | ||
1059 | // UNSPEC is deprecated, remove this code eventually | ||
1060 | if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) { | ||
1061 | PRINTK (KERN_WARNING, "rejecting open with unspecified VPI/VCI (deprecated)"); | ||
1062 | return -EINVAL; | ||
1063 | } | ||
1064 | #endif | ||
1065 | |||
1066 | if (!(0 <= vpi && vpi < (1<<NUM_VPI_BITS) && | ||
1067 | 0 <= vci && vci < (1<<NUM_VCI_BITS))) { | ||
1068 | PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci); | ||
1069 | return -EINVAL; | ||
1070 | } | ||
1071 | |||
1072 | qos = &atm_vcc->qos; | ||
1073 | |||
1074 | if (qos->aal != ATM_AAL5) { | ||
1075 | PRINTD (DBG_QOS, "AAL not supported"); | ||
1076 | return -EINVAL; | ||
1077 | } | ||
1078 | |||
1079 | // traffic parameters | ||
1080 | |||
1081 | PRINTD (DBG_QOS, "TX:"); | ||
1082 | txtp = &qos->txtp; | ||
1083 | if (txtp->traffic_class != ATM_NONE) { | ||
1084 | switch (txtp->traffic_class) { | ||
1085 | case ATM_UBR: { | ||
1086 | // we take "the PCR" as a rate-cap | ||
1087 | int pcr = atm_pcr_goal (txtp); | ||
1088 | if (!pcr) { | ||
1089 | // no rate cap | ||
1090 | tx_rate_bits = 0; | ||
1091 | tx_vc_bits = TX_UBR; | ||
1092 | tx_frame_bits = TX_FRAME_NOTCAP; | ||
1093 | } else { | ||
1094 | rounding r; | ||
1095 | if (pcr < 0) { | ||
1096 | r = round_down; | ||
1097 | pcr = -pcr; | ||
1098 | } else { | ||
1099 | r = round_up; | ||
1100 | } | ||
1101 | error = make_rate (pcr, r, &tx_rate_bits, NULL); | ||
1102 | tx_vc_bits = TX_UBR_CAPPED; | ||
1103 | tx_frame_bits = TX_FRAME_CAPPED; | ||
1104 | } | ||
1105 | break; | ||
1106 | } | ||
1107 | #if 0 | ||
1108 | case ATM_ABR: { | ||
1109 | pcr = atm_pcr_goal (txtp); | ||
1110 | PRINTD (DBG_QOS, "pcr goal = %d", pcr); | ||
1111 | break; | ||
1112 | } | ||
1113 | #endif | ||
1114 | default: { | ||
1115 | // PRINTD (DBG_QOS, "request for non-UBR/ABR denied"); | ||
1116 | PRINTD (DBG_QOS, "request for non-UBR denied"); | ||
1117 | return -EINVAL; | ||
1118 | } | ||
1119 | } | ||
1120 | PRINTD (DBG_QOS, "tx_rate_bits=%hx, tx_vc_bits=%hx", | ||
1121 | tx_rate_bits, tx_vc_bits); | ||
1122 | } | ||
1123 | |||
1124 | PRINTD (DBG_QOS, "RX:"); | ||
1125 | rxtp = &qos->rxtp; | ||
1126 | if (rxtp->traffic_class == ATM_NONE) { | ||
1127 | // do nothing | ||
1128 | } else { | ||
1129 | // choose an RX pool (arranged in increasing size) | ||
1130 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
1131 | if ((unsigned int) rxtp->max_sdu <= dev->rxq[pool].buffer_size) { | ||
1132 | PRINTD (DBG_VCC|DBG_QOS|DBG_POOL, "chose pool %hu (max_sdu %u <= %u)", | ||
1133 | pool, rxtp->max_sdu, dev->rxq[pool].buffer_size); | ||
1134 | break; | ||
1135 | } | ||
1136 | if (pool == NUM_RX_POOLS) { | ||
1137 | PRINTD (DBG_WARN|DBG_VCC|DBG_QOS|DBG_POOL, | ||
1138 | "no pool suitable for VC (RX max_sdu %d is too large)", | ||
1139 | rxtp->max_sdu); | ||
1140 | return -EINVAL; | ||
1141 | } | ||
1142 | |||
1143 | switch (rxtp->traffic_class) { | ||
1144 | case ATM_UBR: { | ||
1145 | break; | ||
1146 | } | ||
1147 | #if 0 | ||
1148 | case ATM_ABR: { | ||
1149 | pcr = atm_pcr_goal (rxtp); | ||
1150 | PRINTD (DBG_QOS, "pcr goal = %d", pcr); | ||
1151 | break; | ||
1152 | } | ||
1153 | #endif | ||
1154 | default: { | ||
1155 | // PRINTD (DBG_QOS, "request for non-UBR/ABR denied"); | ||
1156 | PRINTD (DBG_QOS, "request for non-UBR denied"); | ||
1157 | return -EINVAL; | ||
1158 | } | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | // get space for our vcc stuff | ||
1163 | vcc = kmalloc (sizeof(amb_vcc), GFP_KERNEL); | ||
1164 | if (!vcc) { | ||
1165 | PRINTK (KERN_ERR, "out of memory!"); | ||
1166 | return -ENOMEM; | ||
1167 | } | ||
1168 | atm_vcc->dev_data = (void *) vcc; | ||
1169 | |||
1170 | // no failures beyond this point | ||
1171 | |||
1172 | // we are not really "immediately before allocating the connection | ||
1173 | // identifier in hardware", but it will just have to do! | ||
1174 | set_bit(ATM_VF_ADDR,&atm_vcc->flags); | ||
1175 | |||
1176 | if (txtp->traffic_class != ATM_NONE) { | ||
1177 | command cmd; | ||
1178 | |||
1179 | vcc->tx_frame_bits = tx_frame_bits; | ||
1180 | |||
1181 | down (&dev->vcc_sf); | ||
1182 | if (dev->rxer[vci]) { | ||
1183 | // RXer on the channel already, just modify rate... | ||
1184 | cmd.request = cpu_to_be32 (SRB_MODIFY_VC_RATE); | ||
1185 | cmd.args.modify_rate.vc = cpu_to_be32 (vci); // vpi 0 | ||
1186 | cmd.args.modify_rate.rate = cpu_to_be32 (tx_rate_bits << SRB_RATE_SHIFT); | ||
1187 | while (command_do (dev, &cmd)) | ||
1188 | schedule(); | ||
1189 | // ... and TX flags, preserving the RX pool | ||
1190 | cmd.request = cpu_to_be32 (SRB_MODIFY_VC_FLAGS); | ||
1191 | cmd.args.modify_flags.vc = cpu_to_be32 (vci); // vpi 0 | ||
1192 | cmd.args.modify_flags.flags = cpu_to_be32 | ||
1193 | ( (AMB_VCC(dev->rxer[vci])->rx_info.pool << SRB_POOL_SHIFT) | ||
1194 | | (tx_vc_bits << SRB_FLAGS_SHIFT) ); | ||
1195 | while (command_do (dev, &cmd)) | ||
1196 | schedule(); | ||
1197 | } else { | ||
1198 | // no RXer on the channel, just open (with pool zero) | ||
1199 | cmd.request = cpu_to_be32 (SRB_OPEN_VC); | ||
1200 | cmd.args.open.vc = cpu_to_be32 (vci); // vpi 0 | ||
1201 | cmd.args.open.flags = cpu_to_be32 (tx_vc_bits << SRB_FLAGS_SHIFT); | ||
1202 | cmd.args.open.rate = cpu_to_be32 (tx_rate_bits << SRB_RATE_SHIFT); | ||
1203 | while (command_do (dev, &cmd)) | ||
1204 | schedule(); | ||
1205 | } | ||
1206 | dev->txer[vci].tx_present = 1; | ||
1207 | up (&dev->vcc_sf); | ||
1208 | } | ||
1209 | |||
1210 | if (rxtp->traffic_class != ATM_NONE) { | ||
1211 | command cmd; | ||
1212 | |||
1213 | vcc->rx_info.pool = pool; | ||
1214 | |||
1215 | down (&dev->vcc_sf); | ||
1216 | /* grow RX buffer pool */ | ||
1217 | if (!dev->rxq[pool].buffers_wanted) | ||
1218 | dev->rxq[pool].buffers_wanted = rx_lats; | ||
1219 | dev->rxq[pool].buffers_wanted += 1; | ||
1220 | fill_rx_pool (dev, pool, GFP_KERNEL); | ||
1221 | |||
1222 | if (dev->txer[vci].tx_present) { | ||
1223 | // TXer on the channel already | ||
1224 | // switch (from pool zero) to this pool, preserving the TX bits | ||
1225 | cmd.request = cpu_to_be32 (SRB_MODIFY_VC_FLAGS); | ||
1226 | cmd.args.modify_flags.vc = cpu_to_be32 (vci); // vpi 0 | ||
1227 | cmd.args.modify_flags.flags = cpu_to_be32 | ||
1228 | ( (pool << SRB_POOL_SHIFT) | ||
1229 | | (dev->txer[vci].tx_vc_bits << SRB_FLAGS_SHIFT) ); | ||
1230 | } else { | ||
1231 | // no TXer on the channel, open the VC (with no rate info) | ||
1232 | cmd.request = cpu_to_be32 (SRB_OPEN_VC); | ||
1233 | cmd.args.open.vc = cpu_to_be32 (vci); // vpi 0 | ||
1234 | cmd.args.open.flags = cpu_to_be32 (pool << SRB_POOL_SHIFT); | ||
1235 | cmd.args.open.rate = cpu_to_be32 (0); | ||
1236 | } | ||
1237 | while (command_do (dev, &cmd)) | ||
1238 | schedule(); | ||
1239 | // this link allows RX frames through | ||
1240 | dev->rxer[vci] = atm_vcc; | ||
1241 | up (&dev->vcc_sf); | ||
1242 | } | ||
1243 | |||
1244 | // indicate readiness | ||
1245 | set_bit(ATM_VF_READY,&atm_vcc->flags); | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | /********** Close a VC **********/ | ||
1251 | |||
1252 | static void amb_close (struct atm_vcc * atm_vcc) { | ||
1253 | amb_dev * dev = AMB_DEV (atm_vcc->dev); | ||
1254 | amb_vcc * vcc = AMB_VCC (atm_vcc); | ||
1255 | u16 vci = atm_vcc->vci; | ||
1256 | |||
1257 | PRINTD (DBG_VCC|DBG_FLOW, "amb_close"); | ||
1258 | |||
1259 | // indicate unreadiness | ||
1260 | clear_bit(ATM_VF_READY,&atm_vcc->flags); | ||
1261 | |||
1262 | // disable TXing | ||
1263 | if (atm_vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
1264 | command cmd; | ||
1265 | |||
1266 | down (&dev->vcc_sf); | ||
1267 | if (dev->rxer[vci]) { | ||
1268 | // RXer still on the channel, just modify rate... XXX not really needed | ||
1269 | cmd.request = cpu_to_be32 (SRB_MODIFY_VC_RATE); | ||
1270 | cmd.args.modify_rate.vc = cpu_to_be32 (vci); // vpi 0 | ||
1271 | cmd.args.modify_rate.rate = cpu_to_be32 (0); | ||
1272 | // ... and clear TX rate flags (XXX to stop RM cell output?), preserving RX pool | ||
1273 | } else { | ||
1274 | // no RXer on the channel, close channel | ||
1275 | cmd.request = cpu_to_be32 (SRB_CLOSE_VC); | ||
1276 | cmd.args.close.vc = cpu_to_be32 (vci); // vpi 0 | ||
1277 | } | ||
1278 | dev->txer[vci].tx_present = 0; | ||
1279 | while (command_do (dev, &cmd)) | ||
1280 | schedule(); | ||
1281 | up (&dev->vcc_sf); | ||
1282 | } | ||
1283 | |||
1284 | // disable RXing | ||
1285 | if (atm_vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
1286 | command cmd; | ||
1287 | |||
1288 | // this is (the?) one reason why we need the amb_vcc struct | ||
1289 | unsigned char pool = vcc->rx_info.pool; | ||
1290 | |||
1291 | down (&dev->vcc_sf); | ||
1292 | if (dev->txer[vci].tx_present) { | ||
1293 | // TXer still on the channel, just go to pool zero XXX not really needed | ||
1294 | cmd.request = cpu_to_be32 (SRB_MODIFY_VC_FLAGS); | ||
1295 | cmd.args.modify_flags.vc = cpu_to_be32 (vci); // vpi 0 | ||
1296 | cmd.args.modify_flags.flags = cpu_to_be32 | ||
1297 | (dev->txer[vci].tx_vc_bits << SRB_FLAGS_SHIFT); | ||
1298 | } else { | ||
1299 | // no TXer on the channel, close the VC | ||
1300 | cmd.request = cpu_to_be32 (SRB_CLOSE_VC); | ||
1301 | cmd.args.close.vc = cpu_to_be32 (vci); // vpi 0 | ||
1302 | } | ||
1303 | // forget the rxer - no more skbs will be pushed | ||
1304 | if (atm_vcc != dev->rxer[vci]) | ||
1305 | PRINTK (KERN_ERR, "%s vcc=%p rxer[vci]=%p", | ||
1306 | "arghhh! we're going to die!", | ||
1307 | vcc, dev->rxer[vci]); | ||
1308 | dev->rxer[vci] = NULL; | ||
1309 | while (command_do (dev, &cmd)) | ||
1310 | schedule(); | ||
1311 | |||
1312 | /* shrink RX buffer pool */ | ||
1313 | dev->rxq[pool].buffers_wanted -= 1; | ||
1314 | if (dev->rxq[pool].buffers_wanted == rx_lats) { | ||
1315 | dev->rxq[pool].buffers_wanted = 0; | ||
1316 | drain_rx_pool (dev, pool); | ||
1317 | } | ||
1318 | up (&dev->vcc_sf); | ||
1319 | } | ||
1320 | |||
1321 | // free our structure | ||
1322 | kfree (vcc); | ||
1323 | |||
1324 | // say the VPI/VCI is free again | ||
1325 | clear_bit(ATM_VF_ADDR,&atm_vcc->flags); | ||
1326 | |||
1327 | return; | ||
1328 | } | ||
1329 | |||
1330 | /********** Set socket options for a VC **********/ | ||
1331 | |||
1332 | // int amb_getsockopt (struct atm_vcc * atm_vcc, int level, int optname, void * optval, int optlen); | ||
1333 | |||
1334 | /********** Set socket options for a VC **********/ | ||
1335 | |||
1336 | // int amb_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, void * optval, int optlen); | ||
1337 | |||
1338 | /********** Send **********/ | ||
1339 | |||
1340 | static int amb_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { | ||
1341 | amb_dev * dev = AMB_DEV(atm_vcc->dev); | ||
1342 | amb_vcc * vcc = AMB_VCC(atm_vcc); | ||
1343 | u16 vc = atm_vcc->vci; | ||
1344 | unsigned int tx_len = skb->len; | ||
1345 | unsigned char * tx_data = skb->data; | ||
1346 | tx_simple * tx_descr; | ||
1347 | tx_in tx; | ||
1348 | |||
1349 | if (test_bit (dead, &dev->flags)) | ||
1350 | return -EIO; | ||
1351 | |||
1352 | PRINTD (DBG_FLOW|DBG_TX, "amb_send vc %x data %p len %u", | ||
1353 | vc, tx_data, tx_len); | ||
1354 | |||
1355 | dump_skb (">>>", vc, skb); | ||
1356 | |||
1357 | if (!dev->txer[vc].tx_present) { | ||
1358 | PRINTK (KERN_ERR, "attempt to send on RX-only VC %x", vc); | ||
1359 | return -EBADFD; | ||
1360 | } | ||
1361 | |||
1362 | // this is a driver private field so we have to set it ourselves, | ||
1363 | // despite the fact that we are _required_ to use it to check for a | ||
1364 | // pop function | ||
1365 | ATM_SKB(skb)->vcc = atm_vcc; | ||
1366 | |||
1367 | if (skb->len > (size_t) atm_vcc->qos.txtp.max_sdu) { | ||
1368 | PRINTK (KERN_ERR, "sk_buff length greater than agreed max_sdu, dropping..."); | ||
1369 | return -EIO; | ||
1370 | } | ||
1371 | |||
1372 | if (check_area (skb->data, skb->len)) { | ||
1373 | atomic_inc(&atm_vcc->stats->tx_err); | ||
1374 | return -ENOMEM; // ? | ||
1375 | } | ||
1376 | |||
1377 | // allocate memory for fragments | ||
1378 | tx_descr = kmalloc (sizeof(tx_simple), GFP_KERNEL); | ||
1379 | if (!tx_descr) { | ||
1380 | PRINTK (KERN_ERR, "could not allocate TX descriptor"); | ||
1381 | return -ENOMEM; | ||
1382 | } | ||
1383 | if (check_area (tx_descr, sizeof(tx_simple))) { | ||
1384 | kfree (tx_descr); | ||
1385 | return -ENOMEM; | ||
1386 | } | ||
1387 | PRINTD (DBG_TX, "fragment list allocated at %p", tx_descr); | ||
1388 | |||
1389 | tx_descr->skb = skb; | ||
1390 | |||
1391 | tx_descr->tx_frag.bytes = cpu_to_be32 (tx_len); | ||
1392 | tx_descr->tx_frag.address = cpu_to_be32 (virt_to_bus (tx_data)); | ||
1393 | |||
1394 | tx_descr->tx_frag_end.handle = virt_to_bus (tx_descr); | ||
1395 | tx_descr->tx_frag_end.vc = 0; | ||
1396 | tx_descr->tx_frag_end.next_descriptor_length = 0; | ||
1397 | tx_descr->tx_frag_end.next_descriptor = 0; | ||
1398 | #ifdef AMB_NEW_MICROCODE | ||
1399 | tx_descr->tx_frag_end.cpcs_uu = 0; | ||
1400 | tx_descr->tx_frag_end.cpi = 0; | ||
1401 | tx_descr->tx_frag_end.pad = 0; | ||
1402 | #endif | ||
1403 | |||
1404 | tx.vc = cpu_to_be16 (vcc->tx_frame_bits | vc); | ||
1405 | tx.tx_descr_length = cpu_to_be16 (sizeof(tx_frag)+sizeof(tx_frag_end)); | ||
1406 | tx.tx_descr_addr = cpu_to_be32 (virt_to_bus (&tx_descr->tx_frag)); | ||
1407 | |||
1408 | while (tx_give (dev, &tx)) | ||
1409 | schedule(); | ||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1413 | /********** Change QoS on a VC **********/ | ||
1414 | |||
1415 | // int amb_change_qos (struct atm_vcc * atm_vcc, struct atm_qos * qos, int flags); | ||
1416 | |||
1417 | /********** Free RX Socket Buffer **********/ | ||
1418 | |||
1419 | #if 0 | ||
1420 | static void amb_free_rx_skb (struct atm_vcc * atm_vcc, struct sk_buff * skb) { | ||
1421 | amb_dev * dev = AMB_DEV (atm_vcc->dev); | ||
1422 | amb_vcc * vcc = AMB_VCC (atm_vcc); | ||
1423 | unsigned char pool = vcc->rx_info.pool; | ||
1424 | rx_in rx; | ||
1425 | |||
1426 | // This may be unsafe for various reasons that I cannot really guess | ||
1427 | // at. However, I note that the ATM layer calls kfree_skb rather | ||
1428 | // than dev_kfree_skb at this point so we are least covered as far | ||
1429 | // as buffer locking goes. There may be bugs if pcap clones RX skbs. | ||
1430 | |||
1431 | PRINTD (DBG_FLOW|DBG_SKB, "amb_rx_free skb %p (atm_vcc %p, vcc %p)", | ||
1432 | skb, atm_vcc, vcc); | ||
1433 | |||
1434 | rx.handle = virt_to_bus (skb); | ||
1435 | rx.host_address = cpu_to_be32 (virt_to_bus (skb->data)); | ||
1436 | |||
1437 | skb->data = skb->head; | ||
1438 | skb->tail = skb->head; | ||
1439 | skb->len = 0; | ||
1440 | |||
1441 | if (!rx_give (dev, &rx, pool)) { | ||
1442 | // success | ||
1443 | PRINTD (DBG_SKB|DBG_POOL, "recycled skb for pool %hu", pool); | ||
1444 | return; | ||
1445 | } | ||
1446 | |||
1447 | // just do what the ATM layer would have done | ||
1448 | dev_kfree_skb_any (skb); | ||
1449 | |||
1450 | return; | ||
1451 | } | ||
1452 | #endif | ||
1453 | |||
1454 | /********** Proc File Output **********/ | ||
1455 | |||
1456 | static int amb_proc_read (struct atm_dev * atm_dev, loff_t * pos, char * page) { | ||
1457 | amb_dev * dev = AMB_DEV (atm_dev); | ||
1458 | int left = *pos; | ||
1459 | unsigned char pool; | ||
1460 | |||
1461 | PRINTD (DBG_FLOW, "amb_proc_read"); | ||
1462 | |||
1463 | /* more diagnostics here? */ | ||
1464 | |||
1465 | if (!left--) { | ||
1466 | amb_stats * s = &dev->stats; | ||
1467 | return sprintf (page, | ||
1468 | "frames: TX OK %lu, RX OK %lu, RX bad %lu " | ||
1469 | "(CRC %lu, long %lu, aborted %lu, unused %lu).\n", | ||
1470 | s->tx_ok, s->rx.ok, s->rx.error, | ||
1471 | s->rx.badcrc, s->rx.toolong, | ||
1472 | s->rx.aborted, s->rx.unused); | ||
1473 | } | ||
1474 | |||
1475 | if (!left--) { | ||
1476 | amb_cq * c = &dev->cq; | ||
1477 | return sprintf (page, "cmd queue [cur/hi/max]: %u/%u/%u. ", | ||
1478 | c->pending, c->high, c->maximum); | ||
1479 | } | ||
1480 | |||
1481 | if (!left--) { | ||
1482 | amb_txq * t = &dev->txq; | ||
1483 | return sprintf (page, "TX queue [cur/max high full]: %u/%u %u %u.\n", | ||
1484 | t->pending, t->maximum, t->high, t->filled); | ||
1485 | } | ||
1486 | |||
1487 | if (!left--) { | ||
1488 | unsigned int count = sprintf (page, "RX queues [cur/max/req low empty]:"); | ||
1489 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) { | ||
1490 | amb_rxq * r = &dev->rxq[pool]; | ||
1491 | count += sprintf (page+count, " %u/%u/%u %u %u", | ||
1492 | r->pending, r->maximum, r->buffers_wanted, r->low, r->emptied); | ||
1493 | } | ||
1494 | count += sprintf (page+count, ".\n"); | ||
1495 | return count; | ||
1496 | } | ||
1497 | |||
1498 | if (!left--) { | ||
1499 | unsigned int count = sprintf (page, "RX buffer sizes:"); | ||
1500 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) { | ||
1501 | amb_rxq * r = &dev->rxq[pool]; | ||
1502 | count += sprintf (page+count, " %u", r->buffer_size); | ||
1503 | } | ||
1504 | count += sprintf (page+count, ".\n"); | ||
1505 | return count; | ||
1506 | } | ||
1507 | |||
1508 | #if 0 | ||
1509 | if (!left--) { | ||
1510 | // suni block etc? | ||
1511 | } | ||
1512 | #endif | ||
1513 | |||
1514 | return 0; | ||
1515 | } | ||
1516 | |||
1517 | /********** Operation Structure **********/ | ||
1518 | |||
1519 | static const struct atmdev_ops amb_ops = { | ||
1520 | .open = amb_open, | ||
1521 | .close = amb_close, | ||
1522 | .send = amb_send, | ||
1523 | .proc_read = amb_proc_read, | ||
1524 | .owner = THIS_MODULE, | ||
1525 | }; | ||
1526 | |||
1527 | /********** housekeeping **********/ | ||
1528 | static void do_housekeeping (unsigned long arg) { | ||
1529 | amb_dev * dev = (amb_dev *) arg; | ||
1530 | |||
1531 | // could collect device-specific (not driver/atm-linux) stats here | ||
1532 | |||
1533 | // last resort refill once every ten seconds | ||
1534 | fill_rx_pools (dev); | ||
1535 | mod_timer(&dev->housekeeping, jiffies + 10*HZ); | ||
1536 | |||
1537 | return; | ||
1538 | } | ||
1539 | |||
1540 | /********** creation of communication queues **********/ | ||
1541 | |||
1542 | static int __devinit create_queues (amb_dev * dev, unsigned int cmds, | ||
1543 | unsigned int txs, unsigned int * rxs, | ||
1544 | unsigned int * rx_buffer_sizes) { | ||
1545 | unsigned char pool; | ||
1546 | size_t total = 0; | ||
1547 | void * memory; | ||
1548 | void * limit; | ||
1549 | |||
1550 | PRINTD (DBG_FLOW, "create_queues %p", dev); | ||
1551 | |||
1552 | total += cmds * sizeof(command); | ||
1553 | |||
1554 | total += txs * (sizeof(tx_in) + sizeof(tx_out)); | ||
1555 | |||
1556 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
1557 | total += rxs[pool] * (sizeof(rx_in) + sizeof(rx_out)); | ||
1558 | |||
1559 | memory = kmalloc (total, GFP_KERNEL); | ||
1560 | if (!memory) { | ||
1561 | PRINTK (KERN_ERR, "could not allocate queues"); | ||
1562 | return -ENOMEM; | ||
1563 | } | ||
1564 | if (check_area (memory, total)) { | ||
1565 | PRINTK (KERN_ERR, "queues allocated in nasty area"); | ||
1566 | kfree (memory); | ||
1567 | return -ENOMEM; | ||
1568 | } | ||
1569 | |||
1570 | limit = memory + total; | ||
1571 | PRINTD (DBG_INIT, "queues from %p to %p", memory, limit); | ||
1572 | |||
1573 | PRINTD (DBG_CMD, "command queue at %p", memory); | ||
1574 | |||
1575 | { | ||
1576 | command * cmd = memory; | ||
1577 | amb_cq * cq = &dev->cq; | ||
1578 | |||
1579 | cq->pending = 0; | ||
1580 | cq->high = 0; | ||
1581 | cq->maximum = cmds - 1; | ||
1582 | |||
1583 | cq->ptrs.start = cmd; | ||
1584 | cq->ptrs.in = cmd; | ||
1585 | cq->ptrs.out = cmd; | ||
1586 | cq->ptrs.limit = cmd + cmds; | ||
1587 | |||
1588 | memory = cq->ptrs.limit; | ||
1589 | } | ||
1590 | |||
1591 | PRINTD (DBG_TX, "TX queue pair at %p", memory); | ||
1592 | |||
1593 | { | ||
1594 | tx_in * in = memory; | ||
1595 | tx_out * out; | ||
1596 | amb_txq * txq = &dev->txq; | ||
1597 | |||
1598 | txq->pending = 0; | ||
1599 | txq->high = 0; | ||
1600 | txq->filled = 0; | ||
1601 | txq->maximum = txs - 1; | ||
1602 | |||
1603 | txq->in.start = in; | ||
1604 | txq->in.ptr = in; | ||
1605 | txq->in.limit = in + txs; | ||
1606 | |||
1607 | memory = txq->in.limit; | ||
1608 | out = memory; | ||
1609 | |||
1610 | txq->out.start = out; | ||
1611 | txq->out.ptr = out; | ||
1612 | txq->out.limit = out + txs; | ||
1613 | |||
1614 | memory = txq->out.limit; | ||
1615 | } | ||
1616 | |||
1617 | PRINTD (DBG_RX, "RX queue pairs at %p", memory); | ||
1618 | |||
1619 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) { | ||
1620 | rx_in * in = memory; | ||
1621 | rx_out * out; | ||
1622 | amb_rxq * rxq = &dev->rxq[pool]; | ||
1623 | |||
1624 | rxq->buffer_size = rx_buffer_sizes[pool]; | ||
1625 | rxq->buffers_wanted = 0; | ||
1626 | |||
1627 | rxq->pending = 0; | ||
1628 | rxq->low = rxs[pool] - 1; | ||
1629 | rxq->emptied = 0; | ||
1630 | rxq->maximum = rxs[pool] - 1; | ||
1631 | |||
1632 | rxq->in.start = in; | ||
1633 | rxq->in.ptr = in; | ||
1634 | rxq->in.limit = in + rxs[pool]; | ||
1635 | |||
1636 | memory = rxq->in.limit; | ||
1637 | out = memory; | ||
1638 | |||
1639 | rxq->out.start = out; | ||
1640 | rxq->out.ptr = out; | ||
1641 | rxq->out.limit = out + rxs[pool]; | ||
1642 | |||
1643 | memory = rxq->out.limit; | ||
1644 | } | ||
1645 | |||
1646 | if (memory == limit) { | ||
1647 | return 0; | ||
1648 | } else { | ||
1649 | PRINTK (KERN_ERR, "bad queue alloc %p != %p (tell maintainer)", memory, limit); | ||
1650 | kfree (limit - total); | ||
1651 | return -ENOMEM; | ||
1652 | } | ||
1653 | |||
1654 | } | ||
1655 | |||
1656 | /********** destruction of communication queues **********/ | ||
1657 | |||
1658 | static void destroy_queues (amb_dev * dev) { | ||
1659 | // all queues assumed empty | ||
1660 | void * memory = dev->cq.ptrs.start; | ||
1661 | // includes txq.in, txq.out, rxq[].in and rxq[].out | ||
1662 | |||
1663 | PRINTD (DBG_FLOW, "destroy_queues %p", dev); | ||
1664 | |||
1665 | PRINTD (DBG_INIT, "freeing queues at %p", memory); | ||
1666 | kfree (memory); | ||
1667 | |||
1668 | return; | ||
1669 | } | ||
1670 | |||
1671 | /********** basic loader commands and error handling **********/ | ||
1672 | // centisecond timeouts - guessing away here | ||
1673 | static unsigned int command_timeouts [] = { | ||
1674 | [host_memory_test] = 15, | ||
1675 | [read_adapter_memory] = 2, | ||
1676 | [write_adapter_memory] = 2, | ||
1677 | [adapter_start] = 50, | ||
1678 | [get_version_number] = 10, | ||
1679 | [interrupt_host] = 1, | ||
1680 | [flash_erase_sector] = 1, | ||
1681 | [adap_download_block] = 1, | ||
1682 | [adap_erase_flash] = 1, | ||
1683 | [adap_run_in_iram] = 1, | ||
1684 | [adap_end_download] = 1 | ||
1685 | }; | ||
1686 | |||
1687 | |||
1688 | static unsigned int command_successes [] = { | ||
1689 | [host_memory_test] = COMMAND_PASSED_TEST, | ||
1690 | [read_adapter_memory] = COMMAND_READ_DATA_OK, | ||
1691 | [write_adapter_memory] = COMMAND_WRITE_DATA_OK, | ||
1692 | [adapter_start] = COMMAND_COMPLETE, | ||
1693 | [get_version_number] = COMMAND_COMPLETE, | ||
1694 | [interrupt_host] = COMMAND_COMPLETE, | ||
1695 | [flash_erase_sector] = COMMAND_COMPLETE, | ||
1696 | [adap_download_block] = COMMAND_COMPLETE, | ||
1697 | [adap_erase_flash] = COMMAND_COMPLETE, | ||
1698 | [adap_run_in_iram] = COMMAND_COMPLETE, | ||
1699 | [adap_end_download] = COMMAND_COMPLETE | ||
1700 | }; | ||
1701 | |||
1702 | static int decode_loader_result (loader_command cmd, u32 result) | ||
1703 | { | ||
1704 | int res; | ||
1705 | const char *msg; | ||
1706 | |||
1707 | if (result == command_successes[cmd]) | ||
1708 | return 0; | ||
1709 | |||
1710 | switch (result) { | ||
1711 | case BAD_COMMAND: | ||
1712 | res = -EINVAL; | ||
1713 | msg = "bad command"; | ||
1714 | break; | ||
1715 | case COMMAND_IN_PROGRESS: | ||
1716 | res = -ETIMEDOUT; | ||
1717 | msg = "command in progress"; | ||
1718 | break; | ||
1719 | case COMMAND_PASSED_TEST: | ||
1720 | res = 0; | ||
1721 | msg = "command passed test"; | ||
1722 | break; | ||
1723 | case COMMAND_FAILED_TEST: | ||
1724 | res = -EIO; | ||
1725 | msg = "command failed test"; | ||
1726 | break; | ||
1727 | case COMMAND_READ_DATA_OK: | ||
1728 | res = 0; | ||
1729 | msg = "command read data ok"; | ||
1730 | break; | ||
1731 | case COMMAND_READ_BAD_ADDRESS: | ||
1732 | res = -EINVAL; | ||
1733 | msg = "command read bad address"; | ||
1734 | break; | ||
1735 | case COMMAND_WRITE_DATA_OK: | ||
1736 | res = 0; | ||
1737 | msg = "command write data ok"; | ||
1738 | break; | ||
1739 | case COMMAND_WRITE_BAD_ADDRESS: | ||
1740 | res = -EINVAL; | ||
1741 | msg = "command write bad address"; | ||
1742 | break; | ||
1743 | case COMMAND_WRITE_FLASH_FAILURE: | ||
1744 | res = -EIO; | ||
1745 | msg = "command write flash failure"; | ||
1746 | break; | ||
1747 | case COMMAND_COMPLETE: | ||
1748 | res = 0; | ||
1749 | msg = "command complete"; | ||
1750 | break; | ||
1751 | case COMMAND_FLASH_ERASE_FAILURE: | ||
1752 | res = -EIO; | ||
1753 | msg = "command flash erase failure"; | ||
1754 | break; | ||
1755 | case COMMAND_WRITE_BAD_DATA: | ||
1756 | res = -EINVAL; | ||
1757 | msg = "command write bad data"; | ||
1758 | break; | ||
1759 | default: | ||
1760 | res = -EINVAL; | ||
1761 | msg = "unknown error"; | ||
1762 | PRINTD (DBG_LOAD|DBG_ERR, | ||
1763 | "decode_loader_result got %d=%x !", | ||
1764 | result, result); | ||
1765 | break; | ||
1766 | } | ||
1767 | |||
1768 | PRINTK (KERN_ERR, "%s", msg); | ||
1769 | return res; | ||
1770 | } | ||
1771 | |||
1772 | static int __devinit do_loader_command (volatile loader_block * lb, | ||
1773 | const amb_dev * dev, loader_command cmd) { | ||
1774 | |||
1775 | unsigned long timeout; | ||
1776 | |||
1777 | PRINTD (DBG_FLOW|DBG_LOAD, "do_loader_command"); | ||
1778 | |||
1779 | /* do a command | ||
1780 | |||
1781 | Set the return value to zero, set the command type and set the | ||
1782 | valid entry to the right magic value. The payload is already | ||
1783 | correctly byte-ordered so we leave it alone. Hit the doorbell | ||
1784 | with the bus address of this structure. | ||
1785 | |||
1786 | */ | ||
1787 | |||
1788 | lb->result = 0; | ||
1789 | lb->command = cpu_to_be32 (cmd); | ||
1790 | lb->valid = cpu_to_be32 (DMA_VALID); | ||
1791 | // dump_registers (dev); | ||
1792 | // dump_loader_block (lb); | ||
1793 | wr_mem (dev, offsetof(amb_mem, doorbell), virt_to_bus (lb) & ~onegigmask); | ||
1794 | |||
1795 | timeout = command_timeouts[cmd] * 10; | ||
1796 | |||
1797 | while (!lb->result || lb->result == cpu_to_be32 (COMMAND_IN_PROGRESS)) | ||
1798 | if (timeout) { | ||
1799 | timeout = msleep_interruptible(timeout); | ||
1800 | } else { | ||
1801 | PRINTD (DBG_LOAD|DBG_ERR, "command %d timed out", cmd); | ||
1802 | dump_registers (dev); | ||
1803 | dump_loader_block (lb); | ||
1804 | return -ETIMEDOUT; | ||
1805 | } | ||
1806 | |||
1807 | if (cmd == adapter_start) { | ||
1808 | // wait for start command to acknowledge... | ||
1809 | timeout = 100; | ||
1810 | while (rd_plain (dev, offsetof(amb_mem, doorbell))) | ||
1811 | if (timeout) { | ||
1812 | timeout = msleep_interruptible(timeout); | ||
1813 | } else { | ||
1814 | PRINTD (DBG_LOAD|DBG_ERR, "start command did not clear doorbell, res=%08x", | ||
1815 | be32_to_cpu (lb->result)); | ||
1816 | dump_registers (dev); | ||
1817 | return -ETIMEDOUT; | ||
1818 | } | ||
1819 | return 0; | ||
1820 | } else { | ||
1821 | return decode_loader_result (cmd, be32_to_cpu (lb->result)); | ||
1822 | } | ||
1823 | |||
1824 | } | ||
1825 | |||
1826 | /* loader: determine loader version */ | ||
1827 | |||
1828 | static int __devinit get_loader_version (loader_block * lb, | ||
1829 | const amb_dev * dev, u32 * version) { | ||
1830 | int res; | ||
1831 | |||
1832 | PRINTD (DBG_FLOW|DBG_LOAD, "get_loader_version"); | ||
1833 | |||
1834 | res = do_loader_command (lb, dev, get_version_number); | ||
1835 | if (res) | ||
1836 | return res; | ||
1837 | if (version) | ||
1838 | *version = be32_to_cpu (lb->payload.version); | ||
1839 | return 0; | ||
1840 | } | ||
1841 | |||
1842 | /* loader: write memory data blocks */ | ||
1843 | |||
1844 | static int __devinit loader_write (loader_block * lb, | ||
1845 | const amb_dev * dev, const u32 * data, | ||
1846 | u32 address, unsigned int count) { | ||
1847 | unsigned int i; | ||
1848 | transfer_block * tb = &lb->payload.transfer; | ||
1849 | |||
1850 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_write"); | ||
1851 | |||
1852 | if (count > MAX_TRANSFER_DATA) | ||
1853 | return -EINVAL; | ||
1854 | tb->address = cpu_to_be32 (address); | ||
1855 | tb->count = cpu_to_be32 (count); | ||
1856 | for (i = 0; i < count; ++i) | ||
1857 | tb->data[i] = cpu_to_be32 (data[i]); | ||
1858 | return do_loader_command (lb, dev, write_adapter_memory); | ||
1859 | } | ||
1860 | |||
1861 | /* loader: verify memory data blocks */ | ||
1862 | |||
1863 | static int __devinit loader_verify (loader_block * lb, | ||
1864 | const amb_dev * dev, const u32 * data, | ||
1865 | u32 address, unsigned int count) { | ||
1866 | unsigned int i; | ||
1867 | transfer_block * tb = &lb->payload.transfer; | ||
1868 | int res; | ||
1869 | |||
1870 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_verify"); | ||
1871 | |||
1872 | if (count > MAX_TRANSFER_DATA) | ||
1873 | return -EINVAL; | ||
1874 | tb->address = cpu_to_be32 (address); | ||
1875 | tb->count = cpu_to_be32 (count); | ||
1876 | res = do_loader_command (lb, dev, read_adapter_memory); | ||
1877 | if (!res) | ||
1878 | for (i = 0; i < count; ++i) | ||
1879 | if (tb->data[i] != cpu_to_be32 (data[i])) { | ||
1880 | res = -EINVAL; | ||
1881 | break; | ||
1882 | } | ||
1883 | return res; | ||
1884 | } | ||
1885 | |||
1886 | /* loader: start microcode */ | ||
1887 | |||
1888 | static int __devinit loader_start (loader_block * lb, | ||
1889 | const amb_dev * dev, u32 address) { | ||
1890 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_start"); | ||
1891 | |||
1892 | lb->payload.start = cpu_to_be32 (address); | ||
1893 | return do_loader_command (lb, dev, adapter_start); | ||
1894 | } | ||
1895 | |||
1896 | /********** reset card **********/ | ||
1897 | |||
1898 | static inline void sf (const char * msg) | ||
1899 | { | ||
1900 | PRINTK (KERN_ERR, "self-test failed: %s", msg); | ||
1901 | } | ||
1902 | |||
1903 | static int amb_reset (amb_dev * dev, int diags) { | ||
1904 | u32 word; | ||
1905 | |||
1906 | PRINTD (DBG_FLOW|DBG_LOAD, "amb_reset"); | ||
1907 | |||
1908 | word = rd_plain (dev, offsetof(amb_mem, reset_control)); | ||
1909 | // put card into reset state | ||
1910 | wr_plain (dev, offsetof(amb_mem, reset_control), word | AMB_RESET_BITS); | ||
1911 | // wait a short while | ||
1912 | udelay (10); | ||
1913 | #if 1 | ||
1914 | // put card into known good state | ||
1915 | wr_plain (dev, offsetof(amb_mem, interrupt_control), AMB_DOORBELL_BITS); | ||
1916 | // clear all interrupts just in case | ||
1917 | wr_plain (dev, offsetof(amb_mem, interrupt), -1); | ||
1918 | #endif | ||
1919 | // clear self-test done flag | ||
1920 | wr_plain (dev, offsetof(amb_mem, mb.loader.ready), 0); | ||
1921 | // take card out of reset state | ||
1922 | wr_plain (dev, offsetof(amb_mem, reset_control), word &~ AMB_RESET_BITS); | ||
1923 | |||
1924 | if (diags) { | ||
1925 | unsigned long timeout; | ||
1926 | // 4.2 second wait | ||
1927 | msleep(4200); | ||
1928 | // half second time-out | ||
1929 | timeout = 500; | ||
1930 | while (!rd_plain (dev, offsetof(amb_mem, mb.loader.ready))) | ||
1931 | if (timeout) { | ||
1932 | timeout = msleep_interruptible(timeout); | ||
1933 | } else { | ||
1934 | PRINTD (DBG_LOAD|DBG_ERR, "reset timed out"); | ||
1935 | return -ETIMEDOUT; | ||
1936 | } | ||
1937 | |||
1938 | // get results of self-test | ||
1939 | // XXX double check byte-order | ||
1940 | word = rd_mem (dev, offsetof(amb_mem, mb.loader.result)); | ||
1941 | if (word & SELF_TEST_FAILURE) { | ||
1942 | if (word & GPINT_TST_FAILURE) | ||
1943 | sf ("interrupt"); | ||
1944 | if (word & SUNI_DATA_PATTERN_FAILURE) | ||
1945 | sf ("SUNI data pattern"); | ||
1946 | if (word & SUNI_DATA_BITS_FAILURE) | ||
1947 | sf ("SUNI data bits"); | ||
1948 | if (word & SUNI_UTOPIA_FAILURE) | ||
1949 | sf ("SUNI UTOPIA interface"); | ||
1950 | if (word & SUNI_FIFO_FAILURE) | ||
1951 | sf ("SUNI cell buffer FIFO"); | ||
1952 | if (word & SRAM_FAILURE) | ||
1953 | sf ("bad SRAM"); | ||
1954 | // better return value? | ||
1955 | return -EIO; | ||
1956 | } | ||
1957 | |||
1958 | } | ||
1959 | return 0; | ||
1960 | } | ||
1961 | |||
1962 | /********** transfer and start the microcode **********/ | ||
1963 | |||
1964 | static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { | ||
1965 | unsigned int i = 0; | ||
1966 | unsigned int total = 0; | ||
1967 | const u32 * pointer = ucode_data; | ||
1968 | u32 address; | ||
1969 | unsigned int count; | ||
1970 | int res; | ||
1971 | |||
1972 | PRINTD (DBG_FLOW|DBG_LOAD, "ucode_init"); | ||
1973 | |||
1974 | while (address = ucode_regions[i].start, | ||
1975 | count = ucode_regions[i].count) { | ||
1976 | PRINTD (DBG_LOAD, "starting region (%x, %u)", address, count); | ||
1977 | while (count) { | ||
1978 | unsigned int words; | ||
1979 | if (count <= MAX_TRANSFER_DATA) | ||
1980 | words = count; | ||
1981 | else | ||
1982 | words = MAX_TRANSFER_DATA; | ||
1983 | total += words; | ||
1984 | res = loader_write (lb, dev, pointer, address, words); | ||
1985 | if (res) | ||
1986 | return res; | ||
1987 | res = loader_verify (lb, dev, pointer, address, words); | ||
1988 | if (res) | ||
1989 | return res; | ||
1990 | count -= words; | ||
1991 | address += sizeof(u32) * words; | ||
1992 | pointer += words; | ||
1993 | } | ||
1994 | i += 1; | ||
1995 | } | ||
1996 | if (*pointer == 0xdeadbeef) { | ||
1997 | return loader_start (lb, dev, ucode_start); | ||
1998 | } else { | ||
1999 | // cast needed as there is no %? for pointer differnces | ||
2000 | PRINTD (DBG_LOAD|DBG_ERR, | ||
2001 | "offset=%li, *pointer=%x, address=%x, total=%u", | ||
2002 | (long) (pointer - ucode_data), *pointer, address, total); | ||
2003 | PRINTK (KERN_ERR, "incorrect microcode data"); | ||
2004 | return -ENOMEM; | ||
2005 | } | ||
2006 | } | ||
2007 | |||
2008 | /********** give adapter parameters **********/ | ||
2009 | |||
2010 | static inline __be32 bus_addr(void * addr) { | ||
2011 | return cpu_to_be32 (virt_to_bus (addr)); | ||
2012 | } | ||
2013 | |||
2014 | static int __devinit amb_talk (amb_dev * dev) { | ||
2015 | adap_talk_block a; | ||
2016 | unsigned char pool; | ||
2017 | unsigned long timeout; | ||
2018 | |||
2019 | PRINTD (DBG_FLOW, "amb_talk %p", dev); | ||
2020 | |||
2021 | a.command_start = bus_addr (dev->cq.ptrs.start); | ||
2022 | a.command_end = bus_addr (dev->cq.ptrs.limit); | ||
2023 | a.tx_start = bus_addr (dev->txq.in.start); | ||
2024 | a.tx_end = bus_addr (dev->txq.in.limit); | ||
2025 | a.txcom_start = bus_addr (dev->txq.out.start); | ||
2026 | a.txcom_end = bus_addr (dev->txq.out.limit); | ||
2027 | |||
2028 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) { | ||
2029 | // the other "a" items are set up by the adapter | ||
2030 | a.rec_struct[pool].buffer_start = bus_addr (dev->rxq[pool].in.start); | ||
2031 | a.rec_struct[pool].buffer_end = bus_addr (dev->rxq[pool].in.limit); | ||
2032 | a.rec_struct[pool].rx_start = bus_addr (dev->rxq[pool].out.start); | ||
2033 | a.rec_struct[pool].rx_end = bus_addr (dev->rxq[pool].out.limit); | ||
2034 | a.rec_struct[pool].buffer_size = cpu_to_be32 (dev->rxq[pool].buffer_size); | ||
2035 | } | ||
2036 | |||
2037 | #ifdef AMB_NEW_MICROCODE | ||
2038 | // disable fast PLX prefetching | ||
2039 | a.init_flags = 0; | ||
2040 | #endif | ||
2041 | |||
2042 | // pass the structure | ||
2043 | wr_mem (dev, offsetof(amb_mem, doorbell), virt_to_bus (&a)); | ||
2044 | |||
2045 | // 2.2 second wait (must not touch doorbell during 2 second DMA test) | ||
2046 | msleep(2200); | ||
2047 | // give the adapter another half second? | ||
2048 | timeout = 500; | ||
2049 | while (rd_plain (dev, offsetof(amb_mem, doorbell))) | ||
2050 | if (timeout) { | ||
2051 | timeout = msleep_interruptible(timeout); | ||
2052 | } else { | ||
2053 | PRINTD (DBG_INIT|DBG_ERR, "adapter init timed out"); | ||
2054 | return -ETIMEDOUT; | ||
2055 | } | ||
2056 | |||
2057 | return 0; | ||
2058 | } | ||
2059 | |||
2060 | // get microcode version | ||
2061 | static void __devinit amb_ucode_version (amb_dev * dev) { | ||
2062 | u32 major; | ||
2063 | u32 minor; | ||
2064 | command cmd; | ||
2065 | cmd.request = cpu_to_be32 (SRB_GET_VERSION); | ||
2066 | while (command_do (dev, &cmd)) { | ||
2067 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2068 | schedule(); | ||
2069 | } | ||
2070 | major = be32_to_cpu (cmd.args.version.major); | ||
2071 | minor = be32_to_cpu (cmd.args.version.minor); | ||
2072 | PRINTK (KERN_INFO, "microcode version is %u.%u", major, minor); | ||
2073 | } | ||
2074 | |||
2075 | // swap bits within byte to get Ethernet ordering | ||
2076 | static u8 bit_swap (u8 byte) | ||
2077 | { | ||
2078 | const u8 swap[] = { | ||
2079 | 0x0, 0x8, 0x4, 0xc, | ||
2080 | 0x2, 0xa, 0x6, 0xe, | ||
2081 | 0x1, 0x9, 0x5, 0xd, | ||
2082 | 0x3, 0xb, 0x7, 0xf | ||
2083 | }; | ||
2084 | return ((swap[byte & 0xf]<<4) | swap[byte>>4]); | ||
2085 | } | ||
2086 | |||
2087 | // get end station address | ||
2088 | static void __devinit amb_esi (amb_dev * dev, u8 * esi) { | ||
2089 | u32 lower4; | ||
2090 | u16 upper2; | ||
2091 | command cmd; | ||
2092 | |||
2093 | cmd.request = cpu_to_be32 (SRB_GET_BIA); | ||
2094 | while (command_do (dev, &cmd)) { | ||
2095 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2096 | schedule(); | ||
2097 | } | ||
2098 | lower4 = be32_to_cpu (cmd.args.bia.lower4); | ||
2099 | upper2 = be32_to_cpu (cmd.args.bia.upper2); | ||
2100 | PRINTD (DBG_LOAD, "BIA: lower4: %08x, upper2 %04x", lower4, upper2); | ||
2101 | |||
2102 | if (esi) { | ||
2103 | unsigned int i; | ||
2104 | |||
2105 | PRINTDB (DBG_INIT, "ESI:"); | ||
2106 | for (i = 0; i < ESI_LEN; ++i) { | ||
2107 | if (i < 4) | ||
2108 | esi[i] = bit_swap (lower4>>(8*i)); | ||
2109 | else | ||
2110 | esi[i] = bit_swap (upper2>>(8*(i-4))); | ||
2111 | PRINTDM (DBG_INIT, " %02x", esi[i]); | ||
2112 | } | ||
2113 | |||
2114 | PRINTDE (DBG_INIT, ""); | ||
2115 | } | ||
2116 | |||
2117 | return; | ||
2118 | } | ||
2119 | |||
2120 | static void fixup_plx_window (amb_dev *dev, loader_block *lb) | ||
2121 | { | ||
2122 | // fix up the PLX-mapped window base address to match the block | ||
2123 | unsigned long blb; | ||
2124 | u32 mapreg; | ||
2125 | blb = virt_to_bus(lb); | ||
2126 | // the kernel stack had better not ever cross a 1Gb boundary! | ||
2127 | mapreg = rd_plain (dev, offsetof(amb_mem, stuff[10])); | ||
2128 | mapreg &= ~onegigmask; | ||
2129 | mapreg |= blb & onegigmask; | ||
2130 | wr_plain (dev, offsetof(amb_mem, stuff[10]), mapreg); | ||
2131 | return; | ||
2132 | } | ||
2133 | |||
2134 | static int __devinit amb_init (amb_dev * dev) | ||
2135 | { | ||
2136 | loader_block lb; | ||
2137 | |||
2138 | u32 version; | ||
2139 | |||
2140 | if (amb_reset (dev, 1)) { | ||
2141 | PRINTK (KERN_ERR, "card reset failed!"); | ||
2142 | } else { | ||
2143 | fixup_plx_window (dev, &lb); | ||
2144 | |||
2145 | if (get_loader_version (&lb, dev, &version)) { | ||
2146 | PRINTK (KERN_INFO, "failed to get loader version"); | ||
2147 | } else { | ||
2148 | PRINTK (KERN_INFO, "loader version is %08x", version); | ||
2149 | |||
2150 | if (ucode_init (&lb, dev)) { | ||
2151 | PRINTK (KERN_ERR, "microcode failure"); | ||
2152 | } else if (create_queues (dev, cmds, txs, rxs, rxs_bs)) { | ||
2153 | PRINTK (KERN_ERR, "failed to get memory for queues"); | ||
2154 | } else { | ||
2155 | |||
2156 | if (amb_talk (dev)) { | ||
2157 | PRINTK (KERN_ERR, "adapter did not accept queues"); | ||
2158 | } else { | ||
2159 | |||
2160 | amb_ucode_version (dev); | ||
2161 | return 0; | ||
2162 | |||
2163 | } /* amb_talk */ | ||
2164 | |||
2165 | destroy_queues (dev); | ||
2166 | } /* create_queues, ucode_init */ | ||
2167 | |||
2168 | amb_reset (dev, 0); | ||
2169 | } /* get_loader_version */ | ||
2170 | |||
2171 | } /* amb_reset */ | ||
2172 | |||
2173 | return -EINVAL; | ||
2174 | } | ||
2175 | |||
2176 | static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev) | ||
2177 | { | ||
2178 | unsigned char pool; | ||
2179 | memset (dev, 0, sizeof(amb_dev)); | ||
2180 | |||
2181 | // set up known dev items straight away | ||
2182 | dev->pci_dev = pci_dev; | ||
2183 | pci_set_drvdata(pci_dev, dev); | ||
2184 | |||
2185 | dev->iobase = pci_resource_start (pci_dev, 1); | ||
2186 | dev->irq = pci_dev->irq; | ||
2187 | dev->membase = bus_to_virt(pci_resource_start(pci_dev, 0)); | ||
2188 | |||
2189 | // flags (currently only dead) | ||
2190 | dev->flags = 0; | ||
2191 | |||
2192 | // Allocate cell rates (fibre) | ||
2193 | // ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53 | ||
2194 | // to be really pedantic, this should be ATM_OC3c_PCR | ||
2195 | dev->tx_avail = ATM_OC3_PCR; | ||
2196 | dev->rx_avail = ATM_OC3_PCR; | ||
2197 | |||
2198 | #ifdef FILL_RX_POOLS_IN_BH | ||
2199 | // initialise bottom half | ||
2200 | INIT_WORK(&dev->bh, (void (*)(void *)) fill_rx_pools, dev); | ||
2201 | #endif | ||
2202 | |||
2203 | // semaphore for txer/rxer modifications - we cannot use a | ||
2204 | // spinlock as the critical region needs to switch processes | ||
2205 | init_MUTEX (&dev->vcc_sf); | ||
2206 | // queue manipulation spinlocks; we want atomic reads and | ||
2207 | // writes to the queue descriptors (handles IRQ and SMP) | ||
2208 | // consider replacing "int pending" -> "atomic_t available" | ||
2209 | // => problem related to who gets to move queue pointers | ||
2210 | spin_lock_init (&dev->cq.lock); | ||
2211 | spin_lock_init (&dev->txq.lock); | ||
2212 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
2213 | spin_lock_init (&dev->rxq[pool].lock); | ||
2214 | } | ||
2215 | |||
2216 | static void setup_pci_dev(struct pci_dev *pci_dev) | ||
2217 | { | ||
2218 | unsigned char lat; | ||
2219 | |||
2220 | // enable bus master accesses | ||
2221 | pci_set_master(pci_dev); | ||
2222 | |||
2223 | // frobnicate latency (upwards, usually) | ||
2224 | pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &lat); | ||
2225 | |||
2226 | if (!pci_lat) | ||
2227 | pci_lat = (lat < MIN_PCI_LATENCY) ? MIN_PCI_LATENCY : lat; | ||
2228 | |||
2229 | if (lat != pci_lat) { | ||
2230 | PRINTK (KERN_INFO, "Changing PCI latency timer from %hu to %hu", | ||
2231 | lat, pci_lat); | ||
2232 | pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat); | ||
2233 | } | ||
2234 | } | ||
2235 | |||
2236 | static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | ||
2237 | { | ||
2238 | amb_dev * dev; | ||
2239 | int err; | ||
2240 | unsigned int irq; | ||
2241 | |||
2242 | err = pci_enable_device(pci_dev); | ||
2243 | if (err < 0) { | ||
2244 | PRINTK (KERN_ERR, "skipped broken (PLX rev 2) card"); | ||
2245 | goto out; | ||
2246 | } | ||
2247 | |||
2248 | // read resources from PCI configuration space | ||
2249 | irq = pci_dev->irq; | ||
2250 | |||
2251 | if (pci_dev->device == PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD) { | ||
2252 | PRINTK (KERN_ERR, "skipped broken (PLX rev 2) card"); | ||
2253 | err = -EINVAL; | ||
2254 | goto out_disable; | ||
2255 | } | ||
2256 | |||
2257 | PRINTD (DBG_INFO, "found Madge ATM adapter (amb) at" | ||
2258 | " IO %lx, IRQ %u, MEM %p", pci_resource_start(pci_dev, 1), | ||
2259 | irq, bus_to_virt(pci_resource_start(pci_dev, 0))); | ||
2260 | |||
2261 | // check IO region | ||
2262 | err = pci_request_region(pci_dev, 1, DEV_LABEL); | ||
2263 | if (err < 0) { | ||
2264 | PRINTK (KERN_ERR, "IO range already in use!"); | ||
2265 | goto out_disable; | ||
2266 | } | ||
2267 | |||
2268 | dev = kmalloc (sizeof(amb_dev), GFP_KERNEL); | ||
2269 | if (!dev) { | ||
2270 | PRINTK (KERN_ERR, "out of memory!"); | ||
2271 | err = -ENOMEM; | ||
2272 | goto out_release; | ||
2273 | } | ||
2274 | |||
2275 | setup_dev(dev, pci_dev); | ||
2276 | |||
2277 | err = amb_init(dev); | ||
2278 | if (err < 0) { | ||
2279 | PRINTK (KERN_ERR, "adapter initialisation failure"); | ||
2280 | goto out_free; | ||
2281 | } | ||
2282 | |||
2283 | setup_pci_dev(pci_dev); | ||
2284 | |||
2285 | // grab (but share) IRQ and install handler | ||
2286 | err = request_irq(irq, interrupt_handler, SA_SHIRQ, DEV_LABEL, dev); | ||
2287 | if (err < 0) { | ||
2288 | PRINTK (KERN_ERR, "request IRQ failed!"); | ||
2289 | goto out_reset; | ||
2290 | } | ||
2291 | |||
2292 | dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL); | ||
2293 | if (!dev->atm_dev) { | ||
2294 | PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); | ||
2295 | err = -EINVAL; | ||
2296 | goto out_free_irq; | ||
2297 | } | ||
2298 | |||
2299 | PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", | ||
2300 | dev->atm_dev->number, dev, dev->atm_dev); | ||
2301 | dev->atm_dev->dev_data = (void *) dev; | ||
2302 | |||
2303 | // register our address | ||
2304 | amb_esi (dev, dev->atm_dev->esi); | ||
2305 | |||
2306 | // 0 bits for vpi, 10 bits for vci | ||
2307 | dev->atm_dev->ci_range.vpi_bits = NUM_VPI_BITS; | ||
2308 | dev->atm_dev->ci_range.vci_bits = NUM_VCI_BITS; | ||
2309 | |||
2310 | init_timer(&dev->housekeeping); | ||
2311 | dev->housekeeping.function = do_housekeeping; | ||
2312 | dev->housekeeping.data = (unsigned long) dev; | ||
2313 | mod_timer(&dev->housekeeping, jiffies); | ||
2314 | |||
2315 | // enable host interrupts | ||
2316 | interrupts_on (dev); | ||
2317 | |||
2318 | out: | ||
2319 | return err; | ||
2320 | |||
2321 | out_free_irq: | ||
2322 | free_irq(irq, dev); | ||
2323 | out_reset: | ||
2324 | amb_reset(dev, 0); | ||
2325 | out_free: | ||
2326 | kfree(dev); | ||
2327 | out_release: | ||
2328 | pci_release_region(pci_dev, 1); | ||
2329 | out_disable: | ||
2330 | pci_disable_device(pci_dev); | ||
2331 | goto out; | ||
2332 | } | ||
2333 | |||
2334 | |||
2335 | static void __devexit amb_remove_one(struct pci_dev *pci_dev) | ||
2336 | { | ||
2337 | struct amb_dev *dev; | ||
2338 | |||
2339 | dev = pci_get_drvdata(pci_dev); | ||
2340 | |||
2341 | PRINTD(DBG_INFO|DBG_INIT, "closing %p (atm_dev = %p)", dev, dev->atm_dev); | ||
2342 | del_timer_sync(&dev->housekeeping); | ||
2343 | // the drain should not be necessary | ||
2344 | drain_rx_pools(dev); | ||
2345 | interrupts_off(dev); | ||
2346 | amb_reset(dev, 0); | ||
2347 | free_irq(dev->irq, dev); | ||
2348 | pci_disable_device(pci_dev); | ||
2349 | destroy_queues(dev); | ||
2350 | atm_dev_deregister(dev->atm_dev); | ||
2351 | kfree(dev); | ||
2352 | pci_release_region(pci_dev, 1); | ||
2353 | } | ||
2354 | |||
2355 | static void __init amb_check_args (void) { | ||
2356 | unsigned char pool; | ||
2357 | unsigned int max_rx_size; | ||
2358 | |||
2359 | #ifdef DEBUG_AMBASSADOR | ||
2360 | PRINTK (KERN_NOTICE, "debug bitmap is %hx", debug &= DBG_MASK); | ||
2361 | #else | ||
2362 | if (debug) | ||
2363 | PRINTK (KERN_NOTICE, "no debugging support"); | ||
2364 | #endif | ||
2365 | |||
2366 | if (cmds < MIN_QUEUE_SIZE) | ||
2367 | PRINTK (KERN_NOTICE, "cmds has been raised to %u", | ||
2368 | cmds = MIN_QUEUE_SIZE); | ||
2369 | |||
2370 | if (txs < MIN_QUEUE_SIZE) | ||
2371 | PRINTK (KERN_NOTICE, "txs has been raised to %u", | ||
2372 | txs = MIN_QUEUE_SIZE); | ||
2373 | |||
2374 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
2375 | if (rxs[pool] < MIN_QUEUE_SIZE) | ||
2376 | PRINTK (KERN_NOTICE, "rxs[%hu] has been raised to %u", | ||
2377 | pool, rxs[pool] = MIN_QUEUE_SIZE); | ||
2378 | |||
2379 | // buffers sizes should be greater than zero and strictly increasing | ||
2380 | max_rx_size = 0; | ||
2381 | for (pool = 0; pool < NUM_RX_POOLS; ++pool) | ||
2382 | if (rxs_bs[pool] <= max_rx_size) | ||
2383 | PRINTK (KERN_NOTICE, "useless pool (rxs_bs[%hu] = %u)", | ||
2384 | pool, rxs_bs[pool]); | ||
2385 | else | ||
2386 | max_rx_size = rxs_bs[pool]; | ||
2387 | |||
2388 | if (rx_lats < MIN_RX_BUFFERS) | ||
2389 | PRINTK (KERN_NOTICE, "rx_lats has been raised to %u", | ||
2390 | rx_lats = MIN_RX_BUFFERS); | ||
2391 | |||
2392 | return; | ||
2393 | } | ||
2394 | |||
2395 | /********** module stuff **********/ | ||
2396 | |||
2397 | MODULE_AUTHOR(maintainer_string); | ||
2398 | MODULE_DESCRIPTION(description_string); | ||
2399 | MODULE_LICENSE("GPL"); | ||
2400 | module_param(debug, ushort, 0644); | ||
2401 | module_param(cmds, uint, 0); | ||
2402 | module_param(txs, uint, 0); | ||
2403 | module_param_array(rxs, uint, NULL, 0); | ||
2404 | module_param_array(rxs_bs, uint, NULL, 0); | ||
2405 | module_param(rx_lats, uint, 0); | ||
2406 | module_param(pci_lat, byte, 0); | ||
2407 | MODULE_PARM_DESC(debug, "debug bitmap, see .h file"); | ||
2408 | MODULE_PARM_DESC(cmds, "number of command queue entries"); | ||
2409 | MODULE_PARM_DESC(txs, "number of TX queue entries"); | ||
2410 | MODULE_PARM_DESC(rxs, "number of RX queue entries [" __MODULE_STRING(NUM_RX_POOLS) "]"); | ||
2411 | MODULE_PARM_DESC(rxs_bs, "size of RX buffers [" __MODULE_STRING(NUM_RX_POOLS) "]"); | ||
2412 | MODULE_PARM_DESC(rx_lats, "number of extra buffers to cope with RX latencies"); | ||
2413 | MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); | ||
2414 | |||
2415 | /********** module entry **********/ | ||
2416 | |||
2417 | static struct pci_device_id amb_pci_tbl[] = { | ||
2418 | { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR, PCI_ANY_ID, PCI_ANY_ID, | ||
2419 | 0, 0, 0 }, | ||
2420 | { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD, PCI_ANY_ID, PCI_ANY_ID, | ||
2421 | 0, 0, 0 }, | ||
2422 | { 0, } | ||
2423 | }; | ||
2424 | |||
2425 | MODULE_DEVICE_TABLE(pci, amb_pci_tbl); | ||
2426 | |||
2427 | static struct pci_driver amb_driver = { | ||
2428 | .name = "amb", | ||
2429 | .probe = amb_probe, | ||
2430 | .remove = __devexit_p(amb_remove_one), | ||
2431 | .id_table = amb_pci_tbl, | ||
2432 | }; | ||
2433 | |||
2434 | static int __init amb_module_init (void) | ||
2435 | { | ||
2436 | PRINTD (DBG_FLOW|DBG_INIT, "init_module"); | ||
2437 | |||
2438 | // sanity check - cast needed as printk does not support %Zu | ||
2439 | if (sizeof(amb_mem) != 4*16 + 4*12) { | ||
2440 | PRINTK (KERN_ERR, "Fix amb_mem (is %lu words).", | ||
2441 | (unsigned long) sizeof(amb_mem)); | ||
2442 | return -ENOMEM; | ||
2443 | } | ||
2444 | |||
2445 | show_version(); | ||
2446 | |||
2447 | amb_check_args(); | ||
2448 | |||
2449 | // get the juice | ||
2450 | return pci_register_driver(&amb_driver); | ||
2451 | } | ||
2452 | |||
2453 | /********** module exit **********/ | ||
2454 | |||
2455 | static void __exit amb_module_exit (void) | ||
2456 | { | ||
2457 | PRINTD (DBG_FLOW|DBG_INIT, "cleanup_module"); | ||
2458 | |||
2459 | return pci_unregister_driver(&amb_driver); | ||
2460 | } | ||
2461 | |||
2462 | module_init(amb_module_init); | ||
2463 | module_exit(amb_module_exit); | ||
diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h new file mode 100644 index 000000000000..84a93063cfe1 --- /dev/null +++ b/drivers/atm/ambassador.h | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | Madge Ambassador ATM Adapter driver. | ||
3 | Copyright (C) 1995-1999 Madge Networks Ltd. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian | ||
20 | system and in the file COPYING in the Linux kernel source. | ||
21 | */ | ||
22 | |||
23 | #ifndef AMBASSADOR_H | ||
24 | #define AMBASSADOR_H | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | |||
28 | #ifdef CONFIG_ATM_AMBASSADOR_DEBUG | ||
29 | #define DEBUG_AMBASSADOR | ||
30 | #endif | ||
31 | |||
32 | #define DEV_LABEL "amb" | ||
33 | |||
34 | #ifndef PCI_VENDOR_ID_MADGE | ||
35 | #define PCI_VENDOR_ID_MADGE 0x10B6 | ||
36 | #endif | ||
37 | #ifndef PCI_VENDOR_ID_MADGE_AMBASSADOR | ||
38 | #define PCI_DEVICE_ID_MADGE_AMBASSADOR 0x1001 | ||
39 | #endif | ||
40 | #ifndef PCI_VENDOR_ID_MADGE_AMBASSADOR_BAD | ||
41 | #define PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD 0x1002 | ||
42 | #endif | ||
43 | |||
44 | // diagnostic output | ||
45 | |||
46 | #define PRINTK(severity,format,args...) \ | ||
47 | printk(severity DEV_LABEL ": " format "\n" , ## args) | ||
48 | |||
49 | #ifdef DEBUG_AMBASSADOR | ||
50 | |||
51 | #define DBG_ERR 0x0001 | ||
52 | #define DBG_WARN 0x0002 | ||
53 | #define DBG_INFO 0x0004 | ||
54 | #define DBG_INIT 0x0008 | ||
55 | #define DBG_LOAD 0x0010 | ||
56 | #define DBG_VCC 0x0020 | ||
57 | #define DBG_QOS 0x0040 | ||
58 | #define DBG_CMD 0x0080 | ||
59 | #define DBG_TX 0x0100 | ||
60 | #define DBG_RX 0x0200 | ||
61 | #define DBG_SKB 0x0400 | ||
62 | #define DBG_POOL 0x0800 | ||
63 | #define DBG_IRQ 0x1000 | ||
64 | #define DBG_FLOW 0x2000 | ||
65 | #define DBG_REGS 0x4000 | ||
66 | #define DBG_DATA 0x8000 | ||
67 | #define DBG_MASK 0xffff | ||
68 | |||
69 | /* the ## prevents the annoying double expansion of the macro arguments */ | ||
70 | /* KERN_INFO is used since KERN_DEBUG often does not make it to the console */ | ||
71 | #define PRINTDB(bits,format,args...) \ | ||
72 | ( (debug & (bits)) ? printk (KERN_INFO DEV_LABEL ": " format , ## args) : 1 ) | ||
73 | #define PRINTDM(bits,format,args...) \ | ||
74 | ( (debug & (bits)) ? printk (format , ## args) : 1 ) | ||
75 | #define PRINTDE(bits,format,args...) \ | ||
76 | ( (debug & (bits)) ? printk (format "\n" , ## args) : 1 ) | ||
77 | #define PRINTD(bits,format,args...) \ | ||
78 | ( (debug & (bits)) ? printk (KERN_INFO DEV_LABEL ": " format "\n" , ## args) : 1 ) | ||
79 | |||
80 | #else | ||
81 | |||
82 | #define PRINTD(bits,format,args...) | ||
83 | #define PRINTDB(bits,format,args...) | ||
84 | #define PRINTDM(bits,format,args...) | ||
85 | #define PRINTDE(bits,format,args...) | ||
86 | |||
87 | #endif | ||
88 | |||
89 | #define PRINTDD(bits,format,args...) | ||
90 | #define PRINTDDB(sec,fmt,args...) | ||
91 | #define PRINTDDM(sec,fmt,args...) | ||
92 | #define PRINTDDE(sec,fmt,args...) | ||
93 | |||
94 | // tunable values (?) | ||
95 | |||
96 | /* MUST be powers of two -- why ? */ | ||
97 | #define COM_Q_ENTRIES 8 | ||
98 | #define TX_Q_ENTRIES 32 | ||
99 | #define RX_Q_ENTRIES 64 | ||
100 | |||
101 | // fixed values | ||
102 | |||
103 | // guessing | ||
104 | #define AMB_EXTENT 0x80 | ||
105 | |||
106 | // Minimum allowed size for an Ambassador queue | ||
107 | #define MIN_QUEUE_SIZE 2 | ||
108 | |||
109 | // Ambassador microcode allows 1 to 4 pools, we use 4 (simpler) | ||
110 | #define NUM_RX_POOLS 4 | ||
111 | |||
112 | // minimum RX buffers required to cope with replenishing delay | ||
113 | #define MIN_RX_BUFFERS 1 | ||
114 | |||
115 | // minimum PCI latency we will tolerate (32 IS TOO SMALL) | ||
116 | #define MIN_PCI_LATENCY 64 // 255 | ||
117 | |||
118 | // VCs supported by card (VPI always 0) | ||
119 | #define NUM_VPI_BITS 0 | ||
120 | #define NUM_VCI_BITS 10 | ||
121 | #define NUM_VCS 1024 | ||
122 | |||
123 | /* The status field bits defined so far. */ | ||
124 | #define RX_ERR 0x8000 // always present if there is an error (hmm) | ||
125 | #define CRC_ERR 0x4000 // AAL5 CRC error | ||
126 | #define LEN_ERR 0x2000 // overlength frame | ||
127 | #define ABORT_ERR 0x1000 // zero length field in received frame | ||
128 | #define UNUSED_ERR 0x0800 // buffer returned unused | ||
129 | |||
130 | // Adaptor commands | ||
131 | |||
132 | #define SRB_OPEN_VC 0 | ||
133 | /* par_0: dwordswap(VC_number) */ | ||
134 | /* par_1: dwordswap(flags<<16) or wordswap(flags)*/ | ||
135 | /* flags: */ | ||
136 | |||
137 | /* LANE: 0x0004 */ | ||
138 | /* NOT_UBR: 0x0008 */ | ||
139 | /* ABR: 0x0010 */ | ||
140 | |||
141 | /* RxPool0: 0x0000 */ | ||
142 | /* RxPool1: 0x0020 */ | ||
143 | /* RxPool2: 0x0040 */ | ||
144 | /* RxPool3: 0x0060 */ | ||
145 | |||
146 | /* par_2: dwordswap(fp_rate<<16) or wordswap(fp_rate) */ | ||
147 | |||
148 | #define SRB_CLOSE_VC 1 | ||
149 | /* par_0: dwordswap(VC_number) */ | ||
150 | |||
151 | #define SRB_GET_BIA 2 | ||
152 | /* returns */ | ||
153 | /* par_0: dwordswap(half BIA) */ | ||
154 | /* par_1: dwordswap(half BIA) */ | ||
155 | |||
156 | #define SRB_GET_SUNI_STATS 3 | ||
157 | /* par_0: dwordswap(physical_host_address) */ | ||
158 | |||
159 | #define SRB_SET_BITS_8 4 | ||
160 | #define SRB_SET_BITS_16 5 | ||
161 | #define SRB_SET_BITS_32 6 | ||
162 | #define SRB_CLEAR_BITS_8 7 | ||
163 | #define SRB_CLEAR_BITS_16 8 | ||
164 | #define SRB_CLEAR_BITS_32 9 | ||
165 | /* par_0: dwordswap(ATMizer address) */ | ||
166 | /* par_1: dwordswap(mask) */ | ||
167 | |||
168 | #define SRB_SET_8 10 | ||
169 | #define SRB_SET_16 11 | ||
170 | #define SRB_SET_32 12 | ||
171 | /* par_0: dwordswap(ATMizer address) */ | ||
172 | /* par_1: dwordswap(data) */ | ||
173 | |||
174 | #define SRB_GET_32 13 | ||
175 | /* par_0: dwordswap(ATMizer address) */ | ||
176 | /* returns */ | ||
177 | /* par_1: dwordswap(ATMizer data) */ | ||
178 | |||
179 | #define SRB_GET_VERSION 14 | ||
180 | /* returns */ | ||
181 | /* par_0: dwordswap(Major Version) */ | ||
182 | /* par_1: dwordswap(Minor Version) */ | ||
183 | |||
184 | #define SRB_FLUSH_BUFFER_Q 15 | ||
185 | /* Only flags to define which buffer pool; all others must be zero */ | ||
186 | /* par_0: dwordswap(flags<<16) or wordswap(flags)*/ | ||
187 | |||
188 | #define SRB_GET_DMA_SPEEDS 16 | ||
189 | /* returns */ | ||
190 | /* par_0: dwordswap(Read speed (bytes/sec)) */ | ||
191 | /* par_1: dwordswap(Write speed (bytes/sec)) */ | ||
192 | |||
193 | #define SRB_MODIFY_VC_RATE 17 | ||
194 | /* par_0: dwordswap(VC_number) */ | ||
195 | /* par_1: dwordswap(fp_rate<<16) or wordswap(fp_rate) */ | ||
196 | |||
197 | #define SRB_MODIFY_VC_FLAGS 18 | ||
198 | /* par_0: dwordswap(VC_number) */ | ||
199 | /* par_1: dwordswap(flags<<16) or wordswap(flags)*/ | ||
200 | |||
201 | /* flags: */ | ||
202 | |||
203 | /* LANE: 0x0004 */ | ||
204 | /* NOT_UBR: 0x0008 */ | ||
205 | /* ABR: 0x0010 */ | ||
206 | |||
207 | /* RxPool0: 0x0000 */ | ||
208 | /* RxPool1: 0x0020 */ | ||
209 | /* RxPool2: 0x0040 */ | ||
210 | /* RxPool3: 0x0060 */ | ||
211 | |||
212 | #define SRB_RATE_SHIFT 16 | ||
213 | #define SRB_POOL_SHIFT (SRB_FLAGS_SHIFT+5) | ||
214 | #define SRB_FLAGS_SHIFT 16 | ||
215 | |||
216 | #define SRB_STOP_TASKING 19 | ||
217 | #define SRB_START_TASKING 20 | ||
218 | #define SRB_SHUT_DOWN 21 | ||
219 | #define MAX_SRB 21 | ||
220 | |||
221 | #define SRB_COMPLETE 0xffffffff | ||
222 | |||
223 | #define TX_FRAME 0x80000000 | ||
224 | |||
225 | // number of types of SRB MUST be a power of two -- why? | ||
226 | #define NUM_OF_SRB 32 | ||
227 | |||
228 | // number of bits of period info for rate | ||
229 | #define MAX_RATE_BITS 6 | ||
230 | |||
231 | #define TX_UBR 0x0000 | ||
232 | #define TX_UBR_CAPPED 0x0008 | ||
233 | #define TX_ABR 0x0018 | ||
234 | #define TX_FRAME_NOTCAP 0x0000 | ||
235 | #define TX_FRAME_CAPPED 0x8000 | ||
236 | |||
237 | #define FP_155_RATE 0x24b1 | ||
238 | #define FP_25_RATE 0x1f9d | ||
239 | |||
240 | /* #define VERSION_NUMBER 0x01000000 // initial release */ | ||
241 | /* #define VERSION_NUMBER 0x01010000 // fixed startup probs PLX MB0 not cleared */ | ||
242 | /* #define VERSION_NUMBER 0x01020000 // changed SUNI reset timings; allowed r/w onchip */ | ||
243 | |||
244 | /* #define VERSION_NUMBER 0x01030000 // clear local doorbell int reg on reset */ | ||
245 | /* #define VERSION_NUMBER 0x01040000 // PLX bug work around version PLUS */ | ||
246 | /* remove race conditions on basic interface */ | ||
247 | /* indicate to the host that diagnostics */ | ||
248 | /* have finished; if failed, how and what */ | ||
249 | /* failed */ | ||
250 | /* fix host memory test to fix PLX bug */ | ||
251 | /* allow flash upgrade and BIA upgrade directly */ | ||
252 | /* */ | ||
253 | #define VERSION_NUMBER 0x01050025 /* Jason's first hacked version. */ | ||
254 | /* Change in download algorithm */ | ||
255 | |||
256 | #define DMA_VALID 0xb728e149 /* completely random */ | ||
257 | |||
258 | #define FLASH_BASE 0xa0c00000 | ||
259 | #define FLASH_SIZE 0x00020000 /* 128K */ | ||
260 | #define BIA_BASE (FLASH_BASE+0x0001c000) /* Flash Sector 7 */ | ||
261 | #define BIA_ADDRESS ((void *)0xa0c1c000) | ||
262 | #define PLX_BASE 0xe0000000 | ||
263 | |||
264 | typedef enum { | ||
265 | host_memory_test = 1, | ||
266 | read_adapter_memory, | ||
267 | write_adapter_memory, | ||
268 | adapter_start, | ||
269 | get_version_number, | ||
270 | interrupt_host, | ||
271 | flash_erase_sector, | ||
272 | adap_download_block = 0x20, | ||
273 | adap_erase_flash, | ||
274 | adap_run_in_iram, | ||
275 | adap_end_download | ||
276 | } loader_command; | ||
277 | |||
278 | #define BAD_COMMAND (-1) | ||
279 | #define COMMAND_IN_PROGRESS 1 | ||
280 | #define COMMAND_PASSED_TEST 2 | ||
281 | #define COMMAND_FAILED_TEST 3 | ||
282 | #define COMMAND_READ_DATA_OK 4 | ||
283 | #define COMMAND_READ_BAD_ADDRESS 5 | ||
284 | #define COMMAND_WRITE_DATA_OK 6 | ||
285 | #define COMMAND_WRITE_BAD_ADDRESS 7 | ||
286 | #define COMMAND_WRITE_FLASH_FAILURE 8 | ||
287 | #define COMMAND_COMPLETE 9 | ||
288 | #define COMMAND_FLASH_ERASE_FAILURE 10 | ||
289 | #define COMMAND_WRITE_BAD_DATA 11 | ||
290 | |||
291 | /* bit fields for mailbox[0] return values */ | ||
292 | |||
293 | #define GPINT_TST_FAILURE 0x00000001 | ||
294 | #define SUNI_DATA_PATTERN_FAILURE 0x00000002 | ||
295 | #define SUNI_DATA_BITS_FAILURE 0x00000004 | ||
296 | #define SUNI_UTOPIA_FAILURE 0x00000008 | ||
297 | #define SUNI_FIFO_FAILURE 0x00000010 | ||
298 | #define SRAM_FAILURE 0x00000020 | ||
299 | #define SELF_TEST_FAILURE 0x0000003f | ||
300 | |||
301 | /* mailbox[1] = 0 in progress, -1 on completion */ | ||
302 | /* mailbox[2] = current test 00 00 test(8 bit) phase(8 bit) */ | ||
303 | /* mailbox[3] = last failure, 00 00 test(8 bit) phase(8 bit) */ | ||
304 | /* mailbox[4],mailbox[5],mailbox[6] random failure values */ | ||
305 | |||
306 | /* PLX/etc. memory map including command structure */ | ||
307 | |||
308 | /* These registers may also be memory mapped in PCI memory */ | ||
309 | |||
310 | #define UNUSED_LOADER_MAILBOXES 6 | ||
311 | |||
312 | typedef struct { | ||
313 | u32 stuff[16]; | ||
314 | union { | ||
315 | struct { | ||
316 | u32 result; | ||
317 | u32 ready; | ||
318 | u32 stuff[UNUSED_LOADER_MAILBOXES]; | ||
319 | } loader; | ||
320 | struct { | ||
321 | u32 cmd_address; | ||
322 | u32 tx_address; | ||
323 | u32 rx_address[NUM_RX_POOLS]; | ||
324 | u32 gen_counter; | ||
325 | u32 spare; | ||
326 | } adapter; | ||
327 | } mb; | ||
328 | u32 doorbell; | ||
329 | u32 interrupt; | ||
330 | u32 interrupt_control; | ||
331 | u32 reset_control; | ||
332 | } amb_mem; | ||
333 | |||
334 | /* RESET bit, IRQ (card to host) and doorbell (host to card) enable bits */ | ||
335 | #define AMB_RESET_BITS 0x40000000 | ||
336 | #define AMB_INTERRUPT_BITS 0x00000300 | ||
337 | #define AMB_DOORBELL_BITS 0x00030000 | ||
338 | |||
339 | /* loader commands */ | ||
340 | |||
341 | #define MAX_COMMAND_DATA 13 | ||
342 | #define MAX_TRANSFER_DATA 11 | ||
343 | |||
344 | typedef struct { | ||
345 | __be32 address; | ||
346 | __be32 count; | ||
347 | __be32 data[MAX_TRANSFER_DATA]; | ||
348 | } transfer_block; | ||
349 | |||
350 | typedef struct { | ||
351 | __be32 result; | ||
352 | __be32 command; | ||
353 | union { | ||
354 | transfer_block transfer; | ||
355 | __be32 version; | ||
356 | __be32 start; | ||
357 | __be32 data[MAX_COMMAND_DATA]; | ||
358 | } payload; | ||
359 | __be32 valid; | ||
360 | } loader_block; | ||
361 | |||
362 | /* command queue */ | ||
363 | |||
364 | /* Again all data are BIG ENDIAN */ | ||
365 | |||
366 | typedef struct { | ||
367 | union { | ||
368 | struct { | ||
369 | __be32 vc; | ||
370 | __be32 flags; | ||
371 | __be32 rate; | ||
372 | } open; | ||
373 | struct { | ||
374 | __be32 vc; | ||
375 | __be32 rate; | ||
376 | } modify_rate; | ||
377 | struct { | ||
378 | __be32 vc; | ||
379 | __be32 flags; | ||
380 | } modify_flags; | ||
381 | struct { | ||
382 | __be32 vc; | ||
383 | } close; | ||
384 | struct { | ||
385 | __be32 lower4; | ||
386 | __be32 upper2; | ||
387 | } bia; | ||
388 | struct { | ||
389 | __be32 address; | ||
390 | } suni; | ||
391 | struct { | ||
392 | __be32 major; | ||
393 | __be32 minor; | ||
394 | } version; | ||
395 | struct { | ||
396 | __be32 read; | ||
397 | __be32 write; | ||
398 | } speed; | ||
399 | struct { | ||
400 | __be32 flags; | ||
401 | } flush; | ||
402 | struct { | ||
403 | __be32 address; | ||
404 | __be32 data; | ||
405 | } memory; | ||
406 | __be32 par[3]; | ||
407 | } args; | ||
408 | __be32 request; | ||
409 | } command; | ||
410 | |||
411 | /* transmit queues and associated structures */ | ||
412 | |||
413 | /* The hosts transmit structure. All BIG ENDIAN; host address | ||
414 | restricted to first 1GByte, but address passed to the card must | ||
415 | have the top MS bit or'ed in. -- check this */ | ||
416 | |||
417 | /* TX is described by 1+ tx_frags followed by a tx_frag_end */ | ||
418 | |||
419 | typedef struct { | ||
420 | __be32 bytes; | ||
421 | __be32 address; | ||
422 | } tx_frag; | ||
423 | |||
424 | /* apart from handle the fields here are for the adapter to play with | ||
425 | and should be set to zero */ | ||
426 | |||
427 | typedef struct { | ||
428 | u32 handle; | ||
429 | u16 vc; | ||
430 | u16 next_descriptor_length; | ||
431 | u32 next_descriptor; | ||
432 | #ifdef AMB_NEW_MICROCODE | ||
433 | u8 cpcs_uu; | ||
434 | u8 cpi; | ||
435 | u16 pad; | ||
436 | #endif | ||
437 | } tx_frag_end; | ||
438 | |||
439 | typedef struct { | ||
440 | tx_frag tx_frag; | ||
441 | tx_frag_end tx_frag_end; | ||
442 | struct sk_buff * skb; | ||
443 | } tx_simple; | ||
444 | |||
445 | #if 0 | ||
446 | typedef union { | ||
447 | tx_frag fragment; | ||
448 | tx_frag_end end_of_list; | ||
449 | } tx_descr; | ||
450 | #endif | ||
451 | |||
452 | /* this "points" to the sequence of fragments and trailer */ | ||
453 | |||
454 | typedef struct { | ||
455 | __be16 vc; | ||
456 | __be16 tx_descr_length; | ||
457 | __be32 tx_descr_addr; | ||
458 | } tx_in; | ||
459 | |||
460 | /* handle is the handle from tx_in */ | ||
461 | |||
462 | typedef struct { | ||
463 | u32 handle; | ||
464 | } tx_out; | ||
465 | |||
466 | /* receive frame structure */ | ||
467 | |||
468 | /* All BIG ENDIAN; handle is as passed from host; length is zero for | ||
469 | aborted frames, and frames with errors. Header is actually VC | ||
470 | number, lec-id is NOT yet supported. */ | ||
471 | |||
472 | typedef struct { | ||
473 | u32 handle; | ||
474 | __be16 vc; | ||
475 | __be16 lec_id; // unused | ||
476 | __be16 status; | ||
477 | __be16 length; | ||
478 | } rx_out; | ||
479 | |||
480 | /* buffer supply structure */ | ||
481 | |||
482 | typedef struct { | ||
483 | u32 handle; | ||
484 | __be32 host_address; | ||
485 | } rx_in; | ||
486 | |||
487 | /* This first structure is the area in host memory where the adapter | ||
488 | writes its pointer values. These pointer values are BIG ENDIAN and | ||
489 | reside in the same 4MB 'page' as this structure. The host gives the | ||
490 | adapter the address of this block by sending a doorbell interrupt | ||
491 | to the adapter after downloading the code and setting it going. The | ||
492 | addresses have the top 10 bits set to 1010000010b -- really? | ||
493 | |||
494 | The host must initialise these before handing the block to the | ||
495 | adapter. */ | ||
496 | |||
497 | typedef struct { | ||
498 | __be32 command_start; /* SRB commands completions */ | ||
499 | __be32 command_end; /* SRB commands completions */ | ||
500 | __be32 tx_start; | ||
501 | __be32 tx_end; | ||
502 | __be32 txcom_start; /* tx completions */ | ||
503 | __be32 txcom_end; /* tx completions */ | ||
504 | struct { | ||
505 | __be32 buffer_start; | ||
506 | __be32 buffer_end; | ||
507 | u32 buffer_q_get; | ||
508 | u32 buffer_q_end; | ||
509 | u32 buffer_aptr; | ||
510 | __be32 rx_start; /* rx completions */ | ||
511 | __be32 rx_end; | ||
512 | u32 rx_ptr; | ||
513 | __be32 buffer_size; /* size of host buffer */ | ||
514 | } rec_struct[NUM_RX_POOLS]; | ||
515 | #ifdef AMB_NEW_MICROCODE | ||
516 | u16 init_flags; | ||
517 | u16 talk_block_spare; | ||
518 | #endif | ||
519 | } adap_talk_block; | ||
520 | |||
521 | /* This structure must be kept in line with the vcr image in sarmain.h | ||
522 | |||
523 | This is the structure in the host filled in by the adapter by | ||
524 | GET_SUNI_STATS */ | ||
525 | |||
526 | typedef struct { | ||
527 | u8 racp_chcs; | ||
528 | u8 racp_uhcs; | ||
529 | u16 spare; | ||
530 | u32 racp_rcell; | ||
531 | u32 tacp_tcell; | ||
532 | u32 flags; | ||
533 | u32 dropped_cells; | ||
534 | u32 dropped_frames; | ||
535 | } suni_stats; | ||
536 | |||
537 | typedef enum { | ||
538 | dead | ||
539 | } amb_flags; | ||
540 | |||
541 | #define NEXTQ(current,start,limit) \ | ||
542 | ( (current)+1 < (limit) ? (current)+1 : (start) ) | ||
543 | |||
544 | typedef struct { | ||
545 | command * start; | ||
546 | command * in; | ||
547 | command * out; | ||
548 | command * limit; | ||
549 | } amb_cq_ptrs; | ||
550 | |||
551 | typedef struct { | ||
552 | spinlock_t lock; | ||
553 | unsigned int pending; | ||
554 | unsigned int high; | ||
555 | unsigned int filled; | ||
556 | unsigned int maximum; // size - 1 (q implementation) | ||
557 | amb_cq_ptrs ptrs; | ||
558 | } amb_cq; | ||
559 | |||
560 | typedef struct { | ||
561 | spinlock_t lock; | ||
562 | unsigned int pending; | ||
563 | unsigned int high; | ||
564 | unsigned int filled; | ||
565 | unsigned int maximum; // size - 1 (q implementation) | ||
566 | struct { | ||
567 | tx_in * start; | ||
568 | tx_in * ptr; | ||
569 | tx_in * limit; | ||
570 | } in; | ||
571 | struct { | ||
572 | tx_out * start; | ||
573 | tx_out * ptr; | ||
574 | tx_out * limit; | ||
575 | } out; | ||
576 | } amb_txq; | ||
577 | |||
578 | typedef struct { | ||
579 | spinlock_t lock; | ||
580 | unsigned int pending; | ||
581 | unsigned int low; | ||
582 | unsigned int emptied; | ||
583 | unsigned int maximum; // size - 1 (q implementation) | ||
584 | struct { | ||
585 | rx_in * start; | ||
586 | rx_in * ptr; | ||
587 | rx_in * limit; | ||
588 | } in; | ||
589 | struct { | ||
590 | rx_out * start; | ||
591 | rx_out * ptr; | ||
592 | rx_out * limit; | ||
593 | } out; | ||
594 | unsigned int buffers_wanted; | ||
595 | unsigned int buffer_size; | ||
596 | } amb_rxq; | ||
597 | |||
598 | typedef struct { | ||
599 | unsigned long tx_ok; | ||
600 | struct { | ||
601 | unsigned long ok; | ||
602 | unsigned long error; | ||
603 | unsigned long badcrc; | ||
604 | unsigned long toolong; | ||
605 | unsigned long aborted; | ||
606 | unsigned long unused; | ||
607 | } rx; | ||
608 | } amb_stats; | ||
609 | |||
610 | // a single struct pointed to by atm_vcc->dev_data | ||
611 | |||
612 | typedef struct { | ||
613 | u8 tx_vc_bits:7; | ||
614 | u8 tx_present:1; | ||
615 | } amb_tx_info; | ||
616 | |||
617 | typedef struct { | ||
618 | unsigned char pool; | ||
619 | } amb_rx_info; | ||
620 | |||
621 | typedef struct { | ||
622 | amb_rx_info rx_info; | ||
623 | u16 tx_frame_bits; | ||
624 | unsigned int tx_rate; | ||
625 | unsigned int rx_rate; | ||
626 | } amb_vcc; | ||
627 | |||
628 | struct amb_dev { | ||
629 | u8 irq; | ||
630 | long flags; | ||
631 | u32 iobase; | ||
632 | u32 * membase; | ||
633 | |||
634 | #ifdef FILL_RX_POOLS_IN_BH | ||
635 | struct work_struct bh; | ||
636 | #endif | ||
637 | |||
638 | amb_cq cq; | ||
639 | amb_txq txq; | ||
640 | amb_rxq rxq[NUM_RX_POOLS]; | ||
641 | |||
642 | struct semaphore vcc_sf; | ||
643 | amb_tx_info txer[NUM_VCS]; | ||
644 | struct atm_vcc * rxer[NUM_VCS]; | ||
645 | unsigned int tx_avail; | ||
646 | unsigned int rx_avail; | ||
647 | |||
648 | amb_stats stats; | ||
649 | |||
650 | struct atm_dev * atm_dev; | ||
651 | struct pci_dev * pci_dev; | ||
652 | struct timer_list housekeeping; | ||
653 | }; | ||
654 | |||
655 | typedef struct amb_dev amb_dev; | ||
656 | |||
657 | #define AMB_DEV(atm_dev) ((amb_dev *) (atm_dev)->dev_data) | ||
658 | #define AMB_VCC(atm_vcc) ((amb_vcc *) (atm_vcc)->dev_data) | ||
659 | |||
660 | /* the microcode */ | ||
661 | |||
662 | typedef struct { | ||
663 | u32 start; | ||
664 | unsigned int count; | ||
665 | } region; | ||
666 | |||
667 | static region ucode_regions[]; | ||
668 | static u32 ucode_data[]; | ||
669 | static u32 ucode_start; | ||
670 | |||
671 | /* rate rounding */ | ||
672 | |||
673 | typedef enum { | ||
674 | round_up, | ||
675 | round_down, | ||
676 | round_nearest | ||
677 | } rounding; | ||
678 | |||
679 | #endif | ||
diff --git a/drivers/atm/atmdev_init.c b/drivers/atm/atmdev_init.c new file mode 100644 index 000000000000..0e09e5c28e3f --- /dev/null +++ b/drivers/atm/atmdev_init.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* drivers/atm/atmdev_init.c - ATM device driver initialization */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #include <linux/config.h> | ||
7 | #include <linux/init.h> | ||
8 | |||
9 | |||
10 | #ifdef CONFIG_ATM_ZATM | ||
11 | extern int zatm_detect(void); | ||
12 | #endif | ||
13 | #ifdef CONFIG_ATM_AMBASSADOR | ||
14 | extern int amb_detect(void); | ||
15 | #endif | ||
16 | #ifdef CONFIG_ATM_HORIZON | ||
17 | extern int hrz_detect(void); | ||
18 | #endif | ||
19 | #ifdef CONFIG_ATM_FORE200E | ||
20 | extern int fore200e_detect(void); | ||
21 | #endif | ||
22 | #ifdef CONFIG_ATM_LANAI | ||
23 | extern int lanai_detect(void); | ||
24 | #endif | ||
25 | |||
26 | |||
27 | /* | ||
28 | * For historical reasons, atmdev_init returns the number of devices found. | ||
29 | * Note that some detections may not go via atmdev_init (e.g. eni.c), so this | ||
30 | * number is meaningless. | ||
31 | */ | ||
32 | |||
33 | int __init atmdev_init(void) | ||
34 | { | ||
35 | int devs; | ||
36 | |||
37 | devs = 0; | ||
38 | #ifdef CONFIG_ATM_ZATM | ||
39 | devs += zatm_detect(); | ||
40 | #endif | ||
41 | #ifdef CONFIG_ATM_AMBASSADOR | ||
42 | devs += amb_detect(); | ||
43 | #endif | ||
44 | #ifdef CONFIG_ATM_HORIZON | ||
45 | devs += hrz_detect(); | ||
46 | #endif | ||
47 | #ifdef CONFIG_ATM_FORE200E | ||
48 | devs += fore200e_detect(); | ||
49 | #endif | ||
50 | #ifdef CONFIG_ATM_LANAI | ||
51 | devs += lanai_detect(); | ||
52 | #endif | ||
53 | return devs; | ||
54 | } | ||
diff --git a/drivers/atm/atmsar11.data b/drivers/atm/atmsar11.data new file mode 100644 index 000000000000..5dc8a7613f57 --- /dev/null +++ b/drivers/atm/atmsar11.data | |||
@@ -0,0 +1,2063 @@ | |||
1 | /* | ||
2 | Madge Ambassador ATM Adapter microcode. | ||
3 | Copyright (C) 1995-1999 Madge Networks Ltd. | ||
4 | |||
5 | This microcode data is placed under the terms of the GNU General | ||
6 | Public License. The GPL is contained in /usr/doc/copyright/GPL on a | ||
7 | Debian system and in the file COPYING in the Linux kernel source. | ||
8 | |||
9 | We would prefer you not to distribute modified versions without | ||
10 | consultation and not to ask for assembly/other microcode source. | ||
11 | */ | ||
12 | |||
13 | 0x401a6800, | ||
14 | 0x00000000, | ||
15 | 0x335b007c, | ||
16 | 0x13600005, | ||
17 | 0x335b1000, | ||
18 | 0x3c1aa0c0, | ||
19 | 0x375a0180, | ||
20 | 0x03400008, | ||
21 | 0x00000000, | ||
22 | 0x1760fffb, | ||
23 | 0x335b4000, | ||
24 | 0x401a7000, | ||
25 | 0x13600003, | ||
26 | 0x241b0fc0, | ||
27 | 0xaf9b4500, | ||
28 | 0x25080008, | ||
29 | 0x03400008, | ||
30 | 0x42000010, | ||
31 | 0x8f810c90, | ||
32 | 0x32220002, | ||
33 | 0x10400003, | ||
34 | 0x3c03a0d1, | ||
35 | 0x2463f810, | ||
36 | 0x0060f809, | ||
37 | 0x24210001, | ||
38 | 0x1000001a, | ||
39 | 0xaf810c90, | ||
40 | 0x82020011, | ||
41 | 0xaf900c48, | ||
42 | 0x0441000a, | ||
43 | 0x34420080, | ||
44 | 0x967d0002, | ||
45 | 0x96020012, | ||
46 | 0x00000000, | ||
47 | 0x105d0011, | ||
48 | 0x00000000, | ||
49 | 0x04110161, | ||
50 | 0xa6620002, | ||
51 | 0x1000000d, | ||
52 | 0xae62000c, | ||
53 | 0x34848000, | ||
54 | 0xa2020011, | ||
55 | 0x4d01ffff, | ||
56 | 0x00000000, | ||
57 | 0x8f834c00, | ||
58 | 0x00000000, | ||
59 | 0xaf830fec, | ||
60 | 0x00e0f809, | ||
61 | 0x03e03821, | ||
62 | 0x00041400, | ||
63 | 0x0440fff7, | ||
64 | 0x00000000, | ||
65 | 0xaf80460c, | ||
66 | 0x8e100008, | ||
67 | 0x4d01ffff, | ||
68 | 0x00000000, | ||
69 | 0x8f834c00, | ||
70 | 0x4900001d, | ||
71 | 0xaf830fec, | ||
72 | 0x8f820cbc, | ||
73 | 0x8f9d0c4c, | ||
74 | 0x24420001, | ||
75 | 0x97be0000, | ||
76 | 0xaf820cbc, | ||
77 | 0x13c00009, | ||
78 | 0xaca200d8, | ||
79 | 0xa7a00000, | ||
80 | 0x3c0100d1, | ||
81 | 0x003e0825, | ||
82 | 0x9422002c, | ||
83 | 0x0411013f, | ||
84 | 0xa4220002, | ||
85 | 0xac22000c, | ||
86 | 0xac200010, | ||
87 | 0x8f9e0c54, | ||
88 | 0x27bd0002, | ||
89 | 0x17be0002, | ||
90 | 0x8ca200c0, | ||
91 | 0x8f9d0c50, | ||
92 | 0x8f970fc8, | ||
93 | 0xaf9d0c4c, | ||
94 | 0x12e20005, | ||
95 | 0x87804002, | ||
96 | 0x3c02a0d1, | ||
97 | 0x2442f94c, | ||
98 | 0x0040f809, | ||
99 | 0x00000000, | ||
100 | 0x00e0f809, | ||
101 | 0x03e03821, | ||
102 | 0x4500ffdc, | ||
103 | 0x8e11000c, | ||
104 | 0x3c1300d1, | ||
105 | 0x00111102, | ||
106 | 0x2c430400, | ||
107 | 0x1060ffb9, | ||
108 | 0x00021180, | ||
109 | 0x02629821, | ||
110 | 0x8e76003c, | ||
111 | 0x32220008, | ||
112 | 0x1440ffb7, | ||
113 | 0x8e770034, | ||
114 | 0x8e750030, | ||
115 | 0x3c03cfb0, | ||
116 | 0x16c00003, | ||
117 | 0x02d5102b, | ||
118 | 0x041100be, | ||
119 | 0x00000000, | ||
120 | 0x1040ffa6, | ||
121 | 0x00701826, | ||
122 | 0x4d01ffff, | ||
123 | 0x00000000, | ||
124 | 0x8f824c00, | ||
125 | 0xaf974c00, | ||
126 | 0xaf820fec, | ||
127 | 0xac760010, | ||
128 | 0x02609021, | ||
129 | 0x32220002, | ||
130 | 0x10400007, | ||
131 | 0x8f944a00, | ||
132 | 0x9602003a, | ||
133 | 0x34840004, | ||
134 | 0x14400003, | ||
135 | 0xaf820fbc, | ||
136 | 0x3c029000, | ||
137 | 0xaf820fbc, | ||
138 | 0x8e100008, | ||
139 | 0x32943f00, | ||
140 | 0x8e11000c, | ||
141 | 0x2694ff00, | ||
142 | 0x12800073, | ||
143 | 0x3c1300d1, | ||
144 | 0x49010071, | ||
145 | 0x32370008, | ||
146 | 0x16e0006f, | ||
147 | 0x00111102, | ||
148 | 0x2c430400, | ||
149 | 0x1060006c, | ||
150 | 0x0002b980, | ||
151 | 0x00041740, | ||
152 | 0x0440003a, | ||
153 | 0x02779821, | ||
154 | 0x12720023, | ||
155 | 0x26d60030, | ||
156 | 0xae56003c, | ||
157 | 0x8e76003c, | ||
158 | 0x8e770034, | ||
159 | 0x8e750030, | ||
160 | 0x3c03cfb0, | ||
161 | 0x16c00003, | ||
162 | 0x02d5102b, | ||
163 | 0x04110091, | ||
164 | 0x00000000, | ||
165 | 0x10400060, | ||
166 | 0x2e821000, | ||
167 | 0x14400009, | ||
168 | 0x00701826, | ||
169 | 0x4d01ffff, | ||
170 | 0x00000000, | ||
171 | 0x8f824c00, | ||
172 | 0xaf974c00, | ||
173 | 0xac760010, | ||
174 | 0xae420034, | ||
175 | 0x1000ffd0, | ||
176 | 0xaf80460c, | ||
177 | 0x00e0f809, | ||
178 | 0x03e03821, | ||
179 | 0x3c03cfb0, | ||
180 | 0x00701826, | ||
181 | 0xae460034, | ||
182 | 0x4d01ffff, | ||
183 | 0x00000000, | ||
184 | 0x8f824c00, | ||
185 | 0xaf974c00, | ||
186 | 0xaf820fec, | ||
187 | 0xac760010, | ||
188 | 0x1000ffc3, | ||
189 | 0xaf80460c, | ||
190 | 0x02d5102b, | ||
191 | 0x10400042, | ||
192 | 0x3c17cfb0, | ||
193 | 0x2e821000, | ||
194 | 0x14400006, | ||
195 | 0x02f0b826, | ||
196 | 0x4d01ffff, | ||
197 | 0x00000000, | ||
198 | 0xaef60010, | ||
199 | 0x1000ffb8, | ||
200 | 0xaf80460c, | ||
201 | 0x00e0f809, | ||
202 | 0x03e03821, | ||
203 | 0x4d01ffff, | ||
204 | 0x00000000, | ||
205 | 0x8f824c00, | ||
206 | 0xaf864c00, | ||
207 | 0xaef60010, | ||
208 | 0xaf820fec, | ||
209 | 0x1000ffae, | ||
210 | 0xaf80460c, | ||
211 | 0x3084fffb, | ||
212 | 0x8e570038, | ||
213 | 0x3242ffc0, | ||
214 | 0x00021182, | ||
215 | 0xa7820fb8, | ||
216 | 0xaf970fb4, | ||
217 | 0x865d002a, | ||
218 | 0x865e0008, | ||
219 | 0xa79d0fba, | ||
220 | 0x279d0f18, | ||
221 | 0x33de0060, | ||
222 | 0x03bee821, | ||
223 | 0x001ef0c2, | ||
224 | 0x03bee821, | ||
225 | 0x8f970c58, | ||
226 | 0x4d01ffff, | ||
227 | 0x00000000, | ||
228 | 0x8f834c00, | ||
229 | 0x8fa2001c, | ||
230 | 0x12e30003, | ||
231 | 0x3c030c40, | ||
232 | 0x3c1ec000, | ||
233 | 0xaf9e0fbc, | ||
234 | 0xac620fb4, | ||
235 | 0x8fa30018, | ||
236 | 0x2442000c, | ||
237 | 0x14430002, | ||
238 | 0xaf80460c, | ||
239 | 0x8fa20014, | ||
240 | 0xae40003c, | ||
241 | 0xafa2001c, | ||
242 | 0x8e76003c, | ||
243 | 0x8e770034, | ||
244 | 0x8e750030, | ||
245 | 0x3c03cfb0, | ||
246 | 0x16c00003, | ||
247 | 0x02d5102b, | ||
248 | 0x0411003c, | ||
249 | 0x00000000, | ||
250 | 0x00701826, | ||
251 | 0x4d01ffff, | ||
252 | 0x00000000, | ||
253 | 0xaca500e4, | ||
254 | 0x10400032, | ||
255 | 0xaf974c00, | ||
256 | 0x1000ff7f, | ||
257 | 0xac760010, | ||
258 | 0x00041740, | ||
259 | 0x04400007, | ||
260 | 0x26d60030, | ||
261 | 0xae56003c, | ||
262 | 0x00e0f809, | ||
263 | 0x03e03821, | ||
264 | 0xaf80460c, | ||
265 | 0x1000ff39, | ||
266 | 0xae460034, | ||
267 | 0x8e570038, | ||
268 | 0x3242ffc0, | ||
269 | 0x00021182, | ||
270 | 0xa7820fb8, | ||
271 | 0xaf970fb4, | ||
272 | 0x8f970c58, | ||
273 | 0x00e0f809, | ||
274 | 0x03e03821, | ||
275 | 0x12e60003, | ||
276 | 0x3c030c40, | ||
277 | 0x3c02c000, | ||
278 | 0xaf820fbc, | ||
279 | 0x865d002a, | ||
280 | 0x865e0008, | ||
281 | 0xa79d0fba, | ||
282 | 0x279d0f18, | ||
283 | 0x33de0060, | ||
284 | 0x03bee821, | ||
285 | 0x001ef0c2, | ||
286 | 0x03bee821, | ||
287 | 0x8fa2001c, | ||
288 | 0x4d01ffff, | ||
289 | 0x00000000, | ||
290 | 0x8f974c00, | ||
291 | 0xac620fb4, | ||
292 | 0x3084fffb, | ||
293 | 0x8fa30018, | ||
294 | 0x2442000c, | ||
295 | 0x14430002, | ||
296 | 0xaf80460c, | ||
297 | 0x8fa20014, | ||
298 | 0xae40003c, | ||
299 | 0xafa2001c, | ||
300 | 0x4d01ffff, | ||
301 | 0x00000000, | ||
302 | 0xaca500e4, | ||
303 | 0x1000ff13, | ||
304 | 0xaf974c00, | ||
305 | 0x00e0f809, | ||
306 | 0x03e03821, | ||
307 | 0x1000ff0f, | ||
308 | 0x00000000, | ||
309 | 0x1040005b, | ||
310 | 0x867e0008, | ||
311 | 0x279d0f18, | ||
312 | 0x33de0060, | ||
313 | 0x03bee821, | ||
314 | 0x001e10c2, | ||
315 | 0x03a2e821, | ||
316 | 0x8fb70008, | ||
317 | 0x8fa2000c, | ||
318 | 0x8ef60004, | ||
319 | 0x12e20028, | ||
320 | 0x86620008, | ||
321 | 0x82030010, | ||
322 | 0x00021740, | ||
323 | 0x04410019, | ||
324 | 0x24630001, | ||
325 | 0x10600017, | ||
326 | 0x3c02d1b0, | ||
327 | 0x00501026, | ||
328 | 0x4d01ffff, | ||
329 | 0x00000000, | ||
330 | 0x8f9e4c00, | ||
331 | 0xac560010, | ||
332 | 0x26d6fffe, | ||
333 | 0x86020010, | ||
334 | 0x3c03cfb0, | ||
335 | 0x34632000, | ||
336 | 0xa662002a, | ||
337 | 0x8ee20000, | ||
338 | 0x26f70008, | ||
339 | 0xae620038, | ||
340 | 0x8fa20020, | ||
341 | 0xafb70008, | ||
342 | 0x2417ffff, | ||
343 | 0x02c2a821, | ||
344 | 0x4d01ffff, | ||
345 | 0x00000000, | ||
346 | 0xaf9e4c00, | ||
347 | 0x03e00008, | ||
348 | 0xae750030, | ||
349 | 0x8ee20000, | ||
350 | 0x26f70008, | ||
351 | 0xae620038, | ||
352 | 0x8fa20020, | ||
353 | 0xafb70008, | ||
354 | 0x2417ffff, | ||
355 | 0xa677002a, | ||
356 | 0x02c2a821, | ||
357 | 0x3c03cfb0, | ||
358 | 0x03e00008, | ||
359 | 0xae750030, | ||
360 | 0x001e18c2, | ||
361 | 0x00651821, | ||
362 | 0x8c6300c8, | ||
363 | 0x8fa20010, | ||
364 | 0x00000000, | ||
365 | 0x0062b023, | ||
366 | 0x1ec00003, | ||
367 | 0x8fa10004, | ||
368 | 0x12c0001b, | ||
369 | 0x0022b023, | ||
370 | 0x2ec30041, | ||
371 | 0x14600002, | ||
372 | 0x3c150040, | ||
373 | 0x24160040, | ||
374 | 0x00161e80, | ||
375 | 0x00031882, | ||
376 | 0x00751825, | ||
377 | 0x4d01ffff, | ||
378 | 0x00000000, | ||
379 | 0x8f954c00, | ||
380 | 0x001eb840, | ||
381 | 0x00771821, | ||
382 | 0xac624d00, | ||
383 | 0x00561021, | ||
384 | 0x14410002, | ||
385 | 0x27830d00, | ||
386 | 0x8fa20000, | ||
387 | 0x02e3b821, | ||
388 | 0xafa20010, | ||
389 | 0x02d71821, | ||
390 | 0xafa3000c, | ||
391 | 0x4d01ffff, | ||
392 | 0x00000000, | ||
393 | 0x8ef60004, | ||
394 | 0x1000ffb5, | ||
395 | 0xaf954c00, | ||
396 | 0x3c16dead, | ||
397 | 0xae76003c, | ||
398 | 0xae600038, | ||
399 | 0x26d5ffff, | ||
400 | 0x00001021, | ||
401 | 0x03e00008, | ||
402 | 0xae750030, | ||
403 | 0x2c430ab2, | ||
404 | 0x10600005, | ||
405 | 0x2c4324b2, | ||
406 | 0x10000004, | ||
407 | 0x24020ab2, | ||
408 | 0x10000002, | ||
409 | 0x240224b1, | ||
410 | 0x1060fffd, | ||
411 | 0x304301ff, | ||
412 | 0x00031840, | ||
413 | 0x3c1da0d1, | ||
414 | 0x27bdd6cc, | ||
415 | 0x007d1821, | ||
416 | 0x94630000, | ||
417 | 0x0002ea42, | ||
418 | 0x00031c00, | ||
419 | 0x27bdfffb, | ||
420 | 0x03e00008, | ||
421 | 0x03a31006, | ||
422 | 0x24030fc0, | ||
423 | 0xaf834500, | ||
424 | 0x10000002, | ||
425 | 0x01206021, | ||
426 | 0x3c0ccfb0, | ||
427 | 0x11e00056, | ||
428 | 0x01896026, | ||
429 | 0x85fe0000, | ||
430 | 0x00000000, | ||
431 | 0x13c00047, | ||
432 | 0x3c02cfb0, | ||
433 | 0x07c0002d, | ||
434 | 0x001e1f80, | ||
435 | 0x04610034, | ||
436 | 0x001e1fc0, | ||
437 | 0x04600009, | ||
438 | 0x3c02d3b0, | ||
439 | 0x00e0f809, | ||
440 | 0x03e03821, | ||
441 | 0x4d01ffff, | ||
442 | 0x00000000, | ||
443 | 0x8f864c00, | ||
444 | 0x8f990fec, | ||
445 | 0x1000000b, | ||
446 | 0xaf994c00, | ||
447 | 0x01e27826, | ||
448 | 0x00e0f809, | ||
449 | 0x03e03821, | ||
450 | 0x4d01ffff, | ||
451 | 0x00000000, | ||
452 | 0x8f864c00, | ||
453 | 0xaf994c00, | ||
454 | 0xadef2010, | ||
455 | 0x3c02d3b0, | ||
456 | 0x01e27826, | ||
457 | 0x8f820fc0, | ||
458 | 0x8f830fc4, | ||
459 | 0xaf824d00, | ||
460 | 0x8de20004, | ||
461 | 0xa5e00000, | ||
462 | 0xac620000, | ||
463 | 0x8c620000, | ||
464 | 0x24020380, | ||
465 | 0xaf824d00, | ||
466 | 0x8f824d00, | ||
467 | 0x8f820f14, | ||
468 | 0x24630004, | ||
469 | 0x14620002, | ||
470 | 0x2419ffff, | ||
471 | 0x8f830f10, | ||
472 | 0xaca500e4, | ||
473 | 0xaf830fc4, | ||
474 | 0x4d01ffff, | ||
475 | 0x00000000, | ||
476 | 0x8f824c80, | ||
477 | 0x1000001f, | ||
478 | 0xade2003c, | ||
479 | 0x00e0f809, | ||
480 | 0x03e03821, | ||
481 | 0x4d01ffff, | ||
482 | 0x00000000, | ||
483 | 0xa5e00000, | ||
484 | 0x8f864c00, | ||
485 | 0x15800022, | ||
486 | 0xaf8f4540, | ||
487 | 0x10000017, | ||
488 | 0x01e27826, | ||
489 | 0x00e0f809, | ||
490 | 0x03e03821, | ||
491 | 0x4d01ffff, | ||
492 | 0x00000000, | ||
493 | 0x8f864c00, | ||
494 | 0xaf994c00, | ||
495 | 0xadef2010, | ||
496 | 0x3c02cfb0, | ||
497 | 0x01e27826, | ||
498 | 0xa5e00000, | ||
499 | 0x4d01ffff, | ||
500 | 0x00000000, | ||
501 | 0x10000007, | ||
502 | 0x8f994c00, | ||
503 | 0x00e0f809, | ||
504 | 0x03e03821, | ||
505 | 0x4d01ffff, | ||
506 | 0x00000000, | ||
507 | 0x8f864c00, | ||
508 | 0x8f990fec, | ||
509 | 0x1580000a, | ||
510 | 0xaf8f4500, | ||
511 | 0x00007821, | ||
512 | 0x10000014, | ||
513 | 0xaf190014, | ||
514 | 0x00e0f809, | ||
515 | 0x03e03821, | ||
516 | 0x4d01ffff, | ||
517 | 0x00000000, | ||
518 | 0x1180fff8, | ||
519 | 0x8f864c00, | ||
520 | 0x85220000, | ||
521 | 0x01207821, | ||
522 | 0x0440000a, | ||
523 | 0x8d290008, | ||
524 | 0x130b0004, | ||
525 | 0x000c1602, | ||
526 | 0xaf190014, | ||
527 | 0x8d790014, | ||
528 | 0x0160c021, | ||
529 | 0xaf994c00, | ||
530 | 0xad8e4010, | ||
531 | 0x3042003f, | ||
532 | 0x01c27021, | ||
533 | 0x00041780, | ||
534 | 0x0440018b, | ||
535 | 0x8f824a00, | ||
536 | 0x30818000, | ||
537 | 0x30420004, | ||
538 | 0x1440ff8d, | ||
539 | 0x8d4b0000, | ||
540 | 0x1020000c, | ||
541 | 0x30847fff, | ||
542 | 0x8f820c48, | ||
543 | 0x0120f021, | ||
544 | 0x24430034, | ||
545 | 0x8c5d000c, | ||
546 | 0x24420004, | ||
547 | 0xafdd000c, | ||
548 | 0x1462fffc, | ||
549 | 0x27de0004, | ||
550 | 0xa5210000, | ||
551 | 0x1000ff82, | ||
552 | 0x25080008, | ||
553 | 0x11600058, | ||
554 | 0x00000000, | ||
555 | 0x857d0008, | ||
556 | 0x8d63000c, | ||
557 | 0x9562000a, | ||
558 | 0x8d410004, | ||
559 | 0x07a10026, | ||
560 | 0x00621821, | ||
561 | 0xa563000a, | ||
562 | 0x00031c02, | ||
563 | 0x041101a0, | ||
564 | 0x000318c0, | ||
565 | 0x001d16c0, | ||
566 | 0x0441001f, | ||
567 | 0x27a20080, | ||
568 | 0x00021cc0, | ||
569 | 0x0461000e, | ||
570 | 0x0040e821, | ||
571 | 0x27bd0080, | ||
572 | 0x95620000, | ||
573 | 0x95630002, | ||
574 | 0x3442000c, | ||
575 | 0xad22000c, | ||
576 | 0x24020100, | ||
577 | 0xa5220010, | ||
578 | 0x9562002c, | ||
579 | 0xa5230014, | ||
580 | 0xa5220012, | ||
581 | 0xa5200016, | ||
582 | 0x34028000, | ||
583 | 0xa5220000, | ||
584 | 0xa57d0008, | ||
585 | 0x07a0000c, | ||
586 | 0x8f820c4c, | ||
587 | 0x8f830c50, | ||
588 | 0x2441ffe8, | ||
589 | 0x0023f02b, | ||
590 | 0x13c00002, | ||
591 | 0x00201021, | ||
592 | 0x24420400, | ||
593 | 0x945e0000, | ||
594 | 0x2441fffe, | ||
595 | 0x17c0fff9, | ||
596 | 0xad620010, | ||
597 | 0xa44b0000, | ||
598 | 0x142b001c, | ||
599 | 0xad400000, | ||
600 | 0xad400004, | ||
601 | 0x254a0008, | ||
602 | 0x3142007f, | ||
603 | 0x1440000e, | ||
604 | 0x00041780, | ||
605 | 0x04410003, | ||
606 | 0x8f820fe0, | ||
607 | 0x10000006, | ||
608 | 0x34840001, | ||
609 | 0x34840002, | ||
610 | 0x24420008, | ||
611 | 0x34421000, | ||
612 | 0x38421000, | ||
613 | 0xaf820fe0, | ||
614 | 0x354a0100, | ||
615 | 0x394a0100, | ||
616 | 0x39420080, | ||
617 | 0xaf820fe4, | ||
618 | 0x001d14c0, | ||
619 | 0x04410003, | ||
620 | 0x33a2efff, | ||
621 | 0x1000ff3c, | ||
622 | 0xa5620008, | ||
623 | 0x07a0009f, | ||
624 | 0x33a2fffe, | ||
625 | 0x10000021, | ||
626 | 0xa5620008, | ||
627 | 0x8d620024, | ||
628 | 0x001d1cc0, | ||
629 | 0x04610004, | ||
630 | 0xad420000, | ||
631 | 0x33a3efff, | ||
632 | 0x1000ff31, | ||
633 | 0xa5630008, | ||
634 | 0x07a00005, | ||
635 | 0x33a3fffe, | ||
636 | 0xa5630008, | ||
637 | 0x8d4b0000, | ||
638 | 0x1000ffaa, | ||
639 | 0x00000000, | ||
640 | 0x1000008e, | ||
641 | 0x25080008, | ||
642 | 0x254a0008, | ||
643 | 0x3142007f, | ||
644 | 0x1440000e, | ||
645 | 0x00041780, | ||
646 | 0x04410003, | ||
647 | 0x8f820fe0, | ||
648 | 0x10000006, | ||
649 | 0x34840001, | ||
650 | 0x34840002, | ||
651 | 0x24420008, | ||
652 | 0x34421000, | ||
653 | 0x38421000, | ||
654 | 0xaf820fe0, | ||
655 | 0x354a0100, | ||
656 | 0x394a0100, | ||
657 | 0x39420080, | ||
658 | 0xaf820fe4, | ||
659 | 0x11000003, | ||
660 | 0x8d4b0000, | ||
661 | 0x1000ff93, | ||
662 | 0x2508fff8, | ||
663 | 0x8f820fd8, | ||
664 | 0x8f830fdc, | ||
665 | 0x8f810fd4, | ||
666 | 0x1062001d, | ||
667 | 0x24620008, | ||
668 | 0x4d01ffff, | ||
669 | 0x00000000, | ||
670 | 0x8f8c4c00, | ||
671 | 0x847f0000, | ||
672 | 0x3c1e00d1, | ||
673 | 0x33fd03ff, | ||
674 | 0x001d5980, | ||
675 | 0x017e5821, | ||
676 | 0x857e0008, | ||
677 | 0x001de900, | ||
678 | 0x001e0f00, | ||
679 | 0x03e1f825, | ||
680 | 0x07e00003, | ||
681 | 0xaf820fdc, | ||
682 | 0x879e0ca0, | ||
683 | 0x278b0c98, | ||
684 | 0x07c10042, | ||
685 | 0x3c020840, | ||
686 | 0x3c01f7b0, | ||
687 | 0x8d620020, | ||
688 | 0x00230826, | ||
689 | 0xac220000, | ||
690 | 0x8c620004, | ||
691 | 0x94630002, | ||
692 | 0x2442fff8, | ||
693 | 0x00431021, | ||
694 | 0x1000004e, | ||
695 | 0xad620020, | ||
696 | 0x8f820fd0, | ||
697 | 0x87830ca0, | ||
698 | 0x14220007, | ||
699 | 0x278b0c98, | ||
700 | 0x41000051, | ||
701 | 0x3c018000, | ||
702 | 0xaca100e0, | ||
703 | 0x8ca100c4, | ||
704 | 0x00000000, | ||
705 | 0x1022004c, | ||
706 | 0x0022e823, | ||
707 | 0x8f9f0f0c, | ||
708 | 0x07a10002, | ||
709 | 0xaf810fd4, | ||
710 | 0x03e2e823, | ||
711 | 0x2fa30041, | ||
712 | 0x14600002, | ||
713 | 0x3c1e0040, | ||
714 | 0x241d0040, | ||
715 | 0x001d1e80, | ||
716 | 0x00031882, | ||
717 | 0x007e1825, | ||
718 | 0x4d01ffff, | ||
719 | 0x00000000, | ||
720 | 0x8f8c4c00, | ||
721 | 0xac624cc0, | ||
722 | 0x005d1021, | ||
723 | 0x145f0002, | ||
724 | 0x27830cc0, | ||
725 | 0x8f820f08, | ||
726 | 0x03a3f021, | ||
727 | 0xaf820fd0, | ||
728 | 0xaf9e0fd8, | ||
729 | 0x4d01ffff, | ||
730 | 0x00000000, | ||
731 | 0x1000ffc3, | ||
732 | 0x24620008, | ||
733 | 0x8d63000c, | ||
734 | 0x8d7d0010, | ||
735 | 0xa563000a, | ||
736 | 0x13a00002, | ||
737 | 0x00031c02, | ||
738 | 0xa7a00000, | ||
739 | 0x000318c0, | ||
740 | 0x041100ef, | ||
741 | 0x00681821, | ||
742 | 0x4d01ffff, | ||
743 | 0x00000000, | ||
744 | 0x8f820c44, | ||
745 | 0x8f830c40, | ||
746 | 0xad620010, | ||
747 | 0xa5630004, | ||
748 | 0xa5630006, | ||
749 | 0x10000021, | ||
750 | 0xaf8c4c00, | ||
751 | 0xa57d0000, | ||
752 | 0x8c7d0004, | ||
753 | 0x94630002, | ||
754 | 0xac5d4c40, | ||
755 | 0x27a20008, | ||
756 | 0xad620018, | ||
757 | 0x03a3e821, | ||
758 | 0x27bdfff4, | ||
759 | 0xad7d001c, | ||
760 | 0x27bd0004, | ||
761 | 0xad7d0020, | ||
762 | 0x37c18001, | ||
763 | 0x001e17c0, | ||
764 | 0x0441ffe0, | ||
765 | 0xa5610008, | ||
766 | 0x4d01ffff, | ||
767 | 0x00000000, | ||
768 | 0x8f820c44, | ||
769 | 0x8f830c40, | ||
770 | 0xad620010, | ||
771 | 0xa5630004, | ||
772 | 0xa5630006, | ||
773 | 0x8f820fd8, | ||
774 | 0x8f830fdc, | ||
775 | 0x4d01ffff, | ||
776 | 0x00000000, | ||
777 | 0x1462ff95, | ||
778 | 0x24620008, | ||
779 | 0xaf8c4c00, | ||
780 | 0x87830ca0, | ||
781 | 0x278b0c98, | ||
782 | 0x0461fe97, | ||
783 | 0x00041700, | ||
784 | 0x04400005, | ||
785 | 0x95620000, | ||
786 | 0x11780006, | ||
787 | 0x00000000, | ||
788 | 0xaf0e0010, | ||
789 | 0xa70d0004, | ||
790 | 0x3084fff7, | ||
791 | 0x956d0004, | ||
792 | 0x8d6e0010, | ||
793 | 0x25adffd0, | ||
794 | 0x05a1fe8f, | ||
795 | 0xad22000c, | ||
796 | 0x3c0cffb0, | ||
797 | 0x01896026, | ||
798 | 0x000d1822, | ||
799 | 0x25ad0030, | ||
800 | 0x8d7e0018, | ||
801 | 0x8d61001c, | ||
802 | 0x4d01ffff, | ||
803 | 0x00000000, | ||
804 | 0x103e0036, | ||
805 | 0x8f9d4c00, | ||
806 | 0x3c010840, | ||
807 | 0xac3e4c40, | ||
808 | 0x27de0008, | ||
809 | 0x11a00017, | ||
810 | 0xad7e0018, | ||
811 | 0x000df600, | ||
812 | 0x019e6025, | ||
813 | 0x4d01ffff, | ||
814 | 0x00000000, | ||
815 | 0xad8e4010, | ||
816 | 0x8f8d0c40, | ||
817 | 0x957e0006, | ||
818 | 0x8f8e0c44, | ||
819 | 0x03cdf021, | ||
820 | 0xa57e0006, | ||
821 | 0x000cf782, | ||
822 | 0x000c0e02, | ||
823 | 0x03c1f021, | ||
824 | 0x001e0f80, | ||
825 | 0x000c6200, | ||
826 | 0x000c6202, | ||
827 | 0x01816025, | ||
828 | 0x33de003c, | ||
829 | 0x019e6021, | ||
830 | 0x34010001, | ||
831 | 0x10000008, | ||
832 | 0xa5210000, | ||
833 | 0x957e0006, | ||
834 | 0x4d01ffff, | ||
835 | 0x00000000, | ||
836 | 0x8f8d0c40, | ||
837 | 0x8f8e0c44, | ||
838 | 0x03cdf021, | ||
839 | 0xa57e0006, | ||
840 | 0x4d01ffff, | ||
841 | 0x00000000, | ||
842 | 0x01a3f02b, | ||
843 | 0x17c00008, | ||
844 | 0x0003f600, | ||
845 | 0x01a36823, | ||
846 | 0x019e6025, | ||
847 | 0x01896026, | ||
848 | 0x4d01fff7, | ||
849 | 0x00000000, | ||
850 | 0x1000fe58, | ||
851 | 0xaf9d4c00, | ||
852 | 0x8d7e0018, | ||
853 | 0x8d61001c, | ||
854 | 0x00000000, | ||
855 | 0x143effce, | ||
856 | 0x006d1823, | ||
857 | 0x4d01ffff, | ||
858 | 0x00000000, | ||
859 | 0x2c610008, | ||
860 | 0x10200017, | ||
861 | 0x95610008, | ||
862 | 0x00000000, | ||
863 | 0x0001ff80, | ||
864 | 0x07e0000b, | ||
865 | 0x34210002, | ||
866 | 0x006d1821, | ||
867 | 0x00031e00, | ||
868 | 0x01836025, | ||
869 | 0x01896026, | ||
870 | 0x240d002c, | ||
871 | 0xa5610008, | ||
872 | 0x4d01ffff, | ||
873 | 0x00000000, | ||
874 | 0x1000fe40, | ||
875 | 0xaf9d4c00, | ||
876 | 0x3c1f0c40, | ||
877 | 0xaffe4fa8, | ||
878 | 0x3021fffd, | ||
879 | 0xa5610008, | ||
880 | 0x3c0cd3cf, | ||
881 | 0x358ce000, | ||
882 | 0x10000008, | ||
883 | 0x34030002, | ||
884 | 0x3c1f0c40, | ||
885 | 0xaffe4fa8, | ||
886 | 0x11a0fff9, | ||
887 | 0x000df600, | ||
888 | 0x34030003, | ||
889 | 0x019e6025, | ||
890 | 0x01896026, | ||
891 | 0x34840008, | ||
892 | 0x34420002, | ||
893 | 0xad22000c, | ||
894 | 0x95620006, | ||
895 | 0xa5230000, | ||
896 | 0xad220038, | ||
897 | 0x4d01ffff, | ||
898 | 0x00000000, | ||
899 | 0x857e0008, | ||
900 | 0x8f820fa8, | ||
901 | 0x97830fac, | ||
902 | 0xad220004, | ||
903 | 0x33c17fff, | ||
904 | 0xad600010, | ||
905 | 0xa5610008, | ||
906 | 0x1060fe20, | ||
907 | 0xaf9d4c00, | ||
908 | 0xa57e0008, | ||
909 | 0x00031900, | ||
910 | 0x30633ff0, | ||
911 | 0xa5630000, | ||
912 | 0x8f820fb0, | ||
913 | 0x3c030840, | ||
914 | 0xac624c40, | ||
915 | 0x24430008, | ||
916 | 0xad630018, | ||
917 | 0x97830fae, | ||
918 | 0x2442fff4, | ||
919 | 0x00621821, | ||
920 | 0xad63001c, | ||
921 | 0x4d01ffff, | ||
922 | 0x00000000, | ||
923 | 0x8f8d0c40, | ||
924 | 0x8f830c44, | ||
925 | 0xa56d0004, | ||
926 | 0xa56d0006, | ||
927 | 0xad630010, | ||
928 | 0x1000fe0a, | ||
929 | 0xaf9d4c00, | ||
930 | 0x8f820fe0, | ||
931 | 0x00040fc0, | ||
932 | 0x8c430000, | ||
933 | 0x0421001b, | ||
934 | 0x8f9f0fe4, | ||
935 | 0x8c5d0004, | ||
936 | 0xac400004, | ||
937 | 0x1060000e, | ||
938 | 0xac400000, | ||
939 | 0x00000000, | ||
940 | 0x94620028, | ||
941 | 0x00000000, | ||
942 | 0x005f1020, | ||
943 | 0x8c410004, | ||
944 | 0x00000000, | ||
945 | 0x10200003, | ||
946 | 0xac430004, | ||
947 | 0x10000002, | ||
948 | 0xac230024, | ||
949 | 0xac430000, | ||
950 | 0x17a3fff4, | ||
951 | 0x8c630024, | ||
952 | 0x8f820fe0, | ||
953 | 0x3bff0080, | ||
954 | 0x24420008, | ||
955 | 0x34421000, | ||
956 | 0x38421000, | ||
957 | 0xaf820fe0, | ||
958 | 0xaf9f0fe4, | ||
959 | 0x1000fe57, | ||
960 | 0x3084fffe, | ||
961 | 0x10600010, | ||
962 | 0x00000000, | ||
963 | 0x947d0028, | ||
964 | 0x00000000, | ||
965 | 0x03bfe820, | ||
966 | 0x8fa10004, | ||
967 | 0xafa30004, | ||
968 | 0x10200003, | ||
969 | 0x8c5e0004, | ||
970 | 0x10000002, | ||
971 | 0xac230024, | ||
972 | 0xafa30000, | ||
973 | 0x8c610024, | ||
974 | 0x17c3fe48, | ||
975 | 0xac410000, | ||
976 | 0xac400004, | ||
977 | 0xac400000, | ||
978 | 0x1000fe44, | ||
979 | 0x3084fffd, | ||
980 | 0x2c620100, | ||
981 | 0x1440000e, | ||
982 | 0x006a1021, | ||
983 | 0x3143007f, | ||
984 | 0x01431823, | ||
985 | 0x00431823, | ||
986 | 0x3062007f, | ||
987 | 0xa5620028, | ||
988 | 0x00621823, | ||
989 | 0x00031902, | ||
990 | 0x8f820fe0, | ||
991 | 0x2463fff8, | ||
992 | 0x00621821, | ||
993 | 0x34631000, | ||
994 | 0x10000003, | ||
995 | 0x38631000, | ||
996 | 0x34430100, | ||
997 | 0x38630100, | ||
998 | 0x8c620004, | ||
999 | 0x00000000, | ||
1000 | 0x10400003, | ||
1001 | 0xac6b0004, | ||
1002 | 0x03e00008, | ||
1003 | 0xac4b0024, | ||
1004 | 0x03e00008, | ||
1005 | 0xac6b0000, | ||
1006 | 0x00000002, | ||
1007 | 0xa0d0e000, | ||
1008 | 0x00000000, | ||
1009 | 0x00001000, | ||
1010 | 0x00000006, | ||
1011 | 0x00000008, | ||
1012 | 0x00000000, | ||
1013 | 0x00000008, | ||
1014 | 0x00000002, | ||
1015 | 0xa0d0d648, | ||
1016 | 0x00000000, | ||
1017 | 0x00000888, | ||
1018 | 0x00000000, | ||
1019 | 0x00000000, | ||
1020 | 0x00000000, | ||
1021 | 0x00000000, | ||
1022 | 0x24313200, | ||
1023 | 0x24313200, | ||
1024 | 0x24313200, | ||
1025 | 0x00000000, | ||
1026 | 0x244d4352, | ||
1027 | 0x2420436f, | ||
1028 | 0x70797269, | ||
1029 | 0x67687420, | ||
1030 | 0x28632920, | ||
1031 | 0x4d616467, | ||
1032 | 0x65204e65, | ||
1033 | 0x74776f72, | ||
1034 | 0x6b73204c, | ||
1035 | 0x74642031, | ||
1036 | 0x3939352e, | ||
1037 | 0x20416c6c, | ||
1038 | 0x20726967, | ||
1039 | 0x68747320, | ||
1040 | 0x72657365, | ||
1041 | 0x72766564, | ||
1042 | 0x2e004d61, | ||
1043 | 0x64676520, | ||
1044 | 0x416d6261, | ||
1045 | 0x73736164, | ||
1046 | 0x6f722076, | ||
1047 | 0x312e3031, | ||
1048 | 0x00000000, | ||
1049 | 0x00000001, | ||
1050 | 0x00000001, | ||
1051 | 0x00000000, | ||
1052 | 0x00000000, | ||
1053 | 0x00000000, | ||
1054 | 0x00000000, | ||
1055 | 0x00000000, | ||
1056 | 0x00000000, | ||
1057 | 0x00000000, | ||
1058 | 0x00000000, | ||
1059 | 0x00000000, | ||
1060 | 0x00000000, | ||
1061 | 0x00000000, | ||
1062 | 0x00000000, | ||
1063 | 0x00000000, | ||
1064 | 0x00000000, | ||
1065 | 0x00000000, | ||
1066 | 0x00000000, | ||
1067 | 0x00000000, | ||
1068 | 0x00000000, | ||
1069 | 0x00000000, | ||
1070 | 0x00000000, | ||
1071 | 0x00000000, | ||
1072 | 0x00000000, | ||
1073 | 0x00000000, | ||
1074 | 0x00000000, | ||
1075 | 0x00000000, | ||
1076 | 0x00000000, | ||
1077 | 0x00000000, | ||
1078 | 0x00000000, | ||
1079 | 0x00000000, | ||
1080 | 0x00000000, | ||
1081 | 0x00000000, | ||
1082 | 0x00000000, | ||
1083 | 0x00000000, | ||
1084 | 0xfff04000, | ||
1085 | 0x00000000, | ||
1086 | 0x0c343e2d, | ||
1087 | 0x00000000, | ||
1088 | 0x3c1ca0d1, | ||
1089 | 0x279c5638, | ||
1090 | 0x3c1da0d1, | ||
1091 | 0x27bddfd0, | ||
1092 | 0x3c08a0d1, | ||
1093 | 0x2508dfd0, | ||
1094 | 0xaf878008, | ||
1095 | 0x0c343c13, | ||
1096 | 0x00000000, | ||
1097 | 0x24040003, | ||
1098 | 0x0097000d, | ||
1099 | 0x3c08bfc0, | ||
1100 | 0x35080230, | ||
1101 | 0x8d080000, | ||
1102 | 0x00000000, | ||
1103 | 0x01000008, | ||
1104 | 0x00000000, | ||
1105 | 0x27bdffd0, | ||
1106 | 0xafbf001c, | ||
1107 | 0xafb10018, | ||
1108 | 0xafb00014, | ||
1109 | 0x3c11fff0, | ||
1110 | 0x00008021, | ||
1111 | 0x3c180056, | ||
1112 | 0x37183b79, | ||
1113 | 0x26190200, | ||
1114 | 0x17200002, | ||
1115 | 0x0319001a, | ||
1116 | 0x0007000d, | ||
1117 | 0x2401ffff, | ||
1118 | 0x17210005, | ||
1119 | 0x00000000, | ||
1120 | 0x3c018000, | ||
1121 | 0x17010002, | ||
1122 | 0x00000000, | ||
1123 | 0x0006000d, | ||
1124 | 0x00001012, | ||
1125 | 0x00101840, | ||
1126 | 0x3c05a0d1, | ||
1127 | 0x24a5d6cc, | ||
1128 | 0x00a32021, | ||
1129 | 0xa4820000, | ||
1130 | 0x26100001, | ||
1131 | 0x2a010200, | ||
1132 | 0x1420ffea, | ||
1133 | 0x00000000, | ||
1134 | 0x3c06a0d1, | ||
1135 | 0x24c6f9e4, | ||
1136 | 0x3c07a0d1, | ||
1137 | 0x24e7d648, | ||
1138 | 0xace60000, | ||
1139 | 0x3c08a0d1, | ||
1140 | 0x2508fb14, | ||
1141 | 0xace80004, | ||
1142 | 0x3c09a0d1, | ||
1143 | 0x2529fc94, | ||
1144 | 0xace90008, | ||
1145 | 0x3c0aa0d1, | ||
1146 | 0x254afcd4, | ||
1147 | 0xacea000c, | ||
1148 | 0x3c0ba0d1, | ||
1149 | 0x256bfba8, | ||
1150 | 0xaceb0010, | ||
1151 | 0x3c0ca0d1, | ||
1152 | 0x258cfbc4, | ||
1153 | 0xacec0014, | ||
1154 | 0x3c0da0d1, | ||
1155 | 0x25adfbe0, | ||
1156 | 0xaced0018, | ||
1157 | 0x3c0ea0d1, | ||
1158 | 0x25cefbfc, | ||
1159 | 0xacee001c, | ||
1160 | 0x3c0fa0d1, | ||
1161 | 0x25effc18, | ||
1162 | 0xacef0020, | ||
1163 | 0x3c18a0d1, | ||
1164 | 0x2718fc34, | ||
1165 | 0xacf80024, | ||
1166 | 0x3c19a0d1, | ||
1167 | 0x2739fc50, | ||
1168 | 0xacf90028, | ||
1169 | 0x3c02a0d1, | ||
1170 | 0x2442fc60, | ||
1171 | 0xace2002c, | ||
1172 | 0x3c03a0d1, | ||
1173 | 0x2463fc70, | ||
1174 | 0xace30030, | ||
1175 | 0x3c04a0d1, | ||
1176 | 0x2484fc80, | ||
1177 | 0xace40034, | ||
1178 | 0x3c05a0d1, | ||
1179 | 0x24a5fcb4, | ||
1180 | 0xace50038, | ||
1181 | 0x3c06a0d1, | ||
1182 | 0x24c6fe08, | ||
1183 | 0xace6003c, | ||
1184 | 0x3c08a0d1, | ||
1185 | 0x2508fe90, | ||
1186 | 0xace80040, | ||
1187 | 0x3c09a0d1, | ||
1188 | 0x2529fa38, | ||
1189 | 0xace90044, | ||
1190 | 0x3c0aa0d1, | ||
1191 | 0x254afa74, | ||
1192 | 0xacea0048, | ||
1193 | 0x24100013, | ||
1194 | 0x3c0ba0d1, | ||
1195 | 0x256bf9d8, | ||
1196 | 0x00106080, | ||
1197 | 0x3c0ea0d1, | ||
1198 | 0x25ced648, | ||
1199 | 0x01cc6821, | ||
1200 | 0xadab0000, | ||
1201 | 0x26100001, | ||
1202 | 0x2a010020, | ||
1203 | 0x1420fff6, | ||
1204 | 0x00000000, | ||
1205 | 0x8f988000, | ||
1206 | 0x00000000, | ||
1207 | 0xaf000100, | ||
1208 | 0x8f828000, | ||
1209 | 0x241903ff, | ||
1210 | 0xa4590202, | ||
1211 | 0x00008021, | ||
1212 | 0x8f868000, | ||
1213 | 0x24030fff, | ||
1214 | 0x00102040, | ||
1215 | 0x24c70380, | ||
1216 | 0x00e42821, | ||
1217 | 0xa4a30000, | ||
1218 | 0x26100001, | ||
1219 | 0x2a010008, | ||
1220 | 0x1420fff7, | ||
1221 | 0x00000000, | ||
1222 | 0x8f898000, | ||
1223 | 0x34089c40, | ||
1224 | 0xad2803a0, | ||
1225 | 0x8f8b8000, | ||
1226 | 0x3c0a00ff, | ||
1227 | 0x354affff, | ||
1228 | 0xad6a03a4, | ||
1229 | 0x00008021, | ||
1230 | 0x8f8f8000, | ||
1231 | 0x240c0fff, | ||
1232 | 0x00106840, | ||
1233 | 0x25f80300, | ||
1234 | 0x030d7021, | ||
1235 | 0xa5cc0000, | ||
1236 | 0x26100001, | ||
1237 | 0x2a010008, | ||
1238 | 0x1420fff7, | ||
1239 | 0x00000000, | ||
1240 | 0x8f828000, | ||
1241 | 0x34199c40, | ||
1242 | 0xac590320, | ||
1243 | 0x8f848000, | ||
1244 | 0x3c0300ff, | ||
1245 | 0x3463ffff, | ||
1246 | 0xac830324, | ||
1247 | 0x8f868000, | ||
1248 | 0x240502ff, | ||
1249 | 0xa4c50202, | ||
1250 | 0x3c08a0c0, | ||
1251 | 0x35080180, | ||
1252 | 0x3c09a0d1, | ||
1253 | 0x2529d5b8, | ||
1254 | 0x250a0028, | ||
1255 | 0x8d0b0000, | ||
1256 | 0x8d0c0004, | ||
1257 | 0xad2b0000, | ||
1258 | 0xad2c0004, | ||
1259 | 0x25080008, | ||
1260 | 0x150afffa, | ||
1261 | 0x25290008, | ||
1262 | 0x40026000, | ||
1263 | 0x00000000, | ||
1264 | 0xafa20028, | ||
1265 | 0x24030022, | ||
1266 | 0x3c04a0e0, | ||
1267 | 0x34840014, | ||
1268 | 0xac830000, | ||
1269 | 0x8fa50028, | ||
1270 | 0x00000000, | ||
1271 | 0x34a61001, | ||
1272 | 0x00c01021, | ||
1273 | 0xafa60028, | ||
1274 | 0x3c07ffbf, | ||
1275 | 0x34e7ffff, | ||
1276 | 0x00c73824, | ||
1277 | 0x00e01021, | ||
1278 | 0xafa70028, | ||
1279 | 0x40876000, | ||
1280 | 0x00000000, | ||
1281 | 0x3c080002, | ||
1282 | 0x3508d890, | ||
1283 | 0x3c09fffe, | ||
1284 | 0x35290130, | ||
1285 | 0xad280000, | ||
1286 | 0x8faa0028, | ||
1287 | 0x3c0bf000, | ||
1288 | 0x014b5825, | ||
1289 | 0x01601021, | ||
1290 | 0xafab0028, | ||
1291 | 0x01606021, | ||
1292 | 0x408c6000, | ||
1293 | 0x00000000, | ||
1294 | 0x00008021, | ||
1295 | 0x00107080, | ||
1296 | 0x022e7821, | ||
1297 | 0xade00000, | ||
1298 | 0x26100001, | ||
1299 | 0x2a010400, | ||
1300 | 0x1420fffa, | ||
1301 | 0x00000000, | ||
1302 | 0x24180001, | ||
1303 | 0x3c19a0e8, | ||
1304 | 0xaf380000, | ||
1305 | 0x24020011, | ||
1306 | 0x3c03a0f0, | ||
1307 | 0x34630017, | ||
1308 | 0xa0620000, | ||
1309 | 0x3c04f0eb, | ||
1310 | 0x34840070, | ||
1311 | 0x3c05fff0, | ||
1312 | 0x34a54a00, | ||
1313 | 0xaca40000, | ||
1314 | 0x3c06fceb, | ||
1315 | 0x34c60070, | ||
1316 | 0xaca60000, | ||
1317 | 0x3c07fff0, | ||
1318 | 0x34e74700, | ||
1319 | 0xace00000, | ||
1320 | 0x00008021, | ||
1321 | 0x3c08fff0, | ||
1322 | 0x35080fc0, | ||
1323 | 0x3c09fff0, | ||
1324 | 0x35294500, | ||
1325 | 0xad280000, | ||
1326 | 0x26100001, | ||
1327 | 0x2a010004, | ||
1328 | 0x1420fff8, | ||
1329 | 0x00000000, | ||
1330 | 0x00008021, | ||
1331 | 0x3c0adead, | ||
1332 | 0x00105980, | ||
1333 | 0x3c0100d1, | ||
1334 | 0x002b0821, | ||
1335 | 0xac2a003c, | ||
1336 | 0x3c0100d1, | ||
1337 | 0x002b0821, | ||
1338 | 0xac200030, | ||
1339 | 0x3c0100d1, | ||
1340 | 0x002b0821, | ||
1341 | 0xac200038, | ||
1342 | 0x240dffff, | ||
1343 | 0x3c0100d1, | ||
1344 | 0x002b0821, | ||
1345 | 0xac2d0014, | ||
1346 | 0x00107100, | ||
1347 | 0x3c0100d1, | ||
1348 | 0x002b0821, | ||
1349 | 0xa42e0000, | ||
1350 | 0x3c0100d1, | ||
1351 | 0x002b0821, | ||
1352 | 0xa4200004, | ||
1353 | 0x24180020, | ||
1354 | 0x3c0100d1, | ||
1355 | 0x002b0821, | ||
1356 | 0xa4380008, | ||
1357 | 0x3c0100d1, | ||
1358 | 0x002b0821, | ||
1359 | 0xac200010, | ||
1360 | 0x26100001, | ||
1361 | 0x2a010400, | ||
1362 | 0x1420ffe0, | ||
1363 | 0x00000000, | ||
1364 | 0x00008021, | ||
1365 | 0x001018c0, | ||
1366 | 0x3c05a0d1, | ||
1367 | 0x24a5e000, | ||
1368 | 0x00a32021, | ||
1369 | 0xac800000, | ||
1370 | 0x3c07a0d1, | ||
1371 | 0x24e7e000, | ||
1372 | 0x24e80004, | ||
1373 | 0x01033021, | ||
1374 | 0xacc00000, | ||
1375 | 0x26100001, | ||
1376 | 0x2a010009, | ||
1377 | 0x1420fff3, | ||
1378 | 0x00000000, | ||
1379 | 0x24090380, | ||
1380 | 0x3c0afff0, | ||
1381 | 0x354a4d00, | ||
1382 | 0xad490000, | ||
1383 | 0x3c0ca080, | ||
1384 | 0x358c009c, | ||
1385 | 0xad800000, | ||
1386 | 0x3c0da080, | ||
1387 | 0x35ad00a0, | ||
1388 | 0xada00000, | ||
1389 | 0x3c0e1100, | ||
1390 | 0x3c0fa080, | ||
1391 | 0x35ef00a8, | ||
1392 | 0xadee0000, | ||
1393 | 0x41010003, | ||
1394 | 0x00000000, | ||
1395 | 0x4100ffff, | ||
1396 | 0x00000000, | ||
1397 | 0x3c18a080, | ||
1398 | 0x371800e0, | ||
1399 | 0x8f190000, | ||
1400 | 0x3c01a0d1, | ||
1401 | 0xac39d6c8, | ||
1402 | 0x0c343d43, | ||
1403 | 0x03202021, | ||
1404 | 0x8fb00014, | ||
1405 | 0x8fbf001c, | ||
1406 | 0x8fb10018, | ||
1407 | 0x03e00008, | ||
1408 | 0x27bd0030, | ||
1409 | 0x0080b821, | ||
1410 | 0x3c1cfff0, | ||
1411 | 0xa3800c84, | ||
1412 | 0xa3800c88, | ||
1413 | 0x8f904400, | ||
1414 | 0x00002021, | ||
1415 | 0xaf800cbc, | ||
1416 | 0x240200a8, | ||
1417 | 0x27830f00, | ||
1418 | 0x2c5d0040, | ||
1419 | 0x17a0000c, | ||
1420 | 0x3c1dffb0, | ||
1421 | 0x03a3e826, | ||
1422 | 0xafb74000, | ||
1423 | 0x00000000, | ||
1424 | 0x00000000, | ||
1425 | 0x00000000, | ||
1426 | 0x4d01ffff, | ||
1427 | 0x00000000, | ||
1428 | 0x2442ffc0, | ||
1429 | 0x24630040, | ||
1430 | 0x1000fff3, | ||
1431 | 0x26f70040, | ||
1432 | 0x1040000d, | ||
1433 | 0x00000000, | ||
1434 | 0x0002ee00, | ||
1435 | 0x3c010040, | ||
1436 | 0x03a1e825, | ||
1437 | 0x3c01fff0, | ||
1438 | 0x03a1e826, | ||
1439 | 0x03a3e826, | ||
1440 | 0xafb74000, | ||
1441 | 0x00000000, | ||
1442 | 0x00000000, | ||
1443 | 0x00000000, | ||
1444 | 0x4d01ffff, | ||
1445 | 0x00000000, | ||
1446 | 0x3c05a080, | ||
1447 | 0x8f820f08, | ||
1448 | 0x00000000, | ||
1449 | 0xaf820fd4, | ||
1450 | 0xaf820fd0, | ||
1451 | 0xaca200c4, | ||
1452 | 0x8f820f10, | ||
1453 | 0x00000000, | ||
1454 | 0x00021d82, | ||
1455 | 0xaf830fc0, | ||
1456 | 0x00031d80, | ||
1457 | 0x00431023, | ||
1458 | 0x3c01a080, | ||
1459 | 0x00411025, | ||
1460 | 0xaf820fc4, | ||
1461 | 0xaf820f10, | ||
1462 | 0x8f820f14, | ||
1463 | 0x00000000, | ||
1464 | 0x00431023, | ||
1465 | 0x3c01a080, | ||
1466 | 0x00411025, | ||
1467 | 0xaf820f14, | ||
1468 | 0x24030003, | ||
1469 | 0x279d0f18, | ||
1470 | 0x24be00c8, | ||
1471 | 0x27810d00, | ||
1472 | 0x8fa20000, | ||
1473 | 0x00000000, | ||
1474 | 0xafa20010, | ||
1475 | 0xafc20000, | ||
1476 | 0xafa10008, | ||
1477 | 0xafa1000c, | ||
1478 | 0x8fa20014, | ||
1479 | 0x00000000, | ||
1480 | 0xafa2001c, | ||
1481 | 0x27bd0024, | ||
1482 | 0x27de0004, | ||
1483 | 0x24210040, | ||
1484 | 0x1460fff3, | ||
1485 | 0x2463ffff, | ||
1486 | 0x8f820f00, | ||
1487 | 0x00000000, | ||
1488 | 0xaf820fc8, | ||
1489 | 0xaca200c0, | ||
1490 | 0x27820800, | ||
1491 | 0x2403000f, | ||
1492 | 0xac400000, | ||
1493 | 0x24420004, | ||
1494 | 0x1460fffd, | ||
1495 | 0x2463ffff, | ||
1496 | 0x8f830fc0, | ||
1497 | 0x00000000, | ||
1498 | 0xaf834d00, | ||
1499 | 0x8f834d00, | ||
1500 | 0x8f830f14, | ||
1501 | 0x8f820f10, | ||
1502 | 0x2463fffc, | ||
1503 | 0xac400000, | ||
1504 | 0x1443fffe, | ||
1505 | 0x24420004, | ||
1506 | 0x24020380, | ||
1507 | 0xaf824d00, | ||
1508 | 0x279d0f18, | ||
1509 | 0x27a10090, | ||
1510 | 0x8fa20014, | ||
1511 | 0x8fa30018, | ||
1512 | 0x00000000, | ||
1513 | 0x00621823, | ||
1514 | 0x2c7f0040, | ||
1515 | 0x17e00009, | ||
1516 | 0x3c1f0040, | ||
1517 | 0x37ff0800, | ||
1518 | 0x03a0f021, | ||
1519 | 0x4d01ffff, | ||
1520 | 0x00000000, | ||
1521 | 0xafe20000, | ||
1522 | 0x24420040, | ||
1523 | 0x1000fff6, | ||
1524 | 0x2463ffc0, | ||
1525 | 0x10600006, | ||
1526 | 0x37ff0800, | ||
1527 | 0x00031e00, | ||
1528 | 0x03e3f825, | ||
1529 | 0x4d01ffff, | ||
1530 | 0x00000000, | ||
1531 | 0xafe20000, | ||
1532 | 0x27bd0024, | ||
1533 | 0x17a1ffe8, | ||
1534 | 0x00000000, | ||
1535 | 0x00003821, | ||
1536 | 0x8fc20014, | ||
1537 | 0x8fc30018, | ||
1538 | 0x00000000, | ||
1539 | 0x00621823, | ||
1540 | 0x2c7f0040, | ||
1541 | 0x13e00004, | ||
1542 | 0x3c1f0040, | ||
1543 | 0x00030e00, | ||
1544 | 0x10000002, | ||
1545 | 0x03e1f825, | ||
1546 | 0x24030040, | ||
1547 | 0x37ff0800, | ||
1548 | 0x241e03e7, | ||
1549 | 0x00000821, | ||
1550 | 0x4d01ffff, | ||
1551 | 0x00000000, | ||
1552 | 0xafe20000, | ||
1553 | 0x00230821, | ||
1554 | 0x4900fffb, | ||
1555 | 0x00000000, | ||
1556 | 0x87804002, | ||
1557 | 0x17c0fff8, | ||
1558 | 0x27deffff, | ||
1559 | 0x14e00004, | ||
1560 | 0x34e74000, | ||
1561 | 0x03e7f825, | ||
1562 | 0x1000fff0, | ||
1563 | 0xaf810c60, | ||
1564 | 0xaf810c5c, | ||
1565 | 0x3c01a0d1, | ||
1566 | 0x8c22d6c8, | ||
1567 | 0x00000000, | ||
1568 | 0x3c01a080, | ||
1569 | 0xac2200e0, | ||
1570 | 0x3c01a080, | ||
1571 | 0x8c2000e0, | ||
1572 | 0xaf800fb4, | ||
1573 | 0xa7800fb8, | ||
1574 | 0xa7800fba, | ||
1575 | 0xa7800fbc, | ||
1576 | 0xa7800fbe, | ||
1577 | 0x27820cc0, | ||
1578 | 0xaf820fdc, | ||
1579 | 0xaf820fd8, | ||
1580 | 0x3c02a0d1, | ||
1581 | 0x2442dacc, | ||
1582 | 0xaf820c4c, | ||
1583 | 0xaf820c50, | ||
1584 | 0x24420400, | ||
1585 | 0xaf820c54, | ||
1586 | 0x2402001e, | ||
1587 | 0x3c03fff0, | ||
1588 | 0x247d0040, | ||
1589 | 0xac7d0008, | ||
1590 | 0x03a01821, | ||
1591 | 0x1440fffc, | ||
1592 | 0x2442ffff, | ||
1593 | 0x3c1dfff0, | ||
1594 | 0xac7d0008, | ||
1595 | 0x3c02c704, | ||
1596 | 0x3442dd7b, | ||
1597 | 0xaf820c58, | ||
1598 | 0x3c070000, | ||
1599 | 0x24e70158, | ||
1600 | 0x08343fa9, | ||
1601 | 0x00000000, | ||
1602 | 0x8e620038, | ||
1603 | 0x00000000, | ||
1604 | 0x14400005, | ||
1605 | 0x8f830c94, | ||
1606 | 0x12a00022, | ||
1607 | 0x24630001, | ||
1608 | 0x10000020, | ||
1609 | 0xaf830c94, | ||
1610 | 0xaf820fb4, | ||
1611 | 0x3262ffc0, | ||
1612 | 0x00021182, | ||
1613 | 0x8663002a, | ||
1614 | 0xa7820fb8, | ||
1615 | 0x3c02a000, | ||
1616 | 0xaf820fbc, | ||
1617 | 0xa7830fba, | ||
1618 | 0x867e0008, | ||
1619 | 0x279d0f18, | ||
1620 | 0x33de0060, | ||
1621 | 0x03bee821, | ||
1622 | 0x001ef0c2, | ||
1623 | 0x03bee821, | ||
1624 | 0x8fa2001c, | ||
1625 | 0x3c030c40, | ||
1626 | 0x4d01ffff, | ||
1627 | 0x00000000, | ||
1628 | 0x8f974c00, | ||
1629 | 0xac620fb4, | ||
1630 | 0x8fa30018, | ||
1631 | 0x2442000c, | ||
1632 | 0x14430003, | ||
1633 | 0x00000000, | ||
1634 | 0x8fa20014, | ||
1635 | 0x00000000, | ||
1636 | 0xafa2001c, | ||
1637 | 0x4d01ffff, | ||
1638 | 0x00000000, | ||
1639 | 0xaca500e4, | ||
1640 | 0xaf974c00, | ||
1641 | 0x03e00008, | ||
1642 | 0xae60003c, | ||
1643 | 0x3c0da0d1, | ||
1644 | 0x25add500, | ||
1645 | 0x11a00021, | ||
1646 | 0x00000000, | ||
1647 | 0x8da90000, | ||
1648 | 0x00000000, | ||
1649 | 0x1120001d, | ||
1650 | 0x00000000, | ||
1651 | 0x8daa0004, | ||
1652 | 0x8dab0008, | ||
1653 | 0x8dac000c, | ||
1654 | 0x00094740, | ||
1655 | 0x05010004, | ||
1656 | 0x00000000, | ||
1657 | 0x3c08a0d1, | ||
1658 | 0x2508d638, | ||
1659 | 0x01485021, | ||
1660 | 0x00094780, | ||
1661 | 0x05010007, | ||
1662 | 0x00000000, | ||
1663 | 0x1180000d, | ||
1664 | 0x00000000, | ||
1665 | 0xad400000, | ||
1666 | 0x254a0004, | ||
1667 | 0x1000fffb, | ||
1668 | 0x258cfffc, | ||
1669 | 0x11800007, | ||
1670 | 0x00000000, | ||
1671 | 0x8d6e0000, | ||
1672 | 0x256b0004, | ||
1673 | 0xad4e0000, | ||
1674 | 0x254a0004, | ||
1675 | 0x1000fff9, | ||
1676 | 0x258cfffc, | ||
1677 | 0x1000ffe1, | ||
1678 | 0x25ad0010, | ||
1679 | 0x03e00008, | ||
1680 | 0x00000000, | ||
1681 | 0x3c021040, | ||
1682 | 0xac574ff0, | ||
1683 | 0x00000000, | ||
1684 | 0x00000000, | ||
1685 | 0x00000000, | ||
1686 | 0x00000000, | ||
1687 | 0x4d01ffff, | ||
1688 | 0x00000000, | ||
1689 | 0x8f820ffc, | ||
1690 | 0x00000000, | ||
1691 | 0x3042001f, | ||
1692 | 0x00021080, | ||
1693 | 0x3c17a0d1, | ||
1694 | 0x02e2b821, | ||
1695 | 0x26f7d648, | ||
1696 | 0x8ef70000, | ||
1697 | 0x00000000, | ||
1698 | 0x02e00008, | ||
1699 | 0x00000000, | ||
1700 | 0x2402ffff, | ||
1701 | 0xaf820ffc, | ||
1702 | 0x8f970fc8, | ||
1703 | 0x3c021040, | ||
1704 | 0xac570ff0, | ||
1705 | 0x8f820f04, | ||
1706 | 0x26f70010, | ||
1707 | 0x16e20004, | ||
1708 | 0xaf970fc8, | ||
1709 | 0x8f970f00, | ||
1710 | 0x00000000, | ||
1711 | 0xaf970fc8, | ||
1712 | 0x4d01ffff, | ||
1713 | 0x00000000, | ||
1714 | 0x03e00008, | ||
1715 | 0x00000000, | ||
1716 | 0x3c1fa0d1, | ||
1717 | 0x27fff02c, | ||
1718 | 0x1000ffed, | ||
1719 | 0x8f970ff0, | ||
1720 | 0x3c0200d1, | ||
1721 | 0x32f703ff, | ||
1722 | 0x0017b980, | ||
1723 | 0x02e2b825, | ||
1724 | 0xaee0003c, | ||
1725 | 0x2402ffff, | ||
1726 | 0xaee20030, | ||
1727 | 0xaee20014, | ||
1728 | 0x97830ff4, | ||
1729 | 0x97820ff8, | ||
1730 | 0x3c1d0000, | ||
1731 | 0x27bd0698, | ||
1732 | 0xa6e30008, | ||
1733 | 0xa6e20002, | ||
1734 | 0xaf9f0fe8, | ||
1735 | 0x03a0f809, | ||
1736 | 0xa6e2002c, | ||
1737 | 0x8f9f0fe8, | ||
1738 | 0x1000ffd9, | ||
1739 | 0xaee2000c, | ||
1740 | 0x8f970ff0, | ||
1741 | 0x3c0200d1, | ||
1742 | 0x32f703ff, | ||
1743 | 0x0017b980, | ||
1744 | 0x02e2b825, | ||
1745 | 0x97820ff4, | ||
1746 | 0x3c030000, | ||
1747 | 0x24630698, | ||
1748 | 0xa6e20002, | ||
1749 | 0xaf9f0fe8, | ||
1750 | 0x0060f809, | ||
1751 | 0xa6e2002c, | ||
1752 | 0x8f9f0fe8, | ||
1753 | 0x1000ffca, | ||
1754 | 0xaee2000c, | ||
1755 | 0x8f970ff0, | ||
1756 | 0x3c0200d1, | ||
1757 | 0x32f703ff, | ||
1758 | 0x0017b980, | ||
1759 | 0x02e2b825, | ||
1760 | 0x97820ff4, | ||
1761 | 0x00000000, | ||
1762 | 0x96e30008, | ||
1763 | 0xa6e20008, | ||
1764 | 0x00431026, | ||
1765 | 0x30420060, | ||
1766 | 0x1040ffbd, | ||
1767 | 0x8ee2003c, | ||
1768 | 0xaee0003c, | ||
1769 | 0x1040ffba, | ||
1770 | 0x3c028800, | ||
1771 | 0xaf820fbc, | ||
1772 | 0x8ee20038, | ||
1773 | 0xaee00038, | ||
1774 | 0x30630060, | ||
1775 | 0x279d0f18, | ||
1776 | 0x03a3e821, | ||
1777 | 0x000318c2, | ||
1778 | 0x03a3e821, | ||
1779 | 0x8fa3001c, | ||
1780 | 0x1040ffaf, | ||
1781 | 0xaf820fb4, | ||
1782 | 0x3c020c40, | ||
1783 | 0xac430fb4, | ||
1784 | 0x8fa20018, | ||
1785 | 0x2463000c, | ||
1786 | 0x14430003, | ||
1787 | 0x00000000, | ||
1788 | 0x8fa30014, | ||
1789 | 0x00000000, | ||
1790 | 0xafa3001c, | ||
1791 | 0x4d01ffff, | ||
1792 | 0x00000000, | ||
1793 | 0x1000ffa2, | ||
1794 | 0x00000000, | ||
1795 | 0x8f970ff0, | ||
1796 | 0x3c0200d1, | ||
1797 | 0xa7970fb8, | ||
1798 | 0x0017b980, | ||
1799 | 0x32f7ffc0, | ||
1800 | 0x02e2b821, | ||
1801 | 0xaee00030, | ||
1802 | 0x3c02dead, | ||
1803 | 0x8ee3003c, | ||
1804 | 0xaee2003c, | ||
1805 | 0x8ee20038, | ||
1806 | 0x1060ff95, | ||
1807 | 0xaee00038, | ||
1808 | 0x3c038800, | ||
1809 | 0xaf830fbc, | ||
1810 | 0x86e30008, | ||
1811 | 0x27970f18, | ||
1812 | 0x30630060, | ||
1813 | 0x02e3b821, | ||
1814 | 0x000318c2, | ||
1815 | 0x02e3b821, | ||
1816 | 0x8ee3001c, | ||
1817 | 0x1040ff8a, | ||
1818 | 0xaf820fb4, | ||
1819 | 0x3c020c40, | ||
1820 | 0xac430fb4, | ||
1821 | 0x8ee20018, | ||
1822 | 0x2463000c, | ||
1823 | 0x14430003, | ||
1824 | 0x00000000, | ||
1825 | 0x8ee30014, | ||
1826 | 0x00000000, | ||
1827 | 0xaee3001c, | ||
1828 | 0x4d01ffff, | ||
1829 | 0x00000000, | ||
1830 | 0x1000ff7d, | ||
1831 | 0x00000000, | ||
1832 | 0x8f820ff0, | ||
1833 | 0x8f970ff4, | ||
1834 | 0x90410000, | ||
1835 | 0x00000000, | ||
1836 | 0x00370825, | ||
1837 | 0x1000ff76, | ||
1838 | 0xa0410000, | ||
1839 | 0x8f820ff0, | ||
1840 | 0x8f970ff4, | ||
1841 | 0x94410000, | ||
1842 | 0x00000000, | ||
1843 | 0x00370825, | ||
1844 | 0x1000ff6f, | ||
1845 | 0xa4410000, | ||
1846 | 0x8f820ff0, | ||
1847 | 0x8f970ff4, | ||
1848 | 0x8c410000, | ||
1849 | 0x00000000, | ||
1850 | 0x00370825, | ||
1851 | 0x1000ff68, | ||
1852 | 0xac410000, | ||
1853 | 0x8f820ff0, | ||
1854 | 0x8f970ff4, | ||
1855 | 0x90410000, | ||
1856 | 0x02e0b827, | ||
1857 | 0x00370824, | ||
1858 | 0x1000ff61, | ||
1859 | 0xa0410000, | ||
1860 | 0x8f820ff0, | ||
1861 | 0x8f970ff4, | ||
1862 | 0x94410000, | ||
1863 | 0x02e0b827, | ||
1864 | 0x00370824, | ||
1865 | 0x1000ff5a, | ||
1866 | 0xa4410000, | ||
1867 | 0x8f820ff0, | ||
1868 | 0x8f970ff4, | ||
1869 | 0x8c410000, | ||
1870 | 0x02e0b827, | ||
1871 | 0x00370824, | ||
1872 | 0x1000ff53, | ||
1873 | 0xac410000, | ||
1874 | 0x8f820ff0, | ||
1875 | 0x8f970ff4, | ||
1876 | 0x1000ff4f, | ||
1877 | 0xa0570000, | ||
1878 | 0x8f820ff0, | ||
1879 | 0x8f970ff4, | ||
1880 | 0x1000ff4b, | ||
1881 | 0xa4570000, | ||
1882 | 0x8f820ff0, | ||
1883 | 0x8f970ff4, | ||
1884 | 0x1000ff47, | ||
1885 | 0xac570000, | ||
1886 | 0x8f820ff0, | ||
1887 | 0x00000000, | ||
1888 | 0x8c420000, | ||
1889 | 0x1000ff42, | ||
1890 | 0xaf820ff4, | ||
1891 | 0x3c01a0c2, | ||
1892 | 0x8c22c000, | ||
1893 | 0x00000000, | ||
1894 | 0xaf820ff0, | ||
1895 | 0x3c01a0c2, | ||
1896 | 0x8c22c004, | ||
1897 | 0x1000ff3a, | ||
1898 | 0xaf820ff4, | ||
1899 | 0x3c01a0d1, | ||
1900 | 0x8c22d5ac, | ||
1901 | 0x00000000, | ||
1902 | 0xaf820ff0, | ||
1903 | 0x3c01a0d1, | ||
1904 | 0x8c22d5b0, | ||
1905 | 0x1000ff32, | ||
1906 | 0xaf820ff4, | ||
1907 | 0x3c02a0f0, | ||
1908 | 0xac400000, | ||
1909 | 0x90570153, | ||
1910 | 0x00000000, | ||
1911 | 0xa3970c80, | ||
1912 | 0x90570157, | ||
1913 | 0x00000000, | ||
1914 | 0xa3970c81, | ||
1915 | 0x9057015b, | ||
1916 | 0x00000000, | ||
1917 | 0xa3970c87, | ||
1918 | 0x9057015f, | ||
1919 | 0x00000000, | ||
1920 | 0xa3970c86, | ||
1921 | 0x90570163, | ||
1922 | 0x00000000, | ||
1923 | 0x32f70007, | ||
1924 | 0xa3970c85, | ||
1925 | 0x90570193, | ||
1926 | 0x00000000, | ||
1927 | 0xa3970c8b, | ||
1928 | 0x90570197, | ||
1929 | 0x00000000, | ||
1930 | 0xa3970c8a, | ||
1931 | 0x9057019b, | ||
1932 | 0x00000000, | ||
1933 | 0x32f70007, | ||
1934 | 0xa3970c89, | ||
1935 | 0x9057000b, | ||
1936 | 0x00000000, | ||
1937 | 0x32f700e0, | ||
1938 | 0x00170942, | ||
1939 | 0x90570047, | ||
1940 | 0x00000000, | ||
1941 | 0x32f70078, | ||
1942 | 0x00370825, | ||
1943 | 0x90570067, | ||
1944 | 0x00000000, | ||
1945 | 0x32f7000f, | ||
1946 | 0x0017b9c0, | ||
1947 | 0x00370825, | ||
1948 | 0x905700c7, | ||
1949 | 0x00000000, | ||
1950 | 0x32f7002f, | ||
1951 | 0x0017bac0, | ||
1952 | 0x00370825, | ||
1953 | 0x90570147, | ||
1954 | 0x00000000, | ||
1955 | 0x32f7001e, | ||
1956 | 0x0017bc00, | ||
1957 | 0x00370825, | ||
1958 | 0x90570183, | ||
1959 | 0x00000000, | ||
1960 | 0x32f70060, | ||
1961 | 0x0017bc00, | ||
1962 | 0x00370825, | ||
1963 | 0xaf810c8c, | ||
1964 | 0x3c021840, | ||
1965 | 0x8f970fc8, | ||
1966 | 0x00000000, | ||
1967 | 0x8f970ff0, | ||
1968 | 0x00000000, | ||
1969 | 0xac570c80, | ||
1970 | 0x00000000, | ||
1971 | 0x00000000, | ||
1972 | 0x00000000, | ||
1973 | 0x00000000, | ||
1974 | 0x00000000, | ||
1975 | 0x00000000, | ||
1976 | 0x4d01ffff, | ||
1977 | 0x00000000, | ||
1978 | 0x3c02a0d1, | ||
1979 | 0x2442f998, | ||
1980 | 0xaf800c90, | ||
1981 | 0xaf800c94, | ||
1982 | 0x00400008, | ||
1983 | 0x00000000, | ||
1984 | 0x87970ff0, | ||
1985 | 0x3c1300d1, | ||
1986 | 0xa6770008, | ||
1987 | 0x3c030000, | ||
1988 | 0x24630520, | ||
1989 | 0xaf9f0fe8, | ||
1990 | 0x0060f809, | ||
1991 | 0x24020001, | ||
1992 | 0x8f9f0fe8, | ||
1993 | 0x1040feda, | ||
1994 | 0x97970ff0, | ||
1995 | 0x27830f18, | ||
1996 | 0x00771821, | ||
1997 | 0x0017b8c2, | ||
1998 | 0x02e3b821, | ||
1999 | 0x3c028800, | ||
2000 | 0xaf820fbc, | ||
2001 | 0x8e620038, | ||
2002 | 0xa7800fb8, | ||
2003 | 0xaf820fb4, | ||
2004 | 0x8ee3001c, | ||
2005 | 0x3c020c40, | ||
2006 | 0xac430fb4, | ||
2007 | 0x8ee20018, | ||
2008 | 0x2463000c, | ||
2009 | 0x14430004, | ||
2010 | 0xaee3001c, | ||
2011 | 0x8ee30014, | ||
2012 | 0x00000000, | ||
2013 | 0xaee3001c, | ||
2014 | 0x4d01ffff, | ||
2015 | 0x00000000, | ||
2016 | 0x1000ffdf, | ||
2017 | 0x00000000, | ||
2018 | 0x8f820c5c, | ||
2019 | 0x8f830c60, | ||
2020 | 0xaf820ff0, | ||
2021 | 0x1000febe, | ||
2022 | 0xaf830ff4, | ||
2023 | 0x23890800, | ||
2024 | 0x01201821, | ||
2025 | 0x2402000f, | ||
2026 | 0x206c0040, | ||
2027 | 0xac6c0008, | ||
2028 | 0x01801821, | ||
2029 | 0x1440fffc, | ||
2030 | 0x2042ffff, | ||
2031 | 0xac690008, | ||
2032 | 0x278b0c98, | ||
2033 | 0xa5600000, | ||
2034 | 0x2403ffff, | ||
2035 | 0xad630014, | ||
2036 | 0x34020001, | ||
2037 | 0x34420020, | ||
2038 | 0xa5620008, | ||
2039 | 0x278a0e00, | ||
2040 | 0x01401021, | ||
2041 | 0x00001821, | ||
2042 | 0xac400000, | ||
2043 | 0x24630004, | ||
2044 | 0x2c6c0100, | ||
2045 | 0x1580fffc, | ||
2046 | 0x24420004, | ||
2047 | 0x3c02a0d1, | ||
2048 | 0x2442e000, | ||
2049 | 0xaf820fe0, | ||
2050 | 0x3c1800d1, | ||
2051 | 0x01206021, | ||
2052 | 0x00006821, | ||
2053 | 0x00007821, | ||
2054 | 0x00005821, | ||
2055 | 0x00004021, | ||
2056 | 0x40026000, | ||
2057 | 0x00000000, | ||
2058 | 0x34424001, | ||
2059 | 0x40826000, | ||
2060 | 0x3c020000, | ||
2061 | 0x244206f8, | ||
2062 | 0x00400008, | ||
2063 | 0x00000000, | ||
diff --git a/drivers/atm/atmsar11.regions b/drivers/atm/atmsar11.regions new file mode 100644 index 000000000000..42252b7c0de3 --- /dev/null +++ b/drivers/atm/atmsar11.regions | |||
@@ -0,0 +1,6 @@ | |||
1 | /* | ||
2 | See copyright and licensing conditions in ambassador.* files. | ||
3 | */ | ||
4 | { 0x00000080, 993, }, | ||
5 | { 0xa0d0d500, 80, }, | ||
6 | { 0xa0d0f000, 978, }, | ||
diff --git a/drivers/atm/atmsar11.start b/drivers/atm/atmsar11.start new file mode 100644 index 000000000000..dba55e77d8fd --- /dev/null +++ b/drivers/atm/atmsar11.start | |||
@@ -0,0 +1,4 @@ | |||
1 | /* | ||
2 | See copyright and licensing conditions in ambassador.* files. | ||
3 | */ | ||
4 | 0xa0d0f000 | ||
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c new file mode 100644 index 000000000000..f2f01cb82cb4 --- /dev/null +++ b/drivers/atm/atmtcp.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */ | ||
2 | |||
3 | /* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/wait.h> | ||
8 | #include <linux/atmdev.h> | ||
9 | #include <linux/atm_tcp.h> | ||
10 | #include <linux/bitops.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <asm/uaccess.h> | ||
13 | #include <asm/atomic.h> | ||
14 | |||
15 | |||
16 | extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */ | ||
17 | |||
18 | |||
19 | #define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data)) | ||
20 | |||
21 | |||
22 | struct atmtcp_dev_data { | ||
23 | struct atm_vcc *vcc; /* control VCC; NULL if detached */ | ||
24 | int persist; /* non-zero if persistent */ | ||
25 | }; | ||
26 | |||
27 | |||
28 | #define DEV_LABEL "atmtcp" | ||
29 | |||
30 | #define MAX_VPI_BITS 8 /* simplifies life */ | ||
31 | #define MAX_VCI_BITS 16 | ||
32 | |||
33 | |||
34 | /* | ||
35 | * Hairy code ahead: the control VCC may be closed while we're still | ||
36 | * waiting for an answer, so we need to re-validate out_vcc every once | ||
37 | * in a while. | ||
38 | */ | ||
39 | |||
40 | |||
41 | static int atmtcp_send_control(struct atm_vcc *vcc,int type, | ||
42 | const struct atmtcp_control *msg,int flag) | ||
43 | { | ||
44 | DECLARE_WAITQUEUE(wait,current); | ||
45 | struct atm_vcc *out_vcc; | ||
46 | struct sk_buff *skb; | ||
47 | struct atmtcp_control *new_msg; | ||
48 | int old_test; | ||
49 | int error = 0; | ||
50 | |||
51 | out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; | ||
52 | if (!out_vcc) return -EUNATCH; | ||
53 | skb = alloc_skb(sizeof(*msg),GFP_KERNEL); | ||
54 | if (!skb) return -ENOMEM; | ||
55 | mb(); | ||
56 | out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; | ||
57 | if (!out_vcc) { | ||
58 | dev_kfree_skb(skb); | ||
59 | return -EUNATCH; | ||
60 | } | ||
61 | atm_force_charge(out_vcc,skb->truesize); | ||
62 | new_msg = (struct atmtcp_control *) skb_put(skb,sizeof(*new_msg)); | ||
63 | *new_msg = *msg; | ||
64 | new_msg->hdr.length = ATMTCP_HDR_MAGIC; | ||
65 | new_msg->type = type; | ||
66 | memset(&new_msg->vcc,0,sizeof(atm_kptr_t)); | ||
67 | *(struct atm_vcc **) &new_msg->vcc = vcc; | ||
68 | old_test = test_bit(flag,&vcc->flags); | ||
69 | out_vcc->push(out_vcc,skb); | ||
70 | add_wait_queue(sk_atm(vcc)->sk_sleep, &wait); | ||
71 | while (test_bit(flag,&vcc->flags) == old_test) { | ||
72 | mb(); | ||
73 | out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; | ||
74 | if (!out_vcc) { | ||
75 | error = -EUNATCH; | ||
76 | break; | ||
77 | } | ||
78 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
79 | schedule(); | ||
80 | } | ||
81 | set_current_state(TASK_RUNNING); | ||
82 | remove_wait_queue(sk_atm(vcc)->sk_sleep, &wait); | ||
83 | return error; | ||
84 | } | ||
85 | |||
86 | |||
87 | static int atmtcp_recv_control(const struct atmtcp_control *msg) | ||
88 | { | ||
89 | struct atm_vcc *vcc = *(struct atm_vcc **) &msg->vcc; | ||
90 | |||
91 | vcc->vpi = msg->addr.sap_addr.vpi; | ||
92 | vcc->vci = msg->addr.sap_addr.vci; | ||
93 | vcc->qos = msg->qos; | ||
94 | sk_atm(vcc)->sk_err = -msg->result; | ||
95 | switch (msg->type) { | ||
96 | case ATMTCP_CTRL_OPEN: | ||
97 | change_bit(ATM_VF_READY,&vcc->flags); | ||
98 | break; | ||
99 | case ATMTCP_CTRL_CLOSE: | ||
100 | change_bit(ATM_VF_ADDR,&vcc->flags); | ||
101 | break; | ||
102 | default: | ||
103 | printk(KERN_ERR "atmtcp_recv_control: unknown type %d\n", | ||
104 | msg->type); | ||
105 | return -EINVAL; | ||
106 | } | ||
107 | wake_up(sk_atm(vcc)->sk_sleep); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | |||
112 | static void atmtcp_v_dev_close(struct atm_dev *dev) | ||
113 | { | ||
114 | /* Nothing.... Isn't this simple :-) -- REW */ | ||
115 | } | ||
116 | |||
117 | |||
118 | static int atmtcp_v_open(struct atm_vcc *vcc) | ||
119 | { | ||
120 | struct atmtcp_control msg; | ||
121 | int error; | ||
122 | short vpi = vcc->vpi; | ||
123 | int vci = vcc->vci; | ||
124 | |||
125 | memset(&msg,0,sizeof(msg)); | ||
126 | msg.addr.sap_family = AF_ATMPVC; | ||
127 | msg.hdr.vpi = htons(vpi); | ||
128 | msg.addr.sap_addr.vpi = vpi; | ||
129 | msg.hdr.vci = htons(vci); | ||
130 | msg.addr.sap_addr.vci = vci; | ||
131 | if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0; | ||
132 | msg.type = ATMTCP_CTRL_OPEN; | ||
133 | msg.qos = vcc->qos; | ||
134 | set_bit(ATM_VF_ADDR,&vcc->flags); | ||
135 | clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */ | ||
136 | error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY); | ||
137 | if (error) return error; | ||
138 | return -sk_atm(vcc)->sk_err; | ||
139 | } | ||
140 | |||
141 | |||
142 | static void atmtcp_v_close(struct atm_vcc *vcc) | ||
143 | { | ||
144 | struct atmtcp_control msg; | ||
145 | |||
146 | memset(&msg,0,sizeof(msg)); | ||
147 | msg.addr.sap_family = AF_ATMPVC; | ||
148 | msg.addr.sap_addr.vpi = vcc->vpi; | ||
149 | msg.addr.sap_addr.vci = vcc->vci; | ||
150 | clear_bit(ATM_VF_READY,&vcc->flags); | ||
151 | (void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR); | ||
152 | } | ||
153 | |||
154 | |||
155 | static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
156 | { | ||
157 | struct atm_cirange ci; | ||
158 | struct atm_vcc *vcc; | ||
159 | struct hlist_node *node; | ||
160 | struct sock *s; | ||
161 | int i; | ||
162 | |||
163 | if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD; | ||
164 | if (copy_from_user(&ci, arg,sizeof(ci))) return -EFAULT; | ||
165 | if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS; | ||
166 | if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS; | ||
167 | if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 || | ||
168 | ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL; | ||
169 | read_lock(&vcc_sklist_lock); | ||
170 | for(i = 0; i < VCC_HTABLE_SIZE; ++i) { | ||
171 | struct hlist_head *head = &vcc_hash[i]; | ||
172 | |||
173 | sk_for_each(s, node, head) { | ||
174 | vcc = atm_sk(s); | ||
175 | if (vcc->dev != dev) | ||
176 | continue; | ||
177 | if ((vcc->vpi >> ci.vpi_bits) || | ||
178 | (vcc->vci >> ci.vci_bits)) { | ||
179 | read_unlock(&vcc_sklist_lock); | ||
180 | return -EBUSY; | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | read_unlock(&vcc_sklist_lock); | ||
185 | dev->ci_range = ci; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | |||
190 | static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) | ||
191 | { | ||
192 | struct atmtcp_dev_data *dev_data; | ||
193 | struct atm_vcc *out_vcc=NULL; /* Initializer quietens GCC warning */ | ||
194 | struct sk_buff *new_skb; | ||
195 | struct atmtcp_hdr *hdr; | ||
196 | int size; | ||
197 | |||
198 | if (vcc->qos.txtp.traffic_class == ATM_NONE) { | ||
199 | if (vcc->pop) vcc->pop(vcc,skb); | ||
200 | else dev_kfree_skb(skb); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | dev_data = PRIV(vcc->dev); | ||
204 | if (dev_data) out_vcc = dev_data->vcc; | ||
205 | if (!dev_data || !out_vcc) { | ||
206 | if (vcc->pop) vcc->pop(vcc,skb); | ||
207 | else dev_kfree_skb(skb); | ||
208 | if (dev_data) return 0; | ||
209 | atomic_inc(&vcc->stats->tx_err); | ||
210 | return -ENOLINK; | ||
211 | } | ||
212 | size = skb->len+sizeof(struct atmtcp_hdr); | ||
213 | new_skb = atm_alloc_charge(out_vcc,size,GFP_ATOMIC); | ||
214 | if (!new_skb) { | ||
215 | if (vcc->pop) vcc->pop(vcc,skb); | ||
216 | else dev_kfree_skb(skb); | ||
217 | atomic_inc(&vcc->stats->tx_err); | ||
218 | return -ENOBUFS; | ||
219 | } | ||
220 | hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr)); | ||
221 | hdr->vpi = htons(vcc->vpi); | ||
222 | hdr->vci = htons(vcc->vci); | ||
223 | hdr->length = htonl(skb->len); | ||
224 | memcpy(skb_put(new_skb,skb->len),skb->data,skb->len); | ||
225 | if (vcc->pop) vcc->pop(vcc,skb); | ||
226 | else dev_kfree_skb(skb); | ||
227 | out_vcc->push(out_vcc,new_skb); | ||
228 | atomic_inc(&vcc->stats->tx); | ||
229 | atomic_inc(&out_vcc->stats->rx); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | |||
234 | static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page) | ||
235 | { | ||
236 | struct atmtcp_dev_data *dev_data = PRIV(dev); | ||
237 | |||
238 | if (*pos) return 0; | ||
239 | if (!dev_data->persist) return sprintf(page,"ephemeral\n"); | ||
240 | return sprintf(page,"persistent, %sconnected\n", | ||
241 | dev_data->vcc ? "" : "dis"); | ||
242 | } | ||
243 | |||
244 | |||
245 | static void atmtcp_c_close(struct atm_vcc *vcc) | ||
246 | { | ||
247 | struct atm_dev *atmtcp_dev; | ||
248 | struct atmtcp_dev_data *dev_data; | ||
249 | struct sock *s; | ||
250 | struct hlist_node *node; | ||
251 | struct atm_vcc *walk; | ||
252 | int i; | ||
253 | |||
254 | atmtcp_dev = (struct atm_dev *) vcc->dev_data; | ||
255 | dev_data = PRIV(atmtcp_dev); | ||
256 | dev_data->vcc = NULL; | ||
257 | if (dev_data->persist) return; | ||
258 | atmtcp_dev->dev_data = NULL; | ||
259 | kfree(dev_data); | ||
260 | shutdown_atm_dev(atmtcp_dev); | ||
261 | vcc->dev_data = NULL; | ||
262 | read_lock(&vcc_sklist_lock); | ||
263 | for(i = 0; i < VCC_HTABLE_SIZE; ++i) { | ||
264 | struct hlist_head *head = &vcc_hash[i]; | ||
265 | |||
266 | sk_for_each(s, node, head) { | ||
267 | walk = atm_sk(s); | ||
268 | if (walk->dev != atmtcp_dev) | ||
269 | continue; | ||
270 | wake_up(s->sk_sleep); | ||
271 | } | ||
272 | } | ||
273 | read_unlock(&vcc_sklist_lock); | ||
274 | module_put(THIS_MODULE); | ||
275 | } | ||
276 | |||
277 | |||
278 | static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) | ||
279 | { | ||
280 | struct hlist_head *head; | ||
281 | struct atm_vcc *vcc; | ||
282 | struct hlist_node *node; | ||
283 | struct sock *s; | ||
284 | |||
285 | head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; | ||
286 | |||
287 | sk_for_each(s, node, head) { | ||
288 | vcc = atm_sk(s); | ||
289 | if (vcc->dev == dev && | ||
290 | vcc->vci == vci && vcc->vpi == vpi && | ||
291 | vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
292 | return vcc; | ||
293 | } | ||
294 | } | ||
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | |||
299 | static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) | ||
300 | { | ||
301 | struct atm_dev *dev; | ||
302 | struct atmtcp_hdr *hdr; | ||
303 | struct atm_vcc *out_vcc; | ||
304 | struct sk_buff *new_skb; | ||
305 | int result = 0; | ||
306 | |||
307 | if (!skb->len) return 0; | ||
308 | dev = vcc->dev_data; | ||
309 | hdr = (struct atmtcp_hdr *) skb->data; | ||
310 | if (hdr->length == ATMTCP_HDR_MAGIC) { | ||
311 | result = atmtcp_recv_control( | ||
312 | (struct atmtcp_control *) skb->data); | ||
313 | goto done; | ||
314 | } | ||
315 | read_lock(&vcc_sklist_lock); | ||
316 | out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci)); | ||
317 | read_unlock(&vcc_sklist_lock); | ||
318 | if (!out_vcc) { | ||
319 | atomic_inc(&vcc->stats->tx_err); | ||
320 | goto done; | ||
321 | } | ||
322 | skb_pull(skb,sizeof(struct atmtcp_hdr)); | ||
323 | new_skb = atm_alloc_charge(out_vcc,skb->len,GFP_KERNEL); | ||
324 | if (!new_skb) { | ||
325 | result = -ENOBUFS; | ||
326 | goto done; | ||
327 | } | ||
328 | do_gettimeofday(&new_skb->stamp); | ||
329 | memcpy(skb_put(new_skb,skb->len),skb->data,skb->len); | ||
330 | out_vcc->push(out_vcc,new_skb); | ||
331 | atomic_inc(&vcc->stats->tx); | ||
332 | atomic_inc(&out_vcc->stats->rx); | ||
333 | done: | ||
334 | if (vcc->pop) vcc->pop(vcc,skb); | ||
335 | else dev_kfree_skb(skb); | ||
336 | return result; | ||
337 | } | ||
338 | |||
339 | |||
340 | /* | ||
341 | * Device operations for the virtual ATM devices created by ATMTCP. | ||
342 | */ | ||
343 | |||
344 | |||
345 | static struct atmdev_ops atmtcp_v_dev_ops = { | ||
346 | .dev_close = atmtcp_v_dev_close, | ||
347 | .open = atmtcp_v_open, | ||
348 | .close = atmtcp_v_close, | ||
349 | .ioctl = atmtcp_v_ioctl, | ||
350 | .send = atmtcp_v_send, | ||
351 | .proc_read = atmtcp_v_proc, | ||
352 | .owner = THIS_MODULE | ||
353 | }; | ||
354 | |||
355 | |||
356 | /* | ||
357 | * Device operations for the ATMTCP control device. | ||
358 | */ | ||
359 | |||
360 | |||
361 | static struct atmdev_ops atmtcp_c_dev_ops = { | ||
362 | .close = atmtcp_c_close, | ||
363 | .send = atmtcp_c_send | ||
364 | }; | ||
365 | |||
366 | |||
367 | static struct atm_dev atmtcp_control_dev = { | ||
368 | .ops = &atmtcp_c_dev_ops, | ||
369 | .type = "atmtcp", | ||
370 | .number = 999, | ||
371 | .lock = SPIN_LOCK_UNLOCKED | ||
372 | }; | ||
373 | |||
374 | |||
375 | static int atmtcp_create(int itf,int persist,struct atm_dev **result) | ||
376 | { | ||
377 | struct atmtcp_dev_data *dev_data; | ||
378 | struct atm_dev *dev; | ||
379 | |||
380 | dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL); | ||
381 | if (!dev_data) | ||
382 | return -ENOMEM; | ||
383 | |||
384 | dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL); | ||
385 | if (!dev) { | ||
386 | kfree(dev_data); | ||
387 | return itf == -1 ? -ENOMEM : -EBUSY; | ||
388 | } | ||
389 | dev->ci_range.vpi_bits = MAX_VPI_BITS; | ||
390 | dev->ci_range.vci_bits = MAX_VCI_BITS; | ||
391 | dev->dev_data = dev_data; | ||
392 | PRIV(dev)->vcc = NULL; | ||
393 | PRIV(dev)->persist = persist; | ||
394 | if (result) *result = dev; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | |||
399 | static int atmtcp_attach(struct atm_vcc *vcc,int itf) | ||
400 | { | ||
401 | struct atm_dev *dev; | ||
402 | |||
403 | dev = NULL; | ||
404 | if (itf != -1) dev = atm_dev_lookup(itf); | ||
405 | if (dev) { | ||
406 | if (dev->ops != &atmtcp_v_dev_ops) { | ||
407 | atm_dev_put(dev); | ||
408 | return -EMEDIUMTYPE; | ||
409 | } | ||
410 | if (PRIV(dev)->vcc) return -EBUSY; | ||
411 | } | ||
412 | else { | ||
413 | int error; | ||
414 | |||
415 | error = atmtcp_create(itf,0,&dev); | ||
416 | if (error) return error; | ||
417 | } | ||
418 | PRIV(dev)->vcc = vcc; | ||
419 | vcc->dev = &atmtcp_control_dev; | ||
420 | vcc_insert_socket(sk_atm(vcc)); | ||
421 | set_bit(ATM_VF_META,&vcc->flags); | ||
422 | set_bit(ATM_VF_READY,&vcc->flags); | ||
423 | vcc->dev_data = dev; | ||
424 | (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */ | ||
425 | vcc->stats = &atmtcp_control_dev.stats.aal5; | ||
426 | return dev->number; | ||
427 | } | ||
428 | |||
429 | |||
430 | static int atmtcp_create_persistent(int itf) | ||
431 | { | ||
432 | return atmtcp_create(itf,1,NULL); | ||
433 | } | ||
434 | |||
435 | |||
436 | static int atmtcp_remove_persistent(int itf) | ||
437 | { | ||
438 | struct atm_dev *dev; | ||
439 | struct atmtcp_dev_data *dev_data; | ||
440 | |||
441 | dev = atm_dev_lookup(itf); | ||
442 | if (!dev) return -ENODEV; | ||
443 | if (dev->ops != &atmtcp_v_dev_ops) { | ||
444 | atm_dev_put(dev); | ||
445 | return -EMEDIUMTYPE; | ||
446 | } | ||
447 | dev_data = PRIV(dev); | ||
448 | if (!dev_data->persist) return 0; | ||
449 | dev_data->persist = 0; | ||
450 | if (PRIV(dev)->vcc) return 0; | ||
451 | kfree(dev_data); | ||
452 | atm_dev_put(dev); | ||
453 | shutdown_atm_dev(dev); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int atmtcp_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
458 | { | ||
459 | int err = 0; | ||
460 | struct atm_vcc *vcc = ATM_SD(sock); | ||
461 | |||
462 | if (cmd != SIOCSIFATMTCP && cmd != ATMTCP_CREATE && cmd != ATMTCP_REMOVE) | ||
463 | return -ENOIOCTLCMD; | ||
464 | |||
465 | if (!capable(CAP_NET_ADMIN)) | ||
466 | return -EPERM; | ||
467 | |||
468 | switch (cmd) { | ||
469 | case SIOCSIFATMTCP: | ||
470 | err = atmtcp_attach(vcc, (int) arg); | ||
471 | if (err >= 0) { | ||
472 | sock->state = SS_CONNECTED; | ||
473 | __module_get(THIS_MODULE); | ||
474 | } | ||
475 | break; | ||
476 | case ATMTCP_CREATE: | ||
477 | err = atmtcp_create_persistent((int) arg); | ||
478 | break; | ||
479 | case ATMTCP_REMOVE: | ||
480 | err = atmtcp_remove_persistent((int) arg); | ||
481 | break; | ||
482 | } | ||
483 | return err; | ||
484 | } | ||
485 | |||
486 | static struct atm_ioctl atmtcp_ioctl_ops = { | ||
487 | .owner = THIS_MODULE, | ||
488 | .ioctl = atmtcp_ioctl, | ||
489 | }; | ||
490 | |||
491 | static __init int atmtcp_init(void) | ||
492 | { | ||
493 | register_atm_ioctl(&atmtcp_ioctl_ops); | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | |||
498 | static void __exit atmtcp_exit(void) | ||
499 | { | ||
500 | deregister_atm_ioctl(&atmtcp_ioctl_ops); | ||
501 | } | ||
502 | |||
503 | MODULE_LICENSE("GPL"); | ||
504 | module_init(atmtcp_init); | ||
505 | module_exit(atmtcp_exit); | ||
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c new file mode 100644 index 000000000000..78e34ee79df8 --- /dev/null +++ b/drivers/atm/eni.c | |||
@@ -0,0 +1,2299 @@ | |||
1 | /* drivers/atm/eni.c - Efficient Networks ENI155P device driver */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/config.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/atm.h> | ||
13 | #include <linux/atmdev.h> | ||
14 | #include <linux/sonet.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/time.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/uio.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/atm_eni.h> | ||
21 | #include <linux/bitops.h> | ||
22 | #include <asm/system.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/atomic.h> | ||
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/string.h> | ||
27 | #include <asm/byteorder.h> | ||
28 | |||
29 | #include "tonga.h" | ||
30 | #include "midway.h" | ||
31 | #include "suni.h" | ||
32 | #include "eni.h" | ||
33 | |||
34 | #if !defined(__i386__) && !defined(__x86_64__) | ||
35 | #ifndef ioremap_nocache | ||
36 | #define ioremap_nocache(X,Y) ioremap(X,Y) | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | * TODO: | ||
42 | * | ||
43 | * Show stoppers | ||
44 | * none | ||
45 | * | ||
46 | * Minor | ||
47 | * - OAM support | ||
48 | * - fix bugs listed below | ||
49 | */ | ||
50 | |||
51 | /* | ||
52 | * KNOWN BUGS: | ||
53 | * | ||
54 | * - may run into JK-JK bug and deadlock | ||
55 | * - should allocate UBR channel first | ||
56 | * - buffer space allocation algorithm is stupid | ||
57 | * (RX: should be maxSDU+maxdelay*rate | ||
58 | * TX: should be maxSDU+min(maxSDU,maxdelay*rate) ) | ||
59 | * - doesn't support OAM cells | ||
60 | * - eni_put_free may hang if not putting memory fragments that _complete_ | ||
61 | * 2^n block (never happens in real life, though) | ||
62 | * - keeps IRQ even if initialization fails | ||
63 | */ | ||
64 | |||
65 | |||
66 | #if 0 | ||
67 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
68 | #else | ||
69 | #define DPRINTK(format,args...) | ||
70 | #endif | ||
71 | |||
72 | |||
73 | #ifndef CONFIG_ATM_ENI_TUNE_BURST | ||
74 | #define CONFIG_ATM_ENI_BURST_TX_8W | ||
75 | #define CONFIG_ATM_ENI_BURST_RX_4W | ||
76 | #endif | ||
77 | |||
78 | |||
79 | #ifndef CONFIG_ATM_ENI_DEBUG | ||
80 | |||
81 | |||
82 | #define NULLCHECK(x) | ||
83 | |||
84 | #define EVENT(s,a,b) | ||
85 | |||
86 | |||
87 | static void event_dump(void) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | |||
92 | #else | ||
93 | |||
94 | |||
95 | /* | ||
96 | * NULL pointer checking | ||
97 | */ | ||
98 | |||
99 | #define NULLCHECK(x) \ | ||
100 | if ((unsigned long) (x) < 0x30) \ | ||
101 | printk(KERN_CRIT #x "==0x%lx\n",(unsigned long) (x)) | ||
102 | |||
103 | /* | ||
104 | * Very extensive activity logging. Greatly improves bug detection speed but | ||
105 | * costs a few Mbps if enabled. | ||
106 | */ | ||
107 | |||
108 | #define EV 64 | ||
109 | |||
110 | static const char *ev[EV]; | ||
111 | static unsigned long ev_a[EV],ev_b[EV]; | ||
112 | static int ec = 0; | ||
113 | |||
114 | |||
115 | static void EVENT(const char *s,unsigned long a,unsigned long b) | ||
116 | { | ||
117 | ev[ec] = s; | ||
118 | ev_a[ec] = a; | ||
119 | ev_b[ec] = b; | ||
120 | ec = (ec+1) % EV; | ||
121 | } | ||
122 | |||
123 | |||
124 | static void event_dump(void) | ||
125 | { | ||
126 | int n,i; | ||
127 | |||
128 | for (n = 0; n < EV; n++) { | ||
129 | i = (ec+n) % EV; | ||
130 | printk(KERN_NOTICE); | ||
131 | printk(ev[i] ? ev[i] : "(null)",ev_a[i],ev_b[i]); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | |||
136 | #endif /* CONFIG_ATM_ENI_DEBUG */ | ||
137 | |||
138 | |||
139 | /* | ||
140 | * NExx must not be equal at end | ||
141 | * EExx may be equal at end | ||
142 | * xxPJOK verify validity of pointer jumps | ||
143 | * xxPMOK operating on a circular buffer of "c" words | ||
144 | */ | ||
145 | |||
146 | #define NEPJOK(a0,a1,b) \ | ||
147 | ((a0) < (a1) ? (b) <= (a0) || (b) > (a1) : (b) <= (a0) && (b) > (a1)) | ||
148 | #define EEPJOK(a0,a1,b) \ | ||
149 | ((a0) < (a1) ? (b) < (a0) || (b) >= (a1) : (b) < (a0) && (b) >= (a1)) | ||
150 | #define NEPMOK(a0,d,b,c) NEPJOK(a0,(a0+d) & (c-1),b) | ||
151 | #define EEPMOK(a0,d,b,c) EEPJOK(a0,(a0+d) & (c-1),b) | ||
152 | |||
153 | |||
154 | static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0, | ||
155 | backlogged = 0,rx_enqueued = 0,rx_dequeued = 0,pushed = 0,submitted = 0, | ||
156 | putting = 0; | ||
157 | |||
158 | static struct atm_dev *eni_boards = NULL; | ||
159 | |||
160 | static u32 *cpu_zeroes = NULL; /* aligned "magic" zeroes */ | ||
161 | static dma_addr_t zeroes; | ||
162 | |||
163 | /* Read/write registers on card */ | ||
164 | #define eni_in(r) readl(eni_dev->reg+(r)*4) | ||
165 | #define eni_out(v,r) writel((v),eni_dev->reg+(r)*4) | ||
166 | |||
167 | |||
168 | /*-------------------------------- utilities --------------------------------*/ | ||
169 | |||
170 | |||
171 | static void dump_mem(struct eni_dev *eni_dev) | ||
172 | { | ||
173 | int i; | ||
174 | |||
175 | for (i = 0; i < eni_dev->free_len; i++) | ||
176 | printk(KERN_DEBUG " %d: %p %d\n",i, | ||
177 | eni_dev->free_list[i].start, | ||
178 | 1 << eni_dev->free_list[i].order); | ||
179 | } | ||
180 | |||
181 | |||
182 | static void dump(struct atm_dev *dev) | ||
183 | { | ||
184 | struct eni_dev *eni_dev; | ||
185 | |||
186 | int i; | ||
187 | |||
188 | eni_dev = ENI_DEV(dev); | ||
189 | printk(KERN_NOTICE "Free memory\n"); | ||
190 | dump_mem(eni_dev); | ||
191 | printk(KERN_NOTICE "TX buffers\n"); | ||
192 | for (i = 0; i < NR_CHAN; i++) | ||
193 | if (eni_dev->tx[i].send) | ||
194 | printk(KERN_NOTICE " TX %d @ %p: %ld\n",i, | ||
195 | eni_dev->tx[i].send,eni_dev->tx[i].words*4); | ||
196 | printk(KERN_NOTICE "RX buffers\n"); | ||
197 | for (i = 0; i < 1024; i++) | ||
198 | if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx) | ||
199 | printk(KERN_NOTICE " RX %d @ %p: %ld\n",i, | ||
200 | ENI_VCC(eni_dev->rx_map[i])->recv, | ||
201 | ENI_VCC(eni_dev->rx_map[i])->words*4); | ||
202 | printk(KERN_NOTICE "----\n"); | ||
203 | } | ||
204 | |||
205 | |||
206 | static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start, | ||
207 | unsigned long size) | ||
208 | { | ||
209 | struct eni_free *list; | ||
210 | int len,order; | ||
211 | |||
212 | DPRINTK("init 0x%lx+%ld(0x%lx)\n",start,size,size); | ||
213 | start += eni_dev->base_diff; | ||
214 | list = eni_dev->free_list; | ||
215 | len = eni_dev->free_len; | ||
216 | while (size) { | ||
217 | if (len >= eni_dev->free_list_size) { | ||
218 | printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n", | ||
219 | start,size); | ||
220 | break; | ||
221 | } | ||
222 | for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++); | ||
223 | if (MID_MIN_BUF_SIZE > (1 << order)) { | ||
224 | printk(KERN_CRIT "eni_put_free: order %d too small\n", | ||
225 | order); | ||
226 | break; | ||
227 | } | ||
228 | list[len].start = (void __iomem *) start; | ||
229 | list[len].order = order; | ||
230 | len++; | ||
231 | start += 1 << order; | ||
232 | size -= 1 << order; | ||
233 | } | ||
234 | eni_dev->free_len = len; | ||
235 | /*dump_mem(eni_dev);*/ | ||
236 | } | ||
237 | |||
238 | |||
239 | static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size) | ||
240 | { | ||
241 | struct eni_free *list; | ||
242 | void __iomem *start; | ||
243 | int len,i,order,best_order,index; | ||
244 | |||
245 | list = eni_dev->free_list; | ||
246 | len = eni_dev->free_len; | ||
247 | if (*size < MID_MIN_BUF_SIZE) *size = MID_MIN_BUF_SIZE; | ||
248 | if (*size > MID_MAX_BUF_SIZE) return NULL; | ||
249 | for (order = 0; (1 << order) < *size; order++); | ||
250 | DPRINTK("trying: %ld->%d\n",*size,order); | ||
251 | best_order = 65; /* we don't have more than 2^64 of anything ... */ | ||
252 | index = 0; /* silence GCC */ | ||
253 | for (i = 0; i < len; i++) | ||
254 | if (list[i].order == order) { | ||
255 | best_order = order; | ||
256 | index = i; | ||
257 | break; | ||
258 | } | ||
259 | else if (best_order > list[i].order && list[i].order > order) { | ||
260 | best_order = list[i].order; | ||
261 | index = i; | ||
262 | } | ||
263 | if (best_order == 65) return NULL; | ||
264 | start = list[index].start-eni_dev->base_diff; | ||
265 | list[index] = list[--len]; | ||
266 | eni_dev->free_len = len; | ||
267 | *size = 1 << order; | ||
268 | eni_put_free(eni_dev,start+*size,(1 << best_order)-*size); | ||
269 | DPRINTK("%ld bytes (order %d) at 0x%lx\n",*size,order,start); | ||
270 | memset_io(start,0,*size); /* never leak data */ | ||
271 | /*dump_mem(eni_dev);*/ | ||
272 | return start; | ||
273 | } | ||
274 | |||
275 | |||
276 | static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start, | ||
277 | unsigned long size) | ||
278 | { | ||
279 | struct eni_free *list; | ||
280 | int len,i,order; | ||
281 | |||
282 | start += eni_dev->base_diff; | ||
283 | list = eni_dev->free_list; | ||
284 | len = eni_dev->free_len; | ||
285 | for (order = -1; size; order++) size >>= 1; | ||
286 | DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order); | ||
287 | for (i = 0; i < len; i++) | ||
288 | if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) && | ||
289 | list[i].order == order) { | ||
290 | DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i, | ||
291 | list[i].start,start,1 << order,list[i].order,order); | ||
292 | list[i] = list[--len]; | ||
293 | start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order)); | ||
294 | order++; | ||
295 | i = -1; | ||
296 | continue; | ||
297 | } | ||
298 | if (len >= eni_dev->free_list_size) { | ||
299 | printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start, | ||
300 | order); | ||
301 | return; | ||
302 | } | ||
303 | list[len].start = start; | ||
304 | list[len].order = order; | ||
305 | eni_dev->free_len = len+1; | ||
306 | /*dump_mem(eni_dev);*/ | ||
307 | } | ||
308 | |||
309 | |||
310 | /*----------------------------------- RX ------------------------------------*/ | ||
311 | |||
312 | |||
313 | #define ENI_VCC_NOS ((struct atm_vcc *) 1) | ||
314 | |||
315 | |||
316 | static void rx_ident_err(struct atm_vcc *vcc) | ||
317 | { | ||
318 | struct atm_dev *dev; | ||
319 | struct eni_dev *eni_dev; | ||
320 | struct eni_vcc *eni_vcc; | ||
321 | |||
322 | dev = vcc->dev; | ||
323 | eni_dev = ENI_DEV(dev); | ||
324 | /* immediately halt adapter */ | ||
325 | eni_out(eni_in(MID_MC_S) & | ||
326 | ~(MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE),MID_MC_S); | ||
327 | /* dump useful information */ | ||
328 | eni_vcc = ENI_VCC(vcc); | ||
329 | printk(KERN_ALERT DEV_LABEL "(itf %d): driver error - RX ident " | ||
330 | "mismatch\n",dev->number); | ||
331 | printk(KERN_ALERT " VCI %d, rxing %d, words %ld\n",vcc->vci, | ||
332 | eni_vcc->rxing,eni_vcc->words); | ||
333 | printk(KERN_ALERT " host descr 0x%lx, rx pos 0x%lx, descr value " | ||
334 | "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos, | ||
335 | (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4)); | ||
336 | printk(KERN_ALERT " last %p, servicing %d\n",eni_vcc->last, | ||
337 | eni_vcc->servicing); | ||
338 | EVENT("---dump ends here---\n",0,0); | ||
339 | printk(KERN_NOTICE "---recent events---\n"); | ||
340 | event_dump(); | ||
341 | ENI_DEV(dev)->fast = NULL; /* really stop it */ | ||
342 | ENI_DEV(dev)->slow = NULL; | ||
343 | skb_queue_head_init(&ENI_DEV(dev)->rx_queue); | ||
344 | } | ||
345 | |||
346 | |||
347 | static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb, | ||
348 | unsigned long skip,unsigned long size,unsigned long eff) | ||
349 | { | ||
350 | struct eni_dev *eni_dev; | ||
351 | struct eni_vcc *eni_vcc; | ||
352 | u32 dma_rd,dma_wr; | ||
353 | u32 dma[RX_DMA_BUF*2]; | ||
354 | dma_addr_t paddr; | ||
355 | unsigned long here; | ||
356 | int i,j; | ||
357 | |||
358 | eni_dev = ENI_DEV(vcc->dev); | ||
359 | eni_vcc = ENI_VCC(vcc); | ||
360 | paddr = 0; /* GCC, shut up */ | ||
361 | if (skb) { | ||
362 | paddr = pci_map_single(eni_dev->pci_dev,skb->data,skb->len, | ||
363 | PCI_DMA_FROMDEVICE); | ||
364 | ENI_PRV_PADDR(skb) = paddr; | ||
365 | if (paddr & 3) | ||
366 | printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d has " | ||
367 | "mis-aligned RX data (0x%lx)\n",vcc->dev->number, | ||
368 | vcc->vci,(unsigned long) paddr); | ||
369 | ENI_PRV_SIZE(skb) = size+skip; | ||
370 | /* PDU plus descriptor */ | ||
371 | ATM_SKB(skb)->vcc = vcc; | ||
372 | } | ||
373 | j = 0; | ||
374 | if ((eff && skip) || 1) { /* @@@ actually, skip is always == 1 ... */ | ||
375 | here = (eni_vcc->descr+skip) & (eni_vcc->words-1); | ||
376 | dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci | ||
377 | << MID_DMA_VCI_SHIFT) | MID_DT_JK; | ||
378 | j++; | ||
379 | } | ||
380 | here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1); | ||
381 | if (!eff) size += skip; | ||
382 | else { | ||
383 | unsigned long words; | ||
384 | |||
385 | if (!size) { | ||
386 | DPRINTK("strange things happen ...\n"); | ||
387 | EVENT("strange things happen ... (skip=%ld,eff=%ld)\n", | ||
388 | size,eff); | ||
389 | } | ||
390 | words = eff; | ||
391 | if (paddr & 15) { | ||
392 | unsigned long init; | ||
393 | |||
394 | init = 4-((paddr & 15) >> 2); | ||
395 | if (init > words) init = words; | ||
396 | dma[j++] = MID_DT_WORD | (init << MID_DMA_COUNT_SHIFT) | | ||
397 | (vcc->vci << MID_DMA_VCI_SHIFT); | ||
398 | dma[j++] = paddr; | ||
399 | paddr += init << 2; | ||
400 | words -= init; | ||
401 | } | ||
402 | #ifdef CONFIG_ATM_ENI_BURST_RX_16W /* may work with some PCI chipsets ... */ | ||
403 | if (words & ~15) { | ||
404 | dma[j++] = MID_DT_16W | ((words >> 4) << | ||
405 | MID_DMA_COUNT_SHIFT) | (vcc->vci << | ||
406 | MID_DMA_VCI_SHIFT); | ||
407 | dma[j++] = paddr; | ||
408 | paddr += (words & ~15) << 2; | ||
409 | words &= 15; | ||
410 | } | ||
411 | #endif | ||
412 | #ifdef CONFIG_ATM_ENI_BURST_RX_8W /* works only with *some* PCI chipsets ... */ | ||
413 | if (words & ~7) { | ||
414 | dma[j++] = MID_DT_8W | ((words >> 3) << | ||
415 | MID_DMA_COUNT_SHIFT) | (vcc->vci << | ||
416 | MID_DMA_VCI_SHIFT); | ||
417 | dma[j++] = paddr; | ||
418 | paddr += (words & ~7) << 2; | ||
419 | words &= 7; | ||
420 | } | ||
421 | #endif | ||
422 | #ifdef CONFIG_ATM_ENI_BURST_RX_4W /* recommended */ | ||
423 | if (words & ~3) { | ||
424 | dma[j++] = MID_DT_4W | ((words >> 2) << | ||
425 | MID_DMA_COUNT_SHIFT) | (vcc->vci << | ||
426 | MID_DMA_VCI_SHIFT); | ||
427 | dma[j++] = paddr; | ||
428 | paddr += (words & ~3) << 2; | ||
429 | words &= 3; | ||
430 | } | ||
431 | #endif | ||
432 | #ifdef CONFIG_ATM_ENI_BURST_RX_2W /* probably useless if RX_4W, RX_8W, ... */ | ||
433 | if (words & ~1) { | ||
434 | dma[j++] = MID_DT_2W | ((words >> 1) << | ||
435 | MID_DMA_COUNT_SHIFT) | (vcc->vci << | ||
436 | MID_DMA_VCI_SHIFT); | ||
437 | dma[j++] = paddr; | ||
438 | paddr += (words & ~1) << 2; | ||
439 | words &= 1; | ||
440 | } | ||
441 | #endif | ||
442 | if (words) { | ||
443 | dma[j++] = MID_DT_WORD | (words << MID_DMA_COUNT_SHIFT) | ||
444 | | (vcc->vci << MID_DMA_VCI_SHIFT); | ||
445 | dma[j++] = paddr; | ||
446 | } | ||
447 | } | ||
448 | if (size != eff) { | ||
449 | dma[j++] = (here << MID_DMA_COUNT_SHIFT) | | ||
450 | (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK; | ||
451 | j++; | ||
452 | } | ||
453 | if (!j || j > 2*RX_DMA_BUF) { | ||
454 | printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n"); | ||
455 | goto trouble; | ||
456 | } | ||
457 | dma[j-2] |= MID_DMA_END; | ||
458 | j = j >> 1; | ||
459 | dma_wr = eni_in(MID_DMA_WR_RX); | ||
460 | dma_rd = eni_in(MID_DMA_RD_RX); | ||
461 | /* | ||
462 | * Can I move the dma_wr pointer by 2j+1 positions without overwriting | ||
463 | * data that hasn't been read (position of dma_rd) yet ? | ||
464 | */ | ||
465 | if (!NEPMOK(dma_wr,j+j+1,dma_rd,NR_DMA_RX)) { /* @@@ +1 is ugly */ | ||
466 | printk(KERN_WARNING DEV_LABEL "(itf %d): RX DMA full\n", | ||
467 | vcc->dev->number); | ||
468 | goto trouble; | ||
469 | } | ||
470 | for (i = 0; i < j; i++) { | ||
471 | writel(dma[i*2],eni_dev->rx_dma+dma_wr*8); | ||
472 | writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*8+4); | ||
473 | dma_wr = (dma_wr+1) & (NR_DMA_RX-1); | ||
474 | } | ||
475 | if (skb) { | ||
476 | ENI_PRV_POS(skb) = eni_vcc->descr+size+1; | ||
477 | skb_queue_tail(&eni_dev->rx_queue,skb); | ||
478 | eni_vcc->last = skb; | ||
479 | rx_enqueued++; | ||
480 | } | ||
481 | eni_vcc->descr = here; | ||
482 | eni_out(dma_wr,MID_DMA_WR_RX); | ||
483 | return 0; | ||
484 | |||
485 | trouble: | ||
486 | if (paddr) | ||
487 | pci_unmap_single(eni_dev->pci_dev,paddr,skb->len, | ||
488 | PCI_DMA_FROMDEVICE); | ||
489 | if (skb) dev_kfree_skb_irq(skb); | ||
490 | return -1; | ||
491 | } | ||
492 | |||
493 | |||
494 | static void discard(struct atm_vcc *vcc,unsigned long size) | ||
495 | { | ||
496 | struct eni_vcc *eni_vcc; | ||
497 | |||
498 | eni_vcc = ENI_VCC(vcc); | ||
499 | EVENT("discard (size=%ld)\n",size,0); | ||
500 | while (do_rx_dma(vcc,NULL,1,size,0)) EVENT("BUSY LOOP",0,0); | ||
501 | /* could do a full fallback, but that might be more expensive */ | ||
502 | if (eni_vcc->rxing) ENI_PRV_POS(eni_vcc->last) += size+1; | ||
503 | else eni_vcc->rx_pos = (eni_vcc->rx_pos+size+1) & (eni_vcc->words-1); | ||
504 | } | ||
505 | |||
506 | |||
507 | /* | ||
508 | * TODO: should check whether direct copies (without DMA setup, dequeuing on | ||
509 | * interrupt, etc.) aren't much faster for AAL0 | ||
510 | */ | ||
511 | |||
512 | static int rx_aal0(struct atm_vcc *vcc) | ||
513 | { | ||
514 | struct eni_vcc *eni_vcc; | ||
515 | unsigned long descr; | ||
516 | unsigned long length; | ||
517 | struct sk_buff *skb; | ||
518 | |||
519 | DPRINTK(">rx_aal0\n"); | ||
520 | eni_vcc = ENI_VCC(vcc); | ||
521 | descr = readl(eni_vcc->recv+eni_vcc->descr*4); | ||
522 | if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) { | ||
523 | rx_ident_err(vcc); | ||
524 | return 1; | ||
525 | } | ||
526 | if (descr & MID_RED_T) { | ||
527 | DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n", | ||
528 | vcc->dev->number); | ||
529 | length = 0; | ||
530 | atomic_inc(&vcc->stats->rx_err); | ||
531 | } | ||
532 | else { | ||
533 | length = ATM_CELL_SIZE-1; /* no HEC */ | ||
534 | } | ||
535 | skb = length ? atm_alloc_charge(vcc,length,GFP_ATOMIC) : NULL; | ||
536 | if (!skb) { | ||
537 | discard(vcc,length >> 2); | ||
538 | return 0; | ||
539 | } | ||
540 | skb_put(skb,length); | ||
541 | skb->stamp = eni_vcc->timestamp; | ||
542 | DPRINTK("got len %ld\n",length); | ||
543 | if (do_rx_dma(vcc,skb,1,length >> 2,length >> 2)) return 1; | ||
544 | eni_vcc->rxing++; | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | |||
549 | static int rx_aal5(struct atm_vcc *vcc) | ||
550 | { | ||
551 | struct eni_vcc *eni_vcc; | ||
552 | unsigned long descr; | ||
553 | unsigned long size,eff,length; | ||
554 | struct sk_buff *skb; | ||
555 | |||
556 | EVENT("rx_aal5\n",0,0); | ||
557 | DPRINTK(">rx_aal5\n"); | ||
558 | eni_vcc = ENI_VCC(vcc); | ||
559 | descr = readl(eni_vcc->recv+eni_vcc->descr*4); | ||
560 | if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) { | ||
561 | rx_ident_err(vcc); | ||
562 | return 1; | ||
563 | } | ||
564 | if (descr & (MID_RED_T | MID_RED_CRC_ERR)) { | ||
565 | if (descr & MID_RED_T) { | ||
566 | EVENT("empty cell (descr=0x%lx)\n",descr,0); | ||
567 | DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n", | ||
568 | vcc->dev->number); | ||
569 | size = 0; | ||
570 | } | ||
571 | else { | ||
572 | static unsigned long silence = 0; | ||
573 | |||
574 | if (time_after(jiffies, silence) || silence == 0) { | ||
575 | printk(KERN_WARNING DEV_LABEL "(itf %d): " | ||
576 | "discarding PDU(s) with CRC error\n", | ||
577 | vcc->dev->number); | ||
578 | silence = (jiffies+2*HZ)|1; | ||
579 | } | ||
580 | size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2); | ||
581 | EVENT("CRC error (descr=0x%lx,size=%ld)\n",descr, | ||
582 | size); | ||
583 | } | ||
584 | eff = length = 0; | ||
585 | atomic_inc(&vcc->stats->rx_err); | ||
586 | } | ||
587 | else { | ||
588 | size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2); | ||
589 | DPRINTK("size=%ld\n",size); | ||
590 | length = readl(eni_vcc->recv+(((eni_vcc->descr+size-1) & | ||
591 | (eni_vcc->words-1)))*4) & 0xffff; | ||
592 | /* -trailer(2)+header(1) */ | ||
593 | if (length && length <= (size << 2)-8 && length <= | ||
594 | ATM_MAX_AAL5_PDU) eff = (length+3) >> 2; | ||
595 | else { /* ^ trailer length (8) */ | ||
596 | EVENT("bad PDU (descr=0x08%lx,length=%ld)\n",descr, | ||
597 | length); | ||
598 | printk(KERN_ERR DEV_LABEL "(itf %d): bad AAL5 PDU " | ||
599 | "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n", | ||
600 | vcc->dev->number,vcc->vci,length,size << 2,descr); | ||
601 | length = eff = 0; | ||
602 | atomic_inc(&vcc->stats->rx_err); | ||
603 | } | ||
604 | } | ||
605 | skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL; | ||
606 | if (!skb) { | ||
607 | discard(vcc,size); | ||
608 | return 0; | ||
609 | } | ||
610 | skb_put(skb,length); | ||
611 | DPRINTK("got len %ld\n",length); | ||
612 | if (do_rx_dma(vcc,skb,1,size,eff)) return 1; | ||
613 | eni_vcc->rxing++; | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | |||
618 | static inline int rx_vcc(struct atm_vcc *vcc) | ||
619 | { | ||
620 | void __iomem *vci_dsc; | ||
621 | unsigned long tmp; | ||
622 | struct eni_vcc *eni_vcc; | ||
623 | |||
624 | eni_vcc = ENI_VCC(vcc); | ||
625 | vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*16; | ||
626 | EVENT("rx_vcc(1)\n",0,0); | ||
627 | while (eni_vcc->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) >> | ||
628 | MID_VCI_DESCR_SHIFT)) { | ||
629 | EVENT("rx_vcc(2: host dsc=0x%lx, nic dsc=0x%lx)\n", | ||
630 | eni_vcc->descr,tmp); | ||
631 | DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr, | ||
632 | (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >> | ||
633 | MID_VCI_DESCR_SHIFT)); | ||
634 | if (ENI_VCC(vcc)->rx(vcc)) return 1; | ||
635 | } | ||
636 | /* clear IN_SERVICE flag */ | ||
637 | writel(readl(vci_dsc) & ~MID_VCI_IN_SERVICE,vci_dsc); | ||
638 | /* | ||
639 | * If new data has arrived between evaluating the while condition and | ||
640 | * clearing IN_SERVICE, we wouldn't be notified until additional data | ||
641 | * follows. So we have to loop again to be sure. | ||
642 | */ | ||
643 | EVENT("rx_vcc(3)\n",0,0); | ||
644 | while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) | ||
645 | >> MID_VCI_DESCR_SHIFT)) { | ||
646 | EVENT("rx_vcc(4: host dsc=0x%lx, nic dsc=0x%lx)\n", | ||
647 | eni_vcc->descr,tmp); | ||
648 | DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr, | ||
649 | (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >> | ||
650 | MID_VCI_DESCR_SHIFT)); | ||
651 | if (ENI_VCC(vcc)->rx(vcc)) return 1; | ||
652 | } | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | |||
657 | static void poll_rx(struct atm_dev *dev) | ||
658 | { | ||
659 | struct eni_dev *eni_dev; | ||
660 | struct atm_vcc *curr; | ||
661 | |||
662 | eni_dev = ENI_DEV(dev); | ||
663 | while ((curr = eni_dev->fast)) { | ||
664 | EVENT("poll_rx.fast\n",0,0); | ||
665 | if (rx_vcc(curr)) return; | ||
666 | eni_dev->fast = ENI_VCC(curr)->next; | ||
667 | ENI_VCC(curr)->next = ENI_VCC_NOS; | ||
668 | barrier(); | ||
669 | ENI_VCC(curr)->servicing--; | ||
670 | } | ||
671 | while ((curr = eni_dev->slow)) { | ||
672 | EVENT("poll_rx.slow\n",0,0); | ||
673 | if (rx_vcc(curr)) return; | ||
674 | eni_dev->slow = ENI_VCC(curr)->next; | ||
675 | ENI_VCC(curr)->next = ENI_VCC_NOS; | ||
676 | barrier(); | ||
677 | ENI_VCC(curr)->servicing--; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | |||
682 | static void get_service(struct atm_dev *dev) | ||
683 | { | ||
684 | struct eni_dev *eni_dev; | ||
685 | struct atm_vcc *vcc; | ||
686 | unsigned long vci; | ||
687 | |||
688 | DPRINTK(">get_service\n"); | ||
689 | eni_dev = ENI_DEV(dev); | ||
690 | while (eni_in(MID_SERV_WRITE) != eni_dev->serv_read) { | ||
691 | vci = readl(eni_dev->service+eni_dev->serv_read*4); | ||
692 | eni_dev->serv_read = (eni_dev->serv_read+1) & (NR_SERVICE-1); | ||
693 | vcc = eni_dev->rx_map[vci & 1023]; | ||
694 | if (!vcc) { | ||
695 | printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %ld not " | ||
696 | "found\n",dev->number,vci); | ||
697 | continue; /* nasty but we try to go on anyway */ | ||
698 | /* @@@ nope, doesn't work */ | ||
699 | } | ||
700 | EVENT("getting from service\n",0,0); | ||
701 | if (ENI_VCC(vcc)->next != ENI_VCC_NOS) { | ||
702 | EVENT("double service\n",0,0); | ||
703 | DPRINTK("Grr, servicing VCC %ld twice\n",vci); | ||
704 | continue; | ||
705 | } | ||
706 | do_gettimeofday(&ENI_VCC(vcc)->timestamp); | ||
707 | ENI_VCC(vcc)->next = NULL; | ||
708 | if (vcc->qos.rxtp.traffic_class == ATM_CBR) { | ||
709 | if (eni_dev->fast) | ||
710 | ENI_VCC(eni_dev->last_fast)->next = vcc; | ||
711 | else eni_dev->fast = vcc; | ||
712 | eni_dev->last_fast = vcc; | ||
713 | } | ||
714 | else { | ||
715 | if (eni_dev->slow) | ||
716 | ENI_VCC(eni_dev->last_slow)->next = vcc; | ||
717 | else eni_dev->slow = vcc; | ||
718 | eni_dev->last_slow = vcc; | ||
719 | } | ||
720 | putting++; | ||
721 | ENI_VCC(vcc)->servicing++; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | |||
726 | static void dequeue_rx(struct atm_dev *dev) | ||
727 | { | ||
728 | struct eni_dev *eni_dev; | ||
729 | struct eni_vcc *eni_vcc; | ||
730 | struct atm_vcc *vcc; | ||
731 | struct sk_buff *skb; | ||
732 | void __iomem *vci_dsc; | ||
733 | int first; | ||
734 | |||
735 | eni_dev = ENI_DEV(dev); | ||
736 | first = 1; | ||
737 | while (1) { | ||
738 | skb = skb_dequeue(&eni_dev->rx_queue); | ||
739 | if (!skb) { | ||
740 | if (first) { | ||
741 | DPRINTK(DEV_LABEL "(itf %d): RX but not " | ||
742 | "rxing\n",dev->number); | ||
743 | EVENT("nothing to dequeue\n",0,0); | ||
744 | } | ||
745 | break; | ||
746 | } | ||
747 | EVENT("dequeued (size=%ld,pos=0x%lx)\n",ENI_PRV_SIZE(skb), | ||
748 | ENI_PRV_POS(skb)); | ||
749 | rx_dequeued++; | ||
750 | vcc = ATM_SKB(skb)->vcc; | ||
751 | eni_vcc = ENI_VCC(vcc); | ||
752 | first = 0; | ||
753 | vci_dsc = eni_dev->vci+vcc->vci*16; | ||
754 | if (!EEPMOK(eni_vcc->rx_pos,ENI_PRV_SIZE(skb), | ||
755 | (readl(vci_dsc+4) & MID_VCI_READ) >> MID_VCI_READ_SHIFT, | ||
756 | eni_vcc->words)) { | ||
757 | EVENT("requeuing\n",0,0); | ||
758 | skb_queue_head(&eni_dev->rx_queue,skb); | ||
759 | break; | ||
760 | } | ||
761 | eni_vcc->rxing--; | ||
762 | eni_vcc->rx_pos = ENI_PRV_POS(skb) & (eni_vcc->words-1); | ||
763 | pci_unmap_single(eni_dev->pci_dev,ENI_PRV_PADDR(skb),skb->len, | ||
764 | PCI_DMA_TODEVICE); | ||
765 | if (!skb->len) dev_kfree_skb_irq(skb); | ||
766 | else { | ||
767 | EVENT("pushing (len=%ld)\n",skb->len,0); | ||
768 | if (vcc->qos.aal == ATM_AAL0) | ||
769 | *(unsigned long *) skb->data = | ||
770 | ntohl(*(unsigned long *) skb->data); | ||
771 | memset(skb->cb,0,sizeof(struct eni_skb_prv)); | ||
772 | vcc->push(vcc,skb); | ||
773 | pushed++; | ||
774 | } | ||
775 | atomic_inc(&vcc->stats->rx); | ||
776 | } | ||
777 | wake_up(&eni_dev->rx_wait); | ||
778 | } | ||
779 | |||
780 | |||
781 | static int open_rx_first(struct atm_vcc *vcc) | ||
782 | { | ||
783 | struct eni_dev *eni_dev; | ||
784 | struct eni_vcc *eni_vcc; | ||
785 | unsigned long size; | ||
786 | |||
787 | DPRINTK("open_rx_first\n"); | ||
788 | eni_dev = ENI_DEV(vcc->dev); | ||
789 | eni_vcc = ENI_VCC(vcc); | ||
790 | eni_vcc->rx = NULL; | ||
791 | if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0; | ||
792 | size = vcc->qos.rxtp.max_sdu*eni_dev->rx_mult/100; | ||
793 | if (size > MID_MAX_BUF_SIZE && vcc->qos.rxtp.max_sdu <= | ||
794 | MID_MAX_BUF_SIZE) | ||
795 | size = MID_MAX_BUF_SIZE; | ||
796 | eni_vcc->recv = eni_alloc_mem(eni_dev,&size); | ||
797 | DPRINTK("rx at 0x%lx\n",eni_vcc->recv); | ||
798 | eni_vcc->words = size >> 2; | ||
799 | if (!eni_vcc->recv) return -ENOBUFS; | ||
800 | eni_vcc->rx = vcc->qos.aal == ATM_AAL5 ? rx_aal5 : rx_aal0; | ||
801 | eni_vcc->descr = 0; | ||
802 | eni_vcc->rx_pos = 0; | ||
803 | eni_vcc->rxing = 0; | ||
804 | eni_vcc->servicing = 0; | ||
805 | eni_vcc->next = ENI_VCC_NOS; | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | |||
810 | static int open_rx_second(struct atm_vcc *vcc) | ||
811 | { | ||
812 | void __iomem *here; | ||
813 | struct eni_dev *eni_dev; | ||
814 | struct eni_vcc *eni_vcc; | ||
815 | unsigned long size; | ||
816 | int order; | ||
817 | |||
818 | DPRINTK("open_rx_second\n"); | ||
819 | eni_dev = ENI_DEV(vcc->dev); | ||
820 | eni_vcc = ENI_VCC(vcc); | ||
821 | if (!eni_vcc->rx) return 0; | ||
822 | /* set up VCI descriptor */ | ||
823 | here = eni_dev->vci+vcc->vci*16; | ||
824 | DPRINTK("loc 0x%x\n",(unsigned) (eni_vcc->recv-eni_dev->ram)/4); | ||
825 | size = eni_vcc->words >> 8; | ||
826 | for (order = -1; size; order++) size >>= 1; | ||
827 | writel(0,here+4); /* descr, read = 0 */ | ||
828 | writel(0,here+8); /* write, state, count = 0 */ | ||
829 | if (eni_dev->rx_map[vcc->vci]) | ||
830 | printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already " | ||
831 | "in use\n",vcc->dev->number,vcc->vci); | ||
832 | eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */ | ||
833 | writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) << | ||
834 | MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE | | ||
835 | (((eni_vcc->recv-eni_dev->ram) >> (MID_LOC_SKIP+2)) << | ||
836 | MID_VCI_LOCATION_SHIFT) | (order << MID_VCI_SIZE_SHIFT),here); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | |||
841 | static void close_rx(struct atm_vcc *vcc) | ||
842 | { | ||
843 | DECLARE_WAITQUEUE(wait,current); | ||
844 | void __iomem *here; | ||
845 | struct eni_dev *eni_dev; | ||
846 | struct eni_vcc *eni_vcc; | ||
847 | |||
848 | eni_vcc = ENI_VCC(vcc); | ||
849 | if (!eni_vcc->rx) return; | ||
850 | eni_dev = ENI_DEV(vcc->dev); | ||
851 | if (vcc->vpi != ATM_VPI_UNSPEC && vcc->vci != ATM_VCI_UNSPEC) { | ||
852 | here = eni_dev->vci+vcc->vci*16; | ||
853 | /* block receiver */ | ||
854 | writel((readl(here) & ~MID_VCI_MODE) | (MID_MODE_TRASH << | ||
855 | MID_VCI_MODE_SHIFT),here); | ||
856 | /* wait for receiver to become idle */ | ||
857 | udelay(27); | ||
858 | /* discard pending cell */ | ||
859 | writel(readl(here) & ~MID_VCI_IN_SERVICE,here); | ||
860 | /* don't accept any new ones */ | ||
861 | eni_dev->rx_map[vcc->vci] = NULL; | ||
862 | /* wait for RX queue to drain */ | ||
863 | DPRINTK("eni_close: waiting for RX ...\n"); | ||
864 | EVENT("RX closing\n",0,0); | ||
865 | add_wait_queue(&eni_dev->rx_wait,&wait); | ||
866 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
867 | barrier(); | ||
868 | for (;;) { | ||
869 | /* transition service->rx: rxing++, servicing-- */ | ||
870 | if (!eni_vcc->servicing) { | ||
871 | barrier(); | ||
872 | if (!eni_vcc->rxing) break; | ||
873 | } | ||
874 | EVENT("drain PDUs (rx %ld, serv %ld)\n",eni_vcc->rxing, | ||
875 | eni_vcc->servicing); | ||
876 | printk(KERN_INFO "%d+%d RX left\n",eni_vcc->servicing, | ||
877 | eni_vcc->rxing); | ||
878 | schedule(); | ||
879 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
880 | } | ||
881 | for (;;) { | ||
882 | int at_end; | ||
883 | u32 tmp; | ||
884 | |||
885 | tasklet_disable(&eni_dev->task); | ||
886 | tmp = readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ; | ||
887 | at_end = eni_vcc->rx_pos == tmp >> MID_VCI_READ_SHIFT; | ||
888 | tasklet_enable(&eni_dev->task); | ||
889 | if (at_end) break; | ||
890 | EVENT("drain discard (host 0x%lx, nic 0x%lx)\n", | ||
891 | eni_vcc->rx_pos,tmp); | ||
892 | printk(KERN_INFO "draining RX: host 0x%lx, nic 0x%x\n", | ||
893 | eni_vcc->rx_pos,tmp); | ||
894 | schedule(); | ||
895 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
896 | } | ||
897 | set_current_state(TASK_RUNNING); | ||
898 | remove_wait_queue(&eni_dev->rx_wait,&wait); | ||
899 | } | ||
900 | eni_free_mem(eni_dev,eni_vcc->recv,eni_vcc->words << 2); | ||
901 | eni_vcc->rx = NULL; | ||
902 | } | ||
903 | |||
904 | |||
905 | static int start_rx(struct atm_dev *dev) | ||
906 | { | ||
907 | struct eni_dev *eni_dev; | ||
908 | |||
909 | eni_dev = ENI_DEV(dev); | ||
910 | eni_dev->rx_map = (struct atm_vcc **) get_zeroed_page(GFP_KERNEL); | ||
911 | if (!eni_dev->rx_map) { | ||
912 | printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n", | ||
913 | dev->number); | ||
914 | free_page((unsigned long) eni_dev->free_list); | ||
915 | return -ENOMEM; | ||
916 | } | ||
917 | memset(eni_dev->rx_map,0,PAGE_SIZE); | ||
918 | eni_dev->rx_mult = DEFAULT_RX_MULT; | ||
919 | eni_dev->fast = eni_dev->last_fast = NULL; | ||
920 | eni_dev->slow = eni_dev->last_slow = NULL; | ||
921 | init_waitqueue_head(&eni_dev->rx_wait); | ||
922 | skb_queue_head_init(&eni_dev->rx_queue); | ||
923 | eni_dev->serv_read = eni_in(MID_SERV_WRITE); | ||
924 | eni_out(0,MID_DMA_WR_RX); | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | |||
929 | /*----------------------------------- TX ------------------------------------*/ | ||
930 | |||
931 | |||
932 | enum enq_res { enq_ok,enq_next,enq_jam }; | ||
933 | |||
934 | |||
935 | static inline void put_dma(int chan,u32 *dma,int *j,dma_addr_t paddr, | ||
936 | u32 size) | ||
937 | { | ||
938 | u32 init,words; | ||
939 | |||
940 | DPRINTK("put_dma: 0x%lx+0x%x\n",(unsigned long) paddr,size); | ||
941 | EVENT("put_dma: 0x%lx+0x%lx\n",(unsigned long) paddr,size); | ||
942 | #if 0 /* don't complain anymore */ | ||
943 | if (paddr & 3) | ||
944 | printk(KERN_ERR "put_dma: unaligned addr (0x%lx)\n",paddr); | ||
945 | if (size & 3) | ||
946 | printk(KERN_ERR "put_dma: unaligned size (0x%lx)\n",size); | ||
947 | #endif | ||
948 | if (paddr & 3) { | ||
949 | init = 4-(paddr & 3); | ||
950 | if (init > size || size < 7) init = size; | ||
951 | DPRINTK("put_dma: %lx DMA: %d/%d bytes\n", | ||
952 | (unsigned long) paddr,init,size); | ||
953 | dma[(*j)++] = MID_DT_BYTE | (init << MID_DMA_COUNT_SHIFT) | | ||
954 | (chan << MID_DMA_CHAN_SHIFT); | ||
955 | dma[(*j)++] = paddr; | ||
956 | paddr += init; | ||
957 | size -= init; | ||
958 | } | ||
959 | words = size >> 2; | ||
960 | size &= 3; | ||
961 | if (words && (paddr & 31)) { | ||
962 | init = 8-((paddr & 31) >> 2); | ||
963 | if (init > words) init = words; | ||
964 | DPRINTK("put_dma: %lx DMA: %d/%d words\n", | ||
965 | (unsigned long) paddr,init,words); | ||
966 | dma[(*j)++] = MID_DT_WORD | (init << MID_DMA_COUNT_SHIFT) | | ||
967 | (chan << MID_DMA_CHAN_SHIFT); | ||
968 | dma[(*j)++] = paddr; | ||
969 | paddr += init << 2; | ||
970 | words -= init; | ||
971 | } | ||
972 | #ifdef CONFIG_ATM_ENI_BURST_TX_16W /* may work with some PCI chipsets ... */ | ||
973 | if (words & ~15) { | ||
974 | DPRINTK("put_dma: %lx DMA: %d*16/%d words\n", | ||
975 | (unsigned long) paddr,words >> 4,words); | ||
976 | dma[(*j)++] = MID_DT_16W | ((words >> 4) << MID_DMA_COUNT_SHIFT) | ||
977 | | (chan << MID_DMA_CHAN_SHIFT); | ||
978 | dma[(*j)++] = paddr; | ||
979 | paddr += (words & ~15) << 2; | ||
980 | words &= 15; | ||
981 | } | ||
982 | #endif | ||
983 | #ifdef CONFIG_ATM_ENI_BURST_TX_8W /* recommended */ | ||
984 | if (words & ~7) { | ||
985 | DPRINTK("put_dma: %lx DMA: %d*8/%d words\n", | ||
986 | (unsigned long) paddr,words >> 3,words); | ||
987 | dma[(*j)++] = MID_DT_8W | ((words >> 3) << MID_DMA_COUNT_SHIFT) | ||
988 | | (chan << MID_DMA_CHAN_SHIFT); | ||
989 | dma[(*j)++] = paddr; | ||
990 | paddr += (words & ~7) << 2; | ||
991 | words &= 7; | ||
992 | } | ||
993 | #endif | ||
994 | #ifdef CONFIG_ATM_ENI_BURST_TX_4W /* probably useless if TX_8W or TX_16W */ | ||
995 | if (words & ~3) { | ||
996 | DPRINTK("put_dma: %lx DMA: %d*4/%d words\n", | ||
997 | (unsigned long) paddr,words >> 2,words); | ||
998 | dma[(*j)++] = MID_DT_4W | ((words >> 2) << MID_DMA_COUNT_SHIFT) | ||
999 | | (chan << MID_DMA_CHAN_SHIFT); | ||
1000 | dma[(*j)++] = paddr; | ||
1001 | paddr += (words & ~3) << 2; | ||
1002 | words &= 3; | ||
1003 | } | ||
1004 | #endif | ||
1005 | #ifdef CONFIG_ATM_ENI_BURST_TX_2W /* probably useless if TX_4W, TX_8W, ... */ | ||
1006 | if (words & ~1) { | ||
1007 | DPRINTK("put_dma: %lx DMA: %d*2/%d words\n", | ||
1008 | (unsigned long) paddr,words >> 1,words); | ||
1009 | dma[(*j)++] = MID_DT_2W | ((words >> 1) << MID_DMA_COUNT_SHIFT) | ||
1010 | | (chan << MID_DMA_CHAN_SHIFT); | ||
1011 | dma[(*j)++] = paddr; | ||
1012 | paddr += (words & ~1) << 2; | ||
1013 | words &= 1; | ||
1014 | } | ||
1015 | #endif | ||
1016 | if (words) { | ||
1017 | DPRINTK("put_dma: %lx DMA: %d words\n",(unsigned long) paddr, | ||
1018 | words); | ||
1019 | dma[(*j)++] = MID_DT_WORD | (words << MID_DMA_COUNT_SHIFT) | | ||
1020 | (chan << MID_DMA_CHAN_SHIFT); | ||
1021 | dma[(*j)++] = paddr; | ||
1022 | paddr += words << 2; | ||
1023 | } | ||
1024 | if (size) { | ||
1025 | DPRINTK("put_dma: %lx DMA: %d bytes\n",(unsigned long) paddr, | ||
1026 | size); | ||
1027 | dma[(*j)++] = MID_DT_BYTE | (size << MID_DMA_COUNT_SHIFT) | | ||
1028 | (chan << MID_DMA_CHAN_SHIFT); | ||
1029 | dma[(*j)++] = paddr; | ||
1030 | } | ||
1031 | } | ||
1032 | |||
1033 | |||
1034 | static enum enq_res do_tx(struct sk_buff *skb) | ||
1035 | { | ||
1036 | struct atm_vcc *vcc; | ||
1037 | struct eni_dev *eni_dev; | ||
1038 | struct eni_vcc *eni_vcc; | ||
1039 | struct eni_tx *tx; | ||
1040 | dma_addr_t paddr; | ||
1041 | u32 dma_rd,dma_wr; | ||
1042 | u32 size; /* in words */ | ||
1043 | int aal5,dma_size,i,j; | ||
1044 | |||
1045 | DPRINTK(">do_tx\n"); | ||
1046 | NULLCHECK(skb); | ||
1047 | EVENT("do_tx: skb=0x%lx, %ld bytes\n",(unsigned long) skb,skb->len); | ||
1048 | vcc = ATM_SKB(skb)->vcc; | ||
1049 | NULLCHECK(vcc); | ||
1050 | eni_dev = ENI_DEV(vcc->dev); | ||
1051 | NULLCHECK(eni_dev); | ||
1052 | eni_vcc = ENI_VCC(vcc); | ||
1053 | tx = eni_vcc->tx; | ||
1054 | NULLCHECK(tx); | ||
1055 | #if 0 /* Enable this for testing with the "align" program */ | ||
1056 | { | ||
1057 | unsigned int hack = *((char *) skb->data)-'0'; | ||
1058 | |||
1059 | if (hack < 8) { | ||
1060 | skb->data += hack; | ||
1061 | skb->len -= hack; | ||
1062 | } | ||
1063 | } | ||
1064 | #endif | ||
1065 | #if 0 /* should work now */ | ||
1066 | if ((unsigned long) skb->data & 3) | ||
1067 | printk(KERN_ERR DEV_LABEL "(itf %d): VCI %d has mis-aligned " | ||
1068 | "TX data\n",vcc->dev->number,vcc->vci); | ||
1069 | #endif | ||
1070 | /* | ||
1071 | * Potential future IP speedup: make hard_header big enough to put | ||
1072 | * segmentation descriptor directly into PDU. Saves: 4 slave writes, | ||
1073 | * 1 DMA xfer & 2 DMA'ed bytes (protocol layering is for wimps :-) | ||
1074 | */ | ||
1075 | |||
1076 | aal5 = vcc->qos.aal == ATM_AAL5; | ||
1077 | /* check space in buffer */ | ||
1078 | if (!aal5) | ||
1079 | size = (ATM_CELL_PAYLOAD >> 2)+TX_DESCR_SIZE; | ||
1080 | /* cell without HEC plus segmentation header (includes | ||
1081 | four-byte cell header) */ | ||
1082 | else { | ||
1083 | size = skb->len+4*AAL5_TRAILER+ATM_CELL_PAYLOAD-1; | ||
1084 | /* add AAL5 trailer */ | ||
1085 | size = ((size-(size % ATM_CELL_PAYLOAD)) >> 2)+TX_DESCR_SIZE; | ||
1086 | /* add segmentation header */ | ||
1087 | } | ||
1088 | /* | ||
1089 | * Can I move tx_pos by size bytes without getting closer than TX_GAP | ||
1090 | * to the read pointer ? TX_GAP means to leave some space for what | ||
1091 | * the manual calls "too close". | ||
1092 | */ | ||
1093 | if (!NEPMOK(tx->tx_pos,size+TX_GAP, | ||
1094 | eni_in(MID_TX_RDPTR(tx->index)),tx->words)) { | ||
1095 | DPRINTK(DEV_LABEL "(itf %d): TX full (size %d)\n", | ||
1096 | vcc->dev->number,size); | ||
1097 | return enq_next; | ||
1098 | } | ||
1099 | /* check DMA */ | ||
1100 | dma_wr = eni_in(MID_DMA_WR_TX); | ||
1101 | dma_rd = eni_in(MID_DMA_RD_TX); | ||
1102 | dma_size = 3; /* JK for descriptor and final fill, plus final size | ||
1103 | mis-alignment fix */ | ||
1104 | DPRINTK("iovcnt = %d\n",skb_shinfo(skb)->nr_frags); | ||
1105 | if (!skb_shinfo(skb)->nr_frags) dma_size += 5; | ||
1106 | else dma_size += 5*(skb_shinfo(skb)->nr_frags+1); | ||
1107 | if (dma_size > TX_DMA_BUF) { | ||
1108 | printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries " | ||
1109 | "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF); | ||
1110 | } | ||
1111 | DPRINTK("dma_wr is %d, tx_pos is %ld\n",dma_wr,tx->tx_pos); | ||
1112 | if (dma_wr != dma_rd && ((dma_rd+NR_DMA_TX-dma_wr) & (NR_DMA_TX-1)) < | ||
1113 | dma_size) { | ||
1114 | printk(KERN_WARNING DEV_LABEL "(itf %d): TX DMA full\n", | ||
1115 | vcc->dev->number); | ||
1116 | return enq_jam; | ||
1117 | } | ||
1118 | paddr = pci_map_single(eni_dev->pci_dev,skb->data,skb->len, | ||
1119 | PCI_DMA_TODEVICE); | ||
1120 | ENI_PRV_PADDR(skb) = paddr; | ||
1121 | /* prepare DMA queue entries */ | ||
1122 | j = 0; | ||
1123 | eni_dev->dma[j++] = (((tx->tx_pos+TX_DESCR_SIZE) & (tx->words-1)) << | ||
1124 | MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | | ||
1125 | MID_DT_JK; | ||
1126 | j++; | ||
1127 | if (!skb_shinfo(skb)->nr_frags) | ||
1128 | if (aal5) put_dma(tx->index,eni_dev->dma,&j,paddr,skb->len); | ||
1129 | else put_dma(tx->index,eni_dev->dma,&j,paddr+4,skb->len-4); | ||
1130 | else { | ||
1131 | DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */ | ||
1132 | for (i = -1; i < skb_shinfo(skb)->nr_frags; i++) | ||
1133 | if (i == -1) | ||
1134 | put_dma(tx->index,eni_dev->dma,&j,(unsigned long) | ||
1135 | skb->data, | ||
1136 | skb->len - skb->data_len); | ||
1137 | else | ||
1138 | put_dma(tx->index,eni_dev->dma,&j,(unsigned long) | ||
1139 | skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset, | ||
1140 | skb_shinfo(skb)->frags[i].size); | ||
1141 | } | ||
1142 | if (skb->len & 3) | ||
1143 | put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3)); | ||
1144 | /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */ | ||
1145 | eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) << | ||
1146 | MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | | ||
1147 | MID_DMA_END | MID_DT_JK; | ||
1148 | j++; | ||
1149 | DPRINTK("DMA at end: %d\n",j); | ||
1150 | /* store frame */ | ||
1151 | writel((MID_SEG_TX_ID << MID_SEG_ID_SHIFT) | | ||
1152 | (aal5 ? MID_SEG_AAL5 : 0) | (tx->prescaler << MID_SEG_PR_SHIFT) | | ||
1153 | (tx->resolution << MID_SEG_RATE_SHIFT) | | ||
1154 | (size/(ATM_CELL_PAYLOAD/4)),tx->send+tx->tx_pos*4); | ||
1155 | /*printk("dsc = 0x%08lx\n",(unsigned long) readl(tx->send+tx->tx_pos*4));*/ | ||
1156 | writel((vcc->vci << MID_SEG_VCI_SHIFT) | | ||
1157 | (aal5 ? 0 : (skb->data[3] & 0xf)) | | ||
1158 | (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0), | ||
1159 | tx->send+((tx->tx_pos+1) & (tx->words-1))*4); | ||
1160 | DPRINTK("size: %d, len:%d\n",size,skb->len); | ||
1161 | if (aal5) | ||
1162 | writel(skb->len,tx->send+ | ||
1163 | ((tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1))*4); | ||
1164 | j = j >> 1; | ||
1165 | for (i = 0; i < j; i++) { | ||
1166 | writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*8); | ||
1167 | writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*8+4); | ||
1168 | dma_wr = (dma_wr+1) & (NR_DMA_TX-1); | ||
1169 | } | ||
1170 | ENI_PRV_POS(skb) = tx->tx_pos; | ||
1171 | ENI_PRV_SIZE(skb) = size; | ||
1172 | ENI_VCC(vcc)->txing += size; | ||
1173 | tx->tx_pos = (tx->tx_pos+size) & (tx->words-1); | ||
1174 | DPRINTK("dma_wr set to %d, tx_pos is now %ld\n",dma_wr,tx->tx_pos); | ||
1175 | eni_out(dma_wr,MID_DMA_WR_TX); | ||
1176 | skb_queue_tail(&eni_dev->tx_queue,skb); | ||
1177 | queued++; | ||
1178 | return enq_ok; | ||
1179 | } | ||
1180 | |||
1181 | |||
1182 | static void poll_tx(struct atm_dev *dev) | ||
1183 | { | ||
1184 | struct eni_tx *tx; | ||
1185 | struct sk_buff *skb; | ||
1186 | enum enq_res res; | ||
1187 | int i; | ||
1188 | |||
1189 | DPRINTK(">poll_tx\n"); | ||
1190 | for (i = NR_CHAN-1; i >= 0; i--) { | ||
1191 | tx = &ENI_DEV(dev)->tx[i]; | ||
1192 | if (tx->send) | ||
1193 | while ((skb = skb_dequeue(&tx->backlog))) { | ||
1194 | res = do_tx(skb); | ||
1195 | if (res == enq_ok) continue; | ||
1196 | DPRINTK("re-queuing TX PDU\n"); | ||
1197 | skb_queue_head(&tx->backlog,skb); | ||
1198 | requeued++; | ||
1199 | if (res == enq_jam) return; | ||
1200 | break; | ||
1201 | } | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | |||
1206 | static void dequeue_tx(struct atm_dev *dev) | ||
1207 | { | ||
1208 | struct eni_dev *eni_dev; | ||
1209 | struct atm_vcc *vcc; | ||
1210 | struct sk_buff *skb; | ||
1211 | struct eni_tx *tx; | ||
1212 | |||
1213 | NULLCHECK(dev); | ||
1214 | eni_dev = ENI_DEV(dev); | ||
1215 | NULLCHECK(eni_dev); | ||
1216 | while ((skb = skb_dequeue(&eni_dev->tx_queue))) { | ||
1217 | vcc = ATM_SKB(skb)->vcc; | ||
1218 | NULLCHECK(vcc); | ||
1219 | tx = ENI_VCC(vcc)->tx; | ||
1220 | NULLCHECK(ENI_VCC(vcc)->tx); | ||
1221 | DPRINTK("dequeue_tx: next 0x%lx curr 0x%x\n",ENI_PRV_POS(skb), | ||
1222 | (unsigned) eni_in(MID_TX_DESCRSTART(tx->index))); | ||
1223 | if (ENI_VCC(vcc)->txing < tx->words && ENI_PRV_POS(skb) == | ||
1224 | eni_in(MID_TX_DESCRSTART(tx->index))) { | ||
1225 | skb_queue_head(&eni_dev->tx_queue,skb); | ||
1226 | break; | ||
1227 | } | ||
1228 | ENI_VCC(vcc)->txing -= ENI_PRV_SIZE(skb); | ||
1229 | pci_unmap_single(eni_dev->pci_dev,ENI_PRV_PADDR(skb),skb->len, | ||
1230 | PCI_DMA_TODEVICE); | ||
1231 | if (vcc->pop) vcc->pop(vcc,skb); | ||
1232 | else dev_kfree_skb_irq(skb); | ||
1233 | atomic_inc(&vcc->stats->tx); | ||
1234 | wake_up(&eni_dev->tx_wait); | ||
1235 | dma_complete++; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | |||
1240 | static struct eni_tx *alloc_tx(struct eni_dev *eni_dev,int ubr) | ||
1241 | { | ||
1242 | int i; | ||
1243 | |||
1244 | for (i = !ubr; i < NR_CHAN; i++) | ||
1245 | if (!eni_dev->tx[i].send) return eni_dev->tx+i; | ||
1246 | return NULL; | ||
1247 | } | ||
1248 | |||
1249 | |||
1250 | static int comp_tx(struct eni_dev *eni_dev,int *pcr,int reserved,int *pre, | ||
1251 | int *res,int unlimited) | ||
1252 | { | ||
1253 | static const int pre_div[] = { 4,16,128,2048 }; | ||
1254 | /* 2^(((x+2)^2-(x+2))/2+1) */ | ||
1255 | |||
1256 | if (unlimited) *pre = *res = 0; | ||
1257 | else { | ||
1258 | if (*pcr > 0) { | ||
1259 | int div; | ||
1260 | |||
1261 | for (*pre = 0; *pre < 3; (*pre)++) | ||
1262 | if (TS_CLOCK/pre_div[*pre]/64 <= *pcr) break; | ||
1263 | div = pre_div[*pre]**pcr; | ||
1264 | DPRINTK("min div %d\n",div); | ||
1265 | *res = TS_CLOCK/div-1; | ||
1266 | } | ||
1267 | else { | ||
1268 | int div; | ||
1269 | |||
1270 | if (!*pcr) *pcr = eni_dev->tx_bw+reserved; | ||
1271 | for (*pre = 3; *pre >= 0; (*pre)--) | ||
1272 | if (TS_CLOCK/pre_div[*pre]/64 > -*pcr) break; | ||
1273 | if (*pre < 3) (*pre)++; /* else fail later */ | ||
1274 | div = pre_div[*pre]*-*pcr; | ||
1275 | DPRINTK("max div %d\n",div); | ||
1276 | *res = (TS_CLOCK+div-1)/div-1; | ||
1277 | } | ||
1278 | if (*res < 0) *res = 0; | ||
1279 | if (*res > MID_SEG_MAX_RATE) *res = MID_SEG_MAX_RATE; | ||
1280 | } | ||
1281 | *pcr = TS_CLOCK/pre_div[*pre]/(*res+1); | ||
1282 | DPRINTK("out pcr: %d (%d:%d)\n",*pcr,*pre,*res); | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp, | ||
1288 | int set_rsv,int set_shp) | ||
1289 | { | ||
1290 | struct eni_dev *eni_dev = ENI_DEV(vcc->dev); | ||
1291 | struct eni_vcc *eni_vcc = ENI_VCC(vcc); | ||
1292 | struct eni_tx *tx; | ||
1293 | unsigned long size; | ||
1294 | void __iomem *mem; | ||
1295 | int rate,ubr,unlimited,new_tx; | ||
1296 | int pre,res,order; | ||
1297 | int error; | ||
1298 | |||
1299 | rate = atm_pcr_goal(txtp); | ||
1300 | ubr = txtp->traffic_class == ATM_UBR; | ||
1301 | unlimited = ubr && (!rate || rate <= -ATM_OC3_PCR || | ||
1302 | rate >= ATM_OC3_PCR); | ||
1303 | if (!unlimited) { | ||
1304 | size = txtp->max_sdu*eni_dev->tx_mult/100; | ||
1305 | if (size > MID_MAX_BUF_SIZE && txtp->max_sdu <= | ||
1306 | MID_MAX_BUF_SIZE) | ||
1307 | size = MID_MAX_BUF_SIZE; | ||
1308 | } | ||
1309 | else { | ||
1310 | if (eni_dev->ubr) { | ||
1311 | eni_vcc->tx = eni_dev->ubr; | ||
1312 | txtp->pcr = ATM_OC3_PCR; | ||
1313 | return 0; | ||
1314 | } | ||
1315 | size = UBR_BUFFER; | ||
1316 | } | ||
1317 | new_tx = !eni_vcc->tx; | ||
1318 | mem = NULL; /* for gcc */ | ||
1319 | if (!new_tx) tx = eni_vcc->tx; | ||
1320 | else { | ||
1321 | mem = eni_alloc_mem(eni_dev,&size); | ||
1322 | if (!mem) return -ENOBUFS; | ||
1323 | tx = alloc_tx(eni_dev,unlimited); | ||
1324 | if (!tx) { | ||
1325 | eni_free_mem(eni_dev,mem,size); | ||
1326 | return -EBUSY; | ||
1327 | } | ||
1328 | DPRINTK("got chan %d\n",tx->index); | ||
1329 | tx->reserved = tx->shaping = 0; | ||
1330 | tx->send = mem; | ||
1331 | tx->words = size >> 2; | ||
1332 | skb_queue_head_init(&tx->backlog); | ||
1333 | for (order = 0; size > (1 << (order+10)); order++); | ||
1334 | eni_out((order << MID_SIZE_SHIFT) | | ||
1335 | ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)), | ||
1336 | MID_TX_PLACE(tx->index)); | ||
1337 | tx->tx_pos = eni_in(MID_TX_DESCRSTART(tx->index)) & | ||
1338 | MID_DESCR_START; | ||
1339 | } | ||
1340 | error = comp_tx(eni_dev,&rate,tx->reserved,&pre,&res,unlimited); | ||
1341 | if (!error && txtp->min_pcr > rate) error = -EINVAL; | ||
1342 | if (!error && txtp->max_pcr && txtp->max_pcr != ATM_MAX_PCR && | ||
1343 | txtp->max_pcr < rate) error = -EINVAL; | ||
1344 | if (!error && !ubr && rate > eni_dev->tx_bw+tx->reserved) | ||
1345 | error = -EINVAL; | ||
1346 | if (!error && set_rsv && !set_shp && rate < tx->shaping) | ||
1347 | error = -EINVAL; | ||
1348 | if (!error && !set_rsv && rate > tx->reserved && !ubr) | ||
1349 | error = -EINVAL; | ||
1350 | if (error) { | ||
1351 | if (new_tx) { | ||
1352 | tx->send = NULL; | ||
1353 | eni_free_mem(eni_dev,mem,size); | ||
1354 | } | ||
1355 | return error; | ||
1356 | } | ||
1357 | txtp->pcr = rate; | ||
1358 | if (set_rsv && !ubr) { | ||
1359 | eni_dev->tx_bw += tx->reserved; | ||
1360 | tx->reserved = rate; | ||
1361 | eni_dev->tx_bw -= rate; | ||
1362 | } | ||
1363 | if (set_shp || (unlimited && new_tx)) { | ||
1364 | if (unlimited && new_tx) eni_dev->ubr = tx; | ||
1365 | tx->prescaler = pre; | ||
1366 | tx->resolution = res; | ||
1367 | tx->shaping = rate; | ||
1368 | } | ||
1369 | if (set_shp) eni_vcc->tx = tx; | ||
1370 | DPRINTK("rsv %d shp %d\n",tx->reserved,tx->shaping); | ||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1374 | |||
1375 | static int open_tx_first(struct atm_vcc *vcc) | ||
1376 | { | ||
1377 | ENI_VCC(vcc)->tx = NULL; | ||
1378 | if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; | ||
1379 | ENI_VCC(vcc)->txing = 0; | ||
1380 | return reserve_or_set_tx(vcc,&vcc->qos.txtp,1,1); | ||
1381 | } | ||
1382 | |||
1383 | |||
1384 | static int open_tx_second(struct atm_vcc *vcc) | ||
1385 | { | ||
1386 | return 0; /* nothing to do */ | ||
1387 | } | ||
1388 | |||
1389 | |||
1390 | static void close_tx(struct atm_vcc *vcc) | ||
1391 | { | ||
1392 | DECLARE_WAITQUEUE(wait,current); | ||
1393 | struct eni_dev *eni_dev; | ||
1394 | struct eni_vcc *eni_vcc; | ||
1395 | |||
1396 | eni_vcc = ENI_VCC(vcc); | ||
1397 | if (!eni_vcc->tx) return; | ||
1398 | eni_dev = ENI_DEV(vcc->dev); | ||
1399 | /* wait for TX queue to drain */ | ||
1400 | DPRINTK("eni_close: waiting for TX ...\n"); | ||
1401 | add_wait_queue(&eni_dev->tx_wait,&wait); | ||
1402 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1403 | for (;;) { | ||
1404 | int txing; | ||
1405 | |||
1406 | tasklet_disable(&eni_dev->task); | ||
1407 | txing = skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing; | ||
1408 | tasklet_enable(&eni_dev->task); | ||
1409 | if (!txing) break; | ||
1410 | DPRINTK("%d TX left\n",eni_vcc->txing); | ||
1411 | schedule(); | ||
1412 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1413 | } | ||
1414 | set_current_state(TASK_RUNNING); | ||
1415 | remove_wait_queue(&eni_dev->tx_wait,&wait); | ||
1416 | if (eni_vcc->tx != eni_dev->ubr) { | ||
1417 | /* | ||
1418 | * Looping a few times in here is probably far cheaper than | ||
1419 | * keeping track of TX completions all the time, so let's poll | ||
1420 | * a bit ... | ||
1421 | */ | ||
1422 | while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) != | ||
1423 | eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index))) | ||
1424 | schedule(); | ||
1425 | eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2); | ||
1426 | eni_vcc->tx->send = NULL; | ||
1427 | eni_dev->tx_bw += eni_vcc->tx->reserved; | ||
1428 | } | ||
1429 | eni_vcc->tx = NULL; | ||
1430 | } | ||
1431 | |||
1432 | |||
1433 | static int start_tx(struct atm_dev *dev) | ||
1434 | { | ||
1435 | struct eni_dev *eni_dev; | ||
1436 | int i; | ||
1437 | |||
1438 | eni_dev = ENI_DEV(dev); | ||
1439 | eni_dev->lost = 0; | ||
1440 | eni_dev->tx_bw = ATM_OC3_PCR; | ||
1441 | eni_dev->tx_mult = DEFAULT_TX_MULT; | ||
1442 | init_waitqueue_head(&eni_dev->tx_wait); | ||
1443 | eni_dev->ubr = NULL; | ||
1444 | skb_queue_head_init(&eni_dev->tx_queue); | ||
1445 | eni_out(0,MID_DMA_WR_TX); | ||
1446 | for (i = 0; i < NR_CHAN; i++) { | ||
1447 | eni_dev->tx[i].send = NULL; | ||
1448 | eni_dev->tx[i].index = i; | ||
1449 | } | ||
1450 | return 0; | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | /*--------------------------------- common ----------------------------------*/ | ||
1455 | |||
1456 | |||
1457 | #if 0 /* may become useful again when tuning things */ | ||
1458 | |||
1459 | static void foo(void) | ||
1460 | { | ||
1461 | printk(KERN_INFO | ||
1462 | "tx_complete=%d,dma_complete=%d,queued=%d,requeued=%d,sub=%d,\n" | ||
1463 | "backlogged=%d,rx_enqueued=%d,rx_dequeued=%d,putting=%d,pushed=%d\n", | ||
1464 | tx_complete,dma_complete,queued,requeued,submitted,backlogged, | ||
1465 | rx_enqueued,rx_dequeued,putting,pushed); | ||
1466 | if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost); | ||
1467 | } | ||
1468 | |||
1469 | #endif | ||
1470 | |||
1471 | |||
1472 | static void bug_int(struct atm_dev *dev,unsigned long reason) | ||
1473 | { | ||
1474 | struct eni_dev *eni_dev; | ||
1475 | |||
1476 | DPRINTK(">bug_int\n"); | ||
1477 | eni_dev = ENI_DEV(dev); | ||
1478 | if (reason & MID_DMA_ERR_ACK) | ||
1479 | printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA " | ||
1480 | "error\n",dev->number); | ||
1481 | if (reason & MID_TX_IDENT_MISM) | ||
1482 | printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - ident " | ||
1483 | "mismatch\n",dev->number); | ||
1484 | if (reason & MID_TX_DMA_OVFL) | ||
1485 | printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA " | ||
1486 | "overflow\n",dev->number); | ||
1487 | EVENT("---dump ends here---\n",0,0); | ||
1488 | printk(KERN_NOTICE "---recent events---\n"); | ||
1489 | event_dump(); | ||
1490 | } | ||
1491 | |||
1492 | |||
1493 | static irqreturn_t eni_int(int irq,void *dev_id,struct pt_regs *regs) | ||
1494 | { | ||
1495 | struct atm_dev *dev; | ||
1496 | struct eni_dev *eni_dev; | ||
1497 | u32 reason; | ||
1498 | |||
1499 | DPRINTK(">eni_int\n"); | ||
1500 | dev = dev_id; | ||
1501 | eni_dev = ENI_DEV(dev); | ||
1502 | reason = eni_in(MID_ISA); | ||
1503 | DPRINTK(DEV_LABEL ": int 0x%lx\n",(unsigned long) reason); | ||
1504 | /* | ||
1505 | * Must handle these two right now, because reading ISA doesn't clear | ||
1506 | * them, so they re-occur and we never make it to the tasklet. Since | ||
1507 | * they're rare, we don't mind the occasional invocation of eni_tasklet | ||
1508 | * with eni_dev->events == 0. | ||
1509 | */ | ||
1510 | if (reason & MID_STAT_OVFL) { | ||
1511 | EVENT("stat overflow\n",0,0); | ||
1512 | eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH; | ||
1513 | } | ||
1514 | if (reason & MID_SUNI_INT) { | ||
1515 | EVENT("SUNI int\n",0,0); | ||
1516 | dev->phy->interrupt(dev); | ||
1517 | #if 0 | ||
1518 | foo(); | ||
1519 | #endif | ||
1520 | } | ||
1521 | spin_lock(&eni_dev->lock); | ||
1522 | eni_dev->events |= reason; | ||
1523 | spin_unlock(&eni_dev->lock); | ||
1524 | tasklet_schedule(&eni_dev->task); | ||
1525 | return IRQ_HANDLED; | ||
1526 | } | ||
1527 | |||
1528 | |||
1529 | static void eni_tasklet(unsigned long data) | ||
1530 | { | ||
1531 | struct atm_dev *dev = (struct atm_dev *) data; | ||
1532 | struct eni_dev *eni_dev = ENI_DEV(dev); | ||
1533 | unsigned long flags; | ||
1534 | u32 events; | ||
1535 | |||
1536 | DPRINTK("eni_tasklet (dev %p)\n",dev); | ||
1537 | spin_lock_irqsave(&eni_dev->lock,flags); | ||
1538 | events = xchg(&eni_dev->events,0); | ||
1539 | spin_unlock_irqrestore(&eni_dev->lock,flags); | ||
1540 | if (events & MID_RX_DMA_COMPLETE) { | ||
1541 | EVENT("INT: RX DMA complete, starting dequeue_rx\n",0,0); | ||
1542 | dequeue_rx(dev); | ||
1543 | EVENT("dequeue_rx done, starting poll_rx\n",0,0); | ||
1544 | poll_rx(dev); | ||
1545 | EVENT("poll_rx done\n",0,0); | ||
1546 | /* poll_tx ? */ | ||
1547 | } | ||
1548 | if (events & MID_SERVICE) { | ||
1549 | EVENT("INT: service, starting get_service\n",0,0); | ||
1550 | get_service(dev); | ||
1551 | EVENT("get_service done, starting poll_rx\n",0,0); | ||
1552 | poll_rx(dev); | ||
1553 | EVENT("poll_rx done\n",0,0); | ||
1554 | } | ||
1555 | if (events & MID_TX_DMA_COMPLETE) { | ||
1556 | EVENT("INT: TX DMA COMPLETE\n",0,0); | ||
1557 | dequeue_tx(dev); | ||
1558 | } | ||
1559 | if (events & MID_TX_COMPLETE) { | ||
1560 | EVENT("INT: TX COMPLETE\n",0,0); | ||
1561 | tx_complete++; | ||
1562 | wake_up(&eni_dev->tx_wait); | ||
1563 | /* poll_rx ? */ | ||
1564 | } | ||
1565 | if (events & (MID_DMA_ERR_ACK | MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) { | ||
1566 | EVENT("bug interrupt\n",0,0); | ||
1567 | bug_int(dev,events); | ||
1568 | } | ||
1569 | poll_tx(dev); | ||
1570 | } | ||
1571 | |||
1572 | |||
1573 | /*--------------------------------- entries ---------------------------------*/ | ||
1574 | |||
1575 | |||
1576 | static const char *media_name[] __devinitdata = { | ||
1577 | "MMF", "SMF", "MMF", "03?", /* 0- 3 */ | ||
1578 | "UTP", "05?", "06?", "07?", /* 4- 7 */ | ||
1579 | "TAXI","09?", "10?", "11?", /* 8-11 */ | ||
1580 | "12?", "13?", "14?", "15?", /* 12-15 */ | ||
1581 | "MMF", "SMF", "18?", "19?", /* 16-19 */ | ||
1582 | "UTP", "21?", "22?", "23?", /* 20-23 */ | ||
1583 | "24?", "25?", "26?", "27?", /* 24-27 */ | ||
1584 | "28?", "29?", "30?", "31?" /* 28-31 */ | ||
1585 | }; | ||
1586 | |||
1587 | |||
1588 | #define SET_SEPROM \ | ||
1589 | ({ if (!error && !pci_error) { \ | ||
1590 | pci_error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,tonga); \ | ||
1591 | udelay(10); /* 10 usecs */ \ | ||
1592 | } }) | ||
1593 | #define GET_SEPROM \ | ||
1594 | ({ if (!error && !pci_error) { \ | ||
1595 | pci_error = pci_read_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,&tonga); \ | ||
1596 | udelay(10); /* 10 usecs */ \ | ||
1597 | } }) | ||
1598 | |||
1599 | |||
1600 | static int __devinit get_esi_asic(struct atm_dev *dev) | ||
1601 | { | ||
1602 | struct eni_dev *eni_dev; | ||
1603 | unsigned char tonga; | ||
1604 | int error,failed,pci_error; | ||
1605 | int address,i,j; | ||
1606 | |||
1607 | eni_dev = ENI_DEV(dev); | ||
1608 | error = pci_error = 0; | ||
1609 | tonga = SEPROM_MAGIC | SEPROM_DATA | SEPROM_CLK; | ||
1610 | SET_SEPROM; | ||
1611 | for (i = 0; i < ESI_LEN && !error && !pci_error; i++) { | ||
1612 | /* start operation */ | ||
1613 | tonga |= SEPROM_DATA; | ||
1614 | SET_SEPROM; | ||
1615 | tonga |= SEPROM_CLK; | ||
1616 | SET_SEPROM; | ||
1617 | tonga &= ~SEPROM_DATA; | ||
1618 | SET_SEPROM; | ||
1619 | tonga &= ~SEPROM_CLK; | ||
1620 | SET_SEPROM; | ||
1621 | /* send address */ | ||
1622 | address = ((i+SEPROM_ESI_BASE) << 1)+1; | ||
1623 | for (j = 7; j >= 0; j--) { | ||
1624 | tonga = (address >> j) & 1 ? tonga | SEPROM_DATA : | ||
1625 | tonga & ~SEPROM_DATA; | ||
1626 | SET_SEPROM; | ||
1627 | tonga |= SEPROM_CLK; | ||
1628 | SET_SEPROM; | ||
1629 | tonga &= ~SEPROM_CLK; | ||
1630 | SET_SEPROM; | ||
1631 | } | ||
1632 | /* get ack */ | ||
1633 | tonga |= SEPROM_DATA; | ||
1634 | SET_SEPROM; | ||
1635 | tonga |= SEPROM_CLK; | ||
1636 | SET_SEPROM; | ||
1637 | GET_SEPROM; | ||
1638 | failed = tonga & SEPROM_DATA; | ||
1639 | tonga &= ~SEPROM_CLK; | ||
1640 | SET_SEPROM; | ||
1641 | tonga |= SEPROM_DATA; | ||
1642 | SET_SEPROM; | ||
1643 | if (failed) error = -EIO; | ||
1644 | else { | ||
1645 | dev->esi[i] = 0; | ||
1646 | for (j = 7; j >= 0; j--) { | ||
1647 | dev->esi[i] <<= 1; | ||
1648 | tonga |= SEPROM_DATA; | ||
1649 | SET_SEPROM; | ||
1650 | tonga |= SEPROM_CLK; | ||
1651 | SET_SEPROM; | ||
1652 | GET_SEPROM; | ||
1653 | if (tonga & SEPROM_DATA) dev->esi[i] |= 1; | ||
1654 | tonga &= ~SEPROM_CLK; | ||
1655 | SET_SEPROM; | ||
1656 | tonga |= SEPROM_DATA; | ||
1657 | SET_SEPROM; | ||
1658 | } | ||
1659 | /* get ack */ | ||
1660 | tonga |= SEPROM_DATA; | ||
1661 | SET_SEPROM; | ||
1662 | tonga |= SEPROM_CLK; | ||
1663 | SET_SEPROM; | ||
1664 | GET_SEPROM; | ||
1665 | if (!(tonga & SEPROM_DATA)) error = -EIO; | ||
1666 | tonga &= ~SEPROM_CLK; | ||
1667 | SET_SEPROM; | ||
1668 | tonga |= SEPROM_DATA; | ||
1669 | SET_SEPROM; | ||
1670 | } | ||
1671 | /* stop operation */ | ||
1672 | tonga &= ~SEPROM_DATA; | ||
1673 | SET_SEPROM; | ||
1674 | tonga |= SEPROM_CLK; | ||
1675 | SET_SEPROM; | ||
1676 | tonga |= SEPROM_DATA; | ||
1677 | SET_SEPROM; | ||
1678 | } | ||
1679 | if (pci_error) { | ||
1680 | printk(KERN_ERR DEV_LABEL "(itf %d): error reading ESI " | ||
1681 | "(0x%02x)\n",dev->number,pci_error); | ||
1682 | error = -EIO; | ||
1683 | } | ||
1684 | return error; | ||
1685 | } | ||
1686 | |||
1687 | |||
1688 | #undef SET_SEPROM | ||
1689 | #undef GET_SEPROM | ||
1690 | |||
1691 | |||
1692 | static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base) | ||
1693 | { | ||
1694 | void __iomem *mac_base; | ||
1695 | int i; | ||
1696 | |||
1697 | mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom); | ||
1698 | for (i = 0; i < ESI_LEN; i++) dev->esi[i] = readb(mac_base+(i^3)); | ||
1699 | return 0; | ||
1700 | } | ||
1701 | |||
1702 | |||
1703 | static int __devinit eni_do_init(struct atm_dev *dev) | ||
1704 | { | ||
1705 | struct midway_eprom __iomem *eprom; | ||
1706 | struct eni_dev *eni_dev; | ||
1707 | struct pci_dev *pci_dev; | ||
1708 | unsigned long real_base; | ||
1709 | void __iomem *base; | ||
1710 | unsigned char revision; | ||
1711 | int error,i,last; | ||
1712 | |||
1713 | DPRINTK(">eni_init\n"); | ||
1714 | dev->ci_range.vpi_bits = 0; | ||
1715 | dev->ci_range.vci_bits = NR_VCI_LD; | ||
1716 | dev->link_rate = ATM_OC3_PCR; | ||
1717 | eni_dev = ENI_DEV(dev); | ||
1718 | pci_dev = eni_dev->pci_dev; | ||
1719 | real_base = pci_resource_start(pci_dev, 0); | ||
1720 | eni_dev->irq = pci_dev->irq; | ||
1721 | error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision); | ||
1722 | if (error) { | ||
1723 | printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n", | ||
1724 | dev->number,error); | ||
1725 | return -EINVAL; | ||
1726 | } | ||
1727 | if ((error = pci_write_config_word(pci_dev,PCI_COMMAND, | ||
1728 | PCI_COMMAND_MEMORY | | ||
1729 | (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) { | ||
1730 | printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory " | ||
1731 | "(0x%02x)\n",dev->number,error); | ||
1732 | return -EIO; | ||
1733 | } | ||
1734 | printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,", | ||
1735 | dev->number,revision,real_base,eni_dev->irq); | ||
1736 | if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) { | ||
1737 | printk("\n"); | ||
1738 | printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page " | ||
1739 | "mapping\n",dev->number); | ||
1740 | return error; | ||
1741 | } | ||
1742 | eni_dev->base_diff = real_base - (unsigned long) base; | ||
1743 | /* id may not be present in ASIC Tonga boards - check this @@@ */ | ||
1744 | if (!eni_dev->asic) { | ||
1745 | eprom = (base+EPROM_SIZE-sizeof(struct midway_eprom)); | ||
1746 | if (readl(&eprom->magic) != ENI155_MAGIC) { | ||
1747 | printk("\n"); | ||
1748 | printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad " | ||
1749 | "magic - expected 0x%x, got 0x%x\n",dev->number, | ||
1750 | ENI155_MAGIC,(unsigned) readl(&eprom->magic)); | ||
1751 | return -EINVAL; | ||
1752 | } | ||
1753 | } | ||
1754 | eni_dev->phy = base+PHY_BASE; | ||
1755 | eni_dev->reg = base+REG_BASE; | ||
1756 | eni_dev->ram = base+RAM_BASE; | ||
1757 | last = MAP_MAX_SIZE-RAM_BASE; | ||
1758 | for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) { | ||
1759 | writel(0x55555555,eni_dev->ram+i); | ||
1760 | if (readl(eni_dev->ram+i) != 0x55555555) last = i; | ||
1761 | else { | ||
1762 | writel(0xAAAAAAAA,eni_dev->ram+i); | ||
1763 | if (readl(eni_dev->ram+i) != 0xAAAAAAAA) last = i; | ||
1764 | else writel(i,eni_dev->ram+i); | ||
1765 | } | ||
1766 | } | ||
1767 | for (i = 0; i < last; i += RAM_INCREMENT) | ||
1768 | if (readl(eni_dev->ram+i) != i) break; | ||
1769 | eni_dev->mem = i; | ||
1770 | memset_io(eni_dev->ram,0,eni_dev->mem); | ||
1771 | /* TODO: should shrink allocation now */ | ||
1772 | printk("mem=%dkB (",eni_dev->mem >> 10); | ||
1773 | /* TODO: check for non-SUNI, check for TAXI ? */ | ||
1774 | if (!(eni_in(MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) { | ||
1775 | printk(")\n"); | ||
1776 | printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n", | ||
1777 | dev->number,(unsigned) eni_in(MID_RES_ID_MCON)); | ||
1778 | return -EINVAL; | ||
1779 | } | ||
1780 | error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base); | ||
1781 | if (error) return error; | ||
1782 | for (i = 0; i < ESI_LEN; i++) | ||
1783 | printk("%s%02X",i ? "-" : "",dev->esi[i]); | ||
1784 | printk(")\n"); | ||
1785 | printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number, | ||
1786 | eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA", | ||
1787 | media_name[eni_in(MID_RES_ID_MCON) & DAUGTHER_ID]); | ||
1788 | return suni_init(dev); | ||
1789 | } | ||
1790 | |||
1791 | |||
1792 | static int __devinit eni_start(struct atm_dev *dev) | ||
1793 | { | ||
1794 | struct eni_dev *eni_dev; | ||
1795 | |||
1796 | void __iomem *buf; | ||
1797 | unsigned long buffer_mem; | ||
1798 | int error; | ||
1799 | |||
1800 | DPRINTK(">eni_start\n"); | ||
1801 | eni_dev = ENI_DEV(dev); | ||
1802 | if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) { | ||
1803 | printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", | ||
1804 | dev->number,eni_dev->irq); | ||
1805 | return -EAGAIN; | ||
1806 | } | ||
1807 | /* @@@ should release IRQ on error */ | ||
1808 | pci_set_master(eni_dev->pci_dev); | ||
1809 | if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND, | ||
1810 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | ||
1811 | (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) { | ||
1812 | printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+" | ||
1813 | "master (0x%02x)\n",dev->number,error); | ||
1814 | return error; | ||
1815 | } | ||
1816 | if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL, | ||
1817 | END_SWAP_DMA))) { | ||
1818 | printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap " | ||
1819 | "(0x%02x)\n",dev->number,error); | ||
1820 | return error; | ||
1821 | } | ||
1822 | /* determine addresses of internal tables */ | ||
1823 | eni_dev->vci = eni_dev->ram; | ||
1824 | eni_dev->rx_dma = eni_dev->ram+NR_VCI*16; | ||
1825 | eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*8; | ||
1826 | eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*8; | ||
1827 | buf = eni_dev->service+NR_SERVICE*4; | ||
1828 | DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n", | ||
1829 | eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma, | ||
1830 | eni_dev->service,buf); | ||
1831 | spin_lock_init(&eni_dev->lock); | ||
1832 | tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev); | ||
1833 | eni_dev->events = 0; | ||
1834 | /* initialize memory management */ | ||
1835 | buffer_mem = eni_dev->mem - (buf - eni_dev->ram); | ||
1836 | eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2; | ||
1837 | eni_dev->free_list = (struct eni_free *) kmalloc( | ||
1838 | sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL); | ||
1839 | if (!eni_dev->free_list) { | ||
1840 | printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n", | ||
1841 | dev->number); | ||
1842 | return -ENOMEM; | ||
1843 | } | ||
1844 | eni_dev->free_len = 0; | ||
1845 | eni_put_free(eni_dev,buf,buffer_mem); | ||
1846 | memset_io(eni_dev->vci,0,16*NR_VCI); /* clear VCI table */ | ||
1847 | /* | ||
1848 | * byte_addr free (k) | ||
1849 | * 0x00000000 512 VCI table | ||
1850 | * 0x00004000 496 RX DMA | ||
1851 | * 0x00005000 492 TX DMA | ||
1852 | * 0x00006000 488 service list | ||
1853 | * 0x00007000 484 buffers | ||
1854 | * 0x00080000 0 end (512kB) | ||
1855 | */ | ||
1856 | eni_out(0xffffffff,MID_IE); | ||
1857 | error = start_tx(dev); | ||
1858 | if (error) return error; | ||
1859 | error = start_rx(dev); | ||
1860 | if (error) return error; | ||
1861 | error = dev->phy->start(dev); | ||
1862 | if (error) return error; | ||
1863 | eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) | | ||
1864 | MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE, | ||
1865 | MID_MC_S); | ||
1866 | /* Tonga uses SBus INTReq1 */ | ||
1867 | (void) eni_in(MID_ISA); /* clear Midway interrupts */ | ||
1868 | return 0; | ||
1869 | } | ||
1870 | |||
1871 | |||
1872 | static void eni_close(struct atm_vcc *vcc) | ||
1873 | { | ||
1874 | DPRINTK(">eni_close\n"); | ||
1875 | if (!ENI_VCC(vcc)) return; | ||
1876 | clear_bit(ATM_VF_READY,&vcc->flags); | ||
1877 | close_rx(vcc); | ||
1878 | close_tx(vcc); | ||
1879 | DPRINTK("eni_close: done waiting\n"); | ||
1880 | /* deallocate memory */ | ||
1881 | kfree(ENI_VCC(vcc)); | ||
1882 | vcc->dev_data = NULL; | ||
1883 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1884 | /*foo();*/ | ||
1885 | } | ||
1886 | |||
1887 | |||
1888 | static int eni_open(struct atm_vcc *vcc) | ||
1889 | { | ||
1890 | struct eni_dev *eni_dev; | ||
1891 | struct eni_vcc *eni_vcc; | ||
1892 | int error; | ||
1893 | short vpi = vcc->vpi; | ||
1894 | int vci = vcc->vci; | ||
1895 | |||
1896 | DPRINTK(">eni_open\n"); | ||
1897 | EVENT("eni_open\n",0,0); | ||
1898 | if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) | ||
1899 | vcc->dev_data = NULL; | ||
1900 | eni_dev = ENI_DEV(vcc->dev); | ||
1901 | if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) | ||
1902 | set_bit(ATM_VF_ADDR,&vcc->flags); | ||
1903 | if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5) | ||
1904 | return -EINVAL; | ||
1905 | DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi, | ||
1906 | vcc->vci); | ||
1907 | if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { | ||
1908 | eni_vcc = kmalloc(sizeof(struct eni_vcc),GFP_KERNEL); | ||
1909 | if (!eni_vcc) return -ENOMEM; | ||
1910 | vcc->dev_data = eni_vcc; | ||
1911 | eni_vcc->tx = NULL; /* for eni_close after open_rx */ | ||
1912 | if ((error = open_rx_first(vcc))) { | ||
1913 | eni_close(vcc); | ||
1914 | return error; | ||
1915 | } | ||
1916 | if ((error = open_tx_first(vcc))) { | ||
1917 | eni_close(vcc); | ||
1918 | return error; | ||
1919 | } | ||
1920 | } | ||
1921 | if (vci == ATM_VPI_UNSPEC || vpi == ATM_VCI_UNSPEC) return 0; | ||
1922 | if ((error = open_rx_second(vcc))) { | ||
1923 | eni_close(vcc); | ||
1924 | return error; | ||
1925 | } | ||
1926 | if ((error = open_tx_second(vcc))) { | ||
1927 | eni_close(vcc); | ||
1928 | return error; | ||
1929 | } | ||
1930 | set_bit(ATM_VF_READY,&vcc->flags); | ||
1931 | /* should power down SUNI while !ref_count @@@ */ | ||
1932 | return 0; | ||
1933 | } | ||
1934 | |||
1935 | |||
1936 | static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs) | ||
1937 | { | ||
1938 | struct eni_dev *eni_dev = ENI_DEV(vcc->dev); | ||
1939 | struct eni_tx *tx = ENI_VCC(vcc)->tx; | ||
1940 | struct sk_buff *skb; | ||
1941 | int error,rate,rsv,shp; | ||
1942 | |||
1943 | if (qos->txtp.traffic_class == ATM_NONE) return 0; | ||
1944 | if (tx == eni_dev->ubr) return -EBADFD; | ||
1945 | rate = atm_pcr_goal(&qos->txtp); | ||
1946 | if (rate < 0) rate = -rate; | ||
1947 | rsv = shp = 0; | ||
1948 | if ((flgs & ATM_MF_DEC_RSV) && rate && rate < tx->reserved) rsv = 1; | ||
1949 | if ((flgs & ATM_MF_INC_RSV) && (!rate || rate > tx->reserved)) rsv = 1; | ||
1950 | if ((flgs & ATM_MF_DEC_SHP) && rate && rate < tx->shaping) shp = 1; | ||
1951 | if ((flgs & ATM_MF_INC_SHP) && (!rate || rate > tx->shaping)) shp = 1; | ||
1952 | if (!rsv && !shp) return 0; | ||
1953 | error = reserve_or_set_tx(vcc,&qos->txtp,rsv,shp); | ||
1954 | if (error) return error; | ||
1955 | if (shp && !(flgs & ATM_MF_IMMED)) return 0; | ||
1956 | /* | ||
1957 | * Walk through the send buffer and patch the rate information in all | ||
1958 | * segmentation buffer descriptors of this VCC. | ||
1959 | */ | ||
1960 | tasklet_disable(&eni_dev->task); | ||
1961 | skb_queue_walk(&eni_dev->tx_queue, skb) { | ||
1962 | void __iomem *dsc; | ||
1963 | |||
1964 | if (ATM_SKB(skb)->vcc != vcc) continue; | ||
1965 | dsc = tx->send+ENI_PRV_POS(skb)*4; | ||
1966 | writel((readl(dsc) & ~(MID_SEG_RATE | MID_SEG_PR)) | | ||
1967 | (tx->prescaler << MID_SEG_PR_SHIFT) | | ||
1968 | (tx->resolution << MID_SEG_RATE_SHIFT), dsc); | ||
1969 | } | ||
1970 | tasklet_enable(&eni_dev->task); | ||
1971 | return 0; | ||
1972 | } | ||
1973 | |||
1974 | |||
1975 | static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
1976 | { | ||
1977 | struct eni_dev *eni_dev = ENI_DEV(dev); | ||
1978 | |||
1979 | if (cmd == ENI_MEMDUMP) { | ||
1980 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
1981 | printk(KERN_WARNING "Please use /proc/atm/" DEV_LABEL ":%d " | ||
1982 | "instead of obsolete ioctl ENI_MEMDUMP\n",dev->number); | ||
1983 | dump(dev); | ||
1984 | return 0; | ||
1985 | } | ||
1986 | if (cmd == ENI_SETMULT) { | ||
1987 | struct eni_multipliers mult; | ||
1988 | |||
1989 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
1990 | if (copy_from_user(&mult, arg, | ||
1991 | sizeof(struct eni_multipliers))) | ||
1992 | return -EFAULT; | ||
1993 | if ((mult.tx && mult.tx <= 100) || (mult.rx &&mult.rx <= 100) || | ||
1994 | mult.tx > 65536 || mult.rx > 65536) | ||
1995 | return -EINVAL; | ||
1996 | if (mult.tx) eni_dev->tx_mult = mult.tx; | ||
1997 | if (mult.rx) eni_dev->rx_mult = mult.rx; | ||
1998 | return 0; | ||
1999 | } | ||
2000 | if (cmd == ATM_SETCIRANGE) { | ||
2001 | struct atm_cirange ci; | ||
2002 | |||
2003 | if (copy_from_user(&ci, arg,sizeof(struct atm_cirange))) | ||
2004 | return -EFAULT; | ||
2005 | if ((ci.vpi_bits == 0 || ci.vpi_bits == ATM_CI_MAX) && | ||
2006 | (ci.vci_bits == NR_VCI_LD || ci.vpi_bits == ATM_CI_MAX)) | ||
2007 | return 0; | ||
2008 | return -EINVAL; | ||
2009 | } | ||
2010 | if (!dev->phy->ioctl) return -ENOIOCTLCMD; | ||
2011 | return dev->phy->ioctl(dev,cmd,arg); | ||
2012 | } | ||
2013 | |||
2014 | |||
2015 | static int eni_getsockopt(struct atm_vcc *vcc,int level,int optname, | ||
2016 | void __user *optval,int optlen) | ||
2017 | { | ||
2018 | return -EINVAL; | ||
2019 | } | ||
2020 | |||
2021 | |||
2022 | static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname, | ||
2023 | void __user *optval,int optlen) | ||
2024 | { | ||
2025 | return -EINVAL; | ||
2026 | } | ||
2027 | |||
2028 | |||
2029 | static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb) | ||
2030 | { | ||
2031 | enum enq_res res; | ||
2032 | |||
2033 | DPRINTK(">eni_send\n"); | ||
2034 | if (!ENI_VCC(vcc)->tx) { | ||
2035 | if (vcc->pop) vcc->pop(vcc,skb); | ||
2036 | else dev_kfree_skb(skb); | ||
2037 | return -EINVAL; | ||
2038 | } | ||
2039 | if (!skb) { | ||
2040 | printk(KERN_CRIT "!skb in eni_send ?\n"); | ||
2041 | if (vcc->pop) vcc->pop(vcc,skb); | ||
2042 | return -EINVAL; | ||
2043 | } | ||
2044 | if (vcc->qos.aal == ATM_AAL0) { | ||
2045 | if (skb->len != ATM_CELL_SIZE-1) { | ||
2046 | if (vcc->pop) vcc->pop(vcc,skb); | ||
2047 | else dev_kfree_skb(skb); | ||
2048 | return -EINVAL; | ||
2049 | } | ||
2050 | *(u32 *) skb->data = htonl(*(u32 *) skb->data); | ||
2051 | } | ||
2052 | submitted++; | ||
2053 | ATM_SKB(skb)->vcc = vcc; | ||
2054 | tasklet_disable(&ENI_DEV(vcc->dev)->task); | ||
2055 | res = do_tx(skb); | ||
2056 | tasklet_enable(&ENI_DEV(vcc->dev)->task); | ||
2057 | if (res == enq_ok) return 0; | ||
2058 | skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb); | ||
2059 | backlogged++; | ||
2060 | tasklet_schedule(&ENI_DEV(vcc->dev)->task); | ||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static void eni_phy_put(struct atm_dev *dev,unsigned char value, | ||
2065 | unsigned long addr) | ||
2066 | { | ||
2067 | writel(value,ENI_DEV(dev)->phy+addr*4); | ||
2068 | } | ||
2069 | |||
2070 | |||
2071 | |||
2072 | static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr) | ||
2073 | { | ||
2074 | return readl(ENI_DEV(dev)->phy+addr*4); | ||
2075 | } | ||
2076 | |||
2077 | |||
2078 | static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) | ||
2079 | { | ||
2080 | struct hlist_node *node; | ||
2081 | struct sock *s; | ||
2082 | static const char *signal[] = { "LOST","unknown","okay" }; | ||
2083 | struct eni_dev *eni_dev = ENI_DEV(dev); | ||
2084 | struct atm_vcc *vcc; | ||
2085 | int left,i; | ||
2086 | |||
2087 | left = *pos; | ||
2088 | if (!left) | ||
2089 | return sprintf(page,DEV_LABEL "(itf %d) signal %s, %dkB, " | ||
2090 | "%d cps remaining\n",dev->number,signal[(int) dev->signal], | ||
2091 | eni_dev->mem >> 10,eni_dev->tx_bw); | ||
2092 | if (!--left) | ||
2093 | return sprintf(page,"%4sBursts: TX" | ||
2094 | #if !defined(CONFIG_ATM_ENI_BURST_TX_16W) && \ | ||
2095 | !defined(CONFIG_ATM_ENI_BURST_TX_8W) && \ | ||
2096 | !defined(CONFIG_ATM_ENI_BURST_TX_4W) && \ | ||
2097 | !defined(CONFIG_ATM_ENI_BURST_TX_2W) | ||
2098 | " none" | ||
2099 | #endif | ||
2100 | #ifdef CONFIG_ATM_ENI_BURST_TX_16W | ||
2101 | " 16W" | ||
2102 | #endif | ||
2103 | #ifdef CONFIG_ATM_ENI_BURST_TX_8W | ||
2104 | " 8W" | ||
2105 | #endif | ||
2106 | #ifdef CONFIG_ATM_ENI_BURST_TX_4W | ||
2107 | " 4W" | ||
2108 | #endif | ||
2109 | #ifdef CONFIG_ATM_ENI_BURST_TX_2W | ||
2110 | " 2W" | ||
2111 | #endif | ||
2112 | ", RX" | ||
2113 | #if !defined(CONFIG_ATM_ENI_BURST_RX_16W) && \ | ||
2114 | !defined(CONFIG_ATM_ENI_BURST_RX_8W) && \ | ||
2115 | !defined(CONFIG_ATM_ENI_BURST_RX_4W) && \ | ||
2116 | !defined(CONFIG_ATM_ENI_BURST_RX_2W) | ||
2117 | " none" | ||
2118 | #endif | ||
2119 | #ifdef CONFIG_ATM_ENI_BURST_RX_16W | ||
2120 | " 16W" | ||
2121 | #endif | ||
2122 | #ifdef CONFIG_ATM_ENI_BURST_RX_8W | ||
2123 | " 8W" | ||
2124 | #endif | ||
2125 | #ifdef CONFIG_ATM_ENI_BURST_RX_4W | ||
2126 | " 4W" | ||
2127 | #endif | ||
2128 | #ifdef CONFIG_ATM_ENI_BURST_RX_2W | ||
2129 | " 2W" | ||
2130 | #endif | ||
2131 | #ifndef CONFIG_ATM_ENI_TUNE_BURST | ||
2132 | " (default)" | ||
2133 | #endif | ||
2134 | "\n",""); | ||
2135 | if (!--left) | ||
2136 | return sprintf(page,"%4sBuffer multipliers: tx %d%%, rx %d%%\n", | ||
2137 | "",eni_dev->tx_mult,eni_dev->rx_mult); | ||
2138 | for (i = 0; i < NR_CHAN; i++) { | ||
2139 | struct eni_tx *tx = eni_dev->tx+i; | ||
2140 | |||
2141 | if (!tx->send) continue; | ||
2142 | if (!--left) { | ||
2143 | return sprintf(page,"tx[%d]: 0x%ld-0x%ld " | ||
2144 | "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i, | ||
2145 | (unsigned long) (tx->send - eni_dev->ram), | ||
2146 | tx->send-eni_dev->ram+tx->words*4-1,tx->words*4, | ||
2147 | tx->reserved,tx->shaping, | ||
2148 | tx == eni_dev->ubr ? " (UBR)" : ""); | ||
2149 | } | ||
2150 | if (--left) continue; | ||
2151 | return sprintf(page,"%10sbacklog %u packets\n","", | ||
2152 | skb_queue_len(&tx->backlog)); | ||
2153 | } | ||
2154 | read_lock(&vcc_sklist_lock); | ||
2155 | for(i = 0; i < VCC_HTABLE_SIZE; ++i) { | ||
2156 | struct hlist_head *head = &vcc_hash[i]; | ||
2157 | |||
2158 | sk_for_each(s, node, head) { | ||
2159 | struct eni_vcc *eni_vcc; | ||
2160 | int length; | ||
2161 | |||
2162 | vcc = atm_sk(s); | ||
2163 | if (vcc->dev != dev) | ||
2164 | continue; | ||
2165 | eni_vcc = ENI_VCC(vcc); | ||
2166 | if (--left) continue; | ||
2167 | length = sprintf(page,"vcc %4d: ",vcc->vci); | ||
2168 | if (eni_vcc->rx) { | ||
2169 | length += sprintf(page+length,"0x%ld-0x%ld " | ||
2170 | "(%6ld bytes)", | ||
2171 | (unsigned long) (eni_vcc->recv - eni_dev->ram), | ||
2172 | eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1, | ||
2173 | eni_vcc->words*4); | ||
2174 | if (eni_vcc->tx) length += sprintf(page+length,", "); | ||
2175 | } | ||
2176 | if (eni_vcc->tx) | ||
2177 | length += sprintf(page+length,"tx[%d], txing %d bytes", | ||
2178 | eni_vcc->tx->index,eni_vcc->txing); | ||
2179 | page[length] = '\n'; | ||
2180 | read_unlock(&vcc_sklist_lock); | ||
2181 | return length+1; | ||
2182 | } | ||
2183 | } | ||
2184 | read_unlock(&vcc_sklist_lock); | ||
2185 | for (i = 0; i < eni_dev->free_len; i++) { | ||
2186 | struct eni_free *fe = eni_dev->free_list+i; | ||
2187 | unsigned long offset; | ||
2188 | |||
2189 | if (--left) continue; | ||
2190 | offset = (unsigned long) eni_dev->ram+eni_dev->base_diff; | ||
2191 | return sprintf(page,"free %p-%p (%6d bytes)\n", | ||
2192 | fe->start-offset,fe->start-offset+(1 << fe->order)-1, | ||
2193 | 1 << fe->order); | ||
2194 | } | ||
2195 | return 0; | ||
2196 | } | ||
2197 | |||
2198 | |||
2199 | static const struct atmdev_ops ops = { | ||
2200 | .open = eni_open, | ||
2201 | .close = eni_close, | ||
2202 | .ioctl = eni_ioctl, | ||
2203 | .getsockopt = eni_getsockopt, | ||
2204 | .setsockopt = eni_setsockopt, | ||
2205 | .send = eni_send, | ||
2206 | .phy_put = eni_phy_put, | ||
2207 | .phy_get = eni_phy_get, | ||
2208 | .change_qos = eni_change_qos, | ||
2209 | .proc_read = eni_proc_read | ||
2210 | }; | ||
2211 | |||
2212 | |||
2213 | static int __devinit eni_init_one(struct pci_dev *pci_dev, | ||
2214 | const struct pci_device_id *ent) | ||
2215 | { | ||
2216 | struct atm_dev *dev; | ||
2217 | struct eni_dev *eni_dev; | ||
2218 | int error = -ENOMEM; | ||
2219 | |||
2220 | DPRINTK("eni_init_one\n"); | ||
2221 | |||
2222 | if (pci_enable_device(pci_dev)) { | ||
2223 | error = -EIO; | ||
2224 | goto out0; | ||
2225 | } | ||
2226 | |||
2227 | eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL); | ||
2228 | if (!eni_dev) goto out0; | ||
2229 | if (!cpu_zeroes) { | ||
2230 | cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE, | ||
2231 | &zeroes); | ||
2232 | if (!cpu_zeroes) goto out1; | ||
2233 | } | ||
2234 | dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL); | ||
2235 | if (!dev) goto out2; | ||
2236 | pci_set_drvdata(pci_dev, dev); | ||
2237 | eni_dev->pci_dev = pci_dev; | ||
2238 | dev->dev_data = eni_dev; | ||
2239 | eni_dev->asic = ent->driver_data; | ||
2240 | error = eni_do_init(dev); | ||
2241 | if (error) goto out3; | ||
2242 | error = eni_start(dev); | ||
2243 | if (error) goto out3; | ||
2244 | eni_dev->more = eni_boards; | ||
2245 | eni_boards = dev; | ||
2246 | return 0; | ||
2247 | out3: | ||
2248 | atm_dev_deregister(dev); | ||
2249 | out2: | ||
2250 | pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes); | ||
2251 | cpu_zeroes = NULL; | ||
2252 | out1: | ||
2253 | kfree(eni_dev); | ||
2254 | out0: | ||
2255 | return error; | ||
2256 | } | ||
2257 | |||
2258 | |||
2259 | static struct pci_device_id eni_pci_tbl[] = { | ||
2260 | { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_FPGA, PCI_ANY_ID, PCI_ANY_ID, | ||
2261 | 0, 0, 0 /* FPGA */ }, | ||
2262 | { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID, | ||
2263 | 0, 0, 1 /* ASIC */ }, | ||
2264 | { 0, } | ||
2265 | }; | ||
2266 | MODULE_DEVICE_TABLE(pci,eni_pci_tbl); | ||
2267 | |||
2268 | |||
2269 | static void __devexit eni_remove_one(struct pci_dev *pci_dev) | ||
2270 | { | ||
2271 | /* grrr */ | ||
2272 | } | ||
2273 | |||
2274 | |||
2275 | static struct pci_driver eni_driver = { | ||
2276 | .name = DEV_LABEL, | ||
2277 | .id_table = eni_pci_tbl, | ||
2278 | .probe = eni_init_one, | ||
2279 | .remove = __devexit_p(eni_remove_one), | ||
2280 | }; | ||
2281 | |||
2282 | |||
2283 | static int __init eni_init(void) | ||
2284 | { | ||
2285 | struct sk_buff *skb; /* dummy for sizeof */ | ||
2286 | |||
2287 | if (sizeof(skb->cb) < sizeof(struct eni_skb_prv)) { | ||
2288 | printk(KERN_ERR "eni_detect: skb->cb is too small (%Zd < %Zd)\n", | ||
2289 | sizeof(skb->cb),sizeof(struct eni_skb_prv)); | ||
2290 | return -EIO; | ||
2291 | } | ||
2292 | return pci_register_driver(&eni_driver); | ||
2293 | } | ||
2294 | |||
2295 | |||
2296 | module_init(eni_init); | ||
2297 | /* @@@ since exit routine not defined, this module can not be unloaded */ | ||
2298 | |||
2299 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h new file mode 100644 index 000000000000..385090c2a580 --- /dev/null +++ b/drivers/atm/eni.h | |||
@@ -0,0 +1,130 @@ | |||
1 | /* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVER_ATM_ENI_H | ||
7 | #define DRIVER_ATM_ENI_H | ||
8 | |||
9 | #include <linux/atm.h> | ||
10 | #include <linux/atmdev.h> | ||
11 | #include <linux/sonet.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/time.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <asm/atomic.h> | ||
17 | |||
18 | #include "midway.h" | ||
19 | |||
20 | |||
21 | #define KERNEL_OFFSET 0xC0000000 /* kernel 0x0 is at phys 0xC0000000 */ | ||
22 | #define DEV_LABEL "eni" | ||
23 | |||
24 | #define UBR_BUFFER (128*1024) /* UBR buffer size */ | ||
25 | |||
26 | #define RX_DMA_BUF 8 /* burst and skip a few things */ | ||
27 | #define TX_DMA_BUF 100 /* should be enough for 64 kB */ | ||
28 | |||
29 | #define DEFAULT_RX_MULT 300 /* max_sdu*3 */ | ||
30 | #define DEFAULT_TX_MULT 300 /* max_sdu*3 */ | ||
31 | |||
32 | #define ENI_ZEROES_SIZE 4 /* need that many DMA-able zero bytes */ | ||
33 | |||
34 | |||
35 | struct eni_free { | ||
36 | void __iomem *start; /* counting in bytes */ | ||
37 | int order; | ||
38 | }; | ||
39 | |||
40 | struct eni_tx { | ||
41 | void __iomem *send; /* base, 0 if unused */ | ||
42 | int prescaler; /* shaping prescaler */ | ||
43 | int resolution; /* shaping divider */ | ||
44 | unsigned long tx_pos; /* current TX write position */ | ||
45 | unsigned long words; /* size of TX queue */ | ||
46 | int index; /* TX channel number */ | ||
47 | int reserved; /* reserved peak cell rate */ | ||
48 | int shaping; /* shaped peak cell rate */ | ||
49 | struct sk_buff_head backlog; /* queue of waiting TX buffers */ | ||
50 | }; | ||
51 | |||
52 | struct eni_vcc { | ||
53 | int (*rx)(struct atm_vcc *vcc); /* RX function, NULL if none */ | ||
54 | void __iomem *recv; /* receive buffer */ | ||
55 | unsigned long words; /* its size in words */ | ||
56 | unsigned long descr; /* next descriptor (RX) */ | ||
57 | unsigned long rx_pos; /* current RX descriptor pos */ | ||
58 | struct eni_tx *tx; /* TXer, NULL if none */ | ||
59 | int rxing; /* number of pending PDUs */ | ||
60 | int servicing; /* number of waiting VCs (0 or 1) */ | ||
61 | int txing; /* number of pending TX bytes */ | ||
62 | struct timeval timestamp; /* for RX timing */ | ||
63 | struct atm_vcc *next; /* next pending RX */ | ||
64 | struct sk_buff *last; /* last PDU being DMAed (used to carry | ||
65 | discard information) */ | ||
66 | }; | ||
67 | |||
68 | struct eni_dev { | ||
69 | /*-------------------------------- spinlock */ | ||
70 | spinlock_t lock; /* sync with interrupt */ | ||
71 | struct tasklet_struct task; /* tasklet for interrupt work */ | ||
72 | u32 events; /* pending events */ | ||
73 | /*-------------------------------- base pointers into Midway address | ||
74 | space */ | ||
75 | void __iomem *phy; /* PHY interface chip registers */ | ||
76 | void __iomem *reg; /* register base */ | ||
77 | void __iomem *ram; /* RAM base */ | ||
78 | void __iomem *vci; /* VCI table */ | ||
79 | void __iomem *rx_dma; /* RX DMA queue */ | ||
80 | void __iomem *tx_dma; /* TX DMA queue */ | ||
81 | void __iomem *service; /* service list */ | ||
82 | /*-------------------------------- TX part */ | ||
83 | struct eni_tx tx[NR_CHAN]; /* TX channels */ | ||
84 | struct eni_tx *ubr; /* UBR channel */ | ||
85 | struct sk_buff_head tx_queue; /* PDUs currently being TX DMAed*/ | ||
86 | wait_queue_head_t tx_wait; /* for close */ | ||
87 | int tx_bw; /* remaining bandwidth */ | ||
88 | u32 dma[TX_DMA_BUF*2]; /* DMA request scratch area */ | ||
89 | int tx_mult; /* buffer size multiplier (percent) */ | ||
90 | /*-------------------------------- RX part */ | ||
91 | u32 serv_read; /* host service read index */ | ||
92 | struct atm_vcc *fast,*last_fast;/* queues of VCCs with pending PDUs */ | ||
93 | struct atm_vcc *slow,*last_slow; | ||
94 | struct atm_vcc **rx_map; /* for fast lookups */ | ||
95 | struct sk_buff_head rx_queue; /* PDUs currently being RX-DMAed */ | ||
96 | wait_queue_head_t rx_wait; /* for close */ | ||
97 | int rx_mult; /* buffer size multiplier (percent) */ | ||
98 | /*-------------------------------- statistics */ | ||
99 | unsigned long lost; /* number of lost cells (RX) */ | ||
100 | /*-------------------------------- memory management */ | ||
101 | unsigned long base_diff; /* virtual-real base address */ | ||
102 | int free_len; /* free list length */ | ||
103 | struct eni_free *free_list; /* free list */ | ||
104 | int free_list_size; /* maximum size of free list */ | ||
105 | /*-------------------------------- ENI links */ | ||
106 | struct atm_dev *more; /* other ENI devices */ | ||
107 | /*-------------------------------- general information */ | ||
108 | int mem; /* RAM on board (in bytes) */ | ||
109 | int asic; /* PCI interface type, 0 for FPGA */ | ||
110 | unsigned int irq; /* IRQ */ | ||
111 | struct pci_dev *pci_dev; /* PCI stuff */ | ||
112 | }; | ||
113 | |||
114 | |||
115 | #define ENI_DEV(d) ((struct eni_dev *) (d)->dev_data) | ||
116 | #define ENI_VCC(d) ((struct eni_vcc *) (d)->dev_data) | ||
117 | |||
118 | |||
119 | struct eni_skb_prv { | ||
120 | struct atm_skb_data _; /* reserved */ | ||
121 | unsigned long pos; /* position of next descriptor */ | ||
122 | int size; /* PDU size in reassembly buffer */ | ||
123 | dma_addr_t paddr; /* DMA handle */ | ||
124 | }; | ||
125 | |||
126 | #define ENI_PRV_SIZE(skb) (((struct eni_skb_prv *) (skb)->cb)->size) | ||
127 | #define ENI_PRV_POS(skb) (((struct eni_skb_prv *) (skb)->cb)->pos) | ||
128 | #define ENI_PRV_PADDR(skb) (((struct eni_skb_prv *) (skb)->cb)->paddr) | ||
129 | |||
130 | #endif | ||
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c new file mode 100644 index 000000000000..101f0cc33d10 --- /dev/null +++ b/drivers/atm/firestream.c | |||
@@ -0,0 +1,2053 @@ | |||
1 | |||
2 | /* drivers/atm/firestream.c - FireStream 155 (MB86697) and | ||
3 | * FireStream 50 (MB86695) device driver | ||
4 | */ | ||
5 | |||
6 | /* Written & (C) 2000 by R.E.Wolff@BitWizard.nl | ||
7 | * Copied snippets from zatm.c by Werner Almesberger, EPFL LRC/ICA | ||
8 | * and ambassador.c Copyright (C) 1995-1999 Madge Networks Ltd | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | |||
26 | The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian | ||
27 | system and in the file COPYING in the Linux kernel source. | ||
28 | */ | ||
29 | |||
30 | |||
31 | #include <linux/module.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/mm.h> | ||
35 | #include <linux/pci.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/atm.h> | ||
38 | #include <linux/atmdev.h> | ||
39 | #include <linux/sonet.h> | ||
40 | #include <linux/skbuff.h> | ||
41 | #include <linux/netdevice.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/ioport.h> /* for request_region */ | ||
44 | #include <linux/uio.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/capability.h> | ||
47 | #include <linux/bitops.h> | ||
48 | #include <asm/byteorder.h> | ||
49 | #include <asm/system.h> | ||
50 | #include <asm/string.h> | ||
51 | #include <asm/io.h> | ||
52 | #include <asm/atomic.h> | ||
53 | #include <asm/uaccess.h> | ||
54 | #include <linux/wait.h> | ||
55 | |||
56 | #include "firestream.h" | ||
57 | |||
58 | static int loopback = 0; | ||
59 | static int num=0x5a; | ||
60 | |||
61 | /* According to measurements (but they look suspicious to me!) done in | ||
62 | * '97, 37% of the packets are one cell in size. So it pays to have | ||
63 | * buffers allocated at that size. A large jump in percentage of | ||
64 | * packets occurs at packets around 536 bytes in length. So it also | ||
65 | * pays to have those pre-allocated. Unfortunately, we can't fully | ||
66 | * take advantage of this as the majority of the packets is likely to | ||
67 | * be TCP/IP (As where obviously the measurement comes from) There the | ||
68 | * link would be opened with say a 1500 byte MTU, and we can't handle | ||
69 | * smaller buffers more efficiently than the larger ones. -- REW | ||
70 | */ | ||
71 | |||
72 | /* Due to the way Linux memory management works, specifying "576" as | ||
73 | * an allocation size here isn't going to help. They are allocated | ||
74 | * from 1024-byte regions anyway. With the size of the sk_buffs (quite | ||
75 | * large), it doesn't pay to allocate the smallest size (64) -- REW */ | ||
76 | |||
77 | /* This is all guesswork. Hard numbers to back this up or disprove this, | ||
78 | * are appreciated. -- REW */ | ||
79 | |||
80 | /* The last entry should be about 64k. However, the "buffer size" is | ||
81 | * passed to the chip in a 16 bit field. I don't know how "65536" | ||
82 | * would be interpreted. -- REW */ | ||
83 | |||
84 | #define NP FS_NR_FREE_POOLS | ||
85 | static int rx_buf_sizes[NP] = {128, 256, 512, 1024, 2048, 4096, 16384, 65520}; | ||
86 | /* log2: 7 8 9 10 11 12 14 16 */ | ||
87 | |||
88 | #if 0 | ||
89 | static int rx_pool_sizes[NP] = {1024, 1024, 512, 256, 128, 64, 32, 32}; | ||
90 | #else | ||
91 | /* debug */ | ||
92 | static int rx_pool_sizes[NP] = {128, 128, 128, 64, 64, 64, 32, 32}; | ||
93 | #endif | ||
94 | /* log2: 10 10 9 8 7 6 5 5 */ | ||
95 | /* sumlog2: 17 18 18 18 18 18 19 21 */ | ||
96 | /* mem allocated: 128k 256k 256k 256k 256k 256k 512k 2M */ | ||
97 | /* tot mem: almost 4M */ | ||
98 | |||
99 | /* NP is shorter, so that it fits on a single line. */ | ||
100 | #undef NP | ||
101 | |||
102 | |||
103 | /* Small hardware gotcha: | ||
104 | |||
105 | The FS50 CAM (VP/VC match registers) always take the lowest channel | ||
106 | number that matches. This is not a problem. | ||
107 | |||
108 | However, they also ignore whether the channel is enabled or | ||
109 | not. This means that if you allocate channel 0 to 1.2 and then | ||
110 | channel 1 to 0.0, then disabeling channel 0 and writing 0 to the | ||
111 | match channel for channel 0 will "steal" the traffic from channel | ||
112 | 1, even if you correctly disable channel 0. | ||
113 | |||
114 | Workaround: | ||
115 | |||
116 | - When disabling channels, write an invalid VP/VC value to the | ||
117 | match register. (We use 0xffffffff, which in the worst case | ||
118 | matches VP/VC = <maxVP>/<maxVC>, but I expect it not to match | ||
119 | anything as some "when not in use, program to 0" bits are now | ||
120 | programmed to 1...) | ||
121 | |||
122 | - Don't initialize the match registers to 0, as 0.0 is a valid | ||
123 | channel. | ||
124 | */ | ||
125 | |||
126 | |||
127 | /* Optimization hints and tips. | ||
128 | |||
129 | The FireStream chips are very capable of reducing the amount of | ||
130 | "interrupt-traffic" for the CPU. This driver requests an interrupt on EVERY | ||
131 | action. You could try to minimize this a bit. | ||
132 | |||
133 | Besides that, the userspace->kernel copy and the PCI bus are the | ||
134 | performance limiting issues for this driver. | ||
135 | |||
136 | You could queue up a bunch of outgoing packets without telling the | ||
137 | FireStream. I'm not sure that's going to win you much though. The | ||
138 | Linux layer won't tell us in advance when it's not going to give us | ||
139 | any more packets in a while. So this is tricky to implement right without | ||
140 | introducing extra delays. | ||
141 | |||
142 | -- REW | ||
143 | */ | ||
144 | |||
145 | |||
146 | |||
147 | |||
148 | /* The strings that define what the RX queue entry is all about. */ | ||
149 | /* Fujitsu: Please tell me which ones can have a pointer to a | ||
150 | freepool descriptor! */ | ||
151 | static char *res_strings[] = { | ||
152 | "RX OK: streaming not EOP", | ||
153 | "RX OK: streaming EOP", | ||
154 | "RX OK: Single buffer packet", | ||
155 | "RX OK: packet mode", | ||
156 | "RX OK: F4 OAM (end to end)", | ||
157 | "RX OK: F4 OAM (Segment)", | ||
158 | "RX OK: F5 OAM (end to end)", | ||
159 | "RX OK: F5 OAM (Segment)", | ||
160 | "RX OK: RM cell", | ||
161 | "RX OK: TRANSP cell", | ||
162 | "RX OK: TRANSPC cell", | ||
163 | "Unmatched cell", | ||
164 | "reserved 12", | ||
165 | "reserved 13", | ||
166 | "reserved 14", | ||
167 | "Unrecognized cell", | ||
168 | "reserved 16", | ||
169 | "reassemby abort: AAL5 abort", | ||
170 | "packet purged", | ||
171 | "packet ageing timeout", | ||
172 | "channel ageing timeout", | ||
173 | "calculated lenght error", | ||
174 | "programmed lenght limit error", | ||
175 | "aal5 crc32 error", | ||
176 | "oam transp or transpc crc10 error", | ||
177 | "reserved 25", | ||
178 | "reserved 26", | ||
179 | "reserved 27", | ||
180 | "reserved 28", | ||
181 | "reserved 29", | ||
182 | "reserved 30", | ||
183 | "reassembly abort: no buffers", | ||
184 | "receive buffer overflow", | ||
185 | "change in GFC", | ||
186 | "receive buffer full", | ||
187 | "low priority discard - no receive descriptor", | ||
188 | "low priority discard - missing end of packet", | ||
189 | "reserved 41", | ||
190 | "reserved 42", | ||
191 | "reserved 43", | ||
192 | "reserved 44", | ||
193 | "reserved 45", | ||
194 | "reserved 46", | ||
195 | "reserved 47", | ||
196 | "reserved 48", | ||
197 | "reserved 49", | ||
198 | "reserved 50", | ||
199 | "reserved 51", | ||
200 | "reserved 52", | ||
201 | "reserved 53", | ||
202 | "reserved 54", | ||
203 | "reserved 55", | ||
204 | "reserved 56", | ||
205 | "reserved 57", | ||
206 | "reserved 58", | ||
207 | "reserved 59", | ||
208 | "reserved 60", | ||
209 | "reserved 61", | ||
210 | "reserved 62", | ||
211 | "reserved 63", | ||
212 | }; | ||
213 | |||
214 | static char *irq_bitname[] = { | ||
215 | "LPCO", | ||
216 | "DPCO", | ||
217 | "RBRQ0_W", | ||
218 | "RBRQ1_W", | ||
219 | "RBRQ2_W", | ||
220 | "RBRQ3_W", | ||
221 | "RBRQ0_NF", | ||
222 | "RBRQ1_NF", | ||
223 | "RBRQ2_NF", | ||
224 | "RBRQ3_NF", | ||
225 | "BFP_SC", | ||
226 | "INIT", | ||
227 | "INIT_ERR", | ||
228 | "USCEO", | ||
229 | "UPEC0", | ||
230 | "VPFCO", | ||
231 | "CRCCO", | ||
232 | "HECO", | ||
233 | "TBRQ_W", | ||
234 | "TBRQ_NF", | ||
235 | "CTPQ_E", | ||
236 | "GFC_C0", | ||
237 | "PCI_FTL", | ||
238 | "CSQ_W", | ||
239 | "CSQ_NF", | ||
240 | "EXT_INT", | ||
241 | "RXDMA_S" | ||
242 | }; | ||
243 | |||
244 | |||
245 | #define PHY_EOF -1 | ||
246 | #define PHY_CLEARALL -2 | ||
247 | |||
248 | struct reginit_item { | ||
249 | int reg, val; | ||
250 | }; | ||
251 | |||
252 | |||
253 | static struct reginit_item PHY_NTC_INIT[] __devinitdata = { | ||
254 | { PHY_CLEARALL, 0x40 }, | ||
255 | { 0x12, 0x0001 }, | ||
256 | { 0x13, 0x7605 }, | ||
257 | { 0x1A, 0x0001 }, | ||
258 | { 0x1B, 0x0005 }, | ||
259 | { 0x38, 0x0003 }, | ||
260 | { 0x39, 0x0006 }, /* changed here to make loopback */ | ||
261 | { 0x01, 0x5262 }, | ||
262 | { 0x15, 0x0213 }, | ||
263 | { 0x00, 0x0003 }, | ||
264 | { PHY_EOF, 0}, /* -1 signals end of list */ | ||
265 | }; | ||
266 | |||
267 | |||
268 | /* Safetyfeature: If the card interrupts more than this number of times | ||
269 | in a jiffy (1/100th of a second) then we just disable the interrupt and | ||
270 | print a message. This prevents the system from hanging. | ||
271 | |||
272 | 150000 packets per second is close to the limit a PC is going to have | ||
273 | anyway. We therefore have to disable this for production. -- REW */ | ||
274 | #undef IRQ_RATE_LIMIT // 100 | ||
275 | |||
276 | /* Interrupts work now. Unlike serial cards, ATM cards don't work all | ||
277 | that great without interrupts. -- REW */ | ||
278 | #undef FS_POLL_FREQ // 100 | ||
279 | |||
280 | /* | ||
281 | This driver can spew a whole lot of debugging output at you. If you | ||
282 | need maximum performance, you should disable the DEBUG define. To | ||
283 | aid in debugging in the field, I'm leaving the compile-time debug | ||
284 | features enabled, and disable them "runtime". That allows me to | ||
285 | instruct people with problems to enable debugging without requiring | ||
286 | them to recompile... -- REW | ||
287 | */ | ||
288 | #define DEBUG | ||
289 | |||
290 | #ifdef DEBUG | ||
291 | #define fs_dprintk(f, str...) if (fs_debug & f) printk (str) | ||
292 | #else | ||
293 | #define fs_dprintk(f, str...) /* nothing */ | ||
294 | #endif | ||
295 | |||
296 | |||
297 | static int fs_keystream = 0; | ||
298 | |||
299 | #ifdef DEBUG | ||
300 | /* I didn't forget to set this to zero before shipping. Hit me with a stick | ||
301 | if you get this with the debug default not set to zero again. -- REW */ | ||
302 | static int fs_debug = 0; | ||
303 | #else | ||
304 | #define fs_debug 0 | ||
305 | #endif | ||
306 | |||
307 | #ifdef MODULE | ||
308 | #ifdef DEBUG | ||
309 | module_param(fs_debug, int, 0644); | ||
310 | #endif | ||
311 | module_param(loopback, int, 0); | ||
312 | module_param(num, int, 0); | ||
313 | module_param(fs_keystream, int, 0); | ||
314 | /* XXX Add rx_buf_sizes, and rx_pool_sizes As per request Amar. -- REW */ | ||
315 | #endif | ||
316 | |||
317 | |||
318 | #define FS_DEBUG_FLOW 0x00000001 | ||
319 | #define FS_DEBUG_OPEN 0x00000002 | ||
320 | #define FS_DEBUG_QUEUE 0x00000004 | ||
321 | #define FS_DEBUG_IRQ 0x00000008 | ||
322 | #define FS_DEBUG_INIT 0x00000010 | ||
323 | #define FS_DEBUG_SEND 0x00000020 | ||
324 | #define FS_DEBUG_PHY 0x00000040 | ||
325 | #define FS_DEBUG_CLEANUP 0x00000080 | ||
326 | #define FS_DEBUG_QOS 0x00000100 | ||
327 | #define FS_DEBUG_TXQ 0x00000200 | ||
328 | #define FS_DEBUG_ALLOC 0x00000400 | ||
329 | #define FS_DEBUG_TXMEM 0x00000800 | ||
330 | #define FS_DEBUG_QSIZE 0x00001000 | ||
331 | |||
332 | |||
333 | #define func_enter() fs_dprintk (FS_DEBUG_FLOW, "fs: enter %s\n", __FUNCTION__) | ||
334 | #define func_exit() fs_dprintk (FS_DEBUG_FLOW, "fs: exit %s\n", __FUNCTION__) | ||
335 | |||
336 | |||
337 | static struct fs_dev *fs_boards = NULL; | ||
338 | |||
339 | #ifdef DEBUG | ||
340 | |||
341 | static void my_hd (void *addr, int len) | ||
342 | { | ||
343 | int j, ch; | ||
344 | unsigned char *ptr = addr; | ||
345 | |||
346 | while (len > 0) { | ||
347 | printk ("%p ", ptr); | ||
348 | for (j=0;j < ((len < 16)?len:16);j++) { | ||
349 | printk ("%02x %s", ptr[j], (j==7)?" ":""); | ||
350 | } | ||
351 | for ( ;j < 16;j++) { | ||
352 | printk (" %s", (j==7)?" ":""); | ||
353 | } | ||
354 | for (j=0;j < ((len < 16)?len:16);j++) { | ||
355 | ch = ptr[j]; | ||
356 | printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); | ||
357 | } | ||
358 | printk ("\n"); | ||
359 | ptr += 16; | ||
360 | len -= 16; | ||
361 | } | ||
362 | } | ||
363 | #else /* DEBUG */ | ||
364 | static void my_hd (void *addr, int len){} | ||
365 | #endif /* DEBUG */ | ||
366 | |||
367 | /********** free an skb (as per ATM device driver documentation) **********/ | ||
368 | |||
369 | /* Hmm. If this is ATM specific, why isn't there an ATM routine for this? | ||
370 | * I copied it over from the ambassador driver. -- REW */ | ||
371 | |||
372 | static inline void fs_kfree_skb (struct sk_buff * skb) | ||
373 | { | ||
374 | if (ATM_SKB(skb)->vcc->pop) | ||
375 | ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb); | ||
376 | else | ||
377 | dev_kfree_skb_any (skb); | ||
378 | } | ||
379 | |||
380 | |||
381 | |||
382 | |||
383 | /* It seems the ATM forum recommends this horribly complicated 16bit | ||
384 | * floating point format. Turns out the Ambassador uses the exact same | ||
385 | * encoding. I just copied it over. If Mitch agrees, I'll move it over | ||
386 | * to the atm_misc file or something like that. (and remove it from | ||
387 | * here and the ambassador driver) -- REW | ||
388 | */ | ||
389 | |||
390 | /* The good thing about this format is that it is monotonic. So, | ||
391 | a conversion routine need not be very complicated. To be able to | ||
392 | round "nearest" we need to take along a few extra bits. Lets | ||
393 | put these after 16 bits, so that we can just return the top 16 | ||
394 | bits of the 32bit number as the result: | ||
395 | |||
396 | int mr (unsigned int rate, int r) | ||
397 | { | ||
398 | int e = 16+9; | ||
399 | static int round[4]={0, 0, 0xffff, 0x8000}; | ||
400 | if (!rate) return 0; | ||
401 | while (rate & 0xfc000000) { | ||
402 | rate >>= 1; | ||
403 | e++; | ||
404 | } | ||
405 | while (! (rate & 0xfe000000)) { | ||
406 | rate <<= 1; | ||
407 | e--; | ||
408 | } | ||
409 | |||
410 | // Now the mantissa is in positions bit 16-25. Excepf for the "hidden 1" that's in bit 26. | ||
411 | rate &= ~0x02000000; | ||
412 | // Next add in the exponent | ||
413 | rate |= e << (16+9); | ||
414 | // And perform the rounding: | ||
415 | return (rate + round[r]) >> 16; | ||
416 | } | ||
417 | |||
418 | 14 lines-of-code. Compare that with the 120 that the Ambassador | ||
419 | guys needed. (would be 8 lines shorter if I'd try to really reduce | ||
420 | the number of lines: | ||
421 | |||
422 | int mr (unsigned int rate, int r) | ||
423 | { | ||
424 | int e = 16+9; | ||
425 | static int round[4]={0, 0, 0xffff, 0x8000}; | ||
426 | if (!rate) return 0; | ||
427 | for (; rate & 0xfc000000 ;rate >>= 1, e++); | ||
428 | for (;!(rate & 0xfe000000);rate <<= 1, e--); | ||
429 | return ((rate & ~0x02000000) | (e << (16+9)) + round[r]) >> 16; | ||
430 | } | ||
431 | |||
432 | Exercise for the reader: Remove one more line-of-code, without | ||
433 | cheating. (Just joining two lines is cheating). (I know it's | ||
434 | possible, don't think you've beat me if you found it... If you | ||
435 | manage to lose two lines or more, keep me updated! ;-) | ||
436 | |||
437 | -- REW */ | ||
438 | |||
439 | |||
440 | #define ROUND_UP 1 | ||
441 | #define ROUND_DOWN 2 | ||
442 | #define ROUND_NEAREST 3 | ||
443 | /********** make rate (not quite as much fun as Horizon) **********/ | ||
444 | |||
445 | static unsigned int make_rate (unsigned int rate, int r, | ||
446 | u16 * bits, unsigned int * actual) | ||
447 | { | ||
448 | unsigned char exp = -1; /* hush gcc */ | ||
449 | unsigned int man = -1; /* hush gcc */ | ||
450 | |||
451 | fs_dprintk (FS_DEBUG_QOS, "make_rate %u", rate); | ||
452 | |||
453 | /* rates in cells per second, ITU format (nasty 16-bit floating-point) | ||
454 | given 5-bit e and 9-bit m: | ||
455 | rate = EITHER (1+m/2^9)*2^e OR 0 | ||
456 | bits = EITHER 1<<14 | e<<9 | m OR 0 | ||
457 | (bit 15 is "reserved", bit 14 "non-zero") | ||
458 | smallest rate is 0 (special representation) | ||
459 | largest rate is (1+511/512)*2^31 = 4290772992 (< 2^32-1) | ||
460 | smallest non-zero rate is (1+0/512)*2^0 = 1 (> 0) | ||
461 | simple algorithm: | ||
462 | find position of top bit, this gives e | ||
463 | remove top bit and shift (rounding if feeling clever) by 9-e | ||
464 | */ | ||
465 | /* Ambassador ucode bug: please don't set bit 14! so 0 rate not | ||
466 | representable. // This should move into the ambassador driver | ||
467 | when properly merged. -- REW */ | ||
468 | |||
469 | if (rate > 0xffc00000U) { | ||
470 | /* larger than largest representable rate */ | ||
471 | |||
472 | if (r == ROUND_UP) { | ||
473 | return -EINVAL; | ||
474 | } else { | ||
475 | exp = 31; | ||
476 | man = 511; | ||
477 | } | ||
478 | |||
479 | } else if (rate) { | ||
480 | /* representable rate */ | ||
481 | |||
482 | exp = 31; | ||
483 | man = rate; | ||
484 | |||
485 | /* invariant: rate = man*2^(exp-31) */ | ||
486 | while (!(man & (1<<31))) { | ||
487 | exp = exp - 1; | ||
488 | man = man<<1; | ||
489 | } | ||
490 | |||
491 | /* man has top bit set | ||
492 | rate = (2^31+(man-2^31))*2^(exp-31) | ||
493 | rate = (1+(man-2^31)/2^31)*2^exp | ||
494 | */ | ||
495 | man = man<<1; | ||
496 | man &= 0xffffffffU; /* a nop on 32-bit systems */ | ||
497 | /* rate = (1+man/2^32)*2^exp | ||
498 | |||
499 | exp is in the range 0 to 31, man is in the range 0 to 2^32-1 | ||
500 | time to lose significance... we want m in the range 0 to 2^9-1 | ||
501 | rounding presents a minor problem... we first decide which way | ||
502 | we are rounding (based on given rounding direction and possibly | ||
503 | the bits of the mantissa that are to be discarded). | ||
504 | */ | ||
505 | |||
506 | switch (r) { | ||
507 | case ROUND_DOWN: { | ||
508 | /* just truncate */ | ||
509 | man = man>>(32-9); | ||
510 | break; | ||
511 | } | ||
512 | case ROUND_UP: { | ||
513 | /* check all bits that we are discarding */ | ||
514 | if (man & (-1>>9)) { | ||
515 | man = (man>>(32-9)) + 1; | ||
516 | if (man == (1<<9)) { | ||
517 | /* no need to check for round up outside of range */ | ||
518 | man = 0; | ||
519 | exp += 1; | ||
520 | } | ||
521 | } else { | ||
522 | man = (man>>(32-9)); | ||
523 | } | ||
524 | break; | ||
525 | } | ||
526 | case ROUND_NEAREST: { | ||
527 | /* check msb that we are discarding */ | ||
528 | if (man & (1<<(32-9-1))) { | ||
529 | man = (man>>(32-9)) + 1; | ||
530 | if (man == (1<<9)) { | ||
531 | /* no need to check for round up outside of range */ | ||
532 | man = 0; | ||
533 | exp += 1; | ||
534 | } | ||
535 | } else { | ||
536 | man = (man>>(32-9)); | ||
537 | } | ||
538 | break; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | } else { | ||
543 | /* zero rate - not representable */ | ||
544 | |||
545 | if (r == ROUND_DOWN) { | ||
546 | return -EINVAL; | ||
547 | } else { | ||
548 | exp = 0; | ||
549 | man = 0; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | fs_dprintk (FS_DEBUG_QOS, "rate: man=%u, exp=%hu", man, exp); | ||
554 | |||
555 | if (bits) | ||
556 | *bits = /* (1<<14) | */ (exp<<9) | man; | ||
557 | |||
558 | if (actual) | ||
559 | *actual = (exp >= 9) | ||
560 | ? (1 << exp) + (man << (exp-9)) | ||
561 | : (1 << exp) + ((man + (1<<(9-exp-1))) >> (9-exp)); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | |||
567 | |||
568 | |||
569 | /* FireStream access routines */ | ||
570 | /* For DEEP-DOWN debugging these can be rigged to intercept accesses to | ||
571 | certain registers or to just log all accesses. */ | ||
572 | |||
573 | static inline void write_fs (struct fs_dev *dev, int offset, u32 val) | ||
574 | { | ||
575 | writel (val, dev->base + offset); | ||
576 | } | ||
577 | |||
578 | |||
579 | static inline u32 read_fs (struct fs_dev *dev, int offset) | ||
580 | { | ||
581 | return readl (dev->base + offset); | ||
582 | } | ||
583 | |||
584 | |||
585 | |||
586 | static inline struct FS_QENTRY *get_qentry (struct fs_dev *dev, struct queue *q) | ||
587 | { | ||
588 | return bus_to_virt (read_fs (dev, Q_WP(q->offset)) & Q_ADDR_MASK); | ||
589 | } | ||
590 | |||
591 | |||
592 | static void submit_qentry (struct fs_dev *dev, struct queue *q, struct FS_QENTRY *qe) | ||
593 | { | ||
594 | u32 wp; | ||
595 | struct FS_QENTRY *cqe; | ||
596 | |||
597 | /* XXX Sanity check: the write pointer can be checked to be | ||
598 | still the same as the value passed as qe... -- REW */ | ||
599 | /* udelay (5); */ | ||
600 | while ((wp = read_fs (dev, Q_WP (q->offset))) & Q_FULL) { | ||
601 | fs_dprintk (FS_DEBUG_TXQ, "Found queue at %x full. Waiting.\n", | ||
602 | q->offset); | ||
603 | schedule (); | ||
604 | } | ||
605 | |||
606 | wp &= ~0xf; | ||
607 | cqe = bus_to_virt (wp); | ||
608 | if (qe != cqe) { | ||
609 | fs_dprintk (FS_DEBUG_TXQ, "q mismatch! %p %p\n", qe, cqe); | ||
610 | } | ||
611 | |||
612 | write_fs (dev, Q_WP(q->offset), Q_INCWRAP); | ||
613 | |||
614 | { | ||
615 | static int c; | ||
616 | if (!(c++ % 100)) | ||
617 | { | ||
618 | int rp, wp; | ||
619 | rp = read_fs (dev, Q_RP(q->offset)); | ||
620 | wp = read_fs (dev, Q_WP(q->offset)); | ||
621 | fs_dprintk (FS_DEBUG_TXQ, "q at %d: %x-%x: %x entries.\n", | ||
622 | q->offset, rp, wp, wp-rp); | ||
623 | } | ||
624 | } | ||
625 | } | ||
626 | |||
627 | #ifdef DEBUG_EXTRA | ||
628 | static struct FS_QENTRY pq[60]; | ||
629 | static int qp; | ||
630 | |||
631 | static struct FS_BPENTRY dq[60]; | ||
632 | static int qd; | ||
633 | static void *da[60]; | ||
634 | #endif | ||
635 | |||
636 | static void submit_queue (struct fs_dev *dev, struct queue *q, | ||
637 | u32 cmd, u32 p1, u32 p2, u32 p3) | ||
638 | { | ||
639 | struct FS_QENTRY *qe; | ||
640 | |||
641 | qe = get_qentry (dev, q); | ||
642 | qe->cmd = cmd; | ||
643 | qe->p0 = p1; | ||
644 | qe->p1 = p2; | ||
645 | qe->p2 = p3; | ||
646 | submit_qentry (dev, q, qe); | ||
647 | |||
648 | #ifdef DEBUG_EXTRA | ||
649 | pq[qp].cmd = cmd; | ||
650 | pq[qp].p0 = p1; | ||
651 | pq[qp].p1 = p2; | ||
652 | pq[qp].p2 = p3; | ||
653 | qp++; | ||
654 | if (qp >= 60) qp = 0; | ||
655 | #endif | ||
656 | } | ||
657 | |||
658 | /* Test the "other" way one day... -- REW */ | ||
659 | #if 1 | ||
660 | #define submit_command submit_queue | ||
661 | #else | ||
662 | |||
663 | static void submit_command (struct fs_dev *dev, struct queue *q, | ||
664 | u32 cmd, u32 p1, u32 p2, u32 p3) | ||
665 | { | ||
666 | write_fs (dev, CMDR0, cmd); | ||
667 | write_fs (dev, CMDR1, p1); | ||
668 | write_fs (dev, CMDR2, p2); | ||
669 | write_fs (dev, CMDR3, p3); | ||
670 | } | ||
671 | #endif | ||
672 | |||
673 | |||
674 | |||
675 | static void process_return_queue (struct fs_dev *dev, struct queue *q) | ||
676 | { | ||
677 | long rq; | ||
678 | struct FS_QENTRY *qe; | ||
679 | void *tc; | ||
680 | |||
681 | while (!((rq = read_fs (dev, Q_RP(q->offset))) & Q_EMPTY)) { | ||
682 | fs_dprintk (FS_DEBUG_QUEUE, "reaping return queue entry at %lx\n", rq); | ||
683 | qe = bus_to_virt (rq); | ||
684 | |||
685 | fs_dprintk (FS_DEBUG_QUEUE, "queue entry: %08x %08x %08x %08x. (%d)\n", | ||
686 | qe->cmd, qe->p0, qe->p1, qe->p2, STATUS_CODE (qe)); | ||
687 | |||
688 | switch (STATUS_CODE (qe)) { | ||
689 | case 5: | ||
690 | tc = bus_to_virt (qe->p0); | ||
691 | fs_dprintk (FS_DEBUG_ALLOC, "Free tc: %p\n", tc); | ||
692 | kfree (tc); | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | write_fs (dev, Q_RP(q->offset), Q_INCWRAP); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | |||
701 | static void process_txdone_queue (struct fs_dev *dev, struct queue *q) | ||
702 | { | ||
703 | long rq; | ||
704 | long tmp; | ||
705 | struct FS_QENTRY *qe; | ||
706 | struct sk_buff *skb; | ||
707 | struct FS_BPENTRY *td; | ||
708 | |||
709 | while (!((rq = read_fs (dev, Q_RP(q->offset))) & Q_EMPTY)) { | ||
710 | fs_dprintk (FS_DEBUG_QUEUE, "reaping txdone entry at %lx\n", rq); | ||
711 | qe = bus_to_virt (rq); | ||
712 | |||
713 | fs_dprintk (FS_DEBUG_QUEUE, "queue entry: %08x %08x %08x %08x: %d\n", | ||
714 | qe->cmd, qe->p0, qe->p1, qe->p2, STATUS_CODE (qe)); | ||
715 | |||
716 | if (STATUS_CODE (qe) != 2) | ||
717 | fs_dprintk (FS_DEBUG_TXMEM, "queue entry: %08x %08x %08x %08x: %d\n", | ||
718 | qe->cmd, qe->p0, qe->p1, qe->p2, STATUS_CODE (qe)); | ||
719 | |||
720 | |||
721 | switch (STATUS_CODE (qe)) { | ||
722 | case 0x01: /* This is for AAL0 where we put the chip in streaming mode */ | ||
723 | /* Fall through */ | ||
724 | case 0x02: | ||
725 | /* Process a real txdone entry. */ | ||
726 | tmp = qe->p0; | ||
727 | if (tmp & 0x0f) | ||
728 | printk (KERN_WARNING "td not aligned: %ld\n", tmp); | ||
729 | tmp &= ~0x0f; | ||
730 | td = bus_to_virt (tmp); | ||
731 | |||
732 | fs_dprintk (FS_DEBUG_QUEUE, "Pool entry: %08x %08x %08x %08x %p.\n", | ||
733 | td->flags, td->next, td->bsa, td->aal_bufsize, td->skb ); | ||
734 | |||
735 | skb = td->skb; | ||
736 | if (skb == FS_VCC (ATM_SKB(skb)->vcc)->last_skb) { | ||
737 | wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait); | ||
738 | FS_VCC (ATM_SKB(skb)->vcc)->last_skb = NULL; | ||
739 | } | ||
740 | td->dev->ntxpckts--; | ||
741 | |||
742 | { | ||
743 | static int c=0; | ||
744 | |||
745 | if (!(c++ % 100)) { | ||
746 | fs_dprintk (FS_DEBUG_QSIZE, "[%d]", td->dev->ntxpckts); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); | ||
751 | |||
752 | fs_dprintk (FS_DEBUG_TXMEM, "i"); | ||
753 | fs_dprintk (FS_DEBUG_ALLOC, "Free t-skb: %p\n", skb); | ||
754 | fs_kfree_skb (skb); | ||
755 | |||
756 | fs_dprintk (FS_DEBUG_ALLOC, "Free trans-d: %p\n", td); | ||
757 | memset (td, 0x12, sizeof (struct FS_BPENTRY)); | ||
758 | kfree (td); | ||
759 | break; | ||
760 | default: | ||
761 | /* Here we get the tx purge inhibit command ... */ | ||
762 | /* Action, I believe, is "don't do anything". -- REW */ | ||
763 | ; | ||
764 | } | ||
765 | |||
766 | write_fs (dev, Q_RP(q->offset), Q_INCWRAP); | ||
767 | } | ||
768 | } | ||
769 | |||
770 | |||
771 | static void process_incoming (struct fs_dev *dev, struct queue *q) | ||
772 | { | ||
773 | long rq; | ||
774 | struct FS_QENTRY *qe; | ||
775 | struct FS_BPENTRY *pe; | ||
776 | struct sk_buff *skb; | ||
777 | unsigned int channo; | ||
778 | struct atm_vcc *atm_vcc; | ||
779 | |||
780 | while (!((rq = read_fs (dev, Q_RP(q->offset))) & Q_EMPTY)) { | ||
781 | fs_dprintk (FS_DEBUG_QUEUE, "reaping incoming queue entry at %lx\n", rq); | ||
782 | qe = bus_to_virt (rq); | ||
783 | |||
784 | fs_dprintk (FS_DEBUG_QUEUE, "queue entry: %08x %08x %08x %08x. ", | ||
785 | qe->cmd, qe->p0, qe->p1, qe->p2); | ||
786 | |||
787 | fs_dprintk (FS_DEBUG_QUEUE, "-> %x: %s\n", | ||
788 | STATUS_CODE (qe), | ||
789 | res_strings[STATUS_CODE(qe)]); | ||
790 | |||
791 | pe = bus_to_virt (qe->p0); | ||
792 | fs_dprintk (FS_DEBUG_QUEUE, "Pool entry: %08x %08x %08x %08x %p %p.\n", | ||
793 | pe->flags, pe->next, pe->bsa, pe->aal_bufsize, | ||
794 | pe->skb, pe->fp); | ||
795 | |||
796 | channo = qe->cmd & 0xffff; | ||
797 | |||
798 | if (channo < dev->nchannels) | ||
799 | atm_vcc = dev->atm_vccs[channo]; | ||
800 | else | ||
801 | atm_vcc = NULL; | ||
802 | |||
803 | /* Single buffer packet */ | ||
804 | switch (STATUS_CODE (qe)) { | ||
805 | case 0x1: | ||
806 | /* Fall through for streaming mode */ | ||
807 | case 0x2:/* Packet received OK.... */ | ||
808 | if (atm_vcc) { | ||
809 | skb = pe->skb; | ||
810 | pe->fp->n--; | ||
811 | #if 0 | ||
812 | fs_dprintk (FS_DEBUG_QUEUE, "Got skb: %p\n", skb); | ||
813 | if (FS_DEBUG_QUEUE & fs_debug) my_hd (bus_to_virt (pe->bsa), 0x20); | ||
814 | #endif | ||
815 | skb_put (skb, qe->p1 & 0xffff); | ||
816 | ATM_SKB(skb)->vcc = atm_vcc; | ||
817 | atomic_inc(&atm_vcc->stats->rx); | ||
818 | do_gettimeofday(&skb->stamp); | ||
819 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb); | ||
820 | atm_vcc->push (atm_vcc, skb); | ||
821 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", pe); | ||
822 | kfree (pe); | ||
823 | } else { | ||
824 | printk (KERN_ERR "Got a receive on a non-open channel %d.\n", channo); | ||
825 | } | ||
826 | break; | ||
827 | case 0x17:/* AAL 5 CRC32 error. IFF the length field is nonzero, a buffer | ||
828 | has been consumed and needs to be processed. -- REW */ | ||
829 | if (qe->p1 & 0xffff) { | ||
830 | pe = bus_to_virt (qe->p0); | ||
831 | pe->fp->n--; | ||
832 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", pe->skb); | ||
833 | dev_kfree_skb_any (pe->skb); | ||
834 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", pe); | ||
835 | kfree (pe); | ||
836 | } | ||
837 | if (atm_vcc) | ||
838 | atomic_inc(&atm_vcc->stats->rx_drop); | ||
839 | break; | ||
840 | case 0x1f: /* Reassembly abort: no buffers. */ | ||
841 | /* Silently increment error counter. */ | ||
842 | if (atm_vcc) | ||
843 | atomic_inc(&atm_vcc->stats->rx_drop); | ||
844 | break; | ||
845 | default: /* Hmm. Haven't written the code to handle the others yet... -- REW */ | ||
846 | printk (KERN_WARNING "Don't know what to do with RX status %x: %s.\n", | ||
847 | STATUS_CODE(qe), res_strings[STATUS_CODE (qe)]); | ||
848 | } | ||
849 | write_fs (dev, Q_RP(q->offset), Q_INCWRAP); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | |||
854 | |||
855 | #define DO_DIRECTION(tp) ((tp)->traffic_class != ATM_NONE) | ||
856 | |||
857 | static int fs_open(struct atm_vcc *atm_vcc) | ||
858 | { | ||
859 | struct fs_dev *dev; | ||
860 | struct fs_vcc *vcc; | ||
861 | struct fs_transmit_config *tc; | ||
862 | struct atm_trafprm * txtp; | ||
863 | struct atm_trafprm * rxtp; | ||
864 | /* struct fs_receive_config *rc;*/ | ||
865 | /* struct FS_QENTRY *qe; */ | ||
866 | int error; | ||
867 | int bfp; | ||
868 | int to; | ||
869 | unsigned short tmc0; | ||
870 | short vpi = atm_vcc->vpi; | ||
871 | int vci = atm_vcc->vci; | ||
872 | |||
873 | func_enter (); | ||
874 | |||
875 | dev = FS_DEV(atm_vcc->dev); | ||
876 | fs_dprintk (FS_DEBUG_OPEN, "fs: open on dev: %p, vcc at %p\n", | ||
877 | dev, atm_vcc); | ||
878 | |||
879 | if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) | ||
880 | set_bit(ATM_VF_ADDR, &atm_vcc->flags); | ||
881 | |||
882 | if ((atm_vcc->qos.aal != ATM_AAL5) && | ||
883 | (atm_vcc->qos.aal != ATM_AAL2)) | ||
884 | return -EINVAL; /* XXX AAL0 */ | ||
885 | |||
886 | fs_dprintk (FS_DEBUG_OPEN, "fs: (itf %d): open %d.%d\n", | ||
887 | atm_vcc->dev->number, atm_vcc->vpi, atm_vcc->vci); | ||
888 | |||
889 | /* XXX handle qos parameters (rate limiting) ? */ | ||
890 | |||
891 | vcc = kmalloc(sizeof(struct fs_vcc), GFP_KERNEL); | ||
892 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc VCC: %p(%Zd)\n", vcc, sizeof(struct fs_vcc)); | ||
893 | if (!vcc) { | ||
894 | clear_bit(ATM_VF_ADDR, &atm_vcc->flags); | ||
895 | return -ENOMEM; | ||
896 | } | ||
897 | |||
898 | atm_vcc->dev_data = vcc; | ||
899 | vcc->last_skb = NULL; | ||
900 | |||
901 | init_waitqueue_head (&vcc->close_wait); | ||
902 | |||
903 | txtp = &atm_vcc->qos.txtp; | ||
904 | rxtp = &atm_vcc->qos.rxtp; | ||
905 | |||
906 | if (!test_bit(ATM_VF_PARTIAL, &atm_vcc->flags)) { | ||
907 | if (IS_FS50(dev)) { | ||
908 | /* Increment the channel numer: take a free one next time. */ | ||
909 | for (to=33;to;to--, dev->channo++) { | ||
910 | /* We only have 32 channels */ | ||
911 | if (dev->channo >= 32) | ||
912 | dev->channo = 0; | ||
913 | /* If we need to do RX, AND the RX is inuse, try the next */ | ||
914 | if (DO_DIRECTION(rxtp) && dev->atm_vccs[dev->channo]) | ||
915 | continue; | ||
916 | /* If we need to do TX, AND the TX is inuse, try the next */ | ||
917 | if (DO_DIRECTION(txtp) && test_bit (dev->channo, dev->tx_inuse)) | ||
918 | continue; | ||
919 | /* Ok, both are free! (or not needed) */ | ||
920 | break; | ||
921 | } | ||
922 | if (!to) { | ||
923 | printk ("No more free channels for FS50..\n"); | ||
924 | return -EBUSY; | ||
925 | } | ||
926 | vcc->channo = dev->channo; | ||
927 | dev->channo &= dev->channel_mask; | ||
928 | |||
929 | } else { | ||
930 | vcc->channo = (vpi << FS155_VCI_BITS) | (vci); | ||
931 | if (((DO_DIRECTION(rxtp) && dev->atm_vccs[vcc->channo])) || | ||
932 | ( DO_DIRECTION(txtp) && test_bit (vcc->channo, dev->tx_inuse))) { | ||
933 | printk ("Channel is in use for FS155.\n"); | ||
934 | return -EBUSY; | ||
935 | } | ||
936 | } | ||
937 | fs_dprintk (FS_DEBUG_OPEN, "OK. Allocated channel %x(%d).\n", | ||
938 | vcc->channo, vcc->channo); | ||
939 | } | ||
940 | |||
941 | if (DO_DIRECTION (txtp)) { | ||
942 | tc = kmalloc (sizeof (struct fs_transmit_config), GFP_KERNEL); | ||
943 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc tc: %p(%Zd)\n", | ||
944 | tc, sizeof (struct fs_transmit_config)); | ||
945 | if (!tc) { | ||
946 | fs_dprintk (FS_DEBUG_OPEN, "fs: can't alloc transmit_config.\n"); | ||
947 | return -ENOMEM; | ||
948 | } | ||
949 | |||
950 | /* Allocate the "open" entry from the high priority txq. This makes | ||
951 | it most likely that the chip will notice it. It also prevents us | ||
952 | from having to wait for completion. On the other hand, we may | ||
953 | need to wait for completion anyway, to see if it completed | ||
954 | succesfully. */ | ||
955 | |||
956 | switch (atm_vcc->qos.aal) { | ||
957 | case ATM_AAL2: | ||
958 | case ATM_AAL0: | ||
959 | tc->flags = 0 | ||
960 | | TC_FLAGS_TRANSPARENT_PAYLOAD | ||
961 | | TC_FLAGS_PACKET | ||
962 | | (1 << 28) | ||
963 | | TC_FLAGS_TYPE_UBR /* XXX Change to VBR -- PVDL */ | ||
964 | | TC_FLAGS_CAL0; | ||
965 | break; | ||
966 | case ATM_AAL5: | ||
967 | tc->flags = 0 | ||
968 | | TC_FLAGS_AAL5 | ||
969 | | TC_FLAGS_PACKET /* ??? */ | ||
970 | | TC_FLAGS_TYPE_CBR | ||
971 | | TC_FLAGS_CAL0; | ||
972 | break; | ||
973 | default: | ||
974 | printk ("Unknown aal: %d\n", atm_vcc->qos.aal); | ||
975 | tc->flags = 0; | ||
976 | } | ||
977 | /* Docs are vague about this atm_hdr field. By the way, the FS | ||
978 | * chip makes odd errors if lower bits are set.... -- REW */ | ||
979 | tc->atm_hdr = (vpi << 20) | (vci << 4); | ||
980 | { | ||
981 | int pcr = atm_pcr_goal (txtp); | ||
982 | |||
983 | fs_dprintk (FS_DEBUG_OPEN, "pcr = %d.\n", pcr); | ||
984 | |||
985 | /* XXX Hmm. officially we're only allowed to do this if rounding | ||
986 | is round_down -- REW */ | ||
987 | if (IS_FS50(dev)) { | ||
988 | if (pcr > 51840000/53/8) pcr = 51840000/53/8; | ||
989 | } else { | ||
990 | if (pcr > 155520000/53/8) pcr = 155520000/53/8; | ||
991 | } | ||
992 | if (!pcr) { | ||
993 | /* no rate cap */ | ||
994 | tmc0 = IS_FS50(dev)?0x61BE:0x64c9; /* Just copied over the bits from Fujitsu -- REW */ | ||
995 | } else { | ||
996 | int r; | ||
997 | if (pcr < 0) { | ||
998 | r = ROUND_DOWN; | ||
999 | pcr = -pcr; | ||
1000 | } else { | ||
1001 | r = ROUND_UP; | ||
1002 | } | ||
1003 | error = make_rate (pcr, r, &tmc0, NULL); | ||
1004 | } | ||
1005 | fs_dprintk (FS_DEBUG_OPEN, "pcr = %d.\n", pcr); | ||
1006 | } | ||
1007 | |||
1008 | tc->TMC[0] = tmc0 | 0x4000; | ||
1009 | tc->TMC[1] = 0; /* Unused */ | ||
1010 | tc->TMC[2] = 0; /* Unused */ | ||
1011 | tc->TMC[3] = 0; /* Unused */ | ||
1012 | |||
1013 | tc->spec = 0; /* UTOPIA address, UDF, HEC: Unused -> 0 */ | ||
1014 | tc->rtag[0] = 0; /* What should I do with routing tags??? | ||
1015 | -- Not used -- AS -- Thanks -- REW*/ | ||
1016 | tc->rtag[1] = 0; | ||
1017 | tc->rtag[2] = 0; | ||
1018 | |||
1019 | if (fs_debug & FS_DEBUG_OPEN) { | ||
1020 | fs_dprintk (FS_DEBUG_OPEN, "TX config record:\n"); | ||
1021 | my_hd (tc, sizeof (*tc)); | ||
1022 | } | ||
1023 | |||
1024 | /* We now use the "submit_command" function to submit commands to | ||
1025 | the firestream. There is a define up near the definition of | ||
1026 | that routine that switches this routine between immediate write | ||
1027 | to the immediate comamnd registers and queuing the commands in | ||
1028 | the HPTXQ for execution. This last technique might be more | ||
1029 | efficient if we know we're going to submit a whole lot of | ||
1030 | commands in one go, but this driver is not setup to be able to | ||
1031 | use such a construct. So it probably doen't matter much right | ||
1032 | now. -- REW */ | ||
1033 | |||
1034 | /* The command is IMMediate and INQueue. The parameters are out-of-line.. */ | ||
1035 | submit_command (dev, &dev->hp_txq, | ||
1036 | QE_CMD_CONFIG_TX | QE_CMD_IMM_INQ | vcc->channo, | ||
1037 | virt_to_bus (tc), 0, 0); | ||
1038 | |||
1039 | submit_command (dev, &dev->hp_txq, | ||
1040 | QE_CMD_TX_EN | QE_CMD_IMM_INQ | vcc->channo, | ||
1041 | 0, 0, 0); | ||
1042 | set_bit (vcc->channo, dev->tx_inuse); | ||
1043 | } | ||
1044 | |||
1045 | if (DO_DIRECTION (rxtp)) { | ||
1046 | dev->atm_vccs[vcc->channo] = atm_vcc; | ||
1047 | |||
1048 | for (bfp = 0;bfp < FS_NR_FREE_POOLS; bfp++) | ||
1049 | if (atm_vcc->qos.rxtp.max_sdu <= dev->rx_fp[bfp].bufsize) break; | ||
1050 | if (bfp >= FS_NR_FREE_POOLS) { | ||
1051 | fs_dprintk (FS_DEBUG_OPEN, "No free pool fits sdu: %d.\n", | ||
1052 | atm_vcc->qos.rxtp.max_sdu); | ||
1053 | /* XXX Cleanup? -- Would just calling fs_close work??? -- REW */ | ||
1054 | |||
1055 | /* XXX clear tx inuse. Close TX part? */ | ||
1056 | dev->atm_vccs[vcc->channo] = NULL; | ||
1057 | kfree (vcc); | ||
1058 | return -EINVAL; | ||
1059 | } | ||
1060 | |||
1061 | switch (atm_vcc->qos.aal) { | ||
1062 | case ATM_AAL0: | ||
1063 | case ATM_AAL2: | ||
1064 | submit_command (dev, &dev->hp_txq, | ||
1065 | QE_CMD_CONFIG_RX | QE_CMD_IMM_INQ | vcc->channo, | ||
1066 | RC_FLAGS_TRANSP | | ||
1067 | RC_FLAGS_BFPS_BFP * bfp | | ||
1068 | RC_FLAGS_RXBM_PSB, 0, 0); | ||
1069 | break; | ||
1070 | case ATM_AAL5: | ||
1071 | submit_command (dev, &dev->hp_txq, | ||
1072 | QE_CMD_CONFIG_RX | QE_CMD_IMM_INQ | vcc->channo, | ||
1073 | RC_FLAGS_AAL5 | | ||
1074 | RC_FLAGS_BFPS_BFP * bfp | | ||
1075 | RC_FLAGS_RXBM_PSB, 0, 0); | ||
1076 | break; | ||
1077 | }; | ||
1078 | if (IS_FS50 (dev)) { | ||
1079 | submit_command (dev, &dev->hp_txq, | ||
1080 | QE_CMD_REG_WR | QE_CMD_IMM_INQ, | ||
1081 | 0x80 + vcc->channo, | ||
1082 | (vpi << 16) | vci, 0 ); /* XXX -- Use defines. */ | ||
1083 | } | ||
1084 | submit_command (dev, &dev->hp_txq, | ||
1085 | QE_CMD_RX_EN | QE_CMD_IMM_INQ | vcc->channo, | ||
1086 | 0, 0, 0); | ||
1087 | } | ||
1088 | |||
1089 | /* Indicate we're done! */ | ||
1090 | set_bit(ATM_VF_READY, &atm_vcc->flags); | ||
1091 | |||
1092 | func_exit (); | ||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | |||
1097 | static void fs_close(struct atm_vcc *atm_vcc) | ||
1098 | { | ||
1099 | struct fs_dev *dev = FS_DEV (atm_vcc->dev); | ||
1100 | struct fs_vcc *vcc = FS_VCC (atm_vcc); | ||
1101 | struct atm_trafprm * txtp; | ||
1102 | struct atm_trafprm * rxtp; | ||
1103 | |||
1104 | func_enter (); | ||
1105 | |||
1106 | clear_bit(ATM_VF_READY, &atm_vcc->flags); | ||
1107 | |||
1108 | fs_dprintk (FS_DEBUG_QSIZE, "--==**[%d]**==--", dev->ntxpckts); | ||
1109 | if (vcc->last_skb) { | ||
1110 | fs_dprintk (FS_DEBUG_QUEUE, "Waiting for skb %p to be sent.\n", | ||
1111 | vcc->last_skb); | ||
1112 | /* We're going to wait for the last packet to get sent on this VC. It would | ||
1113 | be impolite not to send them don't you think? | ||
1114 | XXX | ||
1115 | We don't know which packets didn't get sent. So if we get interrupted in | ||
1116 | this sleep_on, we'll lose any reference to these packets. Memory leak! | ||
1117 | On the other hand, it's awfully convenient that we can abort a "close" that | ||
1118 | is taking too long. Maybe just use non-interruptible sleep on? -- REW */ | ||
1119 | interruptible_sleep_on (& vcc->close_wait); | ||
1120 | } | ||
1121 | |||
1122 | txtp = &atm_vcc->qos.txtp; | ||
1123 | rxtp = &atm_vcc->qos.rxtp; | ||
1124 | |||
1125 | |||
1126 | /* See App note XXX (Unpublished as of now) for the reason for the | ||
1127 | removal of the "CMD_IMM_INQ" part of the TX_PURGE_INH... -- REW */ | ||
1128 | |||
1129 | if (DO_DIRECTION (txtp)) { | ||
1130 | submit_command (dev, &dev->hp_txq, | ||
1131 | QE_CMD_TX_PURGE_INH | /*QE_CMD_IMM_INQ|*/ vcc->channo, 0,0,0); | ||
1132 | clear_bit (vcc->channo, dev->tx_inuse); | ||
1133 | } | ||
1134 | |||
1135 | if (DO_DIRECTION (rxtp)) { | ||
1136 | submit_command (dev, &dev->hp_txq, | ||
1137 | QE_CMD_RX_PURGE_INH | QE_CMD_IMM_INQ | vcc->channo, 0,0,0); | ||
1138 | dev->atm_vccs [vcc->channo] = NULL; | ||
1139 | |||
1140 | /* This means that this is configured as a receive channel */ | ||
1141 | if (IS_FS50 (dev)) { | ||
1142 | /* Disable the receive filter. Is 0/0 indeed an invalid receive | ||
1143 | channel? -- REW. Yes it is. -- Hang. Ok. I'll use -1 | ||
1144 | (0xfff...) -- REW */ | ||
1145 | submit_command (dev, &dev->hp_txq, | ||
1146 | QE_CMD_REG_WR | QE_CMD_IMM_INQ, | ||
1147 | 0x80 + vcc->channo, -1, 0 ); | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | fs_dprintk (FS_DEBUG_ALLOC, "Free vcc: %p\n", vcc); | ||
1152 | kfree (vcc); | ||
1153 | |||
1154 | func_exit (); | ||
1155 | } | ||
1156 | |||
1157 | |||
1158 | static int fs_send (struct atm_vcc *atm_vcc, struct sk_buff *skb) | ||
1159 | { | ||
1160 | struct fs_dev *dev = FS_DEV (atm_vcc->dev); | ||
1161 | struct fs_vcc *vcc = FS_VCC (atm_vcc); | ||
1162 | struct FS_BPENTRY *td; | ||
1163 | |||
1164 | func_enter (); | ||
1165 | |||
1166 | fs_dprintk (FS_DEBUG_TXMEM, "I"); | ||
1167 | fs_dprintk (FS_DEBUG_SEND, "Send: atm_vcc %p skb %p vcc %p dev %p\n", | ||
1168 | atm_vcc, skb, vcc, dev); | ||
1169 | |||
1170 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc t-skb: %p (atm_send)\n", skb); | ||
1171 | |||
1172 | ATM_SKB(skb)->vcc = atm_vcc; | ||
1173 | |||
1174 | vcc->last_skb = skb; | ||
1175 | |||
1176 | td = kmalloc (sizeof (struct FS_BPENTRY), GFP_ATOMIC); | ||
1177 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc transd: %p(%Zd)\n", td, sizeof (struct FS_BPENTRY)); | ||
1178 | if (!td) { | ||
1179 | /* Oops out of mem */ | ||
1180 | return -ENOMEM; | ||
1181 | } | ||
1182 | |||
1183 | fs_dprintk (FS_DEBUG_SEND, "first word in buffer: %x\n", | ||
1184 | *(int *) skb->data); | ||
1185 | |||
1186 | td->flags = TD_EPI | TD_DATA | skb->len; | ||
1187 | td->next = 0; | ||
1188 | td->bsa = virt_to_bus (skb->data); | ||
1189 | td->skb = skb; | ||
1190 | td->dev = dev; | ||
1191 | dev->ntxpckts++; | ||
1192 | |||
1193 | #ifdef DEBUG_EXTRA | ||
1194 | da[qd] = td; | ||
1195 | dq[qd].flags = td->flags; | ||
1196 | dq[qd].next = td->next; | ||
1197 | dq[qd].bsa = td->bsa; | ||
1198 | dq[qd].skb = td->skb; | ||
1199 | dq[qd].dev = td->dev; | ||
1200 | qd++; | ||
1201 | if (qd >= 60) qd = 0; | ||
1202 | #endif | ||
1203 | |||
1204 | submit_queue (dev, &dev->hp_txq, | ||
1205 | QE_TRANSMIT_DE | vcc->channo, | ||
1206 | virt_to_bus (td), 0, | ||
1207 | virt_to_bus (td)); | ||
1208 | |||
1209 | fs_dprintk (FS_DEBUG_QUEUE, "in send: txq %d txrq %d\n", | ||
1210 | read_fs (dev, Q_EA (dev->hp_txq.offset)) - | ||
1211 | read_fs (dev, Q_SA (dev->hp_txq.offset)), | ||
1212 | read_fs (dev, Q_EA (dev->tx_relq.offset)) - | ||
1213 | read_fs (dev, Q_SA (dev->tx_relq.offset))); | ||
1214 | |||
1215 | func_exit (); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | /* Some function placeholders for functions we don't yet support. */ | ||
1221 | |||
1222 | #if 0 | ||
1223 | static int fs_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
1224 | { | ||
1225 | func_enter (); | ||
1226 | func_exit (); | ||
1227 | return -ENOIOCTLCMD; | ||
1228 | } | ||
1229 | |||
1230 | |||
1231 | static int fs_getsockopt(struct atm_vcc *vcc,int level,int optname, | ||
1232 | void __user *optval,int optlen) | ||
1233 | { | ||
1234 | func_enter (); | ||
1235 | func_exit (); | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | |||
1240 | static int fs_setsockopt(struct atm_vcc *vcc,int level,int optname, | ||
1241 | void __user *optval,int optlen) | ||
1242 | { | ||
1243 | func_enter (); | ||
1244 | func_exit (); | ||
1245 | return 0; | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | static void fs_phy_put(struct atm_dev *dev,unsigned char value, | ||
1250 | unsigned long addr) | ||
1251 | { | ||
1252 | func_enter (); | ||
1253 | func_exit (); | ||
1254 | } | ||
1255 | |||
1256 | |||
1257 | static unsigned char fs_phy_get(struct atm_dev *dev,unsigned long addr) | ||
1258 | { | ||
1259 | func_enter (); | ||
1260 | func_exit (); | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | |||
1265 | static int fs_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flags) | ||
1266 | { | ||
1267 | func_enter (); | ||
1268 | func_exit (); | ||
1269 | return 0; | ||
1270 | }; | ||
1271 | |||
1272 | #endif | ||
1273 | |||
1274 | |||
1275 | static const struct atmdev_ops ops = { | ||
1276 | .open = fs_open, | ||
1277 | .close = fs_close, | ||
1278 | .send = fs_send, | ||
1279 | .owner = THIS_MODULE, | ||
1280 | /* ioctl: fs_ioctl, */ | ||
1281 | /* getsockopt: fs_getsockopt, */ | ||
1282 | /* setsockopt: fs_setsockopt, */ | ||
1283 | /* change_qos: fs_change_qos, */ | ||
1284 | |||
1285 | /* For now implement these internally here... */ | ||
1286 | /* phy_put: fs_phy_put, */ | ||
1287 | /* phy_get: fs_phy_get, */ | ||
1288 | }; | ||
1289 | |||
1290 | |||
1291 | static void __devinit undocumented_pci_fix (struct pci_dev *pdev) | ||
1292 | { | ||
1293 | int tint; | ||
1294 | |||
1295 | /* The Windows driver says: */ | ||
1296 | /* Switch off FireStream Retry Limit Threshold | ||
1297 | */ | ||
1298 | |||
1299 | /* The register at 0x28 is documented as "reserved", no further | ||
1300 | comments. */ | ||
1301 | |||
1302 | pci_read_config_dword (pdev, 0x28, &tint); | ||
1303 | if (tint != 0x80) { | ||
1304 | tint = 0x80; | ||
1305 | pci_write_config_dword (pdev, 0x28, tint); | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | |||
1310 | |||
1311 | /************************************************************************** | ||
1312 | * PHY routines * | ||
1313 | **************************************************************************/ | ||
1314 | |||
1315 | static void __devinit write_phy (struct fs_dev *dev, int regnum, int val) | ||
1316 | { | ||
1317 | submit_command (dev, &dev->hp_txq, QE_CMD_PRP_WR | QE_CMD_IMM_INQ, | ||
1318 | regnum, val, 0); | ||
1319 | } | ||
1320 | |||
1321 | static int __devinit init_phy (struct fs_dev *dev, struct reginit_item *reginit) | ||
1322 | { | ||
1323 | int i; | ||
1324 | |||
1325 | func_enter (); | ||
1326 | while (reginit->reg != PHY_EOF) { | ||
1327 | if (reginit->reg == PHY_CLEARALL) { | ||
1328 | /* "PHY_CLEARALL means clear all registers. Numregisters is in "val". */ | ||
1329 | for (i=0;i<reginit->val;i++) { | ||
1330 | write_phy (dev, i, 0); | ||
1331 | } | ||
1332 | } else { | ||
1333 | write_phy (dev, reginit->reg, reginit->val); | ||
1334 | } | ||
1335 | reginit++; | ||
1336 | } | ||
1337 | func_exit (); | ||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | static void reset_chip (struct fs_dev *dev) | ||
1342 | { | ||
1343 | int i; | ||
1344 | |||
1345 | write_fs (dev, SARMODE0, SARMODE0_SRTS0); | ||
1346 | |||
1347 | /* Undocumented delay */ | ||
1348 | udelay (128); | ||
1349 | |||
1350 | /* The "internal registers are documented to all reset to zero, but | ||
1351 | comments & code in the Windows driver indicates that the pools are | ||
1352 | NOT reset. */ | ||
1353 | for (i=0;i < FS_NR_FREE_POOLS;i++) { | ||
1354 | write_fs (dev, FP_CNF (RXB_FP(i)), 0); | ||
1355 | write_fs (dev, FP_SA (RXB_FP(i)), 0); | ||
1356 | write_fs (dev, FP_EA (RXB_FP(i)), 0); | ||
1357 | write_fs (dev, FP_CNT (RXB_FP(i)), 0); | ||
1358 | write_fs (dev, FP_CTU (RXB_FP(i)), 0); | ||
1359 | } | ||
1360 | |||
1361 | /* The same goes for the match channel registers, although those are | ||
1362 | NOT documented that way in the Windows driver. -- REW */ | ||
1363 | /* The Windows driver DOES write 0 to these registers somewhere in | ||
1364 | the init sequence. However, a small hardware-feature, will | ||
1365 | prevent reception of data on VPI/VCI = 0/0 (Unless the channel | ||
1366 | allocated happens to have no disabled channels that have a lower | ||
1367 | number. -- REW */ | ||
1368 | |||
1369 | /* Clear the match channel registers. */ | ||
1370 | if (IS_FS50 (dev)) { | ||
1371 | for (i=0;i<FS50_NR_CHANNELS;i++) { | ||
1372 | write_fs (dev, 0x200 + i * 4, -1); | ||
1373 | } | ||
1374 | } | ||
1375 | } | ||
1376 | |||
1377 | static void __devinit *aligned_kmalloc (int size, int flags, int alignment) | ||
1378 | { | ||
1379 | void *t; | ||
1380 | |||
1381 | if (alignment <= 0x10) { | ||
1382 | t = kmalloc (size, flags); | ||
1383 | if ((unsigned long)t & (alignment-1)) { | ||
1384 | printk ("Kmalloc doesn't align things correctly! %p\n", t); | ||
1385 | kfree (t); | ||
1386 | return aligned_kmalloc (size, flags, alignment * 4); | ||
1387 | } | ||
1388 | return t; | ||
1389 | } | ||
1390 | printk (KERN_ERR "Request for > 0x10 alignment not yet implemented (hard!)\n"); | ||
1391 | return NULL; | ||
1392 | } | ||
1393 | |||
1394 | static int __devinit init_q (struct fs_dev *dev, | ||
1395 | struct queue *txq, int queue, int nentries, int is_rq) | ||
1396 | { | ||
1397 | int sz = nentries * sizeof (struct FS_QENTRY); | ||
1398 | struct FS_QENTRY *p; | ||
1399 | |||
1400 | func_enter (); | ||
1401 | |||
1402 | fs_dprintk (FS_DEBUG_INIT, "Inititing queue at %x: %d entries:\n", | ||
1403 | queue, nentries); | ||
1404 | |||
1405 | p = aligned_kmalloc (sz, GFP_KERNEL, 0x10); | ||
1406 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc queue: %p(%d)\n", p, sz); | ||
1407 | |||
1408 | if (!p) return 0; | ||
1409 | |||
1410 | write_fs (dev, Q_SA(queue), virt_to_bus(p)); | ||
1411 | write_fs (dev, Q_EA(queue), virt_to_bus(p+nentries-1)); | ||
1412 | write_fs (dev, Q_WP(queue), virt_to_bus(p)); | ||
1413 | write_fs (dev, Q_RP(queue), virt_to_bus(p)); | ||
1414 | if (is_rq) { | ||
1415 | /* Configuration for the receive queue: 0: interrupt immediately, | ||
1416 | no pre-warning to empty queues: We do our best to keep the | ||
1417 | queue filled anyway. */ | ||
1418 | write_fs (dev, Q_CNF(queue), 0 ); | ||
1419 | } | ||
1420 | |||
1421 | txq->sa = p; | ||
1422 | txq->ea = p; | ||
1423 | txq->offset = queue; | ||
1424 | |||
1425 | func_exit (); | ||
1426 | return 1; | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | static int __devinit init_fp (struct fs_dev *dev, | ||
1431 | struct freepool *fp, int queue, int bufsize, int nr_buffers) | ||
1432 | { | ||
1433 | func_enter (); | ||
1434 | |||
1435 | fs_dprintk (FS_DEBUG_INIT, "Inititing free pool at %x:\n", queue); | ||
1436 | |||
1437 | write_fs (dev, FP_CNF(queue), (bufsize * RBFP_RBS) | RBFP_RBSVAL | RBFP_CME); | ||
1438 | write_fs (dev, FP_SA(queue), 0); | ||
1439 | write_fs (dev, FP_EA(queue), 0); | ||
1440 | write_fs (dev, FP_CTU(queue), 0); | ||
1441 | write_fs (dev, FP_CNT(queue), 0); | ||
1442 | |||
1443 | fp->offset = queue; | ||
1444 | fp->bufsize = bufsize; | ||
1445 | fp->nr_buffers = nr_buffers; | ||
1446 | |||
1447 | func_exit (); | ||
1448 | return 1; | ||
1449 | } | ||
1450 | |||
1451 | |||
1452 | static inline int nr_buffers_in_freepool (struct fs_dev *dev, struct freepool *fp) | ||
1453 | { | ||
1454 | #if 0 | ||
1455 | /* This seems to be unreliable.... */ | ||
1456 | return read_fs (dev, FP_CNT (fp->offset)); | ||
1457 | #else | ||
1458 | return fp->n; | ||
1459 | #endif | ||
1460 | } | ||
1461 | |||
1462 | |||
1463 | /* Check if this gets going again if a pool ever runs out. -- Yes, it | ||
1464 | does. I've seen "receive abort: no buffers" and things started | ||
1465 | working again after that... -- REW */ | ||
1466 | |||
1467 | static void top_off_fp (struct fs_dev *dev, struct freepool *fp, int gfp_flags) | ||
1468 | { | ||
1469 | struct FS_BPENTRY *qe, *ne; | ||
1470 | struct sk_buff *skb; | ||
1471 | int n = 0; | ||
1472 | |||
1473 | fs_dprintk (FS_DEBUG_QUEUE, "Topping off queue at %x (%d-%d/%d)\n", | ||
1474 | fp->offset, read_fs (dev, FP_CNT (fp->offset)), fp->n, | ||
1475 | fp->nr_buffers); | ||
1476 | while (nr_buffers_in_freepool(dev, fp) < fp->nr_buffers) { | ||
1477 | |||
1478 | skb = alloc_skb (fp->bufsize, gfp_flags); | ||
1479 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc rec-skb: %p(%d)\n", skb, fp->bufsize); | ||
1480 | if (!skb) break; | ||
1481 | ne = kmalloc (sizeof (struct FS_BPENTRY), gfp_flags); | ||
1482 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc rec-d: %p(%Zd)\n", ne, sizeof (struct FS_BPENTRY)); | ||
1483 | if (!ne) { | ||
1484 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", skb); | ||
1485 | dev_kfree_skb_any (skb); | ||
1486 | break; | ||
1487 | } | ||
1488 | |||
1489 | fs_dprintk (FS_DEBUG_QUEUE, "Adding skb %p desc %p -> %p(%p) ", | ||
1490 | skb, ne, skb->data, skb->head); | ||
1491 | n++; | ||
1492 | ne->flags = FP_FLAGS_EPI | fp->bufsize; | ||
1493 | ne->next = virt_to_bus (NULL); | ||
1494 | ne->bsa = virt_to_bus (skb->data); | ||
1495 | ne->aal_bufsize = fp->bufsize; | ||
1496 | ne->skb = skb; | ||
1497 | ne->fp = fp; | ||
1498 | |||
1499 | qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset))); | ||
1500 | fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe); | ||
1501 | if (qe) { | ||
1502 | qe = bus_to_virt ((long) qe); | ||
1503 | qe->next = virt_to_bus(ne); | ||
1504 | qe->flags &= ~FP_FLAGS_EPI; | ||
1505 | } else | ||
1506 | write_fs (dev, FP_SA(fp->offset), virt_to_bus(ne)); | ||
1507 | |||
1508 | write_fs (dev, FP_EA(fp->offset), virt_to_bus (ne)); | ||
1509 | fp->n++; /* XXX Atomic_inc? */ | ||
1510 | write_fs (dev, FP_CTU(fp->offset), 1); | ||
1511 | } | ||
1512 | |||
1513 | fs_dprintk (FS_DEBUG_QUEUE, "Added %d entries. \n", n); | ||
1514 | } | ||
1515 | |||
1516 | static void __devexit free_queue (struct fs_dev *dev, struct queue *txq) | ||
1517 | { | ||
1518 | func_enter (); | ||
1519 | |||
1520 | write_fs (dev, Q_SA(txq->offset), 0); | ||
1521 | write_fs (dev, Q_EA(txq->offset), 0); | ||
1522 | write_fs (dev, Q_RP(txq->offset), 0); | ||
1523 | write_fs (dev, Q_WP(txq->offset), 0); | ||
1524 | /* Configuration ? */ | ||
1525 | |||
1526 | fs_dprintk (FS_DEBUG_ALLOC, "Free queue: %p\n", txq->sa); | ||
1527 | kfree (txq->sa); | ||
1528 | |||
1529 | func_exit (); | ||
1530 | } | ||
1531 | |||
1532 | static void __devexit free_freepool (struct fs_dev *dev, struct freepool *fp) | ||
1533 | { | ||
1534 | func_enter (); | ||
1535 | |||
1536 | write_fs (dev, FP_CNF(fp->offset), 0); | ||
1537 | write_fs (dev, FP_SA (fp->offset), 0); | ||
1538 | write_fs (dev, FP_EA (fp->offset), 0); | ||
1539 | write_fs (dev, FP_CNT(fp->offset), 0); | ||
1540 | write_fs (dev, FP_CTU(fp->offset), 0); | ||
1541 | |||
1542 | func_exit (); | ||
1543 | } | ||
1544 | |||
1545 | |||
1546 | |||
1547 | static irqreturn_t fs_irq (int irq, void *dev_id, struct pt_regs * pt_regs) | ||
1548 | { | ||
1549 | int i; | ||
1550 | u32 status; | ||
1551 | struct fs_dev *dev = dev_id; | ||
1552 | |||
1553 | status = read_fs (dev, ISR); | ||
1554 | if (!status) | ||
1555 | return IRQ_NONE; | ||
1556 | |||
1557 | func_enter (); | ||
1558 | |||
1559 | #ifdef IRQ_RATE_LIMIT | ||
1560 | /* Aaargh! I'm ashamed. This costs more lines-of-code than the actual | ||
1561 | interrupt routine!. (Well, used to when I wrote that comment) -- REW */ | ||
1562 | { | ||
1563 | static int lastjif; | ||
1564 | static int nintr=0; | ||
1565 | |||
1566 | if (lastjif == jiffies) { | ||
1567 | if (++nintr > IRQ_RATE_LIMIT) { | ||
1568 | free_irq (dev->irq, dev_id); | ||
1569 | printk (KERN_ERR "fs: Too many interrupts. Turning off interrupt %d.\n", | ||
1570 | dev->irq); | ||
1571 | } | ||
1572 | } else { | ||
1573 | lastjif = jiffies; | ||
1574 | nintr = 0; | ||
1575 | } | ||
1576 | } | ||
1577 | #endif | ||
1578 | fs_dprintk (FS_DEBUG_QUEUE, "in intr: txq %d txrq %d\n", | ||
1579 | read_fs (dev, Q_EA (dev->hp_txq.offset)) - | ||
1580 | read_fs (dev, Q_SA (dev->hp_txq.offset)), | ||
1581 | read_fs (dev, Q_EA (dev->tx_relq.offset)) - | ||
1582 | read_fs (dev, Q_SA (dev->tx_relq.offset))); | ||
1583 | |||
1584 | /* print the bits in the ISR register. */ | ||
1585 | if (fs_debug & FS_DEBUG_IRQ) { | ||
1586 | /* The FS_DEBUG things are unneccesary here. But this way it is | ||
1587 | clear for grep that these are debug prints. */ | ||
1588 | fs_dprintk (FS_DEBUG_IRQ, "IRQ status:"); | ||
1589 | for (i=0;i<27;i++) | ||
1590 | if (status & (1 << i)) | ||
1591 | fs_dprintk (FS_DEBUG_IRQ, " %s", irq_bitname[i]); | ||
1592 | fs_dprintk (FS_DEBUG_IRQ, "\n"); | ||
1593 | } | ||
1594 | |||
1595 | if (status & ISR_RBRQ0_W) { | ||
1596 | fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (0)!!!!\n"); | ||
1597 | process_incoming (dev, &dev->rx_rq[0]); | ||
1598 | /* items mentioned on RBRQ0 are from FP 0 or 1. */ | ||
1599 | top_off_fp (dev, &dev->rx_fp[0], GFP_ATOMIC); | ||
1600 | top_off_fp (dev, &dev->rx_fp[1], GFP_ATOMIC); | ||
1601 | } | ||
1602 | |||
1603 | if (status & ISR_RBRQ1_W) { | ||
1604 | fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (1)!!!!\n"); | ||
1605 | process_incoming (dev, &dev->rx_rq[1]); | ||
1606 | top_off_fp (dev, &dev->rx_fp[2], GFP_ATOMIC); | ||
1607 | top_off_fp (dev, &dev->rx_fp[3], GFP_ATOMIC); | ||
1608 | } | ||
1609 | |||
1610 | if (status & ISR_RBRQ2_W) { | ||
1611 | fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (2)!!!!\n"); | ||
1612 | process_incoming (dev, &dev->rx_rq[2]); | ||
1613 | top_off_fp (dev, &dev->rx_fp[4], GFP_ATOMIC); | ||
1614 | top_off_fp (dev, &dev->rx_fp[5], GFP_ATOMIC); | ||
1615 | } | ||
1616 | |||
1617 | if (status & ISR_RBRQ3_W) { | ||
1618 | fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (3)!!!!\n"); | ||
1619 | process_incoming (dev, &dev->rx_rq[3]); | ||
1620 | top_off_fp (dev, &dev->rx_fp[6], GFP_ATOMIC); | ||
1621 | top_off_fp (dev, &dev->rx_fp[7], GFP_ATOMIC); | ||
1622 | } | ||
1623 | |||
1624 | if (status & ISR_CSQ_W) { | ||
1625 | fs_dprintk (FS_DEBUG_IRQ, "Command executed ok!\n"); | ||
1626 | process_return_queue (dev, &dev->st_q); | ||
1627 | } | ||
1628 | |||
1629 | if (status & ISR_TBRQ_W) { | ||
1630 | fs_dprintk (FS_DEBUG_IRQ, "Data tramsitted!\n"); | ||
1631 | process_txdone_queue (dev, &dev->tx_relq); | ||
1632 | } | ||
1633 | |||
1634 | func_exit (); | ||
1635 | return IRQ_HANDLED; | ||
1636 | } | ||
1637 | |||
1638 | |||
1639 | #ifdef FS_POLL_FREQ | ||
1640 | static void fs_poll (unsigned long data) | ||
1641 | { | ||
1642 | struct fs_dev *dev = (struct fs_dev *) data; | ||
1643 | |||
1644 | fs_irq (0, dev, NULL); | ||
1645 | dev->timer.expires = jiffies + FS_POLL_FREQ; | ||
1646 | add_timer (&dev->timer); | ||
1647 | } | ||
1648 | #endif | ||
1649 | |||
1650 | static int __devinit fs_init (struct fs_dev *dev) | ||
1651 | { | ||
1652 | struct pci_dev *pci_dev; | ||
1653 | int isr, to; | ||
1654 | int i; | ||
1655 | |||
1656 | func_enter (); | ||
1657 | pci_dev = dev->pci_dev; | ||
1658 | |||
1659 | printk (KERN_INFO "found a FireStream %d card, base %08lx, irq%d.\n", | ||
1660 | IS_FS50(dev)?50:155, | ||
1661 | pci_resource_start(pci_dev, 0), dev->pci_dev->irq); | ||
1662 | |||
1663 | if (fs_debug & FS_DEBUG_INIT) | ||
1664 | my_hd ((unsigned char *) dev, sizeof (*dev)); | ||
1665 | |||
1666 | undocumented_pci_fix (pci_dev); | ||
1667 | |||
1668 | dev->hw_base = pci_resource_start(pci_dev, 0); | ||
1669 | |||
1670 | dev->base = ioremap(dev->hw_base, 0x1000); | ||
1671 | |||
1672 | reset_chip (dev); | ||
1673 | |||
1674 | write_fs (dev, SARMODE0, 0 | ||
1675 | | (0 * SARMODE0_SHADEN) /* We don't use shadow registers. */ | ||
1676 | | (1 * SARMODE0_INTMODE_READCLEAR) | ||
1677 | | (1 * SARMODE0_CWRE) | ||
1678 | | IS_FS50(dev)?SARMODE0_PRPWT_FS50_5: | ||
1679 | SARMODE0_PRPWT_FS155_3 | ||
1680 | | (1 * SARMODE0_CALSUP_1) | ||
1681 | | IS_FS50 (dev)?(0 | ||
1682 | | SARMODE0_RXVCS_32 | ||
1683 | | SARMODE0_ABRVCS_32 | ||
1684 | | SARMODE0_TXVCS_32): | ||
1685 | (0 | ||
1686 | | SARMODE0_RXVCS_1k | ||
1687 | | SARMODE0_ABRVCS_1k | ||
1688 | | SARMODE0_TXVCS_1k)); | ||
1689 | |||
1690 | /* 10ms * 100 is 1 second. That should be enough, as AN3:9 says it takes | ||
1691 | 1ms. */ | ||
1692 | to = 100; | ||
1693 | while (--to) { | ||
1694 | isr = read_fs (dev, ISR); | ||
1695 | |||
1696 | /* This bit is documented as "RESERVED" */ | ||
1697 | if (isr & ISR_INIT_ERR) { | ||
1698 | printk (KERN_ERR "Error initializing the FS... \n"); | ||
1699 | return 1; | ||
1700 | } | ||
1701 | if (isr & ISR_INIT) { | ||
1702 | fs_dprintk (FS_DEBUG_INIT, "Ha! Initialized OK!\n"); | ||
1703 | break; | ||
1704 | } | ||
1705 | |||
1706 | /* Try again after 10ms. */ | ||
1707 | msleep(10); | ||
1708 | } | ||
1709 | |||
1710 | if (!to) { | ||
1711 | printk (KERN_ERR "timeout initializing the FS... \n"); | ||
1712 | return 1; | ||
1713 | } | ||
1714 | |||
1715 | /* XXX fix for fs155 */ | ||
1716 | dev->channel_mask = 0x1f; | ||
1717 | dev->channo = 0; | ||
1718 | |||
1719 | /* AN3: 10 */ | ||
1720 | write_fs (dev, SARMODE1, 0 | ||
1721 | | (fs_keystream * SARMODE1_DEFHEC) /* XXX PHY */ | ||
1722 | | ((loopback == 1) * SARMODE1_TSTLP) /* XXX Loopback mode enable... */ | ||
1723 | | (1 * SARMODE1_DCRM) | ||
1724 | | (1 * SARMODE1_DCOAM) | ||
1725 | | (0 * SARMODE1_OAMCRC) | ||
1726 | | (0 * SARMODE1_DUMPE) | ||
1727 | | (0 * SARMODE1_GPLEN) | ||
1728 | | (0 * SARMODE1_GNAM) | ||
1729 | | (0 * SARMODE1_GVAS) | ||
1730 | | (0 * SARMODE1_GPAS) | ||
1731 | | (1 * SARMODE1_GPRI) | ||
1732 | | (0 * SARMODE1_PMS) | ||
1733 | | (0 * SARMODE1_GFCR) | ||
1734 | | (1 * SARMODE1_HECM2) | ||
1735 | | (1 * SARMODE1_HECM1) | ||
1736 | | (1 * SARMODE1_HECM0) | ||
1737 | | (1 << 12) /* That's what hang's driver does. Program to 0 */ | ||
1738 | | (0 * 0xff) /* XXX FS155 */); | ||
1739 | |||
1740 | |||
1741 | /* Cal prescale etc */ | ||
1742 | |||
1743 | /* AN3: 11 */ | ||
1744 | write_fs (dev, TMCONF, 0x0000000f); | ||
1745 | write_fs (dev, CALPRESCALE, 0x01010101 * num); | ||
1746 | write_fs (dev, 0x80, 0x000F00E4); | ||
1747 | |||
1748 | /* AN3: 12 */ | ||
1749 | write_fs (dev, CELLOSCONF, 0 | ||
1750 | | ( 0 * CELLOSCONF_CEN) | ||
1751 | | ( CELLOSCONF_SC1) | ||
1752 | | (0x80 * CELLOSCONF_COBS) | ||
1753 | | (num * CELLOSCONF_COPK) /* Changed from 0xff to 0x5a */ | ||
1754 | | (num * CELLOSCONF_COST));/* after a hint from Hang. | ||
1755 | * performance jumped 50->70... */ | ||
1756 | |||
1757 | /* Magic value by Hang */ | ||
1758 | write_fs (dev, CELLOSCONF_COST, 0x0B809191); | ||
1759 | |||
1760 | if (IS_FS50 (dev)) { | ||
1761 | write_fs (dev, RAS0, RAS0_DCD_XHLT); | ||
1762 | dev->atm_dev->ci_range.vpi_bits = 12; | ||
1763 | dev->atm_dev->ci_range.vci_bits = 16; | ||
1764 | dev->nchannels = FS50_NR_CHANNELS; | ||
1765 | } else { | ||
1766 | write_fs (dev, RAS0, RAS0_DCD_XHLT | ||
1767 | | (((1 << FS155_VPI_BITS) - 1) * RAS0_VPSEL) | ||
1768 | | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL)); | ||
1769 | /* We can chose the split arbitarily. We might be able to | ||
1770 | support more. Whatever. This should do for now. */ | ||
1771 | dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS; | ||
1772 | dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS; | ||
1773 | |||
1774 | /* Address bits we can't use should be compared to 0. */ | ||
1775 | write_fs (dev, RAC, 0); | ||
1776 | |||
1777 | /* Manual (AN9, page 6) says ASF1=0 means compare Utopia address | ||
1778 | * too. I can't find ASF1 anywhere. Anyway, we AND with just the | ||
1779 | * other bits, then compare with 0, which is exactly what we | ||
1780 | * want. */ | ||
1781 | write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1); | ||
1782 | dev->nchannels = FS155_NR_CHANNELS; | ||
1783 | } | ||
1784 | dev->atm_vccs = kmalloc (dev->nchannels * sizeof (struct atm_vcc *), | ||
1785 | GFP_KERNEL); | ||
1786 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc atmvccs: %p(%Zd)\n", | ||
1787 | dev->atm_vccs, dev->nchannels * sizeof (struct atm_vcc *)); | ||
1788 | |||
1789 | if (!dev->atm_vccs) { | ||
1790 | printk (KERN_WARNING "Couldn't allocate memory for VCC buffers. Woops!\n"); | ||
1791 | /* XXX Clean up..... */ | ||
1792 | return 1; | ||
1793 | } | ||
1794 | memset (dev->atm_vccs, 0, dev->nchannels * sizeof (struct atm_vcc *)); | ||
1795 | |||
1796 | dev->tx_inuse = kmalloc (dev->nchannels / 8 /* bits/byte */ , GFP_KERNEL); | ||
1797 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc tx_inuse: %p(%d)\n", | ||
1798 | dev->atm_vccs, dev->nchannels / 8); | ||
1799 | |||
1800 | if (!dev->tx_inuse) { | ||
1801 | printk (KERN_WARNING "Couldn't allocate memory for tx_inuse bits!\n"); | ||
1802 | /* XXX Clean up..... */ | ||
1803 | return 1; | ||
1804 | } | ||
1805 | memset (dev->tx_inuse, 0, dev->nchannels / 8); | ||
1806 | |||
1807 | /* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for both */ | ||
1808 | /* -- RAS2 : FS50 only: Default is OK. */ | ||
1809 | |||
1810 | /* DMAMODE, default should be OK. -- REW */ | ||
1811 | write_fs (dev, DMAMR, DMAMR_TX_MODE_FULL); | ||
1812 | |||
1813 | init_q (dev, &dev->hp_txq, TX_PQ(TXQ_HP), TXQ_NENTRIES, 0); | ||
1814 | init_q (dev, &dev->lp_txq, TX_PQ(TXQ_LP), TXQ_NENTRIES, 0); | ||
1815 | init_q (dev, &dev->tx_relq, TXB_RQ, TXQ_NENTRIES, 1); | ||
1816 | init_q (dev, &dev->st_q, ST_Q, TXQ_NENTRIES, 1); | ||
1817 | |||
1818 | for (i=0;i < FS_NR_FREE_POOLS;i++) { | ||
1819 | init_fp (dev, &dev->rx_fp[i], RXB_FP(i), | ||
1820 | rx_buf_sizes[i], rx_pool_sizes[i]); | ||
1821 | top_off_fp (dev, &dev->rx_fp[i], GFP_KERNEL); | ||
1822 | } | ||
1823 | |||
1824 | |||
1825 | for (i=0;i < FS_NR_RX_QUEUES;i++) | ||
1826 | init_q (dev, &dev->rx_rq[i], RXB_RQ(i), RXRQ_NENTRIES, 1); | ||
1827 | |||
1828 | dev->irq = pci_dev->irq; | ||
1829 | if (request_irq (dev->irq, fs_irq, SA_SHIRQ, "firestream", dev)) { | ||
1830 | printk (KERN_WARNING "couldn't get irq %d for firestream.\n", pci_dev->irq); | ||
1831 | /* XXX undo all previous stuff... */ | ||
1832 | return 1; | ||
1833 | } | ||
1834 | fs_dprintk (FS_DEBUG_INIT, "Grabbed irq %d for dev at %p.\n", dev->irq, dev); | ||
1835 | |||
1836 | /* We want to be notified of most things. Just the statistics count | ||
1837 | overflows are not interesting */ | ||
1838 | write_fs (dev, IMR, 0 | ||
1839 | | ISR_RBRQ0_W | ||
1840 | | ISR_RBRQ1_W | ||
1841 | | ISR_RBRQ2_W | ||
1842 | | ISR_RBRQ3_W | ||
1843 | | ISR_TBRQ_W | ||
1844 | | ISR_CSQ_W); | ||
1845 | |||
1846 | write_fs (dev, SARMODE0, 0 | ||
1847 | | (0 * SARMODE0_SHADEN) /* We don't use shadow registers. */ | ||
1848 | | (1 * SARMODE0_GINT) | ||
1849 | | (1 * SARMODE0_INTMODE_READCLEAR) | ||
1850 | | (0 * SARMODE0_CWRE) | ||
1851 | | (IS_FS50(dev)?SARMODE0_PRPWT_FS50_5: | ||
1852 | SARMODE0_PRPWT_FS155_3) | ||
1853 | | (1 * SARMODE0_CALSUP_1) | ||
1854 | | (IS_FS50 (dev)?(0 | ||
1855 | | SARMODE0_RXVCS_32 | ||
1856 | | SARMODE0_ABRVCS_32 | ||
1857 | | SARMODE0_TXVCS_32): | ||
1858 | (0 | ||
1859 | | SARMODE0_RXVCS_1k | ||
1860 | | SARMODE0_ABRVCS_1k | ||
1861 | | SARMODE0_TXVCS_1k)) | ||
1862 | | (1 * SARMODE0_RUN)); | ||
1863 | |||
1864 | init_phy (dev, PHY_NTC_INIT); | ||
1865 | |||
1866 | if (loopback == 2) { | ||
1867 | write_phy (dev, 0x39, 0x000e); | ||
1868 | } | ||
1869 | |||
1870 | #ifdef FS_POLL_FREQ | ||
1871 | init_timer (&dev->timer); | ||
1872 | dev->timer.data = (unsigned long) dev; | ||
1873 | dev->timer.function = fs_poll; | ||
1874 | dev->timer.expires = jiffies + FS_POLL_FREQ; | ||
1875 | add_timer (&dev->timer); | ||
1876 | #endif | ||
1877 | |||
1878 | dev->atm_dev->dev_data = dev; | ||
1879 | |||
1880 | func_exit (); | ||
1881 | return 0; | ||
1882 | } | ||
1883 | |||
1884 | static int __devinit firestream_init_one (struct pci_dev *pci_dev, | ||
1885 | const struct pci_device_id *ent) | ||
1886 | { | ||
1887 | struct atm_dev *atm_dev; | ||
1888 | struct fs_dev *fs_dev; | ||
1889 | |||
1890 | if (pci_enable_device(pci_dev)) | ||
1891 | goto err_out; | ||
1892 | |||
1893 | fs_dev = kmalloc (sizeof (struct fs_dev), GFP_KERNEL); | ||
1894 | fs_dprintk (FS_DEBUG_ALLOC, "Alloc fs-dev: %p(%Zd)\n", | ||
1895 | fs_dev, sizeof (struct fs_dev)); | ||
1896 | if (!fs_dev) | ||
1897 | goto err_out; | ||
1898 | |||
1899 | memset (fs_dev, 0, sizeof (struct fs_dev)); | ||
1900 | |||
1901 | atm_dev = atm_dev_register("fs", &ops, -1, NULL); | ||
1902 | if (!atm_dev) | ||
1903 | goto err_out_free_fs_dev; | ||
1904 | |||
1905 | fs_dev->pci_dev = pci_dev; | ||
1906 | fs_dev->atm_dev = atm_dev; | ||
1907 | fs_dev->flags = ent->driver_data; | ||
1908 | |||
1909 | if (fs_init(fs_dev)) | ||
1910 | goto err_out_free_atm_dev; | ||
1911 | |||
1912 | fs_dev->next = fs_boards; | ||
1913 | fs_boards = fs_dev; | ||
1914 | return 0; | ||
1915 | |||
1916 | err_out_free_atm_dev: | ||
1917 | atm_dev_deregister(atm_dev); | ||
1918 | err_out_free_fs_dev: | ||
1919 | kfree(fs_dev); | ||
1920 | err_out: | ||
1921 | return -ENODEV; | ||
1922 | } | ||
1923 | |||
1924 | static void __devexit firestream_remove_one (struct pci_dev *pdev) | ||
1925 | { | ||
1926 | int i; | ||
1927 | struct fs_dev *dev, *nxtdev; | ||
1928 | struct fs_vcc *vcc; | ||
1929 | struct FS_BPENTRY *fp, *nxt; | ||
1930 | |||
1931 | func_enter (); | ||
1932 | |||
1933 | #if 0 | ||
1934 | printk ("hptxq:\n"); | ||
1935 | for (i=0;i<60;i++) { | ||
1936 | printk ("%d: %08x %08x %08x %08x \n", | ||
1937 | i, pq[qp].cmd, pq[qp].p0, pq[qp].p1, pq[qp].p2); | ||
1938 | qp++; | ||
1939 | if (qp >= 60) qp = 0; | ||
1940 | } | ||
1941 | |||
1942 | printk ("descriptors:\n"); | ||
1943 | for (i=0;i<60;i++) { | ||
1944 | printk ("%d: %p: %08x %08x %p %p\n", | ||
1945 | i, da[qd], dq[qd].flags, dq[qd].bsa, dq[qd].skb, dq[qd].dev); | ||
1946 | qd++; | ||
1947 | if (qd >= 60) qd = 0; | ||
1948 | } | ||
1949 | #endif | ||
1950 | |||
1951 | for (dev = fs_boards;dev != NULL;dev=nxtdev) { | ||
1952 | fs_dprintk (FS_DEBUG_CLEANUP, "Releasing resources for dev at %p.\n", dev); | ||
1953 | |||
1954 | /* XXX Hit all the tx channels too! */ | ||
1955 | |||
1956 | for (i=0;i < dev->nchannels;i++) { | ||
1957 | if (dev->atm_vccs[i]) { | ||
1958 | vcc = FS_VCC (dev->atm_vccs[i]); | ||
1959 | submit_command (dev, &dev->hp_txq, | ||
1960 | QE_CMD_TX_PURGE_INH | QE_CMD_IMM_INQ | vcc->channo, 0,0,0); | ||
1961 | submit_command (dev, &dev->hp_txq, | ||
1962 | QE_CMD_RX_PURGE_INH | QE_CMD_IMM_INQ | vcc->channo, 0,0,0); | ||
1963 | |||
1964 | } | ||
1965 | } | ||
1966 | |||
1967 | /* XXX Wait a while for the chip to release all buffers. */ | ||
1968 | |||
1969 | for (i=0;i < FS_NR_FREE_POOLS;i++) { | ||
1970 | for (fp=bus_to_virt (read_fs (dev, FP_SA(dev->rx_fp[i].offset))); | ||
1971 | !(fp->flags & FP_FLAGS_EPI);fp = nxt) { | ||
1972 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", fp->skb); | ||
1973 | dev_kfree_skb_any (fp->skb); | ||
1974 | nxt = bus_to_virt (fp->next); | ||
1975 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", fp); | ||
1976 | kfree (fp); | ||
1977 | } | ||
1978 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", fp->skb); | ||
1979 | dev_kfree_skb_any (fp->skb); | ||
1980 | fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", fp); | ||
1981 | kfree (fp); | ||
1982 | } | ||
1983 | |||
1984 | /* Hang the chip in "reset", prevent it clobbering memory that is | ||
1985 | no longer ours. */ | ||
1986 | reset_chip (dev); | ||
1987 | |||
1988 | fs_dprintk (FS_DEBUG_CLEANUP, "Freeing irq%d.\n", dev->irq); | ||
1989 | free_irq (dev->irq, dev); | ||
1990 | del_timer (&dev->timer); | ||
1991 | |||
1992 | atm_dev_deregister(dev->atm_dev); | ||
1993 | free_queue (dev, &dev->hp_txq); | ||
1994 | free_queue (dev, &dev->lp_txq); | ||
1995 | free_queue (dev, &dev->tx_relq); | ||
1996 | free_queue (dev, &dev->st_q); | ||
1997 | |||
1998 | fs_dprintk (FS_DEBUG_ALLOC, "Free atmvccs: %p\n", dev->atm_vccs); | ||
1999 | kfree (dev->atm_vccs); | ||
2000 | |||
2001 | for (i=0;i< FS_NR_FREE_POOLS;i++) | ||
2002 | free_freepool (dev, &dev->rx_fp[i]); | ||
2003 | |||
2004 | for (i=0;i < FS_NR_RX_QUEUES;i++) | ||
2005 | free_queue (dev, &dev->rx_rq[i]); | ||
2006 | |||
2007 | fs_dprintk (FS_DEBUG_ALLOC, "Free fs-dev: %p\n", dev); | ||
2008 | nxtdev = dev->next; | ||
2009 | kfree (dev); | ||
2010 | } | ||
2011 | |||
2012 | func_exit (); | ||
2013 | } | ||
2014 | |||
2015 | static struct pci_device_id firestream_pci_tbl[] = { | ||
2016 | { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50, | ||
2017 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS50}, | ||
2018 | { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155, | ||
2019 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS155}, | ||
2020 | { 0, } | ||
2021 | }; | ||
2022 | |||
2023 | MODULE_DEVICE_TABLE(pci, firestream_pci_tbl); | ||
2024 | |||
2025 | static struct pci_driver firestream_driver = { | ||
2026 | .name = "firestream", | ||
2027 | .id_table = firestream_pci_tbl, | ||
2028 | .probe = firestream_init_one, | ||
2029 | .remove = __devexit_p(firestream_remove_one), | ||
2030 | }; | ||
2031 | |||
2032 | static int __init firestream_init_module (void) | ||
2033 | { | ||
2034 | int error; | ||
2035 | |||
2036 | func_enter (); | ||
2037 | error = pci_register_driver(&firestream_driver); | ||
2038 | func_exit (); | ||
2039 | return error; | ||
2040 | } | ||
2041 | |||
2042 | static void __exit firestream_cleanup_module(void) | ||
2043 | { | ||
2044 | pci_unregister_driver(&firestream_driver); | ||
2045 | } | ||
2046 | |||
2047 | module_init(firestream_init_module); | ||
2048 | module_exit(firestream_cleanup_module); | ||
2049 | |||
2050 | MODULE_LICENSE("GPL"); | ||
2051 | |||
2052 | |||
2053 | |||
diff --git a/drivers/atm/firestream.h b/drivers/atm/firestream.h new file mode 100644 index 000000000000..49e783e35ee9 --- /dev/null +++ b/drivers/atm/firestream.h | |||
@@ -0,0 +1,518 @@ | |||
1 | /* drivers/atm/firestream.h - FireStream 155 (MB86697) and | ||
2 | * FireStream 50 (MB86695) device driver | ||
3 | */ | ||
4 | |||
5 | /* Written & (C) 2000 by R.E.Wolff@BitWizard.nl | ||
6 | * Copied snippets from zatm.c by Werner Almesberger, EPFL LRC/ICA | ||
7 | * and ambassador.c Copyright (C) 1995-1999 Madge Networks Ltd | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | |||
25 | The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian | ||
26 | system and in the file COPYING in the Linux kernel source. | ||
27 | */ | ||
28 | |||
29 | |||
30 | /*********************************************************************** | ||
31 | * first the defines for the chip. * | ||
32 | ***********************************************************************/ | ||
33 | |||
34 | |||
35 | /********************* General chip parameters. ************************/ | ||
36 | |||
37 | #define FS_NR_FREE_POOLS 8 | ||
38 | #define FS_NR_RX_QUEUES 4 | ||
39 | |||
40 | |||
41 | /********************* queues and queue access macros ******************/ | ||
42 | |||
43 | |||
44 | /* A queue entry. */ | ||
45 | struct FS_QENTRY { | ||
46 | u32 cmd; | ||
47 | u32 p0, p1, p2; | ||
48 | }; | ||
49 | |||
50 | |||
51 | /* A freepool entry. */ | ||
52 | struct FS_BPENTRY { | ||
53 | u32 flags; | ||
54 | u32 next; | ||
55 | u32 bsa; | ||
56 | u32 aal_bufsize; | ||
57 | |||
58 | /* The hardware doesn't look at this, but we need the SKB somewhere... */ | ||
59 | struct sk_buff *skb; | ||
60 | struct freepool *fp; | ||
61 | struct fs_dev *dev; | ||
62 | }; | ||
63 | |||
64 | |||
65 | #define STATUS_CODE(qe) ((qe->cmd >> 22) & 0x3f) | ||
66 | |||
67 | |||
68 | /* OFFSETS against the base of a QUEUE... */ | ||
69 | #define QSA 0x00 | ||
70 | #define QEA 0x04 | ||
71 | #define QRP 0x08 | ||
72 | #define QWP 0x0c | ||
73 | #define QCNF 0x10 /* Only for Release queues! */ | ||
74 | /* Not for the transmit pending queue. */ | ||
75 | |||
76 | |||
77 | /* OFFSETS against the base of a FREE POOL... */ | ||
78 | #define FPCNF 0x00 | ||
79 | #define FPSA 0x04 | ||
80 | #define FPEA 0x08 | ||
81 | #define FPCNT 0x0c | ||
82 | #define FPCTU 0x10 | ||
83 | |||
84 | #define Q_SA(b) (b + QSA ) | ||
85 | #define Q_EA(b) (b + QEA ) | ||
86 | #define Q_RP(b) (b + QRP ) | ||
87 | #define Q_WP(b) (b + QWP ) | ||
88 | #define Q_CNF(b) (b + QCNF) | ||
89 | |||
90 | #define FP_CNF(b) (b + FPCNF) | ||
91 | #define FP_SA(b) (b + FPSA) | ||
92 | #define FP_EA(b) (b + FPEA) | ||
93 | #define FP_CNT(b) (b + FPCNT) | ||
94 | #define FP_CTU(b) (b + FPCTU) | ||
95 | |||
96 | /* bits in a queue register. */ | ||
97 | #define Q_FULL 0x1 | ||
98 | #define Q_EMPTY 0x2 | ||
99 | #define Q_INCWRAP 0x4 | ||
100 | #define Q_ADDR_MASK 0xfffffff0 | ||
101 | |||
102 | /* bits in a FreePool config register */ | ||
103 | #define RBFP_RBS (0x1 << 16) | ||
104 | #define RBFP_RBSVAL (0x1 << 15) | ||
105 | #define RBFP_CME (0x1 << 12) | ||
106 | #define RBFP_DLP (0x1 << 11) | ||
107 | #define RBFP_BFPWT (0x1 << 0) | ||
108 | |||
109 | |||
110 | |||
111 | |||
112 | /* FireStream commands. */ | ||
113 | #define QE_CMD_NULL (0x00 << 22) | ||
114 | #define QE_CMD_REG_RD (0x01 << 22) | ||
115 | #define QE_CMD_REG_RDM (0x02 << 22) | ||
116 | #define QE_CMD_REG_WR (0x03 << 22) | ||
117 | #define QE_CMD_REG_WRM (0x04 << 22) | ||
118 | #define QE_CMD_CONFIG_TX (0x05 << 22) | ||
119 | #define QE_CMD_CONFIG_RX (0x06 << 22) | ||
120 | #define QE_CMD_PRP_RD (0x07 << 22) | ||
121 | #define QE_CMD_PRP_RDM (0x2a << 22) | ||
122 | #define QE_CMD_PRP_WR (0x09 << 22) | ||
123 | #define QE_CMD_PRP_WRM (0x2b << 22) | ||
124 | #define QE_CMD_RX_EN (0x0a << 22) | ||
125 | #define QE_CMD_RX_PURGE (0x0b << 22) | ||
126 | #define QE_CMD_RX_PURGE_INH (0x0c << 22) | ||
127 | #define QE_CMD_TX_EN (0x0d << 22) | ||
128 | #define QE_CMD_TX_PURGE (0x0e << 22) | ||
129 | #define QE_CMD_TX_PURGE_INH (0x0f << 22) | ||
130 | #define QE_CMD_RST_CG (0x10 << 22) | ||
131 | #define QE_CMD_SET_CG (0x11 << 22) | ||
132 | #define QE_CMD_RST_CLP (0x12 << 22) | ||
133 | #define QE_CMD_SET_CLP (0x13 << 22) | ||
134 | #define QE_CMD_OVERRIDE (0x14 << 22) | ||
135 | #define QE_CMD_ADD_BFP (0x15 << 22) | ||
136 | #define QE_CMD_DUMP_TX (0x16 << 22) | ||
137 | #define QE_CMD_DUMP_RX (0x17 << 22) | ||
138 | #define QE_CMD_LRAM_RD (0x18 << 22) | ||
139 | #define QE_CMD_LRAM_RDM (0x28 << 22) | ||
140 | #define QE_CMD_LRAM_WR (0x19 << 22) | ||
141 | #define QE_CMD_LRAM_WRM (0x29 << 22) | ||
142 | #define QE_CMD_LRAM_BSET (0x1a << 22) | ||
143 | #define QE_CMD_LRAM_BCLR (0x1b << 22) | ||
144 | #define QE_CMD_CONFIG_SEGM (0x1c << 22) | ||
145 | #define QE_CMD_READ_SEGM (0x1d << 22) | ||
146 | #define QE_CMD_CONFIG_ROUT (0x1e << 22) | ||
147 | #define QE_CMD_READ_ROUT (0x1f << 22) | ||
148 | #define QE_CMD_CONFIG_TM (0x20 << 22) | ||
149 | #define QE_CMD_READ_TM (0x21 << 22) | ||
150 | #define QE_CMD_CONFIG_TXBM (0x22 << 22) | ||
151 | #define QE_CMD_READ_TXBM (0x23 << 22) | ||
152 | #define QE_CMD_CONFIG_RXBM (0x24 << 22) | ||
153 | #define QE_CMD_READ_RXBM (0x25 << 22) | ||
154 | #define QE_CMD_CONFIG_REAS (0x26 << 22) | ||
155 | #define QE_CMD_READ_REAS (0x27 << 22) | ||
156 | |||
157 | #define QE_TRANSMIT_DE (0x0 << 30) | ||
158 | #define QE_CMD_LINKED (0x1 << 30) | ||
159 | #define QE_CMD_IMM (0x2 << 30) | ||
160 | #define QE_CMD_IMM_INQ (0x3 << 30) | ||
161 | |||
162 | #define TD_EPI (0x1 << 27) | ||
163 | #define TD_COMMAND (0x1 << 28) | ||
164 | |||
165 | #define TD_DATA (0x0 << 29) | ||
166 | #define TD_RM_CELL (0x1 << 29) | ||
167 | #define TD_OAM_CELL (0x2 << 29) | ||
168 | #define TD_OAM_CELL_SEGMENT (0x3 << 29) | ||
169 | |||
170 | #define TD_BPI (0x1 << 20) | ||
171 | |||
172 | #define FP_FLAGS_EPI (0x1 << 27) | ||
173 | |||
174 | |||
175 | #define TX_PQ(i) (0x00 + (i) * 0x10) | ||
176 | #define TXB_RQ (0x20) | ||
177 | #define ST_Q (0x48) | ||
178 | #define RXB_FP(i) (0x90 + (i) * 0x14) | ||
179 | #define RXB_RQ(i) (0x134 + (i) * 0x14) | ||
180 | |||
181 | |||
182 | #define TXQ_HP 0 | ||
183 | #define TXQ_LP 1 | ||
184 | |||
185 | /* Phew. You don't want to know how many revisions these simple queue | ||
186 | * address macros went through before I got them nice and compact as | ||
187 | * they are now. -- REW | ||
188 | */ | ||
189 | |||
190 | |||
191 | /* And now for something completely different: | ||
192 | * The rest of the registers... */ | ||
193 | |||
194 | |||
195 | #define CMDR0 0x34 | ||
196 | #define CMDR1 0x38 | ||
197 | #define CMDR2 0x3c | ||
198 | #define CMDR3 0x40 | ||
199 | |||
200 | |||
201 | #define SARMODE0 0x5c | ||
202 | |||
203 | #define SARMODE0_TXVCS_0 (0x0 << 0) | ||
204 | #define SARMODE0_TXVCS_1k (0x1 << 0) | ||
205 | #define SARMODE0_TXVCS_2k (0x2 << 0) | ||
206 | #define SARMODE0_TXVCS_4k (0x3 << 0) | ||
207 | #define SARMODE0_TXVCS_8k (0x4 << 0) | ||
208 | #define SARMODE0_TXVCS_16k (0x5 << 0) | ||
209 | #define SARMODE0_TXVCS_32k (0x6 << 0) | ||
210 | #define SARMODE0_TXVCS_64k (0x7 << 0) | ||
211 | #define SARMODE0_TXVCS_32 (0x8 << 0) | ||
212 | |||
213 | #define SARMODE0_ABRVCS_0 (0x0 << 4) | ||
214 | #define SARMODE0_ABRVCS_512 (0x1 << 4) | ||
215 | #define SARMODE0_ABRVCS_1k (0x2 << 4) | ||
216 | #define SARMODE0_ABRVCS_2k (0x3 << 4) | ||
217 | #define SARMODE0_ABRVCS_4k (0x4 << 4) | ||
218 | #define SARMODE0_ABRVCS_8k (0x5 << 4) | ||
219 | #define SARMODE0_ABRVCS_16k (0x6 << 4) | ||
220 | #define SARMODE0_ABRVCS_32k (0x7 << 4) | ||
221 | #define SARMODE0_ABRVCS_32 (0x9 << 4) /* The others are "8", this one really has to | ||
222 | be 9. Tell me you don't believe me. -- REW */ | ||
223 | |||
224 | #define SARMODE0_RXVCS_0 (0x0 << 8) | ||
225 | #define SARMODE0_RXVCS_1k (0x1 << 8) | ||
226 | #define SARMODE0_RXVCS_2k (0x2 << 8) | ||
227 | #define SARMODE0_RXVCS_4k (0x3 << 8) | ||
228 | #define SARMODE0_RXVCS_8k (0x4 << 8) | ||
229 | #define SARMODE0_RXVCS_16k (0x5 << 8) | ||
230 | #define SARMODE0_RXVCS_32k (0x6 << 8) | ||
231 | #define SARMODE0_RXVCS_64k (0x7 << 8) | ||
232 | #define SARMODE0_RXVCS_32 (0x8 << 8) | ||
233 | |||
234 | #define SARMODE0_CALSUP_1 (0x0 << 12) | ||
235 | #define SARMODE0_CALSUP_2 (0x1 << 12) | ||
236 | #define SARMODE0_CALSUP_3 (0x2 << 12) | ||
237 | #define SARMODE0_CALSUP_4 (0x3 << 12) | ||
238 | |||
239 | #define SARMODE0_PRPWT_FS50_0 (0x0 << 14) | ||
240 | #define SARMODE0_PRPWT_FS50_2 (0x1 << 14) | ||
241 | #define SARMODE0_PRPWT_FS50_5 (0x2 << 14) | ||
242 | #define SARMODE0_PRPWT_FS50_11 (0x3 << 14) | ||
243 | |||
244 | #define SARMODE0_PRPWT_FS155_0 (0x0 << 14) | ||
245 | #define SARMODE0_PRPWT_FS155_1 (0x1 << 14) | ||
246 | #define SARMODE0_PRPWT_FS155_2 (0x2 << 14) | ||
247 | #define SARMODE0_PRPWT_FS155_3 (0x3 << 14) | ||
248 | |||
249 | #define SARMODE0_SRTS0 (0x1 << 23) | ||
250 | #define SARMODE0_SRTS1 (0x1 << 24) | ||
251 | |||
252 | #define SARMODE0_RUN (0x1 << 25) | ||
253 | |||
254 | #define SARMODE0_UNLOCK (0x1 << 26) | ||
255 | #define SARMODE0_CWRE (0x1 << 27) | ||
256 | |||
257 | |||
258 | #define SARMODE0_INTMODE_READCLEAR (0x0 << 28) | ||
259 | #define SARMODE0_INTMODE_READNOCLEAR (0x1 << 28) | ||
260 | #define SARMODE0_INTMODE_READNOCLEARINHIBIT (0x2 << 28) | ||
261 | #define SARMODE0_INTMODE_READCLEARINHIBIT (0x3 << 28) /* Tell me you don't believe me. */ | ||
262 | |||
263 | #define SARMODE0_GINT (0x1 << 30) | ||
264 | #define SARMODE0_SHADEN (0x1 << 31) | ||
265 | |||
266 | |||
267 | #define SARMODE1 0x60 | ||
268 | |||
269 | |||
270 | #define SARMODE1_TRTL_SHIFT 0 /* Program to 0 */ | ||
271 | #define SARMODE1_RRTL_SHIFT 4 /* Program to 0 */ | ||
272 | |||
273 | #define SARMODE1_TAGM (0x1 << 8) /* Program to 0 */ | ||
274 | |||
275 | #define SARMODE1_HECM0 (0x1 << 9) | ||
276 | #define SARMODE1_HECM1 (0x1 << 10) | ||
277 | #define SARMODE1_HECM2 (0x1 << 11) | ||
278 | |||
279 | #define SARMODE1_GFCE (0x1 << 14) | ||
280 | #define SARMODE1_GFCR (0x1 << 15) | ||
281 | #define SARMODE1_PMS (0x1 << 18) | ||
282 | #define SARMODE1_GPRI (0x1 << 19) | ||
283 | #define SARMODE1_GPAS (0x1 << 20) | ||
284 | #define SARMODE1_GVAS (0x1 << 21) | ||
285 | #define SARMODE1_GNAM (0x1 << 22) | ||
286 | #define SARMODE1_GPLEN (0x1 << 23) | ||
287 | #define SARMODE1_DUMPE (0x1 << 24) | ||
288 | #define SARMODE1_OAMCRC (0x1 << 25) | ||
289 | #define SARMODE1_DCOAM (0x1 << 26) | ||
290 | #define SARMODE1_DCRM (0x1 << 27) | ||
291 | #define SARMODE1_TSTLP (0x1 << 28) | ||
292 | #define SARMODE1_DEFHEC (0x1 << 29) | ||
293 | |||
294 | |||
295 | #define ISR 0x64 | ||
296 | #define IUSR 0x68 | ||
297 | #define IMR 0x6c | ||
298 | |||
299 | #define ISR_LPCO (0x1 << 0) | ||
300 | #define ISR_DPCO (0x1 << 1) | ||
301 | #define ISR_RBRQ0_W (0x1 << 2) | ||
302 | #define ISR_RBRQ1_W (0x1 << 3) | ||
303 | #define ISR_RBRQ2_W (0x1 << 4) | ||
304 | #define ISR_RBRQ3_W (0x1 << 5) | ||
305 | #define ISR_RBRQ0_NF (0x1 << 6) | ||
306 | #define ISR_RBRQ1_NF (0x1 << 7) | ||
307 | #define ISR_RBRQ2_NF (0x1 << 8) | ||
308 | #define ISR_RBRQ3_NF (0x1 << 9) | ||
309 | #define ISR_BFP_SC (0x1 << 10) | ||
310 | #define ISR_INIT (0x1 << 11) | ||
311 | #define ISR_INIT_ERR (0x1 << 12) /* Documented as "reserved" */ | ||
312 | #define ISR_USCEO (0x1 << 13) | ||
313 | #define ISR_UPEC0 (0x1 << 14) | ||
314 | #define ISR_VPFCO (0x1 << 15) | ||
315 | #define ISR_CRCCO (0x1 << 16) | ||
316 | #define ISR_HECO (0x1 << 17) | ||
317 | #define ISR_TBRQ_W (0x1 << 18) | ||
318 | #define ISR_TBRQ_NF (0x1 << 19) | ||
319 | #define ISR_CTPQ_E (0x1 << 20) | ||
320 | #define ISR_GFC_C0 (0x1 << 21) | ||
321 | #define ISR_PCI_FTL (0x1 << 22) | ||
322 | #define ISR_CSQ_W (0x1 << 23) | ||
323 | #define ISR_CSQ_NF (0x1 << 24) | ||
324 | #define ISR_EXT_INT (0x1 << 25) | ||
325 | #define ISR_RXDMA_S (0x1 << 26) | ||
326 | |||
327 | |||
328 | #define TMCONF 0x78 | ||
329 | /* Bits? */ | ||
330 | |||
331 | |||
332 | #define CALPRESCALE 0x7c | ||
333 | /* Bits? */ | ||
334 | |||
335 | #define CELLOSCONF 0x84 | ||
336 | #define CELLOSCONF_COTS (0x1 << 28) | ||
337 | #define CELLOSCONF_CEN (0x1 << 27) | ||
338 | #define CELLOSCONF_SC8 (0x3 << 24) | ||
339 | #define CELLOSCONF_SC4 (0x2 << 24) | ||
340 | #define CELLOSCONF_SC2 (0x1 << 24) | ||
341 | #define CELLOSCONF_SC1 (0x0 << 24) | ||
342 | |||
343 | #define CELLOSCONF_COBS (0x1 << 16) | ||
344 | #define CELLOSCONF_COPK (0x1 << 8) | ||
345 | #define CELLOSCONF_COST (0x1 << 0) | ||
346 | /* Bits? */ | ||
347 | |||
348 | #define RAS0 0x1bc | ||
349 | #define RAS0_DCD_XHLT (0x1 << 31) | ||
350 | |||
351 | #define RAS0_VPSEL (0x1 << 16) | ||
352 | #define RAS0_VCSEL (0x1 << 0) | ||
353 | |||
354 | #define RAS1 0x1c0 | ||
355 | #define RAS1_UTREG (0x1 << 5) | ||
356 | |||
357 | |||
358 | #define DMAMR 0x1cc | ||
359 | #define DMAMR_TX_MODE_FULL (0x0 << 0) | ||
360 | #define DMAMR_TX_MODE_PART (0x1 << 0) | ||
361 | #define DMAMR_TX_MODE_NONE (0x2 << 0) /* And 3 */ | ||
362 | |||
363 | |||
364 | |||
365 | #define RAS2 0x280 | ||
366 | |||
367 | #define RAS2_NNI (0x1 << 0) | ||
368 | #define RAS2_USEL (0x1 << 1) | ||
369 | #define RAS2_UBS (0x1 << 2) | ||
370 | |||
371 | |||
372 | |||
373 | struct fs_transmit_config { | ||
374 | u32 flags; | ||
375 | u32 atm_hdr; | ||
376 | u32 TMC[4]; | ||
377 | u32 spec; | ||
378 | u32 rtag[3]; | ||
379 | }; | ||
380 | |||
381 | #define TC_FLAGS_AAL5 (0x0 << 29) | ||
382 | #define TC_FLAGS_TRANSPARENT_PAYLOAD (0x1 << 29) | ||
383 | #define TC_FLAGS_TRANSPARENT_CELL (0x2 << 29) | ||
384 | #define TC_FLAGS_STREAMING (0x1 << 28) | ||
385 | #define TC_FLAGS_PACKET (0x0) | ||
386 | #define TC_FLAGS_TYPE_ABR (0x0 << 22) | ||
387 | #define TC_FLAGS_TYPE_CBR (0x1 << 22) | ||
388 | #define TC_FLAGS_TYPE_VBR (0x2 << 22) | ||
389 | #define TC_FLAGS_TYPE_UBR (0x3 << 22) | ||
390 | #define TC_FLAGS_CAL0 (0x0 << 20) | ||
391 | #define TC_FLAGS_CAL1 (0x1 << 20) | ||
392 | #define TC_FLAGS_CAL2 (0x2 << 20) | ||
393 | #define TC_FLAGS_CAL3 (0x3 << 20) | ||
394 | |||
395 | |||
396 | #define RC_FLAGS_NAM (0x1 << 13) | ||
397 | #define RC_FLAGS_RXBM_PSB (0x0 << 14) | ||
398 | #define RC_FLAGS_RXBM_CIF (0x1 << 14) | ||
399 | #define RC_FLAGS_RXBM_PMB (0x2 << 14) | ||
400 | #define RC_FLAGS_RXBM_STR (0x4 << 14) | ||
401 | #define RC_FLAGS_RXBM_SAF (0x6 << 14) | ||
402 | #define RC_FLAGS_RXBM_POS (0x6 << 14) | ||
403 | #define RC_FLAGS_BFPS (0x1 << 17) | ||
404 | |||
405 | #define RC_FLAGS_BFPS_BFP (0x1 << 17) | ||
406 | |||
407 | #define RC_FLAGS_BFPS_BFP0 (0x0 << 17) | ||
408 | #define RC_FLAGS_BFPS_BFP1 (0x1 << 17) | ||
409 | #define RC_FLAGS_BFPS_BFP2 (0x2 << 17) | ||
410 | #define RC_FLAGS_BFPS_BFP3 (0x3 << 17) | ||
411 | #define RC_FLAGS_BFPS_BFP4 (0x4 << 17) | ||
412 | #define RC_FLAGS_BFPS_BFP5 (0x5 << 17) | ||
413 | #define RC_FLAGS_BFPS_BFP6 (0x6 << 17) | ||
414 | #define RC_FLAGS_BFPS_BFP7 (0x7 << 17) | ||
415 | #define RC_FLAGS_BFPS_BFP01 (0x8 << 17) | ||
416 | #define RC_FLAGS_BFPS_BFP23 (0x9 << 17) | ||
417 | #define RC_FLAGS_BFPS_BFP45 (0xa << 17) | ||
418 | #define RC_FLAGS_BFPS_BFP67 (0xb << 17) | ||
419 | #define RC_FLAGS_BFPS_BFP07 (0xc << 17) | ||
420 | #define RC_FLAGS_BFPS_BFP27 (0xd << 17) | ||
421 | #define RC_FLAGS_BFPS_BFP47 (0xe << 17) | ||
422 | |||
423 | #define RC_FLAGS_BFPS (0x1 << 17) | ||
424 | #define RC_FLAGS_BFPP (0x1 << 21) | ||
425 | #define RC_FLAGS_TEVC (0x1 << 22) | ||
426 | #define RC_FLAGS_TEP (0x1 << 23) | ||
427 | #define RC_FLAGS_AAL5 (0x0 << 24) | ||
428 | #define RC_FLAGS_TRANSP (0x1 << 24) | ||
429 | #define RC_FLAGS_TRANSC (0x2 << 24) | ||
430 | #define RC_FLAGS_ML (0x1 << 27) | ||
431 | #define RC_FLAGS_TRBRM (0x1 << 28) | ||
432 | #define RC_FLAGS_PRI (0x1 << 29) | ||
433 | #define RC_FLAGS_HOAM (0x1 << 30) | ||
434 | #define RC_FLAGS_CRC10 (0x1 << 31) | ||
435 | |||
436 | |||
437 | #define RAC 0x1c8 | ||
438 | #define RAM 0x1c4 | ||
439 | |||
440 | |||
441 | |||
442 | /************************************************************************ | ||
443 | * Then the datastructures that the DRIVER uses. * | ||
444 | ************************************************************************/ | ||
445 | |||
446 | #define TXQ_NENTRIES 32 | ||
447 | #define RXRQ_NENTRIES 1024 | ||
448 | |||
449 | |||
450 | struct fs_vcc { | ||
451 | int channo; | ||
452 | wait_queue_head_t close_wait; | ||
453 | struct sk_buff *last_skb; | ||
454 | }; | ||
455 | |||
456 | |||
457 | struct queue { | ||
458 | struct FS_QENTRY *sa, *ea; | ||
459 | int offset; | ||
460 | }; | ||
461 | |||
462 | struct freepool { | ||
463 | int offset; | ||
464 | int bufsize; | ||
465 | int nr_buffers; | ||
466 | int n; | ||
467 | }; | ||
468 | |||
469 | |||
470 | struct fs_dev { | ||
471 | struct fs_dev *next; /* other FS devices */ | ||
472 | int flags; | ||
473 | |||
474 | unsigned char irq; /* IRQ */ | ||
475 | struct pci_dev *pci_dev; /* PCI stuff */ | ||
476 | struct atm_dev *atm_dev; | ||
477 | struct timer_list timer; | ||
478 | |||
479 | unsigned long hw_base; /* mem base address */ | ||
480 | void __iomem *base; /* Mapping of base address */ | ||
481 | int channo; | ||
482 | unsigned long channel_mask; | ||
483 | |||
484 | struct queue hp_txq, lp_txq, tx_relq, st_q; | ||
485 | struct freepool rx_fp[FS_NR_FREE_POOLS]; | ||
486 | struct queue rx_rq[FS_NR_RX_QUEUES]; | ||
487 | |||
488 | int nchannels; | ||
489 | struct atm_vcc **atm_vccs; | ||
490 | void *tx_inuse; | ||
491 | int ntxpckts; | ||
492 | }; | ||
493 | |||
494 | |||
495 | |||
496 | |||
497 | /* Number of channesl that the FS50 supports. */ | ||
498 | #define FS50_CHANNEL_BITS 5 | ||
499 | #define FS50_NR_CHANNELS (1 << FS50_CHANNEL_BITS) | ||
500 | |||
501 | |||
502 | #define FS_DEV(atm_dev) ((struct fs_dev *) (atm_dev)->dev_data) | ||
503 | #define FS_VCC(atm_vcc) ((struct fs_vcc *) (atm_vcc)->dev_data) | ||
504 | |||
505 | |||
506 | #define FS_IS50 0x1 | ||
507 | #define FS_IS155 0x2 | ||
508 | |||
509 | #define IS_FS50(dev) (dev->flags & FS_IS50) | ||
510 | #define IS_FS155(dev) (dev->flags & FS_IS155) | ||
511 | |||
512 | /* Within limits this is user-configurable. */ | ||
513 | /* Note: Currently the sum (10 -> 1k channels) is hardcoded in the driver. */ | ||
514 | #define FS155_VPI_BITS 4 | ||
515 | #define FS155_VCI_BITS 6 | ||
516 | |||
517 | #define FS155_CHANNEL_BITS (FS155_VPI_BITS + FS155_VCI_BITS) | ||
518 | #define FS155_NR_CHANNELS (1 << FS155_CHANNEL_BITS) | ||
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c new file mode 100644 index 000000000000..196b33644627 --- /dev/null +++ b/drivers/atm/fore200e.c | |||
@@ -0,0 +1,3249 @@ | |||
1 | /* | ||
2 | $Id: fore200e.c,v 1.5 2000/04/14 10:10:34 davem Exp $ | ||
3 | |||
4 | A FORE Systems 200E-series driver for ATM on Linux. | ||
5 | Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2003. | ||
6 | |||
7 | Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de). | ||
8 | |||
9 | This driver simultaneously supports PCA-200E and SBA-200E adapters | ||
10 | on i386, alpha (untested), powerpc, sparc and sparc64 architectures. | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include <linux/config.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/capability.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/bitops.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/atmdev.h> | ||
39 | #include <linux/sonet.h> | ||
40 | #include <linux/atm_suni.h> | ||
41 | #include <linux/dma-mapping.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/string.h> | ||
45 | #include <asm/page.h> | ||
46 | #include <asm/irq.h> | ||
47 | #include <asm/dma.h> | ||
48 | #include <asm/byteorder.h> | ||
49 | #include <asm/uaccess.h> | ||
50 | #include <asm/atomic.h> | ||
51 | |||
52 | #ifdef CONFIG_ATM_FORE200E_SBA | ||
53 | #include <asm/idprom.h> | ||
54 | #include <asm/sbus.h> | ||
55 | #include <asm/openprom.h> | ||
56 | #include <asm/oplib.h> | ||
57 | #include <asm/pgtable.h> | ||
58 | #endif | ||
59 | |||
60 | #if defined(CONFIG_ATM_FORE200E_USE_TASKLET) /* defer interrupt work to a tasklet */ | ||
61 | #define FORE200E_USE_TASKLET | ||
62 | #endif | ||
63 | |||
64 | #if 0 /* enable the debugging code of the buffer supply queues */ | ||
65 | #define FORE200E_BSQ_DEBUG | ||
66 | #endif | ||
67 | |||
68 | #if 1 /* ensure correct handling of 52-byte AAL0 SDUs expected by atmdump-like apps */ | ||
69 | #define FORE200E_52BYTE_AAL0_SDU | ||
70 | #endif | ||
71 | |||
72 | #include "fore200e.h" | ||
73 | #include "suni.h" | ||
74 | |||
75 | #define FORE200E_VERSION "0.3e" | ||
76 | |||
77 | #define FORE200E "fore200e: " | ||
78 | |||
79 | #if 0 /* override .config */ | ||
80 | #define CONFIG_ATM_FORE200E_DEBUG 1 | ||
81 | #endif | ||
82 | #if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0) | ||
83 | #define DPRINTK(level, format, args...) do { if (CONFIG_ATM_FORE200E_DEBUG >= (level)) \ | ||
84 | printk(FORE200E format, ##args); } while (0) | ||
85 | #else | ||
86 | #define DPRINTK(level, format, args...) do {} while (0) | ||
87 | #endif | ||
88 | |||
89 | |||
90 | #define FORE200E_ALIGN(addr, alignment) \ | ||
91 | ((((unsigned long)(addr) + (alignment - 1)) & ~(alignment - 1)) - (unsigned long)(addr)) | ||
92 | |||
93 | #define FORE200E_DMA_INDEX(dma_addr, type, index) ((dma_addr) + (index) * sizeof(type)) | ||
94 | |||
95 | #define FORE200E_INDEX(virt_addr, type, index) (&((type *)(virt_addr))[ index ]) | ||
96 | |||
97 | #define FORE200E_NEXT_ENTRY(index, modulo) (index = ++(index) % (modulo)) | ||
98 | |||
99 | #if 1 | ||
100 | #define ASSERT(expr) if (!(expr)) { \ | ||
101 | printk(FORE200E "assertion failed! %s[%d]: %s\n", \ | ||
102 | __FUNCTION__, __LINE__, #expr); \ | ||
103 | panic(FORE200E "%s", __FUNCTION__); \ | ||
104 | } | ||
105 | #else | ||
106 | #define ASSERT(expr) do {} while (0) | ||
107 | #endif | ||
108 | |||
109 | |||
110 | static const struct atmdev_ops fore200e_ops; | ||
111 | static const struct fore200e_bus fore200e_bus[]; | ||
112 | |||
113 | static LIST_HEAD(fore200e_boards); | ||
114 | |||
115 | |||
116 | MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen"); | ||
117 | MODULE_DESCRIPTION("FORE Systems 200E-series ATM driver - version " FORE200E_VERSION); | ||
118 | MODULE_SUPPORTED_DEVICE("PCA-200E, SBA-200E"); | ||
119 | |||
120 | |||
121 | static const int fore200e_rx_buf_nbr[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = { | ||
122 | { BUFFER_S1_NBR, BUFFER_L1_NBR }, | ||
123 | { BUFFER_S2_NBR, BUFFER_L2_NBR } | ||
124 | }; | ||
125 | |||
126 | static const int fore200e_rx_buf_size[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = { | ||
127 | { BUFFER_S1_SIZE, BUFFER_L1_SIZE }, | ||
128 | { BUFFER_S2_SIZE, BUFFER_L2_SIZE } | ||
129 | }; | ||
130 | |||
131 | |||
132 | #if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0) | ||
133 | static const char* fore200e_traffic_class[] = { "NONE", "UBR", "CBR", "VBR", "ABR", "ANY" }; | ||
134 | #endif | ||
135 | |||
136 | |||
137 | #if 0 /* currently unused */ | ||
138 | static int | ||
139 | fore200e_fore2atm_aal(enum fore200e_aal aal) | ||
140 | { | ||
141 | switch(aal) { | ||
142 | case FORE200E_AAL0: return ATM_AAL0; | ||
143 | case FORE200E_AAL34: return ATM_AAL34; | ||
144 | case FORE200E_AAL5: return ATM_AAL5; | ||
145 | } | ||
146 | |||
147 | return -EINVAL; | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | |||
152 | static enum fore200e_aal | ||
153 | fore200e_atm2fore_aal(int aal) | ||
154 | { | ||
155 | switch(aal) { | ||
156 | case ATM_AAL0: return FORE200E_AAL0; | ||
157 | case ATM_AAL34: return FORE200E_AAL34; | ||
158 | case ATM_AAL1: | ||
159 | case ATM_AAL2: | ||
160 | case ATM_AAL5: return FORE200E_AAL5; | ||
161 | } | ||
162 | |||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | |||
167 | static char* | ||
168 | fore200e_irq_itoa(int irq) | ||
169 | { | ||
170 | #if defined(__sparc_v9__) | ||
171 | return __irq_itoa(irq); | ||
172 | #else | ||
173 | static char str[8]; | ||
174 | sprintf(str, "%d", irq); | ||
175 | return str; | ||
176 | #endif | ||
177 | } | ||
178 | |||
179 | |||
180 | static void* | ||
181 | fore200e_kmalloc(int size, int flags) | ||
182 | { | ||
183 | void* chunk = kmalloc(size, flags); | ||
184 | |||
185 | if (chunk) | ||
186 | memset(chunk, 0x00, size); | ||
187 | else | ||
188 | printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags); | ||
189 | |||
190 | return chunk; | ||
191 | } | ||
192 | |||
193 | |||
194 | static void | ||
195 | fore200e_kfree(void* chunk) | ||
196 | { | ||
197 | kfree(chunk); | ||
198 | } | ||
199 | |||
200 | |||
201 | /* allocate and align a chunk of memory intended to hold the data behing exchanged | ||
202 | between the driver and the adapter (using streaming DVMA) */ | ||
203 | |||
204 | static int | ||
205 | fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment, int direction) | ||
206 | { | ||
207 | unsigned long offset = 0; | ||
208 | |||
209 | if (alignment <= sizeof(int)) | ||
210 | alignment = 0; | ||
211 | |||
212 | chunk->alloc_size = size + alignment; | ||
213 | chunk->align_size = size; | ||
214 | chunk->direction = direction; | ||
215 | |||
216 | chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA); | ||
217 | if (chunk->alloc_addr == NULL) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | if (alignment > 0) | ||
221 | offset = FORE200E_ALIGN(chunk->alloc_addr, alignment); | ||
222 | |||
223 | chunk->align_addr = chunk->alloc_addr + offset; | ||
224 | |||
225 | chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size, direction); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | |||
231 | /* free a chunk of memory */ | ||
232 | |||
233 | static void | ||
234 | fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk) | ||
235 | { | ||
236 | fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction); | ||
237 | |||
238 | fore200e_kfree(chunk->alloc_addr); | ||
239 | } | ||
240 | |||
241 | |||
242 | static void | ||
243 | fore200e_spin(int msecs) | ||
244 | { | ||
245 | unsigned long timeout = jiffies + msecs_to_jiffies(msecs); | ||
246 | while (time_before(jiffies, timeout)); | ||
247 | } | ||
248 | |||
249 | |||
250 | static int | ||
251 | fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs) | ||
252 | { | ||
253 | unsigned long timeout = jiffies + msecs_to_jiffies(msecs); | ||
254 | int ok; | ||
255 | |||
256 | mb(); | ||
257 | do { | ||
258 | if ((ok = (*addr == val)) || (*addr & STATUS_ERROR)) | ||
259 | break; | ||
260 | |||
261 | } while (time_before(jiffies, timeout)); | ||
262 | |||
263 | #if 1 | ||
264 | if (!ok) { | ||
265 | printk(FORE200E "cmd polling failed, got status 0x%08x, expected 0x%08x\n", | ||
266 | *addr, val); | ||
267 | } | ||
268 | #endif | ||
269 | |||
270 | return ok; | ||
271 | } | ||
272 | |||
273 | |||
274 | static int | ||
275 | fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs) | ||
276 | { | ||
277 | unsigned long timeout = jiffies + msecs_to_jiffies(msecs); | ||
278 | int ok; | ||
279 | |||
280 | do { | ||
281 | if ((ok = (fore200e->bus->read(addr) == val))) | ||
282 | break; | ||
283 | |||
284 | } while (time_before(jiffies, timeout)); | ||
285 | |||
286 | #if 1 | ||
287 | if (!ok) { | ||
288 | printk(FORE200E "I/O polling failed, got status 0x%08x, expected 0x%08x\n", | ||
289 | fore200e->bus->read(addr), val); | ||
290 | } | ||
291 | #endif | ||
292 | |||
293 | return ok; | ||
294 | } | ||
295 | |||
296 | |||
297 | static void | ||
298 | fore200e_free_rx_buf(struct fore200e* fore200e) | ||
299 | { | ||
300 | int scheme, magn, nbr; | ||
301 | struct buffer* buffer; | ||
302 | |||
303 | for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) { | ||
304 | for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) { | ||
305 | |||
306 | if ((buffer = fore200e->host_bsq[ scheme ][ magn ].buffer) != NULL) { | ||
307 | |||
308 | for (nbr = 0; nbr < fore200e_rx_buf_nbr[ scheme ][ magn ]; nbr++) { | ||
309 | |||
310 | struct chunk* data = &buffer[ nbr ].data; | ||
311 | |||
312 | if (data->alloc_addr != NULL) | ||
313 | fore200e_chunk_free(fore200e, data); | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | |||
320 | |||
321 | static void | ||
322 | fore200e_uninit_bs_queue(struct fore200e* fore200e) | ||
323 | { | ||
324 | int scheme, magn; | ||
325 | |||
326 | for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) { | ||
327 | for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) { | ||
328 | |||
329 | struct chunk* status = &fore200e->host_bsq[ scheme ][ magn ].status; | ||
330 | struct chunk* rbd_block = &fore200e->host_bsq[ scheme ][ magn ].rbd_block; | ||
331 | |||
332 | if (status->alloc_addr) | ||
333 | fore200e->bus->dma_chunk_free(fore200e, status); | ||
334 | |||
335 | if (rbd_block->alloc_addr) | ||
336 | fore200e->bus->dma_chunk_free(fore200e, rbd_block); | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
341 | |||
342 | static int | ||
343 | fore200e_reset(struct fore200e* fore200e, int diag) | ||
344 | { | ||
345 | int ok; | ||
346 | |||
347 | fore200e->cp_monitor = fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET; | ||
348 | |||
349 | fore200e->bus->write(BSTAT_COLD_START, &fore200e->cp_monitor->bstat); | ||
350 | |||
351 | fore200e->bus->reset(fore200e); | ||
352 | |||
353 | if (diag) { | ||
354 | ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_SELFTEST_OK, 1000); | ||
355 | if (ok == 0) { | ||
356 | |||
357 | printk(FORE200E "device %s self-test failed\n", fore200e->name); | ||
358 | return -ENODEV; | ||
359 | } | ||
360 | |||
361 | printk(FORE200E "device %s self-test passed\n", fore200e->name); | ||
362 | |||
363 | fore200e->state = FORE200E_STATE_RESET; | ||
364 | } | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | |||
370 | static void | ||
371 | fore200e_shutdown(struct fore200e* fore200e) | ||
372 | { | ||
373 | printk(FORE200E "removing device %s at 0x%lx, IRQ %s\n", | ||
374 | fore200e->name, fore200e->phys_base, | ||
375 | fore200e_irq_itoa(fore200e->irq)); | ||
376 | |||
377 | if (fore200e->state > FORE200E_STATE_RESET) { | ||
378 | /* first, reset the board to prevent further interrupts or data transfers */ | ||
379 | fore200e_reset(fore200e, 0); | ||
380 | } | ||
381 | |||
382 | /* then, release all allocated resources */ | ||
383 | switch(fore200e->state) { | ||
384 | |||
385 | case FORE200E_STATE_COMPLETE: | ||
386 | if (fore200e->stats) | ||
387 | kfree(fore200e->stats); | ||
388 | |||
389 | case FORE200E_STATE_IRQ: | ||
390 | free_irq(fore200e->irq, fore200e->atm_dev); | ||
391 | |||
392 | case FORE200E_STATE_ALLOC_BUF: | ||
393 | fore200e_free_rx_buf(fore200e); | ||
394 | |||
395 | case FORE200E_STATE_INIT_BSQ: | ||
396 | fore200e_uninit_bs_queue(fore200e); | ||
397 | |||
398 | case FORE200E_STATE_INIT_RXQ: | ||
399 | fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.status); | ||
400 | fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.rpd); | ||
401 | |||
402 | case FORE200E_STATE_INIT_TXQ: | ||
403 | fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.status); | ||
404 | fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.tpd); | ||
405 | |||
406 | case FORE200E_STATE_INIT_CMDQ: | ||
407 | fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_cmdq.status); | ||
408 | |||
409 | case FORE200E_STATE_INITIALIZE: | ||
410 | /* nothing to do for that state */ | ||
411 | |||
412 | case FORE200E_STATE_START_FW: | ||
413 | /* nothing to do for that state */ | ||
414 | |||
415 | case FORE200E_STATE_LOAD_FW: | ||
416 | /* nothing to do for that state */ | ||
417 | |||
418 | case FORE200E_STATE_RESET: | ||
419 | /* nothing to do for that state */ | ||
420 | |||
421 | case FORE200E_STATE_MAP: | ||
422 | fore200e->bus->unmap(fore200e); | ||
423 | |||
424 | case FORE200E_STATE_CONFIGURE: | ||
425 | /* nothing to do for that state */ | ||
426 | |||
427 | case FORE200E_STATE_REGISTER: | ||
428 | /* XXX shouldn't we *start* by deregistering the device? */ | ||
429 | atm_dev_deregister(fore200e->atm_dev); | ||
430 | |||
431 | case FORE200E_STATE_BLANK: | ||
432 | /* nothing to do for that state */ | ||
433 | break; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | |||
438 | #ifdef CONFIG_ATM_FORE200E_PCA | ||
439 | |||
440 | static u32 fore200e_pca_read(volatile u32 __iomem *addr) | ||
441 | { | ||
442 | /* on big-endian hosts, the board is configured to convert | ||
443 | the endianess of slave RAM accesses */ | ||
444 | return le32_to_cpu(readl(addr)); | ||
445 | } | ||
446 | |||
447 | |||
448 | static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr) | ||
449 | { | ||
450 | /* on big-endian hosts, the board is configured to convert | ||
451 | the endianess of slave RAM accesses */ | ||
452 | writel(cpu_to_le32(val), addr); | ||
453 | } | ||
454 | |||
455 | |||
456 | static u32 | ||
457 | fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) | ||
458 | { | ||
459 | u32 dma_addr = pci_map_single((struct pci_dev*)fore200e->bus_dev, virt_addr, size, direction); | ||
460 | |||
461 | DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d, --> dma_addr = 0x%08x\n", | ||
462 | virt_addr, size, direction, dma_addr); | ||
463 | |||
464 | return dma_addr; | ||
465 | } | ||
466 | |||
467 | |||
468 | static void | ||
469 | fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
470 | { | ||
471 | DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", | ||
472 | dma_addr, size, direction); | ||
473 | |||
474 | pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
475 | } | ||
476 | |||
477 | |||
478 | static void | ||
479 | fore200e_pca_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
480 | { | ||
481 | DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
482 | |||
483 | pci_dma_sync_single_for_cpu((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
484 | } | ||
485 | |||
486 | static void | ||
487 | fore200e_pca_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
488 | { | ||
489 | DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
490 | |||
491 | pci_dma_sync_single_for_device((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
492 | } | ||
493 | |||
494 | |||
495 | /* allocate a DMA consistent chunk of memory intended to act as a communication mechanism | ||
496 | (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */ | ||
497 | |||
498 | static int | ||
499 | fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, | ||
500 | int size, int nbr, int alignment) | ||
501 | { | ||
502 | /* returned chunks are page-aligned */ | ||
503 | chunk->alloc_size = size * nbr; | ||
504 | chunk->alloc_addr = pci_alloc_consistent((struct pci_dev*)fore200e->bus_dev, | ||
505 | chunk->alloc_size, | ||
506 | &chunk->dma_addr); | ||
507 | |||
508 | if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) | ||
509 | return -ENOMEM; | ||
510 | |||
511 | chunk->align_addr = chunk->alloc_addr; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | |||
517 | /* free a DMA consistent chunk of memory */ | ||
518 | |||
519 | static void | ||
520 | fore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) | ||
521 | { | ||
522 | pci_free_consistent((struct pci_dev*)fore200e->bus_dev, | ||
523 | chunk->alloc_size, | ||
524 | chunk->alloc_addr, | ||
525 | chunk->dma_addr); | ||
526 | } | ||
527 | |||
528 | |||
529 | static int | ||
530 | fore200e_pca_irq_check(struct fore200e* fore200e) | ||
531 | { | ||
532 | /* this is a 1 bit register */ | ||
533 | int irq_posted = readl(fore200e->regs.pca.psr); | ||
534 | |||
535 | #if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG == 2) | ||
536 | if (irq_posted && (readl(fore200e->regs.pca.hcr) & PCA200E_HCR_OUTFULL)) { | ||
537 | DPRINTK(2,"FIFO OUT full, device %d\n", fore200e->atm_dev->number); | ||
538 | } | ||
539 | #endif | ||
540 | |||
541 | return irq_posted; | ||
542 | } | ||
543 | |||
544 | |||
545 | static void | ||
546 | fore200e_pca_irq_ack(struct fore200e* fore200e) | ||
547 | { | ||
548 | writel(PCA200E_HCR_CLRINTR, fore200e->regs.pca.hcr); | ||
549 | } | ||
550 | |||
551 | |||
552 | static void | ||
553 | fore200e_pca_reset(struct fore200e* fore200e) | ||
554 | { | ||
555 | writel(PCA200E_HCR_RESET, fore200e->regs.pca.hcr); | ||
556 | fore200e_spin(10); | ||
557 | writel(0, fore200e->regs.pca.hcr); | ||
558 | } | ||
559 | |||
560 | |||
561 | static int __init | ||
562 | fore200e_pca_map(struct fore200e* fore200e) | ||
563 | { | ||
564 | DPRINTK(2, "device %s being mapped in memory\n", fore200e->name); | ||
565 | |||
566 | fore200e->virt_base = ioremap(fore200e->phys_base, PCA200E_IOSPACE_LENGTH); | ||
567 | |||
568 | if (fore200e->virt_base == NULL) { | ||
569 | printk(FORE200E "can't map device %s\n", fore200e->name); | ||
570 | return -EFAULT; | ||
571 | } | ||
572 | |||
573 | DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); | ||
574 | |||
575 | /* gain access to the PCA specific registers */ | ||
576 | fore200e->regs.pca.hcr = fore200e->virt_base + PCA200E_HCR_OFFSET; | ||
577 | fore200e->regs.pca.imr = fore200e->virt_base + PCA200E_IMR_OFFSET; | ||
578 | fore200e->regs.pca.psr = fore200e->virt_base + PCA200E_PSR_OFFSET; | ||
579 | |||
580 | fore200e->state = FORE200E_STATE_MAP; | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | |||
585 | static void | ||
586 | fore200e_pca_unmap(struct fore200e* fore200e) | ||
587 | { | ||
588 | DPRINTK(2, "device %s being unmapped from memory\n", fore200e->name); | ||
589 | |||
590 | if (fore200e->virt_base != NULL) | ||
591 | iounmap(fore200e->virt_base); | ||
592 | } | ||
593 | |||
594 | |||
595 | static int __init | ||
596 | fore200e_pca_configure(struct fore200e* fore200e) | ||
597 | { | ||
598 | struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev; | ||
599 | u8 master_ctrl, latency; | ||
600 | |||
601 | DPRINTK(2, "device %s being configured\n", fore200e->name); | ||
602 | |||
603 | if ((pci_dev->irq == 0) || (pci_dev->irq == 0xFF)) { | ||
604 | printk(FORE200E "incorrect IRQ setting - misconfigured PCI-PCI bridge?\n"); | ||
605 | return -EIO; | ||
606 | } | ||
607 | |||
608 | pci_read_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, &master_ctrl); | ||
609 | |||
610 | master_ctrl = master_ctrl | ||
611 | #if defined(__BIG_ENDIAN) | ||
612 | /* request the PCA board to convert the endianess of slave RAM accesses */ | ||
613 | | PCA200E_CTRL_CONVERT_ENDIAN | ||
614 | #endif | ||
615 | #if 0 | ||
616 | | PCA200E_CTRL_DIS_CACHE_RD | ||
617 | | PCA200E_CTRL_DIS_WRT_INVAL | ||
618 | | PCA200E_CTRL_ENA_CONT_REQ_MODE | ||
619 | | PCA200E_CTRL_2_CACHE_WRT_INVAL | ||
620 | #endif | ||
621 | | PCA200E_CTRL_LARGE_PCI_BURSTS; | ||
622 | |||
623 | pci_write_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, master_ctrl); | ||
624 | |||
625 | /* raise latency from 32 (default) to 192, as this seems to prevent NIC | ||
626 | lockups (under heavy rx loads) due to continuous 'FIFO OUT full' condition. | ||
627 | this may impact the performances of other PCI devices on the same bus, though */ | ||
628 | latency = 192; | ||
629 | pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency); | ||
630 | |||
631 | fore200e->state = FORE200E_STATE_CONFIGURE; | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | |||
636 | static int __init | ||
637 | fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) | ||
638 | { | ||
639 | struct host_cmdq* cmdq = &fore200e->host_cmdq; | ||
640 | struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ]; | ||
641 | struct prom_opcode opcode; | ||
642 | int ok; | ||
643 | u32 prom_dma; | ||
644 | |||
645 | FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); | ||
646 | |||
647 | opcode.opcode = OPCODE_GET_PROM; | ||
648 | opcode.pad = 0; | ||
649 | |||
650 | prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), DMA_FROM_DEVICE); | ||
651 | |||
652 | fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr); | ||
653 | |||
654 | *entry->status = STATUS_PENDING; | ||
655 | |||
656 | fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.prom_block.opcode); | ||
657 | |||
658 | ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); | ||
659 | |||
660 | *entry->status = STATUS_FREE; | ||
661 | |||
662 | fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), DMA_FROM_DEVICE); | ||
663 | |||
664 | if (ok == 0) { | ||
665 | printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name); | ||
666 | return -EIO; | ||
667 | } | ||
668 | |||
669 | #if defined(__BIG_ENDIAN) | ||
670 | |||
671 | #define swap_here(addr) (*((u32*)(addr)) = swab32( *((u32*)(addr)) )) | ||
672 | |||
673 | /* MAC address is stored as little-endian */ | ||
674 | swap_here(&prom->mac_addr[0]); | ||
675 | swap_here(&prom->mac_addr[4]); | ||
676 | #endif | ||
677 | |||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | |||
682 | static int | ||
683 | fore200e_pca_proc_read(struct fore200e* fore200e, char *page) | ||
684 | { | ||
685 | struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev; | ||
686 | |||
687 | return sprintf(page, " PCI bus/slot/function:\t%d/%d/%d\n", | ||
688 | pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); | ||
689 | } | ||
690 | |||
691 | #endif /* CONFIG_ATM_FORE200E_PCA */ | ||
692 | |||
693 | |||
694 | #ifdef CONFIG_ATM_FORE200E_SBA | ||
695 | |||
696 | static u32 | ||
697 | fore200e_sba_read(volatile u32 __iomem *addr) | ||
698 | { | ||
699 | return sbus_readl(addr); | ||
700 | } | ||
701 | |||
702 | |||
703 | static void | ||
704 | fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | ||
705 | { | ||
706 | sbus_writel(val, addr); | ||
707 | } | ||
708 | |||
709 | |||
710 | static u32 | ||
711 | fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) | ||
712 | { | ||
713 | u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction); | ||
714 | |||
715 | DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", | ||
716 | virt_addr, size, direction, dma_addr); | ||
717 | |||
718 | return dma_addr; | ||
719 | } | ||
720 | |||
721 | |||
722 | static void | ||
723 | fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
724 | { | ||
725 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", | ||
726 | dma_addr, size, direction); | ||
727 | |||
728 | sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
729 | } | ||
730 | |||
731 | |||
732 | static void | ||
733 | fore200e_sba_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
734 | { | ||
735 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
736 | |||
737 | sbus_dma_sync_single_for_cpu((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
738 | } | ||
739 | |||
740 | static void | ||
741 | fore200e_sba_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
742 | { | ||
743 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
744 | |||
745 | sbus_dma_sync_single_for_device((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
746 | } | ||
747 | |||
748 | |||
749 | /* allocate a DVMA consistent chunk of memory intended to act as a communication mechanism | ||
750 | (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */ | ||
751 | |||
752 | static int | ||
753 | fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, | ||
754 | int size, int nbr, int alignment) | ||
755 | { | ||
756 | chunk->alloc_size = chunk->align_size = size * nbr; | ||
757 | |||
758 | /* returned chunks are page-aligned */ | ||
759 | chunk->alloc_addr = sbus_alloc_consistent((struct sbus_dev*)fore200e->bus_dev, | ||
760 | chunk->alloc_size, | ||
761 | &chunk->dma_addr); | ||
762 | |||
763 | if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) | ||
764 | return -ENOMEM; | ||
765 | |||
766 | chunk->align_addr = chunk->alloc_addr; | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | |||
772 | /* free a DVMA consistent chunk of memory */ | ||
773 | |||
774 | static void | ||
775 | fore200e_sba_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) | ||
776 | { | ||
777 | sbus_free_consistent((struct sbus_dev*)fore200e->bus_dev, | ||
778 | chunk->alloc_size, | ||
779 | chunk->alloc_addr, | ||
780 | chunk->dma_addr); | ||
781 | } | ||
782 | |||
783 | |||
784 | static void | ||
785 | fore200e_sba_irq_enable(struct fore200e* fore200e) | ||
786 | { | ||
787 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; | ||
788 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr); | ||
789 | } | ||
790 | |||
791 | |||
792 | static int | ||
793 | fore200e_sba_irq_check(struct fore200e* fore200e) | ||
794 | { | ||
795 | return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ; | ||
796 | } | ||
797 | |||
798 | |||
799 | static void | ||
800 | fore200e_sba_irq_ack(struct fore200e* fore200e) | ||
801 | { | ||
802 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; | ||
803 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr); | ||
804 | } | ||
805 | |||
806 | |||
807 | static void | ||
808 | fore200e_sba_reset(struct fore200e* fore200e) | ||
809 | { | ||
810 | fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr); | ||
811 | fore200e_spin(10); | ||
812 | fore200e->bus->write(0, fore200e->regs.sba.hcr); | ||
813 | } | ||
814 | |||
815 | |||
816 | static int __init | ||
817 | fore200e_sba_map(struct fore200e* fore200e) | ||
818 | { | ||
819 | struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev; | ||
820 | unsigned int bursts; | ||
821 | |||
822 | /* gain access to the SBA specific registers */ | ||
823 | fore200e->regs.sba.hcr = sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); | ||
824 | fore200e->regs.sba.bsr = sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); | ||
825 | fore200e->regs.sba.isr = sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); | ||
826 | fore200e->virt_base = sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); | ||
827 | |||
828 | if (fore200e->virt_base == NULL) { | ||
829 | printk(FORE200E "unable to map RAM of device %s\n", fore200e->name); | ||
830 | return -EFAULT; | ||
831 | } | ||
832 | |||
833 | DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); | ||
834 | |||
835 | fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */ | ||
836 | |||
837 | /* get the supported DVMA burst sizes */ | ||
838 | bursts = prom_getintdefault(sbus_dev->bus->prom_node, "burst-sizes", 0x00); | ||
839 | |||
840 | if (sbus_can_dma_64bit(sbus_dev)) | ||
841 | sbus_set_sbus64(sbus_dev, bursts); | ||
842 | |||
843 | fore200e->state = FORE200E_STATE_MAP; | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | |||
848 | static void | ||
849 | fore200e_sba_unmap(struct fore200e* fore200e) | ||
850 | { | ||
851 | sbus_iounmap(fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | ||
852 | sbus_iounmap(fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | ||
853 | sbus_iounmap(fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); | ||
854 | sbus_iounmap(fore200e->virt_base, SBA200E_RAM_LENGTH); | ||
855 | } | ||
856 | |||
857 | |||
858 | static int __init | ||
859 | fore200e_sba_configure(struct fore200e* fore200e) | ||
860 | { | ||
861 | fore200e->state = FORE200E_STATE_CONFIGURE; | ||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | |||
866 | static struct fore200e* __init | ||
867 | fore200e_sba_detect(const struct fore200e_bus* bus, int index) | ||
868 | { | ||
869 | struct fore200e* fore200e; | ||
870 | struct sbus_bus* sbus_bus; | ||
871 | struct sbus_dev* sbus_dev = NULL; | ||
872 | |||
873 | unsigned int count = 0; | ||
874 | |||
875 | for_each_sbus (sbus_bus) { | ||
876 | for_each_sbusdev (sbus_dev, sbus_bus) { | ||
877 | if (strcmp(sbus_dev->prom_name, SBA200E_PROM_NAME) == 0) { | ||
878 | if (count >= index) | ||
879 | goto found; | ||
880 | count++; | ||
881 | } | ||
882 | } | ||
883 | } | ||
884 | return NULL; | ||
885 | |||
886 | found: | ||
887 | if (sbus_dev->num_registers != 4) { | ||
888 | printk(FORE200E "this %s device has %d instead of 4 registers\n", | ||
889 | bus->model_name, sbus_dev->num_registers); | ||
890 | return NULL; | ||
891 | } | ||
892 | |||
893 | fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL); | ||
894 | if (fore200e == NULL) | ||
895 | return NULL; | ||
896 | |||
897 | fore200e->bus = bus; | ||
898 | fore200e->bus_dev = sbus_dev; | ||
899 | fore200e->irq = sbus_dev->irqs[ 0 ]; | ||
900 | |||
901 | fore200e->phys_base = (unsigned long)sbus_dev; | ||
902 | |||
903 | sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1); | ||
904 | |||
905 | return fore200e; | ||
906 | } | ||
907 | |||
908 | |||
909 | static int __init | ||
910 | fore200e_sba_prom_read(struct fore200e* fore200e, struct prom_data* prom) | ||
911 | { | ||
912 | struct sbus_dev* sbus_dev = (struct sbus_dev*) fore200e->bus_dev; | ||
913 | int len; | ||
914 | |||
915 | len = prom_getproperty(sbus_dev->prom_node, "macaddrlo2", &prom->mac_addr[ 4 ], 4); | ||
916 | if (len < 0) | ||
917 | return -EBUSY; | ||
918 | |||
919 | len = prom_getproperty(sbus_dev->prom_node, "macaddrhi4", &prom->mac_addr[ 2 ], 4); | ||
920 | if (len < 0) | ||
921 | return -EBUSY; | ||
922 | |||
923 | prom_getproperty(sbus_dev->prom_node, "serialnumber", | ||
924 | (char*)&prom->serial_number, sizeof(prom->serial_number)); | ||
925 | |||
926 | prom_getproperty(sbus_dev->prom_node, "promversion", | ||
927 | (char*)&prom->hw_revision, sizeof(prom->hw_revision)); | ||
928 | |||
929 | return 0; | ||
930 | } | ||
931 | |||
932 | |||
933 | static int | ||
934 | fore200e_sba_proc_read(struct fore200e* fore200e, char *page) | ||
935 | { | ||
936 | struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev; | ||
937 | |||
938 | return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name); | ||
939 | } | ||
940 | #endif /* CONFIG_ATM_FORE200E_SBA */ | ||
941 | |||
942 | |||
943 | static void | ||
944 | fore200e_tx_irq(struct fore200e* fore200e) | ||
945 | { | ||
946 | struct host_txq* txq = &fore200e->host_txq; | ||
947 | struct host_txq_entry* entry; | ||
948 | struct atm_vcc* vcc; | ||
949 | struct fore200e_vc_map* vc_map; | ||
950 | |||
951 | if (fore200e->host_txq.txing == 0) | ||
952 | return; | ||
953 | |||
954 | for (;;) { | ||
955 | |||
956 | entry = &txq->host_entry[ txq->tail ]; | ||
957 | |||
958 | if ((*entry->status & STATUS_COMPLETE) == 0) { | ||
959 | break; | ||
960 | } | ||
961 | |||
962 | DPRINTK(3, "TX COMPLETED: entry = %p [tail = %d], vc_map = %p, skb = %p\n", | ||
963 | entry, txq->tail, entry->vc_map, entry->skb); | ||
964 | |||
965 | /* free copy of misaligned data */ | ||
966 | if (entry->data) | ||
967 | kfree(entry->data); | ||
968 | |||
969 | /* remove DMA mapping */ | ||
970 | fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length, | ||
971 | DMA_TO_DEVICE); | ||
972 | |||
973 | vc_map = entry->vc_map; | ||
974 | |||
975 | /* vcc closed since the time the entry was submitted for tx? */ | ||
976 | if ((vc_map->vcc == NULL) || | ||
977 | (test_bit(ATM_VF_READY, &vc_map->vcc->flags) == 0)) { | ||
978 | |||
979 | DPRINTK(1, "no ready vcc found for PDU sent on device %d\n", | ||
980 | fore200e->atm_dev->number); | ||
981 | |||
982 | dev_kfree_skb_any(entry->skb); | ||
983 | } | ||
984 | else { | ||
985 | ASSERT(vc_map->vcc); | ||
986 | |||
987 | /* vcc closed then immediately re-opened? */ | ||
988 | if (vc_map->incarn != entry->incarn) { | ||
989 | |||
990 | /* when a vcc is closed, some PDUs may be still pending in the tx queue. | ||
991 | if the same vcc is immediately re-opened, those pending PDUs must | ||
992 | not be popped after the completion of their emission, as they refer | ||
993 | to the prior incarnation of that vcc. otherwise, sk_atm(vcc)->sk_wmem_alloc | ||
994 | would be decremented by the size of the (unrelated) skb, possibly | ||
995 | leading to a negative sk->sk_wmem_alloc count, ultimately freezing the vcc. | ||
996 | we thus bind the tx entry to the current incarnation of the vcc | ||
997 | when the entry is submitted for tx. When the tx later completes, | ||
998 | if the incarnation number of the tx entry does not match the one | ||
999 | of the vcc, then this implies that the vcc has been closed then re-opened. | ||
1000 | we thus just drop the skb here. */ | ||
1001 | |||
1002 | DPRINTK(1, "vcc closed-then-re-opened; dropping PDU sent on device %d\n", | ||
1003 | fore200e->atm_dev->number); | ||
1004 | |||
1005 | dev_kfree_skb_any(entry->skb); | ||
1006 | } | ||
1007 | else { | ||
1008 | vcc = vc_map->vcc; | ||
1009 | ASSERT(vcc); | ||
1010 | |||
1011 | /* notify tx completion */ | ||
1012 | if (vcc->pop) { | ||
1013 | vcc->pop(vcc, entry->skb); | ||
1014 | } | ||
1015 | else { | ||
1016 | dev_kfree_skb_any(entry->skb); | ||
1017 | } | ||
1018 | #if 1 | ||
1019 | /* race fixed by the above incarnation mechanism, but... */ | ||
1020 | if (atomic_read(&sk_atm(vcc)->sk_wmem_alloc) < 0) { | ||
1021 | atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 0); | ||
1022 | } | ||
1023 | #endif | ||
1024 | /* check error condition */ | ||
1025 | if (*entry->status & STATUS_ERROR) | ||
1026 | atomic_inc(&vcc->stats->tx_err); | ||
1027 | else | ||
1028 | atomic_inc(&vcc->stats->tx); | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | *entry->status = STATUS_FREE; | ||
1033 | |||
1034 | fore200e->host_txq.txing--; | ||
1035 | |||
1036 | FORE200E_NEXT_ENTRY(txq->tail, QUEUE_SIZE_TX); | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | #ifdef FORE200E_BSQ_DEBUG | ||
1042 | int bsq_audit(int where, struct host_bsq* bsq, int scheme, int magn) | ||
1043 | { | ||
1044 | struct buffer* buffer; | ||
1045 | int count = 0; | ||
1046 | |||
1047 | buffer = bsq->freebuf; | ||
1048 | while (buffer) { | ||
1049 | |||
1050 | if (buffer->supplied) { | ||
1051 | printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld supplied but in free list!\n", | ||
1052 | where, scheme, magn, buffer->index); | ||
1053 | } | ||
1054 | |||
1055 | if (buffer->magn != magn) { | ||
1056 | printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected magn = %d\n", | ||
1057 | where, scheme, magn, buffer->index, buffer->magn); | ||
1058 | } | ||
1059 | |||
1060 | if (buffer->scheme != scheme) { | ||
1061 | printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected scheme = %d\n", | ||
1062 | where, scheme, magn, buffer->index, buffer->scheme); | ||
1063 | } | ||
1064 | |||
1065 | if ((buffer->index < 0) || (buffer->index >= fore200e_rx_buf_nbr[ scheme ][ magn ])) { | ||
1066 | printk(FORE200E "bsq_audit(%d): queue %d.%d, out of range buffer index = %ld !\n", | ||
1067 | where, scheme, magn, buffer->index); | ||
1068 | } | ||
1069 | |||
1070 | count++; | ||
1071 | buffer = buffer->next; | ||
1072 | } | ||
1073 | |||
1074 | if (count != bsq->freebuf_count) { | ||
1075 | printk(FORE200E "bsq_audit(%d): queue %d.%d, %d bufs in free list, but freebuf_count = %d\n", | ||
1076 | where, scheme, magn, count, bsq->freebuf_count); | ||
1077 | } | ||
1078 | return 0; | ||
1079 | } | ||
1080 | #endif | ||
1081 | |||
1082 | |||
1083 | static void | ||
1084 | fore200e_supply(struct fore200e* fore200e) | ||
1085 | { | ||
1086 | int scheme, magn, i; | ||
1087 | |||
1088 | struct host_bsq* bsq; | ||
1089 | struct host_bsq_entry* entry; | ||
1090 | struct buffer* buffer; | ||
1091 | |||
1092 | for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) { | ||
1093 | for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) { | ||
1094 | |||
1095 | bsq = &fore200e->host_bsq[ scheme ][ magn ]; | ||
1096 | |||
1097 | #ifdef FORE200E_BSQ_DEBUG | ||
1098 | bsq_audit(1, bsq, scheme, magn); | ||
1099 | #endif | ||
1100 | while (bsq->freebuf_count >= RBD_BLK_SIZE) { | ||
1101 | |||
1102 | DPRINTK(2, "supplying %d rx buffers to queue %d / %d, freebuf_count = %d\n", | ||
1103 | RBD_BLK_SIZE, scheme, magn, bsq->freebuf_count); | ||
1104 | |||
1105 | entry = &bsq->host_entry[ bsq->head ]; | ||
1106 | |||
1107 | for (i = 0; i < RBD_BLK_SIZE; i++) { | ||
1108 | |||
1109 | /* take the first buffer in the free buffer list */ | ||
1110 | buffer = bsq->freebuf; | ||
1111 | if (!buffer) { | ||
1112 | printk(FORE200E "no more free bufs in queue %d.%d, but freebuf_count = %d\n", | ||
1113 | scheme, magn, bsq->freebuf_count); | ||
1114 | return; | ||
1115 | } | ||
1116 | bsq->freebuf = buffer->next; | ||
1117 | |||
1118 | #ifdef FORE200E_BSQ_DEBUG | ||
1119 | if (buffer->supplied) | ||
1120 | printk(FORE200E "queue %d.%d, buffer %lu already supplied\n", | ||
1121 | scheme, magn, buffer->index); | ||
1122 | buffer->supplied = 1; | ||
1123 | #endif | ||
1124 | entry->rbd_block->rbd[ i ].buffer_haddr = buffer->data.dma_addr; | ||
1125 | entry->rbd_block->rbd[ i ].handle = FORE200E_BUF2HDL(buffer); | ||
1126 | } | ||
1127 | |||
1128 | FORE200E_NEXT_ENTRY(bsq->head, QUEUE_SIZE_BS); | ||
1129 | |||
1130 | /* decrease accordingly the number of free rx buffers */ | ||
1131 | bsq->freebuf_count -= RBD_BLK_SIZE; | ||
1132 | |||
1133 | *entry->status = STATUS_PENDING; | ||
1134 | fore200e->bus->write(entry->rbd_block_dma, &entry->cp_entry->rbd_block_haddr); | ||
1135 | } | ||
1136 | } | ||
1137 | } | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | static int | ||
1142 | fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rpd) | ||
1143 | { | ||
1144 | struct sk_buff* skb; | ||
1145 | struct buffer* buffer; | ||
1146 | struct fore200e_vcc* fore200e_vcc; | ||
1147 | int i, pdu_len = 0; | ||
1148 | #ifdef FORE200E_52BYTE_AAL0_SDU | ||
1149 | u32 cell_header = 0; | ||
1150 | #endif | ||
1151 | |||
1152 | ASSERT(vcc); | ||
1153 | |||
1154 | fore200e_vcc = FORE200E_VCC(vcc); | ||
1155 | ASSERT(fore200e_vcc); | ||
1156 | |||
1157 | #ifdef FORE200E_52BYTE_AAL0_SDU | ||
1158 | if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.rxtp.max_sdu == ATM_AAL0_SDU)) { | ||
1159 | |||
1160 | cell_header = (rpd->atm_header.gfc << ATM_HDR_GFC_SHIFT) | | ||
1161 | (rpd->atm_header.vpi << ATM_HDR_VPI_SHIFT) | | ||
1162 | (rpd->atm_header.vci << ATM_HDR_VCI_SHIFT) | | ||
1163 | (rpd->atm_header.plt << ATM_HDR_PTI_SHIFT) | | ||
1164 | rpd->atm_header.clp; | ||
1165 | pdu_len = 4; | ||
1166 | } | ||
1167 | #endif | ||
1168 | |||
1169 | /* compute total PDU length */ | ||
1170 | for (i = 0; i < rpd->nseg; i++) | ||
1171 | pdu_len += rpd->rsd[ i ].length; | ||
1172 | |||
1173 | skb = alloc_skb(pdu_len, GFP_ATOMIC); | ||
1174 | if (skb == NULL) { | ||
1175 | DPRINTK(2, "unable to alloc new skb, rx PDU length = %d\n", pdu_len); | ||
1176 | |||
1177 | atomic_inc(&vcc->stats->rx_drop); | ||
1178 | return -ENOMEM; | ||
1179 | } | ||
1180 | |||
1181 | do_gettimeofday(&skb->stamp); | ||
1182 | |||
1183 | #ifdef FORE200E_52BYTE_AAL0_SDU | ||
1184 | if (cell_header) { | ||
1185 | *((u32*)skb_put(skb, 4)) = cell_header; | ||
1186 | } | ||
1187 | #endif | ||
1188 | |||
1189 | /* reassemble segments */ | ||
1190 | for (i = 0; i < rpd->nseg; i++) { | ||
1191 | |||
1192 | /* rebuild rx buffer address from rsd handle */ | ||
1193 | buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle); | ||
1194 | |||
1195 | /* Make device DMA transfer visible to CPU. */ | ||
1196 | fore200e->bus->dma_sync_for_cpu(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, DMA_FROM_DEVICE); | ||
1197 | |||
1198 | memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length); | ||
1199 | |||
1200 | /* Now let the device get at it again. */ | ||
1201 | fore200e->bus->dma_sync_for_device(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, DMA_FROM_DEVICE); | ||
1202 | } | ||
1203 | |||
1204 | DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize); | ||
1205 | |||
1206 | if (pdu_len < fore200e_vcc->rx_min_pdu) | ||
1207 | fore200e_vcc->rx_min_pdu = pdu_len; | ||
1208 | if (pdu_len > fore200e_vcc->rx_max_pdu) | ||
1209 | fore200e_vcc->rx_max_pdu = pdu_len; | ||
1210 | fore200e_vcc->rx_pdu++; | ||
1211 | |||
1212 | /* push PDU */ | ||
1213 | if (atm_charge(vcc, skb->truesize) == 0) { | ||
1214 | |||
1215 | DPRINTK(2, "receive buffers saturated for %d.%d.%d - PDU dropped\n", | ||
1216 | vcc->itf, vcc->vpi, vcc->vci); | ||
1217 | |||
1218 | dev_kfree_skb_any(skb); | ||
1219 | |||
1220 | atomic_inc(&vcc->stats->rx_drop); | ||
1221 | return -ENOMEM; | ||
1222 | } | ||
1223 | |||
1224 | ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0); | ||
1225 | |||
1226 | vcc->push(vcc, skb); | ||
1227 | atomic_inc(&vcc->stats->rx); | ||
1228 | |||
1229 | ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0); | ||
1230 | |||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | |||
1235 | static void | ||
1236 | fore200e_collect_rpd(struct fore200e* fore200e, struct rpd* rpd) | ||
1237 | { | ||
1238 | struct host_bsq* bsq; | ||
1239 | struct buffer* buffer; | ||
1240 | int i; | ||
1241 | |||
1242 | for (i = 0; i < rpd->nseg; i++) { | ||
1243 | |||
1244 | /* rebuild rx buffer address from rsd handle */ | ||
1245 | buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle); | ||
1246 | |||
1247 | bsq = &fore200e->host_bsq[ buffer->scheme ][ buffer->magn ]; | ||
1248 | |||
1249 | #ifdef FORE200E_BSQ_DEBUG | ||
1250 | bsq_audit(2, bsq, buffer->scheme, buffer->magn); | ||
1251 | |||
1252 | if (buffer->supplied == 0) | ||
1253 | printk(FORE200E "queue %d.%d, buffer %ld was not supplied\n", | ||
1254 | buffer->scheme, buffer->magn, buffer->index); | ||
1255 | buffer->supplied = 0; | ||
1256 | #endif | ||
1257 | |||
1258 | /* re-insert the buffer into the free buffer list */ | ||
1259 | buffer->next = bsq->freebuf; | ||
1260 | bsq->freebuf = buffer; | ||
1261 | |||
1262 | /* then increment the number of free rx buffers */ | ||
1263 | bsq->freebuf_count++; | ||
1264 | } | ||
1265 | } | ||
1266 | |||
1267 | |||
1268 | static void | ||
1269 | fore200e_rx_irq(struct fore200e* fore200e) | ||
1270 | { | ||
1271 | struct host_rxq* rxq = &fore200e->host_rxq; | ||
1272 | struct host_rxq_entry* entry; | ||
1273 | struct atm_vcc* vcc; | ||
1274 | struct fore200e_vc_map* vc_map; | ||
1275 | |||
1276 | for (;;) { | ||
1277 | |||
1278 | entry = &rxq->host_entry[ rxq->head ]; | ||
1279 | |||
1280 | /* no more received PDUs */ | ||
1281 | if ((*entry->status & STATUS_COMPLETE) == 0) | ||
1282 | break; | ||
1283 | |||
1284 | vc_map = FORE200E_VC_MAP(fore200e, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci); | ||
1285 | |||
1286 | if ((vc_map->vcc == NULL) || | ||
1287 | (test_bit(ATM_VF_READY, &vc_map->vcc->flags) == 0)) { | ||
1288 | |||
1289 | DPRINTK(1, "no ready VC found for PDU received on %d.%d.%d\n", | ||
1290 | fore200e->atm_dev->number, | ||
1291 | entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci); | ||
1292 | } | ||
1293 | else { | ||
1294 | vcc = vc_map->vcc; | ||
1295 | ASSERT(vcc); | ||
1296 | |||
1297 | if ((*entry->status & STATUS_ERROR) == 0) { | ||
1298 | |||
1299 | fore200e_push_rpd(fore200e, vcc, entry->rpd); | ||
1300 | } | ||
1301 | else { | ||
1302 | DPRINTK(2, "damaged PDU on %d.%d.%d\n", | ||
1303 | fore200e->atm_dev->number, | ||
1304 | entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci); | ||
1305 | atomic_inc(&vcc->stats->rx_err); | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | FORE200E_NEXT_ENTRY(rxq->head, QUEUE_SIZE_RX); | ||
1310 | |||
1311 | fore200e_collect_rpd(fore200e, entry->rpd); | ||
1312 | |||
1313 | /* rewrite the rpd address to ack the received PDU */ | ||
1314 | fore200e->bus->write(entry->rpd_dma, &entry->cp_entry->rpd_haddr); | ||
1315 | *entry->status = STATUS_FREE; | ||
1316 | |||
1317 | fore200e_supply(fore200e); | ||
1318 | } | ||
1319 | } | ||
1320 | |||
1321 | |||
1322 | #ifndef FORE200E_USE_TASKLET | ||
1323 | static void | ||
1324 | fore200e_irq(struct fore200e* fore200e) | ||
1325 | { | ||
1326 | unsigned long flags; | ||
1327 | |||
1328 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1329 | fore200e_rx_irq(fore200e); | ||
1330 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1331 | |||
1332 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1333 | fore200e_tx_irq(fore200e); | ||
1334 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1335 | } | ||
1336 | #endif | ||
1337 | |||
1338 | |||
1339 | static irqreturn_t | ||
1340 | fore200e_interrupt(int irq, void* dev, struct pt_regs* regs) | ||
1341 | { | ||
1342 | struct fore200e* fore200e = FORE200E_DEV((struct atm_dev*)dev); | ||
1343 | |||
1344 | if (fore200e->bus->irq_check(fore200e) == 0) { | ||
1345 | |||
1346 | DPRINTK(3, "interrupt NOT triggered by device %d\n", fore200e->atm_dev->number); | ||
1347 | return IRQ_NONE; | ||
1348 | } | ||
1349 | DPRINTK(3, "interrupt triggered by device %d\n", fore200e->atm_dev->number); | ||
1350 | |||
1351 | #ifdef FORE200E_USE_TASKLET | ||
1352 | tasklet_schedule(&fore200e->tx_tasklet); | ||
1353 | tasklet_schedule(&fore200e->rx_tasklet); | ||
1354 | #else | ||
1355 | fore200e_irq(fore200e); | ||
1356 | #endif | ||
1357 | |||
1358 | fore200e->bus->irq_ack(fore200e); | ||
1359 | return IRQ_HANDLED; | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | #ifdef FORE200E_USE_TASKLET | ||
1364 | static void | ||
1365 | fore200e_tx_tasklet(unsigned long data) | ||
1366 | { | ||
1367 | struct fore200e* fore200e = (struct fore200e*) data; | ||
1368 | unsigned long flags; | ||
1369 | |||
1370 | DPRINTK(3, "tx tasklet scheduled for device %d\n", fore200e->atm_dev->number); | ||
1371 | |||
1372 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1373 | fore200e_tx_irq(fore200e); | ||
1374 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | static void | ||
1379 | fore200e_rx_tasklet(unsigned long data) | ||
1380 | { | ||
1381 | struct fore200e* fore200e = (struct fore200e*) data; | ||
1382 | unsigned long flags; | ||
1383 | |||
1384 | DPRINTK(3, "rx tasklet scheduled for device %d\n", fore200e->atm_dev->number); | ||
1385 | |||
1386 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1387 | fore200e_rx_irq((struct fore200e*) data); | ||
1388 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1389 | } | ||
1390 | #endif | ||
1391 | |||
1392 | |||
1393 | static int | ||
1394 | fore200e_select_scheme(struct atm_vcc* vcc) | ||
1395 | { | ||
1396 | /* fairly balance the VCs over (identical) buffer schemes */ | ||
1397 | int scheme = vcc->vci % 2 ? BUFFER_SCHEME_ONE : BUFFER_SCHEME_TWO; | ||
1398 | |||
1399 | DPRINTK(1, "VC %d.%d.%d uses buffer scheme %d\n", | ||
1400 | vcc->itf, vcc->vpi, vcc->vci, scheme); | ||
1401 | |||
1402 | return scheme; | ||
1403 | } | ||
1404 | |||
1405 | |||
1406 | static int | ||
1407 | fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc* vcc, int mtu) | ||
1408 | { | ||
1409 | struct host_cmdq* cmdq = &fore200e->host_cmdq; | ||
1410 | struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ]; | ||
1411 | struct activate_opcode activ_opcode; | ||
1412 | struct deactivate_opcode deactiv_opcode; | ||
1413 | struct vpvc vpvc; | ||
1414 | int ok; | ||
1415 | enum fore200e_aal aal = fore200e_atm2fore_aal(vcc->qos.aal); | ||
1416 | |||
1417 | FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); | ||
1418 | |||
1419 | if (activate) { | ||
1420 | FORE200E_VCC(vcc)->scheme = fore200e_select_scheme(vcc); | ||
1421 | |||
1422 | activ_opcode.opcode = OPCODE_ACTIVATE_VCIN; | ||
1423 | activ_opcode.aal = aal; | ||
1424 | activ_opcode.scheme = FORE200E_VCC(vcc)->scheme; | ||
1425 | activ_opcode.pad = 0; | ||
1426 | } | ||
1427 | else { | ||
1428 | deactiv_opcode.opcode = OPCODE_DEACTIVATE_VCIN; | ||
1429 | deactiv_opcode.pad = 0; | ||
1430 | } | ||
1431 | |||
1432 | vpvc.vci = vcc->vci; | ||
1433 | vpvc.vpi = vcc->vpi; | ||
1434 | |||
1435 | *entry->status = STATUS_PENDING; | ||
1436 | |||
1437 | if (activate) { | ||
1438 | |||
1439 | #ifdef FORE200E_52BYTE_AAL0_SDU | ||
1440 | mtu = 48; | ||
1441 | #endif | ||
1442 | /* the MTU is not used by the cp, except in the case of AAL0 */ | ||
1443 | fore200e->bus->write(mtu, &entry->cp_entry->cmd.activate_block.mtu); | ||
1444 | fore200e->bus->write(*(u32*)&vpvc, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.vpvc); | ||
1445 | fore200e->bus->write(*(u32*)&activ_opcode, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.opcode); | ||
1446 | } | ||
1447 | else { | ||
1448 | fore200e->bus->write(*(u32*)&vpvc, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.vpvc); | ||
1449 | fore200e->bus->write(*(u32*)&deactiv_opcode, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.opcode); | ||
1450 | } | ||
1451 | |||
1452 | ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); | ||
1453 | |||
1454 | *entry->status = STATUS_FREE; | ||
1455 | |||
1456 | if (ok == 0) { | ||
1457 | printk(FORE200E "unable to %s VC %d.%d.%d\n", | ||
1458 | activate ? "open" : "close", vcc->itf, vcc->vpi, vcc->vci); | ||
1459 | return -EIO; | ||
1460 | } | ||
1461 | |||
1462 | DPRINTK(1, "VC %d.%d.%d %sed\n", vcc->itf, vcc->vpi, vcc->vci, | ||
1463 | activate ? "open" : "clos"); | ||
1464 | |||
1465 | return 0; | ||
1466 | } | ||
1467 | |||
1468 | |||
1469 | #define FORE200E_MAX_BACK2BACK_CELLS 255 /* XXX depends on CDVT */ | ||
1470 | |||
1471 | static void | ||
1472 | fore200e_rate_ctrl(struct atm_qos* qos, struct tpd_rate* rate) | ||
1473 | { | ||
1474 | if (qos->txtp.max_pcr < ATM_OC3_PCR) { | ||
1475 | |||
1476 | /* compute the data cells to idle cells ratio from the tx PCR */ | ||
1477 | rate->data_cells = qos->txtp.max_pcr * FORE200E_MAX_BACK2BACK_CELLS / ATM_OC3_PCR; | ||
1478 | rate->idle_cells = FORE200E_MAX_BACK2BACK_CELLS - rate->data_cells; | ||
1479 | } | ||
1480 | else { | ||
1481 | /* disable rate control */ | ||
1482 | rate->data_cells = rate->idle_cells = 0; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1486 | |||
1487 | static int | ||
1488 | fore200e_open(struct atm_vcc *vcc) | ||
1489 | { | ||
1490 | struct fore200e* fore200e = FORE200E_DEV(vcc->dev); | ||
1491 | struct fore200e_vcc* fore200e_vcc; | ||
1492 | struct fore200e_vc_map* vc_map; | ||
1493 | unsigned long flags; | ||
1494 | int vci = vcc->vci; | ||
1495 | short vpi = vcc->vpi; | ||
1496 | |||
1497 | ASSERT((vpi >= 0) && (vpi < 1<<FORE200E_VPI_BITS)); | ||
1498 | ASSERT((vci >= 0) && (vci < 1<<FORE200E_VCI_BITS)); | ||
1499 | |||
1500 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1501 | |||
1502 | vc_map = FORE200E_VC_MAP(fore200e, vpi, vci); | ||
1503 | if (vc_map->vcc) { | ||
1504 | |||
1505 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1506 | |||
1507 | printk(FORE200E "VC %d.%d.%d already in use\n", | ||
1508 | fore200e->atm_dev->number, vpi, vci); | ||
1509 | |||
1510 | return -EINVAL; | ||
1511 | } | ||
1512 | |||
1513 | vc_map->vcc = vcc; | ||
1514 | |||
1515 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1516 | |||
1517 | fore200e_vcc = fore200e_kmalloc(sizeof(struct fore200e_vcc), GFP_ATOMIC); | ||
1518 | if (fore200e_vcc == NULL) { | ||
1519 | vc_map->vcc = NULL; | ||
1520 | return -ENOMEM; | ||
1521 | } | ||
1522 | |||
1523 | DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; " | ||
1524 | "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d)\n", | ||
1525 | vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal), | ||
1526 | fore200e_traffic_class[ vcc->qos.txtp.traffic_class ], | ||
1527 | vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_cdv, vcc->qos.txtp.max_sdu, | ||
1528 | fore200e_traffic_class[ vcc->qos.rxtp.traffic_class ], | ||
1529 | vcc->qos.rxtp.min_pcr, vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_cdv, vcc->qos.rxtp.max_sdu); | ||
1530 | |||
1531 | /* pseudo-CBR bandwidth requested? */ | ||
1532 | if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) { | ||
1533 | |||
1534 | down(&fore200e->rate_sf); | ||
1535 | if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) { | ||
1536 | up(&fore200e->rate_sf); | ||
1537 | |||
1538 | fore200e_kfree(fore200e_vcc); | ||
1539 | vc_map->vcc = NULL; | ||
1540 | return -EAGAIN; | ||
1541 | } | ||
1542 | |||
1543 | /* reserve bandwidth */ | ||
1544 | fore200e->available_cell_rate -= vcc->qos.txtp.max_pcr; | ||
1545 | up(&fore200e->rate_sf); | ||
1546 | } | ||
1547 | |||
1548 | vcc->itf = vcc->dev->number; | ||
1549 | |||
1550 | set_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1551 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
1552 | |||
1553 | vcc->dev_data = fore200e_vcc; | ||
1554 | |||
1555 | if (fore200e_activate_vcin(fore200e, 1, vcc, vcc->qos.rxtp.max_sdu) < 0) { | ||
1556 | |||
1557 | vc_map->vcc = NULL; | ||
1558 | |||
1559 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
1560 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1561 | |||
1562 | vcc->dev_data = NULL; | ||
1563 | |||
1564 | fore200e->available_cell_rate += vcc->qos.txtp.max_pcr; | ||
1565 | |||
1566 | fore200e_kfree(fore200e_vcc); | ||
1567 | return -EINVAL; | ||
1568 | } | ||
1569 | |||
1570 | /* compute rate control parameters */ | ||
1571 | if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) { | ||
1572 | |||
1573 | fore200e_rate_ctrl(&vcc->qos, &fore200e_vcc->rate); | ||
1574 | set_bit(ATM_VF_HASQOS, &vcc->flags); | ||
1575 | |||
1576 | DPRINTK(3, "tx on %d.%d.%d:%d, tx PCR = %d, rx PCR = %d, data_cells = %u, idle_cells = %u\n", | ||
1577 | vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal), | ||
1578 | vcc->qos.txtp.max_pcr, vcc->qos.rxtp.max_pcr, | ||
1579 | fore200e_vcc->rate.data_cells, fore200e_vcc->rate.idle_cells); | ||
1580 | } | ||
1581 | |||
1582 | fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = MAX_PDU_SIZE + 1; | ||
1583 | fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0; | ||
1584 | fore200e_vcc->tx_pdu = fore200e_vcc->rx_pdu = 0; | ||
1585 | |||
1586 | /* new incarnation of the vcc */ | ||
1587 | vc_map->incarn = ++fore200e->incarn_count; | ||
1588 | |||
1589 | /* VC unusable before this flag is set */ | ||
1590 | set_bit(ATM_VF_READY, &vcc->flags); | ||
1591 | |||
1592 | return 0; | ||
1593 | } | ||
1594 | |||
1595 | |||
1596 | static void | ||
1597 | fore200e_close(struct atm_vcc* vcc) | ||
1598 | { | ||
1599 | struct fore200e* fore200e = FORE200E_DEV(vcc->dev); | ||
1600 | struct fore200e_vcc* fore200e_vcc; | ||
1601 | struct fore200e_vc_map* vc_map; | ||
1602 | unsigned long flags; | ||
1603 | |||
1604 | ASSERT(vcc); | ||
1605 | ASSERT((vcc->vpi >= 0) && (vcc->vpi < 1<<FORE200E_VPI_BITS)); | ||
1606 | ASSERT((vcc->vci >= 0) && (vcc->vci < 1<<FORE200E_VCI_BITS)); | ||
1607 | |||
1608 | DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal)); | ||
1609 | |||
1610 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
1611 | |||
1612 | fore200e_activate_vcin(fore200e, 0, vcc, 0); | ||
1613 | |||
1614 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1615 | |||
1616 | vc_map = FORE200E_VC_MAP(fore200e, vcc->vpi, vcc->vci); | ||
1617 | |||
1618 | /* the vc is no longer considered as "in use" by fore200e_open() */ | ||
1619 | vc_map->vcc = NULL; | ||
1620 | |||
1621 | vcc->itf = vcc->vci = vcc->vpi = 0; | ||
1622 | |||
1623 | fore200e_vcc = FORE200E_VCC(vcc); | ||
1624 | vcc->dev_data = NULL; | ||
1625 | |||
1626 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1627 | |||
1628 | /* release reserved bandwidth, if any */ | ||
1629 | if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) { | ||
1630 | |||
1631 | down(&fore200e->rate_sf); | ||
1632 | fore200e->available_cell_rate += vcc->qos.txtp.max_pcr; | ||
1633 | up(&fore200e->rate_sf); | ||
1634 | |||
1635 | clear_bit(ATM_VF_HASQOS, &vcc->flags); | ||
1636 | } | ||
1637 | |||
1638 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
1639 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1640 | |||
1641 | ASSERT(fore200e_vcc); | ||
1642 | fore200e_kfree(fore200e_vcc); | ||
1643 | } | ||
1644 | |||
1645 | |||
1646 | static int | ||
1647 | fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
1648 | { | ||
1649 | struct fore200e* fore200e = FORE200E_DEV(vcc->dev); | ||
1650 | struct fore200e_vcc* fore200e_vcc = FORE200E_VCC(vcc); | ||
1651 | struct fore200e_vc_map* vc_map; | ||
1652 | struct host_txq* txq = &fore200e->host_txq; | ||
1653 | struct host_txq_entry* entry; | ||
1654 | struct tpd* tpd; | ||
1655 | struct tpd_haddr tpd_haddr; | ||
1656 | int retry = CONFIG_ATM_FORE200E_TX_RETRY; | ||
1657 | int tx_copy = 0; | ||
1658 | int tx_len = skb->len; | ||
1659 | u32* cell_header = NULL; | ||
1660 | unsigned char* skb_data; | ||
1661 | int skb_len; | ||
1662 | unsigned char* data; | ||
1663 | unsigned long flags; | ||
1664 | |||
1665 | ASSERT(vcc); | ||
1666 | ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0); | ||
1667 | ASSERT(fore200e); | ||
1668 | ASSERT(fore200e_vcc); | ||
1669 | |||
1670 | if (!test_bit(ATM_VF_READY, &vcc->flags)) { | ||
1671 | DPRINTK(1, "VC %d.%d.%d not ready for tx\n", vcc->itf, vcc->vpi, vcc->vpi); | ||
1672 | dev_kfree_skb_any(skb); | ||
1673 | return -EINVAL; | ||
1674 | } | ||
1675 | |||
1676 | #ifdef FORE200E_52BYTE_AAL0_SDU | ||
1677 | if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.txtp.max_sdu == ATM_AAL0_SDU)) { | ||
1678 | cell_header = (u32*) skb->data; | ||
1679 | skb_data = skb->data + 4; /* skip 4-byte cell header */ | ||
1680 | skb_len = tx_len = skb->len - 4; | ||
1681 | |||
1682 | DPRINTK(3, "user-supplied cell header = 0x%08x\n", *cell_header); | ||
1683 | } | ||
1684 | else | ||
1685 | #endif | ||
1686 | { | ||
1687 | skb_data = skb->data; | ||
1688 | skb_len = skb->len; | ||
1689 | } | ||
1690 | |||
1691 | if (((unsigned long)skb_data) & 0x3) { | ||
1692 | |||
1693 | DPRINTK(2, "misaligned tx PDU on device %s\n", fore200e->name); | ||
1694 | tx_copy = 1; | ||
1695 | tx_len = skb_len; | ||
1696 | } | ||
1697 | |||
1698 | if ((vcc->qos.aal == ATM_AAL0) && (skb_len % ATM_CELL_PAYLOAD)) { | ||
1699 | |||
1700 | /* this simply NUKES the PCA board */ | ||
1701 | DPRINTK(2, "incomplete tx AAL0 PDU on device %s\n", fore200e->name); | ||
1702 | tx_copy = 1; | ||
1703 | tx_len = ((skb_len / ATM_CELL_PAYLOAD) + 1) * ATM_CELL_PAYLOAD; | ||
1704 | } | ||
1705 | |||
1706 | if (tx_copy) { | ||
1707 | data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA); | ||
1708 | if (data == NULL) { | ||
1709 | if (vcc->pop) { | ||
1710 | vcc->pop(vcc, skb); | ||
1711 | } | ||
1712 | else { | ||
1713 | dev_kfree_skb_any(skb); | ||
1714 | } | ||
1715 | return -ENOMEM; | ||
1716 | } | ||
1717 | |||
1718 | memcpy(data, skb_data, skb_len); | ||
1719 | if (skb_len < tx_len) | ||
1720 | memset(data + skb_len, 0x00, tx_len - skb_len); | ||
1721 | } | ||
1722 | else { | ||
1723 | data = skb_data; | ||
1724 | } | ||
1725 | |||
1726 | vc_map = FORE200E_VC_MAP(fore200e, vcc->vpi, vcc->vci); | ||
1727 | ASSERT(vc_map->vcc == vcc); | ||
1728 | |||
1729 | retry_here: | ||
1730 | |||
1731 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
1732 | |||
1733 | entry = &txq->host_entry[ txq->head ]; | ||
1734 | |||
1735 | if ((*entry->status != STATUS_FREE) || (txq->txing >= QUEUE_SIZE_TX - 2)) { | ||
1736 | |||
1737 | /* try to free completed tx queue entries */ | ||
1738 | fore200e_tx_irq(fore200e); | ||
1739 | |||
1740 | if (*entry->status != STATUS_FREE) { | ||
1741 | |||
1742 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1743 | |||
1744 | /* retry once again? */ | ||
1745 | if (--retry > 0) { | ||
1746 | udelay(50); | ||
1747 | goto retry_here; | ||
1748 | } | ||
1749 | |||
1750 | atomic_inc(&vcc->stats->tx_err); | ||
1751 | |||
1752 | fore200e->tx_sat++; | ||
1753 | DPRINTK(2, "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n", | ||
1754 | fore200e->name, fore200e->cp_queues->heartbeat); | ||
1755 | if (vcc->pop) { | ||
1756 | vcc->pop(vcc, skb); | ||
1757 | } | ||
1758 | else { | ||
1759 | dev_kfree_skb_any(skb); | ||
1760 | } | ||
1761 | |||
1762 | if (tx_copy) | ||
1763 | kfree(data); | ||
1764 | |||
1765 | return -ENOBUFS; | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1769 | entry->incarn = vc_map->incarn; | ||
1770 | entry->vc_map = vc_map; | ||
1771 | entry->skb = skb; | ||
1772 | entry->data = tx_copy ? data : NULL; | ||
1773 | |||
1774 | tpd = entry->tpd; | ||
1775 | tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, data, tx_len, DMA_TO_DEVICE); | ||
1776 | tpd->tsd[ 0 ].length = tx_len; | ||
1777 | |||
1778 | FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX); | ||
1779 | txq->txing++; | ||
1780 | |||
1781 | /* The dma_map call above implies a dma_sync so the device can use it, | ||
1782 | * thus no explicit dma_sync call is necessary here. | ||
1783 | */ | ||
1784 | |||
1785 | DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n", | ||
1786 | vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal), | ||
1787 | tpd->tsd[0].length, skb_len); | ||
1788 | |||
1789 | if (skb_len < fore200e_vcc->tx_min_pdu) | ||
1790 | fore200e_vcc->tx_min_pdu = skb_len; | ||
1791 | if (skb_len > fore200e_vcc->tx_max_pdu) | ||
1792 | fore200e_vcc->tx_max_pdu = skb_len; | ||
1793 | fore200e_vcc->tx_pdu++; | ||
1794 | |||
1795 | /* set tx rate control information */ | ||
1796 | tpd->rate.data_cells = fore200e_vcc->rate.data_cells; | ||
1797 | tpd->rate.idle_cells = fore200e_vcc->rate.idle_cells; | ||
1798 | |||
1799 | if (cell_header) { | ||
1800 | tpd->atm_header.clp = (*cell_header & ATM_HDR_CLP); | ||
1801 | tpd->atm_header.plt = (*cell_header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; | ||
1802 | tpd->atm_header.vci = (*cell_header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; | ||
1803 | tpd->atm_header.vpi = (*cell_header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; | ||
1804 | tpd->atm_header.gfc = (*cell_header & ATM_HDR_GFC_MASK) >> ATM_HDR_GFC_SHIFT; | ||
1805 | } | ||
1806 | else { | ||
1807 | /* set the ATM header, common to all cells conveying the PDU */ | ||
1808 | tpd->atm_header.clp = 0; | ||
1809 | tpd->atm_header.plt = 0; | ||
1810 | tpd->atm_header.vci = vcc->vci; | ||
1811 | tpd->atm_header.vpi = vcc->vpi; | ||
1812 | tpd->atm_header.gfc = 0; | ||
1813 | } | ||
1814 | |||
1815 | tpd->spec.length = tx_len; | ||
1816 | tpd->spec.nseg = 1; | ||
1817 | tpd->spec.aal = fore200e_atm2fore_aal(vcc->qos.aal); | ||
1818 | tpd->spec.intr = 1; | ||
1819 | |||
1820 | tpd_haddr.size = sizeof(struct tpd) / (1<<TPD_HADDR_SHIFT); /* size is expressed in 32 byte blocks */ | ||
1821 | tpd_haddr.pad = 0; | ||
1822 | tpd_haddr.haddr = entry->tpd_dma >> TPD_HADDR_SHIFT; /* shift the address, as we are in a bitfield */ | ||
1823 | |||
1824 | *entry->status = STATUS_PENDING; | ||
1825 | fore200e->bus->write(*(u32*)&tpd_haddr, (u32 __iomem *)&entry->cp_entry->tpd_haddr); | ||
1826 | |||
1827 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
1828 | |||
1829 | return 0; | ||
1830 | } | ||
1831 | |||
1832 | |||
1833 | static int | ||
1834 | fore200e_getstats(struct fore200e* fore200e) | ||
1835 | { | ||
1836 | struct host_cmdq* cmdq = &fore200e->host_cmdq; | ||
1837 | struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ]; | ||
1838 | struct stats_opcode opcode; | ||
1839 | int ok; | ||
1840 | u32 stats_dma_addr; | ||
1841 | |||
1842 | if (fore200e->stats == NULL) { | ||
1843 | fore200e->stats = fore200e_kmalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA); | ||
1844 | if (fore200e->stats == NULL) | ||
1845 | return -ENOMEM; | ||
1846 | } | ||
1847 | |||
1848 | stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, | ||
1849 | sizeof(struct stats), DMA_FROM_DEVICE); | ||
1850 | |||
1851 | FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); | ||
1852 | |||
1853 | opcode.opcode = OPCODE_GET_STATS; | ||
1854 | opcode.pad = 0; | ||
1855 | |||
1856 | fore200e->bus->write(stats_dma_addr, &entry->cp_entry->cmd.stats_block.stats_haddr); | ||
1857 | |||
1858 | *entry->status = STATUS_PENDING; | ||
1859 | |||
1860 | fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.stats_block.opcode); | ||
1861 | |||
1862 | ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); | ||
1863 | |||
1864 | *entry->status = STATUS_FREE; | ||
1865 | |||
1866 | fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), DMA_FROM_DEVICE); | ||
1867 | |||
1868 | if (ok == 0) { | ||
1869 | printk(FORE200E "unable to get statistics from device %s\n", fore200e->name); | ||
1870 | return -EIO; | ||
1871 | } | ||
1872 | |||
1873 | return 0; | ||
1874 | } | ||
1875 | |||
1876 | |||
1877 | static int | ||
1878 | fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen) | ||
1879 | { | ||
1880 | /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */ | ||
1881 | |||
1882 | DPRINTK(2, "getsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n", | ||
1883 | vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen); | ||
1884 | |||
1885 | return -EINVAL; | ||
1886 | } | ||
1887 | |||
1888 | |||
1889 | static int | ||
1890 | fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen) | ||
1891 | { | ||
1892 | /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */ | ||
1893 | |||
1894 | DPRINTK(2, "setsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n", | ||
1895 | vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen); | ||
1896 | |||
1897 | return -EINVAL; | ||
1898 | } | ||
1899 | |||
1900 | |||
1901 | #if 0 /* currently unused */ | ||
1902 | static int | ||
1903 | fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs) | ||
1904 | { | ||
1905 | struct host_cmdq* cmdq = &fore200e->host_cmdq; | ||
1906 | struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ]; | ||
1907 | struct oc3_opcode opcode; | ||
1908 | int ok; | ||
1909 | u32 oc3_regs_dma_addr; | ||
1910 | |||
1911 | oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), DMA_FROM_DEVICE); | ||
1912 | |||
1913 | FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); | ||
1914 | |||
1915 | opcode.opcode = OPCODE_GET_OC3; | ||
1916 | opcode.reg = 0; | ||
1917 | opcode.value = 0; | ||
1918 | opcode.mask = 0; | ||
1919 | |||
1920 | fore200e->bus->write(oc3_regs_dma_addr, &entry->cp_entry->cmd.oc3_block.regs_haddr); | ||
1921 | |||
1922 | *entry->status = STATUS_PENDING; | ||
1923 | |||
1924 | fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode); | ||
1925 | |||
1926 | ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); | ||
1927 | |||
1928 | *entry->status = STATUS_FREE; | ||
1929 | |||
1930 | fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), DMA_FROM_DEVICE); | ||
1931 | |||
1932 | if (ok == 0) { | ||
1933 | printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name); | ||
1934 | return -EIO; | ||
1935 | } | ||
1936 | |||
1937 | return 0; | ||
1938 | } | ||
1939 | #endif | ||
1940 | |||
1941 | |||
1942 | static int | ||
1943 | fore200e_set_oc3(struct fore200e* fore200e, u32 reg, u32 value, u32 mask) | ||
1944 | { | ||
1945 | struct host_cmdq* cmdq = &fore200e->host_cmdq; | ||
1946 | struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ]; | ||
1947 | struct oc3_opcode opcode; | ||
1948 | int ok; | ||
1949 | |||
1950 | DPRINTK(2, "set OC-3 reg = 0x%02x, value = 0x%02x, mask = 0x%02x\n", reg, value, mask); | ||
1951 | |||
1952 | FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); | ||
1953 | |||
1954 | opcode.opcode = OPCODE_SET_OC3; | ||
1955 | opcode.reg = reg; | ||
1956 | opcode.value = value; | ||
1957 | opcode.mask = mask; | ||
1958 | |||
1959 | fore200e->bus->write(0, &entry->cp_entry->cmd.oc3_block.regs_haddr); | ||
1960 | |||
1961 | *entry->status = STATUS_PENDING; | ||
1962 | |||
1963 | fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.oc3_block.opcode); | ||
1964 | |||
1965 | ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); | ||
1966 | |||
1967 | *entry->status = STATUS_FREE; | ||
1968 | |||
1969 | if (ok == 0) { | ||
1970 | printk(FORE200E "unable to set OC-3 reg 0x%02x of device %s\n", reg, fore200e->name); | ||
1971 | return -EIO; | ||
1972 | } | ||
1973 | |||
1974 | return 0; | ||
1975 | } | ||
1976 | |||
1977 | |||
1978 | static int | ||
1979 | fore200e_setloop(struct fore200e* fore200e, int loop_mode) | ||
1980 | { | ||
1981 | u32 mct_value, mct_mask; | ||
1982 | int error; | ||
1983 | |||
1984 | if (!capable(CAP_NET_ADMIN)) | ||
1985 | return -EPERM; | ||
1986 | |||
1987 | switch (loop_mode) { | ||
1988 | |||
1989 | case ATM_LM_NONE: | ||
1990 | mct_value = 0; | ||
1991 | mct_mask = SUNI_MCT_DLE | SUNI_MCT_LLE; | ||
1992 | break; | ||
1993 | |||
1994 | case ATM_LM_LOC_PHY: | ||
1995 | mct_value = mct_mask = SUNI_MCT_DLE; | ||
1996 | break; | ||
1997 | |||
1998 | case ATM_LM_RMT_PHY: | ||
1999 | mct_value = mct_mask = SUNI_MCT_LLE; | ||
2000 | break; | ||
2001 | |||
2002 | default: | ||
2003 | return -EINVAL; | ||
2004 | } | ||
2005 | |||
2006 | error = fore200e_set_oc3(fore200e, SUNI_MCT, mct_value, mct_mask); | ||
2007 | if (error == 0) | ||
2008 | fore200e->loop_mode = loop_mode; | ||
2009 | |||
2010 | return error; | ||
2011 | } | ||
2012 | |||
2013 | |||
2014 | static inline unsigned int | ||
2015 | fore200e_swap(unsigned int in) | ||
2016 | { | ||
2017 | #if defined(__LITTLE_ENDIAN) | ||
2018 | return swab32(in); | ||
2019 | #else | ||
2020 | return in; | ||
2021 | #endif | ||
2022 | } | ||
2023 | |||
2024 | |||
2025 | static int | ||
2026 | fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats __user *arg) | ||
2027 | { | ||
2028 | struct sonet_stats tmp; | ||
2029 | |||
2030 | if (fore200e_getstats(fore200e) < 0) | ||
2031 | return -EIO; | ||
2032 | |||
2033 | tmp.section_bip = fore200e_swap(fore200e->stats->oc3.section_bip8_errors); | ||
2034 | tmp.line_bip = fore200e_swap(fore200e->stats->oc3.line_bip24_errors); | ||
2035 | tmp.path_bip = fore200e_swap(fore200e->stats->oc3.path_bip8_errors); | ||
2036 | tmp.line_febe = fore200e_swap(fore200e->stats->oc3.line_febe_errors); | ||
2037 | tmp.path_febe = fore200e_swap(fore200e->stats->oc3.path_febe_errors); | ||
2038 | tmp.corr_hcs = fore200e_swap(fore200e->stats->oc3.corr_hcs_errors); | ||
2039 | tmp.uncorr_hcs = fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors); | ||
2040 | tmp.tx_cells = fore200e_swap(fore200e->stats->aal0.cells_transmitted) + | ||
2041 | fore200e_swap(fore200e->stats->aal34.cells_transmitted) + | ||
2042 | fore200e_swap(fore200e->stats->aal5.cells_transmitted); | ||
2043 | tmp.rx_cells = fore200e_swap(fore200e->stats->aal0.cells_received) + | ||
2044 | fore200e_swap(fore200e->stats->aal34.cells_received) + | ||
2045 | fore200e_swap(fore200e->stats->aal5.cells_received); | ||
2046 | |||
2047 | if (arg) | ||
2048 | return copy_to_user(arg, &tmp, sizeof(struct sonet_stats)) ? -EFAULT : 0; | ||
2049 | |||
2050 | return 0; | ||
2051 | } | ||
2052 | |||
2053 | |||
2054 | static int | ||
2055 | fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void __user * arg) | ||
2056 | { | ||
2057 | struct fore200e* fore200e = FORE200E_DEV(dev); | ||
2058 | |||
2059 | DPRINTK(2, "ioctl cmd = 0x%x (%u), arg = 0x%p (%lu)\n", cmd, cmd, arg, (unsigned long)arg); | ||
2060 | |||
2061 | switch (cmd) { | ||
2062 | |||
2063 | case SONET_GETSTAT: | ||
2064 | return fore200e_fetch_stats(fore200e, (struct sonet_stats __user *)arg); | ||
2065 | |||
2066 | case SONET_GETDIAG: | ||
2067 | return put_user(0, (int __user *)arg) ? -EFAULT : 0; | ||
2068 | |||
2069 | case ATM_SETLOOP: | ||
2070 | return fore200e_setloop(fore200e, (int)(unsigned long)arg); | ||
2071 | |||
2072 | case ATM_GETLOOP: | ||
2073 | return put_user(fore200e->loop_mode, (int __user *)arg) ? -EFAULT : 0; | ||
2074 | |||
2075 | case ATM_QUERYLOOP: | ||
2076 | return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int __user *)arg) ? -EFAULT : 0; | ||
2077 | } | ||
2078 | |||
2079 | return -ENOSYS; /* not implemented */ | ||
2080 | } | ||
2081 | |||
2082 | |||
2083 | static int | ||
2084 | fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags) | ||
2085 | { | ||
2086 | struct fore200e_vcc* fore200e_vcc = FORE200E_VCC(vcc); | ||
2087 | struct fore200e* fore200e = FORE200E_DEV(vcc->dev); | ||
2088 | |||
2089 | if (!test_bit(ATM_VF_READY, &vcc->flags)) { | ||
2090 | DPRINTK(1, "VC %d.%d.%d not ready for QoS change\n", vcc->itf, vcc->vpi, vcc->vpi); | ||
2091 | return -EINVAL; | ||
2092 | } | ||
2093 | |||
2094 | DPRINTK(2, "change_qos %d.%d.%d, " | ||
2095 | "(tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; " | ||
2096 | "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d), flags = 0x%x\n" | ||
2097 | "available_cell_rate = %u", | ||
2098 | vcc->itf, vcc->vpi, vcc->vci, | ||
2099 | fore200e_traffic_class[ qos->txtp.traffic_class ], | ||
2100 | qos->txtp.min_pcr, qos->txtp.max_pcr, qos->txtp.max_cdv, qos->txtp.max_sdu, | ||
2101 | fore200e_traffic_class[ qos->rxtp.traffic_class ], | ||
2102 | qos->rxtp.min_pcr, qos->rxtp.max_pcr, qos->rxtp.max_cdv, qos->rxtp.max_sdu, | ||
2103 | flags, fore200e->available_cell_rate); | ||
2104 | |||
2105 | if ((qos->txtp.traffic_class == ATM_CBR) && (qos->txtp.max_pcr > 0)) { | ||
2106 | |||
2107 | down(&fore200e->rate_sf); | ||
2108 | if (fore200e->available_cell_rate + vcc->qos.txtp.max_pcr < qos->txtp.max_pcr) { | ||
2109 | up(&fore200e->rate_sf); | ||
2110 | return -EAGAIN; | ||
2111 | } | ||
2112 | |||
2113 | fore200e->available_cell_rate += vcc->qos.txtp.max_pcr; | ||
2114 | fore200e->available_cell_rate -= qos->txtp.max_pcr; | ||
2115 | |||
2116 | up(&fore200e->rate_sf); | ||
2117 | |||
2118 | memcpy(&vcc->qos, qos, sizeof(struct atm_qos)); | ||
2119 | |||
2120 | /* update rate control parameters */ | ||
2121 | fore200e_rate_ctrl(qos, &fore200e_vcc->rate); | ||
2122 | |||
2123 | set_bit(ATM_VF_HASQOS, &vcc->flags); | ||
2124 | |||
2125 | return 0; | ||
2126 | } | ||
2127 | |||
2128 | return -EINVAL; | ||
2129 | } | ||
2130 | |||
2131 | |||
2132 | static int __init | ||
2133 | fore200e_irq_request(struct fore200e* fore200e) | ||
2134 | { | ||
2135 | if (request_irq(fore200e->irq, fore200e_interrupt, SA_SHIRQ, fore200e->name, fore200e->atm_dev) < 0) { | ||
2136 | |||
2137 | printk(FORE200E "unable to reserve IRQ %s for device %s\n", | ||
2138 | fore200e_irq_itoa(fore200e->irq), fore200e->name); | ||
2139 | return -EBUSY; | ||
2140 | } | ||
2141 | |||
2142 | printk(FORE200E "IRQ %s reserved for device %s\n", | ||
2143 | fore200e_irq_itoa(fore200e->irq), fore200e->name); | ||
2144 | |||
2145 | #ifdef FORE200E_USE_TASKLET | ||
2146 | tasklet_init(&fore200e->tx_tasklet, fore200e_tx_tasklet, (unsigned long)fore200e); | ||
2147 | tasklet_init(&fore200e->rx_tasklet, fore200e_rx_tasklet, (unsigned long)fore200e); | ||
2148 | #endif | ||
2149 | |||
2150 | fore200e->state = FORE200E_STATE_IRQ; | ||
2151 | return 0; | ||
2152 | } | ||
2153 | |||
2154 | |||
2155 | static int __init | ||
2156 | fore200e_get_esi(struct fore200e* fore200e) | ||
2157 | { | ||
2158 | struct prom_data* prom = fore200e_kmalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA); | ||
2159 | int ok, i; | ||
2160 | |||
2161 | if (!prom) | ||
2162 | return -ENOMEM; | ||
2163 | |||
2164 | ok = fore200e->bus->prom_read(fore200e, prom); | ||
2165 | if (ok < 0) { | ||
2166 | fore200e_kfree(prom); | ||
2167 | return -EBUSY; | ||
2168 | } | ||
2169 | |||
2170 | printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
2171 | fore200e->name, | ||
2172 | (prom->hw_revision & 0xFF) + '@', /* probably meaningless with SBA boards */ | ||
2173 | prom->serial_number & 0xFFFF, | ||
2174 | prom->mac_addr[ 2 ], prom->mac_addr[ 3 ], prom->mac_addr[ 4 ], | ||
2175 | prom->mac_addr[ 5 ], prom->mac_addr[ 6 ], prom->mac_addr[ 7 ]); | ||
2176 | |||
2177 | for (i = 0; i < ESI_LEN; i++) { | ||
2178 | fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ]; | ||
2179 | } | ||
2180 | |||
2181 | fore200e_kfree(prom); | ||
2182 | |||
2183 | return 0; | ||
2184 | } | ||
2185 | |||
2186 | |||
2187 | static int __init | ||
2188 | fore200e_alloc_rx_buf(struct fore200e* fore200e) | ||
2189 | { | ||
2190 | int scheme, magn, nbr, size, i; | ||
2191 | |||
2192 | struct host_bsq* bsq; | ||
2193 | struct buffer* buffer; | ||
2194 | |||
2195 | for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) { | ||
2196 | for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) { | ||
2197 | |||
2198 | bsq = &fore200e->host_bsq[ scheme ][ magn ]; | ||
2199 | |||
2200 | nbr = fore200e_rx_buf_nbr[ scheme ][ magn ]; | ||
2201 | size = fore200e_rx_buf_size[ scheme ][ magn ]; | ||
2202 | |||
2203 | DPRINTK(2, "rx buffers %d / %d are being allocated\n", scheme, magn); | ||
2204 | |||
2205 | /* allocate the array of receive buffers */ | ||
2206 | buffer = bsq->buffer = fore200e_kmalloc(nbr * sizeof(struct buffer), GFP_KERNEL); | ||
2207 | |||
2208 | if (buffer == NULL) | ||
2209 | return -ENOMEM; | ||
2210 | |||
2211 | bsq->freebuf = NULL; | ||
2212 | |||
2213 | for (i = 0; i < nbr; i++) { | ||
2214 | |||
2215 | buffer[ i ].scheme = scheme; | ||
2216 | buffer[ i ].magn = magn; | ||
2217 | #ifdef FORE200E_BSQ_DEBUG | ||
2218 | buffer[ i ].index = i; | ||
2219 | buffer[ i ].supplied = 0; | ||
2220 | #endif | ||
2221 | |||
2222 | /* allocate the receive buffer body */ | ||
2223 | if (fore200e_chunk_alloc(fore200e, | ||
2224 | &buffer[ i ].data, size, fore200e->bus->buffer_alignment, | ||
2225 | DMA_FROM_DEVICE) < 0) { | ||
2226 | |||
2227 | while (i > 0) | ||
2228 | fore200e_chunk_free(fore200e, &buffer[ --i ].data); | ||
2229 | fore200e_kfree(buffer); | ||
2230 | |||
2231 | return -ENOMEM; | ||
2232 | } | ||
2233 | |||
2234 | /* insert the buffer into the free buffer list */ | ||
2235 | buffer[ i ].next = bsq->freebuf; | ||
2236 | bsq->freebuf = &buffer[ i ]; | ||
2237 | } | ||
2238 | /* all the buffers are free, initially */ | ||
2239 | bsq->freebuf_count = nbr; | ||
2240 | |||
2241 | #ifdef FORE200E_BSQ_DEBUG | ||
2242 | bsq_audit(3, bsq, scheme, magn); | ||
2243 | #endif | ||
2244 | } | ||
2245 | } | ||
2246 | |||
2247 | fore200e->state = FORE200E_STATE_ALLOC_BUF; | ||
2248 | return 0; | ||
2249 | } | ||
2250 | |||
2251 | |||
2252 | static int __init | ||
2253 | fore200e_init_bs_queue(struct fore200e* fore200e) | ||
2254 | { | ||
2255 | int scheme, magn, i; | ||
2256 | |||
2257 | struct host_bsq* bsq; | ||
2258 | struct cp_bsq_entry __iomem * cp_entry; | ||
2259 | |||
2260 | for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) { | ||
2261 | for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) { | ||
2262 | |||
2263 | DPRINTK(2, "buffer supply queue %d / %d is being initialized\n", scheme, magn); | ||
2264 | |||
2265 | bsq = &fore200e->host_bsq[ scheme ][ magn ]; | ||
2266 | |||
2267 | /* allocate and align the array of status words */ | ||
2268 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2269 | &bsq->status, | ||
2270 | sizeof(enum status), | ||
2271 | QUEUE_SIZE_BS, | ||
2272 | fore200e->bus->status_alignment) < 0) { | ||
2273 | return -ENOMEM; | ||
2274 | } | ||
2275 | |||
2276 | /* allocate and align the array of receive buffer descriptors */ | ||
2277 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2278 | &bsq->rbd_block, | ||
2279 | sizeof(struct rbd_block), | ||
2280 | QUEUE_SIZE_BS, | ||
2281 | fore200e->bus->descr_alignment) < 0) { | ||
2282 | |||
2283 | fore200e->bus->dma_chunk_free(fore200e, &bsq->status); | ||
2284 | return -ENOMEM; | ||
2285 | } | ||
2286 | |||
2287 | /* get the base address of the cp resident buffer supply queue entries */ | ||
2288 | cp_entry = fore200e->virt_base + | ||
2289 | fore200e->bus->read(&fore200e->cp_queues->cp_bsq[ scheme ][ magn ]); | ||
2290 | |||
2291 | /* fill the host resident and cp resident buffer supply queue entries */ | ||
2292 | for (i = 0; i < QUEUE_SIZE_BS; i++) { | ||
2293 | |||
2294 | bsq->host_entry[ i ].status = | ||
2295 | FORE200E_INDEX(bsq->status.align_addr, enum status, i); | ||
2296 | bsq->host_entry[ i ].rbd_block = | ||
2297 | FORE200E_INDEX(bsq->rbd_block.align_addr, struct rbd_block, i); | ||
2298 | bsq->host_entry[ i ].rbd_block_dma = | ||
2299 | FORE200E_DMA_INDEX(bsq->rbd_block.dma_addr, struct rbd_block, i); | ||
2300 | bsq->host_entry[ i ].cp_entry = &cp_entry[ i ]; | ||
2301 | |||
2302 | *bsq->host_entry[ i ].status = STATUS_FREE; | ||
2303 | |||
2304 | fore200e->bus->write(FORE200E_DMA_INDEX(bsq->status.dma_addr, enum status, i), | ||
2305 | &cp_entry[ i ].status_haddr); | ||
2306 | } | ||
2307 | } | ||
2308 | } | ||
2309 | |||
2310 | fore200e->state = FORE200E_STATE_INIT_BSQ; | ||
2311 | return 0; | ||
2312 | } | ||
2313 | |||
2314 | |||
2315 | static int __init | ||
2316 | fore200e_init_rx_queue(struct fore200e* fore200e) | ||
2317 | { | ||
2318 | struct host_rxq* rxq = &fore200e->host_rxq; | ||
2319 | struct cp_rxq_entry __iomem * cp_entry; | ||
2320 | int i; | ||
2321 | |||
2322 | DPRINTK(2, "receive queue is being initialized\n"); | ||
2323 | |||
2324 | /* allocate and align the array of status words */ | ||
2325 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2326 | &rxq->status, | ||
2327 | sizeof(enum status), | ||
2328 | QUEUE_SIZE_RX, | ||
2329 | fore200e->bus->status_alignment) < 0) { | ||
2330 | return -ENOMEM; | ||
2331 | } | ||
2332 | |||
2333 | /* allocate and align the array of receive PDU descriptors */ | ||
2334 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2335 | &rxq->rpd, | ||
2336 | sizeof(struct rpd), | ||
2337 | QUEUE_SIZE_RX, | ||
2338 | fore200e->bus->descr_alignment) < 0) { | ||
2339 | |||
2340 | fore200e->bus->dma_chunk_free(fore200e, &rxq->status); | ||
2341 | return -ENOMEM; | ||
2342 | } | ||
2343 | |||
2344 | /* get the base address of the cp resident rx queue entries */ | ||
2345 | cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_rxq); | ||
2346 | |||
2347 | /* fill the host resident and cp resident rx entries */ | ||
2348 | for (i=0; i < QUEUE_SIZE_RX; i++) { | ||
2349 | |||
2350 | rxq->host_entry[ i ].status = | ||
2351 | FORE200E_INDEX(rxq->status.align_addr, enum status, i); | ||
2352 | rxq->host_entry[ i ].rpd = | ||
2353 | FORE200E_INDEX(rxq->rpd.align_addr, struct rpd, i); | ||
2354 | rxq->host_entry[ i ].rpd_dma = | ||
2355 | FORE200E_DMA_INDEX(rxq->rpd.dma_addr, struct rpd, i); | ||
2356 | rxq->host_entry[ i ].cp_entry = &cp_entry[ i ]; | ||
2357 | |||
2358 | *rxq->host_entry[ i ].status = STATUS_FREE; | ||
2359 | |||
2360 | fore200e->bus->write(FORE200E_DMA_INDEX(rxq->status.dma_addr, enum status, i), | ||
2361 | &cp_entry[ i ].status_haddr); | ||
2362 | |||
2363 | fore200e->bus->write(FORE200E_DMA_INDEX(rxq->rpd.dma_addr, struct rpd, i), | ||
2364 | &cp_entry[ i ].rpd_haddr); | ||
2365 | } | ||
2366 | |||
2367 | /* set the head entry of the queue */ | ||
2368 | rxq->head = 0; | ||
2369 | |||
2370 | fore200e->state = FORE200E_STATE_INIT_RXQ; | ||
2371 | return 0; | ||
2372 | } | ||
2373 | |||
2374 | |||
2375 | static int __init | ||
2376 | fore200e_init_tx_queue(struct fore200e* fore200e) | ||
2377 | { | ||
2378 | struct host_txq* txq = &fore200e->host_txq; | ||
2379 | struct cp_txq_entry __iomem * cp_entry; | ||
2380 | int i; | ||
2381 | |||
2382 | DPRINTK(2, "transmit queue is being initialized\n"); | ||
2383 | |||
2384 | /* allocate and align the array of status words */ | ||
2385 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2386 | &txq->status, | ||
2387 | sizeof(enum status), | ||
2388 | QUEUE_SIZE_TX, | ||
2389 | fore200e->bus->status_alignment) < 0) { | ||
2390 | return -ENOMEM; | ||
2391 | } | ||
2392 | |||
2393 | /* allocate and align the array of transmit PDU descriptors */ | ||
2394 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2395 | &txq->tpd, | ||
2396 | sizeof(struct tpd), | ||
2397 | QUEUE_SIZE_TX, | ||
2398 | fore200e->bus->descr_alignment) < 0) { | ||
2399 | |||
2400 | fore200e->bus->dma_chunk_free(fore200e, &txq->status); | ||
2401 | return -ENOMEM; | ||
2402 | } | ||
2403 | |||
2404 | /* get the base address of the cp resident tx queue entries */ | ||
2405 | cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_txq); | ||
2406 | |||
2407 | /* fill the host resident and cp resident tx entries */ | ||
2408 | for (i=0; i < QUEUE_SIZE_TX; i++) { | ||
2409 | |||
2410 | txq->host_entry[ i ].status = | ||
2411 | FORE200E_INDEX(txq->status.align_addr, enum status, i); | ||
2412 | txq->host_entry[ i ].tpd = | ||
2413 | FORE200E_INDEX(txq->tpd.align_addr, struct tpd, i); | ||
2414 | txq->host_entry[ i ].tpd_dma = | ||
2415 | FORE200E_DMA_INDEX(txq->tpd.dma_addr, struct tpd, i); | ||
2416 | txq->host_entry[ i ].cp_entry = &cp_entry[ i ]; | ||
2417 | |||
2418 | *txq->host_entry[ i ].status = STATUS_FREE; | ||
2419 | |||
2420 | fore200e->bus->write(FORE200E_DMA_INDEX(txq->status.dma_addr, enum status, i), | ||
2421 | &cp_entry[ i ].status_haddr); | ||
2422 | |||
2423 | /* although there is a one-to-one mapping of tx queue entries and tpds, | ||
2424 | we do not write here the DMA (physical) base address of each tpd into | ||
2425 | the related cp resident entry, because the cp relies on this write | ||
2426 | operation to detect that a new pdu has been submitted for tx */ | ||
2427 | } | ||
2428 | |||
2429 | /* set the head and tail entries of the queue */ | ||
2430 | txq->head = 0; | ||
2431 | txq->tail = 0; | ||
2432 | |||
2433 | fore200e->state = FORE200E_STATE_INIT_TXQ; | ||
2434 | return 0; | ||
2435 | } | ||
2436 | |||
2437 | |||
2438 | static int __init | ||
2439 | fore200e_init_cmd_queue(struct fore200e* fore200e) | ||
2440 | { | ||
2441 | struct host_cmdq* cmdq = &fore200e->host_cmdq; | ||
2442 | struct cp_cmdq_entry __iomem * cp_entry; | ||
2443 | int i; | ||
2444 | |||
2445 | DPRINTK(2, "command queue is being initialized\n"); | ||
2446 | |||
2447 | /* allocate and align the array of status words */ | ||
2448 | if (fore200e->bus->dma_chunk_alloc(fore200e, | ||
2449 | &cmdq->status, | ||
2450 | sizeof(enum status), | ||
2451 | QUEUE_SIZE_CMD, | ||
2452 | fore200e->bus->status_alignment) < 0) { | ||
2453 | return -ENOMEM; | ||
2454 | } | ||
2455 | |||
2456 | /* get the base address of the cp resident cmd queue entries */ | ||
2457 | cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_cmdq); | ||
2458 | |||
2459 | /* fill the host resident and cp resident cmd entries */ | ||
2460 | for (i=0; i < QUEUE_SIZE_CMD; i++) { | ||
2461 | |||
2462 | cmdq->host_entry[ i ].status = | ||
2463 | FORE200E_INDEX(cmdq->status.align_addr, enum status, i); | ||
2464 | cmdq->host_entry[ i ].cp_entry = &cp_entry[ i ]; | ||
2465 | |||
2466 | *cmdq->host_entry[ i ].status = STATUS_FREE; | ||
2467 | |||
2468 | fore200e->bus->write(FORE200E_DMA_INDEX(cmdq->status.dma_addr, enum status, i), | ||
2469 | &cp_entry[ i ].status_haddr); | ||
2470 | } | ||
2471 | |||
2472 | /* set the head entry of the queue */ | ||
2473 | cmdq->head = 0; | ||
2474 | |||
2475 | fore200e->state = FORE200E_STATE_INIT_CMDQ; | ||
2476 | return 0; | ||
2477 | } | ||
2478 | |||
2479 | |||
2480 | static void __init | ||
2481 | fore200e_param_bs_queue(struct fore200e* fore200e, | ||
2482 | enum buffer_scheme scheme, enum buffer_magn magn, | ||
2483 | int queue_length, int pool_size, int supply_blksize) | ||
2484 | { | ||
2485 | struct bs_spec __iomem * bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ]; | ||
2486 | |||
2487 | fore200e->bus->write(queue_length, &bs_spec->queue_length); | ||
2488 | fore200e->bus->write(fore200e_rx_buf_size[ scheme ][ magn ], &bs_spec->buffer_size); | ||
2489 | fore200e->bus->write(pool_size, &bs_spec->pool_size); | ||
2490 | fore200e->bus->write(supply_blksize, &bs_spec->supply_blksize); | ||
2491 | } | ||
2492 | |||
2493 | |||
2494 | static int __init | ||
2495 | fore200e_initialize(struct fore200e* fore200e) | ||
2496 | { | ||
2497 | struct cp_queues __iomem * cpq; | ||
2498 | int ok, scheme, magn; | ||
2499 | |||
2500 | DPRINTK(2, "device %s being initialized\n", fore200e->name); | ||
2501 | |||
2502 | init_MUTEX(&fore200e->rate_sf); | ||
2503 | spin_lock_init(&fore200e->q_lock); | ||
2504 | |||
2505 | cpq = fore200e->cp_queues = fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET; | ||
2506 | |||
2507 | /* enable cp to host interrupts */ | ||
2508 | fore200e->bus->write(1, &cpq->imask); | ||
2509 | |||
2510 | if (fore200e->bus->irq_enable) | ||
2511 | fore200e->bus->irq_enable(fore200e); | ||
2512 | |||
2513 | fore200e->bus->write(NBR_CONNECT, &cpq->init.num_connect); | ||
2514 | |||
2515 | fore200e->bus->write(QUEUE_SIZE_CMD, &cpq->init.cmd_queue_len); | ||
2516 | fore200e->bus->write(QUEUE_SIZE_RX, &cpq->init.rx_queue_len); | ||
2517 | fore200e->bus->write(QUEUE_SIZE_TX, &cpq->init.tx_queue_len); | ||
2518 | |||
2519 | fore200e->bus->write(RSD_EXTENSION, &cpq->init.rsd_extension); | ||
2520 | fore200e->bus->write(TSD_EXTENSION, &cpq->init.tsd_extension); | ||
2521 | |||
2522 | for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) | ||
2523 | for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) | ||
2524 | fore200e_param_bs_queue(fore200e, scheme, magn, | ||
2525 | QUEUE_SIZE_BS, | ||
2526 | fore200e_rx_buf_nbr[ scheme ][ magn ], | ||
2527 | RBD_BLK_SIZE); | ||
2528 | |||
2529 | /* issue the initialize command */ | ||
2530 | fore200e->bus->write(STATUS_PENDING, &cpq->init.status); | ||
2531 | fore200e->bus->write(OPCODE_INITIALIZE, &cpq->init.opcode); | ||
2532 | |||
2533 | ok = fore200e_io_poll(fore200e, &cpq->init.status, STATUS_COMPLETE, 3000); | ||
2534 | if (ok == 0) { | ||
2535 | printk(FORE200E "device %s initialization failed\n", fore200e->name); | ||
2536 | return -ENODEV; | ||
2537 | } | ||
2538 | |||
2539 | printk(FORE200E "device %s initialized\n", fore200e->name); | ||
2540 | |||
2541 | fore200e->state = FORE200E_STATE_INITIALIZE; | ||
2542 | return 0; | ||
2543 | } | ||
2544 | |||
2545 | |||
2546 | static void __init | ||
2547 | fore200e_monitor_putc(struct fore200e* fore200e, char c) | ||
2548 | { | ||
2549 | struct cp_monitor __iomem * monitor = fore200e->cp_monitor; | ||
2550 | |||
2551 | #if 0 | ||
2552 | printk("%c", c); | ||
2553 | #endif | ||
2554 | fore200e->bus->write(((u32) c) | FORE200E_CP_MONITOR_UART_AVAIL, &monitor->soft_uart.send); | ||
2555 | } | ||
2556 | |||
2557 | |||
2558 | static int __init | ||
2559 | fore200e_monitor_getc(struct fore200e* fore200e) | ||
2560 | { | ||
2561 | struct cp_monitor __iomem * monitor = fore200e->cp_monitor; | ||
2562 | unsigned long timeout = jiffies + msecs_to_jiffies(50); | ||
2563 | int c; | ||
2564 | |||
2565 | while (time_before(jiffies, timeout)) { | ||
2566 | |||
2567 | c = (int) fore200e->bus->read(&monitor->soft_uart.recv); | ||
2568 | |||
2569 | if (c & FORE200E_CP_MONITOR_UART_AVAIL) { | ||
2570 | |||
2571 | fore200e->bus->write(FORE200E_CP_MONITOR_UART_FREE, &monitor->soft_uart.recv); | ||
2572 | #if 0 | ||
2573 | printk("%c", c & 0xFF); | ||
2574 | #endif | ||
2575 | return c & 0xFF; | ||
2576 | } | ||
2577 | } | ||
2578 | |||
2579 | return -1; | ||
2580 | } | ||
2581 | |||
2582 | |||
2583 | static void __init | ||
2584 | fore200e_monitor_puts(struct fore200e* fore200e, char* str) | ||
2585 | { | ||
2586 | while (*str) { | ||
2587 | |||
2588 | /* the i960 monitor doesn't accept any new character if it has something to say */ | ||
2589 | while (fore200e_monitor_getc(fore200e) >= 0); | ||
2590 | |||
2591 | fore200e_monitor_putc(fore200e, *str++); | ||
2592 | } | ||
2593 | |||
2594 | while (fore200e_monitor_getc(fore200e) >= 0); | ||
2595 | } | ||
2596 | |||
2597 | |||
2598 | static int __init | ||
2599 | fore200e_start_fw(struct fore200e* fore200e) | ||
2600 | { | ||
2601 | int ok; | ||
2602 | char cmd[ 48 ]; | ||
2603 | struct fw_header* fw_header = (struct fw_header*) fore200e->bus->fw_data; | ||
2604 | |||
2605 | DPRINTK(2, "device %s firmware being started\n", fore200e->name); | ||
2606 | |||
2607 | #if defined(__sparc_v9__) | ||
2608 | /* reported to be required by SBA cards on some sparc64 hosts */ | ||
2609 | fore200e_spin(100); | ||
2610 | #endif | ||
2611 | |||
2612 | sprintf(cmd, "\rgo %x\r", le32_to_cpu(fw_header->start_offset)); | ||
2613 | |||
2614 | fore200e_monitor_puts(fore200e, cmd); | ||
2615 | |||
2616 | ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_CP_RUNNING, 1000); | ||
2617 | if (ok == 0) { | ||
2618 | printk(FORE200E "device %s firmware didn't start\n", fore200e->name); | ||
2619 | return -ENODEV; | ||
2620 | } | ||
2621 | |||
2622 | printk(FORE200E "device %s firmware started\n", fore200e->name); | ||
2623 | |||
2624 | fore200e->state = FORE200E_STATE_START_FW; | ||
2625 | return 0; | ||
2626 | } | ||
2627 | |||
2628 | |||
2629 | static int __init | ||
2630 | fore200e_load_fw(struct fore200e* fore200e) | ||
2631 | { | ||
2632 | u32* fw_data = (u32*) fore200e->bus->fw_data; | ||
2633 | u32 fw_size = (u32) *fore200e->bus->fw_size / sizeof(u32); | ||
2634 | |||
2635 | struct fw_header* fw_header = (struct fw_header*) fw_data; | ||
2636 | |||
2637 | u32 __iomem *load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset); | ||
2638 | |||
2639 | DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n", | ||
2640 | fore200e->name, load_addr, fw_size); | ||
2641 | |||
2642 | if (le32_to_cpu(fw_header->magic) != FW_HEADER_MAGIC) { | ||
2643 | printk(FORE200E "corrupted %s firmware image\n", fore200e->bus->model_name); | ||
2644 | return -ENODEV; | ||
2645 | } | ||
2646 | |||
2647 | for (; fw_size--; fw_data++, load_addr++) | ||
2648 | fore200e->bus->write(le32_to_cpu(*fw_data), load_addr); | ||
2649 | |||
2650 | fore200e->state = FORE200E_STATE_LOAD_FW; | ||
2651 | return 0; | ||
2652 | } | ||
2653 | |||
2654 | |||
2655 | static int __init | ||
2656 | fore200e_register(struct fore200e* fore200e) | ||
2657 | { | ||
2658 | struct atm_dev* atm_dev; | ||
2659 | |||
2660 | DPRINTK(2, "device %s being registered\n", fore200e->name); | ||
2661 | |||
2662 | atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1, | ||
2663 | NULL); | ||
2664 | if (atm_dev == NULL) { | ||
2665 | printk(FORE200E "unable to register device %s\n", fore200e->name); | ||
2666 | return -ENODEV; | ||
2667 | } | ||
2668 | |||
2669 | atm_dev->dev_data = fore200e; | ||
2670 | fore200e->atm_dev = atm_dev; | ||
2671 | |||
2672 | atm_dev->ci_range.vpi_bits = FORE200E_VPI_BITS; | ||
2673 | atm_dev->ci_range.vci_bits = FORE200E_VCI_BITS; | ||
2674 | |||
2675 | fore200e->available_cell_rate = ATM_OC3_PCR; | ||
2676 | |||
2677 | fore200e->state = FORE200E_STATE_REGISTER; | ||
2678 | return 0; | ||
2679 | } | ||
2680 | |||
2681 | |||
2682 | static int __init | ||
2683 | fore200e_init(struct fore200e* fore200e) | ||
2684 | { | ||
2685 | if (fore200e_register(fore200e) < 0) | ||
2686 | return -ENODEV; | ||
2687 | |||
2688 | if (fore200e->bus->configure(fore200e) < 0) | ||
2689 | return -ENODEV; | ||
2690 | |||
2691 | if (fore200e->bus->map(fore200e) < 0) | ||
2692 | return -ENODEV; | ||
2693 | |||
2694 | if (fore200e_reset(fore200e, 1) < 0) | ||
2695 | return -ENODEV; | ||
2696 | |||
2697 | if (fore200e_load_fw(fore200e) < 0) | ||
2698 | return -ENODEV; | ||
2699 | |||
2700 | if (fore200e_start_fw(fore200e) < 0) | ||
2701 | return -ENODEV; | ||
2702 | |||
2703 | if (fore200e_initialize(fore200e) < 0) | ||
2704 | return -ENODEV; | ||
2705 | |||
2706 | if (fore200e_init_cmd_queue(fore200e) < 0) | ||
2707 | return -ENOMEM; | ||
2708 | |||
2709 | if (fore200e_init_tx_queue(fore200e) < 0) | ||
2710 | return -ENOMEM; | ||
2711 | |||
2712 | if (fore200e_init_rx_queue(fore200e) < 0) | ||
2713 | return -ENOMEM; | ||
2714 | |||
2715 | if (fore200e_init_bs_queue(fore200e) < 0) | ||
2716 | return -ENOMEM; | ||
2717 | |||
2718 | if (fore200e_alloc_rx_buf(fore200e) < 0) | ||
2719 | return -ENOMEM; | ||
2720 | |||
2721 | if (fore200e_get_esi(fore200e) < 0) | ||
2722 | return -EIO; | ||
2723 | |||
2724 | if (fore200e_irq_request(fore200e) < 0) | ||
2725 | return -EBUSY; | ||
2726 | |||
2727 | fore200e_supply(fore200e); | ||
2728 | |||
2729 | /* all done, board initialization is now complete */ | ||
2730 | fore200e->state = FORE200E_STATE_COMPLETE; | ||
2731 | return 0; | ||
2732 | } | ||
2733 | |||
2734 | |||
2735 | static int __devinit | ||
2736 | fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | ||
2737 | { | ||
2738 | const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data; | ||
2739 | struct fore200e* fore200e; | ||
2740 | int err = 0; | ||
2741 | static int index = 0; | ||
2742 | |||
2743 | if (pci_enable_device(pci_dev)) { | ||
2744 | err = -EINVAL; | ||
2745 | goto out; | ||
2746 | } | ||
2747 | |||
2748 | fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL); | ||
2749 | if (fore200e == NULL) { | ||
2750 | err = -ENOMEM; | ||
2751 | goto out_disable; | ||
2752 | } | ||
2753 | |||
2754 | fore200e->bus = bus; | ||
2755 | fore200e->bus_dev = pci_dev; | ||
2756 | fore200e->irq = pci_dev->irq; | ||
2757 | fore200e->phys_base = pci_resource_start(pci_dev, 0); | ||
2758 | |||
2759 | sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1); | ||
2760 | |||
2761 | pci_set_master(pci_dev); | ||
2762 | |||
2763 | printk(FORE200E "device %s found at 0x%lx, IRQ %s\n", | ||
2764 | fore200e->bus->model_name, | ||
2765 | fore200e->phys_base, fore200e_irq_itoa(fore200e->irq)); | ||
2766 | |||
2767 | sprintf(fore200e->name, "%s-%d", bus->model_name, index); | ||
2768 | |||
2769 | err = fore200e_init(fore200e); | ||
2770 | if (err < 0) { | ||
2771 | fore200e_shutdown(fore200e); | ||
2772 | goto out_free; | ||
2773 | } | ||
2774 | |||
2775 | ++index; | ||
2776 | pci_set_drvdata(pci_dev, fore200e); | ||
2777 | |||
2778 | out: | ||
2779 | return err; | ||
2780 | |||
2781 | out_free: | ||
2782 | kfree(fore200e); | ||
2783 | out_disable: | ||
2784 | pci_disable_device(pci_dev); | ||
2785 | goto out; | ||
2786 | } | ||
2787 | |||
2788 | |||
2789 | static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev) | ||
2790 | { | ||
2791 | struct fore200e *fore200e; | ||
2792 | |||
2793 | fore200e = pci_get_drvdata(pci_dev); | ||
2794 | |||
2795 | list_del(&fore200e->entry); | ||
2796 | |||
2797 | fore200e_shutdown(fore200e); | ||
2798 | kfree(fore200e); | ||
2799 | pci_disable_device(pci_dev); | ||
2800 | } | ||
2801 | |||
2802 | |||
2803 | #ifdef CONFIG_ATM_FORE200E_PCA | ||
2804 | static struct pci_device_id fore200e_pca_tbl[] = { | ||
2805 | { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID, | ||
2806 | 0, 0, (unsigned long) &fore200e_bus[0] }, | ||
2807 | { 0, } | ||
2808 | }; | ||
2809 | |||
2810 | MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl); | ||
2811 | |||
2812 | static struct pci_driver fore200e_pca_driver = { | ||
2813 | .name = "fore_200e", | ||
2814 | .probe = fore200e_pca_detect, | ||
2815 | .remove = __devexit_p(fore200e_pca_remove_one), | ||
2816 | .id_table = fore200e_pca_tbl, | ||
2817 | }; | ||
2818 | #endif | ||
2819 | |||
2820 | |||
2821 | static int __init | ||
2822 | fore200e_module_init(void) | ||
2823 | { | ||
2824 | const struct fore200e_bus* bus; | ||
2825 | struct fore200e* fore200e; | ||
2826 | int index; | ||
2827 | |||
2828 | printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); | ||
2829 | |||
2830 | /* for each configured bus interface */ | ||
2831 | for (bus = fore200e_bus; bus->model_name; bus++) { | ||
2832 | |||
2833 | /* detect all boards present on that bus */ | ||
2834 | for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) { | ||
2835 | |||
2836 | printk(FORE200E "device %s found at 0x%lx, IRQ %s\n", | ||
2837 | fore200e->bus->model_name, | ||
2838 | fore200e->phys_base, fore200e_irq_itoa(fore200e->irq)); | ||
2839 | |||
2840 | sprintf(fore200e->name, "%s-%d", bus->model_name, index); | ||
2841 | |||
2842 | if (fore200e_init(fore200e) < 0) { | ||
2843 | |||
2844 | fore200e_shutdown(fore200e); | ||
2845 | break; | ||
2846 | } | ||
2847 | |||
2848 | list_add(&fore200e->entry, &fore200e_boards); | ||
2849 | } | ||
2850 | } | ||
2851 | |||
2852 | #ifdef CONFIG_ATM_FORE200E_PCA | ||
2853 | if (!pci_module_init(&fore200e_pca_driver)) | ||
2854 | return 0; | ||
2855 | #endif | ||
2856 | |||
2857 | if (!list_empty(&fore200e_boards)) | ||
2858 | return 0; | ||
2859 | |||
2860 | return -ENODEV; | ||
2861 | } | ||
2862 | |||
2863 | |||
2864 | static void __exit | ||
2865 | fore200e_module_cleanup(void) | ||
2866 | { | ||
2867 | struct fore200e *fore200e, *next; | ||
2868 | |||
2869 | #ifdef CONFIG_ATM_FORE200E_PCA | ||
2870 | pci_unregister_driver(&fore200e_pca_driver); | ||
2871 | #endif | ||
2872 | |||
2873 | list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) { | ||
2874 | fore200e_shutdown(fore200e); | ||
2875 | kfree(fore200e); | ||
2876 | } | ||
2877 | DPRINTK(1, "module being removed\n"); | ||
2878 | } | ||
2879 | |||
2880 | |||
2881 | static int | ||
2882 | fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) | ||
2883 | { | ||
2884 | struct fore200e* fore200e = FORE200E_DEV(dev); | ||
2885 | struct fore200e_vcc* fore200e_vcc; | ||
2886 | struct atm_vcc* vcc; | ||
2887 | int i, len, left = *pos; | ||
2888 | unsigned long flags; | ||
2889 | |||
2890 | if (!left--) { | ||
2891 | |||
2892 | if (fore200e_getstats(fore200e) < 0) | ||
2893 | return -EIO; | ||
2894 | |||
2895 | len = sprintf(page,"\n" | ||
2896 | " device:\n" | ||
2897 | " internal name:\t\t%s\n", fore200e->name); | ||
2898 | |||
2899 | /* print bus-specific information */ | ||
2900 | if (fore200e->bus->proc_read) | ||
2901 | len += fore200e->bus->proc_read(fore200e, page + len); | ||
2902 | |||
2903 | len += sprintf(page + len, | ||
2904 | " interrupt line:\t\t%s\n" | ||
2905 | " physical base address:\t0x%p\n" | ||
2906 | " virtual base address:\t0x%p\n" | ||
2907 | " factory address (ESI):\t%02x:%02x:%02x:%02x:%02x:%02x\n" | ||
2908 | " board serial number:\t\t%d\n\n", | ||
2909 | fore200e_irq_itoa(fore200e->irq), | ||
2910 | (void*)fore200e->phys_base, | ||
2911 | fore200e->virt_base, | ||
2912 | fore200e->esi[0], fore200e->esi[1], fore200e->esi[2], | ||
2913 | fore200e->esi[3], fore200e->esi[4], fore200e->esi[5], | ||
2914 | fore200e->esi[4] * 256 + fore200e->esi[5]); | ||
2915 | |||
2916 | return len; | ||
2917 | } | ||
2918 | |||
2919 | if (!left--) | ||
2920 | return sprintf(page, | ||
2921 | " free small bufs, scheme 1:\t%d\n" | ||
2922 | " free large bufs, scheme 1:\t%d\n" | ||
2923 | " free small bufs, scheme 2:\t%d\n" | ||
2924 | " free large bufs, scheme 2:\t%d\n", | ||
2925 | fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_SMALL ].freebuf_count, | ||
2926 | fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_LARGE ].freebuf_count, | ||
2927 | fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_SMALL ].freebuf_count, | ||
2928 | fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_LARGE ].freebuf_count); | ||
2929 | |||
2930 | if (!left--) { | ||
2931 | u32 hb = fore200e->bus->read(&fore200e->cp_queues->heartbeat); | ||
2932 | |||
2933 | len = sprintf(page,"\n\n" | ||
2934 | " cell processor:\n" | ||
2935 | " heartbeat state:\t\t"); | ||
2936 | |||
2937 | if (hb >> 16 != 0xDEAD) | ||
2938 | len += sprintf(page + len, "0x%08x\n", hb); | ||
2939 | else | ||
2940 | len += sprintf(page + len, "*** FATAL ERROR %04x ***\n", hb & 0xFFFF); | ||
2941 | |||
2942 | return len; | ||
2943 | } | ||
2944 | |||
2945 | if (!left--) { | ||
2946 | static const char* media_name[] = { | ||
2947 | "unshielded twisted pair", | ||
2948 | "multimode optical fiber ST", | ||
2949 | "multimode optical fiber SC", | ||
2950 | "single-mode optical fiber ST", | ||
2951 | "single-mode optical fiber SC", | ||
2952 | "unknown" | ||
2953 | }; | ||
2954 | |||
2955 | static const char* oc3_mode[] = { | ||
2956 | "normal operation", | ||
2957 | "diagnostic loopback", | ||
2958 | "line loopback", | ||
2959 | "unknown" | ||
2960 | }; | ||
2961 | |||
2962 | u32 fw_release = fore200e->bus->read(&fore200e->cp_queues->fw_release); | ||
2963 | u32 mon960_release = fore200e->bus->read(&fore200e->cp_queues->mon960_release); | ||
2964 | u32 oc3_revision = fore200e->bus->read(&fore200e->cp_queues->oc3_revision); | ||
2965 | u32 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type)); | ||
2966 | u32 oc3_index; | ||
2967 | |||
2968 | if ((media_index < 0) || (media_index > 4)) | ||
2969 | media_index = 5; | ||
2970 | |||
2971 | switch (fore200e->loop_mode) { | ||
2972 | case ATM_LM_NONE: oc3_index = 0; | ||
2973 | break; | ||
2974 | case ATM_LM_LOC_PHY: oc3_index = 1; | ||
2975 | break; | ||
2976 | case ATM_LM_RMT_PHY: oc3_index = 2; | ||
2977 | break; | ||
2978 | default: oc3_index = 3; | ||
2979 | } | ||
2980 | |||
2981 | return sprintf(page, | ||
2982 | " firmware release:\t\t%d.%d.%d\n" | ||
2983 | " monitor release:\t\t%d.%d\n" | ||
2984 | " media type:\t\t\t%s\n" | ||
2985 | " OC-3 revision:\t\t0x%x\n" | ||
2986 | " OC-3 mode:\t\t\t%s", | ||
2987 | fw_release >> 16, fw_release << 16 >> 24, fw_release << 24 >> 24, | ||
2988 | mon960_release >> 16, mon960_release << 16 >> 16, | ||
2989 | media_name[ media_index ], | ||
2990 | oc3_revision, | ||
2991 | oc3_mode[ oc3_index ]); | ||
2992 | } | ||
2993 | |||
2994 | if (!left--) { | ||
2995 | struct cp_monitor __iomem * cp_monitor = fore200e->cp_monitor; | ||
2996 | |||
2997 | return sprintf(page, | ||
2998 | "\n\n" | ||
2999 | " monitor:\n" | ||
3000 | " version number:\t\t%d\n" | ||
3001 | " boot status word:\t\t0x%08x\n", | ||
3002 | fore200e->bus->read(&cp_monitor->mon_version), | ||
3003 | fore200e->bus->read(&cp_monitor->bstat)); | ||
3004 | } | ||
3005 | |||
3006 | if (!left--) | ||
3007 | return sprintf(page, | ||
3008 | "\n" | ||
3009 | " device statistics:\n" | ||
3010 | " 4b5b:\n" | ||
3011 | " crc_header_errors:\t\t%10u\n" | ||
3012 | " framing_errors:\t\t%10u\n", | ||
3013 | fore200e_swap(fore200e->stats->phy.crc_header_errors), | ||
3014 | fore200e_swap(fore200e->stats->phy.framing_errors)); | ||
3015 | |||
3016 | if (!left--) | ||
3017 | return sprintf(page, "\n" | ||
3018 | " OC-3:\n" | ||
3019 | " section_bip8_errors:\t%10u\n" | ||
3020 | " path_bip8_errors:\t\t%10u\n" | ||
3021 | " line_bip24_errors:\t\t%10u\n" | ||
3022 | " line_febe_errors:\t\t%10u\n" | ||
3023 | " path_febe_errors:\t\t%10u\n" | ||
3024 | " corr_hcs_errors:\t\t%10u\n" | ||
3025 | " ucorr_hcs_errors:\t\t%10u\n", | ||
3026 | fore200e_swap(fore200e->stats->oc3.section_bip8_errors), | ||
3027 | fore200e_swap(fore200e->stats->oc3.path_bip8_errors), | ||
3028 | fore200e_swap(fore200e->stats->oc3.line_bip24_errors), | ||
3029 | fore200e_swap(fore200e->stats->oc3.line_febe_errors), | ||
3030 | fore200e_swap(fore200e->stats->oc3.path_febe_errors), | ||
3031 | fore200e_swap(fore200e->stats->oc3.corr_hcs_errors), | ||
3032 | fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors)); | ||
3033 | |||
3034 | if (!left--) | ||
3035 | return sprintf(page,"\n" | ||
3036 | " ATM:\t\t\t\t cells\n" | ||
3037 | " TX:\t\t\t%10u\n" | ||
3038 | " RX:\t\t\t%10u\n" | ||
3039 | " vpi out of range:\t\t%10u\n" | ||
3040 | " vpi no conn:\t\t%10u\n" | ||
3041 | " vci out of range:\t\t%10u\n" | ||
3042 | " vci no conn:\t\t%10u\n", | ||
3043 | fore200e_swap(fore200e->stats->atm.cells_transmitted), | ||
3044 | fore200e_swap(fore200e->stats->atm.cells_received), | ||
3045 | fore200e_swap(fore200e->stats->atm.vpi_bad_range), | ||
3046 | fore200e_swap(fore200e->stats->atm.vpi_no_conn), | ||
3047 | fore200e_swap(fore200e->stats->atm.vci_bad_range), | ||
3048 | fore200e_swap(fore200e->stats->atm.vci_no_conn)); | ||
3049 | |||
3050 | if (!left--) | ||
3051 | return sprintf(page,"\n" | ||
3052 | " AAL0:\t\t\t cells\n" | ||
3053 | " TX:\t\t\t%10u\n" | ||
3054 | " RX:\t\t\t%10u\n" | ||
3055 | " dropped:\t\t\t%10u\n", | ||
3056 | fore200e_swap(fore200e->stats->aal0.cells_transmitted), | ||
3057 | fore200e_swap(fore200e->stats->aal0.cells_received), | ||
3058 | fore200e_swap(fore200e->stats->aal0.cells_dropped)); | ||
3059 | |||
3060 | if (!left--) | ||
3061 | return sprintf(page,"\n" | ||
3062 | " AAL3/4:\n" | ||
3063 | " SAR sublayer:\t\t cells\n" | ||
3064 | " TX:\t\t\t%10u\n" | ||
3065 | " RX:\t\t\t%10u\n" | ||
3066 | " dropped:\t\t\t%10u\n" | ||
3067 | " CRC errors:\t\t%10u\n" | ||
3068 | " protocol errors:\t\t%10u\n\n" | ||
3069 | " CS sublayer:\t\t PDUs\n" | ||
3070 | " TX:\t\t\t%10u\n" | ||
3071 | " RX:\t\t\t%10u\n" | ||
3072 | " dropped:\t\t\t%10u\n" | ||
3073 | " protocol errors:\t\t%10u\n", | ||
3074 | fore200e_swap(fore200e->stats->aal34.cells_transmitted), | ||
3075 | fore200e_swap(fore200e->stats->aal34.cells_received), | ||
3076 | fore200e_swap(fore200e->stats->aal34.cells_dropped), | ||
3077 | fore200e_swap(fore200e->stats->aal34.cells_crc_errors), | ||
3078 | fore200e_swap(fore200e->stats->aal34.cells_protocol_errors), | ||
3079 | fore200e_swap(fore200e->stats->aal34.cspdus_transmitted), | ||
3080 | fore200e_swap(fore200e->stats->aal34.cspdus_received), | ||
3081 | fore200e_swap(fore200e->stats->aal34.cspdus_dropped), | ||
3082 | fore200e_swap(fore200e->stats->aal34.cspdus_protocol_errors)); | ||
3083 | |||
3084 | if (!left--) | ||
3085 | return sprintf(page,"\n" | ||
3086 | " AAL5:\n" | ||
3087 | " SAR sublayer:\t\t cells\n" | ||
3088 | " TX:\t\t\t%10u\n" | ||
3089 | " RX:\t\t\t%10u\n" | ||
3090 | " dropped:\t\t\t%10u\n" | ||
3091 | " congestions:\t\t%10u\n\n" | ||
3092 | " CS sublayer:\t\t PDUs\n" | ||
3093 | " TX:\t\t\t%10u\n" | ||
3094 | " RX:\t\t\t%10u\n" | ||
3095 | " dropped:\t\t\t%10u\n" | ||
3096 | " CRC errors:\t\t%10u\n" | ||
3097 | " protocol errors:\t\t%10u\n", | ||
3098 | fore200e_swap(fore200e->stats->aal5.cells_transmitted), | ||
3099 | fore200e_swap(fore200e->stats->aal5.cells_received), | ||
3100 | fore200e_swap(fore200e->stats->aal5.cells_dropped), | ||
3101 | fore200e_swap(fore200e->stats->aal5.congestion_experienced), | ||
3102 | fore200e_swap(fore200e->stats->aal5.cspdus_transmitted), | ||
3103 | fore200e_swap(fore200e->stats->aal5.cspdus_received), | ||
3104 | fore200e_swap(fore200e->stats->aal5.cspdus_dropped), | ||
3105 | fore200e_swap(fore200e->stats->aal5.cspdus_crc_errors), | ||
3106 | fore200e_swap(fore200e->stats->aal5.cspdus_protocol_errors)); | ||
3107 | |||
3108 | if (!left--) | ||
3109 | return sprintf(page,"\n" | ||
3110 | " AUX:\t\t allocation failures\n" | ||
3111 | " small b1:\t\t\t%10u\n" | ||
3112 | " large b1:\t\t\t%10u\n" | ||
3113 | " small b2:\t\t\t%10u\n" | ||
3114 | " large b2:\t\t\t%10u\n" | ||
3115 | " RX PDUs:\t\t\t%10u\n" | ||
3116 | " TX PDUs:\t\t\t%10lu\n", | ||
3117 | fore200e_swap(fore200e->stats->aux.small_b1_failed), | ||
3118 | fore200e_swap(fore200e->stats->aux.large_b1_failed), | ||
3119 | fore200e_swap(fore200e->stats->aux.small_b2_failed), | ||
3120 | fore200e_swap(fore200e->stats->aux.large_b2_failed), | ||
3121 | fore200e_swap(fore200e->stats->aux.rpd_alloc_failed), | ||
3122 | fore200e->tx_sat); | ||
3123 | |||
3124 | if (!left--) | ||
3125 | return sprintf(page,"\n" | ||
3126 | " receive carrier:\t\t\t%s\n", | ||
3127 | fore200e->stats->aux.receive_carrier ? "ON" : "OFF!"); | ||
3128 | |||
3129 | if (!left--) { | ||
3130 | return sprintf(page,"\n" | ||
3131 | " VCCs:\n address VPI VCI AAL " | ||
3132 | "TX PDUs TX min/max size RX PDUs RX min/max size\n"); | ||
3133 | } | ||
3134 | |||
3135 | for (i = 0; i < NBR_CONNECT; i++) { | ||
3136 | |||
3137 | vcc = fore200e->vc_map[i].vcc; | ||
3138 | |||
3139 | if (vcc == NULL) | ||
3140 | continue; | ||
3141 | |||
3142 | spin_lock_irqsave(&fore200e->q_lock, flags); | ||
3143 | |||
3144 | if (vcc && test_bit(ATM_VF_READY, &vcc->flags) && !left--) { | ||
3145 | |||
3146 | fore200e_vcc = FORE200E_VCC(vcc); | ||
3147 | ASSERT(fore200e_vcc); | ||
3148 | |||
3149 | len = sprintf(page, | ||
3150 | " %08x %03d %05d %1d %09lu %05d/%05d %09lu %05d/%05d\n", | ||
3151 | (u32)(unsigned long)vcc, | ||
3152 | vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal), | ||
3153 | fore200e_vcc->tx_pdu, | ||
3154 | fore200e_vcc->tx_min_pdu > 0xFFFF ? 0 : fore200e_vcc->tx_min_pdu, | ||
3155 | fore200e_vcc->tx_max_pdu, | ||
3156 | fore200e_vcc->rx_pdu, | ||
3157 | fore200e_vcc->rx_min_pdu > 0xFFFF ? 0 : fore200e_vcc->rx_min_pdu, | ||
3158 | fore200e_vcc->rx_max_pdu); | ||
3159 | |||
3160 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
3161 | return len; | ||
3162 | } | ||
3163 | |||
3164 | spin_unlock_irqrestore(&fore200e->q_lock, flags); | ||
3165 | } | ||
3166 | |||
3167 | return 0; | ||
3168 | } | ||
3169 | |||
3170 | module_init(fore200e_module_init); | ||
3171 | module_exit(fore200e_module_cleanup); | ||
3172 | |||
3173 | |||
3174 | static const struct atmdev_ops fore200e_ops = | ||
3175 | { | ||
3176 | .open = fore200e_open, | ||
3177 | .close = fore200e_close, | ||
3178 | .ioctl = fore200e_ioctl, | ||
3179 | .getsockopt = fore200e_getsockopt, | ||
3180 | .setsockopt = fore200e_setsockopt, | ||
3181 | .send = fore200e_send, | ||
3182 | .change_qos = fore200e_change_qos, | ||
3183 | .proc_read = fore200e_proc_read, | ||
3184 | .owner = THIS_MODULE | ||
3185 | }; | ||
3186 | |||
3187 | |||
3188 | #ifdef CONFIG_ATM_FORE200E_PCA | ||
3189 | extern const unsigned char _fore200e_pca_fw_data[]; | ||
3190 | extern const unsigned int _fore200e_pca_fw_size; | ||
3191 | #endif | ||
3192 | #ifdef CONFIG_ATM_FORE200E_SBA | ||
3193 | extern const unsigned char _fore200e_sba_fw_data[]; | ||
3194 | extern const unsigned int _fore200e_sba_fw_size; | ||
3195 | #endif | ||
3196 | |||
3197 | static const struct fore200e_bus fore200e_bus[] = { | ||
3198 | #ifdef CONFIG_ATM_FORE200E_PCA | ||
3199 | { "PCA-200E", "pca200e", 32, 4, 32, | ||
3200 | _fore200e_pca_fw_data, &_fore200e_pca_fw_size, | ||
3201 | fore200e_pca_read, | ||
3202 | fore200e_pca_write, | ||
3203 | fore200e_pca_dma_map, | ||
3204 | fore200e_pca_dma_unmap, | ||
3205 | fore200e_pca_dma_sync_for_cpu, | ||
3206 | fore200e_pca_dma_sync_for_device, | ||
3207 | fore200e_pca_dma_chunk_alloc, | ||
3208 | fore200e_pca_dma_chunk_free, | ||
3209 | NULL, | ||
3210 | fore200e_pca_configure, | ||
3211 | fore200e_pca_map, | ||
3212 | fore200e_pca_reset, | ||
3213 | fore200e_pca_prom_read, | ||
3214 | fore200e_pca_unmap, | ||
3215 | NULL, | ||
3216 | fore200e_pca_irq_check, | ||
3217 | fore200e_pca_irq_ack, | ||
3218 | fore200e_pca_proc_read, | ||
3219 | }, | ||
3220 | #endif | ||
3221 | #ifdef CONFIG_ATM_FORE200E_SBA | ||
3222 | { "SBA-200E", "sba200e", 32, 64, 32, | ||
3223 | _fore200e_sba_fw_data, &_fore200e_sba_fw_size, | ||
3224 | fore200e_sba_read, | ||
3225 | fore200e_sba_write, | ||
3226 | fore200e_sba_dma_map, | ||
3227 | fore200e_sba_dma_unmap, | ||
3228 | fore200e_sba_dma_sync_for_cpu, | ||
3229 | fore200e_sba_dma_sync_for_device, | ||
3230 | fore200e_sba_dma_chunk_alloc, | ||
3231 | fore200e_sba_dma_chunk_free, | ||
3232 | fore200e_sba_detect, | ||
3233 | fore200e_sba_configure, | ||
3234 | fore200e_sba_map, | ||
3235 | fore200e_sba_reset, | ||
3236 | fore200e_sba_prom_read, | ||
3237 | fore200e_sba_unmap, | ||
3238 | fore200e_sba_irq_enable, | ||
3239 | fore200e_sba_irq_check, | ||
3240 | fore200e_sba_irq_ack, | ||
3241 | fore200e_sba_proc_read, | ||
3242 | }, | ||
3243 | #endif | ||
3244 | {} | ||
3245 | }; | ||
3246 | |||
3247 | #ifdef MODULE_LICENSE | ||
3248 | MODULE_LICENSE("GPL"); | ||
3249 | #endif | ||
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h new file mode 100644 index 000000000000..2558eb853235 --- /dev/null +++ b/drivers/atm/fore200e.h | |||
@@ -0,0 +1,985 @@ | |||
1 | /* $Id: fore200e.h,v 1.4 2000/04/14 10:10:34 davem Exp $ */ | ||
2 | #ifndef _FORE200E_H | ||
3 | #define _FORE200E_H | ||
4 | |||
5 | #ifdef __KERNEL__ | ||
6 | #include <linux/config.h> | ||
7 | |||
8 | /* rx buffer sizes */ | ||
9 | |||
10 | #define SMALL_BUFFER_SIZE 384 /* size of small buffers (multiple of 48 (PCA) and 64 (SBA) bytes) */ | ||
11 | #define LARGE_BUFFER_SIZE 4032 /* size of large buffers (multiple of 48 (PCA) and 64 (SBA) bytes) */ | ||
12 | |||
13 | |||
14 | #define RBD_BLK_SIZE 32 /* nbr of supplied rx buffers per rbd */ | ||
15 | |||
16 | |||
17 | #define MAX_PDU_SIZE 65535 /* maximum PDU size supported by AALs */ | ||
18 | |||
19 | |||
20 | #define BUFFER_S1_SIZE SMALL_BUFFER_SIZE /* size of small buffers, scheme 1 */ | ||
21 | #define BUFFER_L1_SIZE LARGE_BUFFER_SIZE /* size of large buffers, scheme 1 */ | ||
22 | |||
23 | #define BUFFER_S2_SIZE SMALL_BUFFER_SIZE /* size of small buffers, scheme 2 */ | ||
24 | #define BUFFER_L2_SIZE LARGE_BUFFER_SIZE /* size of large buffers, scheme 2 */ | ||
25 | |||
26 | #define BUFFER_S1_NBR (RBD_BLK_SIZE * 6) | ||
27 | #define BUFFER_L1_NBR (RBD_BLK_SIZE * 4) | ||
28 | |||
29 | #define BUFFER_S2_NBR (RBD_BLK_SIZE * 6) | ||
30 | #define BUFFER_L2_NBR (RBD_BLK_SIZE * 4) | ||
31 | |||
32 | |||
33 | #define QUEUE_SIZE_CMD 16 /* command queue capacity */ | ||
34 | #define QUEUE_SIZE_RX 64 /* receive queue capacity */ | ||
35 | #define QUEUE_SIZE_TX 256 /* transmit queue capacity */ | ||
36 | #define QUEUE_SIZE_BS 32 /* buffer supply queue capacity */ | ||
37 | |||
38 | #define FORE200E_VPI_BITS 0 | ||
39 | #define FORE200E_VCI_BITS 10 | ||
40 | #define NBR_CONNECT (1 << (FORE200E_VPI_BITS + FORE200E_VCI_BITS)) /* number of connections */ | ||
41 | |||
42 | |||
43 | #define TSD_FIXED 2 | ||
44 | #define TSD_EXTENSION 0 | ||
45 | #define TSD_NBR (TSD_FIXED + TSD_EXTENSION) | ||
46 | |||
47 | |||
48 | /* the cp starts putting a received PDU into one *small* buffer, | ||
49 | then it uses a number of *large* buffers for the trailing data. | ||
50 | we compute here the total number of receive segment descriptors | ||
51 | required to hold the largest possible PDU */ | ||
52 | |||
53 | #define RSD_REQUIRED (((MAX_PDU_SIZE - SMALL_BUFFER_SIZE + LARGE_BUFFER_SIZE) / LARGE_BUFFER_SIZE) + 1) | ||
54 | |||
55 | #define RSD_FIXED 3 | ||
56 | |||
57 | /* RSD_REQUIRED receive segment descriptors are enough to describe a max-sized PDU, | ||
58 | but we have to keep the size of the receive PDU descriptor multiple of 32 bytes, | ||
59 | so we add one extra RSD to RSD_EXTENSION | ||
60 | (WARNING: THIS MAY CHANGE IF BUFFER SIZES ARE MODIFIED) */ | ||
61 | |||
62 | #define RSD_EXTENSION ((RSD_REQUIRED - RSD_FIXED) + 1) | ||
63 | #define RSD_NBR (RSD_FIXED + RSD_EXTENSION) | ||
64 | |||
65 | |||
66 | #define FORE200E_DEV(d) ((struct fore200e*)((d)->dev_data)) | ||
67 | #define FORE200E_VCC(d) ((struct fore200e_vcc*)((d)->dev_data)) | ||
68 | |||
69 | /* bitfields endian games */ | ||
70 | |||
71 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
72 | #define BITFIELD2(b1, b2) b1; b2; | ||
73 | #define BITFIELD3(b1, b2, b3) b1; b2; b3; | ||
74 | #define BITFIELD4(b1, b2, b3, b4) b1; b2; b3; b4; | ||
75 | #define BITFIELD5(b1, b2, b3, b4, b5) b1; b2; b3; b4; b5; | ||
76 | #define BITFIELD6(b1, b2, b3, b4, b5, b6) b1; b2; b3; b4; b5; b6; | ||
77 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
78 | #define BITFIELD2(b1, b2) b2; b1; | ||
79 | #define BITFIELD3(b1, b2, b3) b3; b2; b1; | ||
80 | #define BITFIELD4(b1, b2, b3, b4) b4; b3; b2; b1; | ||
81 | #define BITFIELD5(b1, b2, b3, b4, b5) b5; b4; b3; b2; b1; | ||
82 | #define BITFIELD6(b1, b2, b3, b4, b5, b6) b6; b5; b4; b3; b2; b1; | ||
83 | #else | ||
84 | #error unknown bitfield endianess | ||
85 | #endif | ||
86 | |||
87 | |||
88 | /* ATM cell header (minus HEC byte) */ | ||
89 | |||
90 | typedef struct atm_header { | ||
91 | BITFIELD5( | ||
92 | u32 clp : 1, /* cell loss priority */ | ||
93 | u32 plt : 3, /* payload type */ | ||
94 | u32 vci : 16, /* virtual channel identifier */ | ||
95 | u32 vpi : 8, /* virtual path identifier */ | ||
96 | u32 gfc : 4 /* generic flow control */ | ||
97 | ) | ||
98 | } atm_header_t; | ||
99 | |||
100 | |||
101 | /* ATM adaptation layer id */ | ||
102 | |||
103 | typedef enum fore200e_aal { | ||
104 | FORE200E_AAL0 = 0, | ||
105 | FORE200E_AAL34 = 4, | ||
106 | FORE200E_AAL5 = 5, | ||
107 | } fore200e_aal_t; | ||
108 | |||
109 | |||
110 | /* transmit PDU descriptor specification */ | ||
111 | |||
112 | typedef struct tpd_spec { | ||
113 | BITFIELD4( | ||
114 | u32 length : 16, /* total PDU length */ | ||
115 | u32 nseg : 8, /* number of transmit segments */ | ||
116 | enum fore200e_aal aal : 4, /* adaptation layer */ | ||
117 | u32 intr : 4 /* interrupt requested */ | ||
118 | ) | ||
119 | } tpd_spec_t; | ||
120 | |||
121 | |||
122 | /* transmit PDU rate control */ | ||
123 | |||
124 | typedef struct tpd_rate | ||
125 | { | ||
126 | BITFIELD2( | ||
127 | u32 idle_cells : 16, /* number of idle cells to insert */ | ||
128 | u32 data_cells : 16 /* number of data cells to transmit */ | ||
129 | ) | ||
130 | } tpd_rate_t; | ||
131 | |||
132 | |||
133 | /* transmit segment descriptor */ | ||
134 | |||
135 | typedef struct tsd { | ||
136 | u32 buffer; /* transmit buffer DMA address */ | ||
137 | u32 length; /* number of bytes in buffer */ | ||
138 | } tsd_t; | ||
139 | |||
140 | |||
141 | /* transmit PDU descriptor */ | ||
142 | |||
143 | typedef struct tpd { | ||
144 | struct atm_header atm_header; /* ATM header minus HEC byte */ | ||
145 | struct tpd_spec spec; /* tpd specification */ | ||
146 | struct tpd_rate rate; /* tpd rate control */ | ||
147 | u32 pad; /* reserved */ | ||
148 | struct tsd tsd[ TSD_NBR ]; /* transmit segment descriptors */ | ||
149 | } tpd_t; | ||
150 | |||
151 | |||
152 | /* receive segment descriptor */ | ||
153 | |||
154 | typedef struct rsd { | ||
155 | u32 handle; /* host supplied receive buffer handle */ | ||
156 | u32 length; /* number of bytes in buffer */ | ||
157 | } rsd_t; | ||
158 | |||
159 | |||
160 | /* receive PDU descriptor */ | ||
161 | |||
162 | typedef struct rpd { | ||
163 | struct atm_header atm_header; /* ATM header minus HEC byte */ | ||
164 | u32 nseg; /* number of receive segments */ | ||
165 | struct rsd rsd[ RSD_NBR ]; /* receive segment descriptors */ | ||
166 | } rpd_t; | ||
167 | |||
168 | |||
169 | /* buffer scheme */ | ||
170 | |||
171 | typedef enum buffer_scheme { | ||
172 | BUFFER_SCHEME_ONE, | ||
173 | BUFFER_SCHEME_TWO, | ||
174 | BUFFER_SCHEME_NBR /* always last */ | ||
175 | } buffer_scheme_t; | ||
176 | |||
177 | |||
178 | /* buffer magnitude */ | ||
179 | |||
180 | typedef enum buffer_magn { | ||
181 | BUFFER_MAGN_SMALL, | ||
182 | BUFFER_MAGN_LARGE, | ||
183 | BUFFER_MAGN_NBR /* always last */ | ||
184 | } buffer_magn_t; | ||
185 | |||
186 | |||
187 | /* receive buffer descriptor */ | ||
188 | |||
189 | typedef struct rbd { | ||
190 | u32 handle; /* host supplied handle */ | ||
191 | u32 buffer_haddr; /* host DMA address of host buffer */ | ||
192 | } rbd_t; | ||
193 | |||
194 | |||
195 | /* receive buffer descriptor block */ | ||
196 | |||
197 | typedef struct rbd_block { | ||
198 | struct rbd rbd[ RBD_BLK_SIZE ]; /* receive buffer descriptor */ | ||
199 | } rbd_block_t; | ||
200 | |||
201 | |||
202 | /* tpd DMA address */ | ||
203 | |||
204 | typedef struct tpd_haddr { | ||
205 | BITFIELD3( | ||
206 | u32 size : 4, /* tpd size expressed in 32 byte blocks */ | ||
207 | u32 pad : 1, /* reserved */ | ||
208 | u32 haddr : 27 /* tpd DMA addr aligned on 32 byte boundary */ | ||
209 | ) | ||
210 | } tpd_haddr_t; | ||
211 | |||
212 | #define TPD_HADDR_SHIFT 5 /* addr aligned on 32 byte boundary */ | ||
213 | |||
214 | /* cp resident transmit queue entry */ | ||
215 | |||
216 | typedef struct cp_txq_entry { | ||
217 | struct tpd_haddr tpd_haddr; /* host DMA address of tpd */ | ||
218 | u32 status_haddr; /* host DMA address of completion status */ | ||
219 | } cp_txq_entry_t; | ||
220 | |||
221 | |||
222 | /* cp resident receive queue entry */ | ||
223 | |||
224 | typedef struct cp_rxq_entry { | ||
225 | u32 rpd_haddr; /* host DMA address of rpd */ | ||
226 | u32 status_haddr; /* host DMA address of completion status */ | ||
227 | } cp_rxq_entry_t; | ||
228 | |||
229 | |||
230 | /* cp resident buffer supply queue entry */ | ||
231 | |||
232 | typedef struct cp_bsq_entry { | ||
233 | u32 rbd_block_haddr; /* host DMA address of rbd block */ | ||
234 | u32 status_haddr; /* host DMA address of completion status */ | ||
235 | } cp_bsq_entry_t; | ||
236 | |||
237 | |||
238 | /* completion status */ | ||
239 | |||
240 | typedef volatile enum status { | ||
241 | STATUS_PENDING = (1<<0), /* initial status (written by host) */ | ||
242 | STATUS_COMPLETE = (1<<1), /* completion status (written by cp) */ | ||
243 | STATUS_FREE = (1<<2), /* initial status (written by host) */ | ||
244 | STATUS_ERROR = (1<<3) /* completion status (written by cp) */ | ||
245 | } status_t; | ||
246 | |||
247 | |||
248 | /* cp operation code */ | ||
249 | |||
250 | typedef enum opcode { | ||
251 | OPCODE_INITIALIZE = 1, /* initialize board */ | ||
252 | OPCODE_ACTIVATE_VCIN, /* activate incoming VCI */ | ||
253 | OPCODE_ACTIVATE_VCOUT, /* activate outgoing VCI */ | ||
254 | OPCODE_DEACTIVATE_VCIN, /* deactivate incoming VCI */ | ||
255 | OPCODE_DEACTIVATE_VCOUT, /* deactivate incoing VCI */ | ||
256 | OPCODE_GET_STATS, /* get board statistics */ | ||
257 | OPCODE_SET_OC3, /* set OC-3 registers */ | ||
258 | OPCODE_GET_OC3, /* get OC-3 registers */ | ||
259 | OPCODE_RESET_STATS, /* reset board statistics */ | ||
260 | OPCODE_GET_PROM, /* get expansion PROM data (PCI specific) */ | ||
261 | OPCODE_SET_VPI_BITS, /* set x bits of those decoded by the | ||
262 | firmware to be low order bits from | ||
263 | the VPI field of the ATM cell header */ | ||
264 | OPCODE_REQUEST_INTR = (1<<7) /* request interrupt */ | ||
265 | } opcode_t; | ||
266 | |||
267 | |||
268 | /* virtual path / virtual channel identifers */ | ||
269 | |||
270 | typedef struct vpvc { | ||
271 | BITFIELD3( | ||
272 | u32 vci : 16, /* virtual channel identifier */ | ||
273 | u32 vpi : 8, /* virtual path identifier */ | ||
274 | u32 pad : 8 /* reserved */ | ||
275 | ) | ||
276 | } vpvc_t; | ||
277 | |||
278 | |||
279 | /* activate VC command opcode */ | ||
280 | |||
281 | typedef struct activate_opcode { | ||
282 | BITFIELD4( | ||
283 | enum opcode opcode : 8, /* cp opcode */ | ||
284 | enum fore200e_aal aal : 8, /* adaptation layer */ | ||
285 | enum buffer_scheme scheme : 8, /* buffer scheme */ | ||
286 | u32 pad : 8 /* reserved */ | ||
287 | ) | ||
288 | } activate_opcode_t; | ||
289 | |||
290 | |||
291 | /* activate VC command block */ | ||
292 | |||
293 | typedef struct activate_block { | ||
294 | struct activate_opcode opcode; /* activate VC command opcode */ | ||
295 | struct vpvc vpvc; /* VPI/VCI */ | ||
296 | u32 mtu; /* for AAL0 only */ | ||
297 | |||
298 | } activate_block_t; | ||
299 | |||
300 | |||
301 | /* deactivate VC command opcode */ | ||
302 | |||
303 | typedef struct deactivate_opcode { | ||
304 | BITFIELD2( | ||
305 | enum opcode opcode : 8, /* cp opcode */ | ||
306 | u32 pad : 24 /* reserved */ | ||
307 | ) | ||
308 | } deactivate_opcode_t; | ||
309 | |||
310 | |||
311 | /* deactivate VC command block */ | ||
312 | |||
313 | typedef struct deactivate_block { | ||
314 | struct deactivate_opcode opcode; /* deactivate VC command opcode */ | ||
315 | struct vpvc vpvc; /* VPI/VCI */ | ||
316 | } deactivate_block_t; | ||
317 | |||
318 | |||
319 | /* OC-3 registers */ | ||
320 | |||
321 | typedef struct oc3_regs { | ||
322 | u32 reg[ 128 ]; /* see the PMC Sierra PC5346 S/UNI-155-Lite | ||
323 | Saturn User Network Interface documentation | ||
324 | for a description of the OC-3 chip registers */ | ||
325 | } oc3_regs_t; | ||
326 | |||
327 | |||
328 | /* set/get OC-3 regs command opcode */ | ||
329 | |||
330 | typedef struct oc3_opcode { | ||
331 | BITFIELD4( | ||
332 | enum opcode opcode : 8, /* cp opcode */ | ||
333 | u32 reg : 8, /* register index */ | ||
334 | u32 value : 8, /* register value */ | ||
335 | u32 mask : 8 /* register mask that specifies which | ||
336 | bits of the register value field | ||
337 | are significant */ | ||
338 | ) | ||
339 | } oc3_opcode_t; | ||
340 | |||
341 | |||
342 | /* set/get OC-3 regs command block */ | ||
343 | |||
344 | typedef struct oc3_block { | ||
345 | struct oc3_opcode opcode; /* set/get OC-3 regs command opcode */ | ||
346 | u32 regs_haddr; /* host DMA address of OC-3 regs buffer */ | ||
347 | } oc3_block_t; | ||
348 | |||
349 | |||
350 | /* physical encoding statistics */ | ||
351 | |||
352 | typedef struct stats_phy { | ||
353 | u32 crc_header_errors; /* cells received with bad header CRC */ | ||
354 | u32 framing_errors; /* cells received with bad framing */ | ||
355 | u32 pad[ 2 ]; /* i960 padding */ | ||
356 | } stats_phy_t; | ||
357 | |||
358 | |||
359 | /* OC-3 statistics */ | ||
360 | |||
361 | typedef struct stats_oc3 { | ||
362 | u32 section_bip8_errors; /* section 8 bit interleaved parity */ | ||
363 | u32 path_bip8_errors; /* path 8 bit interleaved parity */ | ||
364 | u32 line_bip24_errors; /* line 24 bit interleaved parity */ | ||
365 | u32 line_febe_errors; /* line far end block errors */ | ||
366 | u32 path_febe_errors; /* path far end block errors */ | ||
367 | u32 corr_hcs_errors; /* correctable header check sequence */ | ||
368 | u32 ucorr_hcs_errors; /* uncorrectable header check sequence */ | ||
369 | u32 pad[ 1 ]; /* i960 padding */ | ||
370 | } stats_oc3_t; | ||
371 | |||
372 | |||
373 | /* ATM statistics */ | ||
374 | |||
375 | typedef struct stats_atm { | ||
376 | u32 cells_transmitted; /* cells transmitted */ | ||
377 | u32 cells_received; /* cells received */ | ||
378 | u32 vpi_bad_range; /* cell drops: VPI out of range */ | ||
379 | u32 vpi_no_conn; /* cell drops: no connection for VPI */ | ||
380 | u32 vci_bad_range; /* cell drops: VCI out of range */ | ||
381 | u32 vci_no_conn; /* cell drops: no connection for VCI */ | ||
382 | u32 pad[ 2 ]; /* i960 padding */ | ||
383 | } stats_atm_t; | ||
384 | |||
385 | /* AAL0 statistics */ | ||
386 | |||
387 | typedef struct stats_aal0 { | ||
388 | u32 cells_transmitted; /* cells transmitted */ | ||
389 | u32 cells_received; /* cells received */ | ||
390 | u32 cells_dropped; /* cells dropped */ | ||
391 | u32 pad[ 1 ]; /* i960 padding */ | ||
392 | } stats_aal0_t; | ||
393 | |||
394 | |||
395 | /* AAL3/4 statistics */ | ||
396 | |||
397 | typedef struct stats_aal34 { | ||
398 | u32 cells_transmitted; /* cells transmitted from segmented PDUs */ | ||
399 | u32 cells_received; /* cells reassembled into PDUs */ | ||
400 | u32 cells_crc_errors; /* payload CRC error count */ | ||
401 | u32 cells_protocol_errors; /* SAR or CS layer protocol errors */ | ||
402 | u32 cells_dropped; /* cells dropped: partial reassembly */ | ||
403 | u32 cspdus_transmitted; /* CS PDUs transmitted */ | ||
404 | u32 cspdus_received; /* CS PDUs received */ | ||
405 | u32 cspdus_protocol_errors; /* CS layer protocol errors */ | ||
406 | u32 cspdus_dropped; /* reassembled PDUs drop'd (in cells) */ | ||
407 | u32 pad[ 3 ]; /* i960 padding */ | ||
408 | } stats_aal34_t; | ||
409 | |||
410 | |||
411 | /* AAL5 statistics */ | ||
412 | |||
413 | typedef struct stats_aal5 { | ||
414 | u32 cells_transmitted; /* cells transmitted from segmented SDUs */ | ||
415 | u32 cells_received; /* cells reassembled into SDUs */ | ||
416 | u32 cells_dropped; /* reassembled PDUs dropped (in cells) */ | ||
417 | u32 congestion_experienced; /* CRC error and length wrong */ | ||
418 | u32 cspdus_transmitted; /* CS PDUs transmitted */ | ||
419 | u32 cspdus_received; /* CS PDUs received */ | ||
420 | u32 cspdus_crc_errors; /* CS PDUs CRC errors */ | ||
421 | u32 cspdus_protocol_errors; /* CS layer protocol errors */ | ||
422 | u32 cspdus_dropped; /* reassembled PDUs dropped */ | ||
423 | u32 pad[ 3 ]; /* i960 padding */ | ||
424 | } stats_aal5_t; | ||
425 | |||
426 | |||
427 | /* auxiliary statistics */ | ||
428 | |||
429 | typedef struct stats_aux { | ||
430 | u32 small_b1_failed; /* receive BD allocation failures */ | ||
431 | u32 large_b1_failed; /* receive BD allocation failures */ | ||
432 | u32 small_b2_failed; /* receive BD allocation failures */ | ||
433 | u32 large_b2_failed; /* receive BD allocation failures */ | ||
434 | u32 rpd_alloc_failed; /* receive PDU allocation failures */ | ||
435 | u32 receive_carrier; /* no carrier = 0, carrier = 1 */ | ||
436 | u32 pad[ 2 ]; /* i960 padding */ | ||
437 | } stats_aux_t; | ||
438 | |||
439 | |||
440 | /* whole statistics buffer */ | ||
441 | |||
442 | typedef struct stats { | ||
443 | struct stats_phy phy; /* physical encoding statistics */ | ||
444 | struct stats_oc3 oc3; /* OC-3 statistics */ | ||
445 | struct stats_atm atm; /* ATM statistics */ | ||
446 | struct stats_aal0 aal0; /* AAL0 statistics */ | ||
447 | struct stats_aal34 aal34; /* AAL3/4 statistics */ | ||
448 | struct stats_aal5 aal5; /* AAL5 statistics */ | ||
449 | struct stats_aux aux; /* auxiliary statistics */ | ||
450 | } stats_t; | ||
451 | |||
452 | |||
453 | /* get statistics command opcode */ | ||
454 | |||
455 | typedef struct stats_opcode { | ||
456 | BITFIELD2( | ||
457 | enum opcode opcode : 8, /* cp opcode */ | ||
458 | u32 pad : 24 /* reserved */ | ||
459 | ) | ||
460 | } stats_opcode_t; | ||
461 | |||
462 | |||
463 | /* get statistics command block */ | ||
464 | |||
465 | typedef struct stats_block { | ||
466 | struct stats_opcode opcode; /* get statistics command opcode */ | ||
467 | u32 stats_haddr; /* host DMA address of stats buffer */ | ||
468 | } stats_block_t; | ||
469 | |||
470 | |||
471 | /* expansion PROM data (PCI specific) */ | ||
472 | |||
473 | typedef struct prom_data { | ||
474 | u32 hw_revision; /* hardware revision */ | ||
475 | u32 serial_number; /* board serial number */ | ||
476 | u8 mac_addr[ 8 ]; /* board MAC address */ | ||
477 | } prom_data_t; | ||
478 | |||
479 | |||
480 | /* get expansion PROM data command opcode */ | ||
481 | |||
482 | typedef struct prom_opcode { | ||
483 | BITFIELD2( | ||
484 | enum opcode opcode : 8, /* cp opcode */ | ||
485 | u32 pad : 24 /* reserved */ | ||
486 | ) | ||
487 | } prom_opcode_t; | ||
488 | |||
489 | |||
490 | /* get expansion PROM data command block */ | ||
491 | |||
492 | typedef struct prom_block { | ||
493 | struct prom_opcode opcode; /* get PROM data command opcode */ | ||
494 | u32 prom_haddr; /* host DMA address of PROM buffer */ | ||
495 | } prom_block_t; | ||
496 | |||
497 | |||
498 | /* cp command */ | ||
499 | |||
500 | typedef union cmd { | ||
501 | enum opcode opcode; /* operation code */ | ||
502 | struct activate_block activate_block; /* activate VC */ | ||
503 | struct deactivate_block deactivate_block; /* deactivate VC */ | ||
504 | struct stats_block stats_block; /* get statistics */ | ||
505 | struct prom_block prom_block; /* get expansion PROM data */ | ||
506 | struct oc3_block oc3_block; /* get/set OC-3 registers */ | ||
507 | u32 pad[ 4 ]; /* i960 padding */ | ||
508 | } cmd_t; | ||
509 | |||
510 | |||
511 | /* cp resident command queue */ | ||
512 | |||
513 | typedef struct cp_cmdq_entry { | ||
514 | union cmd cmd; /* command */ | ||
515 | u32 status_haddr; /* host DMA address of completion status */ | ||
516 | u32 pad[ 3 ]; /* i960 padding */ | ||
517 | } cp_cmdq_entry_t; | ||
518 | |||
519 | |||
520 | /* host resident transmit queue entry */ | ||
521 | |||
522 | typedef struct host_txq_entry { | ||
523 | struct cp_txq_entry __iomem *cp_entry; /* addr of cp resident tx queue entry */ | ||
524 | enum status* status; /* addr of host resident status */ | ||
525 | struct tpd* tpd; /* addr of transmit PDU descriptor */ | ||
526 | u32 tpd_dma; /* DMA address of tpd */ | ||
527 | struct sk_buff* skb; /* related skb */ | ||
528 | void* data; /* copy of misaligned data */ | ||
529 | unsigned long incarn; /* vc_map incarnation when submitted for tx */ | ||
530 | struct fore200e_vc_map* vc_map; | ||
531 | |||
532 | } host_txq_entry_t; | ||
533 | |||
534 | |||
535 | /* host resident receive queue entry */ | ||
536 | |||
537 | typedef struct host_rxq_entry { | ||
538 | struct cp_rxq_entry __iomem *cp_entry; /* addr of cp resident rx queue entry */ | ||
539 | enum status* status; /* addr of host resident status */ | ||
540 | struct rpd* rpd; /* addr of receive PDU descriptor */ | ||
541 | u32 rpd_dma; /* DMA address of rpd */ | ||
542 | } host_rxq_entry_t; | ||
543 | |||
544 | |||
545 | /* host resident buffer supply queue entry */ | ||
546 | |||
547 | typedef struct host_bsq_entry { | ||
548 | struct cp_bsq_entry __iomem *cp_entry; /* addr of cp resident buffer supply queue entry */ | ||
549 | enum status* status; /* addr of host resident status */ | ||
550 | struct rbd_block* rbd_block; /* addr of receive buffer descriptor block */ | ||
551 | u32 rbd_block_dma; /* DMA address od rdb */ | ||
552 | } host_bsq_entry_t; | ||
553 | |||
554 | |||
555 | /* host resident command queue entry */ | ||
556 | |||
557 | typedef struct host_cmdq_entry { | ||
558 | struct cp_cmdq_entry __iomem *cp_entry; /* addr of cp resident cmd queue entry */ | ||
559 | enum status *status; /* addr of host resident status */ | ||
560 | } host_cmdq_entry_t; | ||
561 | |||
562 | |||
563 | /* chunk of memory */ | ||
564 | |||
565 | typedef struct chunk { | ||
566 | void* alloc_addr; /* base address of allocated chunk */ | ||
567 | void* align_addr; /* base address of aligned chunk */ | ||
568 | dma_addr_t dma_addr; /* DMA address of aligned chunk */ | ||
569 | int direction; /* direction of DMA mapping */ | ||
570 | u32 alloc_size; /* length of allocated chunk */ | ||
571 | u32 align_size; /* length of aligned chunk */ | ||
572 | } chunk_t; | ||
573 | |||
574 | #define dma_size align_size /* DMA useable size */ | ||
575 | |||
576 | |||
577 | /* host resident receive buffer */ | ||
578 | |||
579 | typedef struct buffer { | ||
580 | struct buffer* next; /* next receive buffer */ | ||
581 | enum buffer_scheme scheme; /* buffer scheme */ | ||
582 | enum buffer_magn magn; /* buffer magnitude */ | ||
583 | struct chunk data; /* data buffer */ | ||
584 | #ifdef FORE200E_BSQ_DEBUG | ||
585 | unsigned long index; /* buffer # in queue */ | ||
586 | int supplied; /* 'buffer supplied' flag */ | ||
587 | #endif | ||
588 | } buffer_t; | ||
589 | |||
590 | |||
591 | #if (BITS_PER_LONG == 32) | ||
592 | #define FORE200E_BUF2HDL(buffer) ((u32)(buffer)) | ||
593 | #define FORE200E_HDL2BUF(handle) ((struct buffer*)(handle)) | ||
594 | #else /* deal with 64 bit pointers */ | ||
595 | #define FORE200E_BUF2HDL(buffer) ((u32)((u64)(buffer))) | ||
596 | #define FORE200E_HDL2BUF(handle) ((struct buffer*)(((u64)(handle)) | PAGE_OFFSET)) | ||
597 | #endif | ||
598 | |||
599 | |||
600 | /* host resident command queue */ | ||
601 | |||
602 | typedef struct host_cmdq { | ||
603 | struct host_cmdq_entry host_entry[ QUEUE_SIZE_CMD ]; /* host resident cmd queue entries */ | ||
604 | int head; /* head of cmd queue */ | ||
605 | struct chunk status; /* array of completion status */ | ||
606 | } host_cmdq_t; | ||
607 | |||
608 | |||
609 | /* host resident transmit queue */ | ||
610 | |||
611 | typedef struct host_txq { | ||
612 | struct host_txq_entry host_entry[ QUEUE_SIZE_TX ]; /* host resident tx queue entries */ | ||
613 | int head; /* head of tx queue */ | ||
614 | int tail; /* tail of tx queue */ | ||
615 | struct chunk tpd; /* array of tpds */ | ||
616 | struct chunk status; /* arry of completion status */ | ||
617 | int txing; /* number of pending PDUs in tx queue */ | ||
618 | } host_txq_t; | ||
619 | |||
620 | |||
621 | /* host resident receive queue */ | ||
622 | |||
623 | typedef struct host_rxq { | ||
624 | struct host_rxq_entry host_entry[ QUEUE_SIZE_RX ]; /* host resident rx queue entries */ | ||
625 | int head; /* head of rx queue */ | ||
626 | struct chunk rpd; /* array of rpds */ | ||
627 | struct chunk status; /* array of completion status */ | ||
628 | } host_rxq_t; | ||
629 | |||
630 | |||
631 | /* host resident buffer supply queues */ | ||
632 | |||
633 | typedef struct host_bsq { | ||
634 | struct host_bsq_entry host_entry[ QUEUE_SIZE_BS ]; /* host resident buffer supply queue entries */ | ||
635 | int head; /* head of buffer supply queue */ | ||
636 | struct chunk rbd_block; /* array of rbds */ | ||
637 | struct chunk status; /* array of completion status */ | ||
638 | struct buffer* buffer; /* array of rx buffers */ | ||
639 | struct buffer* freebuf; /* list of free rx buffers */ | ||
640 | volatile int freebuf_count; /* count of free rx buffers */ | ||
641 | } host_bsq_t; | ||
642 | |||
643 | |||
644 | /* header of the firmware image */ | ||
645 | |||
646 | typedef struct fw_header { | ||
647 | u32 magic; /* magic number */ | ||
648 | u32 version; /* firmware version id */ | ||
649 | u32 load_offset; /* fw load offset in board memory */ | ||
650 | u32 start_offset; /* fw execution start address in board memory */ | ||
651 | } fw_header_t; | ||
652 | |||
653 | #define FW_HEADER_MAGIC 0x65726f66 /* 'fore' */ | ||
654 | |||
655 | |||
656 | /* receive buffer supply queues scheme specification */ | ||
657 | |||
658 | typedef struct bs_spec { | ||
659 | u32 queue_length; /* queue capacity */ | ||
660 | u32 buffer_size; /* host buffer size */ | ||
661 | u32 pool_size; /* number of rbds */ | ||
662 | u32 supply_blksize; /* num of rbds in I/O block (multiple | ||
663 | of 4 between 4 and 124 inclusive) */ | ||
664 | } bs_spec_t; | ||
665 | |||
666 | |||
667 | /* initialization command block (one-time command, not in cmd queue) */ | ||
668 | |||
669 | typedef struct init_block { | ||
670 | enum opcode opcode; /* initialize command */ | ||
671 | enum status status; /* related status word */ | ||
672 | u32 receive_threshold; /* not used */ | ||
673 | u32 num_connect; /* ATM connections */ | ||
674 | u32 cmd_queue_len; /* length of command queue */ | ||
675 | u32 tx_queue_len; /* length of transmit queue */ | ||
676 | u32 rx_queue_len; /* length of receive queue */ | ||
677 | u32 rsd_extension; /* number of extra 32 byte blocks */ | ||
678 | u32 tsd_extension; /* number of extra 32 byte blocks */ | ||
679 | u32 conless_vpvc; /* not used */ | ||
680 | u32 pad[ 2 ]; /* force quad alignment */ | ||
681 | struct bs_spec bs_spec[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ]; /* buffer supply queues spec */ | ||
682 | } init_block_t; | ||
683 | |||
684 | |||
685 | typedef enum media_type { | ||
686 | MEDIA_TYPE_CAT5_UTP = 0x06, /* unshielded twisted pair */ | ||
687 | MEDIA_TYPE_MM_OC3_ST = 0x16, /* multimode fiber ST */ | ||
688 | MEDIA_TYPE_MM_OC3_SC = 0x26, /* multimode fiber SC */ | ||
689 | MEDIA_TYPE_SM_OC3_ST = 0x36, /* single-mode fiber ST */ | ||
690 | MEDIA_TYPE_SM_OC3_SC = 0x46 /* single-mode fiber SC */ | ||
691 | } media_type_t; | ||
692 | |||
693 | #define FORE200E_MEDIA_INDEX(media_type) ((media_type)>>4) | ||
694 | |||
695 | |||
696 | /* cp resident queues */ | ||
697 | |||
698 | typedef struct cp_queues { | ||
699 | u32 cp_cmdq; /* command queue */ | ||
700 | u32 cp_txq; /* transmit queue */ | ||
701 | u32 cp_rxq; /* receive queue */ | ||
702 | u32 cp_bsq[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ]; /* buffer supply queues */ | ||
703 | u32 imask; /* 1 enables cp to host interrupts */ | ||
704 | u32 istat; /* 1 for interrupt posted */ | ||
705 | u32 heap_base; /* offset form beginning of ram */ | ||
706 | u32 heap_size; /* space available for queues */ | ||
707 | u32 hlogger; /* non zero for host logging */ | ||
708 | u32 heartbeat; /* cp heartbeat */ | ||
709 | u32 fw_release; /* firmware version */ | ||
710 | u32 mon960_release; /* i960 monitor version */ | ||
711 | u32 tq_plen; /* transmit throughput measurements */ | ||
712 | /* make sure the init block remains on a quad word boundary */ | ||
713 | struct init_block init; /* one time cmd, not in cmd queue */ | ||
714 | enum media_type media_type; /* media type id */ | ||
715 | u32 oc3_revision; /* OC-3 revision number */ | ||
716 | } cp_queues_t; | ||
717 | |||
718 | |||
719 | /* boot status */ | ||
720 | |||
721 | typedef enum boot_status { | ||
722 | BSTAT_COLD_START = (u32) 0xc01dc01d, /* cold start */ | ||
723 | BSTAT_SELFTEST_OK = (u32) 0x02201958, /* self-test ok */ | ||
724 | BSTAT_SELFTEST_FAIL = (u32) 0xadbadbad, /* self-test failed */ | ||
725 | BSTAT_CP_RUNNING = (u32) 0xce11feed, /* cp is running */ | ||
726 | BSTAT_MON_TOO_BIG = (u32) 0x10aded00 /* i960 monitor is too big */ | ||
727 | } boot_status_t; | ||
728 | |||
729 | |||
730 | /* software UART */ | ||
731 | |||
732 | typedef struct soft_uart { | ||
733 | u32 send; /* write register */ | ||
734 | u32 recv; /* read register */ | ||
735 | } soft_uart_t; | ||
736 | |||
737 | #define FORE200E_CP_MONITOR_UART_FREE 0x00000000 | ||
738 | #define FORE200E_CP_MONITOR_UART_AVAIL 0x01000000 | ||
739 | |||
740 | |||
741 | /* i960 monitor */ | ||
742 | |||
743 | typedef struct cp_monitor { | ||
744 | struct soft_uart soft_uart; /* software UART */ | ||
745 | enum boot_status bstat; /* boot status */ | ||
746 | u32 app_base; /* application base offset */ | ||
747 | u32 mon_version; /* i960 monitor version */ | ||
748 | } cp_monitor_t; | ||
749 | |||
750 | |||
751 | /* device state */ | ||
752 | |||
753 | typedef enum fore200e_state { | ||
754 | FORE200E_STATE_BLANK, /* initial state */ | ||
755 | FORE200E_STATE_REGISTER, /* device registered */ | ||
756 | FORE200E_STATE_CONFIGURE, /* bus interface configured */ | ||
757 | FORE200E_STATE_MAP, /* board space mapped in host memory */ | ||
758 | FORE200E_STATE_RESET, /* board resetted */ | ||
759 | FORE200E_STATE_LOAD_FW, /* firmware loaded */ | ||
760 | FORE200E_STATE_START_FW, /* firmware started */ | ||
761 | FORE200E_STATE_INITIALIZE, /* initialize command successful */ | ||
762 | FORE200E_STATE_INIT_CMDQ, /* command queue initialized */ | ||
763 | FORE200E_STATE_INIT_TXQ, /* transmit queue initialized */ | ||
764 | FORE200E_STATE_INIT_RXQ, /* receive queue initialized */ | ||
765 | FORE200E_STATE_INIT_BSQ, /* buffer supply queue initialized */ | ||
766 | FORE200E_STATE_ALLOC_BUF, /* receive buffers allocated */ | ||
767 | FORE200E_STATE_IRQ, /* host interrupt requested */ | ||
768 | FORE200E_STATE_COMPLETE /* initialization completed */ | ||
769 | } fore200e_state; | ||
770 | |||
771 | |||
772 | /* PCA-200E registers */ | ||
773 | |||
774 | typedef struct fore200e_pca_regs { | ||
775 | volatile u32 __iomem * hcr; /* address of host control register */ | ||
776 | volatile u32 __iomem * imr; /* address of host interrupt mask register */ | ||
777 | volatile u32 __iomem * psr; /* address of PCI specific register */ | ||
778 | } fore200e_pca_regs_t; | ||
779 | |||
780 | |||
781 | /* SBA-200E registers */ | ||
782 | |||
783 | typedef struct fore200e_sba_regs { | ||
784 | volatile u32 __iomem *hcr; /* address of host control register */ | ||
785 | volatile u32 __iomem *bsr; /* address of burst transfer size register */ | ||
786 | volatile u32 __iomem *isr; /* address of interrupt level selection register */ | ||
787 | } fore200e_sba_regs_t; | ||
788 | |||
789 | |||
790 | /* model-specific registers */ | ||
791 | |||
792 | typedef union fore200e_regs { | ||
793 | struct fore200e_pca_regs pca; /* PCA-200E registers */ | ||
794 | struct fore200e_sba_regs sba; /* SBA-200E registers */ | ||
795 | } fore200e_regs; | ||
796 | |||
797 | |||
798 | struct fore200e; | ||
799 | |||
800 | /* bus-dependent data */ | ||
801 | |||
802 | typedef struct fore200e_bus { | ||
803 | char* model_name; /* board model name */ | ||
804 | char* proc_name; /* board name under /proc/atm */ | ||
805 | int descr_alignment; /* tpd/rpd/rbd DMA alignment requirement */ | ||
806 | int buffer_alignment; /* rx buffers DMA alignment requirement */ | ||
807 | int status_alignment; /* status words DMA alignment requirement */ | ||
808 | const unsigned char* fw_data; /* address of firmware data start */ | ||
809 | const unsigned int* fw_size; /* address of firmware data size */ | ||
810 | u32 (*read)(volatile u32 __iomem *); | ||
811 | void (*write)(u32, volatile u32 __iomem *); | ||
812 | u32 (*dma_map)(struct fore200e*, void*, int, int); | ||
813 | void (*dma_unmap)(struct fore200e*, u32, int, int); | ||
814 | void (*dma_sync_for_cpu)(struct fore200e*, u32, int, int); | ||
815 | void (*dma_sync_for_device)(struct fore200e*, u32, int, int); | ||
816 | int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); | ||
817 | void (*dma_chunk_free)(struct fore200e*, struct chunk*); | ||
818 | struct fore200e* (*detect)(const struct fore200e_bus*, int); | ||
819 | int (*configure)(struct fore200e*); | ||
820 | int (*map)(struct fore200e*); | ||
821 | void (*reset)(struct fore200e*); | ||
822 | int (*prom_read)(struct fore200e*, struct prom_data*); | ||
823 | void (*unmap)(struct fore200e*); | ||
824 | void (*irq_enable)(struct fore200e*); | ||
825 | int (*irq_check)(struct fore200e*); | ||
826 | void (*irq_ack)(struct fore200e*); | ||
827 | int (*proc_read)(struct fore200e*, char*); | ||
828 | } fore200e_bus_t; | ||
829 | |||
830 | /* vc mapping */ | ||
831 | |||
832 | typedef struct fore200e_vc_map { | ||
833 | struct atm_vcc* vcc; /* vcc entry */ | ||
834 | unsigned long incarn; /* vcc incarnation number */ | ||
835 | } fore200e_vc_map_t; | ||
836 | |||
837 | #define FORE200E_VC_MAP(fore200e, vpi, vci) \ | ||
838 | (& (fore200e)->vc_map[ ((vpi) << FORE200E_VCI_BITS) | (vci) ]) | ||
839 | |||
840 | |||
841 | /* per-device data */ | ||
842 | |||
843 | typedef struct fore200e { | ||
844 | struct list_head entry; /* next device */ | ||
845 | const struct fore200e_bus* bus; /* bus-dependent code and data */ | ||
846 | union fore200e_regs regs; /* bus-dependent registers */ | ||
847 | struct atm_dev* atm_dev; /* ATM device */ | ||
848 | |||
849 | enum fore200e_state state; /* device state */ | ||
850 | |||
851 | char name[16]; /* device name */ | ||
852 | void* bus_dev; /* bus-specific kernel data */ | ||
853 | int irq; /* irq number */ | ||
854 | unsigned long phys_base; /* physical base address */ | ||
855 | void __iomem * virt_base; /* virtual base address */ | ||
856 | |||
857 | unsigned char esi[ ESI_LEN ]; /* end system identifier */ | ||
858 | |||
859 | struct cp_monitor __iomem * cp_monitor; /* i960 monitor address */ | ||
860 | struct cp_queues __iomem * cp_queues; /* cp resident queues */ | ||
861 | struct host_cmdq host_cmdq; /* host resident cmd queue */ | ||
862 | struct host_txq host_txq; /* host resident tx queue */ | ||
863 | struct host_rxq host_rxq; /* host resident rx queue */ | ||
864 | /* host resident buffer supply queues */ | ||
865 | struct host_bsq host_bsq[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ]; | ||
866 | |||
867 | u32 available_cell_rate; /* remaining pseudo-CBR bw on link */ | ||
868 | |||
869 | int loop_mode; /* S/UNI loopback mode */ | ||
870 | |||
871 | struct stats* stats; /* last snapshot of the stats */ | ||
872 | |||
873 | struct semaphore rate_sf; /* protects rate reservation ops */ | ||
874 | spinlock_t q_lock; /* protects queue ops */ | ||
875 | #ifdef FORE200E_USE_TASKLET | ||
876 | struct tasklet_struct tx_tasklet; /* performs tx interrupt work */ | ||
877 | struct tasklet_struct rx_tasklet; /* performs rx interrupt work */ | ||
878 | #endif | ||
879 | unsigned long tx_sat; /* tx queue saturation count */ | ||
880 | |||
881 | unsigned long incarn_count; | ||
882 | struct fore200e_vc_map vc_map[ NBR_CONNECT ]; /* vc mapping */ | ||
883 | } fore200e_t; | ||
884 | |||
885 | |||
886 | /* per-vcc data */ | ||
887 | |||
888 | typedef struct fore200e_vcc { | ||
889 | enum buffer_scheme scheme; /* rx buffer scheme */ | ||
890 | struct tpd_rate rate; /* tx rate control data */ | ||
891 | int rx_min_pdu; /* size of smallest PDU received */ | ||
892 | int rx_max_pdu; /* size of largest PDU received */ | ||
893 | int tx_min_pdu; /* size of smallest PDU transmitted */ | ||
894 | int tx_max_pdu; /* size of largest PDU transmitted */ | ||
895 | unsigned long tx_pdu; /* nbr of tx pdus */ | ||
896 | unsigned long rx_pdu; /* nbr of rx pdus */ | ||
897 | } fore200e_vcc_t; | ||
898 | |||
899 | |||
900 | |||
901 | /* 200E-series common memory layout */ | ||
902 | |||
903 | #define FORE200E_CP_MONITOR_OFFSET 0x00000400 /* i960 monitor interface */ | ||
904 | #define FORE200E_CP_QUEUES_OFFSET 0x00004d40 /* cp resident queues */ | ||
905 | |||
906 | |||
907 | /* PCA-200E memory layout */ | ||
908 | |||
909 | #define PCA200E_IOSPACE_LENGTH 0x00200000 | ||
910 | |||
911 | #define PCA200E_HCR_OFFSET 0x00100000 /* board control register */ | ||
912 | #define PCA200E_IMR_OFFSET 0x00100004 /* host IRQ mask register */ | ||
913 | #define PCA200E_PSR_OFFSET 0x00100008 /* PCI specific register */ | ||
914 | |||
915 | |||
916 | /* PCA-200E host control register */ | ||
917 | |||
918 | #define PCA200E_HCR_RESET (1<<0) /* read / write */ | ||
919 | #define PCA200E_HCR_HOLD_LOCK (1<<1) /* read / write */ | ||
920 | #define PCA200E_HCR_I960FAIL (1<<2) /* read */ | ||
921 | #define PCA200E_HCR_INTRB (1<<2) /* write */ | ||
922 | #define PCA200E_HCR_HOLD_ACK (1<<3) /* read */ | ||
923 | #define PCA200E_HCR_INTRA (1<<3) /* write */ | ||
924 | #define PCA200E_HCR_OUTFULL (1<<4) /* read */ | ||
925 | #define PCA200E_HCR_CLRINTR (1<<4) /* write */ | ||
926 | #define PCA200E_HCR_ESPHOLD (1<<5) /* read */ | ||
927 | #define PCA200E_HCR_INFULL (1<<6) /* read */ | ||
928 | #define PCA200E_HCR_TESTMODE (1<<7) /* read */ | ||
929 | |||
930 | |||
931 | /* PCA-200E PCI bus interface regs (offsets in PCI config space) */ | ||
932 | |||
933 | #define PCA200E_PCI_LATENCY 0x40 /* maximum slave latenty */ | ||
934 | #define PCA200E_PCI_MASTER_CTRL 0x41 /* master control */ | ||
935 | #define PCA200E_PCI_THRESHOLD 0x42 /* burst / continous req threshold */ | ||
936 | |||
937 | /* PBI master control register */ | ||
938 | |||
939 | #define PCA200E_CTRL_DIS_CACHE_RD (1<<0) /* disable cache-line reads */ | ||
940 | #define PCA200E_CTRL_DIS_WRT_INVAL (1<<1) /* disable writes and invalidates */ | ||
941 | #define PCA200E_CTRL_2_CACHE_WRT_INVAL (1<<2) /* require 2 cache-lines for writes and invalidates */ | ||
942 | #define PCA200E_CTRL_IGN_LAT_TIMER (1<<3) /* ignore the latency timer */ | ||
943 | #define PCA200E_CTRL_ENA_CONT_REQ_MODE (1<<4) /* enable continuous request mode */ | ||
944 | #define PCA200E_CTRL_LARGE_PCI_BURSTS (1<<5) /* force large PCI bus bursts */ | ||
945 | #define PCA200E_CTRL_CONVERT_ENDIAN (1<<6) /* convert endianess of slave RAM accesses */ | ||
946 | |||
947 | |||
948 | |||
949 | #define SBA200E_PROM_NAME "FORE,sba-200e" /* device name in openprom tree */ | ||
950 | |||
951 | |||
952 | /* size of SBA-200E registers */ | ||
953 | |||
954 | #define SBA200E_HCR_LENGTH 4 | ||
955 | #define SBA200E_BSR_LENGTH 4 | ||
956 | #define SBA200E_ISR_LENGTH 4 | ||
957 | #define SBA200E_RAM_LENGTH 0x40000 | ||
958 | |||
959 | |||
960 | /* SBA-200E SBUS burst transfer size register */ | ||
961 | |||
962 | #define SBA200E_BSR_BURST4 0x04 | ||
963 | #define SBA200E_BSR_BURST8 0x08 | ||
964 | #define SBA200E_BSR_BURST16 0x10 | ||
965 | |||
966 | |||
967 | /* SBA-200E host control register */ | ||
968 | |||
969 | #define SBA200E_HCR_RESET (1<<0) /* read / write (sticky) */ | ||
970 | #define SBA200E_HCR_HOLD_LOCK (1<<1) /* read / write (sticky) */ | ||
971 | #define SBA200E_HCR_I960FAIL (1<<2) /* read */ | ||
972 | #define SBA200E_HCR_I960SETINTR (1<<2) /* write */ | ||
973 | #define SBA200E_HCR_OUTFULL (1<<3) /* read */ | ||
974 | #define SBA200E_HCR_INTR_CLR (1<<3) /* write */ | ||
975 | #define SBA200E_HCR_INTR_ENA (1<<4) /* read / write (sticky) */ | ||
976 | #define SBA200E_HCR_ESPHOLD (1<<5) /* read */ | ||
977 | #define SBA200E_HCR_INFULL (1<<6) /* read */ | ||
978 | #define SBA200E_HCR_TESTMODE (1<<7) /* read */ | ||
979 | #define SBA200E_HCR_INTR_REQ (1<<8) /* read */ | ||
980 | |||
981 | #define SBA200E_HCR_STICKY (SBA200E_HCR_RESET | SBA200E_HCR_HOLD_LOCK | SBA200E_HCR_INTR_ENA) | ||
982 | |||
983 | |||
984 | #endif /* __KERNEL__ */ | ||
985 | #endif /* _FORE200E_H */ | ||
diff --git a/drivers/atm/fore200e_firmware_copyright b/drivers/atm/fore200e_firmware_copyright new file mode 100644 index 000000000000..d58e6490836e --- /dev/null +++ b/drivers/atm/fore200e_firmware_copyright | |||
@@ -0,0 +1,31 @@ | |||
1 | |||
2 | These microcode data are placed under the terms of the GNU General Public License. | ||
3 | |||
4 | We would prefer you not to distribute modified versions of it and not to ask | ||
5 | for assembly or other microcode source. | ||
6 | |||
7 | Copyright (c) 1995-2000 FORE Systems, Inc., as an unpublished work. This | ||
8 | notice does not imply unrestricted or public access to these materials which | ||
9 | are a trade secret of FORE Systems, Inc. or its subsidiaries or affiliates | ||
10 | (together referred to as "FORE"), and which may not be reproduced, used, sold | ||
11 | or transferred to any third party without FORE's prior written consent. All | ||
12 | rights reserved. | ||
13 | |||
14 | U.S. Government Restricted Rights. If you are licensing the Software on | ||
15 | behalf of the U.S. Government ("Government"), the following provisions apply | ||
16 | to you. If the software is supplied to the Department of Defense ("DoD"), it | ||
17 | is classified as "Commercial Computer Software" under paragraph 252.227-7014 | ||
18 | of the DoD Supplement to the Federal Acquisition Regulations ("DFARS") (or any | ||
19 | successor regulations) and the Government is acquiring only the license | ||
20 | rights granted herein (the license rights customarily provided to non-Government | ||
21 | users). If the Software is supplied to any unit or agency of the Government | ||
22 | other than the DoD, it is classified as "Restricted Computer Software" and | ||
23 | the Government's rights in the Software are defined in paragraph 52.227-19 of | ||
24 | the Federal Acquisition Regulations ("FAR") (or any successor regulations) or, | ||
25 | in the cases of NASA, in paragraph 18.52.227-86 of the NASA Supplement to the FAR | ||
26 | (or any successor regulations). | ||
27 | |||
28 | FORE Systems is a registered trademark, and ForeRunner, ForeRunnerLE, and | ||
29 | ForeThought are trademarks of FORE Systems, Inc. All other brands or product | ||
30 | names are trademarks or registered trademarks of their respective holders. | ||
31 | |||
diff --git a/drivers/atm/fore200e_mkfirm.c b/drivers/atm/fore200e_mkfirm.c new file mode 100644 index 000000000000..2ebe1a1e6f8b --- /dev/null +++ b/drivers/atm/fore200e_mkfirm.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | $Id: fore200e_mkfirm.c,v 1.1 2000/02/21 16:04:32 davem Exp $ | ||
3 | |||
4 | mkfirm.c: generates a C readable file from a binary firmware image | ||
5 | |||
6 | Christophe Lizzi (lizzi@{csti.fr, cnam.fr}), June 1999. | ||
7 | |||
8 | This software may be used and distributed according to the terms | ||
9 | of the GNU General Public License, incorporated herein by reference. | ||
10 | */ | ||
11 | |||
12 | #include <stdio.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <sys/types.h> | ||
15 | #include <time.h> | ||
16 | |||
17 | char* default_basename = "pca200e"; /* was initially written for the PCA-200E firmware */ | ||
18 | char* default_infname = "<stdin>"; | ||
19 | char* default_outfname = "<stdout>"; | ||
20 | |||
21 | char* progname; | ||
22 | int verbose = 0; | ||
23 | int inkernel = 0; | ||
24 | |||
25 | |||
26 | void usage(void) | ||
27 | { | ||
28 | fprintf(stderr, | ||
29 | "%s: [-v] [-k] [-b basename ] [-i firmware.bin] [-o firmware.c]\n", | ||
30 | progname); | ||
31 | exit(-1); | ||
32 | } | ||
33 | |||
34 | |||
35 | int main(int argc, char** argv) | ||
36 | { | ||
37 | time_t now; | ||
38 | char* infname = NULL; | ||
39 | char* outfname = NULL; | ||
40 | char* basename = NULL; | ||
41 | FILE* infile; | ||
42 | FILE* outfile; | ||
43 | unsigned firmsize; | ||
44 | int c; | ||
45 | |||
46 | progname = *(argv++); | ||
47 | |||
48 | while (argc > 1) { | ||
49 | if ((*argv)[0] == '-') { | ||
50 | switch ((*argv)[1]) { | ||
51 | case 'i': | ||
52 | if (argc-- < 3) | ||
53 | usage(); | ||
54 | infname = *(++argv); | ||
55 | break; | ||
56 | case 'o': | ||
57 | if (argc-- < 3) | ||
58 | usage(); | ||
59 | outfname = *(++argv); | ||
60 | break; | ||
61 | case 'b': | ||
62 | if (argc-- < 3) | ||
63 | usage(); | ||
64 | basename = *(++argv); | ||
65 | break; | ||
66 | case 'v': | ||
67 | verbose = 1; | ||
68 | break; | ||
69 | case 'k': | ||
70 | inkernel = 1; | ||
71 | break; | ||
72 | default: | ||
73 | usage(); | ||
74 | } | ||
75 | } | ||
76 | else { | ||
77 | usage(); | ||
78 | } | ||
79 | argc--; | ||
80 | argv++; | ||
81 | } | ||
82 | |||
83 | if (infname != NULL) { | ||
84 | infile = fopen(infname, "r"); | ||
85 | if (infile == NULL) { | ||
86 | fprintf(stderr, "%s: can't open %s for reading\n", | ||
87 | progname, infname); | ||
88 | exit(-2); | ||
89 | } | ||
90 | } | ||
91 | else { | ||
92 | infile = stdin; | ||
93 | infname = default_infname; | ||
94 | } | ||
95 | |||
96 | if (outfname) { | ||
97 | outfile = fopen(outfname, "w"); | ||
98 | if (outfile == NULL) { | ||
99 | fprintf(stderr, "%s: can't open %s for writing\n", | ||
100 | progname, outfname); | ||
101 | exit(-3); | ||
102 | } | ||
103 | } | ||
104 | else { | ||
105 | outfile = stdout; | ||
106 | outfname = default_outfname; | ||
107 | } | ||
108 | |||
109 | if (basename == NULL) | ||
110 | basename = default_basename; | ||
111 | |||
112 | if (verbose) { | ||
113 | fprintf(stderr, "%s: input file = %s\n", progname, infname ); | ||
114 | fprintf(stderr, "%s: output file = %s\n", progname, outfname ); | ||
115 | fprintf(stderr, "%s: firmware basename = %s\n", progname, basename ); | ||
116 | } | ||
117 | |||
118 | time(&now); | ||
119 | fprintf(outfile, "/*\n generated by %s from %s on %s" | ||
120 | " DO NOT EDIT!\n*/\n\n", | ||
121 | progname, infname, ctime(&now)); | ||
122 | |||
123 | if (inkernel) | ||
124 | fprintf(outfile, "#include <linux/init.h>\n\n" ); | ||
125 | |||
126 | /* XXX force 32 bit alignment? */ | ||
127 | fprintf(outfile, "const unsigned char%s %s_data[] = {\n", | ||
128 | inkernel ? " __initdata" : "", basename ); | ||
129 | |||
130 | c = getc(infile); | ||
131 | fprintf(outfile,"\t0x%02x", c); | ||
132 | firmsize = 1; | ||
133 | |||
134 | while ((c = getc(infile)) >= 0) { | ||
135 | |||
136 | if (firmsize++ % 8) | ||
137 | fprintf(outfile,", 0x%02x", c); | ||
138 | else | ||
139 | fprintf(outfile,",\n\t0x%02x", c); | ||
140 | } | ||
141 | |||
142 | fprintf(outfile, "\n};\n\n"); | ||
143 | |||
144 | fprintf(outfile, "const unsigned int%s %s_size = %u;\n", | ||
145 | inkernel ? " __initdata" : "", basename, firmsize ); | ||
146 | |||
147 | if (infile != stdin) | ||
148 | fclose(infile); | ||
149 | if (outfile != stdout) | ||
150 | fclose(outfile); | ||
151 | |||
152 | if(verbose) | ||
153 | fprintf(stderr, "%s: firmware size = %u\n", progname, firmsize); | ||
154 | |||
155 | exit(0); | ||
156 | } | ||
diff --git a/drivers/atm/he.c b/drivers/atm/he.c new file mode 100644 index 000000000000..c2c31a5f4513 --- /dev/null +++ b/drivers/atm/he.c | |||
@@ -0,0 +1,3091 @@ | |||
1 | /* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */ | ||
2 | |||
3 | /* | ||
4 | |||
5 | he.c | ||
6 | |||
7 | ForeRunnerHE ATM Adapter driver for ATM on Linux | ||
8 | Copyright (C) 1999-2001 Naval Research Laboratory | ||
9 | |||
10 | This library is free software; you can redistribute it and/or | ||
11 | modify it under the terms of the GNU Lesser General Public | ||
12 | License as published by the Free Software Foundation; either | ||
13 | version 2.1 of the License, or (at your option) any later version. | ||
14 | |||
15 | This library is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | Lesser General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU Lesser General Public | ||
21 | License along with this library; if not, write to the Free Software | ||
22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | |||
24 | */ | ||
25 | |||
26 | /* | ||
27 | |||
28 | he.c | ||
29 | |||
30 | ForeRunnerHE ATM Adapter driver for ATM on Linux | ||
31 | Copyright (C) 1999-2001 Naval Research Laboratory | ||
32 | |||
33 | Permission to use, copy, modify and distribute this software and its | ||
34 | documentation is hereby granted, provided that both the copyright | ||
35 | notice and this permission notice appear in all copies of the software, | ||
36 | derivative works or modified versions, and any portions thereof, and | ||
37 | that both notices appear in supporting documentation. | ||
38 | |||
39 | NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND | ||
40 | DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER | ||
41 | RESULTING FROM THE USE OF THIS SOFTWARE. | ||
42 | |||
43 | This driver was written using the "Programmer's Reference Manual for | ||
44 | ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98. | ||
45 | |||
46 | AUTHORS: | ||
47 | chas williams <chas@cmf.nrl.navy.mil> | ||
48 | eric kinzie <ekinzie@cmf.nrl.navy.mil> | ||
49 | |||
50 | NOTES: | ||
51 | 4096 supported 'connections' | ||
52 | group 0 is used for all traffic | ||
53 | interrupt queue 0 is used for all interrupts | ||
54 | aal0 support (based on work from ulrich.u.muller@nokia.com) | ||
55 | |||
56 | */ | ||
57 | |||
58 | #include <linux/config.h> | ||
59 | #include <linux/module.h> | ||
60 | #include <linux/version.h> | ||
61 | #include <linux/kernel.h> | ||
62 | #include <linux/skbuff.h> | ||
63 | #include <linux/pci.h> | ||
64 | #include <linux/errno.h> | ||
65 | #include <linux/types.h> | ||
66 | #include <linux/string.h> | ||
67 | #include <linux/delay.h> | ||
68 | #include <linux/init.h> | ||
69 | #include <linux/mm.h> | ||
70 | #include <linux/sched.h> | ||
71 | #include <linux/timer.h> | ||
72 | #include <linux/interrupt.h> | ||
73 | #include <asm/io.h> | ||
74 | #include <asm/byteorder.h> | ||
75 | #include <asm/uaccess.h> | ||
76 | |||
77 | #include <linux/atmdev.h> | ||
78 | #include <linux/atm.h> | ||
79 | #include <linux/sonet.h> | ||
80 | |||
81 | #define USE_TASKLET | ||
82 | #undef USE_SCATTERGATHER | ||
83 | #undef USE_CHECKSUM_HW /* still confused about this */ | ||
84 | #define USE_RBPS | ||
85 | #undef USE_RBPS_POOL /* if memory is tight try this */ | ||
86 | #undef USE_RBPL_POOL /* if memory is tight try this */ | ||
87 | #define USE_TPD_POOL | ||
88 | /* #undef CONFIG_ATM_HE_USE_SUNI */ | ||
89 | /* #undef HE_DEBUG */ | ||
90 | |||
91 | #include "he.h" | ||
92 | #include "suni.h" | ||
93 | #include <linux/atm_he.h> | ||
94 | |||
95 | #define hprintk(fmt,args...) printk(KERN_ERR DEV_LABEL "%d: " fmt, he_dev->number , ##args) | ||
96 | |||
97 | #ifdef HE_DEBUG | ||
98 | #define HPRINTK(fmt,args...) printk(KERN_DEBUG DEV_LABEL "%d: " fmt, he_dev->number , ##args) | ||
99 | #else /* !HE_DEBUG */ | ||
100 | #define HPRINTK(fmt,args...) do { } while (0) | ||
101 | #endif /* HE_DEBUG */ | ||
102 | |||
103 | /* version definition */ | ||
104 | |||
105 | static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $"; | ||
106 | |||
107 | /* declarations */ | ||
108 | |||
109 | static int he_open(struct atm_vcc *vcc); | ||
110 | static void he_close(struct atm_vcc *vcc); | ||
111 | static int he_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
112 | static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg); | ||
113 | static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs); | ||
114 | static void he_tasklet(unsigned long data); | ||
115 | static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page); | ||
116 | static int he_start(struct atm_dev *dev); | ||
117 | static void he_stop(struct he_dev *dev); | ||
118 | static void he_phy_put(struct atm_dev *, unsigned char, unsigned long); | ||
119 | static unsigned char he_phy_get(struct atm_dev *, unsigned long); | ||
120 | |||
121 | static u8 read_prom_byte(struct he_dev *he_dev, int addr); | ||
122 | |||
123 | /* globals */ | ||
124 | |||
125 | static struct he_dev *he_devs; | ||
126 | static int disable64; | ||
127 | static short nvpibits = -1; | ||
128 | static short nvcibits = -1; | ||
129 | static short rx_skb_reserve = 16; | ||
130 | static int irq_coalesce = 1; | ||
131 | static int sdh = 0; | ||
132 | |||
133 | /* Read from EEPROM = 0000 0011b */ | ||
134 | static unsigned int readtab[] = { | ||
135 | CS_HIGH | CLK_HIGH, | ||
136 | CS_LOW | CLK_LOW, | ||
137 | CLK_HIGH, /* 0 */ | ||
138 | CLK_LOW, | ||
139 | CLK_HIGH, /* 0 */ | ||
140 | CLK_LOW, | ||
141 | CLK_HIGH, /* 0 */ | ||
142 | CLK_LOW, | ||
143 | CLK_HIGH, /* 0 */ | ||
144 | CLK_LOW, | ||
145 | CLK_HIGH, /* 0 */ | ||
146 | CLK_LOW, | ||
147 | CLK_HIGH, /* 0 */ | ||
148 | CLK_LOW | SI_HIGH, | ||
149 | CLK_HIGH | SI_HIGH, /* 1 */ | ||
150 | CLK_LOW | SI_HIGH, | ||
151 | CLK_HIGH | SI_HIGH /* 1 */ | ||
152 | }; | ||
153 | |||
154 | /* Clock to read from/write to the EEPROM */ | ||
155 | static unsigned int clocktab[] = { | ||
156 | CLK_LOW, | ||
157 | CLK_HIGH, | ||
158 | CLK_LOW, | ||
159 | CLK_HIGH, | ||
160 | CLK_LOW, | ||
161 | CLK_HIGH, | ||
162 | CLK_LOW, | ||
163 | CLK_HIGH, | ||
164 | CLK_LOW, | ||
165 | CLK_HIGH, | ||
166 | CLK_LOW, | ||
167 | CLK_HIGH, | ||
168 | CLK_LOW, | ||
169 | CLK_HIGH, | ||
170 | CLK_LOW, | ||
171 | CLK_HIGH, | ||
172 | CLK_LOW | ||
173 | }; | ||
174 | |||
175 | static struct atmdev_ops he_ops = | ||
176 | { | ||
177 | .open = he_open, | ||
178 | .close = he_close, | ||
179 | .ioctl = he_ioctl, | ||
180 | .send = he_send, | ||
181 | .phy_put = he_phy_put, | ||
182 | .phy_get = he_phy_get, | ||
183 | .proc_read = he_proc_read, | ||
184 | .owner = THIS_MODULE | ||
185 | }; | ||
186 | |||
187 | #define he_writel(dev, val, reg) do { writel(val, (dev)->membase + (reg)); wmb(); } while (0) | ||
188 | #define he_readl(dev, reg) readl((dev)->membase + (reg)) | ||
189 | |||
190 | /* section 2.12 connection memory access */ | ||
191 | |||
192 | static __inline__ void | ||
193 | he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr, | ||
194 | unsigned flags) | ||
195 | { | ||
196 | he_writel(he_dev, val, CON_DAT); | ||
197 | (void) he_readl(he_dev, CON_DAT); /* flush posted writes */ | ||
198 | he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL); | ||
199 | while (he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); | ||
200 | } | ||
201 | |||
202 | #define he_writel_rcm(dev, val, reg) \ | ||
203 | he_writel_internal(dev, val, reg, CON_CTL_RCM) | ||
204 | |||
205 | #define he_writel_tcm(dev, val, reg) \ | ||
206 | he_writel_internal(dev, val, reg, CON_CTL_TCM) | ||
207 | |||
208 | #define he_writel_mbox(dev, val, reg) \ | ||
209 | he_writel_internal(dev, val, reg, CON_CTL_MBOX) | ||
210 | |||
211 | static unsigned | ||
212 | he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags) | ||
213 | { | ||
214 | he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL); | ||
215 | while (he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); | ||
216 | return he_readl(he_dev, CON_DAT); | ||
217 | } | ||
218 | |||
219 | #define he_readl_rcm(dev, reg) \ | ||
220 | he_readl_internal(dev, reg, CON_CTL_RCM) | ||
221 | |||
222 | #define he_readl_tcm(dev, reg) \ | ||
223 | he_readl_internal(dev, reg, CON_CTL_TCM) | ||
224 | |||
225 | #define he_readl_mbox(dev, reg) \ | ||
226 | he_readl_internal(dev, reg, CON_CTL_MBOX) | ||
227 | |||
228 | |||
229 | /* figure 2.2 connection id */ | ||
230 | |||
231 | #define he_mkcid(dev, vpi, vci) (((vpi << (dev)->vcibits) | vci) & 0x1fff) | ||
232 | |||
233 | /* 2.5.1 per connection transmit state registers */ | ||
234 | |||
235 | #define he_writel_tsr0(dev, val, cid) \ | ||
236 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 0) | ||
237 | #define he_readl_tsr0(dev, cid) \ | ||
238 | he_readl_tcm(dev, CONFIG_TSRA | (cid << 3) | 0) | ||
239 | |||
240 | #define he_writel_tsr1(dev, val, cid) \ | ||
241 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 1) | ||
242 | |||
243 | #define he_writel_tsr2(dev, val, cid) \ | ||
244 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 2) | ||
245 | |||
246 | #define he_writel_tsr3(dev, val, cid) \ | ||
247 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 3) | ||
248 | |||
249 | #define he_writel_tsr4(dev, val, cid) \ | ||
250 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 4) | ||
251 | |||
252 | /* from page 2-20 | ||
253 | * | ||
254 | * NOTE While the transmit connection is active, bits 23 through 0 | ||
255 | * of this register must not be written by the host. Byte | ||
256 | * enables should be used during normal operation when writing | ||
257 | * the most significant byte. | ||
258 | */ | ||
259 | |||
260 | #define he_writel_tsr4_upper(dev, val, cid) \ | ||
261 | he_writel_internal(dev, val, CONFIG_TSRA | (cid << 3) | 4, \ | ||
262 | CON_CTL_TCM \ | ||
263 | | CON_BYTE_DISABLE_2 \ | ||
264 | | CON_BYTE_DISABLE_1 \ | ||
265 | | CON_BYTE_DISABLE_0) | ||
266 | |||
267 | #define he_readl_tsr4(dev, cid) \ | ||
268 | he_readl_tcm(dev, CONFIG_TSRA | (cid << 3) | 4) | ||
269 | |||
270 | #define he_writel_tsr5(dev, val, cid) \ | ||
271 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 5) | ||
272 | |||
273 | #define he_writel_tsr6(dev, val, cid) \ | ||
274 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 6) | ||
275 | |||
276 | #define he_writel_tsr7(dev, val, cid) \ | ||
277 | he_writel_tcm(dev, val, CONFIG_TSRA | (cid << 3) | 7) | ||
278 | |||
279 | |||
280 | #define he_writel_tsr8(dev, val, cid) \ | ||
281 | he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 0) | ||
282 | |||
283 | #define he_writel_tsr9(dev, val, cid) \ | ||
284 | he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 1) | ||
285 | |||
286 | #define he_writel_tsr10(dev, val, cid) \ | ||
287 | he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 2) | ||
288 | |||
289 | #define he_writel_tsr11(dev, val, cid) \ | ||
290 | he_writel_tcm(dev, val, CONFIG_TSRB | (cid << 2) | 3) | ||
291 | |||
292 | |||
293 | #define he_writel_tsr12(dev, val, cid) \ | ||
294 | he_writel_tcm(dev, val, CONFIG_TSRC | (cid << 1) | 0) | ||
295 | |||
296 | #define he_writel_tsr13(dev, val, cid) \ | ||
297 | he_writel_tcm(dev, val, CONFIG_TSRC | (cid << 1) | 1) | ||
298 | |||
299 | |||
300 | #define he_writel_tsr14(dev, val, cid) \ | ||
301 | he_writel_tcm(dev, val, CONFIG_TSRD | cid) | ||
302 | |||
303 | #define he_writel_tsr14_upper(dev, val, cid) \ | ||
304 | he_writel_internal(dev, val, CONFIG_TSRD | cid, \ | ||
305 | CON_CTL_TCM \ | ||
306 | | CON_BYTE_DISABLE_2 \ | ||
307 | | CON_BYTE_DISABLE_1 \ | ||
308 | | CON_BYTE_DISABLE_0) | ||
309 | |||
310 | /* 2.7.1 per connection receive state registers */ | ||
311 | |||
312 | #define he_writel_rsr0(dev, val, cid) \ | ||
313 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 0) | ||
314 | #define he_readl_rsr0(dev, cid) \ | ||
315 | he_readl_rcm(dev, 0x00000 | (cid << 3) | 0) | ||
316 | |||
317 | #define he_writel_rsr1(dev, val, cid) \ | ||
318 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 1) | ||
319 | |||
320 | #define he_writel_rsr2(dev, val, cid) \ | ||
321 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 2) | ||
322 | |||
323 | #define he_writel_rsr3(dev, val, cid) \ | ||
324 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 3) | ||
325 | |||
326 | #define he_writel_rsr4(dev, val, cid) \ | ||
327 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 4) | ||
328 | |||
329 | #define he_writel_rsr5(dev, val, cid) \ | ||
330 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 5) | ||
331 | |||
332 | #define he_writel_rsr6(dev, val, cid) \ | ||
333 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 6) | ||
334 | |||
335 | #define he_writel_rsr7(dev, val, cid) \ | ||
336 | he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 7) | ||
337 | |||
338 | static __inline__ struct atm_vcc* | ||
339 | __find_vcc(struct he_dev *he_dev, unsigned cid) | ||
340 | { | ||
341 | struct hlist_head *head; | ||
342 | struct atm_vcc *vcc; | ||
343 | struct hlist_node *node; | ||
344 | struct sock *s; | ||
345 | short vpi; | ||
346 | int vci; | ||
347 | |||
348 | vpi = cid >> he_dev->vcibits; | ||
349 | vci = cid & ((1 << he_dev->vcibits) - 1); | ||
350 | head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; | ||
351 | |||
352 | sk_for_each(s, node, head) { | ||
353 | vcc = atm_sk(s); | ||
354 | if (vcc->dev == he_dev->atm_dev && | ||
355 | vcc->vci == vci && vcc->vpi == vpi && | ||
356 | vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
357 | return vcc; | ||
358 | } | ||
359 | } | ||
360 | return NULL; | ||
361 | } | ||
362 | |||
363 | static int __devinit | ||
364 | he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | ||
365 | { | ||
366 | struct atm_dev *atm_dev = NULL; | ||
367 | struct he_dev *he_dev = NULL; | ||
368 | int err = 0; | ||
369 | |||
370 | printk(KERN_INFO "he: %s\n", version); | ||
371 | |||
372 | if (pci_enable_device(pci_dev)) | ||
373 | return -EIO; | ||
374 | if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) { | ||
375 | printk(KERN_WARNING "he: no suitable dma available\n"); | ||
376 | err = -EIO; | ||
377 | goto init_one_failure; | ||
378 | } | ||
379 | |||
380 | atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL); | ||
381 | if (!atm_dev) { | ||
382 | err = -ENODEV; | ||
383 | goto init_one_failure; | ||
384 | } | ||
385 | pci_set_drvdata(pci_dev, atm_dev); | ||
386 | |||
387 | he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev), | ||
388 | GFP_KERNEL); | ||
389 | if (!he_dev) { | ||
390 | err = -ENOMEM; | ||
391 | goto init_one_failure; | ||
392 | } | ||
393 | memset(he_dev, 0, sizeof(struct he_dev)); | ||
394 | |||
395 | he_dev->pci_dev = pci_dev; | ||
396 | he_dev->atm_dev = atm_dev; | ||
397 | he_dev->atm_dev->dev_data = he_dev; | ||
398 | atm_dev->dev_data = he_dev; | ||
399 | he_dev->number = atm_dev->number; | ||
400 | if (he_start(atm_dev)) { | ||
401 | he_stop(he_dev); | ||
402 | err = -ENODEV; | ||
403 | goto init_one_failure; | ||
404 | } | ||
405 | he_dev->next = NULL; | ||
406 | if (he_devs) | ||
407 | he_dev->next = he_devs; | ||
408 | he_devs = he_dev; | ||
409 | return 0; | ||
410 | |||
411 | init_one_failure: | ||
412 | if (atm_dev) | ||
413 | atm_dev_deregister(atm_dev); | ||
414 | if (he_dev) | ||
415 | kfree(he_dev); | ||
416 | pci_disable_device(pci_dev); | ||
417 | return err; | ||
418 | } | ||
419 | |||
420 | static void __devexit | ||
421 | he_remove_one (struct pci_dev *pci_dev) | ||
422 | { | ||
423 | struct atm_dev *atm_dev; | ||
424 | struct he_dev *he_dev; | ||
425 | |||
426 | atm_dev = pci_get_drvdata(pci_dev); | ||
427 | he_dev = HE_DEV(atm_dev); | ||
428 | |||
429 | /* need to remove from he_devs */ | ||
430 | |||
431 | he_stop(he_dev); | ||
432 | atm_dev_deregister(atm_dev); | ||
433 | kfree(he_dev); | ||
434 | |||
435 | pci_set_drvdata(pci_dev, NULL); | ||
436 | pci_disable_device(pci_dev); | ||
437 | } | ||
438 | |||
439 | |||
440 | static unsigned | ||
441 | rate_to_atmf(unsigned rate) /* cps to atm forum format */ | ||
442 | { | ||
443 | #define NONZERO (1 << 14) | ||
444 | |||
445 | unsigned exp = 0; | ||
446 | |||
447 | if (rate == 0) | ||
448 | return 0; | ||
449 | |||
450 | rate <<= 9; | ||
451 | while (rate > 0x3ff) { | ||
452 | ++exp; | ||
453 | rate >>= 1; | ||
454 | } | ||
455 | |||
456 | return (NONZERO | (exp << 9) | (rate & 0x1ff)); | ||
457 | } | ||
458 | |||
459 | static void __init | ||
460 | he_init_rx_lbfp0(struct he_dev *he_dev) | ||
461 | { | ||
462 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; | ||
463 | unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; | ||
464 | unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; | ||
465 | unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row; | ||
466 | |||
467 | lbufd_index = 0; | ||
468 | lbm_offset = he_readl(he_dev, RCMLBM_BA); | ||
469 | |||
470 | he_writel(he_dev, lbufd_index, RLBF0_H); | ||
471 | |||
472 | for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i) { | ||
473 | lbufd_index += 2; | ||
474 | lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; | ||
475 | |||
476 | he_writel_rcm(he_dev, lbuf_addr, lbm_offset); | ||
477 | he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); | ||
478 | |||
479 | if (++lbuf_count == lbufs_per_row) { | ||
480 | lbuf_count = 0; | ||
481 | row_offset += he_dev->bytes_per_row; | ||
482 | } | ||
483 | lbm_offset += 4; | ||
484 | } | ||
485 | |||
486 | he_writel(he_dev, lbufd_index - 2, RLBF0_T); | ||
487 | he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C); | ||
488 | } | ||
489 | |||
490 | static void __init | ||
491 | he_init_rx_lbfp1(struct he_dev *he_dev) | ||
492 | { | ||
493 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; | ||
494 | unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; | ||
495 | unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; | ||
496 | unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row; | ||
497 | |||
498 | lbufd_index = 1; | ||
499 | lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index); | ||
500 | |||
501 | he_writel(he_dev, lbufd_index, RLBF1_H); | ||
502 | |||
503 | for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i) { | ||
504 | lbufd_index += 2; | ||
505 | lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; | ||
506 | |||
507 | he_writel_rcm(he_dev, lbuf_addr, lbm_offset); | ||
508 | he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); | ||
509 | |||
510 | if (++lbuf_count == lbufs_per_row) { | ||
511 | lbuf_count = 0; | ||
512 | row_offset += he_dev->bytes_per_row; | ||
513 | } | ||
514 | lbm_offset += 4; | ||
515 | } | ||
516 | |||
517 | he_writel(he_dev, lbufd_index - 2, RLBF1_T); | ||
518 | he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C); | ||
519 | } | ||
520 | |||
521 | static void __init | ||
522 | he_init_tx_lbfp(struct he_dev *he_dev) | ||
523 | { | ||
524 | unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; | ||
525 | unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; | ||
526 | unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; | ||
527 | unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row; | ||
528 | |||
529 | lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs; | ||
530 | lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index); | ||
531 | |||
532 | he_writel(he_dev, lbufd_index, TLBF_H); | ||
533 | |||
534 | for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i) { | ||
535 | lbufd_index += 1; | ||
536 | lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; | ||
537 | |||
538 | he_writel_rcm(he_dev, lbuf_addr, lbm_offset); | ||
539 | he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); | ||
540 | |||
541 | if (++lbuf_count == lbufs_per_row) { | ||
542 | lbuf_count = 0; | ||
543 | row_offset += he_dev->bytes_per_row; | ||
544 | } | ||
545 | lbm_offset += 2; | ||
546 | } | ||
547 | |||
548 | he_writel(he_dev, lbufd_index - 1, TLBF_T); | ||
549 | } | ||
550 | |||
551 | static int __init | ||
552 | he_init_tpdrq(struct he_dev *he_dev) | ||
553 | { | ||
554 | he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, | ||
555 | CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys); | ||
556 | if (he_dev->tpdrq_base == NULL) { | ||
557 | hprintk("failed to alloc tpdrq\n"); | ||
558 | return -ENOMEM; | ||
559 | } | ||
560 | memset(he_dev->tpdrq_base, 0, | ||
561 | CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq)); | ||
562 | |||
563 | he_dev->tpdrq_tail = he_dev->tpdrq_base; | ||
564 | he_dev->tpdrq_head = he_dev->tpdrq_base; | ||
565 | |||
566 | he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H); | ||
567 | he_writel(he_dev, 0, TPDRQ_T); | ||
568 | he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static void __init | ||
574 | he_init_cs_block(struct he_dev *he_dev) | ||
575 | { | ||
576 | unsigned clock, rate, delta; | ||
577 | int reg; | ||
578 | |||
579 | /* 5.1.7 cs block initialization */ | ||
580 | |||
581 | for (reg = 0; reg < 0x20; ++reg) | ||
582 | he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg); | ||
583 | |||
584 | /* rate grid timer reload values */ | ||
585 | |||
586 | clock = he_is622(he_dev) ? 66667000 : 50000000; | ||
587 | rate = he_dev->atm_dev->link_rate; | ||
588 | delta = rate / 16 / 2; | ||
589 | |||
590 | for (reg = 0; reg < 0x10; ++reg) { | ||
591 | /* 2.4 internal transmit function | ||
592 | * | ||
593 | * we initialize the first row in the rate grid. | ||
594 | * values are period (in clock cycles) of timer | ||
595 | */ | ||
596 | unsigned period = clock / rate; | ||
597 | |||
598 | he_writel_mbox(he_dev, period, CS_TGRLD0 + reg); | ||
599 | rate -= delta; | ||
600 | } | ||
601 | |||
602 | if (he_is622(he_dev)) { | ||
603 | /* table 5.2 (4 cells per lbuf) */ | ||
604 | he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0); | ||
605 | he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1); | ||
606 | he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2); | ||
607 | he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3); | ||
608 | he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4); | ||
609 | |||
610 | /* table 5.3, 5.4, 5.5, 5.6, 5.7 */ | ||
611 | he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0); | ||
612 | he_writel_mbox(he_dev, 0x1801, CS_ERCTL1); | ||
613 | he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2); | ||
614 | he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0); | ||
615 | he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1); | ||
616 | he_writel_mbox(he_dev, 0x14585, CS_RTFWR); | ||
617 | |||
618 | he_writel_mbox(he_dev, 0x4680, CS_RTATR); | ||
619 | |||
620 | /* table 5.8 */ | ||
621 | he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET); | ||
622 | he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX); | ||
623 | he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN); | ||
624 | he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC); | ||
625 | he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC); | ||
626 | he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL); | ||
627 | |||
628 | /* table 5.9 */ | ||
629 | he_writel_mbox(he_dev, 0x5, CS_OTPPER); | ||
630 | he_writel_mbox(he_dev, 0x14, CS_OTWPER); | ||
631 | } else { | ||
632 | /* table 5.1 (4 cells per lbuf) */ | ||
633 | he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0); | ||
634 | he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1); | ||
635 | he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2); | ||
636 | he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3); | ||
637 | he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4); | ||
638 | |||
639 | /* table 5.3, 5.4, 5.5, 5.6, 5.7 */ | ||
640 | he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0); | ||
641 | he_writel_mbox(he_dev, 0x4701, CS_ERCTL1); | ||
642 | he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2); | ||
643 | he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0); | ||
644 | he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1); | ||
645 | he_writel_mbox(he_dev, 0xf424, CS_RTFWR); | ||
646 | |||
647 | he_writel_mbox(he_dev, 0x4680, CS_RTATR); | ||
648 | |||
649 | /* table 5.8 */ | ||
650 | he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET); | ||
651 | he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX); | ||
652 | he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN); | ||
653 | he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC); | ||
654 | he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC); | ||
655 | he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL); | ||
656 | |||
657 | /* table 5.9 */ | ||
658 | he_writel_mbox(he_dev, 0x6, CS_OTPPER); | ||
659 | he_writel_mbox(he_dev, 0x1e, CS_OTWPER); | ||
660 | } | ||
661 | |||
662 | he_writel_mbox(he_dev, 0x8, CS_OTTLIM); | ||
663 | |||
664 | for (reg = 0; reg < 0x8; ++reg) | ||
665 | he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg); | ||
666 | |||
667 | } | ||
668 | |||
669 | static int __init | ||
670 | he_init_cs_block_rcm(struct he_dev *he_dev) | ||
671 | { | ||
672 | unsigned (*rategrid)[16][16]; | ||
673 | unsigned rate, delta; | ||
674 | int i, j, reg; | ||
675 | |||
676 | unsigned rate_atmf, exp, man; | ||
677 | unsigned long long rate_cps; | ||
678 | int mult, buf, buf_limit = 4; | ||
679 | |||
680 | rategrid = kmalloc( sizeof(unsigned) * 16 * 16, GFP_KERNEL); | ||
681 | if (!rategrid) | ||
682 | return -ENOMEM; | ||
683 | |||
684 | /* initialize rate grid group table */ | ||
685 | |||
686 | for (reg = 0x0; reg < 0xff; ++reg) | ||
687 | he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg); | ||
688 | |||
689 | /* initialize rate controller groups */ | ||
690 | |||
691 | for (reg = 0x100; reg < 0x1ff; ++reg) | ||
692 | he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg); | ||
693 | |||
694 | /* initialize tNrm lookup table */ | ||
695 | |||
696 | /* the manual makes reference to a routine in a sample driver | ||
697 | for proper configuration; fortunately, we only need this | ||
698 | in order to support abr connection */ | ||
699 | |||
700 | /* initialize rate to group table */ | ||
701 | |||
702 | rate = he_dev->atm_dev->link_rate; | ||
703 | delta = rate / 32; | ||
704 | |||
705 | /* | ||
706 | * 2.4 transmit internal functions | ||
707 | * | ||
708 | * we construct a copy of the rate grid used by the scheduler | ||
709 | * in order to construct the rate to group table below | ||
710 | */ | ||
711 | |||
712 | for (j = 0; j < 16; j++) { | ||
713 | (*rategrid)[0][j] = rate; | ||
714 | rate -= delta; | ||
715 | } | ||
716 | |||
717 | for (i = 1; i < 16; i++) | ||
718 | for (j = 0; j < 16; j++) | ||
719 | if (i > 14) | ||
720 | (*rategrid)[i][j] = (*rategrid)[i - 1][j] / 4; | ||
721 | else | ||
722 | (*rategrid)[i][j] = (*rategrid)[i - 1][j] / 2; | ||
723 | |||
724 | /* | ||
725 | * 2.4 transmit internal function | ||
726 | * | ||
727 | * this table maps the upper 5 bits of exponent and mantissa | ||
728 | * of the atm forum representation of the rate into an index | ||
729 | * on rate grid | ||
730 | */ | ||
731 | |||
732 | rate_atmf = 0; | ||
733 | while (rate_atmf < 0x400) { | ||
734 | man = (rate_atmf & 0x1f) << 4; | ||
735 | exp = rate_atmf >> 5; | ||
736 | |||
737 | /* | ||
738 | instead of '/ 512', use '>> 9' to prevent a call | ||
739 | to divdu3 on x86 platforms | ||
740 | */ | ||
741 | rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9; | ||
742 | |||
743 | if (rate_cps < 10) | ||
744 | rate_cps = 10; /* 2.2.1 minimum payload rate is 10 cps */ | ||
745 | |||
746 | for (i = 255; i > 0; i--) | ||
747 | if ((*rategrid)[i/16][i%16] >= rate_cps) | ||
748 | break; /* pick nearest rate instead? */ | ||
749 | |||
750 | /* | ||
751 | * each table entry is 16 bits: (rate grid index (8 bits) | ||
752 | * and a buffer limit (8 bits) | ||
753 | * there are two table entries in each 32-bit register | ||
754 | */ | ||
755 | |||
756 | #ifdef notdef | ||
757 | buf = rate_cps * he_dev->tx_numbuffs / | ||
758 | (he_dev->atm_dev->link_rate * 2); | ||
759 | #else | ||
760 | /* this is pretty, but avoids _divdu3 and is mostly correct */ | ||
761 | mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR; | ||
762 | if (rate_cps > (272 * mult)) | ||
763 | buf = 4; | ||
764 | else if (rate_cps > (204 * mult)) | ||
765 | buf = 3; | ||
766 | else if (rate_cps > (136 * mult)) | ||
767 | buf = 2; | ||
768 | else if (rate_cps > (68 * mult)) | ||
769 | buf = 1; | ||
770 | else | ||
771 | buf = 0; | ||
772 | #endif | ||
773 | if (buf > buf_limit) | ||
774 | buf = buf_limit; | ||
775 | reg = (reg << 16) | ((i << 8) | buf); | ||
776 | |||
777 | #define RTGTBL_OFFSET 0x400 | ||
778 | |||
779 | if (rate_atmf & 0x1) | ||
780 | he_writel_rcm(he_dev, reg, | ||
781 | CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf >> 1)); | ||
782 | |||
783 | ++rate_atmf; | ||
784 | } | ||
785 | |||
786 | kfree(rategrid); | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static int __init | ||
791 | he_init_group(struct he_dev *he_dev, int group) | ||
792 | { | ||
793 | int i; | ||
794 | |||
795 | #ifdef USE_RBPS | ||
796 | /* small buffer pool */ | ||
797 | #ifdef USE_RBPS_POOL | ||
798 | he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev, | ||
799 | CONFIG_RBPS_BUFSIZE, 8, 0); | ||
800 | if (he_dev->rbps_pool == NULL) { | ||
801 | hprintk("unable to create rbps pages\n"); | ||
802 | return -ENOMEM; | ||
803 | } | ||
804 | #else /* !USE_RBPS_POOL */ | ||
805 | he_dev->rbps_pages = pci_alloc_consistent(he_dev->pci_dev, | ||
806 | CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, &he_dev->rbps_pages_phys); | ||
807 | if (he_dev->rbps_pages == NULL) { | ||
808 | hprintk("unable to create rbps page pool\n"); | ||
809 | return -ENOMEM; | ||
810 | } | ||
811 | #endif /* USE_RBPS_POOL */ | ||
812 | |||
813 | he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, | ||
814 | CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); | ||
815 | if (he_dev->rbps_base == NULL) { | ||
816 | hprintk("failed to alloc rbps\n"); | ||
817 | return -ENOMEM; | ||
818 | } | ||
819 | memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); | ||
820 | he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); | ||
821 | |||
822 | for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { | ||
823 | dma_addr_t dma_handle; | ||
824 | void *cpuaddr; | ||
825 | |||
826 | #ifdef USE_RBPS_POOL | ||
827 | cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); | ||
828 | if (cpuaddr == NULL) | ||
829 | return -ENOMEM; | ||
830 | #else | ||
831 | cpuaddr = he_dev->rbps_pages + (i * CONFIG_RBPS_BUFSIZE); | ||
832 | dma_handle = he_dev->rbps_pages_phys + (i * CONFIG_RBPS_BUFSIZE); | ||
833 | #endif | ||
834 | |||
835 | he_dev->rbps_virt[i].virt = cpuaddr; | ||
836 | he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); | ||
837 | he_dev->rbps_base[i].phys = dma_handle; | ||
838 | |||
839 | } | ||
840 | he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE - 1]; | ||
841 | |||
842 | he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32)); | ||
843 | he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), | ||
844 | G0_RBPS_T + (group * 32)); | ||
845 | he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4, | ||
846 | G0_RBPS_BS + (group * 32)); | ||
847 | he_writel(he_dev, | ||
848 | RBP_THRESH(CONFIG_RBPS_THRESH) | | ||
849 | RBP_QSIZE(CONFIG_RBPS_SIZE - 1) | | ||
850 | RBP_INT_ENB, | ||
851 | G0_RBPS_QI + (group * 32)); | ||
852 | #else /* !USE_RBPS */ | ||
853 | he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); | ||
854 | he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); | ||
855 | he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); | ||
856 | he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), | ||
857 | G0_RBPS_BS + (group * 32)); | ||
858 | #endif /* USE_RBPS */ | ||
859 | |||
860 | /* large buffer pool */ | ||
861 | #ifdef USE_RBPL_POOL | ||
862 | he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev, | ||
863 | CONFIG_RBPL_BUFSIZE, 8, 0); | ||
864 | if (he_dev->rbpl_pool == NULL) { | ||
865 | hprintk("unable to create rbpl pool\n"); | ||
866 | return -ENOMEM; | ||
867 | } | ||
868 | #else /* !USE_RBPL_POOL */ | ||
869 | he_dev->rbpl_pages = (void *) pci_alloc_consistent(he_dev->pci_dev, | ||
870 | CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, &he_dev->rbpl_pages_phys); | ||
871 | if (he_dev->rbpl_pages == NULL) { | ||
872 | hprintk("unable to create rbpl pages\n"); | ||
873 | return -ENOMEM; | ||
874 | } | ||
875 | #endif /* USE_RBPL_POOL */ | ||
876 | |||
877 | he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, | ||
878 | CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); | ||
879 | if (he_dev->rbpl_base == NULL) { | ||
880 | hprintk("failed to alloc rbpl\n"); | ||
881 | return -ENOMEM; | ||
882 | } | ||
883 | memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); | ||
884 | he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); | ||
885 | |||
886 | for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { | ||
887 | dma_addr_t dma_handle; | ||
888 | void *cpuaddr; | ||
889 | |||
890 | #ifdef USE_RBPL_POOL | ||
891 | cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); | ||
892 | if (cpuaddr == NULL) | ||
893 | return -ENOMEM; | ||
894 | #else | ||
895 | cpuaddr = he_dev->rbpl_pages + (i * CONFIG_RBPL_BUFSIZE); | ||
896 | dma_handle = he_dev->rbpl_pages_phys + (i * CONFIG_RBPL_BUFSIZE); | ||
897 | #endif | ||
898 | |||
899 | he_dev->rbpl_virt[i].virt = cpuaddr; | ||
900 | he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); | ||
901 | he_dev->rbpl_base[i].phys = dma_handle; | ||
902 | } | ||
903 | he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE - 1]; | ||
904 | |||
905 | he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32)); | ||
906 | he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), | ||
907 | G0_RBPL_T + (group * 32)); | ||
908 | he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4, | ||
909 | G0_RBPL_BS + (group * 32)); | ||
910 | he_writel(he_dev, | ||
911 | RBP_THRESH(CONFIG_RBPL_THRESH) | | ||
912 | RBP_QSIZE(CONFIG_RBPL_SIZE - 1) | | ||
913 | RBP_INT_ENB, | ||
914 | G0_RBPL_QI + (group * 32)); | ||
915 | |||
916 | /* rx buffer ready queue */ | ||
917 | |||
918 | he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev, | ||
919 | CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); | ||
920 | if (he_dev->rbrq_base == NULL) { | ||
921 | hprintk("failed to allocate rbrq\n"); | ||
922 | return -ENOMEM; | ||
923 | } | ||
924 | memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); | ||
925 | |||
926 | he_dev->rbrq_head = he_dev->rbrq_base; | ||
927 | he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16)); | ||
928 | he_writel(he_dev, 0, G0_RBRQ_H + (group * 16)); | ||
929 | he_writel(he_dev, | ||
930 | RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE - 1), | ||
931 | G0_RBRQ_Q + (group * 16)); | ||
932 | if (irq_coalesce) { | ||
933 | hprintk("coalescing interrupts\n"); | ||
934 | he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7), | ||
935 | G0_RBRQ_I + (group * 16)); | ||
936 | } else | ||
937 | he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1), | ||
938 | G0_RBRQ_I + (group * 16)); | ||
939 | |||
940 | /* tx buffer ready queue */ | ||
941 | |||
942 | he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev, | ||
943 | CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); | ||
944 | if (he_dev->tbrq_base == NULL) { | ||
945 | hprintk("failed to allocate tbrq\n"); | ||
946 | return -ENOMEM; | ||
947 | } | ||
948 | memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); | ||
949 | |||
950 | he_dev->tbrq_head = he_dev->tbrq_base; | ||
951 | |||
952 | he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16)); | ||
953 | he_writel(he_dev, 0, G0_TBRQ_H + (group * 16)); | ||
954 | he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16)); | ||
955 | he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static int __init | ||
961 | he_init_irq(struct he_dev *he_dev) | ||
962 | { | ||
963 | int i; | ||
964 | |||
965 | /* 2.9.3.5 tail offset for each interrupt queue is located after the | ||
966 | end of the interrupt queue */ | ||
967 | |||
968 | he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev, | ||
969 | (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys); | ||
970 | if (he_dev->irq_base == NULL) { | ||
971 | hprintk("failed to allocate irq\n"); | ||
972 | return -ENOMEM; | ||
973 | } | ||
974 | he_dev->irq_tailoffset = (unsigned *) | ||
975 | &he_dev->irq_base[CONFIG_IRQ_SIZE]; | ||
976 | *he_dev->irq_tailoffset = 0; | ||
977 | he_dev->irq_head = he_dev->irq_base; | ||
978 | he_dev->irq_tail = he_dev->irq_base; | ||
979 | |||
980 | for (i = 0; i < CONFIG_IRQ_SIZE; ++i) | ||
981 | he_dev->irq_base[i].isw = ITYPE_INVALID; | ||
982 | |||
983 | he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE); | ||
984 | he_writel(he_dev, | ||
985 | IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH), | ||
986 | IRQ0_HEAD); | ||
987 | he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL); | ||
988 | he_writel(he_dev, 0x0, IRQ0_DATA); | ||
989 | |||
990 | he_writel(he_dev, 0x0, IRQ1_BASE); | ||
991 | he_writel(he_dev, 0x0, IRQ1_HEAD); | ||
992 | he_writel(he_dev, 0x0, IRQ1_CNTL); | ||
993 | he_writel(he_dev, 0x0, IRQ1_DATA); | ||
994 | |||
995 | he_writel(he_dev, 0x0, IRQ2_BASE); | ||
996 | he_writel(he_dev, 0x0, IRQ2_HEAD); | ||
997 | he_writel(he_dev, 0x0, IRQ2_CNTL); | ||
998 | he_writel(he_dev, 0x0, IRQ2_DATA); | ||
999 | |||
1000 | he_writel(he_dev, 0x0, IRQ3_BASE); | ||
1001 | he_writel(he_dev, 0x0, IRQ3_HEAD); | ||
1002 | he_writel(he_dev, 0x0, IRQ3_CNTL); | ||
1003 | he_writel(he_dev, 0x0, IRQ3_DATA); | ||
1004 | |||
1005 | /* 2.9.3.2 interrupt queue mapping registers */ | ||
1006 | |||
1007 | he_writel(he_dev, 0x0, GRP_10_MAP); | ||
1008 | he_writel(he_dev, 0x0, GRP_32_MAP); | ||
1009 | he_writel(he_dev, 0x0, GRP_54_MAP); | ||
1010 | he_writel(he_dev, 0x0, GRP_76_MAP); | ||
1011 | |||
1012 | if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev)) { | ||
1013 | hprintk("irq %d already in use\n", he_dev->pci_dev->irq); | ||
1014 | return -EINVAL; | ||
1015 | } | ||
1016 | |||
1017 | he_dev->irq = he_dev->pci_dev->irq; | ||
1018 | |||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | static int __init | ||
1023 | he_start(struct atm_dev *dev) | ||
1024 | { | ||
1025 | struct he_dev *he_dev; | ||
1026 | struct pci_dev *pci_dev; | ||
1027 | unsigned long membase; | ||
1028 | |||
1029 | u16 command; | ||
1030 | u32 gen_cntl_0, host_cntl, lb_swap; | ||
1031 | u8 cache_size, timer; | ||
1032 | |||
1033 | unsigned err; | ||
1034 | unsigned int status, reg; | ||
1035 | int i, group; | ||
1036 | |||
1037 | he_dev = HE_DEV(dev); | ||
1038 | pci_dev = he_dev->pci_dev; | ||
1039 | |||
1040 | membase = pci_resource_start(pci_dev, 0); | ||
1041 | HPRINTK("membase = 0x%lx irq = %d.\n", membase, pci_dev->irq); | ||
1042 | |||
1043 | /* | ||
1044 | * pci bus controller initialization | ||
1045 | */ | ||
1046 | |||
1047 | /* 4.3 pci bus controller-specific initialization */ | ||
1048 | if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0) { | ||
1049 | hprintk("can't read GEN_CNTL_0\n"); | ||
1050 | return -EINVAL; | ||
1051 | } | ||
1052 | gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT); | ||
1053 | if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0) { | ||
1054 | hprintk("can't write GEN_CNTL_0.\n"); | ||
1055 | return -EINVAL; | ||
1056 | } | ||
1057 | |||
1058 | if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0) { | ||
1059 | hprintk("can't read PCI_COMMAND.\n"); | ||
1060 | return -EINVAL; | ||
1061 | } | ||
1062 | |||
1063 | command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); | ||
1064 | if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0) { | ||
1065 | hprintk("can't enable memory.\n"); | ||
1066 | return -EINVAL; | ||
1067 | } | ||
1068 | |||
1069 | if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size)) { | ||
1070 | hprintk("can't read cache line size?\n"); | ||
1071 | return -EINVAL; | ||
1072 | } | ||
1073 | |||
1074 | if (cache_size < 16) { | ||
1075 | cache_size = 16; | ||
1076 | if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size)) | ||
1077 | hprintk("can't set cache line size to %d\n", cache_size); | ||
1078 | } | ||
1079 | |||
1080 | if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer)) { | ||
1081 | hprintk("can't read latency timer?\n"); | ||
1082 | return -EINVAL; | ||
1083 | } | ||
1084 | |||
1085 | /* from table 3.9 | ||
1086 | * | ||
1087 | * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE | ||
1088 | * | ||
1089 | * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles] | ||
1090 | * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles] | ||
1091 | * | ||
1092 | */ | ||
1093 | #define LAT_TIMER 209 | ||
1094 | if (timer < LAT_TIMER) { | ||
1095 | HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER); | ||
1096 | timer = LAT_TIMER; | ||
1097 | if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer)) | ||
1098 | hprintk("can't set latency timer to %d\n", timer); | ||
1099 | } | ||
1100 | |||
1101 | if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) { | ||
1102 | hprintk("can't set up page mapping\n"); | ||
1103 | return -EINVAL; | ||
1104 | } | ||
1105 | |||
1106 | /* 4.4 card reset */ | ||
1107 | he_writel(he_dev, 0x0, RESET_CNTL); | ||
1108 | he_writel(he_dev, 0xff, RESET_CNTL); | ||
1109 | |||
1110 | udelay(16*1000); /* 16 ms */ | ||
1111 | status = he_readl(he_dev, RESET_CNTL); | ||
1112 | if ((status & BOARD_RST_STATUS) == 0) { | ||
1113 | hprintk("reset failed\n"); | ||
1114 | return -EINVAL; | ||
1115 | } | ||
1116 | |||
1117 | /* 4.5 set bus width */ | ||
1118 | host_cntl = he_readl(he_dev, HOST_CNTL); | ||
1119 | if (host_cntl & PCI_BUS_SIZE64) | ||
1120 | gen_cntl_0 |= ENBL_64; | ||
1121 | else | ||
1122 | gen_cntl_0 &= ~ENBL_64; | ||
1123 | |||
1124 | if (disable64 == 1) { | ||
1125 | hprintk("disabling 64-bit pci bus transfers\n"); | ||
1126 | gen_cntl_0 &= ~ENBL_64; | ||
1127 | } | ||
1128 | |||
1129 | if (gen_cntl_0 & ENBL_64) | ||
1130 | hprintk("64-bit transfers enabled\n"); | ||
1131 | |||
1132 | pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); | ||
1133 | |||
1134 | /* 4.7 read prom contents */ | ||
1135 | for (i = 0; i < PROD_ID_LEN; ++i) | ||
1136 | he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i); | ||
1137 | |||
1138 | he_dev->media = read_prom_byte(he_dev, MEDIA); | ||
1139 | |||
1140 | for (i = 0; i < 6; ++i) | ||
1141 | dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i); | ||
1142 | |||
1143 | hprintk("%s%s, %x:%x:%x:%x:%x:%x\n", | ||
1144 | he_dev->prod_id, | ||
1145 | he_dev->media & 0x40 ? "SM" : "MM", | ||
1146 | dev->esi[0], | ||
1147 | dev->esi[1], | ||
1148 | dev->esi[2], | ||
1149 | dev->esi[3], | ||
1150 | dev->esi[4], | ||
1151 | dev->esi[5]); | ||
1152 | he_dev->atm_dev->link_rate = he_is622(he_dev) ? | ||
1153 | ATM_OC12_PCR : ATM_OC3_PCR; | ||
1154 | |||
1155 | /* 4.6 set host endianess */ | ||
1156 | lb_swap = he_readl(he_dev, LB_SWAP); | ||
1157 | if (he_is622(he_dev)) | ||
1158 | lb_swap &= ~XFER_SIZE; /* 4 cells */ | ||
1159 | else | ||
1160 | lb_swap |= XFER_SIZE; /* 8 cells */ | ||
1161 | #ifdef __BIG_ENDIAN | ||
1162 | lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST; | ||
1163 | #else | ||
1164 | lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST | | ||
1165 | DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP); | ||
1166 | #endif /* __BIG_ENDIAN */ | ||
1167 | he_writel(he_dev, lb_swap, LB_SWAP); | ||
1168 | |||
1169 | /* 4.8 sdram controller initialization */ | ||
1170 | he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL); | ||
1171 | |||
1172 | /* 4.9 initialize rnum value */ | ||
1173 | lb_swap |= SWAP_RNUM_MAX(0xf); | ||
1174 | he_writel(he_dev, lb_swap, LB_SWAP); | ||
1175 | |||
1176 | /* 4.10 initialize the interrupt queues */ | ||
1177 | if ((err = he_init_irq(he_dev)) != 0) | ||
1178 | return err; | ||
1179 | |||
1180 | #ifdef USE_TASKLET | ||
1181 | tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); | ||
1182 | #endif | ||
1183 | spin_lock_init(&he_dev->global_lock); | ||
1184 | |||
1185 | /* 4.11 enable pci bus controller state machines */ | ||
1186 | host_cntl |= (OUTFF_ENB | CMDFF_ENB | | ||
1187 | QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB); | ||
1188 | he_writel(he_dev, host_cntl, HOST_CNTL); | ||
1189 | |||
1190 | gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB; | ||
1191 | pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); | ||
1192 | |||
1193 | /* | ||
1194 | * atm network controller initialization | ||
1195 | */ | ||
1196 | |||
1197 | /* 5.1.1 generic configuration state */ | ||
1198 | |||
1199 | /* | ||
1200 | * local (cell) buffer memory map | ||
1201 | * | ||
1202 | * HE155 HE622 | ||
1203 | * | ||
1204 | * 0 ____________1023 bytes 0 _______________________2047 bytes | ||
1205 | * | | | | | | ||
1206 | * | utility | | rx0 | | | ||
1207 | * 5|____________| 255|___________________| u | | ||
1208 | * 6| | 256| | t | | ||
1209 | * | | | | i | | ||
1210 | * | rx0 | row | tx | l | | ||
1211 | * | | | | i | | ||
1212 | * | | 767|___________________| t | | ||
1213 | * 517|____________| 768| | y | | ||
1214 | * row 518| | | rx1 | | | ||
1215 | * | | 1023|___________________|___| | ||
1216 | * | | | ||
1217 | * | tx | | ||
1218 | * | | | ||
1219 | * | | | ||
1220 | * 1535|____________| | ||
1221 | * 1536| | | ||
1222 | * | rx1 | | ||
1223 | * 2047|____________| | ||
1224 | * | ||
1225 | */ | ||
1226 | |||
1227 | /* total 4096 connections */ | ||
1228 | he_dev->vcibits = CONFIG_DEFAULT_VCIBITS; | ||
1229 | he_dev->vpibits = CONFIG_DEFAULT_VPIBITS; | ||
1230 | |||
1231 | if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS) { | ||
1232 | hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS); | ||
1233 | return -ENODEV; | ||
1234 | } | ||
1235 | |||
1236 | if (nvpibits != -1) { | ||
1237 | he_dev->vpibits = nvpibits; | ||
1238 | he_dev->vcibits = HE_MAXCIDBITS - nvpibits; | ||
1239 | } | ||
1240 | |||
1241 | if (nvcibits != -1) { | ||
1242 | he_dev->vcibits = nvcibits; | ||
1243 | he_dev->vpibits = HE_MAXCIDBITS - nvcibits; | ||
1244 | } | ||
1245 | |||
1246 | |||
1247 | if (he_is622(he_dev)) { | ||
1248 | he_dev->cells_per_row = 40; | ||
1249 | he_dev->bytes_per_row = 2048; | ||
1250 | he_dev->r0_numrows = 256; | ||
1251 | he_dev->tx_numrows = 512; | ||
1252 | he_dev->r1_numrows = 256; | ||
1253 | he_dev->r0_startrow = 0; | ||
1254 | he_dev->tx_startrow = 256; | ||
1255 | he_dev->r1_startrow = 768; | ||
1256 | } else { | ||
1257 | he_dev->cells_per_row = 20; | ||
1258 | he_dev->bytes_per_row = 1024; | ||
1259 | he_dev->r0_numrows = 512; | ||
1260 | he_dev->tx_numrows = 1018; | ||
1261 | he_dev->r1_numrows = 512; | ||
1262 | he_dev->r0_startrow = 6; | ||
1263 | he_dev->tx_startrow = 518; | ||
1264 | he_dev->r1_startrow = 1536; | ||
1265 | } | ||
1266 | |||
1267 | he_dev->cells_per_lbuf = 4; | ||
1268 | he_dev->buffer_limit = 4; | ||
1269 | he_dev->r0_numbuffs = he_dev->r0_numrows * | ||
1270 | he_dev->cells_per_row / he_dev->cells_per_lbuf; | ||
1271 | if (he_dev->r0_numbuffs > 2560) | ||
1272 | he_dev->r0_numbuffs = 2560; | ||
1273 | |||
1274 | he_dev->r1_numbuffs = he_dev->r1_numrows * | ||
1275 | he_dev->cells_per_row / he_dev->cells_per_lbuf; | ||
1276 | if (he_dev->r1_numbuffs > 2560) | ||
1277 | he_dev->r1_numbuffs = 2560; | ||
1278 | |||
1279 | he_dev->tx_numbuffs = he_dev->tx_numrows * | ||
1280 | he_dev->cells_per_row / he_dev->cells_per_lbuf; | ||
1281 | if (he_dev->tx_numbuffs > 5120) | ||
1282 | he_dev->tx_numbuffs = 5120; | ||
1283 | |||
1284 | /* 5.1.2 configure hardware dependent registers */ | ||
1285 | |||
1286 | he_writel(he_dev, | ||
1287 | SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) | | ||
1288 | RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) | | ||
1289 | (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) | | ||
1290 | (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)), | ||
1291 | LBARB); | ||
1292 | |||
1293 | he_writel(he_dev, BANK_ON | | ||
1294 | (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)), | ||
1295 | SDRAMCON); | ||
1296 | |||
1297 | he_writel(he_dev, | ||
1298 | (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) | | ||
1299 | RM_RW_WAIT(1), RCMCONFIG); | ||
1300 | he_writel(he_dev, | ||
1301 | (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) | | ||
1302 | TM_RW_WAIT(1), TCMCONFIG); | ||
1303 | |||
1304 | he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG); | ||
1305 | |||
1306 | he_writel(he_dev, | ||
1307 | (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) | | ||
1308 | (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) | | ||
1309 | RX_VALVP(he_dev->vpibits) | | ||
1310 | RX_VALVC(he_dev->vcibits), RC_CONFIG); | ||
1311 | |||
1312 | he_writel(he_dev, DRF_THRESH(0x20) | | ||
1313 | (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) | | ||
1314 | TX_VCI_MASK(he_dev->vcibits) | | ||
1315 | LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG); | ||
1316 | |||
1317 | he_writel(he_dev, 0x0, TXAAL5_PROTO); | ||
1318 | |||
1319 | he_writel(he_dev, PHY_INT_ENB | | ||
1320 | (he_is622(he_dev) ? PTMR_PRE(67 - 1) : PTMR_PRE(50 - 1)), | ||
1321 | RH_CONFIG); | ||
1322 | |||
1323 | /* 5.1.3 initialize connection memory */ | ||
1324 | |||
1325 | for (i = 0; i < TCM_MEM_SIZE; ++i) | ||
1326 | he_writel_tcm(he_dev, 0, i); | ||
1327 | |||
1328 | for (i = 0; i < RCM_MEM_SIZE; ++i) | ||
1329 | he_writel_rcm(he_dev, 0, i); | ||
1330 | |||
1331 | /* | ||
1332 | * transmit connection memory map | ||
1333 | * | ||
1334 | * tx memory | ||
1335 | * 0x0 ___________________ | ||
1336 | * | | | ||
1337 | * | | | ||
1338 | * | TSRa | | ||
1339 | * | | | ||
1340 | * | | | ||
1341 | * 0x8000|___________________| | ||
1342 | * | | | ||
1343 | * | TSRb | | ||
1344 | * 0xc000|___________________| | ||
1345 | * | | | ||
1346 | * | TSRc | | ||
1347 | * 0xe000|___________________| | ||
1348 | * | TSRd | | ||
1349 | * 0xf000|___________________| | ||
1350 | * | tmABR | | ||
1351 | * 0x10000|___________________| | ||
1352 | * | | | ||
1353 | * | tmTPD | | ||
1354 | * |___________________| | ||
1355 | * | | | ||
1356 | * .... | ||
1357 | * 0x1ffff|___________________| | ||
1358 | * | ||
1359 | * | ||
1360 | */ | ||
1361 | |||
1362 | he_writel(he_dev, CONFIG_TSRB, TSRB_BA); | ||
1363 | he_writel(he_dev, CONFIG_TSRC, TSRC_BA); | ||
1364 | he_writel(he_dev, CONFIG_TSRD, TSRD_BA); | ||
1365 | he_writel(he_dev, CONFIG_TMABR, TMABR_BA); | ||
1366 | he_writel(he_dev, CONFIG_TPDBA, TPD_BA); | ||
1367 | |||
1368 | |||
1369 | /* | ||
1370 | * receive connection memory map | ||
1371 | * | ||
1372 | * 0x0 ___________________ | ||
1373 | * | | | ||
1374 | * | | | ||
1375 | * | RSRa | | ||
1376 | * | | | ||
1377 | * | | | ||
1378 | * 0x8000|___________________| | ||
1379 | * | | | ||
1380 | * | rx0/1 | | ||
1381 | * | LBM | link lists of local | ||
1382 | * | tx | buffer memory | ||
1383 | * | | | ||
1384 | * 0xd000|___________________| | ||
1385 | * | | | ||
1386 | * | rmABR | | ||
1387 | * 0xe000|___________________| | ||
1388 | * | | | ||
1389 | * | RSRb | | ||
1390 | * |___________________| | ||
1391 | * | | | ||
1392 | * .... | ||
1393 | * 0xffff|___________________| | ||
1394 | */ | ||
1395 | |||
1396 | he_writel(he_dev, 0x08000, RCMLBM_BA); | ||
1397 | he_writel(he_dev, 0x0e000, RCMRSRB_BA); | ||
1398 | he_writel(he_dev, 0x0d800, RCMABR_BA); | ||
1399 | |||
1400 | /* 5.1.4 initialize local buffer free pools linked lists */ | ||
1401 | |||
1402 | he_init_rx_lbfp0(he_dev); | ||
1403 | he_init_rx_lbfp1(he_dev); | ||
1404 | |||
1405 | he_writel(he_dev, 0x0, RLBC_H); | ||
1406 | he_writel(he_dev, 0x0, RLBC_T); | ||
1407 | he_writel(he_dev, 0x0, RLBC_H2); | ||
1408 | |||
1409 | he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */ | ||
1410 | he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */ | ||
1411 | |||
1412 | he_init_tx_lbfp(he_dev); | ||
1413 | |||
1414 | he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA); | ||
1415 | |||
1416 | /* 5.1.5 initialize intermediate receive queues */ | ||
1417 | |||
1418 | if (he_is622(he_dev)) { | ||
1419 | he_writel(he_dev, 0x000f, G0_INMQ_S); | ||
1420 | he_writel(he_dev, 0x200f, G0_INMQ_L); | ||
1421 | |||
1422 | he_writel(he_dev, 0x001f, G1_INMQ_S); | ||
1423 | he_writel(he_dev, 0x201f, G1_INMQ_L); | ||
1424 | |||
1425 | he_writel(he_dev, 0x002f, G2_INMQ_S); | ||
1426 | he_writel(he_dev, 0x202f, G2_INMQ_L); | ||
1427 | |||
1428 | he_writel(he_dev, 0x003f, G3_INMQ_S); | ||
1429 | he_writel(he_dev, 0x203f, G3_INMQ_L); | ||
1430 | |||
1431 | he_writel(he_dev, 0x004f, G4_INMQ_S); | ||
1432 | he_writel(he_dev, 0x204f, G4_INMQ_L); | ||
1433 | |||
1434 | he_writel(he_dev, 0x005f, G5_INMQ_S); | ||
1435 | he_writel(he_dev, 0x205f, G5_INMQ_L); | ||
1436 | |||
1437 | he_writel(he_dev, 0x006f, G6_INMQ_S); | ||
1438 | he_writel(he_dev, 0x206f, G6_INMQ_L); | ||
1439 | |||
1440 | he_writel(he_dev, 0x007f, G7_INMQ_S); | ||
1441 | he_writel(he_dev, 0x207f, G7_INMQ_L); | ||
1442 | } else { | ||
1443 | he_writel(he_dev, 0x0000, G0_INMQ_S); | ||
1444 | he_writel(he_dev, 0x0008, G0_INMQ_L); | ||
1445 | |||
1446 | he_writel(he_dev, 0x0001, G1_INMQ_S); | ||
1447 | he_writel(he_dev, 0x0009, G1_INMQ_L); | ||
1448 | |||
1449 | he_writel(he_dev, 0x0002, G2_INMQ_S); | ||
1450 | he_writel(he_dev, 0x000a, G2_INMQ_L); | ||
1451 | |||
1452 | he_writel(he_dev, 0x0003, G3_INMQ_S); | ||
1453 | he_writel(he_dev, 0x000b, G3_INMQ_L); | ||
1454 | |||
1455 | he_writel(he_dev, 0x0004, G4_INMQ_S); | ||
1456 | he_writel(he_dev, 0x000c, G4_INMQ_L); | ||
1457 | |||
1458 | he_writel(he_dev, 0x0005, G5_INMQ_S); | ||
1459 | he_writel(he_dev, 0x000d, G5_INMQ_L); | ||
1460 | |||
1461 | he_writel(he_dev, 0x0006, G6_INMQ_S); | ||
1462 | he_writel(he_dev, 0x000e, G6_INMQ_L); | ||
1463 | |||
1464 | he_writel(he_dev, 0x0007, G7_INMQ_S); | ||
1465 | he_writel(he_dev, 0x000f, G7_INMQ_L); | ||
1466 | } | ||
1467 | |||
1468 | /* 5.1.6 application tunable parameters */ | ||
1469 | |||
1470 | he_writel(he_dev, 0x0, MCC); | ||
1471 | he_writel(he_dev, 0x0, OEC); | ||
1472 | he_writel(he_dev, 0x0, DCC); | ||
1473 | he_writel(he_dev, 0x0, CEC); | ||
1474 | |||
1475 | /* 5.1.7 cs block initialization */ | ||
1476 | |||
1477 | he_init_cs_block(he_dev); | ||
1478 | |||
1479 | /* 5.1.8 cs block connection memory initialization */ | ||
1480 | |||
1481 | if (he_init_cs_block_rcm(he_dev) < 0) | ||
1482 | return -ENOMEM; | ||
1483 | |||
1484 | /* 5.1.10 initialize host structures */ | ||
1485 | |||
1486 | he_init_tpdrq(he_dev); | ||
1487 | |||
1488 | #ifdef USE_TPD_POOL | ||
1489 | he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev, | ||
1490 | sizeof(struct he_tpd), TPD_ALIGNMENT, 0); | ||
1491 | if (he_dev->tpd_pool == NULL) { | ||
1492 | hprintk("unable to create tpd pci_pool\n"); | ||
1493 | return -ENOMEM; | ||
1494 | } | ||
1495 | |||
1496 | INIT_LIST_HEAD(&he_dev->outstanding_tpds); | ||
1497 | #else | ||
1498 | he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev, | ||
1499 | CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys); | ||
1500 | if (!he_dev->tpd_base) | ||
1501 | return -ENOMEM; | ||
1502 | |||
1503 | for (i = 0; i < CONFIG_NUMTPDS; ++i) { | ||
1504 | he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT); | ||
1505 | he_dev->tpd_base[i].inuse = 0; | ||
1506 | } | ||
1507 | |||
1508 | he_dev->tpd_head = he_dev->tpd_base; | ||
1509 | he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS - 1]; | ||
1510 | #endif | ||
1511 | |||
1512 | if (he_init_group(he_dev, 0) != 0) | ||
1513 | return -ENOMEM; | ||
1514 | |||
1515 | for (group = 1; group < HE_NUM_GROUPS; ++group) { | ||
1516 | he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); | ||
1517 | he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); | ||
1518 | he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); | ||
1519 | he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), | ||
1520 | G0_RBPS_BS + (group * 32)); | ||
1521 | |||
1522 | he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32)); | ||
1523 | he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32)); | ||
1524 | he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), | ||
1525 | G0_RBPL_QI + (group * 32)); | ||
1526 | he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32)); | ||
1527 | |||
1528 | he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16)); | ||
1529 | he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16)); | ||
1530 | he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0), | ||
1531 | G0_RBRQ_Q + (group * 16)); | ||
1532 | he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16)); | ||
1533 | |||
1534 | he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16)); | ||
1535 | he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16)); | ||
1536 | he_writel(he_dev, TBRQ_THRESH(0x1), | ||
1537 | G0_TBRQ_THRESH + (group * 16)); | ||
1538 | he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16)); | ||
1539 | } | ||
1540 | |||
1541 | /* host status page */ | ||
1542 | |||
1543 | he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev, | ||
1544 | sizeof(struct he_hsp), &he_dev->hsp_phys); | ||
1545 | if (he_dev->hsp == NULL) { | ||
1546 | hprintk("failed to allocate host status page\n"); | ||
1547 | return -ENOMEM; | ||
1548 | } | ||
1549 | memset(he_dev->hsp, 0, sizeof(struct he_hsp)); | ||
1550 | he_writel(he_dev, he_dev->hsp_phys, HSP_BA); | ||
1551 | |||
1552 | /* initialize framer */ | ||
1553 | |||
1554 | #ifdef CONFIG_ATM_HE_USE_SUNI | ||
1555 | suni_init(he_dev->atm_dev); | ||
1556 | if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start) | ||
1557 | he_dev->atm_dev->phy->start(he_dev->atm_dev); | ||
1558 | #endif /* CONFIG_ATM_HE_USE_SUNI */ | ||
1559 | |||
1560 | if (sdh) { | ||
1561 | /* this really should be in suni.c but for now... */ | ||
1562 | int val; | ||
1563 | |||
1564 | val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); | ||
1565 | val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT); | ||
1566 | he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM); | ||
1567 | } | ||
1568 | |||
1569 | /* 5.1.12 enable transmit and receive */ | ||
1570 | |||
1571 | reg = he_readl_mbox(he_dev, CS_ERCTL0); | ||
1572 | reg |= TX_ENABLE|ER_ENABLE; | ||
1573 | he_writel_mbox(he_dev, reg, CS_ERCTL0); | ||
1574 | |||
1575 | reg = he_readl(he_dev, RC_CONFIG); | ||
1576 | reg |= RX_ENABLE; | ||
1577 | he_writel(he_dev, reg, RC_CONFIG); | ||
1578 | |||
1579 | for (i = 0; i < HE_NUM_CS_STPER; ++i) { | ||
1580 | he_dev->cs_stper[i].inuse = 0; | ||
1581 | he_dev->cs_stper[i].pcr = -1; | ||
1582 | } | ||
1583 | he_dev->total_bw = 0; | ||
1584 | |||
1585 | |||
1586 | /* atm linux initialization */ | ||
1587 | |||
1588 | he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits; | ||
1589 | he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits; | ||
1590 | |||
1591 | he_dev->irq_peak = 0; | ||
1592 | he_dev->rbrq_peak = 0; | ||
1593 | he_dev->rbpl_peak = 0; | ||
1594 | he_dev->tbrq_peak = 0; | ||
1595 | |||
1596 | HPRINTK("hell bent for leather!\n"); | ||
1597 | |||
1598 | return 0; | ||
1599 | } | ||
1600 | |||
1601 | static void | ||
1602 | he_stop(struct he_dev *he_dev) | ||
1603 | { | ||
1604 | u16 command; | ||
1605 | u32 gen_cntl_0, reg; | ||
1606 | struct pci_dev *pci_dev; | ||
1607 | |||
1608 | pci_dev = he_dev->pci_dev; | ||
1609 | |||
1610 | /* disable interrupts */ | ||
1611 | |||
1612 | if (he_dev->membase) { | ||
1613 | pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0); | ||
1614 | gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB); | ||
1615 | pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); | ||
1616 | |||
1617 | #ifdef USE_TASKLET | ||
1618 | tasklet_disable(&he_dev->tasklet); | ||
1619 | #endif | ||
1620 | |||
1621 | /* disable recv and transmit */ | ||
1622 | |||
1623 | reg = he_readl_mbox(he_dev, CS_ERCTL0); | ||
1624 | reg &= ~(TX_ENABLE|ER_ENABLE); | ||
1625 | he_writel_mbox(he_dev, reg, CS_ERCTL0); | ||
1626 | |||
1627 | reg = he_readl(he_dev, RC_CONFIG); | ||
1628 | reg &= ~(RX_ENABLE); | ||
1629 | he_writel(he_dev, reg, RC_CONFIG); | ||
1630 | } | ||
1631 | |||
1632 | #ifdef CONFIG_ATM_HE_USE_SUNI | ||
1633 | if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop) | ||
1634 | he_dev->atm_dev->phy->stop(he_dev->atm_dev); | ||
1635 | #endif /* CONFIG_ATM_HE_USE_SUNI */ | ||
1636 | |||
1637 | if (he_dev->irq) | ||
1638 | free_irq(he_dev->irq, he_dev); | ||
1639 | |||
1640 | if (he_dev->irq_base) | ||
1641 | pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1) | ||
1642 | * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys); | ||
1643 | |||
1644 | if (he_dev->hsp) | ||
1645 | pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp), | ||
1646 | he_dev->hsp, he_dev->hsp_phys); | ||
1647 | |||
1648 | if (he_dev->rbpl_base) { | ||
1649 | #ifdef USE_RBPL_POOL | ||
1650 | for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { | ||
1651 | void *cpuaddr = he_dev->rbpl_virt[i].virt; | ||
1652 | dma_addr_t dma_handle = he_dev->rbpl_base[i].phys; | ||
1653 | |||
1654 | pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle); | ||
1655 | } | ||
1656 | #else | ||
1657 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE | ||
1658 | * CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys); | ||
1659 | #endif | ||
1660 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE | ||
1661 | * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); | ||
1662 | } | ||
1663 | |||
1664 | #ifdef USE_RBPL_POOL | ||
1665 | if (he_dev->rbpl_pool) | ||
1666 | pci_pool_destroy(he_dev->rbpl_pool); | ||
1667 | #endif | ||
1668 | |||
1669 | #ifdef USE_RBPS | ||
1670 | if (he_dev->rbps_base) { | ||
1671 | #ifdef USE_RBPS_POOL | ||
1672 | for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { | ||
1673 | void *cpuaddr = he_dev->rbps_virt[i].virt; | ||
1674 | dma_addr_t dma_handle = he_dev->rbps_base[i].phys; | ||
1675 | |||
1676 | pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle); | ||
1677 | } | ||
1678 | #else | ||
1679 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE | ||
1680 | * CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys); | ||
1681 | #endif | ||
1682 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE | ||
1683 | * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys); | ||
1684 | } | ||
1685 | |||
1686 | #ifdef USE_RBPS_POOL | ||
1687 | if (he_dev->rbps_pool) | ||
1688 | pci_pool_destroy(he_dev->rbps_pool); | ||
1689 | #endif | ||
1690 | |||
1691 | #endif /* USE_RBPS */ | ||
1692 | |||
1693 | if (he_dev->rbrq_base) | ||
1694 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), | ||
1695 | he_dev->rbrq_base, he_dev->rbrq_phys); | ||
1696 | |||
1697 | if (he_dev->tbrq_base) | ||
1698 | pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), | ||
1699 | he_dev->tbrq_base, he_dev->tbrq_phys); | ||
1700 | |||
1701 | if (he_dev->tpdrq_base) | ||
1702 | pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), | ||
1703 | he_dev->tpdrq_base, he_dev->tpdrq_phys); | ||
1704 | |||
1705 | #ifdef USE_TPD_POOL | ||
1706 | if (he_dev->tpd_pool) | ||
1707 | pci_pool_destroy(he_dev->tpd_pool); | ||
1708 | #else | ||
1709 | if (he_dev->tpd_base) | ||
1710 | pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd), | ||
1711 | he_dev->tpd_base, he_dev->tpd_base_phys); | ||
1712 | #endif | ||
1713 | |||
1714 | if (he_dev->pci_dev) { | ||
1715 | pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command); | ||
1716 | command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | ||
1717 | pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command); | ||
1718 | } | ||
1719 | |||
1720 | if (he_dev->membase) | ||
1721 | iounmap(he_dev->membase); | ||
1722 | } | ||
1723 | |||
1724 | static struct he_tpd * | ||
1725 | __alloc_tpd(struct he_dev *he_dev) | ||
1726 | { | ||
1727 | #ifdef USE_TPD_POOL | ||
1728 | struct he_tpd *tpd; | ||
1729 | dma_addr_t dma_handle; | ||
1730 | |||
1731 | tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle); | ||
1732 | if (tpd == NULL) | ||
1733 | return NULL; | ||
1734 | |||
1735 | tpd->status = TPD_ADDR(dma_handle); | ||
1736 | tpd->reserved = 0; | ||
1737 | tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0; | ||
1738 | tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0; | ||
1739 | tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0; | ||
1740 | |||
1741 | return tpd; | ||
1742 | #else | ||
1743 | int i; | ||
1744 | |||
1745 | for (i = 0; i < CONFIG_NUMTPDS; ++i) { | ||
1746 | ++he_dev->tpd_head; | ||
1747 | if (he_dev->tpd_head > he_dev->tpd_end) { | ||
1748 | he_dev->tpd_head = he_dev->tpd_base; | ||
1749 | } | ||
1750 | |||
1751 | if (!he_dev->tpd_head->inuse) { | ||
1752 | he_dev->tpd_head->inuse = 1; | ||
1753 | he_dev->tpd_head->status &= TPD_MASK; | ||
1754 | he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0; | ||
1755 | he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0; | ||
1756 | he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0; | ||
1757 | return he_dev->tpd_head; | ||
1758 | } | ||
1759 | } | ||
1760 | hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS); | ||
1761 | return NULL; | ||
1762 | #endif | ||
1763 | } | ||
1764 | |||
1765 | #define AAL5_LEN(buf,len) \ | ||
1766 | ((((unsigned char *)(buf))[(len)-6] << 8) | \ | ||
1767 | (((unsigned char *)(buf))[(len)-5])) | ||
1768 | |||
1769 | /* 2.10.1.2 receive | ||
1770 | * | ||
1771 | * aal5 packets can optionally return the tcp checksum in the lower | ||
1772 | * 16 bits of the crc (RSR0_TCP_CKSUM) | ||
1773 | */ | ||
1774 | |||
1775 | #define TCP_CKSUM(buf,len) \ | ||
1776 | ((((unsigned char *)(buf))[(len)-2] << 8) | \ | ||
1777 | (((unsigned char *)(buf))[(len-1)])) | ||
1778 | |||
1779 | static int | ||
1780 | he_service_rbrq(struct he_dev *he_dev, int group) | ||
1781 | { | ||
1782 | struct he_rbrq *rbrq_tail = (struct he_rbrq *) | ||
1783 | ((unsigned long)he_dev->rbrq_base | | ||
1784 | he_dev->hsp->group[group].rbrq_tail); | ||
1785 | struct he_rbp *rbp = NULL; | ||
1786 | unsigned cid, lastcid = -1; | ||
1787 | unsigned buf_len = 0; | ||
1788 | struct sk_buff *skb; | ||
1789 | struct atm_vcc *vcc = NULL; | ||
1790 | struct he_vcc *he_vcc; | ||
1791 | struct he_iovec *iov; | ||
1792 | int pdus_assembled = 0; | ||
1793 | int updated = 0; | ||
1794 | |||
1795 | read_lock(&vcc_sklist_lock); | ||
1796 | while (he_dev->rbrq_head != rbrq_tail) { | ||
1797 | ++updated; | ||
1798 | |||
1799 | HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n", | ||
1800 | he_dev->rbrq_head, group, | ||
1801 | RBRQ_ADDR(he_dev->rbrq_head), | ||
1802 | RBRQ_BUFLEN(he_dev->rbrq_head), | ||
1803 | RBRQ_CID(he_dev->rbrq_head), | ||
1804 | RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "", | ||
1805 | RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "", | ||
1806 | RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "", | ||
1807 | RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "", | ||
1808 | RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "", | ||
1809 | RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : ""); | ||
1810 | |||
1811 | #ifdef USE_RBPS | ||
1812 | if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF) | ||
1813 | rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; | ||
1814 | else | ||
1815 | #endif | ||
1816 | rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; | ||
1817 | |||
1818 | buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; | ||
1819 | cid = RBRQ_CID(he_dev->rbrq_head); | ||
1820 | |||
1821 | if (cid != lastcid) | ||
1822 | vcc = __find_vcc(he_dev, cid); | ||
1823 | lastcid = cid; | ||
1824 | |||
1825 | if (vcc == NULL) { | ||
1826 | hprintk("vcc == NULL (cid 0x%x)\n", cid); | ||
1827 | if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) | ||
1828 | rbp->status &= ~RBP_LOANED; | ||
1829 | |||
1830 | goto next_rbrq_entry; | ||
1831 | } | ||
1832 | |||
1833 | he_vcc = HE_VCC(vcc); | ||
1834 | if (he_vcc == NULL) { | ||
1835 | hprintk("he_vcc == NULL (cid 0x%x)\n", cid); | ||
1836 | if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) | ||
1837 | rbp->status &= ~RBP_LOANED; | ||
1838 | goto next_rbrq_entry; | ||
1839 | } | ||
1840 | |||
1841 | if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) { | ||
1842 | hprintk("HBUF_ERR! (cid 0x%x)\n", cid); | ||
1843 | atomic_inc(&vcc->stats->rx_drop); | ||
1844 | goto return_host_buffers; | ||
1845 | } | ||
1846 | |||
1847 | he_vcc->iov_tail->iov_base = RBRQ_ADDR(he_dev->rbrq_head); | ||
1848 | he_vcc->iov_tail->iov_len = buf_len; | ||
1849 | he_vcc->pdu_len += buf_len; | ||
1850 | ++he_vcc->iov_tail; | ||
1851 | |||
1852 | if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) { | ||
1853 | lastcid = -1; | ||
1854 | HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid); | ||
1855 | wake_up(&he_vcc->rx_waitq); | ||
1856 | goto return_host_buffers; | ||
1857 | } | ||
1858 | |||
1859 | #ifdef notdef | ||
1860 | if ((he_vcc->iov_tail - he_vcc->iov_head) > HE_MAXIOV) { | ||
1861 | hprintk("iovec full! cid 0x%x\n", cid); | ||
1862 | goto return_host_buffers; | ||
1863 | } | ||
1864 | #endif | ||
1865 | if (!RBRQ_END_PDU(he_dev->rbrq_head)) | ||
1866 | goto next_rbrq_entry; | ||
1867 | |||
1868 | if (RBRQ_LEN_ERR(he_dev->rbrq_head) | ||
1869 | || RBRQ_CRC_ERR(he_dev->rbrq_head)) { | ||
1870 | HPRINTK("%s%s (%d.%d)\n", | ||
1871 | RBRQ_CRC_ERR(he_dev->rbrq_head) | ||
1872 | ? "CRC_ERR " : "", | ||
1873 | RBRQ_LEN_ERR(he_dev->rbrq_head) | ||
1874 | ? "LEN_ERR" : "", | ||
1875 | vcc->vpi, vcc->vci); | ||
1876 | atomic_inc(&vcc->stats->rx_err); | ||
1877 | goto return_host_buffers; | ||
1878 | } | ||
1879 | |||
1880 | skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve, | ||
1881 | GFP_ATOMIC); | ||
1882 | if (!skb) { | ||
1883 | HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci); | ||
1884 | goto return_host_buffers; | ||
1885 | } | ||
1886 | |||
1887 | if (rx_skb_reserve > 0) | ||
1888 | skb_reserve(skb, rx_skb_reserve); | ||
1889 | |||
1890 | do_gettimeofday(&skb->stamp); | ||
1891 | |||
1892 | for (iov = he_vcc->iov_head; | ||
1893 | iov < he_vcc->iov_tail; ++iov) { | ||
1894 | #ifdef USE_RBPS | ||
1895 | if (iov->iov_base & RBP_SMALLBUF) | ||
1896 | memcpy(skb_put(skb, iov->iov_len), | ||
1897 | he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); | ||
1898 | else | ||
1899 | #endif | ||
1900 | memcpy(skb_put(skb, iov->iov_len), | ||
1901 | he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); | ||
1902 | } | ||
1903 | |||
1904 | switch (vcc->qos.aal) { | ||
1905 | case ATM_AAL0: | ||
1906 | /* 2.10.1.5 raw cell receive */ | ||
1907 | skb->len = ATM_AAL0_SDU; | ||
1908 | skb->tail = skb->data + skb->len; | ||
1909 | break; | ||
1910 | case ATM_AAL5: | ||
1911 | /* 2.10.1.2 aal5 receive */ | ||
1912 | |||
1913 | skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len); | ||
1914 | skb->tail = skb->data + skb->len; | ||
1915 | #ifdef USE_CHECKSUM_HW | ||
1916 | if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) { | ||
1917 | skb->ip_summed = CHECKSUM_HW; | ||
1918 | skb->csum = TCP_CKSUM(skb->data, | ||
1919 | he_vcc->pdu_len); | ||
1920 | } | ||
1921 | #endif | ||
1922 | break; | ||
1923 | } | ||
1924 | |||
1925 | #ifdef should_never_happen | ||
1926 | if (skb->len > vcc->qos.rxtp.max_sdu) | ||
1927 | hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)! cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid); | ||
1928 | #endif | ||
1929 | |||
1930 | #ifdef notdef | ||
1931 | ATM_SKB(skb)->vcc = vcc; | ||
1932 | #endif | ||
1933 | vcc->push(vcc, skb); | ||
1934 | |||
1935 | atomic_inc(&vcc->stats->rx); | ||
1936 | |||
1937 | return_host_buffers: | ||
1938 | ++pdus_assembled; | ||
1939 | |||
1940 | for (iov = he_vcc->iov_head; | ||
1941 | iov < he_vcc->iov_tail; ++iov) { | ||
1942 | #ifdef USE_RBPS | ||
1943 | if (iov->iov_base & RBP_SMALLBUF) | ||
1944 | rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)]; | ||
1945 | else | ||
1946 | #endif | ||
1947 | rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)]; | ||
1948 | |||
1949 | rbp->status &= ~RBP_LOANED; | ||
1950 | } | ||
1951 | |||
1952 | he_vcc->iov_tail = he_vcc->iov_head; | ||
1953 | he_vcc->pdu_len = 0; | ||
1954 | |||
1955 | next_rbrq_entry: | ||
1956 | he_dev->rbrq_head = (struct he_rbrq *) | ||
1957 | ((unsigned long) he_dev->rbrq_base | | ||
1958 | RBRQ_MASK(++he_dev->rbrq_head)); | ||
1959 | |||
1960 | } | ||
1961 | read_unlock(&vcc_sklist_lock); | ||
1962 | |||
1963 | if (updated) { | ||
1964 | if (updated > he_dev->rbrq_peak) | ||
1965 | he_dev->rbrq_peak = updated; | ||
1966 | |||
1967 | he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head), | ||
1968 | G0_RBRQ_H + (group * 16)); | ||
1969 | } | ||
1970 | |||
1971 | return pdus_assembled; | ||
1972 | } | ||
1973 | |||
1974 | static void | ||
1975 | he_service_tbrq(struct he_dev *he_dev, int group) | ||
1976 | { | ||
1977 | struct he_tbrq *tbrq_tail = (struct he_tbrq *) | ||
1978 | ((unsigned long)he_dev->tbrq_base | | ||
1979 | he_dev->hsp->group[group].tbrq_tail); | ||
1980 | struct he_tpd *tpd; | ||
1981 | int slot, updated = 0; | ||
1982 | #ifdef USE_TPD_POOL | ||
1983 | struct he_tpd *__tpd; | ||
1984 | #endif | ||
1985 | |||
1986 | /* 2.1.6 transmit buffer return queue */ | ||
1987 | |||
1988 | while (he_dev->tbrq_head != tbrq_tail) { | ||
1989 | ++updated; | ||
1990 | |||
1991 | HPRINTK("tbrq%d 0x%x%s%s\n", | ||
1992 | group, | ||
1993 | TBRQ_TPD(he_dev->tbrq_head), | ||
1994 | TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "", | ||
1995 | TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : ""); | ||
1996 | #ifdef USE_TPD_POOL | ||
1997 | tpd = NULL; | ||
1998 | list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) { | ||
1999 | if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) { | ||
2000 | tpd = __tpd; | ||
2001 | list_del(&__tpd->entry); | ||
2002 | break; | ||
2003 | } | ||
2004 | } | ||
2005 | |||
2006 | if (tpd == NULL) { | ||
2007 | hprintk("unable to locate tpd for dma buffer %x\n", | ||
2008 | TBRQ_TPD(he_dev->tbrq_head)); | ||
2009 | goto next_tbrq_entry; | ||
2010 | } | ||
2011 | #else | ||
2012 | tpd = &he_dev->tpd_base[ TPD_INDEX(TBRQ_TPD(he_dev->tbrq_head)) ]; | ||
2013 | #endif | ||
2014 | |||
2015 | if (TBRQ_EOS(he_dev->tbrq_head)) { | ||
2016 | HPRINTK("wake_up(tx_waitq) cid 0x%x\n", | ||
2017 | he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci)); | ||
2018 | if (tpd->vcc) | ||
2019 | wake_up(&HE_VCC(tpd->vcc)->tx_waitq); | ||
2020 | |||
2021 | goto next_tbrq_entry; | ||
2022 | } | ||
2023 | |||
2024 | for (slot = 0; slot < TPD_MAXIOV; ++slot) { | ||
2025 | if (tpd->iovec[slot].addr) | ||
2026 | pci_unmap_single(he_dev->pci_dev, | ||
2027 | tpd->iovec[slot].addr, | ||
2028 | tpd->iovec[slot].len & TPD_LEN_MASK, | ||
2029 | PCI_DMA_TODEVICE); | ||
2030 | if (tpd->iovec[slot].len & TPD_LST) | ||
2031 | break; | ||
2032 | |||
2033 | } | ||
2034 | |||
2035 | if (tpd->skb) { /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */ | ||
2036 | if (tpd->vcc && tpd->vcc->pop) | ||
2037 | tpd->vcc->pop(tpd->vcc, tpd->skb); | ||
2038 | else | ||
2039 | dev_kfree_skb_any(tpd->skb); | ||
2040 | } | ||
2041 | |||
2042 | next_tbrq_entry: | ||
2043 | #ifdef USE_TPD_POOL | ||
2044 | if (tpd) | ||
2045 | pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); | ||
2046 | #else | ||
2047 | tpd->inuse = 0; | ||
2048 | #endif | ||
2049 | he_dev->tbrq_head = (struct he_tbrq *) | ||
2050 | ((unsigned long) he_dev->tbrq_base | | ||
2051 | TBRQ_MASK(++he_dev->tbrq_head)); | ||
2052 | } | ||
2053 | |||
2054 | if (updated) { | ||
2055 | if (updated > he_dev->tbrq_peak) | ||
2056 | he_dev->tbrq_peak = updated; | ||
2057 | |||
2058 | he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head), | ||
2059 | G0_TBRQ_H + (group * 16)); | ||
2060 | } | ||
2061 | } | ||
2062 | |||
2063 | |||
2064 | static void | ||
2065 | he_service_rbpl(struct he_dev *he_dev, int group) | ||
2066 | { | ||
2067 | struct he_rbp *newtail; | ||
2068 | struct he_rbp *rbpl_head; | ||
2069 | int moved = 0; | ||
2070 | |||
2071 | rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | | ||
2072 | RBPL_MASK(he_readl(he_dev, G0_RBPL_S))); | ||
2073 | |||
2074 | for (;;) { | ||
2075 | newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | | ||
2076 | RBPL_MASK(he_dev->rbpl_tail+1)); | ||
2077 | |||
2078 | /* table 3.42 -- rbpl_tail should never be set to rbpl_head */ | ||
2079 | if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED)) | ||
2080 | break; | ||
2081 | |||
2082 | newtail->status |= RBP_LOANED; | ||
2083 | he_dev->rbpl_tail = newtail; | ||
2084 | ++moved; | ||
2085 | } | ||
2086 | |||
2087 | if (moved) | ||
2088 | he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); | ||
2089 | } | ||
2090 | |||
2091 | #ifdef USE_RBPS | ||
2092 | static void | ||
2093 | he_service_rbps(struct he_dev *he_dev, int group) | ||
2094 | { | ||
2095 | struct he_rbp *newtail; | ||
2096 | struct he_rbp *rbps_head; | ||
2097 | int moved = 0; | ||
2098 | |||
2099 | rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | | ||
2100 | RBPS_MASK(he_readl(he_dev, G0_RBPS_S))); | ||
2101 | |||
2102 | for (;;) { | ||
2103 | newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | | ||
2104 | RBPS_MASK(he_dev->rbps_tail+1)); | ||
2105 | |||
2106 | /* table 3.42 -- rbps_tail should never be set to rbps_head */ | ||
2107 | if ((newtail == rbps_head) || (newtail->status & RBP_LOANED)) | ||
2108 | break; | ||
2109 | |||
2110 | newtail->status |= RBP_LOANED; | ||
2111 | he_dev->rbps_tail = newtail; | ||
2112 | ++moved; | ||
2113 | } | ||
2114 | |||
2115 | if (moved) | ||
2116 | he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T); | ||
2117 | } | ||
2118 | #endif /* USE_RBPS */ | ||
2119 | |||
2120 | static void | ||
2121 | he_tasklet(unsigned long data) | ||
2122 | { | ||
2123 | unsigned long flags; | ||
2124 | struct he_dev *he_dev = (struct he_dev *) data; | ||
2125 | int group, type; | ||
2126 | int updated = 0; | ||
2127 | |||
2128 | HPRINTK("tasklet (0x%lx)\n", data); | ||
2129 | #ifdef USE_TASKLET | ||
2130 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2131 | #endif | ||
2132 | |||
2133 | while (he_dev->irq_head != he_dev->irq_tail) { | ||
2134 | ++updated; | ||
2135 | |||
2136 | type = ITYPE_TYPE(he_dev->irq_head->isw); | ||
2137 | group = ITYPE_GROUP(he_dev->irq_head->isw); | ||
2138 | |||
2139 | switch (type) { | ||
2140 | case ITYPE_RBRQ_THRESH: | ||
2141 | HPRINTK("rbrq%d threshold\n", group); | ||
2142 | /* fall through */ | ||
2143 | case ITYPE_RBRQ_TIMER: | ||
2144 | if (he_service_rbrq(he_dev, group)) { | ||
2145 | he_service_rbpl(he_dev, group); | ||
2146 | #ifdef USE_RBPS | ||
2147 | he_service_rbps(he_dev, group); | ||
2148 | #endif /* USE_RBPS */ | ||
2149 | } | ||
2150 | break; | ||
2151 | case ITYPE_TBRQ_THRESH: | ||
2152 | HPRINTK("tbrq%d threshold\n", group); | ||
2153 | /* fall through */ | ||
2154 | case ITYPE_TPD_COMPLETE: | ||
2155 | he_service_tbrq(he_dev, group); | ||
2156 | break; | ||
2157 | case ITYPE_RBPL_THRESH: | ||
2158 | he_service_rbpl(he_dev, group); | ||
2159 | break; | ||
2160 | case ITYPE_RBPS_THRESH: | ||
2161 | #ifdef USE_RBPS | ||
2162 | he_service_rbps(he_dev, group); | ||
2163 | #endif /* USE_RBPS */ | ||
2164 | break; | ||
2165 | case ITYPE_PHY: | ||
2166 | HPRINTK("phy interrupt\n"); | ||
2167 | #ifdef CONFIG_ATM_HE_USE_SUNI | ||
2168 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2169 | if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt) | ||
2170 | he_dev->atm_dev->phy->interrupt(he_dev->atm_dev); | ||
2171 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2172 | #endif | ||
2173 | break; | ||
2174 | case ITYPE_OTHER: | ||
2175 | switch (type|group) { | ||
2176 | case ITYPE_PARITY: | ||
2177 | hprintk("parity error\n"); | ||
2178 | break; | ||
2179 | case ITYPE_ABORT: | ||
2180 | hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR)); | ||
2181 | break; | ||
2182 | } | ||
2183 | break; | ||
2184 | case ITYPE_TYPE(ITYPE_INVALID): | ||
2185 | /* see 8.1.1 -- check all queues */ | ||
2186 | |||
2187 | HPRINTK("isw not updated 0x%x\n", he_dev->irq_head->isw); | ||
2188 | |||
2189 | he_service_rbrq(he_dev, 0); | ||
2190 | he_service_rbpl(he_dev, 0); | ||
2191 | #ifdef USE_RBPS | ||
2192 | he_service_rbps(he_dev, 0); | ||
2193 | #endif /* USE_RBPS */ | ||
2194 | he_service_tbrq(he_dev, 0); | ||
2195 | break; | ||
2196 | default: | ||
2197 | hprintk("bad isw 0x%x?\n", he_dev->irq_head->isw); | ||
2198 | } | ||
2199 | |||
2200 | he_dev->irq_head->isw = ITYPE_INVALID; | ||
2201 | |||
2202 | he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK); | ||
2203 | } | ||
2204 | |||
2205 | if (updated) { | ||
2206 | if (updated > he_dev->irq_peak) | ||
2207 | he_dev->irq_peak = updated; | ||
2208 | |||
2209 | he_writel(he_dev, | ||
2210 | IRQ_SIZE(CONFIG_IRQ_SIZE) | | ||
2211 | IRQ_THRESH(CONFIG_IRQ_THRESH) | | ||
2212 | IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD); | ||
2213 | (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata; flush posted writes */ | ||
2214 | } | ||
2215 | #ifdef USE_TASKLET | ||
2216 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2217 | #endif | ||
2218 | } | ||
2219 | |||
2220 | static irqreturn_t | ||
2221 | he_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
2222 | { | ||
2223 | unsigned long flags; | ||
2224 | struct he_dev *he_dev = (struct he_dev * )dev_id; | ||
2225 | int handled = 0; | ||
2226 | |||
2227 | if (he_dev == NULL) | ||
2228 | return IRQ_NONE; | ||
2229 | |||
2230 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2231 | |||
2232 | he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) | | ||
2233 | (*he_dev->irq_tailoffset << 2)); | ||
2234 | |||
2235 | if (he_dev->irq_tail == he_dev->irq_head) { | ||
2236 | HPRINTK("tailoffset not updated?\n"); | ||
2237 | he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base | | ||
2238 | ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2)); | ||
2239 | (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */ | ||
2240 | } | ||
2241 | |||
2242 | #ifdef DEBUG | ||
2243 | if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */) | ||
2244 | hprintk("spurious (or shared) interrupt?\n"); | ||
2245 | #endif | ||
2246 | |||
2247 | if (he_dev->irq_head != he_dev->irq_tail) { | ||
2248 | handled = 1; | ||
2249 | #ifdef USE_TASKLET | ||
2250 | tasklet_schedule(&he_dev->tasklet); | ||
2251 | #else | ||
2252 | he_tasklet((unsigned long) he_dev); | ||
2253 | #endif | ||
2254 | he_writel(he_dev, INT_CLEAR_A, INT_FIFO); /* clear interrupt */ | ||
2255 | (void) he_readl(he_dev, INT_FIFO); /* flush posted writes */ | ||
2256 | } | ||
2257 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2258 | return IRQ_RETVAL(handled); | ||
2259 | |||
2260 | } | ||
2261 | |||
2262 | static __inline__ void | ||
2263 | __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) | ||
2264 | { | ||
2265 | struct he_tpdrq *new_tail; | ||
2266 | |||
2267 | HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n", | ||
2268 | tpd, cid, he_dev->tpdrq_tail); | ||
2269 | |||
2270 | /* new_tail = he_dev->tpdrq_tail; */ | ||
2271 | new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base | | ||
2272 | TPDRQ_MASK(he_dev->tpdrq_tail+1)); | ||
2273 | |||
2274 | /* | ||
2275 | * check to see if we are about to set the tail == head | ||
2276 | * if true, update the head pointer from the adapter | ||
2277 | * to see if this is really the case (reading the queue | ||
2278 | * head for every enqueue would be unnecessarily slow) | ||
2279 | */ | ||
2280 | |||
2281 | if (new_tail == he_dev->tpdrq_head) { | ||
2282 | he_dev->tpdrq_head = (struct he_tpdrq *) | ||
2283 | (((unsigned long)he_dev->tpdrq_base) | | ||
2284 | TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H))); | ||
2285 | |||
2286 | if (new_tail == he_dev->tpdrq_head) { | ||
2287 | hprintk("tpdrq full (cid 0x%x)\n", cid); | ||
2288 | /* | ||
2289 | * FIXME | ||
2290 | * push tpd onto a transmit backlog queue | ||
2291 | * after service_tbrq, service the backlog | ||
2292 | * for now, we just drop the pdu | ||
2293 | */ | ||
2294 | if (tpd->skb) { | ||
2295 | if (tpd->vcc->pop) | ||
2296 | tpd->vcc->pop(tpd->vcc, tpd->skb); | ||
2297 | else | ||
2298 | dev_kfree_skb_any(tpd->skb); | ||
2299 | atomic_inc(&tpd->vcc->stats->tx_err); | ||
2300 | } | ||
2301 | #ifdef USE_TPD_POOL | ||
2302 | pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); | ||
2303 | #else | ||
2304 | tpd->inuse = 0; | ||
2305 | #endif | ||
2306 | return; | ||
2307 | } | ||
2308 | } | ||
2309 | |||
2310 | /* 2.1.5 transmit packet descriptor ready queue */ | ||
2311 | #ifdef USE_TPD_POOL | ||
2312 | list_add_tail(&tpd->entry, &he_dev->outstanding_tpds); | ||
2313 | he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status); | ||
2314 | #else | ||
2315 | he_dev->tpdrq_tail->tpd = he_dev->tpd_base_phys + | ||
2316 | (TPD_INDEX(tpd->status) * sizeof(struct he_tpd)); | ||
2317 | #endif | ||
2318 | he_dev->tpdrq_tail->cid = cid; | ||
2319 | wmb(); | ||
2320 | |||
2321 | he_dev->tpdrq_tail = new_tail; | ||
2322 | |||
2323 | he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T); | ||
2324 | (void) he_readl(he_dev, TPDRQ_T); /* flush posted writes */ | ||
2325 | } | ||
2326 | |||
2327 | static int | ||
2328 | he_open(struct atm_vcc *vcc) | ||
2329 | { | ||
2330 | unsigned long flags; | ||
2331 | struct he_dev *he_dev = HE_DEV(vcc->dev); | ||
2332 | struct he_vcc *he_vcc; | ||
2333 | int err = 0; | ||
2334 | unsigned cid, rsr0, rsr1, rsr4, tsr0, tsr0_aal, tsr4, period, reg, clock; | ||
2335 | short vpi = vcc->vpi; | ||
2336 | int vci = vcc->vci; | ||
2337 | |||
2338 | if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) | ||
2339 | return 0; | ||
2340 | |||
2341 | HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci); | ||
2342 | |||
2343 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
2344 | |||
2345 | cid = he_mkcid(he_dev, vpi, vci); | ||
2346 | |||
2347 | he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC); | ||
2348 | if (he_vcc == NULL) { | ||
2349 | hprintk("unable to allocate he_vcc during open\n"); | ||
2350 | return -ENOMEM; | ||
2351 | } | ||
2352 | |||
2353 | he_vcc->iov_tail = he_vcc->iov_head; | ||
2354 | he_vcc->pdu_len = 0; | ||
2355 | he_vcc->rc_index = -1; | ||
2356 | |||
2357 | init_waitqueue_head(&he_vcc->rx_waitq); | ||
2358 | init_waitqueue_head(&he_vcc->tx_waitq); | ||
2359 | |||
2360 | vcc->dev_data = he_vcc; | ||
2361 | |||
2362 | if (vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2363 | int pcr_goal; | ||
2364 | |||
2365 | pcr_goal = atm_pcr_goal(&vcc->qos.txtp); | ||
2366 | if (pcr_goal == 0) | ||
2367 | pcr_goal = he_dev->atm_dev->link_rate; | ||
2368 | if (pcr_goal < 0) /* means round down, technically */ | ||
2369 | pcr_goal = -pcr_goal; | ||
2370 | |||
2371 | HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal); | ||
2372 | |||
2373 | switch (vcc->qos.aal) { | ||
2374 | case ATM_AAL5: | ||
2375 | tsr0_aal = TSR0_AAL5; | ||
2376 | tsr4 = TSR4_AAL5; | ||
2377 | break; | ||
2378 | case ATM_AAL0: | ||
2379 | tsr0_aal = TSR0_AAL0_SDU; | ||
2380 | tsr4 = TSR4_AAL0_SDU; | ||
2381 | break; | ||
2382 | default: | ||
2383 | err = -EINVAL; | ||
2384 | goto open_failed; | ||
2385 | } | ||
2386 | |||
2387 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2388 | tsr0 = he_readl_tsr0(he_dev, cid); | ||
2389 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2390 | |||
2391 | if (TSR0_CONN_STATE(tsr0) != 0) { | ||
2392 | hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0); | ||
2393 | err = -EBUSY; | ||
2394 | goto open_failed; | ||
2395 | } | ||
2396 | |||
2397 | switch (vcc->qos.txtp.traffic_class) { | ||
2398 | case ATM_UBR: | ||
2399 | /* 2.3.3.1 open connection ubr */ | ||
2400 | |||
2401 | tsr0 = TSR0_UBR | TSR0_GROUP(0) | tsr0_aal | | ||
2402 | TSR0_USE_WMIN | TSR0_UPDATE_GER; | ||
2403 | break; | ||
2404 | |||
2405 | case ATM_CBR: | ||
2406 | /* 2.3.3.2 open connection cbr */ | ||
2407 | |||
2408 | /* 8.2.3 cbr scheduler wrap problem -- limit to 90% total link rate */ | ||
2409 | if ((he_dev->total_bw + pcr_goal) | ||
2410 | > (he_dev->atm_dev->link_rate * 9 / 10)) | ||
2411 | { | ||
2412 | err = -EBUSY; | ||
2413 | goto open_failed; | ||
2414 | } | ||
2415 | |||
2416 | spin_lock_irqsave(&he_dev->global_lock, flags); /* also protects he_dev->cs_stper[] */ | ||
2417 | |||
2418 | /* find an unused cs_stper register */ | ||
2419 | for (reg = 0; reg < HE_NUM_CS_STPER; ++reg) | ||
2420 | if (he_dev->cs_stper[reg].inuse == 0 || | ||
2421 | he_dev->cs_stper[reg].pcr == pcr_goal) | ||
2422 | break; | ||
2423 | |||
2424 | if (reg == HE_NUM_CS_STPER) { | ||
2425 | err = -EBUSY; | ||
2426 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2427 | goto open_failed; | ||
2428 | } | ||
2429 | |||
2430 | he_dev->total_bw += pcr_goal; | ||
2431 | |||
2432 | he_vcc->rc_index = reg; | ||
2433 | ++he_dev->cs_stper[reg].inuse; | ||
2434 | he_dev->cs_stper[reg].pcr = pcr_goal; | ||
2435 | |||
2436 | clock = he_is622(he_dev) ? 66667000 : 50000000; | ||
2437 | period = clock / pcr_goal; | ||
2438 | |||
2439 | HPRINTK("rc_index = %d period = %d\n", | ||
2440 | reg, period); | ||
2441 | |||
2442 | he_writel_mbox(he_dev, rate_to_atmf(period/2), | ||
2443 | CS_STPER0 + reg); | ||
2444 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2445 | |||
2446 | tsr0 = TSR0_CBR | TSR0_GROUP(0) | tsr0_aal | | ||
2447 | TSR0_RC_INDEX(reg); | ||
2448 | |||
2449 | break; | ||
2450 | default: | ||
2451 | err = -EINVAL; | ||
2452 | goto open_failed; | ||
2453 | } | ||
2454 | |||
2455 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2456 | |||
2457 | he_writel_tsr0(he_dev, tsr0, cid); | ||
2458 | he_writel_tsr4(he_dev, tsr4 | 1, cid); | ||
2459 | he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) | | ||
2460 | TSR1_PCR(rate_to_atmf(pcr_goal)), cid); | ||
2461 | he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid); | ||
2462 | he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid); | ||
2463 | |||
2464 | he_writel_tsr3(he_dev, 0x0, cid); | ||
2465 | he_writel_tsr5(he_dev, 0x0, cid); | ||
2466 | he_writel_tsr6(he_dev, 0x0, cid); | ||
2467 | he_writel_tsr7(he_dev, 0x0, cid); | ||
2468 | he_writel_tsr8(he_dev, 0x0, cid); | ||
2469 | he_writel_tsr10(he_dev, 0x0, cid); | ||
2470 | he_writel_tsr11(he_dev, 0x0, cid); | ||
2471 | he_writel_tsr12(he_dev, 0x0, cid); | ||
2472 | he_writel_tsr13(he_dev, 0x0, cid); | ||
2473 | he_writel_tsr14(he_dev, 0x0, cid); | ||
2474 | (void) he_readl_tsr0(he_dev, cid); /* flush posted writes */ | ||
2475 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2476 | } | ||
2477 | |||
2478 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2479 | unsigned aal; | ||
2480 | |||
2481 | HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid, | ||
2482 | &HE_VCC(vcc)->rx_waitq); | ||
2483 | |||
2484 | switch (vcc->qos.aal) { | ||
2485 | case ATM_AAL5: | ||
2486 | aal = RSR0_AAL5; | ||
2487 | break; | ||
2488 | case ATM_AAL0: | ||
2489 | aal = RSR0_RAWCELL; | ||
2490 | break; | ||
2491 | default: | ||
2492 | err = -EINVAL; | ||
2493 | goto open_failed; | ||
2494 | } | ||
2495 | |||
2496 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2497 | |||
2498 | rsr0 = he_readl_rsr0(he_dev, cid); | ||
2499 | if (rsr0 & RSR0_OPEN_CONN) { | ||
2500 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2501 | |||
2502 | hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0); | ||
2503 | err = -EBUSY; | ||
2504 | goto open_failed; | ||
2505 | } | ||
2506 | |||
2507 | #ifdef USE_RBPS | ||
2508 | rsr1 = RSR1_GROUP(0); | ||
2509 | rsr4 = RSR4_GROUP(0); | ||
2510 | #else /* !USE_RBPS */ | ||
2511 | rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY; | ||
2512 | rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY; | ||
2513 | #endif /* USE_RBPS */ | ||
2514 | rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? | ||
2515 | (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0; | ||
2516 | |||
2517 | #ifdef USE_CHECKSUM_HW | ||
2518 | if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) | ||
2519 | rsr0 |= RSR0_TCP_CKSUM; | ||
2520 | #endif | ||
2521 | |||
2522 | he_writel_rsr4(he_dev, rsr4, cid); | ||
2523 | he_writel_rsr1(he_dev, rsr1, cid); | ||
2524 | /* 5.1.11 last parameter initialized should be | ||
2525 | the open/closed indication in rsr0 */ | ||
2526 | he_writel_rsr0(he_dev, | ||
2527 | rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid); | ||
2528 | (void) he_readl_rsr0(he_dev, cid); /* flush posted writes */ | ||
2529 | |||
2530 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2531 | } | ||
2532 | |||
2533 | open_failed: | ||
2534 | |||
2535 | if (err) { | ||
2536 | if (he_vcc) | ||
2537 | kfree(he_vcc); | ||
2538 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
2539 | } | ||
2540 | else | ||
2541 | set_bit(ATM_VF_READY, &vcc->flags); | ||
2542 | |||
2543 | return err; | ||
2544 | } | ||
2545 | |||
2546 | static void | ||
2547 | he_close(struct atm_vcc *vcc) | ||
2548 | { | ||
2549 | unsigned long flags; | ||
2550 | DECLARE_WAITQUEUE(wait, current); | ||
2551 | struct he_dev *he_dev = HE_DEV(vcc->dev); | ||
2552 | struct he_tpd *tpd; | ||
2553 | unsigned cid; | ||
2554 | struct he_vcc *he_vcc = HE_VCC(vcc); | ||
2555 | #define MAX_RETRY 30 | ||
2556 | int retry = 0, sleep = 1, tx_inuse; | ||
2557 | |||
2558 | HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci); | ||
2559 | |||
2560 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
2561 | cid = he_mkcid(he_dev, vcc->vpi, vcc->vci); | ||
2562 | |||
2563 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2564 | int timeout; | ||
2565 | |||
2566 | HPRINTK("close rx cid 0x%x\n", cid); | ||
2567 | |||
2568 | /* 2.7.2.2 close receive operation */ | ||
2569 | |||
2570 | /* wait for previous close (if any) to finish */ | ||
2571 | |||
2572 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2573 | while (he_readl(he_dev, RCC_STAT) & RCC_BUSY) { | ||
2574 | HPRINTK("close cid 0x%x RCC_BUSY\n", cid); | ||
2575 | udelay(250); | ||
2576 | } | ||
2577 | |||
2578 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2579 | add_wait_queue(&he_vcc->rx_waitq, &wait); | ||
2580 | |||
2581 | he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid); | ||
2582 | (void) he_readl_rsr0(he_dev, cid); /* flush posted writes */ | ||
2583 | he_writel_mbox(he_dev, cid, RXCON_CLOSE); | ||
2584 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2585 | |||
2586 | timeout = schedule_timeout(30*HZ); | ||
2587 | |||
2588 | remove_wait_queue(&he_vcc->rx_waitq, &wait); | ||
2589 | set_current_state(TASK_RUNNING); | ||
2590 | |||
2591 | if (timeout == 0) | ||
2592 | hprintk("close rx timeout cid 0x%x\n", cid); | ||
2593 | |||
2594 | HPRINTK("close rx cid 0x%x complete\n", cid); | ||
2595 | |||
2596 | } | ||
2597 | |||
2598 | if (vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2599 | volatile unsigned tsr4, tsr0; | ||
2600 | int timeout; | ||
2601 | |||
2602 | HPRINTK("close tx cid 0x%x\n", cid); | ||
2603 | |||
2604 | /* 2.1.2 | ||
2605 | * | ||
2606 | * ... the host must first stop queueing packets to the TPDRQ | ||
2607 | * on the connection to be closed, then wait for all outstanding | ||
2608 | * packets to be transmitted and their buffers returned to the | ||
2609 | * TBRQ. When the last packet on the connection arrives in the | ||
2610 | * TBRQ, the host issues the close command to the adapter. | ||
2611 | */ | ||
2612 | |||
2613 | while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) && | ||
2614 | (retry < MAX_RETRY)) { | ||
2615 | msleep(sleep); | ||
2616 | if (sleep < 250) | ||
2617 | sleep = sleep * 2; | ||
2618 | |||
2619 | ++retry; | ||
2620 | } | ||
2621 | |||
2622 | if (tx_inuse) | ||
2623 | hprintk("close tx cid 0x%x tx_inuse = %d\n", cid, tx_inuse); | ||
2624 | |||
2625 | /* 2.3.1.1 generic close operations with flush */ | ||
2626 | |||
2627 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2628 | he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid); | ||
2629 | /* also clears TSR4_SESSION_ENDED */ | ||
2630 | |||
2631 | switch (vcc->qos.txtp.traffic_class) { | ||
2632 | case ATM_UBR: | ||
2633 | he_writel_tsr1(he_dev, | ||
2634 | TSR1_MCR(rate_to_atmf(200000)) | ||
2635 | | TSR1_PCR(0), cid); | ||
2636 | break; | ||
2637 | case ATM_CBR: | ||
2638 | he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid); | ||
2639 | break; | ||
2640 | } | ||
2641 | (void) he_readl_tsr4(he_dev, cid); /* flush posted writes */ | ||
2642 | |||
2643 | tpd = __alloc_tpd(he_dev); | ||
2644 | if (tpd == NULL) { | ||
2645 | hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid); | ||
2646 | goto close_tx_incomplete; | ||
2647 | } | ||
2648 | tpd->status |= TPD_EOS | TPD_INT; | ||
2649 | tpd->skb = NULL; | ||
2650 | tpd->vcc = vcc; | ||
2651 | wmb(); | ||
2652 | |||
2653 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2654 | add_wait_queue(&he_vcc->tx_waitq, &wait); | ||
2655 | __enqueue_tpd(he_dev, tpd, cid); | ||
2656 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2657 | |||
2658 | timeout = schedule_timeout(30*HZ); | ||
2659 | |||
2660 | remove_wait_queue(&he_vcc->tx_waitq, &wait); | ||
2661 | set_current_state(TASK_RUNNING); | ||
2662 | |||
2663 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2664 | |||
2665 | if (timeout == 0) { | ||
2666 | hprintk("close tx timeout cid 0x%x\n", cid); | ||
2667 | goto close_tx_incomplete; | ||
2668 | } | ||
2669 | |||
2670 | while (!((tsr4 = he_readl_tsr4(he_dev, cid)) & TSR4_SESSION_ENDED)) { | ||
2671 | HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4); | ||
2672 | udelay(250); | ||
2673 | } | ||
2674 | |||
2675 | while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0) { | ||
2676 | HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0); | ||
2677 | udelay(250); | ||
2678 | } | ||
2679 | |||
2680 | close_tx_incomplete: | ||
2681 | |||
2682 | if (vcc->qos.txtp.traffic_class == ATM_CBR) { | ||
2683 | int reg = he_vcc->rc_index; | ||
2684 | |||
2685 | HPRINTK("cs_stper reg = %d\n", reg); | ||
2686 | |||
2687 | if (he_dev->cs_stper[reg].inuse == 0) | ||
2688 | hprintk("cs_stper[%d].inuse = 0!\n", reg); | ||
2689 | else | ||
2690 | --he_dev->cs_stper[reg].inuse; | ||
2691 | |||
2692 | he_dev->total_bw -= he_dev->cs_stper[reg].pcr; | ||
2693 | } | ||
2694 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2695 | |||
2696 | HPRINTK("close tx cid 0x%x complete\n", cid); | ||
2697 | } | ||
2698 | |||
2699 | kfree(he_vcc); | ||
2700 | |||
2701 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
2702 | } | ||
2703 | |||
2704 | static int | ||
2705 | he_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
2706 | { | ||
2707 | unsigned long flags; | ||
2708 | struct he_dev *he_dev = HE_DEV(vcc->dev); | ||
2709 | unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci); | ||
2710 | struct he_tpd *tpd; | ||
2711 | #ifdef USE_SCATTERGATHER | ||
2712 | int i, slot = 0; | ||
2713 | #endif | ||
2714 | |||
2715 | #define HE_TPD_BUFSIZE 0xffff | ||
2716 | |||
2717 | HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci); | ||
2718 | |||
2719 | if ((skb->len > HE_TPD_BUFSIZE) || | ||
2720 | ((vcc->qos.aal == ATM_AAL0) && (skb->len != ATM_AAL0_SDU))) { | ||
2721 | hprintk("buffer too large (or small) -- %d bytes\n", skb->len ); | ||
2722 | if (vcc->pop) | ||
2723 | vcc->pop(vcc, skb); | ||
2724 | else | ||
2725 | dev_kfree_skb_any(skb); | ||
2726 | atomic_inc(&vcc->stats->tx_err); | ||
2727 | return -EINVAL; | ||
2728 | } | ||
2729 | |||
2730 | #ifndef USE_SCATTERGATHER | ||
2731 | if (skb_shinfo(skb)->nr_frags) { | ||
2732 | hprintk("no scatter/gather support\n"); | ||
2733 | if (vcc->pop) | ||
2734 | vcc->pop(vcc, skb); | ||
2735 | else | ||
2736 | dev_kfree_skb_any(skb); | ||
2737 | atomic_inc(&vcc->stats->tx_err); | ||
2738 | return -EINVAL; | ||
2739 | } | ||
2740 | #endif | ||
2741 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2742 | |||
2743 | tpd = __alloc_tpd(he_dev); | ||
2744 | if (tpd == NULL) { | ||
2745 | if (vcc->pop) | ||
2746 | vcc->pop(vcc, skb); | ||
2747 | else | ||
2748 | dev_kfree_skb_any(skb); | ||
2749 | atomic_inc(&vcc->stats->tx_err); | ||
2750 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2751 | return -ENOMEM; | ||
2752 | } | ||
2753 | |||
2754 | if (vcc->qos.aal == ATM_AAL5) | ||
2755 | tpd->status |= TPD_CELLTYPE(TPD_USERCELL); | ||
2756 | else { | ||
2757 | char *pti_clp = (void *) (skb->data + 3); | ||
2758 | int clp, pti; | ||
2759 | |||
2760 | pti = (*pti_clp & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; | ||
2761 | clp = (*pti_clp & ATM_HDR_CLP); | ||
2762 | tpd->status |= TPD_CELLTYPE(pti); | ||
2763 | if (clp) | ||
2764 | tpd->status |= TPD_CLP; | ||
2765 | |||
2766 | skb_pull(skb, ATM_AAL0_SDU - ATM_CELL_PAYLOAD); | ||
2767 | } | ||
2768 | |||
2769 | #ifdef USE_SCATTERGATHER | ||
2770 | tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data, | ||
2771 | skb->len - skb->data_len, PCI_DMA_TODEVICE); | ||
2772 | tpd->iovec[slot].len = skb->len - skb->data_len; | ||
2773 | ++slot; | ||
2774 | |||
2775 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
2776 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | ||
2777 | |||
2778 | if (slot == TPD_MAXIOV) { /* queue tpd; start new tpd */ | ||
2779 | tpd->vcc = vcc; | ||
2780 | tpd->skb = NULL; /* not the last fragment | ||
2781 | so dont ->push() yet */ | ||
2782 | wmb(); | ||
2783 | |||
2784 | __enqueue_tpd(he_dev, tpd, cid); | ||
2785 | tpd = __alloc_tpd(he_dev); | ||
2786 | if (tpd == NULL) { | ||
2787 | if (vcc->pop) | ||
2788 | vcc->pop(vcc, skb); | ||
2789 | else | ||
2790 | dev_kfree_skb_any(skb); | ||
2791 | atomic_inc(&vcc->stats->tx_err); | ||
2792 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2793 | return -ENOMEM; | ||
2794 | } | ||
2795 | tpd->status |= TPD_USERCELL; | ||
2796 | slot = 0; | ||
2797 | } | ||
2798 | |||
2799 | tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, | ||
2800 | (void *) page_address(frag->page) + frag->page_offset, | ||
2801 | frag->size, PCI_DMA_TODEVICE); | ||
2802 | tpd->iovec[slot].len = frag->size; | ||
2803 | ++slot; | ||
2804 | |||
2805 | } | ||
2806 | |||
2807 | tpd->iovec[slot - 1].len |= TPD_LST; | ||
2808 | #else | ||
2809 | tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); | ||
2810 | tpd->length0 = skb->len | TPD_LST; | ||
2811 | #endif | ||
2812 | tpd->status |= TPD_INT; | ||
2813 | |||
2814 | tpd->vcc = vcc; | ||
2815 | tpd->skb = skb; | ||
2816 | wmb(); | ||
2817 | ATM_SKB(skb)->vcc = vcc; | ||
2818 | |||
2819 | __enqueue_tpd(he_dev, tpd, cid); | ||
2820 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2821 | |||
2822 | atomic_inc(&vcc->stats->tx); | ||
2823 | |||
2824 | return 0; | ||
2825 | } | ||
2826 | |||
2827 | static int | ||
2828 | he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg) | ||
2829 | { | ||
2830 | unsigned long flags; | ||
2831 | struct he_dev *he_dev = HE_DEV(atm_dev); | ||
2832 | struct he_ioctl_reg reg; | ||
2833 | int err = 0; | ||
2834 | |||
2835 | switch (cmd) { | ||
2836 | case HE_GET_REG: | ||
2837 | if (!capable(CAP_NET_ADMIN)) | ||
2838 | return -EPERM; | ||
2839 | |||
2840 | if (copy_from_user(®, arg, | ||
2841 | sizeof(struct he_ioctl_reg))) | ||
2842 | return -EFAULT; | ||
2843 | |||
2844 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2845 | switch (reg.type) { | ||
2846 | case HE_REGTYPE_PCI: | ||
2847 | reg.val = he_readl(he_dev, reg.addr); | ||
2848 | break; | ||
2849 | case HE_REGTYPE_RCM: | ||
2850 | reg.val = | ||
2851 | he_readl_rcm(he_dev, reg.addr); | ||
2852 | break; | ||
2853 | case HE_REGTYPE_TCM: | ||
2854 | reg.val = | ||
2855 | he_readl_tcm(he_dev, reg.addr); | ||
2856 | break; | ||
2857 | case HE_REGTYPE_MBOX: | ||
2858 | reg.val = | ||
2859 | he_readl_mbox(he_dev, reg.addr); | ||
2860 | break; | ||
2861 | default: | ||
2862 | err = -EINVAL; | ||
2863 | break; | ||
2864 | } | ||
2865 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2866 | if (err == 0) | ||
2867 | if (copy_to_user(arg, ®, | ||
2868 | sizeof(struct he_ioctl_reg))) | ||
2869 | return -EFAULT; | ||
2870 | break; | ||
2871 | default: | ||
2872 | #ifdef CONFIG_ATM_HE_USE_SUNI | ||
2873 | if (atm_dev->phy && atm_dev->phy->ioctl) | ||
2874 | err = atm_dev->phy->ioctl(atm_dev, cmd, arg); | ||
2875 | #else /* CONFIG_ATM_HE_USE_SUNI */ | ||
2876 | err = -EINVAL; | ||
2877 | #endif /* CONFIG_ATM_HE_USE_SUNI */ | ||
2878 | break; | ||
2879 | } | ||
2880 | |||
2881 | return err; | ||
2882 | } | ||
2883 | |||
2884 | static void | ||
2885 | he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr) | ||
2886 | { | ||
2887 | unsigned long flags; | ||
2888 | struct he_dev *he_dev = HE_DEV(atm_dev); | ||
2889 | |||
2890 | HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr); | ||
2891 | |||
2892 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2893 | he_writel(he_dev, val, FRAMER + (addr*4)); | ||
2894 | (void) he_readl(he_dev, FRAMER + (addr*4)); /* flush posted writes */ | ||
2895 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2896 | } | ||
2897 | |||
2898 | |||
2899 | static unsigned char | ||
2900 | he_phy_get(struct atm_dev *atm_dev, unsigned long addr) | ||
2901 | { | ||
2902 | unsigned long flags; | ||
2903 | struct he_dev *he_dev = HE_DEV(atm_dev); | ||
2904 | unsigned reg; | ||
2905 | |||
2906 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2907 | reg = he_readl(he_dev, FRAMER + (addr*4)); | ||
2908 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2909 | |||
2910 | HPRINTK("phy_get(addr 0x%lx) =0x%x\n", addr, reg); | ||
2911 | return reg; | ||
2912 | } | ||
2913 | |||
2914 | static int | ||
2915 | he_proc_read(struct atm_dev *dev, loff_t *pos, char *page) | ||
2916 | { | ||
2917 | unsigned long flags; | ||
2918 | struct he_dev *he_dev = HE_DEV(dev); | ||
2919 | int left, i; | ||
2920 | #ifdef notdef | ||
2921 | struct he_rbrq *rbrq_tail; | ||
2922 | struct he_tpdrq *tpdrq_head; | ||
2923 | int rbpl_head, rbpl_tail; | ||
2924 | #endif | ||
2925 | static long mcc = 0, oec = 0, dcc = 0, cec = 0; | ||
2926 | |||
2927 | |||
2928 | left = *pos; | ||
2929 | if (!left--) | ||
2930 | return sprintf(page, "%s\n", version); | ||
2931 | |||
2932 | if (!left--) | ||
2933 | return sprintf(page, "%s%s\n\n", | ||
2934 | he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM"); | ||
2935 | |||
2936 | if (!left--) | ||
2937 | return sprintf(page, "Mismatched Cells VPI/VCI Not Open Dropped Cells RCM Dropped Cells\n"); | ||
2938 | |||
2939 | spin_lock_irqsave(&he_dev->global_lock, flags); | ||
2940 | mcc += he_readl(he_dev, MCC); | ||
2941 | oec += he_readl(he_dev, OEC); | ||
2942 | dcc += he_readl(he_dev, DCC); | ||
2943 | cec += he_readl(he_dev, CEC); | ||
2944 | spin_unlock_irqrestore(&he_dev->global_lock, flags); | ||
2945 | |||
2946 | if (!left--) | ||
2947 | return sprintf(page, "%16ld %16ld %13ld %17ld\n\n", | ||
2948 | mcc, oec, dcc, cec); | ||
2949 | |||
2950 | if (!left--) | ||
2951 | return sprintf(page, "irq_size = %d inuse = ? peak = %d\n", | ||
2952 | CONFIG_IRQ_SIZE, he_dev->irq_peak); | ||
2953 | |||
2954 | if (!left--) | ||
2955 | return sprintf(page, "tpdrq_size = %d inuse = ?\n", | ||
2956 | CONFIG_TPDRQ_SIZE); | ||
2957 | |||
2958 | if (!left--) | ||
2959 | return sprintf(page, "rbrq_size = %d inuse = ? peak = %d\n", | ||
2960 | CONFIG_RBRQ_SIZE, he_dev->rbrq_peak); | ||
2961 | |||
2962 | if (!left--) | ||
2963 | return sprintf(page, "tbrq_size = %d peak = %d\n", | ||
2964 | CONFIG_TBRQ_SIZE, he_dev->tbrq_peak); | ||
2965 | |||
2966 | |||
2967 | #ifdef notdef | ||
2968 | rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S)); | ||
2969 | rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T)); | ||
2970 | |||
2971 | inuse = rbpl_head - rbpl_tail; | ||
2972 | if (inuse < 0) | ||
2973 | inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp); | ||
2974 | inuse /= sizeof(struct he_rbp); | ||
2975 | |||
2976 | if (!left--) | ||
2977 | return sprintf(page, "rbpl_size = %d inuse = %d\n\n", | ||
2978 | CONFIG_RBPL_SIZE, inuse); | ||
2979 | #endif | ||
2980 | |||
2981 | if (!left--) | ||
2982 | return sprintf(page, "rate controller periods (cbr)\n pcr #vc\n"); | ||
2983 | |||
2984 | for (i = 0; i < HE_NUM_CS_STPER; ++i) | ||
2985 | if (!left--) | ||
2986 | return sprintf(page, "cs_stper%-2d %8ld %3d\n", i, | ||
2987 | he_dev->cs_stper[i].pcr, | ||
2988 | he_dev->cs_stper[i].inuse); | ||
2989 | |||
2990 | if (!left--) | ||
2991 | return sprintf(page, "total bw (cbr): %d (limit %d)\n", | ||
2992 | he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9); | ||
2993 | |||
2994 | return 0; | ||
2995 | } | ||
2996 | |||
2997 | /* eeprom routines -- see 4.7 */ | ||
2998 | |||
2999 | u8 | ||
3000 | read_prom_byte(struct he_dev *he_dev, int addr) | ||
3001 | { | ||
3002 | u32 val = 0, tmp_read = 0; | ||
3003 | int i, j = 0; | ||
3004 | u8 byte_read = 0; | ||
3005 | |||
3006 | val = readl(he_dev->membase + HOST_CNTL); | ||
3007 | val &= 0xFFFFE0FF; | ||
3008 | |||
3009 | /* Turn on write enable */ | ||
3010 | val |= 0x800; | ||
3011 | he_writel(he_dev, val, HOST_CNTL); | ||
3012 | |||
3013 | /* Send READ instruction */ | ||
3014 | for (i = 0; i < sizeof(readtab)/sizeof(readtab[0]); i++) { | ||
3015 | he_writel(he_dev, val | readtab[i], HOST_CNTL); | ||
3016 | udelay(EEPROM_DELAY); | ||
3017 | } | ||
3018 | |||
3019 | /* Next, we need to send the byte address to read from */ | ||
3020 | for (i = 7; i >= 0; i--) { | ||
3021 | he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL); | ||
3022 | udelay(EEPROM_DELAY); | ||
3023 | he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL); | ||
3024 | udelay(EEPROM_DELAY); | ||
3025 | } | ||
3026 | |||
3027 | j = 0; | ||
3028 | |||
3029 | val &= 0xFFFFF7FF; /* Turn off write enable */ | ||
3030 | he_writel(he_dev, val, HOST_CNTL); | ||
3031 | |||
3032 | /* Now, we can read data from the EEPROM by clocking it in */ | ||
3033 | for (i = 7; i >= 0; i--) { | ||
3034 | he_writel(he_dev, val | clocktab[j++], HOST_CNTL); | ||
3035 | udelay(EEPROM_DELAY); | ||
3036 | tmp_read = he_readl(he_dev, HOST_CNTL); | ||
3037 | byte_read |= (unsigned char) | ||
3038 | ((tmp_read & ID_DOUT) >> ID_DOFFSET << i); | ||
3039 | he_writel(he_dev, val | clocktab[j++], HOST_CNTL); | ||
3040 | udelay(EEPROM_DELAY); | ||
3041 | } | ||
3042 | |||
3043 | he_writel(he_dev, val | ID_CS, HOST_CNTL); | ||
3044 | udelay(EEPROM_DELAY); | ||
3045 | |||
3046 | return byte_read; | ||
3047 | } | ||
3048 | |||
3049 | MODULE_LICENSE("GPL"); | ||
3050 | MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>"); | ||
3051 | MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver"); | ||
3052 | module_param(disable64, bool, 0); | ||
3053 | MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers"); | ||
3054 | module_param(nvpibits, short, 0); | ||
3055 | MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)"); | ||
3056 | module_param(nvcibits, short, 0); | ||
3057 | MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)"); | ||
3058 | module_param(rx_skb_reserve, short, 0); | ||
3059 | MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)"); | ||
3060 | module_param(irq_coalesce, bool, 0); | ||
3061 | MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)"); | ||
3062 | module_param(sdh, bool, 0); | ||
3063 | MODULE_PARM_DESC(sdh, "use SDH framing (default 0)"); | ||
3064 | |||
3065 | static struct pci_device_id he_pci_tbl[] = { | ||
3066 | { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID, | ||
3067 | 0, 0, 0 }, | ||
3068 | { 0, } | ||
3069 | }; | ||
3070 | |||
3071 | MODULE_DEVICE_TABLE(pci, he_pci_tbl); | ||
3072 | |||
3073 | static struct pci_driver he_driver = { | ||
3074 | .name = "he", | ||
3075 | .probe = he_init_one, | ||
3076 | .remove = __devexit_p(he_remove_one), | ||
3077 | .id_table = he_pci_tbl, | ||
3078 | }; | ||
3079 | |||
3080 | static int __init he_init(void) | ||
3081 | { | ||
3082 | return pci_register_driver(&he_driver); | ||
3083 | } | ||
3084 | |||
3085 | static void __exit he_cleanup(void) | ||
3086 | { | ||
3087 | pci_unregister_driver(&he_driver); | ||
3088 | } | ||
3089 | |||
3090 | module_init(he_init); | ||
3091 | module_exit(he_cleanup); | ||
diff --git a/drivers/atm/he.h b/drivers/atm/he.h new file mode 100644 index 000000000000..1a903859343a --- /dev/null +++ b/drivers/atm/he.h | |||
@@ -0,0 +1,895 @@ | |||
1 | /* $Id: he.h,v 1.4 2003/05/06 22:48:00 chas Exp $ */ | ||
2 | |||
3 | /* | ||
4 | |||
5 | he.h | ||
6 | |||
7 | ForeRunnerHE ATM Adapter driver for ATM on Linux | ||
8 | Copyright (C) 1999-2001 Naval Research Laboratory | ||
9 | |||
10 | This library is free software; you can redistribute it and/or | ||
11 | modify it under the terms of the GNU Lesser General Public | ||
12 | License as published by the Free Software Foundation; either | ||
13 | version 2.1 of the License, or (at your option) any later version. | ||
14 | |||
15 | This library is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | Lesser General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU Lesser General Public | ||
21 | License along with this library; if not, write to the Free Software | ||
22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | |||
24 | */ | ||
25 | |||
26 | /* | ||
27 | |||
28 | he.h | ||
29 | |||
30 | ForeRunnerHE ATM Adapter driver for ATM on Linux | ||
31 | Copyright (C) 1999-2000 Naval Research Laboratory | ||
32 | |||
33 | Permission to use, copy, modify and distribute this software and its | ||
34 | documentation is hereby granted, provided that both the copyright | ||
35 | notice and this permission notice appear in all copies of the software, | ||
36 | derivative works or modified versions, and any portions thereof, and | ||
37 | that both notices appear in supporting documentation. | ||
38 | |||
39 | NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND | ||
40 | DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER | ||
41 | RESULTING FROM THE USE OF THIS SOFTWARE. | ||
42 | |||
43 | */ | ||
44 | |||
45 | #ifndef _HE_H_ | ||
46 | #define _HE_H_ | ||
47 | |||
48 | #define DEV_LABEL "he" | ||
49 | |||
50 | #define CONFIG_DEFAULT_VCIBITS 12 | ||
51 | #define CONFIG_DEFAULT_VPIBITS 0 | ||
52 | |||
53 | #define CONFIG_IRQ_SIZE 128 | ||
54 | #define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2) | ||
55 | |||
56 | #define CONFIG_NUMTPDS 256 | ||
57 | |||
58 | #define CONFIG_TPDRQ_SIZE 512 | ||
59 | #define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1)) | ||
60 | |||
61 | #define CONFIG_RBRQ_SIZE 512 | ||
62 | #define CONFIG_RBRQ_THRESH 400 | ||
63 | #define RBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1)) | ||
64 | |||
65 | #define CONFIG_TBRQ_SIZE 512 | ||
66 | #define CONFIG_TBRQ_THRESH 400 | ||
67 | #define TBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1)) | ||
68 | |||
69 | #define CONFIG_RBPL_SIZE 512 | ||
70 | #define CONFIG_RBPL_THRESH 64 | ||
71 | #define CONFIG_RBPL_BUFSIZE 4096 | ||
72 | #define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1)) | ||
73 | |||
74 | #define CONFIG_RBPS_SIZE 1024 | ||
75 | #define CONFIG_RBPS_THRESH 64 | ||
76 | #define CONFIG_RBPS_BUFSIZE 128 | ||
77 | #define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1)) | ||
78 | |||
79 | /* 5.1.3 initialize connection memory */ | ||
80 | |||
81 | #define CONFIG_RSRA 0x00000 | ||
82 | #define CONFIG_RCMLBM 0x08000 | ||
83 | #define CONFIG_RCMABR 0x0d800 | ||
84 | #define CONFIG_RSRB 0x0e000 | ||
85 | |||
86 | #define CONFIG_TSRA 0x00000 | ||
87 | #define CONFIG_TSRB 0x08000 | ||
88 | #define CONFIG_TSRC 0x0c000 | ||
89 | #define CONFIG_TSRD 0x0e000 | ||
90 | #define CONFIG_TMABR 0x0f000 | ||
91 | #define CONFIG_TPDBA 0x10000 | ||
92 | |||
93 | #define HE_MAXCIDBITS 12 | ||
94 | |||
95 | /* 2.9.3.3 interrupt encodings */ | ||
96 | |||
97 | struct he_irq { | ||
98 | volatile u32 isw; | ||
99 | }; | ||
100 | |||
101 | #define IRQ_ALIGNMENT 0x1000 | ||
102 | |||
103 | #define NEXT_ENTRY(base, tail, mask) \ | ||
104 | (((unsigned long)base)|(((unsigned long)(tail+1))&mask)) | ||
105 | |||
106 | #define ITYPE_INVALID 0xffffffff | ||
107 | #define ITYPE_TBRQ_THRESH (0<<3) | ||
108 | #define ITYPE_TPD_COMPLETE (1<<3) | ||
109 | #define ITYPE_RBPS_THRESH (2<<3) | ||
110 | #define ITYPE_RBPL_THRESH (3<<3) | ||
111 | #define ITYPE_RBRQ_THRESH (4<<3) | ||
112 | #define ITYPE_RBRQ_TIMER (5<<3) | ||
113 | #define ITYPE_PHY (6<<3) | ||
114 | #define ITYPE_OTHER 0x80 | ||
115 | #define ITYPE_PARITY 0x81 | ||
116 | #define ITYPE_ABORT 0x82 | ||
117 | |||
118 | #define ITYPE_GROUP(x) (x & 0x7) | ||
119 | #define ITYPE_TYPE(x) (x & 0xf8) | ||
120 | |||
121 | #define HE_NUM_GROUPS 8 | ||
122 | |||
123 | /* 2.1.4 transmit packet descriptor */ | ||
124 | |||
125 | struct he_tpd { | ||
126 | |||
127 | /* read by the adapter */ | ||
128 | |||
129 | volatile u32 status; | ||
130 | volatile u32 reserved; | ||
131 | |||
132 | #define TPD_MAXIOV 3 | ||
133 | struct { | ||
134 | u32 addr, len; | ||
135 | } iovec[TPD_MAXIOV]; | ||
136 | |||
137 | #define address0 iovec[0].addr | ||
138 | #define length0 iovec[0].len | ||
139 | |||
140 | /* linux-atm extensions */ | ||
141 | |||
142 | struct sk_buff *skb; | ||
143 | struct atm_vcc *vcc; | ||
144 | |||
145 | #ifdef USE_TPD_POOL | ||
146 | struct list_head entry; | ||
147 | #else | ||
148 | u32 inuse; | ||
149 | char padding[32 - sizeof(u32) - (2*sizeof(void*))]; | ||
150 | #endif | ||
151 | }; | ||
152 | |||
153 | #define TPD_ALIGNMENT 64 | ||
154 | #define TPD_LEN_MASK 0xffff | ||
155 | |||
156 | #define TPD_ADDR_SHIFT 6 | ||
157 | #define TPD_MASK 0xffffffc0 | ||
158 | #define TPD_ADDR(x) ((x) & TPD_MASK) | ||
159 | #define TPD_INDEX(x) (TPD_ADDR(x) >> TPD_ADDR_SHIFT) | ||
160 | |||
161 | |||
162 | /* table 2.3 transmit buffer return elements */ | ||
163 | |||
164 | struct he_tbrq { | ||
165 | volatile u32 tbre; | ||
166 | }; | ||
167 | |||
168 | #define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE | ||
169 | |||
170 | #define TBRQ_TPD(tbrq) ((tbrq)->tbre & 0xffffffc0) | ||
171 | #define TBRQ_EOS(tbrq) ((tbrq)->tbre & (1<<3)) | ||
172 | #define TBRQ_MULTIPLE(tbrq) ((tbrq)->tbre & (1)) | ||
173 | |||
174 | /* table 2.21 receive buffer return queue element field organization */ | ||
175 | |||
176 | struct he_rbrq { | ||
177 | volatile u32 addr; | ||
178 | volatile u32 cidlen; | ||
179 | }; | ||
180 | |||
181 | #define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE | ||
182 | |||
183 | #define RBRQ_ADDR(rbrq) ((rbrq)->addr & 0xffffffc0) | ||
184 | #define RBRQ_CRC_ERR(rbrq) ((rbrq)->addr & (1<<5)) | ||
185 | #define RBRQ_LEN_ERR(rbrq) ((rbrq)->addr & (1<<4)) | ||
186 | #define RBRQ_END_PDU(rbrq) ((rbrq)->addr & (1<<3)) | ||
187 | #define RBRQ_AAL5_PROT(rbrq) ((rbrq)->addr & (1<<2)) | ||
188 | #define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1)) | ||
189 | #define RBRQ_HBUF_ERR(rbrq) ((rbrq)->addr & 1) | ||
190 | #define RBRQ_CID(rbrq) (((rbrq)->cidlen >> 16) & 0x1fff) | ||
191 | #define RBRQ_BUFLEN(rbrq) ((rbrq)->cidlen & 0xffff) | ||
192 | |||
193 | /* figure 2.3 transmit packet descriptor ready queue */ | ||
194 | |||
195 | struct he_tpdrq { | ||
196 | volatile u32 tpd; | ||
197 | volatile u32 cid; | ||
198 | }; | ||
199 | |||
200 | #define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE | ||
201 | |||
202 | /* table 2.30 host status page detail */ | ||
203 | |||
204 | #define HSP_ALIGNMENT 0x400 /* must align on 1k boundary */ | ||
205 | |||
206 | struct he_hsp { | ||
207 | struct he_hsp_entry { | ||
208 | volatile u32 tbrq_tail; | ||
209 | volatile u32 reserved1[15]; | ||
210 | volatile u32 rbrq_tail; | ||
211 | volatile u32 reserved2[15]; | ||
212 | } group[HE_NUM_GROUPS]; | ||
213 | }; | ||
214 | |||
215 | /* figure 2.9 receive buffer pools */ | ||
216 | |||
217 | struct he_rbp { | ||
218 | volatile u32 phys; | ||
219 | volatile u32 status; | ||
220 | }; | ||
221 | |||
222 | /* NOTE: it is suggested that virt be the virtual address of the host | ||
223 | buffer. on a 64-bit machine, this would not work. Instead, we | ||
224 | store the real virtual address in another list, and store an index | ||
225 | (and buffer status) in the virt member. | ||
226 | */ | ||
227 | |||
228 | #define RBP_INDEX_OFF 6 | ||
229 | #define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff) | ||
230 | #define RBP_LOANED 0x80000000 | ||
231 | #define RBP_SMALLBUF 0x40000000 | ||
232 | |||
233 | struct he_virt { | ||
234 | void *virt; | ||
235 | }; | ||
236 | |||
237 | #define RBPL_ALIGNMENT CONFIG_RBPL_SIZE | ||
238 | #define RBPS_ALIGNMENT CONFIG_RBPS_SIZE | ||
239 | |||
240 | #ifdef notyet | ||
241 | struct he_group { | ||
242 | u32 rpbs_size, rpbs_qsize; | ||
243 | struct he_rbp rbps_ba; | ||
244 | |||
245 | u32 rpbl_size, rpbl_qsize; | ||
246 | struct he_rpb_entry *rbpl_ba; | ||
247 | }; | ||
248 | #endif | ||
249 | |||
250 | #define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc) | ||
251 | |||
252 | struct he_vcc_table | ||
253 | { | ||
254 | struct atm_vcc *vcc; | ||
255 | }; | ||
256 | |||
257 | struct he_cs_stper | ||
258 | { | ||
259 | long pcr; | ||
260 | int inuse; | ||
261 | }; | ||
262 | |||
263 | #define HE_NUM_CS_STPER 16 | ||
264 | |||
265 | struct he_dev { | ||
266 | unsigned int number; | ||
267 | unsigned int irq; | ||
268 | void __iomem *membase; | ||
269 | |||
270 | char prod_id[30]; | ||
271 | char mac_addr[6]; | ||
272 | int media; /* | ||
273 | * 0x26 = HE155 MM | ||
274 | * 0x27 = HE622 MM | ||
275 | * 0x46 = HE155 SM | ||
276 | * 0x47 = HE622 SM | ||
277 | */ | ||
278 | |||
279 | |||
280 | unsigned int vcibits, vpibits; | ||
281 | unsigned int cells_per_row; | ||
282 | unsigned int bytes_per_row; | ||
283 | unsigned int cells_per_lbuf; | ||
284 | unsigned int r0_numrows, r0_startrow, r0_numbuffs; | ||
285 | unsigned int r1_numrows, r1_startrow, r1_numbuffs; | ||
286 | unsigned int tx_numrows, tx_startrow, tx_numbuffs; | ||
287 | unsigned int buffer_limit; | ||
288 | |||
289 | struct he_vcc_table *he_vcc_table; | ||
290 | |||
291 | #ifdef notyet | ||
292 | struct he_group group[HE_NUM_GROUPS]; | ||
293 | #endif | ||
294 | struct he_cs_stper cs_stper[HE_NUM_CS_STPER]; | ||
295 | unsigned total_bw; | ||
296 | |||
297 | dma_addr_t irq_phys; | ||
298 | struct he_irq *irq_base, *irq_head, *irq_tail; | ||
299 | volatile unsigned *irq_tailoffset; | ||
300 | int irq_peak; | ||
301 | |||
302 | #ifdef USE_TASKLET | ||
303 | struct tasklet_struct tasklet; | ||
304 | #endif | ||
305 | #ifdef USE_TPD_POOL | ||
306 | struct pci_pool *tpd_pool; | ||
307 | struct list_head outstanding_tpds; | ||
308 | #else | ||
309 | struct he_tpd *tpd_head, *tpd_base, *tpd_end; | ||
310 | dma_addr_t tpd_base_phys; | ||
311 | #endif | ||
312 | |||
313 | dma_addr_t tpdrq_phys; | ||
314 | struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head; | ||
315 | |||
316 | spinlock_t global_lock; /* 8.1.5 pci transaction ordering | ||
317 | error problem */ | ||
318 | dma_addr_t rbrq_phys; | ||
319 | struct he_rbrq *rbrq_base, *rbrq_head; | ||
320 | int rbrq_peak; | ||
321 | |||
322 | #ifdef USE_RBPL_POOL | ||
323 | struct pci_pool *rbpl_pool; | ||
324 | #else | ||
325 | void *rbpl_pages; | ||
326 | dma_addr_t rbpl_pages_phys; | ||
327 | #endif | ||
328 | dma_addr_t rbpl_phys; | ||
329 | struct he_rbp *rbpl_base, *rbpl_tail; | ||
330 | struct he_virt *rbpl_virt; | ||
331 | int rbpl_peak; | ||
332 | |||
333 | #ifdef USE_RBPS | ||
334 | #ifdef USE_RBPS_POOL | ||
335 | struct pci_pool *rbps_pool; | ||
336 | #else | ||
337 | void *rbps_pages; | ||
338 | dma_addr_t rbps_pages_phys; | ||
339 | #endif | ||
340 | #endif | ||
341 | dma_addr_t rbps_phys; | ||
342 | struct he_rbp *rbps_base, *rbps_tail; | ||
343 | struct he_virt *rbps_virt; | ||
344 | int rbps_peak; | ||
345 | |||
346 | dma_addr_t tbrq_phys; | ||
347 | struct he_tbrq *tbrq_base, *tbrq_head; | ||
348 | int tbrq_peak; | ||
349 | |||
350 | dma_addr_t hsp_phys; | ||
351 | struct he_hsp *hsp; | ||
352 | |||
353 | struct pci_dev *pci_dev; | ||
354 | struct atm_dev *atm_dev; | ||
355 | struct he_dev *next; | ||
356 | }; | ||
357 | |||
358 | struct he_iovec | ||
359 | { | ||
360 | u32 iov_base; | ||
361 | u32 iov_len; | ||
362 | }; | ||
363 | |||
364 | #define HE_MAXIOV 20 | ||
365 | |||
366 | struct he_vcc | ||
367 | { | ||
368 | struct he_iovec iov_head[HE_MAXIOV]; | ||
369 | struct he_iovec *iov_tail; | ||
370 | int pdu_len; | ||
371 | |||
372 | int rc_index; | ||
373 | |||
374 | wait_queue_head_t rx_waitq; | ||
375 | wait_queue_head_t tx_waitq; | ||
376 | }; | ||
377 | |||
378 | #define HE_VCC(vcc) ((struct he_vcc *)(vcc->dev_data)) | ||
379 | |||
380 | #define PCI_VENDOR_ID_FORE 0x1127 | ||
381 | #define PCI_DEVICE_ID_FORE_HE 0x400 | ||
382 | |||
383 | #define HE_DMA_MASK 0xffffffff | ||
384 | |||
385 | #define GEN_CNTL_0 0x40 | ||
386 | #define INT_PROC_ENBL (1<<25) | ||
387 | #define SLAVE_ENDIAN_MODE (1<<16) | ||
388 | #define MRL_ENB (1<<5) | ||
389 | #define MRM_ENB (1<<4) | ||
390 | #define INIT_ENB (1<<2) | ||
391 | #define IGNORE_TIMEOUT (1<<1) | ||
392 | #define ENBL_64 (1<<0) | ||
393 | |||
394 | #define MIN_PCI_LATENCY 32 /* errata 8.1.3 */ | ||
395 | |||
396 | #define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data) | ||
397 | |||
398 | #define he_is622(dev) ((dev)->media & 0x1) | ||
399 | |||
400 | #define HE_REGMAP_SIZE 0x100000 | ||
401 | |||
402 | #define RESET_CNTL 0x80000 | ||
403 | #define BOARD_RST_STATUS (1<<6) | ||
404 | |||
405 | #define HOST_CNTL 0x80004 | ||
406 | #define PCI_BUS_SIZE64 (1<<27) | ||
407 | #define DESC_RD_STATIC_64 (1<<26) | ||
408 | #define DATA_RD_STATIC_64 (1<<25) | ||
409 | #define DATA_WR_STATIC_64 (1<<24) | ||
410 | #define ID_CS (1<<12) | ||
411 | #define ID_WREN (1<<11) | ||
412 | #define ID_DOUT (1<<10) | ||
413 | #define ID_DOFFSET 10 | ||
414 | #define ID_DIN (1<<9) | ||
415 | #define ID_CLOCK (1<<8) | ||
416 | #define QUICK_RD_RETRY (1<<7) | ||
417 | #define QUICK_WR_RETRY (1<<6) | ||
418 | #define OUTFF_ENB (1<<5) | ||
419 | #define CMDFF_ENB (1<<4) | ||
420 | #define PERR_INT_ENB (1<<2) | ||
421 | #define IGNORE_INTR (1<<0) | ||
422 | |||
423 | #define LB_SWAP 0x80008 | ||
424 | #define SWAP_RNUM_MAX(x) (x<<27) | ||
425 | #define DATA_WR_SWAP (1<<20) | ||
426 | #define DESC_RD_SWAP (1<<19) | ||
427 | #define DATA_RD_SWAP (1<<18) | ||
428 | #define INTR_SWAP (1<<17) | ||
429 | #define DESC_WR_SWAP (1<<16) | ||
430 | #define SDRAM_INIT (1<<15) | ||
431 | #define BIG_ENDIAN_HOST (1<<14) | ||
432 | #define XFER_SIZE (1<<7) | ||
433 | |||
434 | #define LB_MEM_ADDR 0x8000c | ||
435 | #define LB_MEM_DATA 0x80010 | ||
436 | |||
437 | #define LB_MEM_ACCESS 0x80014 | ||
438 | #define LB_MEM_HNDSHK (1<<30) | ||
439 | #define LM_MEM_WRITE (0x7) | ||
440 | #define LM_MEM_READ (0x3) | ||
441 | |||
442 | #define SDRAM_CTL 0x80018 | ||
443 | #define LB_64_ENB (1<<3) | ||
444 | #define LB_TWR (1<<2) | ||
445 | #define LB_TRP (1<<1) | ||
446 | #define LB_TRAS (1<<0) | ||
447 | |||
448 | #define INT_FIFO 0x8001c | ||
449 | #define INT_MASK_D (1<<15) | ||
450 | #define INT_MASK_C (1<<14) | ||
451 | #define INT_MASK_B (1<<13) | ||
452 | #define INT_MASK_A (1<<12) | ||
453 | #define INT_CLEAR_D (1<<11) | ||
454 | #define INT_CLEAR_C (1<<10) | ||
455 | #define INT_CLEAR_B (1<<9) | ||
456 | #define INT_CLEAR_A (1<<8) | ||
457 | |||
458 | #define ABORT_ADDR 0x80020 | ||
459 | |||
460 | #define IRQ0_BASE 0x80080 | ||
461 | #define IRQ_BASE(x) (x<<12) | ||
462 | #define IRQ_MASK ((CONFIG_IRQ_SIZE<<2)-1) /* was 0x3ff */ | ||
463 | #define IRQ_TAIL(x) (((unsigned long)(x)) & IRQ_MASK) | ||
464 | #define IRQ0_HEAD 0x80084 | ||
465 | #define IRQ_SIZE(x) (x<<22) | ||
466 | #define IRQ_THRESH(x) (x<<12) | ||
467 | #define IRQ_HEAD(x) (x<<2) | ||
468 | /* #define IRQ_PENDING (1) conflict with linux/irq.h */ | ||
469 | #define IRQ0_CNTL 0x80088 | ||
470 | #define IRQ_ADDRSEL(x) (x<<2) | ||
471 | #define IRQ_INT_A (0<<2) | ||
472 | #define IRQ_INT_B (1<<2) | ||
473 | #define IRQ_INT_C (2<<2) | ||
474 | #define IRQ_INT_D (3<<2) | ||
475 | #define IRQ_TYPE_ADDR 0x1 | ||
476 | #define IRQ_TYPE_LINE 0x0 | ||
477 | #define IRQ0_DATA 0x8008c | ||
478 | |||
479 | #define IRQ1_BASE 0x80090 | ||
480 | #define IRQ1_HEAD 0x80094 | ||
481 | #define IRQ1_CNTL 0x80098 | ||
482 | #define IRQ1_DATA 0x8009c | ||
483 | |||
484 | #define IRQ2_BASE 0x800a0 | ||
485 | #define IRQ2_HEAD 0x800a4 | ||
486 | #define IRQ2_CNTL 0x800a8 | ||
487 | #define IRQ2_DATA 0x800ac | ||
488 | |||
489 | #define IRQ3_BASE 0x800b0 | ||
490 | #define IRQ3_HEAD 0x800b4 | ||
491 | #define IRQ3_CNTL 0x800b8 | ||
492 | #define IRQ3_DATA 0x800bc | ||
493 | |||
494 | #define GRP_10_MAP 0x800c0 | ||
495 | #define GRP_32_MAP 0x800c4 | ||
496 | #define GRP_54_MAP 0x800c8 | ||
497 | #define GRP_76_MAP 0x800cc | ||
498 | |||
499 | #define G0_RBPS_S 0x80400 | ||
500 | #define G0_RBPS_T 0x80404 | ||
501 | #define RBP_TAIL(x) ((x)<<3) | ||
502 | #define RBP_MASK(x) ((x)|0x1fff) | ||
503 | #define G0_RBPS_QI 0x80408 | ||
504 | #define RBP_QSIZE(x) ((x)<<14) | ||
505 | #define RBP_INT_ENB (1<<13) | ||
506 | #define RBP_THRESH(x) (x) | ||
507 | #define G0_RBPS_BS 0x8040c | ||
508 | #define G0_RBPL_S 0x80410 | ||
509 | #define G0_RBPL_T 0x80414 | ||
510 | #define G0_RBPL_QI 0x80418 | ||
511 | #define G0_RBPL_BS 0x8041c | ||
512 | |||
513 | #define G1_RBPS_S 0x80420 | ||
514 | #define G1_RBPS_T 0x80424 | ||
515 | #define G1_RBPS_QI 0x80428 | ||
516 | #define G1_RBPS_BS 0x8042c | ||
517 | #define G1_RBPL_S 0x80430 | ||
518 | #define G1_RBPL_T 0x80434 | ||
519 | #define G1_RBPL_QI 0x80438 | ||
520 | #define G1_RBPL_BS 0x8043c | ||
521 | |||
522 | #define G2_RBPS_S 0x80440 | ||
523 | #define G2_RBPS_T 0x80444 | ||
524 | #define G2_RBPS_QI 0x80448 | ||
525 | #define G2_RBPS_BS 0x8044c | ||
526 | #define G2_RBPL_S 0x80450 | ||
527 | #define G2_RBPL_T 0x80454 | ||
528 | #define G2_RBPL_QI 0x80458 | ||
529 | #define G2_RBPL_BS 0x8045c | ||
530 | |||
531 | #define G3_RBPS_S 0x80460 | ||
532 | #define G3_RBPS_T 0x80464 | ||
533 | #define G3_RBPS_QI 0x80468 | ||
534 | #define G3_RBPS_BS 0x8046c | ||
535 | #define G3_RBPL_S 0x80470 | ||
536 | #define G3_RBPL_T 0x80474 | ||
537 | #define G3_RBPL_QI 0x80478 | ||
538 | #define G3_RBPL_BS 0x8047c | ||
539 | |||
540 | #define G4_RBPS_S 0x80480 | ||
541 | #define G4_RBPS_T 0x80484 | ||
542 | #define G4_RBPS_QI 0x80488 | ||
543 | #define G4_RBPS_BS 0x8048c | ||
544 | #define G4_RBPL_S 0x80490 | ||
545 | #define G4_RBPL_T 0x80494 | ||
546 | #define G4_RBPL_QI 0x80498 | ||
547 | #define G4_RBPL_BS 0x8049c | ||
548 | |||
549 | #define G5_RBPS_S 0x804a0 | ||
550 | #define G5_RBPS_T 0x804a4 | ||
551 | #define G5_RBPS_QI 0x804a8 | ||
552 | #define G5_RBPS_BS 0x804ac | ||
553 | #define G5_RBPL_S 0x804b0 | ||
554 | #define G5_RBPL_T 0x804b4 | ||
555 | #define G5_RBPL_QI 0x804b8 | ||
556 | #define G5_RBPL_BS 0x804bc | ||
557 | |||
558 | #define G6_RBPS_S 0x804c0 | ||
559 | #define G6_RBPS_T 0x804c4 | ||
560 | #define G6_RBPS_QI 0x804c8 | ||
561 | #define G6_RBPS_BS 0x804cc | ||
562 | #define G6_RBPL_S 0x804d0 | ||
563 | #define G6_RBPL_T 0x804d4 | ||
564 | #define G6_RBPL_QI 0x804d8 | ||
565 | #define G6_RBPL_BS 0x804dc | ||
566 | |||
567 | #define G7_RBPS_S 0x804e0 | ||
568 | #define G7_RBPS_T 0x804e4 | ||
569 | #define G7_RBPS_QI 0x804e8 | ||
570 | #define G7_RBPS_BS 0x804ec | ||
571 | |||
572 | #define G7_RBPL_S 0x804f0 | ||
573 | #define G7_RBPL_T 0x804f4 | ||
574 | #define G7_RBPL_QI 0x804f8 | ||
575 | #define G7_RBPL_BS 0x804fc | ||
576 | |||
577 | #define G0_RBRQ_ST 0x80500 | ||
578 | #define G0_RBRQ_H 0x80504 | ||
579 | #define G0_RBRQ_Q 0x80508 | ||
580 | #define RBRQ_THRESH(x) ((x)<<13) | ||
581 | #define RBRQ_SIZE(x) (x) | ||
582 | #define G0_RBRQ_I 0x8050c | ||
583 | #define RBRQ_TIME(x) ((x)<<8) | ||
584 | #define RBRQ_COUNT(x) (x) | ||
585 | |||
586 | /* fill in 1 ... 7 later */ | ||
587 | |||
588 | #define G0_TBRQ_B_T 0x80600 | ||
589 | #define G0_TBRQ_H 0x80604 | ||
590 | #define G0_TBRQ_S 0x80608 | ||
591 | #define G0_TBRQ_THRESH 0x8060c | ||
592 | #define TBRQ_THRESH(x) (x) | ||
593 | |||
594 | /* fill in 1 ... 7 later */ | ||
595 | |||
596 | #define RH_CONFIG 0x805c0 | ||
597 | #define PHY_INT_ENB (1<<10) | ||
598 | #define OAM_GID(x) (x<<7) | ||
599 | #define PTMR_PRE(x) (x) | ||
600 | |||
601 | #define G0_INMQ_S 0x80580 | ||
602 | #define G0_INMQ_L 0x80584 | ||
603 | #define G1_INMQ_S 0x80588 | ||
604 | #define G1_INMQ_L 0x8058c | ||
605 | #define G2_INMQ_S 0x80590 | ||
606 | #define G2_INMQ_L 0x80594 | ||
607 | #define G3_INMQ_S 0x80598 | ||
608 | #define G3_INMQ_L 0x8059c | ||
609 | #define G4_INMQ_S 0x805a0 | ||
610 | #define G4_INMQ_L 0x805a4 | ||
611 | #define G5_INMQ_S 0x805a8 | ||
612 | #define G5_INMQ_L 0x805ac | ||
613 | #define G6_INMQ_S 0x805b0 | ||
614 | #define G6_INMQ_L 0x805b4 | ||
615 | #define G7_INMQ_S 0x805b8 | ||
616 | #define G7_INMQ_L 0x805bc | ||
617 | |||
618 | #define TPDRQ_B_H 0x80680 | ||
619 | #define TPDRQ_T 0x80684 | ||
620 | #define TPDRQ_S 0x80688 | ||
621 | |||
622 | #define UBUFF_BA 0x8068c | ||
623 | |||
624 | #define RLBF0_H 0x806c0 | ||
625 | #define RLBF0_T 0x806c4 | ||
626 | #define RLBF1_H 0x806c8 | ||
627 | #define RLBF1_T 0x806cc | ||
628 | #define RLBC_H 0x806d0 | ||
629 | #define RLBC_T 0x806d4 | ||
630 | #define RLBC_H2 0x806d8 | ||
631 | #define TLBF_H 0x806e0 | ||
632 | #define TLBF_T 0x806e4 | ||
633 | #define RLBF0_C 0x806e8 | ||
634 | #define RLBF1_C 0x806ec | ||
635 | #define RXTHRSH 0x806f0 | ||
636 | #define LITHRSH 0x806f4 | ||
637 | |||
638 | #define LBARB 0x80700 | ||
639 | #define SLICE_X(x) (x<<28) | ||
640 | #define ARB_RNUM_MAX(x) (x<<23) | ||
641 | #define TH_PRTY(x) (x<<21) | ||
642 | #define RH_PRTY(x) (x<<19) | ||
643 | #define TL_PRTY(x) (x<<17) | ||
644 | #define RL_PRTY(x) (x<<15) | ||
645 | #define BUS_MULTI(x) (x<<8) | ||
646 | #define NET_PREF(x) (x) | ||
647 | |||
648 | #define SDRAMCON 0x80704 | ||
649 | #define BANK_ON (1<<14) | ||
650 | #define WIDE_DATA (1<<13) | ||
651 | #define TWR_WAIT (1<<12) | ||
652 | #define TRP_WAIT (1<<11) | ||
653 | #define TRAS_WAIT (1<<10) | ||
654 | #define REF_RATE(x) (x) | ||
655 | |||
656 | #define LBSTAT 0x80708 | ||
657 | |||
658 | #define RCC_STAT 0x8070c | ||
659 | #define RCC_BUSY (1) | ||
660 | |||
661 | #define TCMCONFIG 0x80740 | ||
662 | #define TM_DESL2 (1<<10) | ||
663 | #define TM_BANK_WAIT(x) (x<<6) | ||
664 | #define TM_ADD_BANK4(x) (x<<4) | ||
665 | #define TM_PAR_CHECK(x) (x<<3) | ||
666 | #define TM_RW_WAIT(x) (x<<2) | ||
667 | #define TM_SRAM_TYPE(x) (x) | ||
668 | |||
669 | #define TSRB_BA 0x80744 | ||
670 | #define TSRC_BA 0x80748 | ||
671 | #define TMABR_BA 0x8074c | ||
672 | #define TPD_BA 0x80750 | ||
673 | #define TSRD_BA 0x80758 | ||
674 | |||
675 | #define TX_CONFIG 0x80760 | ||
676 | #define DRF_THRESH(x) (x<<22) | ||
677 | #define TX_UT_MODE(x) (x<<21) | ||
678 | #define TX_VCI_MASK(x) (x<<17) | ||
679 | #define LBFREE_CNT(x) (x) | ||
680 | |||
681 | #define TXAAL5_PROTO 0x80764 | ||
682 | #define CPCS_UU(x) (x<<8) | ||
683 | #define CPI(x) (x) | ||
684 | |||
685 | #define RCMCONFIG 0x80780 | ||
686 | #define RM_DESL2(x) (x<<10) | ||
687 | #define RM_BANK_WAIT(x) (x<<6) | ||
688 | #define RM_ADD_BANK(x) (x<<4) | ||
689 | #define RM_PAR_CHECK(x) (x<<3) | ||
690 | #define RM_RW_WAIT(x) (x<<2) | ||
691 | #define RM_SRAM_TYPE(x) (x) | ||
692 | |||
693 | #define RCMRSRB_BA 0x80784 | ||
694 | #define RCMLBM_BA 0x80788 | ||
695 | #define RCMABR_BA 0x8078c | ||
696 | |||
697 | #define RC_CONFIG 0x807c0 | ||
698 | #define UT_RD_DELAY(x) (x<<11) | ||
699 | #define WRAP_MODE(x) (x<<10) | ||
700 | #define RC_UT_MODE(x) (x<<9) | ||
701 | #define RX_ENABLE (1<<8) | ||
702 | #define RX_VALVP(x) (x<<4) | ||
703 | #define RX_VALVC(x) (x) | ||
704 | |||
705 | #define MCC 0x807c4 | ||
706 | #define OEC 0x807c8 | ||
707 | #define DCC 0x807cc | ||
708 | #define CEC 0x807d0 | ||
709 | |||
710 | #define HSP_BA 0x807f0 | ||
711 | |||
712 | #define LB_CONFIG 0x807f4 | ||
713 | #define LB_SIZE(x) (x) | ||
714 | |||
715 | #define CON_DAT 0x807f8 | ||
716 | #define CON_CTL 0x807fc | ||
717 | #define CON_CTL_MBOX (2<<30) | ||
718 | #define CON_CTL_TCM (1<<30) | ||
719 | #define CON_CTL_RCM (0<<30) | ||
720 | #define CON_CTL_WRITE (1<<29) | ||
721 | #define CON_CTL_READ (0<<29) | ||
722 | #define CON_CTL_BUSY (1<<28) | ||
723 | #define CON_BYTE_DISABLE_3 (1<<22) /* 24..31 */ | ||
724 | #define CON_BYTE_DISABLE_2 (1<<21) /* 16..23 */ | ||
725 | #define CON_BYTE_DISABLE_1 (1<<20) /* 8..15 */ | ||
726 | #define CON_BYTE_DISABLE_0 (1<<19) /* 0..7 */ | ||
727 | #define CON_CTL_ADDR(x) (x) | ||
728 | |||
729 | #define FRAMER 0x80800 /* to 0x80bfc */ | ||
730 | |||
731 | /* 3.3 network controller (internal) mailbox registers */ | ||
732 | |||
733 | #define CS_STPER0 0x0 | ||
734 | /* ... */ | ||
735 | #define CS_STPER31 0x01f | ||
736 | |||
737 | #define CS_STTIM0 0x020 | ||
738 | /* ... */ | ||
739 | #define CS_STTIM31 0x03f | ||
740 | |||
741 | #define CS_TGRLD0 0x040 | ||
742 | /* ... */ | ||
743 | #define CS_TGRLD15 0x04f | ||
744 | |||
745 | #define CS_ERTHR0 0x050 | ||
746 | #define CS_ERTHR1 0x051 | ||
747 | #define CS_ERTHR2 0x052 | ||
748 | #define CS_ERTHR3 0x053 | ||
749 | #define CS_ERTHR4 0x054 | ||
750 | #define CS_ERCTL0 0x055 | ||
751 | #define TX_ENABLE (1<<28) | ||
752 | #define ER_ENABLE (1<<27) | ||
753 | #define CS_ERCTL1 0x056 | ||
754 | #define CS_ERCTL2 0x057 | ||
755 | #define CS_ERSTAT0 0x058 | ||
756 | #define CS_ERSTAT1 0x059 | ||
757 | |||
758 | #define CS_RTCCT 0x060 | ||
759 | #define CS_RTFWC 0x061 | ||
760 | #define CS_RTFWR 0x062 | ||
761 | #define CS_RTFTC 0x063 | ||
762 | #define CS_RTATR 0x064 | ||
763 | |||
764 | #define CS_TFBSET 0x070 | ||
765 | #define CS_TFBADD 0x071 | ||
766 | #define CS_TFBSUB 0x072 | ||
767 | #define CS_WCRMAX 0x073 | ||
768 | #define CS_WCRMIN 0x074 | ||
769 | #define CS_WCRINC 0x075 | ||
770 | #define CS_WCRDEC 0x076 | ||
771 | #define CS_WCRCEIL 0x077 | ||
772 | #define CS_BWDCNT 0x078 | ||
773 | |||
774 | #define CS_OTPPER 0x080 | ||
775 | #define CS_OTWPER 0x081 | ||
776 | #define CS_OTTLIM 0x082 | ||
777 | #define CS_OTTCNT 0x083 | ||
778 | |||
779 | #define CS_HGRRT0 0x090 | ||
780 | /* ... */ | ||
781 | #define CS_HGRRT7 0x097 | ||
782 | |||
783 | #define CS_ORPTRS 0x0a0 | ||
784 | |||
785 | #define RXCON_CLOSE 0x100 | ||
786 | |||
787 | |||
788 | #define RCM_MEM_SIZE 0x10000 /* 1M of 32-bit registers */ | ||
789 | #define TCM_MEM_SIZE 0x20000 /* 2M of 32-bit registers */ | ||
790 | |||
791 | /* 2.5 transmit connection memory registers */ | ||
792 | |||
793 | #define TSR0_CONN_STATE(x) ((x>>28) & 0x7) | ||
794 | #define TSR0_USE_WMIN (1<<23) | ||
795 | #define TSR0_GROUP(x) ((x & 0x7)<<18) | ||
796 | #define TSR0_ABR (2<<16) | ||
797 | #define TSR0_UBR (1<<16) | ||
798 | #define TSR0_CBR (0<<16) | ||
799 | #define TSR0_PROT (1<<15) | ||
800 | #define TSR0_AAL0_SDU (2<<12) | ||
801 | #define TSR0_AAL0 (1<<12) | ||
802 | #define TSR0_AAL5 (0<<12) | ||
803 | #define TSR0_HALT_ER (1<<11) | ||
804 | #define TSR0_MARK_CI (1<<10) | ||
805 | #define TSR0_MARK_ER (1<<9) | ||
806 | #define TSR0_UPDATE_GER (1<<8) | ||
807 | #define TSR0_RC_INDEX(x) (x & 0x1F) | ||
808 | |||
809 | #define TSR1_PCR(x) ((x & 0x7FFF)<<16) | ||
810 | #define TSR1_MCR(x) (x & 0x7FFF) | ||
811 | |||
812 | #define TSR2_ACR(x) ((x & 0x7FFF)<<16) | ||
813 | |||
814 | #define TSR3_NRM_CNT(x) ((x & 0xFF)<<24) | ||
815 | #define TSR3_CRM_CNT(x) (x & 0xFFFF) | ||
816 | |||
817 | #define TSR4_FLUSH_CONN (1<<31) | ||
818 | #define TSR4_SESSION_ENDED (1<<30) | ||
819 | #define TSR4_CRC10 (1<<28) | ||
820 | #define TSR4_NULL_CRC10 (1<<27) | ||
821 | #define TSR4_PROT (1<<26) | ||
822 | #define TSR4_AAL0_SDU (2<<23) | ||
823 | #define TSR4_AAL0 (1<<23) | ||
824 | #define TSR4_AAL5 (0<<23) | ||
825 | |||
826 | #define TSR9_OPEN_CONN (1<<20) | ||
827 | |||
828 | #define TSR11_ICR(x) ((x & 0x7FFF)<<16) | ||
829 | #define TSR11_TRM(x) ((x & 0x7)<<13) | ||
830 | #define TSR11_NRM(x) ((x & 0x7)<<10) | ||
831 | #define TSR11_ADTF(x) (x & 0x3FF) | ||
832 | |||
833 | #define TSR13_RDF(x) ((x & 0xF)<<23) | ||
834 | #define TSR13_RIF(x) ((x & 0xF)<<19) | ||
835 | #define TSR13_CDF(x) ((x & 0x7)<<16) | ||
836 | #define TSR13_CRM(x) (x & 0xFFFF) | ||
837 | |||
838 | #define TSR14_DELETE (1<<31) | ||
839 | #define TSR14_ABR_CLOSE (1<<16) | ||
840 | |||
841 | /* 2.7.1 per connection receieve state registers */ | ||
842 | |||
843 | #define RSR0_START_PDU (1<<10) | ||
844 | #define RSR0_OPEN_CONN (1<<6) | ||
845 | #define RSR0_CLOSE_CONN (0<<6) | ||
846 | #define RSR0_PPD_ENABLE (1<<5) | ||
847 | #define RSR0_EPD_ENABLE (1<<4) | ||
848 | #define RSR0_TCP_CKSUM (1<<3) | ||
849 | #define RSR0_AAL5 (0) | ||
850 | #define RSR0_AAL0 (1) | ||
851 | #define RSR0_AAL0_SDU (2) | ||
852 | #define RSR0_RAWCELL (3) | ||
853 | #define RSR0_RAWCELL_CRC10 (4) | ||
854 | |||
855 | #define RSR1_AQI_ENABLE (1<<20) | ||
856 | #define RSR1_RBPL_ONLY (1<<19) | ||
857 | #define RSR1_GROUP(x) ((x)<<16) | ||
858 | |||
859 | #define RSR4_AQI_ENABLE (1<<30) | ||
860 | #define RSR4_GROUP(x) ((x)<<27) | ||
861 | #define RSR4_RBPL_ONLY (1<<26) | ||
862 | |||
863 | /* 2.1.4 transmit packet descriptor */ | ||
864 | |||
865 | #define TPD_USERCELL 0x0 | ||
866 | #define TPD_SEGMENT_OAMF5 0x4 | ||
867 | #define TPD_END2END_OAMF5 0x5 | ||
868 | #define TPD_RMCELL 0x6 | ||
869 | #define TPD_CELLTYPE(x) (x<<3) | ||
870 | #define TPD_EOS (1<<2) | ||
871 | #define TPD_CLP (1<<1) | ||
872 | #define TPD_INT (1<<0) | ||
873 | #define TPD_LST (1<<31) | ||
874 | |||
875 | /* table 4.3 serial eeprom information */ | ||
876 | |||
877 | #define PROD_ID 0x08 /* char[] */ | ||
878 | #define PROD_ID_LEN 30 | ||
879 | #define HW_REV 0x26 /* char[] */ | ||
880 | #define M_SN 0x3a /* integer */ | ||
881 | #define MEDIA 0x3e /* integer */ | ||
882 | #define HE155MM 0x26 | ||
883 | #define HE155SM 0x27 | ||
884 | #define HE622MM 0x46 | ||
885 | #define HE622SM 0x47 | ||
886 | #define MAC_ADDR 0x42 /* char[] */ | ||
887 | |||
888 | #define CS_LOW 0x0 | ||
889 | #define CS_HIGH ID_CS /* HOST_CNTL_ID_PROM_SEL */ | ||
890 | #define CLK_LOW 0x0 | ||
891 | #define CLK_HIGH ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */ | ||
892 | #define SI_HIGH ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */ | ||
893 | #define EEPROM_DELAY 400 /* microseconds */ | ||
894 | |||
895 | #endif /* _HE_H_ */ | ||
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c new file mode 100644 index 000000000000..924a2c8988bd --- /dev/null +++ b/drivers/atm/horizon.c | |||
@@ -0,0 +1,2953 @@ | |||
1 | /* | ||
2 | Madge Horizon ATM Adapter driver. | ||
3 | Copyright (C) 1995-1999 Madge Networks Ltd. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian | ||
20 | system and in the file COPYING in the Linux kernel source. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | IMPORTANT NOTE: Madge Networks no longer makes the adapters | ||
25 | supported by this driver and makes no commitment to maintain it. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/atm.h> | ||
34 | #include <linux/atmdev.h> | ||
35 | #include <linux/sonet.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/time.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/uio.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/wait.h> | ||
43 | |||
44 | #include <asm/system.h> | ||
45 | #include <asm/io.h> | ||
46 | #include <asm/atomic.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | #include <asm/string.h> | ||
49 | #include <asm/byteorder.h> | ||
50 | |||
51 | #include "horizon.h" | ||
52 | |||
53 | #define maintainer_string "Giuliano Procida at Madge Networks <gprocida@madge.com>" | ||
54 | #define description_string "Madge ATM Horizon [Ultra] driver" | ||
55 | #define version_string "1.2.1" | ||
56 | |||
57 | static inline void __init show_version (void) { | ||
58 | printk ("%s version %s\n", description_string, version_string); | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | |||
63 | CREDITS | ||
64 | |||
65 | Driver and documentation by: | ||
66 | |||
67 | Chris Aston Madge Networks | ||
68 | Giuliano Procida Madge Networks | ||
69 | Simon Benham Madge Networks | ||
70 | Simon Johnson Madge Networks | ||
71 | Various Others Madge Networks | ||
72 | |||
73 | Some inspiration taken from other drivers by: | ||
74 | |||
75 | Alexandru Cucos UTBv | ||
76 | Kari Mettinen University of Helsinki | ||
77 | Werner Almesberger EPFL LRC | ||
78 | |||
79 | Theory of Operation | ||
80 | |||
81 | I Hardware, detection, initialisation and shutdown. | ||
82 | |||
83 | 1. Supported Hardware | ||
84 | |||
85 | This driver should handle all variants of the PCI Madge ATM adapters | ||
86 | with the Horizon chipset. These are all PCI cards supporting PIO, BM | ||
87 | DMA and a form of MMIO (registers only, not internal RAM). | ||
88 | |||
89 | The driver is only known to work with SONET and UTP Horizon Ultra | ||
90 | cards at 155Mb/s. However, code is in place to deal with both the | ||
91 | original Horizon and 25Mb/s operation. | ||
92 | |||
93 | There are two revisions of the Horizon ASIC: the original and the | ||
94 | Ultra. Details of hardware bugs are in section III. | ||
95 | |||
96 | The ASIC version can be distinguished by chip markings but is NOT | ||
97 | indicated by the PCI revision (all adapters seem to have PCI rev 1). | ||
98 | |||
99 | I believe that: | ||
100 | |||
101 | Horizon => Collage 25 PCI Adapter (UTP and STP) | ||
102 | Horizon Ultra => Collage 155 PCI Client (UTP or SONET) | ||
103 | Ambassador x => Collage 155 PCI Server (completely different) | ||
104 | |||
105 | Horizon (25Mb/s) is fitted with UTP and STP connectors. It seems to | ||
106 | have a Madge B154 plus glue logic serializer. I have also found a | ||
107 | really ancient version of this with slightly different glue. It | ||
108 | comes with the revision 0 (140-025-01) ASIC. | ||
109 | |||
110 | Horizon Ultra (155Mb/s) is fitted with either a Pulse Medialink | ||
111 | output (UTP) or an HP HFBR 5205 output (SONET). It has either | ||
112 | Madge's SAMBA framer or a SUNI-lite device (early versions). It | ||
113 | comes with the revision 1 (140-027-01) ASIC. | ||
114 | |||
115 | 2. Detection | ||
116 | |||
117 | All Horizon-based cards present with the same PCI Vendor and Device | ||
118 | IDs. The standard Linux 2.2 PCI API is used to locate any cards and | ||
119 | to enable bus-mastering (with appropriate latency). | ||
120 | |||
121 | ATM_LAYER_STATUS in the control register distinguishes between the | ||
122 | two possible physical layers (25 and 155). It is not clear whether | ||
123 | the 155 cards can also operate at 25Mbps. We rely on the fact that a | ||
124 | card operates at 155 if and only if it has the newer Horizon Ultra | ||
125 | ASIC. | ||
126 | |||
127 | For 155 cards the two possible framers are probed for and then set | ||
128 | up for loop-timing. | ||
129 | |||
130 | 3. Initialisation | ||
131 | |||
132 | The card is reset and then put into a known state. The physical | ||
133 | layer is configured for normal operation at the appropriate speed; | ||
134 | in the case of the 155 cards, the framer is initialised with | ||
135 | line-based timing; the internal RAM is zeroed and the allocation of | ||
136 | buffers for RX and TX is made; the Burnt In Address is read and | ||
137 | copied to the ATM ESI; various policy settings for RX (VPI bits, | ||
138 | unknown VCs, oam cells) are made. Ideally all policy items should be | ||
139 | configurable at module load (if not actually on-demand), however, | ||
140 | only the vpi vs vci bit allocation can be specified at insmod. | ||
141 | |||
142 | 4. Shutdown | ||
143 | |||
144 | This is in response to module_cleaup. No VCs are in use and the card | ||
145 | should be idle; it is reset. | ||
146 | |||
147 | II Driver software (as it should be) | ||
148 | |||
149 | 0. Traffic Parameters | ||
150 | |||
151 | The traffic classes (not an enumeration) are currently: ATM_NONE (no | ||
152 | traffic), ATM_UBR, ATM_CBR, ATM_VBR and ATM_ABR, ATM_ANYCLASS | ||
153 | (compatible with everything). Together with (perhaps only some of) | ||
154 | the following items they make up the traffic specification. | ||
155 | |||
156 | struct atm_trafprm { | ||
157 | unsigned char traffic_class; traffic class (ATM_UBR, ...) | ||
158 | int max_pcr; maximum PCR in cells per second | ||
159 | int pcr; desired PCR in cells per second | ||
160 | int min_pcr; minimum PCR in cells per second | ||
161 | int max_cdv; maximum CDV in microseconds | ||
162 | int max_sdu; maximum SDU in bytes | ||
163 | }; | ||
164 | |||
165 | Note that these denote bandwidth available not bandwidth used; the | ||
166 | possibilities according to ATMF are: | ||
167 | |||
168 | Real Time (cdv and max CDT given) | ||
169 | |||
170 | CBR(pcr) pcr bandwidth always available | ||
171 | rtVBR(pcr,scr,mbs) scr bandwidth always available, upto pcr at mbs too | ||
172 | |||
173 | Non Real Time | ||
174 | |||
175 | nrtVBR(pcr,scr,mbs) scr bandwidth always available, upto pcr at mbs too | ||
176 | UBR() | ||
177 | ABR(mcr,pcr) mcr bandwidth always available, upto pcr (depending) too | ||
178 | |||
179 | mbs is max burst size (bucket) | ||
180 | pcr and scr have associated cdvt values | ||
181 | mcr is like scr but has no cdtv | ||
182 | cdtv may differ at each hop | ||
183 | |||
184 | Some of the above items are qos items (as opposed to traffic | ||
185 | parameters). We have nothing to do with qos. All except ABR can have | ||
186 | their traffic parameters converted to GCRA parameters. The GCRA may | ||
187 | be implemented as a (real-number) leaky bucket. The GCRA can be used | ||
188 | in complicated ways by switches and in simpler ways by end-stations. | ||
189 | It can be used both to filter incoming cells and shape out-going | ||
190 | cells. | ||
191 | |||
192 | ATM Linux actually supports: | ||
193 | |||
194 | ATM_NONE() (no traffic in this direction) | ||
195 | ATM_UBR(max_frame_size) | ||
196 | ATM_CBR(max/min_pcr, max_cdv, max_frame_size) | ||
197 | |||
198 | 0 or ATM_MAX_PCR are used to indicate maximum available PCR | ||
199 | |||
200 | A traffic specification consists of the AAL type and separate | ||
201 | traffic specifications for either direction. In ATM Linux it is: | ||
202 | |||
203 | struct atm_qos { | ||
204 | struct atm_trafprm txtp; | ||
205 | struct atm_trafprm rxtp; | ||
206 | unsigned char aal; | ||
207 | }; | ||
208 | |||
209 | AAL types are: | ||
210 | |||
211 | ATM_NO_AAL AAL not specified | ||
212 | ATM_AAL0 "raw" ATM cells | ||
213 | ATM_AAL1 AAL1 (CBR) | ||
214 | ATM_AAL2 AAL2 (VBR) | ||
215 | ATM_AAL34 AAL3/4 (data) | ||
216 | ATM_AAL5 AAL5 (data) | ||
217 | ATM_SAAL signaling AAL | ||
218 | |||
219 | The Horizon has support for AAL frame types: 0, 3/4 and 5. However, | ||
220 | it does not implement AAL 3/4 SAR and it has a different notion of | ||
221 | "raw cell" to ATM Linux's (48 bytes vs. 52 bytes) so neither are | ||
222 | supported by this driver. | ||
223 | |||
224 | The Horizon has limited support for ABR (including UBR), VBR and | ||
225 | CBR. Each TX channel has a bucket (containing up to 31 cell units) | ||
226 | and two timers (PCR and SCR) associated with it that can be used to | ||
227 | govern cell emissions and host notification (in the case of ABR this | ||
228 | is presumably so that RM cells may be emitted at appropriate times). | ||
229 | The timers may either be disabled or may be set to any of 240 values | ||
230 | (determined by the clock crystal, a fixed (?) per-device divider, a | ||
231 | configurable divider and a configurable timer preload value). | ||
232 | |||
233 | At the moment only UBR and CBR are supported by the driver. VBR will | ||
234 | be supported as soon as ATM for Linux supports it. ABR support is | ||
235 | very unlikely as RM cell handling is completely up to the driver. | ||
236 | |||
237 | 1. TX (TX channel setup and TX transfer) | ||
238 | |||
239 | The TX half of the driver owns the TX Horizon registers. The TX | ||
240 | component in the IRQ handler is the BM completion handler. This can | ||
241 | only be entered when tx_busy is true (enforced by hardware). The | ||
242 | other TX component can only be entered when tx_busy is false | ||
243 | (enforced by driver). So TX is single-threaded. | ||
244 | |||
245 | Apart from a minor optimisation to not re-select the last channel, | ||
246 | the TX send component works as follows: | ||
247 | |||
248 | Atomic test and set tx_busy until we succeed; we should implement | ||
249 | some sort of timeout so that tx_busy will never be stuck at true. | ||
250 | |||
251 | If no TX channel is set up for this VC we wait for an idle one (if | ||
252 | necessary) and set it up. | ||
253 | |||
254 | At this point we have a TX channel ready for use. We wait for enough | ||
255 | buffers to become available then start a TX transmit (set the TX | ||
256 | descriptor, schedule transfer, exit). | ||
257 | |||
258 | The IRQ component handles TX completion (stats, free buffer, tx_busy | ||
259 | unset, exit). We also re-schedule further transfers for the same | ||
260 | frame if needed. | ||
261 | |||
262 | TX setup in more detail: | ||
263 | |||
264 | TX open is a nop, the relevant information is held in the hrz_vcc | ||
265 | (vcc->dev_data) structure and is "cached" on the card. | ||
266 | |||
267 | TX close gets the TX lock and clears the channel from the "cache". | ||
268 | |||
269 | 2. RX (Data Available and RX transfer) | ||
270 | |||
271 | The RX half of the driver owns the RX registers. There are two RX | ||
272 | components in the IRQ handler: the data available handler deals with | ||
273 | fresh data that has arrived on the card, the BM completion handler | ||
274 | is very similar to the TX completion handler. The data available | ||
275 | handler grabs the rx_lock and it is only released once the data has | ||
276 | been discarded or completely transferred to the host. The BM | ||
277 | completion handler only runs when the lock is held; the data | ||
278 | available handler is locked out over the same period. | ||
279 | |||
280 | Data available on the card triggers an interrupt. If the data is not | ||
281 | suitable for our existing RX channels or we cannot allocate a buffer | ||
282 | it is flushed. Otherwise an RX receive is scheduled. Multiple RX | ||
283 | transfers may be scheduled for the same frame. | ||
284 | |||
285 | RX setup in more detail: | ||
286 | |||
287 | RX open... | ||
288 | RX close... | ||
289 | |||
290 | III Hardware Bugs | ||
291 | |||
292 | 0. Byte vs Word addressing of adapter RAM. | ||
293 | |||
294 | A design feature; see the .h file (especially the memory map). | ||
295 | |||
296 | 1. Bus Master Data Transfers (original Horizon only, fixed in Ultra) | ||
297 | |||
298 | The host must not start a transmit direction transfer at a | ||
299 | non-four-byte boundary in host memory. Instead the host should | ||
300 | perform a byte, or a two byte, or one byte followed by two byte | ||
301 | transfer in order to start the rest of the transfer on a four byte | ||
302 | boundary. RX is OK. | ||
303 | |||
304 | Simultaneous transmit and receive direction bus master transfers are | ||
305 | not allowed. | ||
306 | |||
307 | The simplest solution to these two is to always do PIO (never DMA) | ||
308 | in the TX direction on the original Horizon. More complicated | ||
309 | solutions are likely to hurt my brain. | ||
310 | |||
311 | 2. Loss of buffer on close VC | ||
312 | |||
313 | When a VC is being closed, the buffer associated with it is not | ||
314 | returned to the pool. The host must store the reference to this | ||
315 | buffer and when opening a new VC then give it to that new VC. | ||
316 | |||
317 | The host intervention currently consists of stacking such a buffer | ||
318 | pointer at VC close and checking the stack at VC open. | ||
319 | |||
320 | 3. Failure to close a VC | ||
321 | |||
322 | If a VC is currently receiving a frame then closing the VC may fail | ||
323 | and the frame continues to be received. | ||
324 | |||
325 | The solution is to make sure any received frames are flushed when | ||
326 | ready. This is currently done just before the solution to 2. | ||
327 | |||
328 | 4. PCI bus (original Horizon only, fixed in Ultra) | ||
329 | |||
330 | Reading from the data port prior to initialisation will hang the PCI | ||
331 | bus. Just don't do that then! We don't. | ||
332 | |||
333 | IV To Do List | ||
334 | |||
335 | . Timer code may be broken. | ||
336 | |||
337 | . Allow users to specify buffer allocation split for TX and RX. | ||
338 | |||
339 | . Deal once and for all with buggy VC close. | ||
340 | |||
341 | . Handle interrupted and/or non-blocking operations. | ||
342 | |||
343 | . Change some macros to functions and move from .h to .c. | ||
344 | |||
345 | . Try to limit the number of TX frames each VC may have queued, in | ||
346 | order to reduce the chances of TX buffer exhaustion. | ||
347 | |||
348 | . Implement VBR (bucket and timers not understood) and ABR (need to | ||
349 | do RM cells manually); also no Linux support for either. | ||
350 | |||
351 | . Implement QoS changes on open VCs (involves extracting parts of VC open | ||
352 | and close into separate functions and using them to make changes). | ||
353 | |||
354 | */ | ||
355 | |||
356 | /********** globals **********/ | ||
357 | |||
358 | static void do_housekeeping (unsigned long arg); | ||
359 | |||
360 | static unsigned short debug = 0; | ||
361 | static unsigned short vpi_bits = 0; | ||
362 | static int max_tx_size = 9000; | ||
363 | static int max_rx_size = 9000; | ||
364 | static unsigned char pci_lat = 0; | ||
365 | |||
366 | /********** access functions **********/ | ||
367 | |||
368 | /* Read / Write Horizon registers */ | ||
369 | static inline void wr_regl (const hrz_dev * dev, unsigned char reg, u32 data) { | ||
370 | outl (cpu_to_le32 (data), dev->iobase + reg); | ||
371 | } | ||
372 | |||
373 | static inline u32 rd_regl (const hrz_dev * dev, unsigned char reg) { | ||
374 | return le32_to_cpu (inl (dev->iobase + reg)); | ||
375 | } | ||
376 | |||
377 | static inline void wr_regw (const hrz_dev * dev, unsigned char reg, u16 data) { | ||
378 | outw (cpu_to_le16 (data), dev->iobase + reg); | ||
379 | } | ||
380 | |||
381 | static inline u16 rd_regw (const hrz_dev * dev, unsigned char reg) { | ||
382 | return le16_to_cpu (inw (dev->iobase + reg)); | ||
383 | } | ||
384 | |||
385 | static inline void wrs_regb (const hrz_dev * dev, unsigned char reg, void * addr, u32 len) { | ||
386 | outsb (dev->iobase + reg, addr, len); | ||
387 | } | ||
388 | |||
389 | static inline void rds_regb (const hrz_dev * dev, unsigned char reg, void * addr, u32 len) { | ||
390 | insb (dev->iobase + reg, addr, len); | ||
391 | } | ||
392 | |||
393 | /* Read / Write to a given address in Horizon buffer memory. | ||
394 | Interrupts must be disabled between the address register and data | ||
395 | port accesses as these must form an atomic operation. */ | ||
396 | static inline void wr_mem (const hrz_dev * dev, HDW * addr, u32 data) { | ||
397 | // wr_regl (dev, MEM_WR_ADDR_REG_OFF, (u32) addr); | ||
398 | wr_regl (dev, MEM_WR_ADDR_REG_OFF, (addr - (HDW *) 0) * sizeof(HDW)); | ||
399 | wr_regl (dev, MEMORY_PORT_OFF, data); | ||
400 | } | ||
401 | |||
402 | static inline u32 rd_mem (const hrz_dev * dev, HDW * addr) { | ||
403 | // wr_regl (dev, MEM_RD_ADDR_REG_OFF, (u32) addr); | ||
404 | wr_regl (dev, MEM_RD_ADDR_REG_OFF, (addr - (HDW *) 0) * sizeof(HDW)); | ||
405 | return rd_regl (dev, MEMORY_PORT_OFF); | ||
406 | } | ||
407 | |||
408 | static inline void wr_framer (const hrz_dev * dev, u32 addr, u32 data) { | ||
409 | wr_regl (dev, MEM_WR_ADDR_REG_OFF, (u32) addr | 0x80000000); | ||
410 | wr_regl (dev, MEMORY_PORT_OFF, data); | ||
411 | } | ||
412 | |||
413 | static inline u32 rd_framer (const hrz_dev * dev, u32 addr) { | ||
414 | wr_regl (dev, MEM_RD_ADDR_REG_OFF, (u32) addr | 0x80000000); | ||
415 | return rd_regl (dev, MEMORY_PORT_OFF); | ||
416 | } | ||
417 | |||
418 | /********** specialised access functions **********/ | ||
419 | |||
420 | /* RX */ | ||
421 | |||
422 | static inline void FLUSH_RX_CHANNEL (hrz_dev * dev, u16 channel) { | ||
423 | wr_regw (dev, RX_CHANNEL_PORT_OFF, FLUSH_CHANNEL | channel); | ||
424 | return; | ||
425 | } | ||
426 | |||
427 | static inline void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) { | ||
428 | while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & FLUSH_CHANNEL) | ||
429 | ; | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | static inline void SELECT_RX_CHANNEL (hrz_dev * dev, u16 channel) { | ||
434 | wr_regw (dev, RX_CHANNEL_PORT_OFF, channel); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | static inline void WAIT_UPDATE_COMPLETE (hrz_dev * dev) { | ||
439 | while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & RX_CHANNEL_UPDATE_IN_PROGRESS) | ||
440 | ; | ||
441 | return; | ||
442 | } | ||
443 | |||
444 | /* TX */ | ||
445 | |||
446 | static inline void SELECT_TX_CHANNEL (hrz_dev * dev, u16 tx_channel) { | ||
447 | wr_regl (dev, TX_CHANNEL_PORT_OFF, tx_channel); | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | /* Update or query one configuration parameter of a particular channel. */ | ||
452 | |||
453 | static inline void update_tx_channel_config (hrz_dev * dev, short chan, u8 mode, u16 value) { | ||
454 | wr_regw (dev, TX_CHANNEL_CONFIG_COMMAND_OFF, | ||
455 | chan * TX_CHANNEL_CONFIG_MULT | mode); | ||
456 | wr_regw (dev, TX_CHANNEL_CONFIG_DATA_OFF, value); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | static inline u16 query_tx_channel_config (hrz_dev * dev, short chan, u8 mode) { | ||
461 | wr_regw (dev, TX_CHANNEL_CONFIG_COMMAND_OFF, | ||
462 | chan * TX_CHANNEL_CONFIG_MULT | mode); | ||
463 | return rd_regw (dev, TX_CHANNEL_CONFIG_DATA_OFF); | ||
464 | } | ||
465 | |||
466 | /********** dump functions **********/ | ||
467 | |||
468 | static inline void dump_skb (char * prefix, unsigned int vc, struct sk_buff * skb) { | ||
469 | #ifdef DEBUG_HORIZON | ||
470 | unsigned int i; | ||
471 | unsigned char * data = skb->data; | ||
472 | PRINTDB (DBG_DATA, "%s(%u) ", prefix, vc); | ||
473 | for (i=0; i<skb->len && i < 256;i++) | ||
474 | PRINTDM (DBG_DATA, "%02x ", data[i]); | ||
475 | PRINTDE (DBG_DATA,""); | ||
476 | #else | ||
477 | (void) prefix; | ||
478 | (void) vc; | ||
479 | (void) skb; | ||
480 | #endif | ||
481 | return; | ||
482 | } | ||
483 | |||
484 | static inline void dump_regs (hrz_dev * dev) { | ||
485 | #ifdef DEBUG_HORIZON | ||
486 | PRINTD (DBG_REGS, "CONTROL 0: %#x", rd_regl (dev, CONTROL_0_REG)); | ||
487 | PRINTD (DBG_REGS, "RX CONFIG: %#x", rd_regw (dev, RX_CONFIG_OFF)); | ||
488 | PRINTD (DBG_REGS, "TX CONFIG: %#x", rd_regw (dev, TX_CONFIG_OFF)); | ||
489 | PRINTD (DBG_REGS, "TX STATUS: %#x", rd_regw (dev, TX_STATUS_OFF)); | ||
490 | PRINTD (DBG_REGS, "IRQ ENBLE: %#x", rd_regl (dev, INT_ENABLE_REG_OFF)); | ||
491 | PRINTD (DBG_REGS, "IRQ SORCE: %#x", rd_regl (dev, INT_SOURCE_REG_OFF)); | ||
492 | #else | ||
493 | (void) dev; | ||
494 | #endif | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | static inline void dump_framer (hrz_dev * dev) { | ||
499 | #ifdef DEBUG_HORIZON | ||
500 | unsigned int i; | ||
501 | PRINTDB (DBG_REGS, "framer registers:"); | ||
502 | for (i = 0; i < 0x10; ++i) | ||
503 | PRINTDM (DBG_REGS, " %02x", rd_framer (dev, i)); | ||
504 | PRINTDE (DBG_REGS,""); | ||
505 | #else | ||
506 | (void) dev; | ||
507 | #endif | ||
508 | return; | ||
509 | } | ||
510 | |||
511 | /********** VPI/VCI <-> (RX) channel conversions **********/ | ||
512 | |||
513 | /* RX channels are 10 bit integers, these fns are quite paranoid */ | ||
514 | |||
515 | static inline int channel_to_vpivci (const u16 channel, short * vpi, int * vci) { | ||
516 | unsigned short vci_bits = 10 - vpi_bits; | ||
517 | if ((channel & RX_CHANNEL_MASK) == channel) { | ||
518 | *vci = channel & ((~0)<<vci_bits); | ||
519 | *vpi = channel >> vci_bits; | ||
520 | return channel ? 0 : -EINVAL; | ||
521 | } | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | static inline int vpivci_to_channel (u16 * channel, const short vpi, const int vci) { | ||
526 | unsigned short vci_bits = 10 - vpi_bits; | ||
527 | if (0 <= vpi && vpi < 1<<vpi_bits && 0 <= vci && vci < 1<<vci_bits) { | ||
528 | *channel = vpi<<vci_bits | vci; | ||
529 | return *channel ? 0 : -EINVAL; | ||
530 | } | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
534 | /********** decode RX queue entries **********/ | ||
535 | |||
536 | static inline u16 rx_q_entry_to_length (u32 x) { | ||
537 | return x & RX_Q_ENTRY_LENGTH_MASK; | ||
538 | } | ||
539 | |||
540 | static inline u16 rx_q_entry_to_rx_channel (u32 x) { | ||
541 | return (x>>RX_Q_ENTRY_CHANNEL_SHIFT) & RX_CHANNEL_MASK; | ||
542 | } | ||
543 | |||
544 | /* Cell Transmit Rate Values | ||
545 | * | ||
546 | * the cell transmit rate (cells per sec) can be set to a variety of | ||
547 | * different values by specifying two parameters: a timer preload from | ||
548 | * 1 to 16 (stored as 0 to 15) and a clock divider (2 to the power of | ||
549 | * an exponent from 0 to 14; the special value 15 disables the timer). | ||
550 | * | ||
551 | * cellrate = baserate / (preload * 2^divider) | ||
552 | * | ||
553 | * The maximum cell rate that can be specified is therefore just the | ||
554 | * base rate. Halving the preload is equivalent to adding 1 to the | ||
555 | * divider and so values 1 to 8 of the preload are redundant except | ||
556 | * in the case of a maximal divider (14). | ||
557 | * | ||
558 | * Given a desired cell rate, an algorithm to determine the preload | ||
559 | * and divider is: | ||
560 | * | ||
561 | * a) x = baserate / cellrate, want p * 2^d = x (as far as possible) | ||
562 | * b) if x > 16 * 2^14 then set p = 16, d = 14 (min rate), done | ||
563 | * if x <= 16 then set p = x, d = 0 (high rates), done | ||
564 | * c) now have 16 < x <= 2^18, or 1 < x/16 <= 2^14 and we want to | ||
565 | * know n such that 2^(n-1) < x/16 <= 2^n, so slide a bit until | ||
566 | * we find the range (n will be between 1 and 14), set d = n | ||
567 | * d) Also have 8 < x/2^n <= 16, so set p nearest x/2^n | ||
568 | * | ||
569 | * The algorithm used below is a minor variant of the above. | ||
570 | * | ||
571 | * The base rate is derived from the oscillator frequency (Hz) using a | ||
572 | * fixed divider: | ||
573 | * | ||
574 | * baserate = freq / 32 in the case of some Unknown Card | ||
575 | * baserate = freq / 8 in the case of the Horizon 25 | ||
576 | * baserate = freq / 8 in the case of the Horizon Ultra 155 | ||
577 | * | ||
578 | * The Horizon cards have oscillators and base rates as follows: | ||
579 | * | ||
580 | * Card Oscillator Base Rate | ||
581 | * Unknown Card 33 MHz 1.03125 MHz (33 MHz = PCI freq) | ||
582 | * Horizon 25 32 MHz 4 MHz | ||
583 | * Horizon Ultra 155 40 MHz 5 MHz | ||
584 | * | ||
585 | * The following defines give the base rates in Hz. These were | ||
586 | * previously a factor of 100 larger, no doubt someone was using | ||
587 | * cps*100. | ||
588 | */ | ||
589 | |||
590 | #define BR_UKN 1031250l | ||
591 | #define BR_HRZ 4000000l | ||
592 | #define BR_ULT 5000000l | ||
593 | |||
594 | // d is an exponent | ||
595 | #define CR_MIND 0 | ||
596 | #define CR_MAXD 14 | ||
597 | |||
598 | // p ranges from 1 to a power of 2 | ||
599 | #define CR_MAXPEXP 4 | ||
600 | |||
601 | static int make_rate (const hrz_dev * dev, u32 c, rounding r, | ||
602 | u16 * bits, unsigned int * actual) | ||
603 | { | ||
604 | // note: rounding the rate down means rounding 'p' up | ||
605 | const unsigned long br = test_bit(ultra, &dev->flags) ? BR_ULT : BR_HRZ; | ||
606 | |||
607 | u32 div = CR_MIND; | ||
608 | u32 pre; | ||
609 | |||
610 | // br_exp and br_man are used to avoid overflowing (c*maxp*2^d) in | ||
611 | // the tests below. We could think harder about exact possibilities | ||
612 | // of failure... | ||
613 | |||
614 | unsigned long br_man = br; | ||
615 | unsigned int br_exp = 0; | ||
616 | |||
617 | PRINTD (DBG_QOS|DBG_FLOW, "make_rate b=%lu, c=%u, %s", br, c, | ||
618 | r == round_up ? "up" : r == round_down ? "down" : "nearest"); | ||
619 | |||
620 | // avoid div by zero | ||
621 | if (!c) { | ||
622 | PRINTD (DBG_QOS|DBG_ERR, "zero rate is not allowed!"); | ||
623 | return -EINVAL; | ||
624 | } | ||
625 | |||
626 | while (br_exp < CR_MAXPEXP + CR_MIND && (br_man % 2 == 0)) { | ||
627 | br_man = br_man >> 1; | ||
628 | ++br_exp; | ||
629 | } | ||
630 | // (br >>br_exp) <<br_exp == br and | ||
631 | // br_exp <= CR_MAXPEXP+CR_MIND | ||
632 | |||
633 | if (br_man <= (c << (CR_MAXPEXP+CR_MIND-br_exp))) { | ||
634 | // Equivalent to: B <= (c << (MAXPEXP+MIND)) | ||
635 | // take care of rounding | ||
636 | switch (r) { | ||
637 | case round_down: | ||
638 | pre = (br+(c<<div)-1)/(c<<div); | ||
639 | // but p must be non-zero | ||
640 | if (!pre) | ||
641 | pre = 1; | ||
642 | break; | ||
643 | case round_nearest: | ||
644 | pre = (br+(c<<div)/2)/(c<<div); | ||
645 | // but p must be non-zero | ||
646 | if (!pre) | ||
647 | pre = 1; | ||
648 | break; | ||
649 | default: /* round_up */ | ||
650 | pre = br/(c<<div); | ||
651 | // but p must be non-zero | ||
652 | if (!pre) | ||
653 | return -EINVAL; | ||
654 | } | ||
655 | PRINTD (DBG_QOS, "A: p=%u, d=%u", pre, div); | ||
656 | goto got_it; | ||
657 | } | ||
658 | |||
659 | // at this point we have | ||
660 | // d == MIND and (c << (MAXPEXP+MIND)) < B | ||
661 | while (div < CR_MAXD) { | ||
662 | div++; | ||
663 | if (br_man <= (c << (CR_MAXPEXP+div-br_exp))) { | ||
664 | // Equivalent to: B <= (c << (MAXPEXP+d)) | ||
665 | // c << (MAXPEXP+d-1) < B <= c << (MAXPEXP+d) | ||
666 | // 1 << (MAXPEXP-1) < B/2^d/c <= 1 << MAXPEXP | ||
667 | // MAXP/2 < B/c2^d <= MAXP | ||
668 | // take care of rounding | ||
669 | switch (r) { | ||
670 | case round_down: | ||
671 | pre = (br+(c<<div)-1)/(c<<div); | ||
672 | break; | ||
673 | case round_nearest: | ||
674 | pre = (br+(c<<div)/2)/(c<<div); | ||
675 | break; | ||
676 | default: /* round_up */ | ||
677 | pre = br/(c<<div); | ||
678 | } | ||
679 | PRINTD (DBG_QOS, "B: p=%u, d=%u", pre, div); | ||
680 | goto got_it; | ||
681 | } | ||
682 | } | ||
683 | // at this point we have | ||
684 | // d == MAXD and (c << (MAXPEXP+MAXD)) < B | ||
685 | // but we cannot go any higher | ||
686 | // take care of rounding | ||
687 | if (r == round_down) | ||
688 | return -EINVAL; | ||
689 | pre = 1 << CR_MAXPEXP; | ||
690 | PRINTD (DBG_QOS, "C: p=%u, d=%u", pre, div); | ||
691 | got_it: | ||
692 | // paranoia | ||
693 | if (div > CR_MAXD || (!pre) || pre > 1<<CR_MAXPEXP) { | ||
694 | PRINTD (DBG_QOS, "set_cr internal failure: d=%u p=%u", | ||
695 | div, pre); | ||
696 | return -EINVAL; | ||
697 | } else { | ||
698 | if (bits) | ||
699 | *bits = (div<<CLOCK_SELECT_SHIFT) | (pre-1); | ||
700 | if (actual) { | ||
701 | *actual = (br + (pre<<div) - 1) / (pre<<div); | ||
702 | PRINTD (DBG_QOS, "actual rate: %u", *actual); | ||
703 | } | ||
704 | return 0; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | static int make_rate_with_tolerance (const hrz_dev * dev, u32 c, rounding r, unsigned int tol, | ||
709 | u16 * bit_pattern, unsigned int * actual) { | ||
710 | unsigned int my_actual; | ||
711 | |||
712 | PRINTD (DBG_QOS|DBG_FLOW, "make_rate_with_tolerance c=%u, %s, tol=%u", | ||
713 | c, (r == round_up) ? "up" : (r == round_down) ? "down" : "nearest", tol); | ||
714 | |||
715 | if (!actual) | ||
716 | // actual rate is not returned | ||
717 | actual = &my_actual; | ||
718 | |||
719 | if (make_rate (dev, c, round_nearest, bit_pattern, actual)) | ||
720 | // should never happen as round_nearest always succeeds | ||
721 | return -1; | ||
722 | |||
723 | if (c - tol <= *actual && *actual <= c + tol) | ||
724 | // within tolerance | ||
725 | return 0; | ||
726 | else | ||
727 | // intolerant, try rounding instead | ||
728 | return make_rate (dev, c, r, bit_pattern, actual); | ||
729 | } | ||
730 | |||
731 | /********** Listen on a VC **********/ | ||
732 | |||
733 | static int hrz_open_rx (hrz_dev * dev, u16 channel) { | ||
734 | // is there any guarantee that we don't get two simulataneous | ||
735 | // identical calls of this function from different processes? yes | ||
736 | // rate_lock | ||
737 | unsigned long flags; | ||
738 | u32 channel_type; // u16? | ||
739 | |||
740 | u16 buf_ptr = RX_CHANNEL_IDLE; | ||
741 | |||
742 | rx_ch_desc * rx_desc = &memmap->rx_descs[channel]; | ||
743 | |||
744 | PRINTD (DBG_FLOW, "hrz_open_rx %x", channel); | ||
745 | |||
746 | spin_lock_irqsave (&dev->mem_lock, flags); | ||
747 | channel_type = rd_mem (dev, &rx_desc->wr_buf_type) & BUFFER_PTR_MASK; | ||
748 | spin_unlock_irqrestore (&dev->mem_lock, flags); | ||
749 | |||
750 | // very serious error, should never occur | ||
751 | if (channel_type != RX_CHANNEL_DISABLED) { | ||
752 | PRINTD (DBG_ERR|DBG_VCC, "RX channel for VC already open"); | ||
753 | return -EBUSY; // clean up? | ||
754 | } | ||
755 | |||
756 | // Give back spare buffer | ||
757 | if (dev->noof_spare_buffers) { | ||
758 | buf_ptr = dev->spare_buffers[--dev->noof_spare_buffers]; | ||
759 | PRINTD (DBG_VCC, "using a spare buffer: %u", buf_ptr); | ||
760 | // should never occur | ||
761 | if (buf_ptr == RX_CHANNEL_DISABLED || buf_ptr == RX_CHANNEL_IDLE) { | ||
762 | // but easy to recover from | ||
763 | PRINTD (DBG_ERR|DBG_VCC, "bad spare buffer pointer, using IDLE"); | ||
764 | buf_ptr = RX_CHANNEL_IDLE; | ||
765 | } | ||
766 | } else { | ||
767 | PRINTD (DBG_VCC, "using IDLE buffer pointer"); | ||
768 | } | ||
769 | |||
770 | // Channel is currently disabled so change its status to idle | ||
771 | |||
772 | // do we really need to save the flags again? | ||
773 | spin_lock_irqsave (&dev->mem_lock, flags); | ||
774 | |||
775 | wr_mem (dev, &rx_desc->wr_buf_type, | ||
776 | buf_ptr | CHANNEL_TYPE_AAL5 | FIRST_CELL_OF_AAL5_FRAME); | ||
777 | if (buf_ptr != RX_CHANNEL_IDLE) | ||
778 | wr_mem (dev, &rx_desc->rd_buf_type, buf_ptr); | ||
779 | |||
780 | spin_unlock_irqrestore (&dev->mem_lock, flags); | ||
781 | |||
782 | // rxer->rate = make_rate (qos->peak_cells); | ||
783 | |||
784 | PRINTD (DBG_FLOW, "hrz_open_rx ok"); | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | #if 0 | ||
790 | /********** change vc rate for a given vc **********/ | ||
791 | |||
792 | static void hrz_change_vc_qos (ATM_RXER * rxer, MAAL_QOS * qos) { | ||
793 | rxer->rate = make_rate (qos->peak_cells); | ||
794 | } | ||
795 | #endif | ||
796 | |||
797 | /********** free an skb (as per ATM device driver documentation) **********/ | ||
798 | |||
799 | static inline void hrz_kfree_skb (struct sk_buff * skb) { | ||
800 | if (ATM_SKB(skb)->vcc->pop) { | ||
801 | ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb); | ||
802 | } else { | ||
803 | dev_kfree_skb_any (skb); | ||
804 | } | ||
805 | } | ||
806 | |||
807 | /********** cancel listen on a VC **********/ | ||
808 | |||
809 | static void hrz_close_rx (hrz_dev * dev, u16 vc) { | ||
810 | unsigned long flags; | ||
811 | |||
812 | u32 value; | ||
813 | |||
814 | u32 r1, r2; | ||
815 | |||
816 | rx_ch_desc * rx_desc = &memmap->rx_descs[vc]; | ||
817 | |||
818 | int was_idle = 0; | ||
819 | |||
820 | spin_lock_irqsave (&dev->mem_lock, flags); | ||
821 | value = rd_mem (dev, &rx_desc->wr_buf_type) & BUFFER_PTR_MASK; | ||
822 | spin_unlock_irqrestore (&dev->mem_lock, flags); | ||
823 | |||
824 | if (value == RX_CHANNEL_DISABLED) { | ||
825 | // I suppose this could happen once we deal with _NONE traffic properly | ||
826 | PRINTD (DBG_VCC, "closing VC: RX channel %u already disabled", vc); | ||
827 | return; | ||
828 | } | ||
829 | if (value == RX_CHANNEL_IDLE) | ||
830 | was_idle = 1; | ||
831 | |||
832 | spin_lock_irqsave (&dev->mem_lock, flags); | ||
833 | |||
834 | for (;;) { | ||
835 | wr_mem (dev, &rx_desc->wr_buf_type, RX_CHANNEL_DISABLED); | ||
836 | |||
837 | if ((rd_mem (dev, &rx_desc->wr_buf_type) & BUFFER_PTR_MASK) == RX_CHANNEL_DISABLED) | ||
838 | break; | ||
839 | |||
840 | was_idle = 0; | ||
841 | } | ||
842 | |||
843 | if (was_idle) { | ||
844 | spin_unlock_irqrestore (&dev->mem_lock, flags); | ||
845 | return; | ||
846 | } | ||
847 | |||
848 | WAIT_FLUSH_RX_COMPLETE(dev); | ||
849 | |||
850 | // XXX Is this all really necessary? We can rely on the rx_data_av | ||
851 | // handler to discard frames that remain queued for delivery. If the | ||
852 | // worry is that immediately reopening the channel (perhaps by a | ||
853 | // different process) may cause some data to be mis-delivered then | ||
854 | // there may still be a simpler solution (such as busy-waiting on | ||
855 | // rx_busy once the channel is disabled or before a new one is | ||
856 | // opened - does this leave any holes?). Arguably setting up and | ||
857 | // tearing down the TX and RX halves of each virtual circuit could | ||
858 | // most safely be done within ?x_busy protected regions. | ||
859 | |||
860 | // OK, current changes are that Simon's marker is disabled and we DO | ||
861 | // look for NULL rxer elsewhere. The code here seems flush frames | ||
862 | // and then remember the last dead cell belonging to the channel | ||
863 | // just disabled - the cell gets relinked at the next vc_open. | ||
864 | // However, when all VCs are closed or only a few opened there are a | ||
865 | // handful of buffers that are unusable. | ||
866 | |||
867 | // Does anyone feel like documenting spare_buffers properly? | ||
868 | // Does anyone feel like fixing this in a nicer way? | ||
869 | |||
870 | // Flush any data which is left in the channel | ||
871 | for (;;) { | ||
872 | // Change the rx channel port to something different to the RX | ||
873 | // channel we are trying to close to force Horizon to flush the rx | ||
874 | // channel read and write pointers. | ||
875 | |||
876 | u16 other = vc^(RX_CHANS/2); | ||
877 | |||
878 | SELECT_RX_CHANNEL (dev, other); | ||
879 | WAIT_UPDATE_COMPLETE (dev); | ||
880 | |||
881 | r1 = rd_mem (dev, &rx_desc->rd_buf_type); | ||
882 | |||
883 | // Select this RX channel. Flush doesn't seem to work unless we | ||
884 | // select an RX channel before hand | ||
885 | |||
886 | SELECT_RX_CHANNEL (dev, vc); | ||
887 | WAIT_UPDATE_COMPLETE (dev); | ||
888 | |||
889 | // Attempt to flush a frame on this RX channel | ||
890 | |||
891 | FLUSH_RX_CHANNEL (dev, vc); | ||
892 | WAIT_FLUSH_RX_COMPLETE (dev); | ||
893 | |||
894 | // Force Horizon to flush rx channel read and write pointers as before | ||
895 | |||
896 | SELECT_RX_CHANNEL (dev, other); | ||
897 | WAIT_UPDATE_COMPLETE (dev); | ||
898 | |||
899 | r2 = rd_mem (dev, &rx_desc->rd_buf_type); | ||
900 | |||
901 | PRINTD (DBG_VCC|DBG_RX, "r1 = %u, r2 = %u", r1, r2); | ||
902 | |||
903 | if (r1 == r2) { | ||
904 | dev->spare_buffers[dev->noof_spare_buffers++] = (u16)r1; | ||
905 | break; | ||
906 | } | ||
907 | } | ||
908 | |||
909 | #if 0 | ||
910 | { | ||
911 | rx_q_entry * wr_ptr = &memmap->rx_q_entries[rd_regw (dev, RX_QUEUE_WR_PTR_OFF)]; | ||
912 | rx_q_entry * rd_ptr = dev->rx_q_entry; | ||
913 | |||
914 | PRINTD (DBG_VCC|DBG_RX, "rd_ptr = %u, wr_ptr = %u", rd_ptr, wr_ptr); | ||
915 | |||
916 | while (rd_ptr != wr_ptr) { | ||
917 | u32 x = rd_mem (dev, (HDW *) rd_ptr); | ||
918 | |||
919 | if (vc == rx_q_entry_to_rx_channel (x)) { | ||
920 | x |= SIMONS_DODGEY_MARKER; | ||
921 | |||
922 | PRINTD (DBG_RX|DBG_VCC|DBG_WARN, "marking a frame as dodgey"); | ||
923 | |||
924 | wr_mem (dev, (HDW *) rd_ptr, x); | ||
925 | } | ||
926 | |||
927 | if (rd_ptr == dev->rx_q_wrap) | ||
928 | rd_ptr = dev->rx_q_reset; | ||
929 | else | ||
930 | rd_ptr++; | ||
931 | } | ||
932 | } | ||
933 | #endif | ||
934 | |||
935 | spin_unlock_irqrestore (&dev->mem_lock, flags); | ||
936 | |||
937 | return; | ||
938 | } | ||
939 | |||
940 | /********** schedule RX transfers **********/ | ||
941 | |||
942 | // Note on tail recursion: a GCC developer said that it is not likely | ||
943 | // to be fixed soon, so do not define TAILRECUSRIONWORKS unless you | ||
944 | // are sure it does as you may otherwise overflow the kernel stack. | ||
945 | |||
946 | // giving this fn a return value would help GCC, alledgedly | ||
947 | |||
948 | static void rx_schedule (hrz_dev * dev, int irq) { | ||
949 | unsigned int rx_bytes; | ||
950 | |||
951 | int pio_instead = 0; | ||
952 | #ifndef TAILRECURSIONWORKS | ||
953 | pio_instead = 1; | ||
954 | while (pio_instead) { | ||
955 | #endif | ||
956 | // bytes waiting for RX transfer | ||
957 | rx_bytes = dev->rx_bytes; | ||
958 | |||
959 | #if 0 | ||
960 | spin_count = 0; | ||
961 | while (rd_regl (dev, MASTER_RX_COUNT_REG_OFF)) { | ||
962 | PRINTD (DBG_RX|DBG_WARN, "RX error: other PCI Bus Master RX still in progress!"); | ||
963 | if (++spin_count > 10) { | ||
964 | PRINTD (DBG_RX|DBG_ERR, "spun out waiting PCI Bus Master RX completion"); | ||
965 | wr_regl (dev, MASTER_RX_COUNT_REG_OFF, 0); | ||
966 | clear_bit (rx_busy, &dev->flags); | ||
967 | hrz_kfree_skb (dev->rx_skb); | ||
968 | return; | ||
969 | } | ||
970 | } | ||
971 | #endif | ||
972 | |||
973 | // this code follows the TX code but (at the moment) there is only | ||
974 | // one region - the skb itself. I don't know if this will change, | ||
975 | // but it doesn't hurt to have the code here, disabled. | ||
976 | |||
977 | if (rx_bytes) { | ||
978 | // start next transfer within same region | ||
979 | if (rx_bytes <= MAX_PIO_COUNT) { | ||
980 | PRINTD (DBG_RX|DBG_BUS, "(pio)"); | ||
981 | pio_instead = 1; | ||
982 | } | ||
983 | if (rx_bytes <= MAX_TRANSFER_COUNT) { | ||
984 | PRINTD (DBG_RX|DBG_BUS, "(simple or last multi)"); | ||
985 | dev->rx_bytes = 0; | ||
986 | } else { | ||
987 | PRINTD (DBG_RX|DBG_BUS, "(continuing multi)"); | ||
988 | dev->rx_bytes = rx_bytes - MAX_TRANSFER_COUNT; | ||
989 | rx_bytes = MAX_TRANSFER_COUNT; | ||
990 | } | ||
991 | } else { | ||
992 | // rx_bytes == 0 -- we're between regions | ||
993 | // regions remaining to transfer | ||
994 | #if 0 | ||
995 | unsigned int rx_regions = dev->rx_regions; | ||
996 | #else | ||
997 | unsigned int rx_regions = 0; | ||
998 | #endif | ||
999 | |||
1000 | if (rx_regions) { | ||
1001 | #if 0 | ||
1002 | // start a new region | ||
1003 | dev->rx_addr = dev->rx_iovec->iov_base; | ||
1004 | rx_bytes = dev->rx_iovec->iov_len; | ||
1005 | ++dev->rx_iovec; | ||
1006 | dev->rx_regions = rx_regions - 1; | ||
1007 | |||
1008 | if (rx_bytes <= MAX_PIO_COUNT) { | ||
1009 | PRINTD (DBG_RX|DBG_BUS, "(pio)"); | ||
1010 | pio_instead = 1; | ||
1011 | } | ||
1012 | if (rx_bytes <= MAX_TRANSFER_COUNT) { | ||
1013 | PRINTD (DBG_RX|DBG_BUS, "(full region)"); | ||
1014 | dev->rx_bytes = 0; | ||
1015 | } else { | ||
1016 | PRINTD (DBG_RX|DBG_BUS, "(start multi region)"); | ||
1017 | dev->rx_bytes = rx_bytes - MAX_TRANSFER_COUNT; | ||
1018 | rx_bytes = MAX_TRANSFER_COUNT; | ||
1019 | } | ||
1020 | #endif | ||
1021 | } else { | ||
1022 | // rx_regions == 0 | ||
1023 | // that's all folks - end of frame | ||
1024 | struct sk_buff * skb = dev->rx_skb; | ||
1025 | // dev->rx_iovec = 0; | ||
1026 | |||
1027 | FLUSH_RX_CHANNEL (dev, dev->rx_channel); | ||
1028 | |||
1029 | dump_skb ("<<<", dev->rx_channel, skb); | ||
1030 | |||
1031 | PRINTD (DBG_RX|DBG_SKB, "push %p %u", skb->data, skb->len); | ||
1032 | |||
1033 | { | ||
1034 | struct atm_vcc * vcc = ATM_SKB(skb)->vcc; | ||
1035 | // VC layer stats | ||
1036 | atomic_inc(&vcc->stats->rx); | ||
1037 | do_gettimeofday(&skb->stamp); | ||
1038 | // end of our responsability | ||
1039 | vcc->push (vcc, skb); | ||
1040 | } | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | // note: writing RX_COUNT clears any interrupt condition | ||
1045 | if (rx_bytes) { | ||
1046 | if (pio_instead) { | ||
1047 | if (irq) | ||
1048 | wr_regl (dev, MASTER_RX_COUNT_REG_OFF, 0); | ||
1049 | rds_regb (dev, DATA_PORT_OFF, dev->rx_addr, rx_bytes); | ||
1050 | } else { | ||
1051 | wr_regl (dev, MASTER_RX_ADDR_REG_OFF, virt_to_bus (dev->rx_addr)); | ||
1052 | wr_regl (dev, MASTER_RX_COUNT_REG_OFF, rx_bytes); | ||
1053 | } | ||
1054 | dev->rx_addr += rx_bytes; | ||
1055 | } else { | ||
1056 | if (irq) | ||
1057 | wr_regl (dev, MASTER_RX_COUNT_REG_OFF, 0); | ||
1058 | // allow another RX thread to start | ||
1059 | YELLOW_LED_ON(dev); | ||
1060 | clear_bit (rx_busy, &dev->flags); | ||
1061 | PRINTD (DBG_RX, "cleared rx_busy for dev %p", dev); | ||
1062 | } | ||
1063 | |||
1064 | #ifdef TAILRECURSIONWORKS | ||
1065 | // and we all bless optimised tail calls | ||
1066 | if (pio_instead) | ||
1067 | return rx_schedule (dev, 0); | ||
1068 | return; | ||
1069 | #else | ||
1070 | // grrrrrrr! | ||
1071 | irq = 0; | ||
1072 | } | ||
1073 | return; | ||
1074 | #endif | ||
1075 | } | ||
1076 | |||
1077 | /********** handle RX bus master complete events **********/ | ||
1078 | |||
1079 | static inline void rx_bus_master_complete_handler (hrz_dev * dev) { | ||
1080 | if (test_bit (rx_busy, &dev->flags)) { | ||
1081 | rx_schedule (dev, 1); | ||
1082 | } else { | ||
1083 | PRINTD (DBG_RX|DBG_ERR, "unexpected RX bus master completion"); | ||
1084 | // clear interrupt condition on adapter | ||
1085 | wr_regl (dev, MASTER_RX_COUNT_REG_OFF, 0); | ||
1086 | } | ||
1087 | return; | ||
1088 | } | ||
1089 | |||
1090 | /********** (queue to) become the next TX thread **********/ | ||
1091 | |||
1092 | static inline int tx_hold (hrz_dev * dev) { | ||
1093 | PRINTD (DBG_TX, "sleeping at tx lock %p %lu", dev, dev->flags); | ||
1094 | wait_event_interruptible(dev->tx_queue, (!test_and_set_bit(tx_busy, &dev->flags))); | ||
1095 | PRINTD (DBG_TX, "woken at tx lock %p %lu", dev, dev->flags); | ||
1096 | if (signal_pending (current)) | ||
1097 | return -1; | ||
1098 | PRINTD (DBG_TX, "set tx_busy for dev %p", dev); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | /********** allow another TX thread to start **********/ | ||
1103 | |||
1104 | static inline void tx_release (hrz_dev * dev) { | ||
1105 | clear_bit (tx_busy, &dev->flags); | ||
1106 | PRINTD (DBG_TX, "cleared tx_busy for dev %p", dev); | ||
1107 | wake_up_interruptible (&dev->tx_queue); | ||
1108 | } | ||
1109 | |||
1110 | /********** schedule TX transfers **********/ | ||
1111 | |||
1112 | static void tx_schedule (hrz_dev * const dev, int irq) { | ||
1113 | unsigned int tx_bytes; | ||
1114 | |||
1115 | int append_desc = 0; | ||
1116 | |||
1117 | int pio_instead = 0; | ||
1118 | #ifndef TAILRECURSIONWORKS | ||
1119 | pio_instead = 1; | ||
1120 | while (pio_instead) { | ||
1121 | #endif | ||
1122 | // bytes in current region waiting for TX transfer | ||
1123 | tx_bytes = dev->tx_bytes; | ||
1124 | |||
1125 | #if 0 | ||
1126 | spin_count = 0; | ||
1127 | while (rd_regl (dev, MASTER_TX_COUNT_REG_OFF)) { | ||
1128 | PRINTD (DBG_TX|DBG_WARN, "TX error: other PCI Bus Master TX still in progress!"); | ||
1129 | if (++spin_count > 10) { | ||
1130 | PRINTD (DBG_TX|DBG_ERR, "spun out waiting PCI Bus Master TX completion"); | ||
1131 | wr_regl (dev, MASTER_TX_COUNT_REG_OFF, 0); | ||
1132 | tx_release (dev); | ||
1133 | hrz_kfree_skb (dev->tx_skb); | ||
1134 | return; | ||
1135 | } | ||
1136 | } | ||
1137 | #endif | ||
1138 | |||
1139 | if (tx_bytes) { | ||
1140 | // start next transfer within same region | ||
1141 | if (!test_bit (ultra, &dev->flags) || tx_bytes <= MAX_PIO_COUNT) { | ||
1142 | PRINTD (DBG_TX|DBG_BUS, "(pio)"); | ||
1143 | pio_instead = 1; | ||
1144 | } | ||
1145 | if (tx_bytes <= MAX_TRANSFER_COUNT) { | ||
1146 | PRINTD (DBG_TX|DBG_BUS, "(simple or last multi)"); | ||
1147 | if (!dev->tx_iovec) { | ||
1148 | // end of last region | ||
1149 | append_desc = 1; | ||
1150 | } | ||
1151 | dev->tx_bytes = 0; | ||
1152 | } else { | ||
1153 | PRINTD (DBG_TX|DBG_BUS, "(continuing multi)"); | ||
1154 | dev->tx_bytes = tx_bytes - MAX_TRANSFER_COUNT; | ||
1155 | tx_bytes = MAX_TRANSFER_COUNT; | ||
1156 | } | ||
1157 | } else { | ||
1158 | // tx_bytes == 0 -- we're between regions | ||
1159 | // regions remaining to transfer | ||
1160 | unsigned int tx_regions = dev->tx_regions; | ||
1161 | |||
1162 | if (tx_regions) { | ||
1163 | // start a new region | ||
1164 | dev->tx_addr = dev->tx_iovec->iov_base; | ||
1165 | tx_bytes = dev->tx_iovec->iov_len; | ||
1166 | ++dev->tx_iovec; | ||
1167 | dev->tx_regions = tx_regions - 1; | ||
1168 | |||
1169 | if (!test_bit (ultra, &dev->flags) || tx_bytes <= MAX_PIO_COUNT) { | ||
1170 | PRINTD (DBG_TX|DBG_BUS, "(pio)"); | ||
1171 | pio_instead = 1; | ||
1172 | } | ||
1173 | if (tx_bytes <= MAX_TRANSFER_COUNT) { | ||
1174 | PRINTD (DBG_TX|DBG_BUS, "(full region)"); | ||
1175 | dev->tx_bytes = 0; | ||
1176 | } else { | ||
1177 | PRINTD (DBG_TX|DBG_BUS, "(start multi region)"); | ||
1178 | dev->tx_bytes = tx_bytes - MAX_TRANSFER_COUNT; | ||
1179 | tx_bytes = MAX_TRANSFER_COUNT; | ||
1180 | } | ||
1181 | } else { | ||
1182 | // tx_regions == 0 | ||
1183 | // that's all folks - end of frame | ||
1184 | struct sk_buff * skb = dev->tx_skb; | ||
1185 | dev->tx_iovec = NULL; | ||
1186 | |||
1187 | // VC layer stats | ||
1188 | atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); | ||
1189 | |||
1190 | // free the skb | ||
1191 | hrz_kfree_skb (skb); | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | // note: writing TX_COUNT clears any interrupt condition | ||
1196 | if (tx_bytes) { | ||
1197 | if (pio_instead) { | ||
1198 | if (irq) | ||
1199 | wr_regl (dev, MASTER_TX_COUNT_REG_OFF, 0); | ||
1200 | wrs_regb (dev, DATA_PORT_OFF, dev->tx_addr, tx_bytes); | ||
1201 | if (append_desc) | ||
1202 | wr_regl (dev, TX_DESCRIPTOR_PORT_OFF, cpu_to_be32 (dev->tx_skb->len)); | ||
1203 | } else { | ||
1204 | wr_regl (dev, MASTER_TX_ADDR_REG_OFF, virt_to_bus (dev->tx_addr)); | ||
1205 | if (append_desc) | ||
1206 | wr_regl (dev, TX_DESCRIPTOR_REG_OFF, cpu_to_be32 (dev->tx_skb->len)); | ||
1207 | wr_regl (dev, MASTER_TX_COUNT_REG_OFF, | ||
1208 | append_desc | ||
1209 | ? tx_bytes | MASTER_TX_AUTO_APPEND_DESC | ||
1210 | : tx_bytes); | ||
1211 | } | ||
1212 | dev->tx_addr += tx_bytes; | ||
1213 | } else { | ||
1214 | if (irq) | ||
1215 | wr_regl (dev, MASTER_TX_COUNT_REG_OFF, 0); | ||
1216 | YELLOW_LED_ON(dev); | ||
1217 | tx_release (dev); | ||
1218 | } | ||
1219 | |||
1220 | #ifdef TAILRECURSIONWORKS | ||
1221 | // and we all bless optimised tail calls | ||
1222 | if (pio_instead) | ||
1223 | return tx_schedule (dev, 0); | ||
1224 | return; | ||
1225 | #else | ||
1226 | // grrrrrrr! | ||
1227 | irq = 0; | ||
1228 | } | ||
1229 | return; | ||
1230 | #endif | ||
1231 | } | ||
1232 | |||
1233 | /********** handle TX bus master complete events **********/ | ||
1234 | |||
1235 | static inline void tx_bus_master_complete_handler (hrz_dev * dev) { | ||
1236 | if (test_bit (tx_busy, &dev->flags)) { | ||
1237 | tx_schedule (dev, 1); | ||
1238 | } else { | ||
1239 | PRINTD (DBG_TX|DBG_ERR, "unexpected TX bus master completion"); | ||
1240 | // clear interrupt condition on adapter | ||
1241 | wr_regl (dev, MASTER_TX_COUNT_REG_OFF, 0); | ||
1242 | } | ||
1243 | return; | ||
1244 | } | ||
1245 | |||
1246 | /********** move RX Q pointer to next item in circular buffer **********/ | ||
1247 | |||
1248 | // called only from IRQ sub-handler | ||
1249 | static inline u32 rx_queue_entry_next (hrz_dev * dev) { | ||
1250 | u32 rx_queue_entry; | ||
1251 | spin_lock (&dev->mem_lock); | ||
1252 | rx_queue_entry = rd_mem (dev, &dev->rx_q_entry->entry); | ||
1253 | if (dev->rx_q_entry == dev->rx_q_wrap) | ||
1254 | dev->rx_q_entry = dev->rx_q_reset; | ||
1255 | else | ||
1256 | dev->rx_q_entry++; | ||
1257 | wr_regw (dev, RX_QUEUE_RD_PTR_OFF, dev->rx_q_entry - dev->rx_q_reset); | ||
1258 | spin_unlock (&dev->mem_lock); | ||
1259 | return rx_queue_entry; | ||
1260 | } | ||
1261 | |||
1262 | /********** handle RX disabled by device **********/ | ||
1263 | |||
1264 | static inline void rx_disabled_handler (hrz_dev * dev) { | ||
1265 | wr_regw (dev, RX_CONFIG_OFF, rd_regw (dev, RX_CONFIG_OFF) | RX_ENABLE); | ||
1266 | // count me please | ||
1267 | PRINTK (KERN_WARNING, "RX was disabled!"); | ||
1268 | } | ||
1269 | |||
1270 | /********** handle RX data received by device **********/ | ||
1271 | |||
1272 | // called from IRQ handler | ||
1273 | static inline void rx_data_av_handler (hrz_dev * dev) { | ||
1274 | u32 rx_queue_entry; | ||
1275 | u32 rx_queue_entry_flags; | ||
1276 | u16 rx_len; | ||
1277 | u16 rx_channel; | ||
1278 | |||
1279 | PRINTD (DBG_FLOW, "hrz_data_av_handler"); | ||
1280 | |||
1281 | // try to grab rx lock (not possible during RX bus mastering) | ||
1282 | if (test_and_set_bit (rx_busy, &dev->flags)) { | ||
1283 | PRINTD (DBG_RX, "locked out of rx lock"); | ||
1284 | return; | ||
1285 | } | ||
1286 | PRINTD (DBG_RX, "set rx_busy for dev %p", dev); | ||
1287 | // lock is cleared if we fail now, o/w after bus master completion | ||
1288 | |||
1289 | YELLOW_LED_OFF(dev); | ||
1290 | |||
1291 | rx_queue_entry = rx_queue_entry_next (dev); | ||
1292 | |||
1293 | rx_len = rx_q_entry_to_length (rx_queue_entry); | ||
1294 | rx_channel = rx_q_entry_to_rx_channel (rx_queue_entry); | ||
1295 | |||
1296 | WAIT_FLUSH_RX_COMPLETE (dev); | ||
1297 | |||
1298 | SELECT_RX_CHANNEL (dev, rx_channel); | ||
1299 | |||
1300 | PRINTD (DBG_RX, "rx_queue_entry is: %#x", rx_queue_entry); | ||
1301 | rx_queue_entry_flags = rx_queue_entry & (RX_CRC_32_OK|RX_COMPLETE_FRAME|SIMONS_DODGEY_MARKER); | ||
1302 | |||
1303 | if (!rx_len) { | ||
1304 | // (at least) bus-mastering breaks if we try to handle a | ||
1305 | // zero-length frame, besides AAL5 does not support them | ||
1306 | PRINTK (KERN_ERR, "zero-length frame!"); | ||
1307 | rx_queue_entry_flags &= ~RX_COMPLETE_FRAME; | ||
1308 | } | ||
1309 | |||
1310 | if (rx_queue_entry_flags & SIMONS_DODGEY_MARKER) { | ||
1311 | PRINTD (DBG_RX|DBG_ERR, "Simon's marker detected!"); | ||
1312 | } | ||
1313 | if (rx_queue_entry_flags == (RX_CRC_32_OK | RX_COMPLETE_FRAME)) { | ||
1314 | struct atm_vcc * atm_vcc; | ||
1315 | |||
1316 | PRINTD (DBG_RX, "got a frame on rx_channel %x len %u", rx_channel, rx_len); | ||
1317 | |||
1318 | atm_vcc = dev->rxer[rx_channel]; | ||
1319 | // if no vcc is assigned to this channel, we should drop the frame | ||
1320 | // (is this what SIMONS etc. was trying to achieve?) | ||
1321 | |||
1322 | if (atm_vcc) { | ||
1323 | |||
1324 | if (atm_vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
1325 | |||
1326 | if (rx_len <= atm_vcc->qos.rxtp.max_sdu) { | ||
1327 | |||
1328 | struct sk_buff * skb = atm_alloc_charge (atm_vcc, rx_len, GFP_ATOMIC); | ||
1329 | if (skb) { | ||
1330 | // remember this so we can push it later | ||
1331 | dev->rx_skb = skb; | ||
1332 | // remember this so we can flush it later | ||
1333 | dev->rx_channel = rx_channel; | ||
1334 | |||
1335 | // prepare socket buffer | ||
1336 | skb_put (skb, rx_len); | ||
1337 | ATM_SKB(skb)->vcc = atm_vcc; | ||
1338 | |||
1339 | // simple transfer | ||
1340 | // dev->rx_regions = 0; | ||
1341 | // dev->rx_iovec = 0; | ||
1342 | dev->rx_bytes = rx_len; | ||
1343 | dev->rx_addr = skb->data; | ||
1344 | PRINTD (DBG_RX, "RX start simple transfer (addr %p, len %d)", | ||
1345 | skb->data, rx_len); | ||
1346 | |||
1347 | // do the business | ||
1348 | rx_schedule (dev, 0); | ||
1349 | return; | ||
1350 | |||
1351 | } else { | ||
1352 | PRINTD (DBG_SKB|DBG_WARN, "failed to get skb"); | ||
1353 | } | ||
1354 | |||
1355 | } else { | ||
1356 | PRINTK (KERN_INFO, "frame received on TX-only VC %x", rx_channel); | ||
1357 | // do we count this? | ||
1358 | } | ||
1359 | |||
1360 | } else { | ||
1361 | PRINTK (KERN_WARNING, "dropped over-size frame"); | ||
1362 | // do we count this? | ||
1363 | } | ||
1364 | |||
1365 | } else { | ||
1366 | PRINTD (DBG_WARN|DBG_VCC|DBG_RX, "no VCC for this frame (VC closed)"); | ||
1367 | // do we count this? | ||
1368 | } | ||
1369 | |||
1370 | } else { | ||
1371 | // Wait update complete ? SPONG | ||
1372 | } | ||
1373 | |||
1374 | // RX was aborted | ||
1375 | YELLOW_LED_ON(dev); | ||
1376 | |||
1377 | FLUSH_RX_CHANNEL (dev,rx_channel); | ||
1378 | clear_bit (rx_busy, &dev->flags); | ||
1379 | |||
1380 | return; | ||
1381 | } | ||
1382 | |||
1383 | /********** interrupt handler **********/ | ||
1384 | |||
1385 | static irqreturn_t interrupt_handler(int irq, void *dev_id, | ||
1386 | struct pt_regs *pt_regs) { | ||
1387 | hrz_dev * dev = (hrz_dev *) dev_id; | ||
1388 | u32 int_source; | ||
1389 | unsigned int irq_ok; | ||
1390 | (void) pt_regs; | ||
1391 | |||
1392 | PRINTD (DBG_FLOW, "interrupt_handler: %p", dev_id); | ||
1393 | |||
1394 | if (!dev_id) { | ||
1395 | PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq); | ||
1396 | return IRQ_NONE; | ||
1397 | } | ||
1398 | if (irq != dev->irq) { | ||
1399 | PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq); | ||
1400 | return IRQ_NONE; | ||
1401 | } | ||
1402 | |||
1403 | // definitely for us | ||
1404 | irq_ok = 0; | ||
1405 | while ((int_source = rd_regl (dev, INT_SOURCE_REG_OFF) | ||
1406 | & INTERESTING_INTERRUPTS)) { | ||
1407 | // In the interests of fairness, the (inline) handlers below are | ||
1408 | // called in sequence and without immediate return to the head of | ||
1409 | // the while loop. This is only of issue for slow hosts (or when | ||
1410 | // debugging messages are on). Really slow hosts may find a fast | ||
1411 | // sender keeps them permanently in the IRQ handler. :( | ||
1412 | |||
1413 | // (only an issue for slow hosts) RX completion goes before | ||
1414 | // rx_data_av as the former implies rx_busy and so the latter | ||
1415 | // would just abort. If it reschedules another transfer | ||
1416 | // (continuing the same frame) then it will not clear rx_busy. | ||
1417 | |||
1418 | // (only an issue for slow hosts) TX completion goes before RX | ||
1419 | // data available as it is a much shorter routine - there is the | ||
1420 | // chance that any further transfers it schedules will be complete | ||
1421 | // by the time of the return to the head of the while loop | ||
1422 | |||
1423 | if (int_source & RX_BUS_MASTER_COMPLETE) { | ||
1424 | ++irq_ok; | ||
1425 | PRINTD (DBG_IRQ|DBG_BUS|DBG_RX, "rx_bus_master_complete asserted"); | ||
1426 | rx_bus_master_complete_handler (dev); | ||
1427 | } | ||
1428 | if (int_source & TX_BUS_MASTER_COMPLETE) { | ||
1429 | ++irq_ok; | ||
1430 | PRINTD (DBG_IRQ|DBG_BUS|DBG_TX, "tx_bus_master_complete asserted"); | ||
1431 | tx_bus_master_complete_handler (dev); | ||
1432 | } | ||
1433 | if (int_source & RX_DATA_AV) { | ||
1434 | ++irq_ok; | ||
1435 | PRINTD (DBG_IRQ|DBG_RX, "rx_data_av asserted"); | ||
1436 | rx_data_av_handler (dev); | ||
1437 | } | ||
1438 | } | ||
1439 | if (irq_ok) { | ||
1440 | PRINTD (DBG_IRQ, "work done: %u", irq_ok); | ||
1441 | } else { | ||
1442 | PRINTD (DBG_IRQ|DBG_WARN, "spurious interrupt source: %#x", int_source); | ||
1443 | } | ||
1444 | |||
1445 | PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler done: %p", dev_id); | ||
1446 | if (irq_ok) | ||
1447 | return IRQ_HANDLED; | ||
1448 | return IRQ_NONE; | ||
1449 | } | ||
1450 | |||
1451 | /********** housekeeping **********/ | ||
1452 | |||
1453 | static void do_housekeeping (unsigned long arg) { | ||
1454 | // just stats at the moment | ||
1455 | hrz_dev * dev = (hrz_dev *) arg; | ||
1456 | |||
1457 | // collect device-specific (not driver/atm-linux) stats here | ||
1458 | dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF); | ||
1459 | dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF); | ||
1460 | dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF); | ||
1461 | dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF); | ||
1462 | |||
1463 | mod_timer (&dev->housekeeping, jiffies + HZ/10); | ||
1464 | |||
1465 | return; | ||
1466 | } | ||
1467 | |||
1468 | /********** find an idle channel for TX and set it up **********/ | ||
1469 | |||
1470 | // called with tx_busy set | ||
1471 | static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) { | ||
1472 | unsigned short idle_channels; | ||
1473 | short tx_channel = -1; | ||
1474 | unsigned int spin_count; | ||
1475 | PRINTD (DBG_FLOW|DBG_TX, "setup_idle_tx_channel %p", dev); | ||
1476 | |||
1477 | // better would be to fail immediately, the caller can then decide whether | ||
1478 | // to wait or drop (depending on whether this is UBR etc.) | ||
1479 | spin_count = 0; | ||
1480 | while (!(idle_channels = rd_regw (dev, TX_STATUS_OFF) & IDLE_CHANNELS_MASK)) { | ||
1481 | PRINTD (DBG_TX|DBG_WARN, "waiting for idle TX channel"); | ||
1482 | // delay a bit here | ||
1483 | if (++spin_count > 100) { | ||
1484 | PRINTD (DBG_TX|DBG_ERR, "spun out waiting for idle TX channel"); | ||
1485 | return -EBUSY; | ||
1486 | } | ||
1487 | } | ||
1488 | |||
1489 | // got an idle channel | ||
1490 | { | ||
1491 | // tx_idle ensures we look for idle channels in RR order | ||
1492 | int chan = dev->tx_idle; | ||
1493 | |||
1494 | int keep_going = 1; | ||
1495 | while (keep_going) { | ||
1496 | if (idle_channels & (1<<chan)) { | ||
1497 | tx_channel = chan; | ||
1498 | keep_going = 0; | ||
1499 | } | ||
1500 | ++chan; | ||
1501 | if (chan == TX_CHANS) | ||
1502 | chan = 0; | ||
1503 | } | ||
1504 | |||
1505 | dev->tx_idle = chan; | ||
1506 | } | ||
1507 | |||
1508 | // set up the channel we found | ||
1509 | { | ||
1510 | // Initialise the cell header in the transmit channel descriptor | ||
1511 | // a.k.a. prepare the channel and remember that we have done so. | ||
1512 | |||
1513 | tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel]; | ||
1514 | u16 rd_ptr; | ||
1515 | u16 wr_ptr; | ||
1516 | u16 channel = vcc->channel; | ||
1517 | |||
1518 | unsigned long flags; | ||
1519 | spin_lock_irqsave (&dev->mem_lock, flags); | ||
1520 | |||
1521 | // Update the transmit channel record. | ||
1522 | dev->tx_channel_record[tx_channel] = channel; | ||
1523 | |||
1524 | // xBR channel | ||
1525 | update_tx_channel_config (dev, tx_channel, RATE_TYPE_ACCESS, | ||
1526 | vcc->tx_xbr_bits); | ||
1527 | |||
1528 | // Update the PCR counter preload value etc. | ||
1529 | update_tx_channel_config (dev, tx_channel, PCR_TIMER_ACCESS, | ||
1530 | vcc->tx_pcr_bits); | ||
1531 | |||
1532 | #if 0 | ||
1533 | if (vcc->tx_xbr_bits == VBR_RATE_TYPE) { | ||
1534 | // SCR timer | ||
1535 | update_tx_channel_config (dev, tx_channel, SCR_TIMER_ACCESS, | ||
1536 | vcc->tx_scr_bits); | ||
1537 | |||
1538 | // Bucket size... | ||
1539 | update_tx_channel_config (dev, tx_channel, BUCKET_CAPACITY_ACCESS, | ||
1540 | vcc->tx_bucket_bits); | ||
1541 | |||
1542 | // ... and fullness | ||
1543 | update_tx_channel_config (dev, tx_channel, BUCKET_FULLNESS_ACCESS, | ||
1544 | vcc->tx_bucket_bits); | ||
1545 | } | ||
1546 | #endif | ||
1547 | |||
1548 | // Initialise the read and write buffer pointers | ||
1549 | rd_ptr = rd_mem (dev, &tx_desc->rd_buf_type) & BUFFER_PTR_MASK; | ||
1550 | wr_ptr = rd_mem (dev, &tx_desc->wr_buf_type) & BUFFER_PTR_MASK; | ||
1551 | |||
1552 | // idle TX channels should have identical pointers | ||
1553 | if (rd_ptr != wr_ptr) { | ||
1554 | PRINTD (DBG_TX|DBG_ERR, "TX buffer pointers are broken!"); | ||
1555 | // spin_unlock... return -E... | ||
1556 | // I wonder if gcc would get rid of one of the pointer aliases | ||
1557 | } | ||
1558 | PRINTD (DBG_TX, "TX buffer pointers are: rd %x, wr %x.", | ||
1559 | rd_ptr, wr_ptr); | ||
1560 | |||
1561 | switch (vcc->aal) { | ||
1562 | case aal0: | ||
1563 | PRINTD (DBG_QOS|DBG_TX, "tx_channel: aal0"); | ||
1564 | rd_ptr |= CHANNEL_TYPE_RAW_CELLS; | ||
1565 | wr_ptr |= CHANNEL_TYPE_RAW_CELLS; | ||
1566 | break; | ||
1567 | case aal34: | ||
1568 | PRINTD (DBG_QOS|DBG_TX, "tx_channel: aal34"); | ||
1569 | rd_ptr |= CHANNEL_TYPE_AAL3_4; | ||
1570 | wr_ptr |= CHANNEL_TYPE_AAL3_4; | ||
1571 | break; | ||
1572 | case aal5: | ||
1573 | rd_ptr |= CHANNEL_TYPE_AAL5; | ||
1574 | wr_ptr |= CHANNEL_TYPE_AAL5; | ||
1575 | // Initialise the CRC | ||
1576 | wr_mem (dev, &tx_desc->partial_crc, INITIAL_CRC); | ||
1577 | break; | ||
1578 | } | ||
1579 | |||
1580 | wr_mem (dev, &tx_desc->rd_buf_type, rd_ptr); | ||
1581 | wr_mem (dev, &tx_desc->wr_buf_type, wr_ptr); | ||
1582 | |||
1583 | // Write the Cell Header | ||
1584 | // Payload Type, CLP and GFC would go here if non-zero | ||
1585 | wr_mem (dev, &tx_desc->cell_header, channel); | ||
1586 | |||
1587 | spin_unlock_irqrestore (&dev->mem_lock, flags); | ||
1588 | } | ||
1589 | |||
1590 | return tx_channel; | ||
1591 | } | ||
1592 | |||
1593 | /********** send a frame **********/ | ||
1594 | |||
1595 | static int hrz_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { | ||
1596 | unsigned int spin_count; | ||
1597 | int free_buffers; | ||
1598 | hrz_dev * dev = HRZ_DEV(atm_vcc->dev); | ||
1599 | hrz_vcc * vcc = HRZ_VCC(atm_vcc); | ||
1600 | u16 channel = vcc->channel; | ||
1601 | |||
1602 | u32 buffers_required; | ||
1603 | |||
1604 | /* signed for error return */ | ||
1605 | short tx_channel; | ||
1606 | |||
1607 | PRINTD (DBG_FLOW|DBG_TX, "hrz_send vc %x data %p len %u", | ||
1608 | channel, skb->data, skb->len); | ||
1609 | |||
1610 | dump_skb (">>>", channel, skb); | ||
1611 | |||
1612 | if (atm_vcc->qos.txtp.traffic_class == ATM_NONE) { | ||
1613 | PRINTK (KERN_ERR, "attempt to send on RX-only VC %x", channel); | ||
1614 | hrz_kfree_skb (skb); | ||
1615 | return -EIO; | ||
1616 | } | ||
1617 | |||
1618 | // don't understand this | ||
1619 | ATM_SKB(skb)->vcc = atm_vcc; | ||
1620 | |||
1621 | if (skb->len > atm_vcc->qos.txtp.max_sdu) { | ||
1622 | PRINTK (KERN_ERR, "sk_buff length greater than agreed max_sdu, dropping..."); | ||
1623 | hrz_kfree_skb (skb); | ||
1624 | return -EIO; | ||
1625 | } | ||
1626 | |||
1627 | if (!channel) { | ||
1628 | PRINTD (DBG_ERR|DBG_TX, "attempt to transmit on zero (rx_)channel"); | ||
1629 | hrz_kfree_skb (skb); | ||
1630 | return -EIO; | ||
1631 | } | ||
1632 | |||
1633 | #if 0 | ||
1634 | { | ||
1635 | // where would be a better place for this? housekeeping? | ||
1636 | u16 status; | ||
1637 | pci_read_config_word (dev->pci_dev, PCI_STATUS, &status); | ||
1638 | if (status & PCI_STATUS_REC_MASTER_ABORT) { | ||
1639 | PRINTD (DBG_BUS|DBG_ERR, "Clearing PCI Master Abort (and cleaning up)"); | ||
1640 | status &= ~PCI_STATUS_REC_MASTER_ABORT; | ||
1641 | pci_write_config_word (dev->pci_dev, PCI_STATUS, status); | ||
1642 | if (test_bit (tx_busy, &dev->flags)) { | ||
1643 | hrz_kfree_skb (dev->tx_skb); | ||
1644 | tx_release (dev); | ||
1645 | } | ||
1646 | } | ||
1647 | } | ||
1648 | #endif | ||
1649 | |||
1650 | #ifdef DEBUG_HORIZON | ||
1651 | /* wey-hey! */ | ||
1652 | if (channel == 1023) { | ||
1653 | unsigned int i; | ||
1654 | unsigned short d = 0; | ||
1655 | char * s = skb->data; | ||
1656 | if (*s++ == 'D') { | ||
1657 | for (i = 0; i < 4; ++i) { | ||
1658 | d = (d<<4) | ((*s <= '9') ? (*s - '0') : (*s - 'a' + 10)); | ||
1659 | ++s; | ||
1660 | } | ||
1661 | PRINTK (KERN_INFO, "debug bitmap is now %hx", debug = d); | ||
1662 | } | ||
1663 | } | ||
1664 | #endif | ||
1665 | |||
1666 | // wait until TX is free and grab lock | ||
1667 | if (tx_hold (dev)) { | ||
1668 | hrz_kfree_skb (skb); | ||
1669 | return -ERESTARTSYS; | ||
1670 | } | ||
1671 | |||
1672 | // Wait for enough space to be available in transmit buffer memory. | ||
1673 | |||
1674 | // should be number of cells needed + 2 (according to hardware docs) | ||
1675 | // = ((framelen+8)+47) / 48 + 2 | ||
1676 | // = (framelen+7) / 48 + 3, hmm... faster to put addition inside XXX | ||
1677 | buffers_required = (skb->len+(ATM_AAL5_TRAILER-1)) / ATM_CELL_PAYLOAD + 3; | ||
1678 | |||
1679 | // replace with timer and sleep, add dev->tx_buffers_queue (max 1 entry) | ||
1680 | spin_count = 0; | ||
1681 | while ((free_buffers = rd_regw (dev, TX_FREE_BUFFER_COUNT_OFF)) < buffers_required) { | ||
1682 | PRINTD (DBG_TX, "waiting for free TX buffers, got %d of %d", | ||
1683 | free_buffers, buffers_required); | ||
1684 | // what is the appropriate delay? implement a timeout? (depending on line speed?) | ||
1685 | // mdelay (1); | ||
1686 | // what happens if we kill (current_pid, SIGKILL) ? | ||
1687 | schedule(); | ||
1688 | if (++spin_count > 1000) { | ||
1689 | PRINTD (DBG_TX|DBG_ERR, "spun out waiting for tx buffers, got %d of %d", | ||
1690 | free_buffers, buffers_required); | ||
1691 | tx_release (dev); | ||
1692 | hrz_kfree_skb (skb); | ||
1693 | return -ERESTARTSYS; | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | // Select a channel to transmit the frame on. | ||
1698 | if (channel == dev->last_vc) { | ||
1699 | PRINTD (DBG_TX, "last vc hack: hit"); | ||
1700 | tx_channel = dev->tx_last; | ||
1701 | } else { | ||
1702 | PRINTD (DBG_TX, "last vc hack: miss"); | ||
1703 | // Are we currently transmitting this VC on one of the channels? | ||
1704 | for (tx_channel = 0; tx_channel < TX_CHANS; ++tx_channel) | ||
1705 | if (dev->tx_channel_record[tx_channel] == channel) { | ||
1706 | PRINTD (DBG_TX, "vc already on channel: hit"); | ||
1707 | break; | ||
1708 | } | ||
1709 | if (tx_channel == TX_CHANS) { | ||
1710 | PRINTD (DBG_TX, "vc already on channel: miss"); | ||
1711 | // Find and set up an idle channel. | ||
1712 | tx_channel = setup_idle_tx_channel (dev, vcc); | ||
1713 | if (tx_channel < 0) { | ||
1714 | PRINTD (DBG_TX|DBG_ERR, "failed to get channel"); | ||
1715 | tx_release (dev); | ||
1716 | return tx_channel; | ||
1717 | } | ||
1718 | } | ||
1719 | |||
1720 | PRINTD (DBG_TX, "got channel"); | ||
1721 | SELECT_TX_CHANNEL(dev, tx_channel); | ||
1722 | |||
1723 | dev->last_vc = channel; | ||
1724 | dev->tx_last = tx_channel; | ||
1725 | } | ||
1726 | |||
1727 | PRINTD (DBG_TX, "using channel %u", tx_channel); | ||
1728 | |||
1729 | YELLOW_LED_OFF(dev); | ||
1730 | |||
1731 | // TX start transfer | ||
1732 | |||
1733 | { | ||
1734 | unsigned int tx_len = skb->len; | ||
1735 | unsigned int tx_iovcnt = skb_shinfo(skb)->nr_frags; | ||
1736 | // remember this so we can free it later | ||
1737 | dev->tx_skb = skb; | ||
1738 | |||
1739 | if (tx_iovcnt) { | ||
1740 | // scatter gather transfer | ||
1741 | dev->tx_regions = tx_iovcnt; | ||
1742 | dev->tx_iovec = NULL; /* @@@ needs rewritten */ | ||
1743 | dev->tx_bytes = 0; | ||
1744 | PRINTD (DBG_TX|DBG_BUS, "TX start scatter-gather transfer (iovec %p, len %d)", | ||
1745 | skb->data, tx_len); | ||
1746 | tx_release (dev); | ||
1747 | hrz_kfree_skb (skb); | ||
1748 | return -EIO; | ||
1749 | } else { | ||
1750 | // simple transfer | ||
1751 | dev->tx_regions = 0; | ||
1752 | dev->tx_iovec = NULL; | ||
1753 | dev->tx_bytes = tx_len; | ||
1754 | dev->tx_addr = skb->data; | ||
1755 | PRINTD (DBG_TX|DBG_BUS, "TX start simple transfer (addr %p, len %d)", | ||
1756 | skb->data, tx_len); | ||
1757 | } | ||
1758 | |||
1759 | // and do the business | ||
1760 | tx_schedule (dev, 0); | ||
1761 | |||
1762 | } | ||
1763 | |||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1767 | /********** reset a card **********/ | ||
1768 | |||
1769 | static void hrz_reset (const hrz_dev * dev) { | ||
1770 | u32 control_0_reg = rd_regl (dev, CONTROL_0_REG); | ||
1771 | |||
1772 | // why not set RESET_HORIZON to one and wait for the card to | ||
1773 | // reassert that bit as zero? Like so: | ||
1774 | control_0_reg = control_0_reg & RESET_HORIZON; | ||
1775 | wr_regl (dev, CONTROL_0_REG, control_0_reg); | ||
1776 | while (control_0_reg & RESET_HORIZON) | ||
1777 | control_0_reg = rd_regl (dev, CONTROL_0_REG); | ||
1778 | |||
1779 | // old reset code retained: | ||
1780 | wr_regl (dev, CONTROL_0_REG, control_0_reg | | ||
1781 | RESET_ATM | RESET_RX | RESET_TX | RESET_HOST); | ||
1782 | // just guessing here | ||
1783 | udelay (1000); | ||
1784 | |||
1785 | wr_regl (dev, CONTROL_0_REG, control_0_reg); | ||
1786 | } | ||
1787 | |||
1788 | /********** read the burnt in address **********/ | ||
1789 | |||
1790 | static inline void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl) | ||
1791 | { | ||
1792 | wr_regl (dev, CONTROL_0_REG, ctrl); | ||
1793 | udelay (5); | ||
1794 | } | ||
1795 | |||
1796 | static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl) | ||
1797 | { | ||
1798 | // DI must be valid around rising SK edge | ||
1799 | WRITE_IT_WAIT(dev, ctrl & ~SEEPROM_SK); | ||
1800 | WRITE_IT_WAIT(dev, ctrl | SEEPROM_SK); | ||
1801 | } | ||
1802 | |||
1803 | static u16 __init read_bia (const hrz_dev * dev, u16 addr) | ||
1804 | { | ||
1805 | u32 ctrl = rd_regl (dev, CONTROL_0_REG); | ||
1806 | |||
1807 | const unsigned int addr_bits = 6; | ||
1808 | const unsigned int data_bits = 16; | ||
1809 | |||
1810 | unsigned int i; | ||
1811 | |||
1812 | u16 res; | ||
1813 | |||
1814 | ctrl &= ~(SEEPROM_CS | SEEPROM_SK | SEEPROM_DI); | ||
1815 | WRITE_IT_WAIT(dev, ctrl); | ||
1816 | |||
1817 | // wake Serial EEPROM and send 110 (READ) command | ||
1818 | ctrl |= (SEEPROM_CS | SEEPROM_DI); | ||
1819 | CLOCK_IT(dev, ctrl); | ||
1820 | |||
1821 | ctrl |= SEEPROM_DI; | ||
1822 | CLOCK_IT(dev, ctrl); | ||
1823 | |||
1824 | ctrl &= ~SEEPROM_DI; | ||
1825 | CLOCK_IT(dev, ctrl); | ||
1826 | |||
1827 | for (i=0; i<addr_bits; i++) { | ||
1828 | if (addr & (1 << (addr_bits-1))) | ||
1829 | ctrl |= SEEPROM_DI; | ||
1830 | else | ||
1831 | ctrl &= ~SEEPROM_DI; | ||
1832 | |||
1833 | CLOCK_IT(dev, ctrl); | ||
1834 | |||
1835 | addr = addr << 1; | ||
1836 | } | ||
1837 | |||
1838 | // we could check that we have DO = 0 here | ||
1839 | ctrl &= ~SEEPROM_DI; | ||
1840 | |||
1841 | res = 0; | ||
1842 | for (i=0;i<data_bits;i++) { | ||
1843 | res = res >> 1; | ||
1844 | |||
1845 | CLOCK_IT(dev, ctrl); | ||
1846 | |||
1847 | if (rd_regl (dev, CONTROL_0_REG) & SEEPROM_DO) | ||
1848 | res |= (1 << (data_bits-1)); | ||
1849 | } | ||
1850 | |||
1851 | ctrl &= ~(SEEPROM_SK | SEEPROM_CS); | ||
1852 | WRITE_IT_WAIT(dev, ctrl); | ||
1853 | |||
1854 | return res; | ||
1855 | } | ||
1856 | |||
1857 | /********** initialise a card **********/ | ||
1858 | |||
1859 | static int __init hrz_init (hrz_dev * dev) { | ||
1860 | int onefivefive; | ||
1861 | |||
1862 | u16 chan; | ||
1863 | |||
1864 | int buff_count; | ||
1865 | |||
1866 | HDW * mem; | ||
1867 | |||
1868 | cell_buf * tx_desc; | ||
1869 | cell_buf * rx_desc; | ||
1870 | |||
1871 | u32 ctrl; | ||
1872 | |||
1873 | ctrl = rd_regl (dev, CONTROL_0_REG); | ||
1874 | PRINTD (DBG_INFO, "ctrl0reg is %#x", ctrl); | ||
1875 | onefivefive = ctrl & ATM_LAYER_STATUS; | ||
1876 | |||
1877 | if (onefivefive) | ||
1878 | printk (DEV_LABEL ": Horizon Ultra (at 155.52 MBps)"); | ||
1879 | else | ||
1880 | printk (DEV_LABEL ": Horizon (at 25 MBps)"); | ||
1881 | |||
1882 | printk (":"); | ||
1883 | // Reset the card to get everything in a known state | ||
1884 | |||
1885 | printk (" reset"); | ||
1886 | hrz_reset (dev); | ||
1887 | |||
1888 | // Clear all the buffer memory | ||
1889 | |||
1890 | printk (" clearing memory"); | ||
1891 | |||
1892 | for (mem = (HDW *) memmap; mem < (HDW *) (memmap + 1); ++mem) | ||
1893 | wr_mem (dev, mem, 0); | ||
1894 | |||
1895 | printk (" tx channels"); | ||
1896 | |||
1897 | // All transmit eight channels are set up as AAL5 ABR channels with | ||
1898 | // a 16us cell spacing. Why? | ||
1899 | |||
1900 | // Channel 0 gets the free buffer at 100h, channel 1 gets the free | ||
1901 | // buffer at 110h etc. | ||
1902 | |||
1903 | for (chan = 0; chan < TX_CHANS; ++chan) { | ||
1904 | tx_ch_desc * tx_desc = &memmap->tx_descs[chan]; | ||
1905 | cell_buf * buf = &memmap->inittxbufs[chan]; | ||
1906 | |||
1907 | // initialise the read and write buffer pointers | ||
1908 | wr_mem (dev, &tx_desc->rd_buf_type, BUF_PTR(buf)); | ||
1909 | wr_mem (dev, &tx_desc->wr_buf_type, BUF_PTR(buf)); | ||
1910 | |||
1911 | // set the status of the initial buffers to empty | ||
1912 | wr_mem (dev, &buf->next, BUFF_STATUS_EMPTY); | ||
1913 | } | ||
1914 | |||
1915 | // Use space bufn3 at the moment for tx buffers | ||
1916 | |||
1917 | printk (" tx buffers"); | ||
1918 | |||
1919 | tx_desc = memmap->bufn3; | ||
1920 | |||
1921 | wr_mem (dev, &memmap->txfreebufstart.next, BUF_PTR(tx_desc) | BUFF_STATUS_EMPTY); | ||
1922 | |||
1923 | for (buff_count = 0; buff_count < BUFN3_SIZE-1; buff_count++) { | ||
1924 | wr_mem (dev, &tx_desc->next, BUF_PTR(tx_desc+1) | BUFF_STATUS_EMPTY); | ||
1925 | tx_desc++; | ||
1926 | } | ||
1927 | |||
1928 | wr_mem (dev, &tx_desc->next, BUF_PTR(&memmap->txfreebufend) | BUFF_STATUS_EMPTY); | ||
1929 | |||
1930 | // Initialise the transmit free buffer count | ||
1931 | wr_regw (dev, TX_FREE_BUFFER_COUNT_OFF, BUFN3_SIZE); | ||
1932 | |||
1933 | printk (" rx channels"); | ||
1934 | |||
1935 | // Initialise all of the receive channels to be AAL5 disabled with | ||
1936 | // an interrupt threshold of 0 | ||
1937 | |||
1938 | for (chan = 0; chan < RX_CHANS; ++chan) { | ||
1939 | rx_ch_desc * rx_desc = &memmap->rx_descs[chan]; | ||
1940 | |||
1941 | wr_mem (dev, &rx_desc->wr_buf_type, CHANNEL_TYPE_AAL5 | RX_CHANNEL_DISABLED); | ||
1942 | } | ||
1943 | |||
1944 | printk (" rx buffers"); | ||
1945 | |||
1946 | // Use space bufn4 at the moment for rx buffers | ||
1947 | |||
1948 | rx_desc = memmap->bufn4; | ||
1949 | |||
1950 | wr_mem (dev, &memmap->rxfreebufstart.next, BUF_PTR(rx_desc) | BUFF_STATUS_EMPTY); | ||
1951 | |||
1952 | for (buff_count = 0; buff_count < BUFN4_SIZE-1; buff_count++) { | ||
1953 | wr_mem (dev, &rx_desc->next, BUF_PTR(rx_desc+1) | BUFF_STATUS_EMPTY); | ||
1954 | |||
1955 | rx_desc++; | ||
1956 | } | ||
1957 | |||
1958 | wr_mem (dev, &rx_desc->next, BUF_PTR(&memmap->rxfreebufend) | BUFF_STATUS_EMPTY); | ||
1959 | |||
1960 | // Initialise the receive free buffer count | ||
1961 | wr_regw (dev, RX_FREE_BUFFER_COUNT_OFF, BUFN4_SIZE); | ||
1962 | |||
1963 | // Initialize Horizons registers | ||
1964 | |||
1965 | // TX config | ||
1966 | wr_regw (dev, TX_CONFIG_OFF, | ||
1967 | ABR_ROUND_ROBIN | TX_NORMAL_OPERATION | DRVR_DRVRBAR_ENABLE); | ||
1968 | |||
1969 | // RX config. Use 10-x VC bits, x VP bits, non user cells in channel 0. | ||
1970 | wr_regw (dev, RX_CONFIG_OFF, | ||
1971 | DISCARD_UNUSED_VPI_VCI_BITS_SET | NON_USER_CELLS_IN_ONE_CHANNEL | vpi_bits); | ||
1972 | |||
1973 | // RX line config | ||
1974 | wr_regw (dev, RX_LINE_CONFIG_OFF, | ||
1975 | LOCK_DETECT_ENABLE | FREQUENCY_DETECT_ENABLE | GXTALOUT_SELECT_DIV4); | ||
1976 | |||
1977 | // Set the max AAL5 cell count to be just enough to contain the | ||
1978 | // largest AAL5 frame that the user wants to receive | ||
1979 | wr_regw (dev, MAX_AAL5_CELL_COUNT_OFF, | ||
1980 | (max_rx_size + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD); | ||
1981 | |||
1982 | // Enable receive | ||
1983 | wr_regw (dev, RX_CONFIG_OFF, rd_regw (dev, RX_CONFIG_OFF) | RX_ENABLE); | ||
1984 | |||
1985 | printk (" control"); | ||
1986 | |||
1987 | // Drive the OE of the LEDs then turn the green LED on | ||
1988 | ctrl |= GREEN_LED_OE | YELLOW_LED_OE | GREEN_LED | YELLOW_LED; | ||
1989 | wr_regl (dev, CONTROL_0_REG, ctrl); | ||
1990 | |||
1991 | // Test for a 155-capable card | ||
1992 | |||
1993 | if (onefivefive) { | ||
1994 | // Select 155 mode... make this a choice (or: how do we detect | ||
1995 | // external line speed and switch?) | ||
1996 | ctrl |= ATM_LAYER_SELECT; | ||
1997 | wr_regl (dev, CONTROL_0_REG, ctrl); | ||
1998 | |||
1999 | // test SUNI-lite vs SAMBA | ||
2000 | |||
2001 | // Register 0x00 in the SUNI will have some of bits 3-7 set, and | ||
2002 | // they will always be zero for the SAMBA. Ha! Bloody hardware | ||
2003 | // engineers. It'll never work. | ||
2004 | |||
2005 | if (rd_framer (dev, 0) & 0x00f0) { | ||
2006 | // SUNI | ||
2007 | printk (" SUNI"); | ||
2008 | |||
2009 | // Reset, just in case | ||
2010 | wr_framer (dev, 0x00, 0x0080); | ||
2011 | wr_framer (dev, 0x00, 0x0000); | ||
2012 | |||
2013 | // Configure transmit FIFO | ||
2014 | wr_framer (dev, 0x63, rd_framer (dev, 0x63) | 0x0002); | ||
2015 | |||
2016 | // Set line timed mode | ||
2017 | wr_framer (dev, 0x05, rd_framer (dev, 0x05) | 0x0001); | ||
2018 | } else { | ||
2019 | // SAMBA | ||
2020 | printk (" SAMBA"); | ||
2021 | |||
2022 | // Reset, just in case | ||
2023 | wr_framer (dev, 0, rd_framer (dev, 0) | 0x0001); | ||
2024 | wr_framer (dev, 0, rd_framer (dev, 0) &~ 0x0001); | ||
2025 | |||
2026 | // Turn off diagnostic loopback and enable line-timed mode | ||
2027 | wr_framer (dev, 0, 0x0002); | ||
2028 | |||
2029 | // Turn on transmit outputs | ||
2030 | wr_framer (dev, 2, 0x0B80); | ||
2031 | } | ||
2032 | } else { | ||
2033 | // Select 25 mode | ||
2034 | ctrl &= ~ATM_LAYER_SELECT; | ||
2035 | |||
2036 | // Madge B154 setup | ||
2037 | // none required? | ||
2038 | } | ||
2039 | |||
2040 | printk (" LEDs"); | ||
2041 | |||
2042 | GREEN_LED_ON(dev); | ||
2043 | YELLOW_LED_ON(dev); | ||
2044 | |||
2045 | printk (" ESI="); | ||
2046 | |||
2047 | { | ||
2048 | u16 b = 0; | ||
2049 | int i; | ||
2050 | u8 * esi = dev->atm_dev->esi; | ||
2051 | |||
2052 | // in the card I have, EEPROM | ||
2053 | // addresses 0, 1, 2 contain 0 | ||
2054 | // addresess 5, 6 etc. contain ffff | ||
2055 | // NB: Madge prefix is 00 00 f6 (which is 00 00 6f in Ethernet bit order) | ||
2056 | // the read_bia routine gets the BIA in Ethernet bit order | ||
2057 | |||
2058 | for (i=0; i < ESI_LEN; ++i) { | ||
2059 | if (i % 2 == 0) | ||
2060 | b = read_bia (dev, i/2 + 2); | ||
2061 | else | ||
2062 | b = b >> 8; | ||
2063 | esi[i] = b & 0xFF; | ||
2064 | printk ("%02x", esi[i]); | ||
2065 | } | ||
2066 | } | ||
2067 | |||
2068 | // Enable RX_Q and ?X_COMPLETE interrupts only | ||
2069 | wr_regl (dev, INT_ENABLE_REG_OFF, INTERESTING_INTERRUPTS); | ||
2070 | printk (" IRQ on"); | ||
2071 | |||
2072 | printk (".\n"); | ||
2073 | |||
2074 | return onefivefive; | ||
2075 | } | ||
2076 | |||
2077 | /********** check max_sdu **********/ | ||
2078 | |||
2079 | static int check_max_sdu (hrz_aal aal, struct atm_trafprm * tp, unsigned int max_frame_size) { | ||
2080 | PRINTD (DBG_FLOW|DBG_QOS, "check_max_sdu"); | ||
2081 | |||
2082 | switch (aal) { | ||
2083 | case aal0: | ||
2084 | if (!(tp->max_sdu)) { | ||
2085 | PRINTD (DBG_QOS, "defaulting max_sdu"); | ||
2086 | tp->max_sdu = ATM_AAL0_SDU; | ||
2087 | } else if (tp->max_sdu != ATM_AAL0_SDU) { | ||
2088 | PRINTD (DBG_QOS|DBG_ERR, "rejecting max_sdu"); | ||
2089 | return -EINVAL; | ||
2090 | } | ||
2091 | break; | ||
2092 | case aal34: | ||
2093 | if (tp->max_sdu == 0 || tp->max_sdu > ATM_MAX_AAL34_PDU) { | ||
2094 | PRINTD (DBG_QOS, "%sing max_sdu", tp->max_sdu ? "capp" : "default"); | ||
2095 | tp->max_sdu = ATM_MAX_AAL34_PDU; | ||
2096 | } | ||
2097 | break; | ||
2098 | case aal5: | ||
2099 | if (tp->max_sdu == 0 || tp->max_sdu > max_frame_size) { | ||
2100 | PRINTD (DBG_QOS, "%sing max_sdu", tp->max_sdu ? "capp" : "default"); | ||
2101 | tp->max_sdu = max_frame_size; | ||
2102 | } | ||
2103 | break; | ||
2104 | } | ||
2105 | return 0; | ||
2106 | } | ||
2107 | |||
2108 | /********** check pcr **********/ | ||
2109 | |||
2110 | // something like this should be part of ATM Linux | ||
2111 | static int atm_pcr_check (struct atm_trafprm * tp, unsigned int pcr) { | ||
2112 | // we are assuming non-UBR, and non-special values of pcr | ||
2113 | if (tp->min_pcr == ATM_MAX_PCR) | ||
2114 | PRINTD (DBG_QOS, "luser gave min_pcr = ATM_MAX_PCR"); | ||
2115 | else if (tp->min_pcr < 0) | ||
2116 | PRINTD (DBG_QOS, "luser gave negative min_pcr"); | ||
2117 | else if (tp->min_pcr && tp->min_pcr > pcr) | ||
2118 | PRINTD (DBG_QOS, "pcr less than min_pcr"); | ||
2119 | else | ||
2120 | // !! max_pcr = UNSPEC (0) is equivalent to max_pcr = MAX (-1) | ||
2121 | // easier to #define ATM_MAX_PCR 0 and have all rates unsigned? | ||
2122 | // [this would get rid of next two conditionals] | ||
2123 | if ((0) && tp->max_pcr == ATM_MAX_PCR) | ||
2124 | PRINTD (DBG_QOS, "luser gave max_pcr = ATM_MAX_PCR"); | ||
2125 | else if ((tp->max_pcr != ATM_MAX_PCR) && tp->max_pcr < 0) | ||
2126 | PRINTD (DBG_QOS, "luser gave negative max_pcr"); | ||
2127 | else if (tp->max_pcr && tp->max_pcr != ATM_MAX_PCR && tp->max_pcr < pcr) | ||
2128 | PRINTD (DBG_QOS, "pcr greater than max_pcr"); | ||
2129 | else { | ||
2130 | // each limit unspecified or not violated | ||
2131 | PRINTD (DBG_QOS, "xBR(pcr) OK"); | ||
2132 | return 0; | ||
2133 | } | ||
2134 | PRINTD (DBG_QOS, "pcr=%u, tp: min_pcr=%d, pcr=%d, max_pcr=%d", | ||
2135 | pcr, tp->min_pcr, tp->pcr, tp->max_pcr); | ||
2136 | return -EINVAL; | ||
2137 | } | ||
2138 | |||
2139 | /********** open VC **********/ | ||
2140 | |||
2141 | static int hrz_open (struct atm_vcc *atm_vcc) | ||
2142 | { | ||
2143 | int error; | ||
2144 | u16 channel; | ||
2145 | |||
2146 | struct atm_qos * qos; | ||
2147 | struct atm_trafprm * txtp; | ||
2148 | struct atm_trafprm * rxtp; | ||
2149 | |||
2150 | hrz_dev * dev = HRZ_DEV(atm_vcc->dev); | ||
2151 | hrz_vcc vcc; | ||
2152 | hrz_vcc * vccp; // allocated late | ||
2153 | short vpi = atm_vcc->vpi; | ||
2154 | int vci = atm_vcc->vci; | ||
2155 | PRINTD (DBG_FLOW|DBG_VCC, "hrz_open %x %x", vpi, vci); | ||
2156 | |||
2157 | #ifdef ATM_VPI_UNSPEC | ||
2158 | // UNSPEC is deprecated, remove this code eventually | ||
2159 | if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) { | ||
2160 | PRINTK (KERN_WARNING, "rejecting open with unspecified VPI/VCI (deprecated)"); | ||
2161 | return -EINVAL; | ||
2162 | } | ||
2163 | #endif | ||
2164 | |||
2165 | error = vpivci_to_channel (&channel, vpi, vci); | ||
2166 | if (error) { | ||
2167 | PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci); | ||
2168 | return error; | ||
2169 | } | ||
2170 | |||
2171 | vcc.channel = channel; | ||
2172 | // max speed for the moment | ||
2173 | vcc.tx_rate = 0x0; | ||
2174 | |||
2175 | qos = &atm_vcc->qos; | ||
2176 | |||
2177 | // check AAL and remember it | ||
2178 | switch (qos->aal) { | ||
2179 | case ATM_AAL0: | ||
2180 | // we would if it were 48 bytes and not 52! | ||
2181 | PRINTD (DBG_QOS|DBG_VCC, "AAL0"); | ||
2182 | vcc.aal = aal0; | ||
2183 | break; | ||
2184 | case ATM_AAL34: | ||
2185 | // we would if I knew how do the SAR! | ||
2186 | PRINTD (DBG_QOS|DBG_VCC, "AAL3/4"); | ||
2187 | vcc.aal = aal34; | ||
2188 | break; | ||
2189 | case ATM_AAL5: | ||
2190 | PRINTD (DBG_QOS|DBG_VCC, "AAL5"); | ||
2191 | vcc.aal = aal5; | ||
2192 | break; | ||
2193 | default: | ||
2194 | PRINTD (DBG_QOS|DBG_VCC, "Bad AAL!"); | ||
2195 | return -EINVAL; | ||
2196 | break; | ||
2197 | } | ||
2198 | |||
2199 | // TX traffic parameters | ||
2200 | |||
2201 | // there are two, interrelated problems here: 1. the reservation of | ||
2202 | // PCR is not a binary choice, we are given bounds and/or a | ||
2203 | // desirable value; 2. the device is only capable of certain values, | ||
2204 | // most of which are not integers. It is almost certainly acceptable | ||
2205 | // to be off by a maximum of 1 to 10 cps. | ||
2206 | |||
2207 | // Pragmatic choice: always store an integral PCR as that which has | ||
2208 | // been allocated, even if we allocate a little (or a lot) less, | ||
2209 | // after rounding. The actual allocation depends on what we can | ||
2210 | // manage with our rate selection algorithm. The rate selection | ||
2211 | // algorithm is given an integral PCR and a tolerance and told | ||
2212 | // whether it should round the value up or down if the tolerance is | ||
2213 | // exceeded; it returns: a) the actual rate selected (rounded up to | ||
2214 | // the nearest integer), b) a bit pattern to feed to the timer | ||
2215 | // register, and c) a failure value if no applicable rate exists. | ||
2216 | |||
2217 | // Part of the job is done by atm_pcr_goal which gives us a PCR | ||
2218 | // specification which says: EITHER grab the maximum available PCR | ||
2219 | // (and perhaps a lower bound which we musn't pass), OR grab this | ||
2220 | // amount, rounding down if you have to (and perhaps a lower bound | ||
2221 | // which we musn't pass) OR grab this amount, rounding up if you | ||
2222 | // have to (and perhaps an upper bound which we musn't pass). If any | ||
2223 | // bounds ARE passed we fail. Note that rounding is only rounding to | ||
2224 | // match device limitations, we do not round down to satisfy | ||
2225 | // bandwidth availability even if this would not violate any given | ||
2226 | // lower bound. | ||
2227 | |||
2228 | // Note: telephony = 64kb/s = 48 byte cell payload @ 500/3 cells/s | ||
2229 | // (say) so this is not even a binary fixpoint cell rate (but this | ||
2230 | // device can do it). To avoid this sort of hassle we use a | ||
2231 | // tolerance parameter (currently fixed at 10 cps). | ||
2232 | |||
2233 | PRINTD (DBG_QOS, "TX:"); | ||
2234 | |||
2235 | txtp = &qos->txtp; | ||
2236 | |||
2237 | // set up defaults for no traffic | ||
2238 | vcc.tx_rate = 0; | ||
2239 | // who knows what would actually happen if you try and send on this? | ||
2240 | vcc.tx_xbr_bits = IDLE_RATE_TYPE; | ||
2241 | vcc.tx_pcr_bits = CLOCK_DISABLE; | ||
2242 | #if 0 | ||
2243 | vcc.tx_scr_bits = CLOCK_DISABLE; | ||
2244 | vcc.tx_bucket_bits = 0; | ||
2245 | #endif | ||
2246 | |||
2247 | if (txtp->traffic_class != ATM_NONE) { | ||
2248 | error = check_max_sdu (vcc.aal, txtp, max_tx_size); | ||
2249 | if (error) { | ||
2250 | PRINTD (DBG_QOS, "TX max_sdu check failed"); | ||
2251 | return error; | ||
2252 | } | ||
2253 | |||
2254 | switch (txtp->traffic_class) { | ||
2255 | case ATM_UBR: { | ||
2256 | // we take "the PCR" as a rate-cap | ||
2257 | // not reserved | ||
2258 | vcc.tx_rate = 0; | ||
2259 | make_rate (dev, 1<<30, round_nearest, &vcc.tx_pcr_bits, NULL); | ||
2260 | vcc.tx_xbr_bits = ABR_RATE_TYPE; | ||
2261 | break; | ||
2262 | } | ||
2263 | #if 0 | ||
2264 | case ATM_ABR: { | ||
2265 | // reserve min, allow up to max | ||
2266 | vcc.tx_rate = 0; // ? | ||
2267 | make_rate (dev, 1<<30, round_nearest, &vcc.tx_pcr_bits, 0); | ||
2268 | vcc.tx_xbr_bits = ABR_RATE_TYPE; | ||
2269 | break; | ||
2270 | } | ||
2271 | #endif | ||
2272 | case ATM_CBR: { | ||
2273 | int pcr = atm_pcr_goal (txtp); | ||
2274 | rounding r; | ||
2275 | if (!pcr) { | ||
2276 | // down vs. up, remaining bandwidth vs. unlimited bandwidth!! | ||
2277 | // should really have: once someone gets unlimited bandwidth | ||
2278 | // that no more non-UBR channels can be opened until the | ||
2279 | // unlimited one closes?? For the moment, round_down means | ||
2280 | // greedy people actually get something and not nothing | ||
2281 | r = round_down; | ||
2282 | // slight race (no locking) here so we may get -EAGAIN | ||
2283 | // later; the greedy bastards would deserve it :) | ||
2284 | PRINTD (DBG_QOS, "snatching all remaining TX bandwidth"); | ||
2285 | pcr = dev->tx_avail; | ||
2286 | } else if (pcr < 0) { | ||
2287 | r = round_down; | ||
2288 | pcr = -pcr; | ||
2289 | } else { | ||
2290 | r = round_up; | ||
2291 | } | ||
2292 | error = make_rate_with_tolerance (dev, pcr, r, 10, | ||
2293 | &vcc.tx_pcr_bits, &vcc.tx_rate); | ||
2294 | if (error) { | ||
2295 | PRINTD (DBG_QOS, "could not make rate from TX PCR"); | ||
2296 | return error; | ||
2297 | } | ||
2298 | // not really clear what further checking is needed | ||
2299 | error = atm_pcr_check (txtp, vcc.tx_rate); | ||
2300 | if (error) { | ||
2301 | PRINTD (DBG_QOS, "TX PCR failed consistency check"); | ||
2302 | return error; | ||
2303 | } | ||
2304 | vcc.tx_xbr_bits = CBR_RATE_TYPE; | ||
2305 | break; | ||
2306 | } | ||
2307 | #if 0 | ||
2308 | case ATM_VBR: { | ||
2309 | int pcr = atm_pcr_goal (txtp); | ||
2310 | // int scr = atm_scr_goal (txtp); | ||
2311 | int scr = pcr/2; // just for fun | ||
2312 | unsigned int mbs = 60; // just for fun | ||
2313 | rounding pr; | ||
2314 | rounding sr; | ||
2315 | unsigned int bucket; | ||
2316 | if (!pcr) { | ||
2317 | pr = round_nearest; | ||
2318 | pcr = 1<<30; | ||
2319 | } else if (pcr < 0) { | ||
2320 | pr = round_down; | ||
2321 | pcr = -pcr; | ||
2322 | } else { | ||
2323 | pr = round_up; | ||
2324 | } | ||
2325 | error = make_rate_with_tolerance (dev, pcr, pr, 10, | ||
2326 | &vcc.tx_pcr_bits, 0); | ||
2327 | if (!scr) { | ||
2328 | // see comments for PCR with CBR above | ||
2329 | sr = round_down; | ||
2330 | // slight race (no locking) here so we may get -EAGAIN | ||
2331 | // later; the greedy bastards would deserve it :) | ||
2332 | PRINTD (DBG_QOS, "snatching all remaining TX bandwidth"); | ||
2333 | scr = dev->tx_avail; | ||
2334 | } else if (scr < 0) { | ||
2335 | sr = round_down; | ||
2336 | scr = -scr; | ||
2337 | } else { | ||
2338 | sr = round_up; | ||
2339 | } | ||
2340 | error = make_rate_with_tolerance (dev, scr, sr, 10, | ||
2341 | &vcc.tx_scr_bits, &vcc.tx_rate); | ||
2342 | if (error) { | ||
2343 | PRINTD (DBG_QOS, "could not make rate from TX SCR"); | ||
2344 | return error; | ||
2345 | } | ||
2346 | // not really clear what further checking is needed | ||
2347 | // error = atm_scr_check (txtp, vcc.tx_rate); | ||
2348 | if (error) { | ||
2349 | PRINTD (DBG_QOS, "TX SCR failed consistency check"); | ||
2350 | return error; | ||
2351 | } | ||
2352 | // bucket calculations (from a piece of paper...) cell bucket | ||
2353 | // capacity must be largest integer smaller than m(p-s)/p + 1 | ||
2354 | // where m = max burst size, p = pcr, s = scr | ||
2355 | bucket = mbs*(pcr-scr)/pcr; | ||
2356 | if (bucket*pcr != mbs*(pcr-scr)) | ||
2357 | bucket += 1; | ||
2358 | if (bucket > BUCKET_MAX_SIZE) { | ||
2359 | PRINTD (DBG_QOS, "shrinking bucket from %u to %u", | ||
2360 | bucket, BUCKET_MAX_SIZE); | ||
2361 | bucket = BUCKET_MAX_SIZE; | ||
2362 | } | ||
2363 | vcc.tx_xbr_bits = VBR_RATE_TYPE; | ||
2364 | vcc.tx_bucket_bits = bucket; | ||
2365 | break; | ||
2366 | } | ||
2367 | #endif | ||
2368 | default: { | ||
2369 | PRINTD (DBG_QOS, "unsupported TX traffic class"); | ||
2370 | return -EINVAL; | ||
2371 | break; | ||
2372 | } | ||
2373 | } | ||
2374 | } | ||
2375 | |||
2376 | // RX traffic parameters | ||
2377 | |||
2378 | PRINTD (DBG_QOS, "RX:"); | ||
2379 | |||
2380 | rxtp = &qos->rxtp; | ||
2381 | |||
2382 | // set up defaults for no traffic | ||
2383 | vcc.rx_rate = 0; | ||
2384 | |||
2385 | if (rxtp->traffic_class != ATM_NONE) { | ||
2386 | error = check_max_sdu (vcc.aal, rxtp, max_rx_size); | ||
2387 | if (error) { | ||
2388 | PRINTD (DBG_QOS, "RX max_sdu check failed"); | ||
2389 | return error; | ||
2390 | } | ||
2391 | switch (rxtp->traffic_class) { | ||
2392 | case ATM_UBR: { | ||
2393 | // not reserved | ||
2394 | break; | ||
2395 | } | ||
2396 | #if 0 | ||
2397 | case ATM_ABR: { | ||
2398 | // reserve min | ||
2399 | vcc.rx_rate = 0; // ? | ||
2400 | break; | ||
2401 | } | ||
2402 | #endif | ||
2403 | case ATM_CBR: { | ||
2404 | int pcr = atm_pcr_goal (rxtp); | ||
2405 | if (!pcr) { | ||
2406 | // slight race (no locking) here so we may get -EAGAIN | ||
2407 | // later; the greedy bastards would deserve it :) | ||
2408 | PRINTD (DBG_QOS, "snatching all remaining RX bandwidth"); | ||
2409 | pcr = dev->rx_avail; | ||
2410 | } else if (pcr < 0) { | ||
2411 | pcr = -pcr; | ||
2412 | } | ||
2413 | vcc.rx_rate = pcr; | ||
2414 | // not really clear what further checking is needed | ||
2415 | error = atm_pcr_check (rxtp, vcc.rx_rate); | ||
2416 | if (error) { | ||
2417 | PRINTD (DBG_QOS, "RX PCR failed consistency check"); | ||
2418 | return error; | ||
2419 | } | ||
2420 | break; | ||
2421 | } | ||
2422 | #if 0 | ||
2423 | case ATM_VBR: { | ||
2424 | // int scr = atm_scr_goal (rxtp); | ||
2425 | int scr = 1<<16; // just for fun | ||
2426 | if (!scr) { | ||
2427 | // slight race (no locking) here so we may get -EAGAIN | ||
2428 | // later; the greedy bastards would deserve it :) | ||
2429 | PRINTD (DBG_QOS, "snatching all remaining RX bandwidth"); | ||
2430 | scr = dev->rx_avail; | ||
2431 | } else if (scr < 0) { | ||
2432 | scr = -scr; | ||
2433 | } | ||
2434 | vcc.rx_rate = scr; | ||
2435 | // not really clear what further checking is needed | ||
2436 | // error = atm_scr_check (rxtp, vcc.rx_rate); | ||
2437 | if (error) { | ||
2438 | PRINTD (DBG_QOS, "RX SCR failed consistency check"); | ||
2439 | return error; | ||
2440 | } | ||
2441 | break; | ||
2442 | } | ||
2443 | #endif | ||
2444 | default: { | ||
2445 | PRINTD (DBG_QOS, "unsupported RX traffic class"); | ||
2446 | return -EINVAL; | ||
2447 | break; | ||
2448 | } | ||
2449 | } | ||
2450 | } | ||
2451 | |||
2452 | |||
2453 | // late abort useful for diagnostics | ||
2454 | if (vcc.aal != aal5) { | ||
2455 | PRINTD (DBG_QOS, "AAL not supported"); | ||
2456 | return -EINVAL; | ||
2457 | } | ||
2458 | |||
2459 | // get space for our vcc stuff and copy parameters into it | ||
2460 | vccp = kmalloc (sizeof(hrz_vcc), GFP_KERNEL); | ||
2461 | if (!vccp) { | ||
2462 | PRINTK (KERN_ERR, "out of memory!"); | ||
2463 | return -ENOMEM; | ||
2464 | } | ||
2465 | *vccp = vcc; | ||
2466 | |||
2467 | // clear error and grab cell rate resource lock | ||
2468 | error = 0; | ||
2469 | spin_lock (&dev->rate_lock); | ||
2470 | |||
2471 | if (vcc.tx_rate > dev->tx_avail) { | ||
2472 | PRINTD (DBG_QOS, "not enough TX PCR left"); | ||
2473 | error = -EAGAIN; | ||
2474 | } | ||
2475 | |||
2476 | if (vcc.rx_rate > dev->rx_avail) { | ||
2477 | PRINTD (DBG_QOS, "not enough RX PCR left"); | ||
2478 | error = -EAGAIN; | ||
2479 | } | ||
2480 | |||
2481 | if (!error) { | ||
2482 | // really consume cell rates | ||
2483 | dev->tx_avail -= vcc.tx_rate; | ||
2484 | dev->rx_avail -= vcc.rx_rate; | ||
2485 | PRINTD (DBG_QOS|DBG_VCC, "reserving %u TX PCR and %u RX PCR", | ||
2486 | vcc.tx_rate, vcc.rx_rate); | ||
2487 | } | ||
2488 | |||
2489 | // release lock and exit on error | ||
2490 | spin_unlock (&dev->rate_lock); | ||
2491 | if (error) { | ||
2492 | PRINTD (DBG_QOS|DBG_VCC, "insufficient cell rate resources"); | ||
2493 | kfree (vccp); | ||
2494 | return error; | ||
2495 | } | ||
2496 | |||
2497 | // this is "immediately before allocating the connection identifier | ||
2498 | // in hardware" - so long as the next call does not fail :) | ||
2499 | set_bit(ATM_VF_ADDR,&atm_vcc->flags); | ||
2500 | |||
2501 | // any errors here are very serious and should never occur | ||
2502 | |||
2503 | if (rxtp->traffic_class != ATM_NONE) { | ||
2504 | if (dev->rxer[channel]) { | ||
2505 | PRINTD (DBG_ERR|DBG_VCC, "VC already open for RX"); | ||
2506 | error = -EBUSY; | ||
2507 | } | ||
2508 | if (!error) | ||
2509 | error = hrz_open_rx (dev, channel); | ||
2510 | if (error) { | ||
2511 | kfree (vccp); | ||
2512 | return error; | ||
2513 | } | ||
2514 | // this link allows RX frames through | ||
2515 | dev->rxer[channel] = atm_vcc; | ||
2516 | } | ||
2517 | |||
2518 | // success, set elements of atm_vcc | ||
2519 | atm_vcc->dev_data = (void *) vccp; | ||
2520 | |||
2521 | // indicate readiness | ||
2522 | set_bit(ATM_VF_READY,&atm_vcc->flags); | ||
2523 | |||
2524 | return 0; | ||
2525 | } | ||
2526 | |||
2527 | /********** close VC **********/ | ||
2528 | |||
2529 | static void hrz_close (struct atm_vcc * atm_vcc) { | ||
2530 | hrz_dev * dev = HRZ_DEV(atm_vcc->dev); | ||
2531 | hrz_vcc * vcc = HRZ_VCC(atm_vcc); | ||
2532 | u16 channel = vcc->channel; | ||
2533 | PRINTD (DBG_VCC|DBG_FLOW, "hrz_close"); | ||
2534 | |||
2535 | // indicate unreadiness | ||
2536 | clear_bit(ATM_VF_READY,&atm_vcc->flags); | ||
2537 | |||
2538 | if (atm_vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2539 | unsigned int i; | ||
2540 | |||
2541 | // let any TX on this channel that has started complete | ||
2542 | // no restart, just keep trying | ||
2543 | while (tx_hold (dev)) | ||
2544 | ; | ||
2545 | // remove record of any tx_channel having been setup for this channel | ||
2546 | for (i = 0; i < TX_CHANS; ++i) | ||
2547 | if (dev->tx_channel_record[i] == channel) { | ||
2548 | dev->tx_channel_record[i] = -1; | ||
2549 | break; | ||
2550 | } | ||
2551 | if (dev->last_vc == channel) | ||
2552 | dev->tx_last = -1; | ||
2553 | tx_release (dev); | ||
2554 | } | ||
2555 | |||
2556 | if (atm_vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2557 | // disable RXing - it tries quite hard | ||
2558 | hrz_close_rx (dev, channel); | ||
2559 | // forget the vcc - no more skbs will be pushed | ||
2560 | if (atm_vcc != dev->rxer[channel]) | ||
2561 | PRINTK (KERN_ERR, "%s atm_vcc=%p rxer[channel]=%p", | ||
2562 | "arghhh! we're going to die!", | ||
2563 | atm_vcc, dev->rxer[channel]); | ||
2564 | dev->rxer[channel] = NULL; | ||
2565 | } | ||
2566 | |||
2567 | // atomically release our rate reservation | ||
2568 | spin_lock (&dev->rate_lock); | ||
2569 | PRINTD (DBG_QOS|DBG_VCC, "releasing %u TX PCR and %u RX PCR", | ||
2570 | vcc->tx_rate, vcc->rx_rate); | ||
2571 | dev->tx_avail += vcc->tx_rate; | ||
2572 | dev->rx_avail += vcc->rx_rate; | ||
2573 | spin_unlock (&dev->rate_lock); | ||
2574 | |||
2575 | // free our structure | ||
2576 | kfree (vcc); | ||
2577 | // say the VPI/VCI is free again | ||
2578 | clear_bit(ATM_VF_ADDR,&atm_vcc->flags); | ||
2579 | } | ||
2580 | |||
2581 | #if 0 | ||
2582 | static int hrz_getsockopt (struct atm_vcc * atm_vcc, int level, int optname, | ||
2583 | void *optval, int optlen) { | ||
2584 | hrz_dev * dev = HRZ_DEV(atm_vcc->dev); | ||
2585 | PRINTD (DBG_FLOW|DBG_VCC, "hrz_getsockopt"); | ||
2586 | switch (level) { | ||
2587 | case SOL_SOCKET: | ||
2588 | switch (optname) { | ||
2589 | // case SO_BCTXOPT: | ||
2590 | // break; | ||
2591 | // case SO_BCRXOPT: | ||
2592 | // break; | ||
2593 | default: | ||
2594 | return -ENOPROTOOPT; | ||
2595 | break; | ||
2596 | }; | ||
2597 | break; | ||
2598 | } | ||
2599 | return -EINVAL; | ||
2600 | } | ||
2601 | |||
2602 | static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, | ||
2603 | void *optval, int optlen) { | ||
2604 | hrz_dev * dev = HRZ_DEV(atm_vcc->dev); | ||
2605 | PRINTD (DBG_FLOW|DBG_VCC, "hrz_setsockopt"); | ||
2606 | switch (level) { | ||
2607 | case SOL_SOCKET: | ||
2608 | switch (optname) { | ||
2609 | // case SO_BCTXOPT: | ||
2610 | // break; | ||
2611 | // case SO_BCRXOPT: | ||
2612 | // break; | ||
2613 | default: | ||
2614 | return -ENOPROTOOPT; | ||
2615 | break; | ||
2616 | }; | ||
2617 | break; | ||
2618 | } | ||
2619 | return -EINVAL; | ||
2620 | } | ||
2621 | #endif | ||
2622 | |||
2623 | #if 0 | ||
2624 | static int hrz_ioctl (struct atm_dev * atm_dev, unsigned int cmd, void *arg) { | ||
2625 | hrz_dev * dev = HRZ_DEV(atm_dev); | ||
2626 | PRINTD (DBG_FLOW, "hrz_ioctl"); | ||
2627 | return -1; | ||
2628 | } | ||
2629 | |||
2630 | unsigned char hrz_phy_get (struct atm_dev * atm_dev, unsigned long addr) { | ||
2631 | hrz_dev * dev = HRZ_DEV(atm_dev); | ||
2632 | PRINTD (DBG_FLOW, "hrz_phy_get"); | ||
2633 | return 0; | ||
2634 | } | ||
2635 | |||
2636 | static void hrz_phy_put (struct atm_dev * atm_dev, unsigned char value, | ||
2637 | unsigned long addr) { | ||
2638 | hrz_dev * dev = HRZ_DEV(atm_dev); | ||
2639 | PRINTD (DBG_FLOW, "hrz_phy_put"); | ||
2640 | } | ||
2641 | |||
2642 | static int hrz_change_qos (struct atm_vcc * atm_vcc, struct atm_qos *qos, int flgs) { | ||
2643 | hrz_dev * dev = HRZ_DEV(vcc->dev); | ||
2644 | PRINTD (DBG_FLOW, "hrz_change_qos"); | ||
2645 | return -1; | ||
2646 | } | ||
2647 | #endif | ||
2648 | |||
2649 | /********** proc file contents **********/ | ||
2650 | |||
2651 | static int hrz_proc_read (struct atm_dev * atm_dev, loff_t * pos, char * page) { | ||
2652 | hrz_dev * dev = HRZ_DEV(atm_dev); | ||
2653 | int left = *pos; | ||
2654 | PRINTD (DBG_FLOW, "hrz_proc_read"); | ||
2655 | |||
2656 | /* more diagnostics here? */ | ||
2657 | |||
2658 | #if 0 | ||
2659 | if (!left--) { | ||
2660 | unsigned int count = sprintf (page, "vbr buckets:"); | ||
2661 | unsigned int i; | ||
2662 | for (i = 0; i < TX_CHANS; ++i) | ||
2663 | count += sprintf (page, " %u/%u", | ||
2664 | query_tx_channel_config (dev, i, BUCKET_FULLNESS_ACCESS), | ||
2665 | query_tx_channel_config (dev, i, BUCKET_CAPACITY_ACCESS)); | ||
2666 | count += sprintf (page+count, ".\n"); | ||
2667 | return count; | ||
2668 | } | ||
2669 | #endif | ||
2670 | |||
2671 | if (!left--) | ||
2672 | return sprintf (page, | ||
2673 | "cells: TX %lu, RX %lu, HEC errors %lu, unassigned %lu.\n", | ||
2674 | dev->tx_cell_count, dev->rx_cell_count, | ||
2675 | dev->hec_error_count, dev->unassigned_cell_count); | ||
2676 | |||
2677 | if (!left--) | ||
2678 | return sprintf (page, | ||
2679 | "free cell buffers: TX %hu, RX %hu+%hu.\n", | ||
2680 | rd_regw (dev, TX_FREE_BUFFER_COUNT_OFF), | ||
2681 | rd_regw (dev, RX_FREE_BUFFER_COUNT_OFF), | ||
2682 | dev->noof_spare_buffers); | ||
2683 | |||
2684 | if (!left--) | ||
2685 | return sprintf (page, | ||
2686 | "cps remaining: TX %u, RX %u\n", | ||
2687 | dev->tx_avail, dev->rx_avail); | ||
2688 | |||
2689 | return 0; | ||
2690 | } | ||
2691 | |||
2692 | static const struct atmdev_ops hrz_ops = { | ||
2693 | .open = hrz_open, | ||
2694 | .close = hrz_close, | ||
2695 | .send = hrz_send, | ||
2696 | .proc_read = hrz_proc_read, | ||
2697 | .owner = THIS_MODULE, | ||
2698 | }; | ||
2699 | |||
2700 | static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | ||
2701 | { | ||
2702 | hrz_dev * dev; | ||
2703 | int err = 0; | ||
2704 | |||
2705 | // adapter slot free, read resources from PCI configuration space | ||
2706 | u32 iobase = pci_resource_start (pci_dev, 0); | ||
2707 | u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1)); | ||
2708 | unsigned int irq; | ||
2709 | unsigned char lat; | ||
2710 | |||
2711 | PRINTD (DBG_FLOW, "hrz_probe"); | ||
2712 | |||
2713 | if (pci_enable_device(pci_dev)) | ||
2714 | return -EINVAL; | ||
2715 | |||
2716 | /* XXX DEV_LABEL is a guess */ | ||
2717 | if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL)) { | ||
2718 | return -EINVAL; | ||
2719 | goto out_disable; | ||
2720 | } | ||
2721 | |||
2722 | dev = kmalloc(sizeof(hrz_dev), GFP_KERNEL); | ||
2723 | if (!dev) { | ||
2724 | // perhaps we should be nice: deregister all adapters and abort? | ||
2725 | PRINTD(DBG_ERR, "out of memory"); | ||
2726 | err = -ENOMEM; | ||
2727 | goto out_release; | ||
2728 | } | ||
2729 | |||
2730 | memset(dev, 0, sizeof(hrz_dev)); | ||
2731 | |||
2732 | pci_set_drvdata(pci_dev, dev); | ||
2733 | |||
2734 | // grab IRQ and install handler - move this someplace more sensible | ||
2735 | irq = pci_dev->irq; | ||
2736 | if (request_irq(irq, | ||
2737 | interrupt_handler, | ||
2738 | SA_SHIRQ, /* irqflags guess */ | ||
2739 | DEV_LABEL, /* name guess */ | ||
2740 | dev)) { | ||
2741 | PRINTD(DBG_WARN, "request IRQ failed!"); | ||
2742 | err = -EINVAL; | ||
2743 | goto out_free; | ||
2744 | } | ||
2745 | |||
2746 | PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p", | ||
2747 | iobase, irq, membase); | ||
2748 | |||
2749 | dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL); | ||
2750 | if (!(dev->atm_dev)) { | ||
2751 | PRINTD(DBG_ERR, "failed to register Madge ATM adapter"); | ||
2752 | err = -EINVAL; | ||
2753 | goto out_free_irq; | ||
2754 | } | ||
2755 | |||
2756 | PRINTD(DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", | ||
2757 | dev->atm_dev->number, dev, dev->atm_dev); | ||
2758 | dev->atm_dev->dev_data = (void *) dev; | ||
2759 | dev->pci_dev = pci_dev; | ||
2760 | |||
2761 | // enable bus master accesses | ||
2762 | pci_set_master(pci_dev); | ||
2763 | |||
2764 | // frobnicate latency (upwards, usually) | ||
2765 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat); | ||
2766 | if (pci_lat) { | ||
2767 | PRINTD(DBG_INFO, "%s PCI latency timer from %hu to %hu", | ||
2768 | "changing", lat, pci_lat); | ||
2769 | pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat); | ||
2770 | } else if (lat < MIN_PCI_LATENCY) { | ||
2771 | PRINTK(KERN_INFO, "%s PCI latency timer from %hu to %hu", | ||
2772 | "increasing", lat, MIN_PCI_LATENCY); | ||
2773 | pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY); | ||
2774 | } | ||
2775 | |||
2776 | dev->iobase = iobase; | ||
2777 | dev->irq = irq; | ||
2778 | dev->membase = membase; | ||
2779 | |||
2780 | dev->rx_q_entry = dev->rx_q_reset = &memmap->rx_q_entries[0]; | ||
2781 | dev->rx_q_wrap = &memmap->rx_q_entries[RX_CHANS-1]; | ||
2782 | |||
2783 | // these next three are performance hacks | ||
2784 | dev->last_vc = -1; | ||
2785 | dev->tx_last = -1; | ||
2786 | dev->tx_idle = 0; | ||
2787 | |||
2788 | dev->tx_regions = 0; | ||
2789 | dev->tx_bytes = 0; | ||
2790 | dev->tx_skb = NULL; | ||
2791 | dev->tx_iovec = NULL; | ||
2792 | |||
2793 | dev->tx_cell_count = 0; | ||
2794 | dev->rx_cell_count = 0; | ||
2795 | dev->hec_error_count = 0; | ||
2796 | dev->unassigned_cell_count = 0; | ||
2797 | |||
2798 | dev->noof_spare_buffers = 0; | ||
2799 | |||
2800 | { | ||
2801 | unsigned int i; | ||
2802 | for (i = 0; i < TX_CHANS; ++i) | ||
2803 | dev->tx_channel_record[i] = -1; | ||
2804 | } | ||
2805 | |||
2806 | dev->flags = 0; | ||
2807 | |||
2808 | // Allocate cell rates and remember ASIC version | ||
2809 | // Fibre: ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53 | ||
2810 | // Copper: (WRONG) we want 6 into the above, close to 25Mb/s | ||
2811 | // Copper: (plagarise!) 25600000/8/270*260/53 - n/53 | ||
2812 | |||
2813 | if (hrz_init(dev)) { | ||
2814 | // to be really pedantic, this should be ATM_OC3c_PCR | ||
2815 | dev->tx_avail = ATM_OC3_PCR; | ||
2816 | dev->rx_avail = ATM_OC3_PCR; | ||
2817 | set_bit(ultra, &dev->flags); // NOT "|= ultra" ! | ||
2818 | } else { | ||
2819 | dev->tx_avail = ((25600000/8)*26)/(27*53); | ||
2820 | dev->rx_avail = ((25600000/8)*26)/(27*53); | ||
2821 | PRINTD(DBG_WARN, "Buggy ASIC: no TX bus-mastering."); | ||
2822 | } | ||
2823 | |||
2824 | // rate changes spinlock | ||
2825 | spin_lock_init(&dev->rate_lock); | ||
2826 | |||
2827 | // on-board memory access spinlock; we want atomic reads and | ||
2828 | // writes to adapter memory (handles IRQ and SMP) | ||
2829 | spin_lock_init(&dev->mem_lock); | ||
2830 | |||
2831 | init_waitqueue_head(&dev->tx_queue); | ||
2832 | |||
2833 | // vpi in 0..4, vci in 6..10 | ||
2834 | dev->atm_dev->ci_range.vpi_bits = vpi_bits; | ||
2835 | dev->atm_dev->ci_range.vci_bits = 10-vpi_bits; | ||
2836 | |||
2837 | init_timer(&dev->housekeeping); | ||
2838 | dev->housekeeping.function = do_housekeeping; | ||
2839 | dev->housekeeping.data = (unsigned long) dev; | ||
2840 | mod_timer(&dev->housekeeping, jiffies); | ||
2841 | |||
2842 | out: | ||
2843 | return err; | ||
2844 | |||
2845 | out_free_irq: | ||
2846 | free_irq(dev->irq, dev); | ||
2847 | out_free: | ||
2848 | kfree(dev); | ||
2849 | out_release: | ||
2850 | release_region(iobase, HRZ_IO_EXTENT); | ||
2851 | out_disable: | ||
2852 | pci_disable_device(pci_dev); | ||
2853 | goto out; | ||
2854 | } | ||
2855 | |||
2856 | static void __devexit hrz_remove_one(struct pci_dev *pci_dev) | ||
2857 | { | ||
2858 | hrz_dev *dev; | ||
2859 | |||
2860 | dev = pci_get_drvdata(pci_dev); | ||
2861 | |||
2862 | PRINTD(DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev); | ||
2863 | del_timer_sync(&dev->housekeeping); | ||
2864 | hrz_reset(dev); | ||
2865 | atm_dev_deregister(dev->atm_dev); | ||
2866 | free_irq(dev->irq, dev); | ||
2867 | release_region(dev->iobase, HRZ_IO_EXTENT); | ||
2868 | kfree(dev); | ||
2869 | |||
2870 | pci_disable_device(pci_dev); | ||
2871 | } | ||
2872 | |||
2873 | static void __init hrz_check_args (void) { | ||
2874 | #ifdef DEBUG_HORIZON | ||
2875 | PRINTK (KERN_NOTICE, "debug bitmap is %hx", debug &= DBG_MASK); | ||
2876 | #else | ||
2877 | if (debug) | ||
2878 | PRINTK (KERN_NOTICE, "no debug support in this image"); | ||
2879 | #endif | ||
2880 | |||
2881 | if (vpi_bits > HRZ_MAX_VPI) | ||
2882 | PRINTK (KERN_ERR, "vpi_bits has been limited to %hu", | ||
2883 | vpi_bits = HRZ_MAX_VPI); | ||
2884 | |||
2885 | if (max_tx_size < 0 || max_tx_size > TX_AAL5_LIMIT) | ||
2886 | PRINTK (KERN_NOTICE, "max_tx_size has been limited to %hu", | ||
2887 | max_tx_size = TX_AAL5_LIMIT); | ||
2888 | |||
2889 | if (max_rx_size < 0 || max_rx_size > RX_AAL5_LIMIT) | ||
2890 | PRINTK (KERN_NOTICE, "max_rx_size has been limited to %hu", | ||
2891 | max_rx_size = RX_AAL5_LIMIT); | ||
2892 | |||
2893 | return; | ||
2894 | } | ||
2895 | |||
2896 | MODULE_AUTHOR(maintainer_string); | ||
2897 | MODULE_DESCRIPTION(description_string); | ||
2898 | MODULE_LICENSE("GPL"); | ||
2899 | module_param(debug, ushort, 0644); | ||
2900 | module_param(vpi_bits, ushort, 0); | ||
2901 | module_param(max_tx_size, int, 0); | ||
2902 | module_param(max_rx_size, int, 0); | ||
2903 | module_param(pci_lat, byte, 0); | ||
2904 | MODULE_PARM_DESC(debug, "debug bitmap, see .h file"); | ||
2905 | MODULE_PARM_DESC(vpi_bits, "number of bits (0..4) to allocate to VPIs"); | ||
2906 | MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames"); | ||
2907 | MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames"); | ||
2908 | MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); | ||
2909 | |||
2910 | static struct pci_device_id hrz_pci_tbl[] = { | ||
2911 | { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID, | ||
2912 | 0, 0, 0 }, | ||
2913 | { 0, } | ||
2914 | }; | ||
2915 | |||
2916 | MODULE_DEVICE_TABLE(pci, hrz_pci_tbl); | ||
2917 | |||
2918 | static struct pci_driver hrz_driver = { | ||
2919 | .name = "horizon", | ||
2920 | .probe = hrz_probe, | ||
2921 | .remove = __devexit_p(hrz_remove_one), | ||
2922 | .id_table = hrz_pci_tbl, | ||
2923 | }; | ||
2924 | |||
2925 | /********** module entry **********/ | ||
2926 | |||
2927 | static int __init hrz_module_init (void) { | ||
2928 | // sanity check - cast is needed since printk does not support %Zu | ||
2929 | if (sizeof(struct MEMMAP) != 128*1024/4) { | ||
2930 | PRINTK (KERN_ERR, "Fix struct MEMMAP (is %lu fakewords).", | ||
2931 | (unsigned long) sizeof(struct MEMMAP)); | ||
2932 | return -ENOMEM; | ||
2933 | } | ||
2934 | |||
2935 | show_version(); | ||
2936 | |||
2937 | // check arguments | ||
2938 | hrz_check_args(); | ||
2939 | |||
2940 | // get the juice | ||
2941 | return pci_register_driver(&hrz_driver); | ||
2942 | } | ||
2943 | |||
2944 | /********** module exit **********/ | ||
2945 | |||
2946 | static void __exit hrz_module_exit (void) { | ||
2947 | PRINTD (DBG_FLOW, "cleanup_module"); | ||
2948 | |||
2949 | return pci_unregister_driver(&hrz_driver); | ||
2950 | } | ||
2951 | |||
2952 | module_init(hrz_module_init); | ||
2953 | module_exit(hrz_module_exit); | ||
diff --git a/drivers/atm/horizon.h b/drivers/atm/horizon.h new file mode 100644 index 000000000000..e2cc7020fa3b --- /dev/null +++ b/drivers/atm/horizon.h | |||
@@ -0,0 +1,508 @@ | |||
1 | /* | ||
2 | Madge Horizon ATM Adapter driver. | ||
3 | Copyright (C) 1995-1999 Madge Networks Ltd. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian | ||
20 | system and in the file COPYING in the Linux kernel source. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | IMPORTANT NOTE: Madge Networks no longer makes the adapters | ||
25 | supported by this driver and makes no commitment to maintain it. | ||
26 | */ | ||
27 | |||
28 | /* too many macros - change to inline functions */ | ||
29 | |||
30 | #ifndef DRIVER_ATM_HORIZON_H | ||
31 | #define DRIVER_ATM_HORIZON_H | ||
32 | |||
33 | #include <linux/config.h> | ||
34 | |||
35 | #ifdef CONFIG_ATM_HORIZON_DEBUG | ||
36 | #define DEBUG_HORIZON | ||
37 | #endif | ||
38 | |||
39 | #define DEV_LABEL "hrz" | ||
40 | |||
41 | #ifndef PCI_VENDOR_ID_MADGE | ||
42 | #define PCI_VENDOR_ID_MADGE 0x10B6 | ||
43 | #endif | ||
44 | #ifndef PCI_DEVICE_ID_MADGE_HORIZON | ||
45 | #define PCI_DEVICE_ID_MADGE_HORIZON 0x1000 | ||
46 | #endif | ||
47 | |||
48 | // diagnostic output | ||
49 | |||
50 | #define PRINTK(severity,format,args...) \ | ||
51 | printk(severity DEV_LABEL ": " format "\n" , ## args) | ||
52 | |||
53 | #ifdef DEBUG_HORIZON | ||
54 | |||
55 | #define DBG_ERR 0x0001 | ||
56 | #define DBG_WARN 0x0002 | ||
57 | #define DBG_INFO 0x0004 | ||
58 | #define DBG_VCC 0x0008 | ||
59 | #define DBG_QOS 0x0010 | ||
60 | #define DBG_TX 0x0020 | ||
61 | #define DBG_RX 0x0040 | ||
62 | #define DBG_SKB 0x0080 | ||
63 | #define DBG_IRQ 0x0100 | ||
64 | #define DBG_FLOW 0x0200 | ||
65 | #define DBG_BUS 0x0400 | ||
66 | #define DBG_REGS 0x0800 | ||
67 | #define DBG_DATA 0x1000 | ||
68 | #define DBG_MASK 0x1fff | ||
69 | |||
70 | /* the ## prevents the annoying double expansion of the macro arguments */ | ||
71 | /* KERN_INFO is used since KERN_DEBUG often does not make it to the console */ | ||
72 | #define PRINTDB(bits,format,args...) \ | ||
73 | ( (debug & (bits)) ? printk (KERN_INFO DEV_LABEL ": " format , ## args) : 1 ) | ||
74 | #define PRINTDM(bits,format,args...) \ | ||
75 | ( (debug & (bits)) ? printk (format , ## args) : 1 ) | ||
76 | #define PRINTDE(bits,format,args...) \ | ||
77 | ( (debug & (bits)) ? printk (format "\n" , ## args) : 1 ) | ||
78 | #define PRINTD(bits,format,args...) \ | ||
79 | ( (debug & (bits)) ? printk (KERN_INFO DEV_LABEL ": " format "\n" , ## args) : 1 ) | ||
80 | |||
81 | #else | ||
82 | |||
83 | #define PRINTD(bits,format,args...) | ||
84 | #define PRINTDB(bits,format,args...) | ||
85 | #define PRINTDM(bits,format,args...) | ||
86 | #define PRINTDE(bits,format,args...) | ||
87 | |||
88 | #endif | ||
89 | |||
90 | #define PRINTDD(sec,fmt,args...) | ||
91 | #define PRINTDDB(sec,fmt,args...) | ||
92 | #define PRINTDDM(sec,fmt,args...) | ||
93 | #define PRINTDDE(sec,fmt,args...) | ||
94 | |||
95 | // fixed constants | ||
96 | |||
97 | #define SPARE_BUFFER_POOL_SIZE MAX_VCS | ||
98 | #define HRZ_MAX_VPI 4 | ||
99 | #define MIN_PCI_LATENCY 48 // 24 IS TOO SMALL | ||
100 | |||
101 | /* Horizon specific bits */ | ||
102 | /* Register offsets */ | ||
103 | |||
104 | #define HRZ_IO_EXTENT 0x80 | ||
105 | |||
106 | #define DATA_PORT_OFF 0x00 | ||
107 | #define TX_CHANNEL_PORT_OFF 0x04 | ||
108 | #define TX_DESCRIPTOR_PORT_OFF 0x08 | ||
109 | #define MEMORY_PORT_OFF 0x0C | ||
110 | #define MEM_WR_ADDR_REG_OFF 0x14 | ||
111 | #define MEM_RD_ADDR_REG_OFF 0x18 | ||
112 | #define CONTROL_0_REG 0x1C | ||
113 | #define INT_SOURCE_REG_OFF 0x20 | ||
114 | #define INT_ENABLE_REG_OFF 0x24 | ||
115 | #define MASTER_RX_ADDR_REG_OFF 0x28 | ||
116 | #define MASTER_RX_COUNT_REG_OFF 0x2C | ||
117 | #define MASTER_TX_ADDR_REG_OFF 0x30 | ||
118 | #define MASTER_TX_COUNT_REG_OFF 0x34 | ||
119 | #define TX_DESCRIPTOR_REG_OFF 0x38 | ||
120 | #define TX_CHANNEL_CONFIG_COMMAND_OFF 0x40 | ||
121 | #define TX_CHANNEL_CONFIG_DATA_OFF 0x44 | ||
122 | #define TX_FREE_BUFFER_COUNT_OFF 0x48 | ||
123 | #define RX_FREE_BUFFER_COUNT_OFF 0x4C | ||
124 | #define TX_CONFIG_OFF 0x50 | ||
125 | #define TX_STATUS_OFF 0x54 | ||
126 | #define RX_CONFIG_OFF 0x58 | ||
127 | #define RX_LINE_CONFIG_OFF 0x5C | ||
128 | #define RX_QUEUE_RD_PTR_OFF 0x60 | ||
129 | #define RX_QUEUE_WR_PTR_OFF 0x64 | ||
130 | #define MAX_AAL5_CELL_COUNT_OFF 0x68 | ||
131 | #define RX_CHANNEL_PORT_OFF 0x6C | ||
132 | #define TX_CELL_COUNT_OFF 0x70 | ||
133 | #define RX_CELL_COUNT_OFF 0x74 | ||
134 | #define HEC_ERROR_COUNT_OFF 0x78 | ||
135 | #define UNASSIGNED_CELL_COUNT_OFF 0x7C | ||
136 | |||
137 | /* Register bit definitions */ | ||
138 | |||
139 | /* Control 0 register */ | ||
140 | |||
141 | #define SEEPROM_DO 0x00000001 | ||
142 | #define SEEPROM_DI 0x00000002 | ||
143 | #define SEEPROM_SK 0x00000004 | ||
144 | #define SEEPROM_CS 0x00000008 | ||
145 | #define DEBUG_BIT_0 0x00000010 | ||
146 | #define DEBUG_BIT_1 0x00000020 | ||
147 | #define DEBUG_BIT_2 0x00000040 | ||
148 | // RESERVED 0x00000080 | ||
149 | #define DEBUG_BIT_0_OE 0x00000100 | ||
150 | #define DEBUG_BIT_1_OE 0x00000200 | ||
151 | #define DEBUG_BIT_2_OE 0x00000400 | ||
152 | // RESERVED 0x00000800 | ||
153 | #define DEBUG_BIT_0_STATE 0x00001000 | ||
154 | #define DEBUG_BIT_1_STATE 0x00002000 | ||
155 | #define DEBUG_BIT_2_STATE 0x00004000 | ||
156 | // RESERVED 0x00008000 | ||
157 | #define GENERAL_BIT_0 0x00010000 | ||
158 | #define GENERAL_BIT_1 0x00020000 | ||
159 | #define GENERAL_BIT_2 0x00040000 | ||
160 | #define GENERAL_BIT_3 0x00080000 | ||
161 | #define RESET_HORIZON 0x00100000 | ||
162 | #define RESET_ATM 0x00200000 | ||
163 | #define RESET_RX 0x00400000 | ||
164 | #define RESET_TX 0x00800000 | ||
165 | #define RESET_HOST 0x01000000 | ||
166 | // RESERVED 0x02000000 | ||
167 | #define TARGET_RETRY_DISABLE 0x04000000 | ||
168 | #define ATM_LAYER_SELECT 0x08000000 | ||
169 | #define ATM_LAYER_STATUS 0x10000000 | ||
170 | // RESERVED 0xE0000000 | ||
171 | |||
172 | /* Interrupt source and enable registers */ | ||
173 | |||
174 | #define RX_DATA_AV 0x00000001 | ||
175 | #define RX_DISABLED 0x00000002 | ||
176 | #define TIMING_MARKER 0x00000004 | ||
177 | #define FORCED 0x00000008 | ||
178 | #define RX_BUS_MASTER_COMPLETE 0x00000010 | ||
179 | #define TX_BUS_MASTER_COMPLETE 0x00000020 | ||
180 | #define ABR_TX_CELL_COUNT_INT 0x00000040 | ||
181 | #define DEBUG_INT 0x00000080 | ||
182 | // RESERVED 0xFFFFFF00 | ||
183 | |||
184 | /* PIO and Bus Mastering */ | ||
185 | |||
186 | #define MAX_PIO_COUNT 0x000000ff // 255 - make tunable? | ||
187 | // 8188 is a hard limit for bus mastering | ||
188 | #define MAX_TRANSFER_COUNT 0x00001ffc // 8188 | ||
189 | #define MASTER_TX_AUTO_APPEND_DESC 0x80000000 | ||
190 | |||
191 | /* TX channel config command port */ | ||
192 | |||
193 | #define PCR_TIMER_ACCESS 0x0000 | ||
194 | #define SCR_TIMER_ACCESS 0x0001 | ||
195 | #define BUCKET_CAPACITY_ACCESS 0x0002 | ||
196 | #define BUCKET_FULLNESS_ACCESS 0x0003 | ||
197 | #define RATE_TYPE_ACCESS 0x0004 | ||
198 | // UNUSED 0x00F8 | ||
199 | #define TX_CHANNEL_CONFIG_MULT 0x0100 | ||
200 | // UNUSED 0xF800 | ||
201 | #define BUCKET_MAX_SIZE 0x003f | ||
202 | |||
203 | /* TX channel config data port */ | ||
204 | |||
205 | #define CLOCK_SELECT_SHIFT 4 | ||
206 | #define CLOCK_DISABLE 0x00ff | ||
207 | |||
208 | #define IDLE_RATE_TYPE 0x0 | ||
209 | #define ABR_RATE_TYPE 0x1 | ||
210 | #define VBR_RATE_TYPE 0x2 | ||
211 | #define CBR_RATE_TYPE 0x3 | ||
212 | |||
213 | /* TX config register */ | ||
214 | |||
215 | #define DRVR_DRVRBAR_ENABLE 0x0001 | ||
216 | #define TXCLK_MUX_SELECT_RCLK 0x0002 | ||
217 | #define TRANSMIT_TIMING_MARKER 0x0004 | ||
218 | #define LOOPBACK_TIMING_MARKER 0x0008 | ||
219 | #define TX_TEST_MODE_16MHz 0x0000 | ||
220 | #define TX_TEST_MODE_8MHz 0x0010 | ||
221 | #define TX_TEST_MODE_5_33MHz 0x0020 | ||
222 | #define TX_TEST_MODE_4MHz 0x0030 | ||
223 | #define TX_TEST_MODE_3_2MHz 0x0040 | ||
224 | #define TX_TEST_MODE_2_66MHz 0x0050 | ||
225 | #define TX_TEST_MODE_2_29MHz 0x0060 | ||
226 | #define TX_NORMAL_OPERATION 0x0070 | ||
227 | #define ABR_ROUND_ROBIN 0x0080 | ||
228 | |||
229 | /* TX status register */ | ||
230 | |||
231 | #define IDLE_CHANNELS_MASK 0x00FF | ||
232 | #define ABR_CELL_COUNT_REACHED_MULT 0x0100 | ||
233 | #define ABR_CELL_COUNT_REACHED_MASK 0xFF | ||
234 | |||
235 | /* RX config register */ | ||
236 | |||
237 | #define NON_USER_CELLS_IN_ONE_CHANNEL 0x0008 | ||
238 | #define RX_ENABLE 0x0010 | ||
239 | #define IGNORE_UNUSED_VPI_VCI_BITS_SET 0x0000 | ||
240 | #define NON_USER_UNUSED_VPI_VCI_BITS_SET 0x0020 | ||
241 | #define DISCARD_UNUSED_VPI_VCI_BITS_SET 0x0040 | ||
242 | |||
243 | /* RX line config register */ | ||
244 | |||
245 | #define SIGNAL_LOSS 0x0001 | ||
246 | #define FREQUENCY_DETECT_ERROR 0x0002 | ||
247 | #define LOCK_DETECT_ERROR 0x0004 | ||
248 | #define SELECT_INTERNAL_LOOPBACK 0x0008 | ||
249 | #define LOCK_DETECT_ENABLE 0x0010 | ||
250 | #define FREQUENCY_DETECT_ENABLE 0x0020 | ||
251 | #define USER_FRAQ 0x0040 | ||
252 | #define GXTALOUT_SELECT_DIV4 0x0080 | ||
253 | #define GXTALOUT_SELECT_NO_GATING 0x0100 | ||
254 | #define TIMING_MARKER_RECEIVED 0x0200 | ||
255 | |||
256 | /* RX channel port */ | ||
257 | |||
258 | #define RX_CHANNEL_MASK 0x03FF | ||
259 | // UNUSED 0x3C00 | ||
260 | #define FLUSH_CHANNEL 0x4000 | ||
261 | #define RX_CHANNEL_UPDATE_IN_PROGRESS 0x8000 | ||
262 | |||
263 | /* Receive queue entry */ | ||
264 | |||
265 | #define RX_Q_ENTRY_LENGTH_MASK 0x0000FFFF | ||
266 | #define RX_Q_ENTRY_CHANNEL_SHIFT 16 | ||
267 | #define SIMONS_DODGEY_MARKER 0x08000000 | ||
268 | #define RX_CONGESTION_EXPERIENCED 0x10000000 | ||
269 | #define RX_CRC_10_OK 0x20000000 | ||
270 | #define RX_CRC_32_OK 0x40000000 | ||
271 | #define RX_COMPLETE_FRAME 0x80000000 | ||
272 | |||
273 | /* Offsets and constants for use with the buffer memory */ | ||
274 | |||
275 | /* Buffer pointers and channel types */ | ||
276 | |||
277 | #define BUFFER_PTR_MASK 0x0000FFFF | ||
278 | #define RX_INT_THRESHOLD_MULT 0x00010000 | ||
279 | #define RX_INT_THRESHOLD_MASK 0x07FF | ||
280 | #define INT_EVERY_N_CELLS 0x08000000 | ||
281 | #define CONGESTION_EXPERIENCED 0x10000000 | ||
282 | #define FIRST_CELL_OF_AAL5_FRAME 0x20000000 | ||
283 | #define CHANNEL_TYPE_AAL5 0x00000000 | ||
284 | #define CHANNEL_TYPE_RAW_CELLS 0x40000000 | ||
285 | #define CHANNEL_TYPE_AAL3_4 0x80000000 | ||
286 | |||
287 | /* Buffer status stuff */ | ||
288 | |||
289 | #define BUFF_STATUS_MASK 0x00030000 | ||
290 | #define BUFF_STATUS_EMPTY 0x00000000 | ||
291 | #define BUFF_STATUS_CELL_AV 0x00010000 | ||
292 | #define BUFF_STATUS_LAST_CELL_AV 0x00020000 | ||
293 | |||
294 | /* Transmit channel stuff */ | ||
295 | |||
296 | /* Receive channel stuff */ | ||
297 | |||
298 | #define RX_CHANNEL_DISABLED 0x00000000 | ||
299 | #define RX_CHANNEL_IDLE 0x00000001 | ||
300 | |||
301 | /* General things */ | ||
302 | |||
303 | #define INITIAL_CRC 0xFFFFFFFF | ||
304 | |||
305 | // A Horizon u32, a byte! Really nasty. Horizon pointers are (32 bit) | ||
306 | // word addresses and so standard C pointer operations break (as they | ||
307 | // assume byte addresses); so we pretend that Horizon words (and word | ||
308 | // pointers) are bytes (and byte pointers) for the purposes of having | ||
309 | // a memory map that works. | ||
310 | |||
311 | typedef u8 HDW; | ||
312 | |||
313 | typedef struct cell_buf { | ||
314 | HDW payload[12]; | ||
315 | HDW next; | ||
316 | HDW cell_count; // AAL5 rx bufs | ||
317 | HDW res; | ||
318 | union { | ||
319 | HDW partial_crc; // AAL5 rx bufs | ||
320 | HDW cell_header; // RAW bufs | ||
321 | } u; | ||
322 | } cell_buf; | ||
323 | |||
324 | typedef struct tx_ch_desc { | ||
325 | HDW rd_buf_type; | ||
326 | HDW wr_buf_type; | ||
327 | HDW partial_crc; | ||
328 | HDW cell_header; | ||
329 | } tx_ch_desc; | ||
330 | |||
331 | typedef struct rx_ch_desc { | ||
332 | HDW wr_buf_type; | ||
333 | HDW rd_buf_type; | ||
334 | } rx_ch_desc; | ||
335 | |||
336 | typedef struct rx_q_entry { | ||
337 | HDW entry; | ||
338 | } rx_q_entry; | ||
339 | |||
340 | #define TX_CHANS 8 | ||
341 | #define RX_CHANS 1024 | ||
342 | #define RX_QS 1024 | ||
343 | #define MAX_VCS RX_CHANS | ||
344 | |||
345 | /* Horizon buffer memory map */ | ||
346 | |||
347 | // TX Channel Descriptors 2 | ||
348 | // TX Initial Buffers 8 // TX_CHANS | ||
349 | #define BUFN1_SIZE 118 // (126 - TX_CHANS) | ||
350 | // RX/TX Start/End Buffers 4 | ||
351 | #define BUFN2_SIZE 124 | ||
352 | // RX Queue Entries 64 | ||
353 | #define BUFN3_SIZE 192 | ||
354 | // RX Channel Descriptors 128 | ||
355 | #define BUFN4_SIZE 1408 | ||
356 | // TOTAL cell_buff chunks 2048 | ||
357 | |||
358 | // cell_buf bufs[2048]; | ||
359 | // HDW dws[32768]; | ||
360 | |||
361 | typedef struct MEMMAP { | ||
362 | tx_ch_desc tx_descs[TX_CHANS]; // 8 * 4 = 32 , 0x0020 | ||
363 | cell_buf inittxbufs[TX_CHANS]; // these are really | ||
364 | cell_buf bufn1[BUFN1_SIZE]; // part of this pool | ||
365 | cell_buf txfreebufstart; | ||
366 | cell_buf txfreebufend; | ||
367 | cell_buf rxfreebufstart; | ||
368 | cell_buf rxfreebufend; // 8+118+1+1+1+1+124 = 254 | ||
369 | cell_buf bufn2[BUFN2_SIZE]; // 16 * 254 = 4064 , 0x1000 | ||
370 | rx_q_entry rx_q_entries[RX_QS]; // 1 * 1024 = 1024 , 0x1400 | ||
371 | cell_buf bufn3[BUFN3_SIZE]; // 16 * 192 = 3072 , 0x2000 | ||
372 | rx_ch_desc rx_descs[MAX_VCS]; // 2 * 1024 = 2048 , 0x2800 | ||
373 | cell_buf bufn4[BUFN4_SIZE]; // 16 * 1408 = 22528 , 0x8000 | ||
374 | } MEMMAP; | ||
375 | |||
376 | #define memmap ((MEMMAP *)0) | ||
377 | |||
378 | /* end horizon specific bits */ | ||
379 | |||
380 | typedef enum { | ||
381 | aal0, | ||
382 | aal34, | ||
383 | aal5 | ||
384 | } hrz_aal; | ||
385 | |||
386 | typedef enum { | ||
387 | tx_busy, | ||
388 | rx_busy, | ||
389 | ultra | ||
390 | } hrz_flags; | ||
391 | |||
392 | // a single struct pointed to by atm_vcc->dev_data | ||
393 | |||
394 | typedef struct { | ||
395 | unsigned int tx_rate; | ||
396 | unsigned int rx_rate; | ||
397 | u16 channel; | ||
398 | u16 tx_xbr_bits; | ||
399 | u16 tx_pcr_bits; | ||
400 | #if 0 | ||
401 | u16 tx_scr_bits; | ||
402 | u16 tx_bucket_bits; | ||
403 | #endif | ||
404 | hrz_aal aal; | ||
405 | } hrz_vcc; | ||
406 | |||
407 | struct hrz_dev { | ||
408 | |||
409 | u32 iobase; | ||
410 | u32 * membase; | ||
411 | |||
412 | struct sk_buff * rx_skb; // skb being RXed | ||
413 | unsigned int rx_bytes; // bytes remaining to RX within region | ||
414 | void * rx_addr; // addr to send bytes to (for PIO) | ||
415 | unsigned int rx_channel; // channel that the skb is going out on | ||
416 | |||
417 | struct sk_buff * tx_skb; // skb being TXed | ||
418 | unsigned int tx_bytes; // bytes remaining to TX within region | ||
419 | void * tx_addr; // addr to send bytes from (for PIO) | ||
420 | struct iovec * tx_iovec; // remaining regions | ||
421 | unsigned int tx_regions; // number of remaining regions | ||
422 | |||
423 | spinlock_t mem_lock; | ||
424 | wait_queue_head_t tx_queue; | ||
425 | |||
426 | u8 irq; | ||
427 | long flags; | ||
428 | u8 tx_last; | ||
429 | u8 tx_idle; | ||
430 | |||
431 | rx_q_entry * rx_q_reset; | ||
432 | rx_q_entry * rx_q_entry; | ||
433 | rx_q_entry * rx_q_wrap; | ||
434 | |||
435 | struct atm_dev * atm_dev; | ||
436 | |||
437 | u32 last_vc; | ||
438 | |||
439 | int noof_spare_buffers; | ||
440 | u16 spare_buffers[SPARE_BUFFER_POOL_SIZE]; | ||
441 | |||
442 | u16 tx_channel_record[TX_CHANS]; | ||
443 | |||
444 | // this is what we follow when we get incoming data | ||
445 | u32 txer[MAX_VCS/32]; | ||
446 | struct atm_vcc * rxer[MAX_VCS]; | ||
447 | |||
448 | // cell rate allocation | ||
449 | spinlock_t rate_lock; | ||
450 | unsigned int rx_avail; | ||
451 | unsigned int tx_avail; | ||
452 | |||
453 | // dev stats | ||
454 | unsigned long tx_cell_count; | ||
455 | unsigned long rx_cell_count; | ||
456 | unsigned long hec_error_count; | ||
457 | unsigned long unassigned_cell_count; | ||
458 | |||
459 | struct pci_dev * pci_dev; | ||
460 | struct timer_list housekeeping; | ||
461 | }; | ||
462 | |||
463 | typedef struct hrz_dev hrz_dev; | ||
464 | |||
465 | /* macros for use later */ | ||
466 | |||
467 | #define BUF_PTR(cbptr) ((cbptr) - (cell_buf *) 0) | ||
468 | |||
469 | #define INTERESTING_INTERRUPTS \ | ||
470 | (RX_DATA_AV | RX_DISABLED | TX_BUS_MASTER_COMPLETE | RX_BUS_MASTER_COMPLETE) | ||
471 | |||
472 | // 190 cells by default (192 TX buffers - 2 elbow room, see docs) | ||
473 | #define TX_AAL5_LIMIT (190*ATM_CELL_PAYLOAD-ATM_AAL5_TRAILER) // 9112 | ||
474 | |||
475 | // Have enough RX buffers (unless we allow other buffer splits) | ||
476 | #define RX_AAL5_LIMIT ATM_MAX_AAL5_PDU | ||
477 | |||
478 | /* multi-statement macro protector */ | ||
479 | #define DW(x) do{ x } while(0) | ||
480 | |||
481 | #define HRZ_DEV(atm_dev) ((hrz_dev *) (atm_dev)->dev_data) | ||
482 | #define HRZ_VCC(atm_vcc) ((hrz_vcc *) (atm_vcc)->dev_data) | ||
483 | |||
484 | /* Turn the LEDs on and off */ | ||
485 | // The LEDs bits are upside down in that setting the bit in the debug | ||
486 | // register will turn the appropriate LED off. | ||
487 | |||
488 | #define YELLOW_LED DEBUG_BIT_0 | ||
489 | #define GREEN_LED DEBUG_BIT_1 | ||
490 | #define YELLOW_LED_OE DEBUG_BIT_0_OE | ||
491 | #define GREEN_LED_OE DEBUG_BIT_1_OE | ||
492 | |||
493 | #define GREEN_LED_OFF(dev) \ | ||
494 | wr_regl (dev, CONTROL_0_REG, rd_regl (dev, CONTROL_0_REG) | GREEN_LED) | ||
495 | #define GREEN_LED_ON(dev) \ | ||
496 | wr_regl (dev, CONTROL_0_REG, rd_regl (dev, CONTROL_0_REG) &~ GREEN_LED) | ||
497 | #define YELLOW_LED_OFF(dev) \ | ||
498 | wr_regl (dev, CONTROL_0_REG, rd_regl (dev, CONTROL_0_REG) | YELLOW_LED) | ||
499 | #define YELLOW_LED_ON(dev) \ | ||
500 | wr_regl (dev, CONTROL_0_REG, rd_regl (dev, CONTROL_0_REG) &~ YELLOW_LED) | ||
501 | |||
502 | typedef enum { | ||
503 | round_up, | ||
504 | round_down, | ||
505 | round_nearest | ||
506 | } rounding; | ||
507 | |||
508 | #endif /* DRIVER_ATM_HORIZON_H */ | ||
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c new file mode 100644 index 000000000000..b8c260ed4b27 --- /dev/null +++ b/drivers/atm/idt77105.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* drivers/atm/idt77105.c - IDT77105 (PHY) driver */ | ||
2 | |||
3 | /* Written 1999 by Greg Banks, NEC Australia <gnb@linuxfan.com>. Based on suni.c */ | ||
4 | |||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/sched.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/atmdev.h> | ||
12 | #include <linux/sonet.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/timer.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/capability.h> | ||
17 | #include <linux/atm_idt77105.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <asm/system.h> | ||
20 | #include <asm/param.h> | ||
21 | #include <asm/uaccess.h> | ||
22 | |||
23 | #include "idt77105.h" | ||
24 | |||
25 | #undef GENERAL_DEBUG | ||
26 | |||
27 | #ifdef GENERAL_DEBUG | ||
28 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
29 | #else | ||
30 | #define DPRINTK(format,args...) | ||
31 | #endif | ||
32 | |||
33 | |||
34 | struct idt77105_priv { | ||
35 | struct idt77105_stats stats; /* link diagnostics */ | ||
36 | struct atm_dev *dev; /* device back-pointer */ | ||
37 | struct idt77105_priv *next; | ||
38 | int loop_mode; | ||
39 | unsigned char old_mcr; /* storage of MCR reg while signal lost */ | ||
40 | }; | ||
41 | |||
42 | static DEFINE_SPINLOCK(idt77105_priv_lock); | ||
43 | |||
44 | #define PRIV(dev) ((struct idt77105_priv *) dev->phy_data) | ||
45 | |||
46 | #define PUT(val,reg) dev->ops->phy_put(dev,val,IDT77105_##reg) | ||
47 | #define GET(reg) dev->ops->phy_get(dev,IDT77105_##reg) | ||
48 | |||
49 | static void idt77105_stats_timer_func(unsigned long); | ||
50 | static void idt77105_restart_timer_func(unsigned long); | ||
51 | |||
52 | |||
53 | static struct timer_list stats_timer = | ||
54 | TIMER_INITIALIZER(idt77105_stats_timer_func, 0, 0); | ||
55 | static struct timer_list restart_timer = | ||
56 | TIMER_INITIALIZER(idt77105_restart_timer_func, 0, 0); | ||
57 | static int start_timer = 1; | ||
58 | static struct idt77105_priv *idt77105_all = NULL; | ||
59 | |||
60 | /* | ||
61 | * Retrieve the value of one of the IDT77105's counters. | ||
62 | * `counter' is one of the IDT77105_CTRSEL_* constants. | ||
63 | */ | ||
64 | static u16 get_counter(struct atm_dev *dev, int counter) | ||
65 | { | ||
66 | u16 val; | ||
67 | |||
68 | /* write the counter bit into PHY register 6 */ | ||
69 | PUT(counter, CTRSEL); | ||
70 | /* read the low 8 bits from register 4 */ | ||
71 | val = GET(CTRLO); | ||
72 | /* read the high 8 bits from register 5 */ | ||
73 | val |= GET(CTRHI)<<8; | ||
74 | |||
75 | return val; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Timer function called every second to gather statistics | ||
80 | * from the 77105. This is done because the h/w registers | ||
81 | * will overflow if not read at least once per second. The | ||
82 | * kernel's stats are much higher precision. Also, having | ||
83 | * a separate copy of the stats allows implementation of | ||
84 | * an ioctl which gathers the stats *without* zero'ing them. | ||
85 | */ | ||
86 | static void idt77105_stats_timer_func(unsigned long dummy) | ||
87 | { | ||
88 | struct idt77105_priv *walk; | ||
89 | struct atm_dev *dev; | ||
90 | struct idt77105_stats *stats; | ||
91 | |||
92 | DPRINTK("IDT77105 gathering statistics\n"); | ||
93 | for (walk = idt77105_all; walk; walk = walk->next) { | ||
94 | dev = walk->dev; | ||
95 | |||
96 | stats = &walk->stats; | ||
97 | stats->symbol_errors += get_counter(dev, IDT77105_CTRSEL_SEC); | ||
98 | stats->tx_cells += get_counter(dev, IDT77105_CTRSEL_TCC); | ||
99 | stats->rx_cells += get_counter(dev, IDT77105_CTRSEL_RCC); | ||
100 | stats->rx_hec_errors += get_counter(dev, IDT77105_CTRSEL_RHEC); | ||
101 | } | ||
102 | if (!start_timer) mod_timer(&stats_timer,jiffies+IDT77105_STATS_TIMER_PERIOD); | ||
103 | } | ||
104 | |||
105 | |||
106 | /* | ||
107 | * A separate timer func which handles restarting PHY chips which | ||
108 | * have had the cable re-inserted after being pulled out. This is | ||
109 | * done by polling the Good Signal Bit in the Interrupt Status | ||
110 | * register every 5 seconds. The other technique (checking Good | ||
111 | * Signal Bit in the interrupt handler) cannot be used because PHY | ||
112 | * interrupts need to be disabled when the cable is pulled out | ||
113 | * to avoid lots of spurious cell error interrupts. | ||
114 | */ | ||
115 | static void idt77105_restart_timer_func(unsigned long dummy) | ||
116 | { | ||
117 | struct idt77105_priv *walk; | ||
118 | struct atm_dev *dev; | ||
119 | unsigned char istat; | ||
120 | |||
121 | DPRINTK("IDT77105 checking for cable re-insertion\n"); | ||
122 | for (walk = idt77105_all; walk; walk = walk->next) { | ||
123 | dev = walk->dev; | ||
124 | |||
125 | if (dev->signal != ATM_PHY_SIG_LOST) | ||
126 | continue; | ||
127 | |||
128 | istat = GET(ISTAT); /* side effect: clears all interrupt status bits */ | ||
129 | if (istat & IDT77105_ISTAT_GOODSIG) { | ||
130 | /* Found signal again */ | ||
131 | dev->signal = ATM_PHY_SIG_FOUND; | ||
132 | printk(KERN_NOTICE "%s(itf %d): signal detected again\n", | ||
133 | dev->type,dev->number); | ||
134 | /* flush the receive FIFO */ | ||
135 | PUT( GET(DIAG) | IDT77105_DIAG_RFLUSH, DIAG); | ||
136 | /* re-enable interrupts */ | ||
137 | PUT( walk->old_mcr ,MCR); | ||
138 | } | ||
139 | } | ||
140 | if (!start_timer) mod_timer(&restart_timer,jiffies+IDT77105_RESTART_TIMER_PERIOD); | ||
141 | } | ||
142 | |||
143 | |||
144 | static int fetch_stats(struct atm_dev *dev,struct idt77105_stats __user *arg,int zero) | ||
145 | { | ||
146 | unsigned long flags; | ||
147 | struct idt77105_stats stats; | ||
148 | |||
149 | spin_lock_irqsave(&idt77105_priv_lock, flags); | ||
150 | memcpy(&stats, &PRIV(dev)->stats, sizeof(struct idt77105_stats)); | ||
151 | if (zero) | ||
152 | memset(&PRIV(dev)->stats, 0, sizeof(struct idt77105_stats)); | ||
153 | spin_unlock_irqrestore(&idt77105_priv_lock, flags); | ||
154 | if (arg == NULL) | ||
155 | return 0; | ||
156 | return copy_to_user(arg, &PRIV(dev)->stats, | ||
157 | sizeof(struct idt77105_stats)) ? -EFAULT : 0; | ||
158 | } | ||
159 | |||
160 | |||
161 | static int set_loopback(struct atm_dev *dev,int mode) | ||
162 | { | ||
163 | int diag; | ||
164 | |||
165 | diag = GET(DIAG) & ~IDT77105_DIAG_LCMASK; | ||
166 | switch (mode) { | ||
167 | case ATM_LM_NONE: | ||
168 | break; | ||
169 | case ATM_LM_LOC_ATM: | ||
170 | diag |= IDT77105_DIAG_LC_PHY_LOOPBACK; | ||
171 | break; | ||
172 | case ATM_LM_RMT_ATM: | ||
173 | diag |= IDT77105_DIAG_LC_LINE_LOOPBACK; | ||
174 | break; | ||
175 | default: | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | PUT(diag,DIAG); | ||
179 | printk(KERN_NOTICE "%s(%d) Loopback mode is: %s\n", dev->type, | ||
180 | dev->number, | ||
181 | (mode == ATM_LM_NONE ? "NONE" : | ||
182 | (mode == ATM_LM_LOC_ATM ? "DIAG (local)" : | ||
183 | (mode == IDT77105_DIAG_LC_LINE_LOOPBACK ? "LOOP (remote)" : | ||
184 | "unknown"))) | ||
185 | ); | ||
186 | PRIV(dev)->loop_mode = mode; | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | |||
191 | static int idt77105_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
192 | { | ||
193 | printk(KERN_NOTICE "%s(%d) idt77105_ioctl() called\n",dev->type,dev->number); | ||
194 | switch (cmd) { | ||
195 | case IDT77105_GETSTATZ: | ||
196 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
197 | /* fall through */ | ||
198 | case IDT77105_GETSTAT: | ||
199 | return fetch_stats(dev, arg, cmd == IDT77105_GETSTATZ); | ||
200 | case ATM_SETLOOP: | ||
201 | return set_loopback(dev,(int)(unsigned long) arg); | ||
202 | case ATM_GETLOOP: | ||
203 | return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ? | ||
204 | -EFAULT : 0; | ||
205 | case ATM_QUERYLOOP: | ||
206 | return put_user(ATM_LM_LOC_ATM | ATM_LM_RMT_ATM, | ||
207 | (int __user *) arg) ? -EFAULT : 0; | ||
208 | default: | ||
209 | return -ENOIOCTLCMD; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | |||
214 | |||
215 | static void idt77105_int(struct atm_dev *dev) | ||
216 | { | ||
217 | unsigned char istat; | ||
218 | |||
219 | istat = GET(ISTAT); /* side effect: clears all interrupt status bits */ | ||
220 | |||
221 | DPRINTK("IDT77105 generated an interrupt, istat=%02x\n", (unsigned)istat); | ||
222 | |||
223 | if (istat & IDT77105_ISTAT_RSCC) { | ||
224 | /* Rx Signal Condition Change - line went up or down */ | ||
225 | if (istat & IDT77105_ISTAT_GOODSIG) { /* signal detected again */ | ||
226 | /* This should not happen (restart timer does it) but JIC */ | ||
227 | dev->signal = ATM_PHY_SIG_FOUND; | ||
228 | } else { /* signal lost */ | ||
229 | /* | ||
230 | * Disable interrupts and stop all transmission and | ||
231 | * reception - the restart timer will restore these. | ||
232 | */ | ||
233 | PRIV(dev)->old_mcr = GET(MCR); | ||
234 | PUT( | ||
235 | (PRIV(dev)->old_mcr| | ||
236 | IDT77105_MCR_DREC| | ||
237 | IDT77105_MCR_DRIC| | ||
238 | IDT77105_MCR_HALTTX | ||
239 | ) & ~IDT77105_MCR_EIP, MCR); | ||
240 | dev->signal = ATM_PHY_SIG_LOST; | ||
241 | printk(KERN_NOTICE "%s(itf %d): signal lost\n", | ||
242 | dev->type,dev->number); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | if (istat & IDT77105_ISTAT_RFO) { | ||
247 | /* Rx FIFO Overrun -- perform a FIFO flush */ | ||
248 | PUT( GET(DIAG) | IDT77105_DIAG_RFLUSH, DIAG); | ||
249 | printk(KERN_NOTICE "%s(itf %d): receive FIFO overrun\n", | ||
250 | dev->type,dev->number); | ||
251 | } | ||
252 | #ifdef GENERAL_DEBUG | ||
253 | if (istat & (IDT77105_ISTAT_HECERR | IDT77105_ISTAT_SCR | | ||
254 | IDT77105_ISTAT_RSE)) { | ||
255 | /* normally don't care - just report in stats */ | ||
256 | printk(KERN_NOTICE "%s(itf %d): received cell with error\n", | ||
257 | dev->type,dev->number); | ||
258 | } | ||
259 | #endif | ||
260 | } | ||
261 | |||
262 | |||
263 | static int idt77105_start(struct atm_dev *dev) | ||
264 | { | ||
265 | unsigned long flags; | ||
266 | |||
267 | if (!(dev->dev_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL))) | ||
268 | return -ENOMEM; | ||
269 | PRIV(dev)->dev = dev; | ||
270 | spin_lock_irqsave(&idt77105_priv_lock, flags); | ||
271 | PRIV(dev)->next = idt77105_all; | ||
272 | idt77105_all = PRIV(dev); | ||
273 | spin_unlock_irqrestore(&idt77105_priv_lock, flags); | ||
274 | memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats)); | ||
275 | |||
276 | /* initialise dev->signal from Good Signal Bit */ | ||
277 | dev->signal = GET(ISTAT) & IDT77105_ISTAT_GOODSIG ? ATM_PHY_SIG_FOUND : | ||
278 | ATM_PHY_SIG_LOST; | ||
279 | if (dev->signal == ATM_PHY_SIG_LOST) | ||
280 | printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type, | ||
281 | dev->number); | ||
282 | |||
283 | /* initialise loop mode from hardware */ | ||
284 | switch ( GET(DIAG) & IDT77105_DIAG_LCMASK ) { | ||
285 | case IDT77105_DIAG_LC_NORMAL: | ||
286 | PRIV(dev)->loop_mode = ATM_LM_NONE; | ||
287 | break; | ||
288 | case IDT77105_DIAG_LC_PHY_LOOPBACK: | ||
289 | PRIV(dev)->loop_mode = ATM_LM_LOC_ATM; | ||
290 | break; | ||
291 | case IDT77105_DIAG_LC_LINE_LOOPBACK: | ||
292 | PRIV(dev)->loop_mode = ATM_LM_RMT_ATM; | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | /* enable interrupts, e.g. on loss of signal */ | ||
297 | PRIV(dev)->old_mcr = GET(MCR); | ||
298 | if (dev->signal == ATM_PHY_SIG_FOUND) { | ||
299 | PRIV(dev)->old_mcr |= IDT77105_MCR_EIP; | ||
300 | PUT(PRIV(dev)->old_mcr, MCR); | ||
301 | } | ||
302 | |||
303 | |||
304 | idt77105_stats_timer_func(0); /* clear 77105 counters */ | ||
305 | (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ | ||
306 | |||
307 | spin_lock_irqsave(&idt77105_priv_lock, flags); | ||
308 | if (start_timer) { | ||
309 | start_timer = 0; | ||
310 | |||
311 | init_timer(&stats_timer); | ||
312 | stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD; | ||
313 | stats_timer.function = idt77105_stats_timer_func; | ||
314 | add_timer(&stats_timer); | ||
315 | |||
316 | init_timer(&restart_timer); | ||
317 | restart_timer.expires = jiffies+IDT77105_RESTART_TIMER_PERIOD; | ||
318 | restart_timer.function = idt77105_restart_timer_func; | ||
319 | add_timer(&restart_timer); | ||
320 | } | ||
321 | spin_unlock_irqrestore(&idt77105_priv_lock, flags); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | |||
326 | static int idt77105_stop(struct atm_dev *dev) | ||
327 | { | ||
328 | struct idt77105_priv *walk, *prev; | ||
329 | |||
330 | DPRINTK("%s(itf %d): stopping IDT77105\n",dev->type,dev->number); | ||
331 | |||
332 | /* disable interrupts */ | ||
333 | PUT( GET(MCR) & ~IDT77105_MCR_EIP, MCR ); | ||
334 | |||
335 | /* detach private struct from atm_dev & free */ | ||
336 | for (prev = NULL, walk = idt77105_all ; | ||
337 | walk != NULL; | ||
338 | prev = walk, walk = walk->next) { | ||
339 | if (walk->dev == dev) { | ||
340 | if (prev != NULL) | ||
341 | prev->next = walk->next; | ||
342 | else | ||
343 | idt77105_all = walk->next; | ||
344 | dev->phy = NULL; | ||
345 | dev->dev_data = NULL; | ||
346 | kfree(walk); | ||
347 | break; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | |||
355 | static const struct atmphy_ops idt77105_ops = { | ||
356 | .start = idt77105_start, | ||
357 | .ioctl = idt77105_ioctl, | ||
358 | .interrupt = idt77105_int, | ||
359 | .stop = idt77105_stop, | ||
360 | }; | ||
361 | |||
362 | |||
363 | int idt77105_init(struct atm_dev *dev) | ||
364 | { | ||
365 | dev->phy = &idt77105_ops; | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | EXPORT_SYMBOL(idt77105_init); | ||
370 | |||
371 | static void __exit idt77105_exit(void) | ||
372 | { | ||
373 | /* turn off timers */ | ||
374 | del_timer(&stats_timer); | ||
375 | del_timer(&restart_timer); | ||
376 | } | ||
377 | |||
378 | module_exit(idt77105_exit); | ||
379 | |||
380 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/atm/idt77105.h b/drivers/atm/idt77105.h new file mode 100644 index 000000000000..8ba8218aaefe --- /dev/null +++ b/drivers/atm/idt77105.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* drivers/atm/idt77105.h - IDT77105 (PHY) declarations */ | ||
2 | |||
3 | /* Written 1999 by Greg Banks, NEC Australia <gnb@linuxfan.com>. Based on suni.h */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVER_ATM_IDT77105_H | ||
7 | #define DRIVER_ATM_IDT77105_H | ||
8 | |||
9 | #include <linux/atmdev.h> | ||
10 | #include <linux/atmioc.h> | ||
11 | |||
12 | |||
13 | /* IDT77105 registers */ | ||
14 | |||
15 | #define IDT77105_MCR 0x0 /* Master Control Register */ | ||
16 | #define IDT77105_ISTAT 0x1 /* Interrupt Status */ | ||
17 | #define IDT77105_DIAG 0x2 /* Diagnostic Control */ | ||
18 | #define IDT77105_LEDHEC 0x3 /* LED Driver & HEC Status/Control */ | ||
19 | #define IDT77105_CTRLO 0x4 /* Low Byte Counter Register */ | ||
20 | #define IDT77105_CTRHI 0x5 /* High Byte Counter Register */ | ||
21 | #define IDT77105_CTRSEL 0x6 /* Counter Register Read Select */ | ||
22 | |||
23 | /* IDT77105 register values */ | ||
24 | |||
25 | /* MCR */ | ||
26 | #define IDT77105_MCR_UPLO 0x80 /* R/W, User Prog'le Output Latch */ | ||
27 | #define IDT77105_MCR_DREC 0x40 /* R/W, Discard Receive Error Cells */ | ||
28 | #define IDT77105_MCR_ECEIO 0x20 /* R/W, Enable Cell Error Interrupts | ||
29 | * Only */ | ||
30 | #define IDT77105_MCR_TDPC 0x10 /* R/W, Transmit Data Parity Check */ | ||
31 | #define IDT77105_MCR_DRIC 0x08 /* R/W, Discard Received Idle Cells */ | ||
32 | #define IDT77105_MCR_HALTTX 0x04 /* R/W, Halt Tx */ | ||
33 | #define IDT77105_MCR_UMODE 0x02 /* R/W, Utopia (cell/byte) Mode */ | ||
34 | #define IDT77105_MCR_EIP 0x01 /* R/W, Enable Interrupt Pin */ | ||
35 | |||
36 | /* ISTAT */ | ||
37 | #define IDT77105_ISTAT_GOODSIG 0x40 /* R, Good Signal Bit */ | ||
38 | #define IDT77105_ISTAT_HECERR 0x20 /* sticky, HEC Error*/ | ||
39 | #define IDT77105_ISTAT_SCR 0x10 /* sticky, Short Cell Received */ | ||
40 | #define IDT77105_ISTAT_TPE 0x08 /* sticky, Transmit Parity Error */ | ||
41 | #define IDT77105_ISTAT_RSCC 0x04 /* sticky, Rx Signal Condition Change */ | ||
42 | #define IDT77105_ISTAT_RSE 0x02 /* sticky, Rx Symbol Error */ | ||
43 | #define IDT77105_ISTAT_RFO 0x01 /* sticky, Rx FIFO Overrun */ | ||
44 | |||
45 | /* DIAG */ | ||
46 | #define IDT77105_DIAG_FTD 0x80 /* R/W, Force TxClav deassert */ | ||
47 | #define IDT77105_DIAG_ROS 0x40 /* R/W, RxClav operation select */ | ||
48 | #define IDT77105_DIAG_MPCS 0x20 /* R/W, Multi-PHY config'n select */ | ||
49 | #define IDT77105_DIAG_RFLUSH 0x10 /* R/W, clear receive FIFO */ | ||
50 | #define IDT77105_DIAG_ITPE 0x08 /* R/W, Insert Tx payload error */ | ||
51 | #define IDT77105_DIAG_ITHE 0x04 /* R/W, Insert Tx HEC error */ | ||
52 | #define IDT77105_DIAG_UMODE 0x02 /* R/W, Utopia (cell/byte) Mode */ | ||
53 | #define IDT77105_DIAG_LCMASK 0x03 /* R/W, Loopback Control */ | ||
54 | |||
55 | #define IDT77105_DIAG_LC_NORMAL 0x00 /* Receive from network */ | ||
56 | #define IDT77105_DIAG_LC_PHY_LOOPBACK 0x02 | ||
57 | #define IDT77105_DIAG_LC_LINE_LOOPBACK 0x03 | ||
58 | |||
59 | /* LEDHEC */ | ||
60 | #define IDT77105_LEDHEC_DRHC 0x40 /* R/W, Disable Rx HEC check */ | ||
61 | #define IDT77105_LEDHEC_DTHC 0x20 /* R/W, Disable Tx HEC calculation */ | ||
62 | #define IDT77105_LEDHEC_RPWMASK 0x18 /* R/W, RxRef pulse width select */ | ||
63 | #define IDT77105_LEDHEC_TFS 0x04 /* R, Tx FIFO Status (1=empty) */ | ||
64 | #define IDT77105_LEDHEC_TLS 0x02 /* R, Tx LED Status (1=lit) */ | ||
65 | #define IDT77105_LEDHEC_RLS 0x01 /* R, Rx LED Status (1=lit) */ | ||
66 | |||
67 | #define IDT77105_LEDHEC_RPW_1 0x00 /* RxRef active for 1 RxClk cycle */ | ||
68 | #define IDT77105_LEDHEC_RPW_2 0x08 /* RxRef active for 2 RxClk cycle */ | ||
69 | #define IDT77105_LEDHEC_RPW_4 0x10 /* RxRef active for 4 RxClk cycle */ | ||
70 | #define IDT77105_LEDHEC_RPW_8 0x18 /* RxRef active for 8 RxClk cycle */ | ||
71 | |||
72 | /* CTRSEL */ | ||
73 | #define IDT77105_CTRSEL_SEC 0x08 /* W, Symbol Error Counter */ | ||
74 | #define IDT77105_CTRSEL_TCC 0x04 /* W, Tx Cell Counter */ | ||
75 | #define IDT77105_CTRSEL_RCC 0x02 /* W, Rx Cell Counter */ | ||
76 | #define IDT77105_CTRSEL_RHEC 0x01 /* W, Rx HEC Error Counter */ | ||
77 | |||
78 | #ifdef __KERNEL__ | ||
79 | int idt77105_init(struct atm_dev *dev) __init; | ||
80 | #endif | ||
81 | |||
82 | /* | ||
83 | * Tunable parameters | ||
84 | */ | ||
85 | |||
86 | /* Time between samples of the hardware cell counters. Should be <= 1 sec */ | ||
87 | #define IDT77105_STATS_TIMER_PERIOD (HZ) | ||
88 | /* Time between checks to see if the signal has been found again */ | ||
89 | #define IDT77105_RESTART_TIMER_PERIOD (5 * HZ) | ||
90 | |||
91 | #endif | ||
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c new file mode 100644 index 000000000000..baaf1a3d2242 --- /dev/null +++ b/drivers/atm/idt77252.c | |||
@@ -0,0 +1,3882 @@ | |||
1 | /******************************************************************* | ||
2 | * ident "$Id: idt77252.c,v 1.2 2001/11/11 08:13:54 ecd Exp $" | ||
3 | * | ||
4 | * $Author: ecd $ | ||
5 | * $Date: 2001/11/11 08:13:54 $ | ||
6 | * | ||
7 | * Copyright (c) 2000 ATecoM GmbH | ||
8 | * | ||
9 | * The author may be reached at ecd@atecom.com. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
19 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License along | ||
28 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | * | ||
31 | *******************************************************************/ | ||
32 | static char const rcsid[] = | ||
33 | "$Id: idt77252.c,v 1.2 2001/11/11 08:13:54 ecd Exp $"; | ||
34 | |||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/config.h> | ||
38 | #include <linux/pci.h> | ||
39 | #include <linux/skbuff.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/vmalloc.h> | ||
42 | #include <linux/netdevice.h> | ||
43 | #include <linux/atmdev.h> | ||
44 | #include <linux/atm.h> | ||
45 | #include <linux/delay.h> | ||
46 | #include <linux/init.h> | ||
47 | #include <linux/bitops.h> | ||
48 | #include <linux/wait.h> | ||
49 | #include <asm/semaphore.h> | ||
50 | #include <asm/io.h> | ||
51 | #include <asm/uaccess.h> | ||
52 | #include <asm/atomic.h> | ||
53 | #include <asm/byteorder.h> | ||
54 | |||
55 | #ifdef CONFIG_ATM_IDT77252_USE_SUNI | ||
56 | #include "suni.h" | ||
57 | #endif /* CONFIG_ATM_IDT77252_USE_SUNI */ | ||
58 | |||
59 | |||
60 | #include "idt77252.h" | ||
61 | #include "idt77252_tables.h" | ||
62 | |||
63 | static unsigned int vpibits = 1; | ||
64 | |||
65 | |||
66 | #define CONFIG_ATM_IDT77252_SEND_IDLE 1 | ||
67 | |||
68 | |||
69 | /* | ||
70 | * Debug HACKs. | ||
71 | */ | ||
72 | #define DEBUG_MODULE 1 | ||
73 | #undef HAVE_EEPROM /* does not work, yet. */ | ||
74 | |||
75 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
76 | static unsigned long debug = DBG_GENERAL; | ||
77 | #endif | ||
78 | |||
79 | |||
80 | #define SAR_RX_DELAY (SAR_CFG_RXINT_NODELAY) | ||
81 | |||
82 | |||
83 | /* | ||
84 | * SCQ Handling. | ||
85 | */ | ||
86 | static struct scq_info *alloc_scq(struct idt77252_dev *, int); | ||
87 | static void free_scq(struct idt77252_dev *, struct scq_info *); | ||
88 | static int queue_skb(struct idt77252_dev *, struct vc_map *, | ||
89 | struct sk_buff *, int oam); | ||
90 | static void drain_scq(struct idt77252_dev *, struct vc_map *); | ||
91 | static unsigned long get_free_scd(struct idt77252_dev *, struct vc_map *); | ||
92 | static void fill_scd(struct idt77252_dev *, struct scq_info *, int); | ||
93 | |||
94 | /* | ||
95 | * FBQ Handling. | ||
96 | */ | ||
97 | static int push_rx_skb(struct idt77252_dev *, | ||
98 | struct sk_buff *, int queue); | ||
99 | static void recycle_rx_skb(struct idt77252_dev *, struct sk_buff *); | ||
100 | static void flush_rx_pool(struct idt77252_dev *, struct rx_pool *); | ||
101 | static void recycle_rx_pool_skb(struct idt77252_dev *, | ||
102 | struct rx_pool *); | ||
103 | static void add_rx_skb(struct idt77252_dev *, int queue, | ||
104 | unsigned int size, unsigned int count); | ||
105 | |||
106 | /* | ||
107 | * RSQ Handling. | ||
108 | */ | ||
109 | static int init_rsq(struct idt77252_dev *); | ||
110 | static void deinit_rsq(struct idt77252_dev *); | ||
111 | static void idt77252_rx(struct idt77252_dev *); | ||
112 | |||
113 | /* | ||
114 | * TSQ handling. | ||
115 | */ | ||
116 | static int init_tsq(struct idt77252_dev *); | ||
117 | static void deinit_tsq(struct idt77252_dev *); | ||
118 | static void idt77252_tx(struct idt77252_dev *); | ||
119 | |||
120 | |||
121 | /* | ||
122 | * ATM Interface. | ||
123 | */ | ||
124 | static void idt77252_dev_close(struct atm_dev *dev); | ||
125 | static int idt77252_open(struct atm_vcc *vcc); | ||
126 | static void idt77252_close(struct atm_vcc *vcc); | ||
127 | static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
128 | static int idt77252_send_oam(struct atm_vcc *vcc, void *cell, | ||
129 | int flags); | ||
130 | static void idt77252_phy_put(struct atm_dev *dev, unsigned char value, | ||
131 | unsigned long addr); | ||
132 | static unsigned char idt77252_phy_get(struct atm_dev *dev, unsigned long addr); | ||
133 | static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, | ||
134 | int flags); | ||
135 | static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos, | ||
136 | char *page); | ||
137 | static void idt77252_softint(void *dev_id); | ||
138 | |||
139 | |||
140 | static struct atmdev_ops idt77252_ops = | ||
141 | { | ||
142 | .dev_close = idt77252_dev_close, | ||
143 | .open = idt77252_open, | ||
144 | .close = idt77252_close, | ||
145 | .send = idt77252_send, | ||
146 | .send_oam = idt77252_send_oam, | ||
147 | .phy_put = idt77252_phy_put, | ||
148 | .phy_get = idt77252_phy_get, | ||
149 | .change_qos = idt77252_change_qos, | ||
150 | .proc_read = idt77252_proc_read, | ||
151 | .owner = THIS_MODULE | ||
152 | }; | ||
153 | |||
154 | static struct idt77252_dev *idt77252_chain = NULL; | ||
155 | static unsigned int idt77252_sram_write_errors = 0; | ||
156 | |||
157 | /*****************************************************************************/ | ||
158 | /* */ | ||
159 | /* I/O and Utility Bus */ | ||
160 | /* */ | ||
161 | /*****************************************************************************/ | ||
162 | |||
163 | static void | ||
164 | waitfor_idle(struct idt77252_dev *card) | ||
165 | { | ||
166 | u32 stat; | ||
167 | |||
168 | stat = readl(SAR_REG_STAT); | ||
169 | while (stat & SAR_STAT_CMDBZ) | ||
170 | stat = readl(SAR_REG_STAT); | ||
171 | } | ||
172 | |||
173 | static u32 | ||
174 | read_sram(struct idt77252_dev *card, unsigned long addr) | ||
175 | { | ||
176 | unsigned long flags; | ||
177 | u32 value; | ||
178 | |||
179 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
180 | writel(SAR_CMD_READ_SRAM | (addr << 2), SAR_REG_CMD); | ||
181 | waitfor_idle(card); | ||
182 | value = readl(SAR_REG_DR0); | ||
183 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
184 | return value; | ||
185 | } | ||
186 | |||
187 | static void | ||
188 | write_sram(struct idt77252_dev *card, unsigned long addr, u32 value) | ||
189 | { | ||
190 | unsigned long flags; | ||
191 | |||
192 | if ((idt77252_sram_write_errors == 0) && | ||
193 | (((addr > card->tst[0] + card->tst_size - 2) && | ||
194 | (addr < card->tst[0] + card->tst_size)) || | ||
195 | ((addr > card->tst[1] + card->tst_size - 2) && | ||
196 | (addr < card->tst[1] + card->tst_size)))) { | ||
197 | printk("%s: ERROR: TST JMP section at %08lx written: %08x\n", | ||
198 | card->name, addr, value); | ||
199 | } | ||
200 | |||
201 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
202 | writel(value, SAR_REG_DR0); | ||
203 | writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD); | ||
204 | waitfor_idle(card); | ||
205 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
206 | } | ||
207 | |||
208 | static u8 | ||
209 | read_utility(void *dev, unsigned long ubus_addr) | ||
210 | { | ||
211 | struct idt77252_dev *card = dev; | ||
212 | unsigned long flags; | ||
213 | u8 value; | ||
214 | |||
215 | if (!card) { | ||
216 | printk("Error: No such device.\n"); | ||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
221 | writel(SAR_CMD_READ_UTILITY + ubus_addr, SAR_REG_CMD); | ||
222 | waitfor_idle(card); | ||
223 | value = readl(SAR_REG_DR0); | ||
224 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
225 | return value; | ||
226 | } | ||
227 | |||
228 | static void | ||
229 | write_utility(void *dev, unsigned long ubus_addr, u8 value) | ||
230 | { | ||
231 | struct idt77252_dev *card = dev; | ||
232 | unsigned long flags; | ||
233 | |||
234 | if (!card) { | ||
235 | printk("Error: No such device.\n"); | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
240 | writel((u32) value, SAR_REG_DR0); | ||
241 | writel(SAR_CMD_WRITE_UTILITY + ubus_addr, SAR_REG_CMD); | ||
242 | waitfor_idle(card); | ||
243 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
244 | } | ||
245 | |||
246 | #ifdef HAVE_EEPROM | ||
247 | static u32 rdsrtab[] = | ||
248 | { | ||
249 | SAR_GP_EECS | SAR_GP_EESCLK, | ||
250 | 0, | ||
251 | SAR_GP_EESCLK, /* 0 */ | ||
252 | 0, | ||
253 | SAR_GP_EESCLK, /* 0 */ | ||
254 | 0, | ||
255 | SAR_GP_EESCLK, /* 0 */ | ||
256 | 0, | ||
257 | SAR_GP_EESCLK, /* 0 */ | ||
258 | 0, | ||
259 | SAR_GP_EESCLK, /* 0 */ | ||
260 | SAR_GP_EEDO, | ||
261 | SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */ | ||
262 | 0, | ||
263 | SAR_GP_EESCLK, /* 0 */ | ||
264 | SAR_GP_EEDO, | ||
265 | SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */ | ||
266 | }; | ||
267 | |||
268 | static u32 wrentab[] = | ||
269 | { | ||
270 | SAR_GP_EECS | SAR_GP_EESCLK, | ||
271 | 0, | ||
272 | SAR_GP_EESCLK, /* 0 */ | ||
273 | 0, | ||
274 | SAR_GP_EESCLK, /* 0 */ | ||
275 | 0, | ||
276 | SAR_GP_EESCLK, /* 0 */ | ||
277 | 0, | ||
278 | SAR_GP_EESCLK, /* 0 */ | ||
279 | SAR_GP_EEDO, | ||
280 | SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */ | ||
281 | SAR_GP_EEDO, | ||
282 | SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */ | ||
283 | 0, | ||
284 | SAR_GP_EESCLK, /* 0 */ | ||
285 | 0, | ||
286 | SAR_GP_EESCLK /* 0 */ | ||
287 | }; | ||
288 | |||
289 | static u32 rdtab[] = | ||
290 | { | ||
291 | SAR_GP_EECS | SAR_GP_EESCLK, | ||
292 | 0, | ||
293 | SAR_GP_EESCLK, /* 0 */ | ||
294 | 0, | ||
295 | SAR_GP_EESCLK, /* 0 */ | ||
296 | 0, | ||
297 | SAR_GP_EESCLK, /* 0 */ | ||
298 | 0, | ||
299 | SAR_GP_EESCLK, /* 0 */ | ||
300 | 0, | ||
301 | SAR_GP_EESCLK, /* 0 */ | ||
302 | 0, | ||
303 | SAR_GP_EESCLK, /* 0 */ | ||
304 | SAR_GP_EEDO, | ||
305 | SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */ | ||
306 | SAR_GP_EEDO, | ||
307 | SAR_GP_EESCLK | SAR_GP_EEDO /* 1 */ | ||
308 | }; | ||
309 | |||
310 | static u32 wrtab[] = | ||
311 | { | ||
312 | SAR_GP_EECS | SAR_GP_EESCLK, | ||
313 | 0, | ||
314 | SAR_GP_EESCLK, /* 0 */ | ||
315 | 0, | ||
316 | SAR_GP_EESCLK, /* 0 */ | ||
317 | 0, | ||
318 | SAR_GP_EESCLK, /* 0 */ | ||
319 | 0, | ||
320 | SAR_GP_EESCLK, /* 0 */ | ||
321 | 0, | ||
322 | SAR_GP_EESCLK, /* 0 */ | ||
323 | 0, | ||
324 | SAR_GP_EESCLK, /* 0 */ | ||
325 | SAR_GP_EEDO, | ||
326 | SAR_GP_EESCLK | SAR_GP_EEDO, /* 1 */ | ||
327 | 0, | ||
328 | SAR_GP_EESCLK /* 0 */ | ||
329 | }; | ||
330 | |||
331 | static u32 clktab[] = | ||
332 | { | ||
333 | 0, | ||
334 | SAR_GP_EESCLK, | ||
335 | 0, | ||
336 | SAR_GP_EESCLK, | ||
337 | 0, | ||
338 | SAR_GP_EESCLK, | ||
339 | 0, | ||
340 | SAR_GP_EESCLK, | ||
341 | 0, | ||
342 | SAR_GP_EESCLK, | ||
343 | 0, | ||
344 | SAR_GP_EESCLK, | ||
345 | 0, | ||
346 | SAR_GP_EESCLK, | ||
347 | 0, | ||
348 | SAR_GP_EESCLK, | ||
349 | 0 | ||
350 | }; | ||
351 | |||
352 | static u32 | ||
353 | idt77252_read_gp(struct idt77252_dev *card) | ||
354 | { | ||
355 | u32 gp; | ||
356 | |||
357 | gp = readl(SAR_REG_GP); | ||
358 | #if 0 | ||
359 | printk("RD: %s\n", gp & SAR_GP_EEDI ? "1" : "0"); | ||
360 | #endif | ||
361 | return gp; | ||
362 | } | ||
363 | |||
364 | static void | ||
365 | idt77252_write_gp(struct idt77252_dev *card, u32 value) | ||
366 | { | ||
367 | unsigned long flags; | ||
368 | |||
369 | #if 0 | ||
370 | printk("WR: %s %s %s\n", value & SAR_GP_EECS ? " " : "/CS", | ||
371 | value & SAR_GP_EESCLK ? "HIGH" : "LOW ", | ||
372 | value & SAR_GP_EEDO ? "1" : "0"); | ||
373 | #endif | ||
374 | |||
375 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
376 | waitfor_idle(card); | ||
377 | writel(value, SAR_REG_GP); | ||
378 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
379 | } | ||
380 | |||
381 | static u8 | ||
382 | idt77252_eeprom_read_status(struct idt77252_dev *card) | ||
383 | { | ||
384 | u8 byte; | ||
385 | u32 gp; | ||
386 | int i, j; | ||
387 | |||
388 | gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO); | ||
389 | |||
390 | for (i = 0; i < sizeof(rdsrtab)/sizeof(rdsrtab[0]); i++) { | ||
391 | idt77252_write_gp(card, gp | rdsrtab[i]); | ||
392 | udelay(5); | ||
393 | } | ||
394 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
395 | udelay(5); | ||
396 | |||
397 | byte = 0; | ||
398 | for (i = 0, j = 0; i < 8; i++) { | ||
399 | byte <<= 1; | ||
400 | |||
401 | idt77252_write_gp(card, gp | clktab[j++]); | ||
402 | udelay(5); | ||
403 | |||
404 | byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0; | ||
405 | |||
406 | idt77252_write_gp(card, gp | clktab[j++]); | ||
407 | udelay(5); | ||
408 | } | ||
409 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
410 | udelay(5); | ||
411 | |||
412 | return byte; | ||
413 | } | ||
414 | |||
415 | static u8 | ||
416 | idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset) | ||
417 | { | ||
418 | u8 byte; | ||
419 | u32 gp; | ||
420 | int i, j; | ||
421 | |||
422 | gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO); | ||
423 | |||
424 | for (i = 0; i < sizeof(rdtab)/sizeof(rdtab[0]); i++) { | ||
425 | idt77252_write_gp(card, gp | rdtab[i]); | ||
426 | udelay(5); | ||
427 | } | ||
428 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
429 | udelay(5); | ||
430 | |||
431 | for (i = 0, j = 0; i < 8; i++) { | ||
432 | idt77252_write_gp(card, gp | clktab[j++] | | ||
433 | (offset & 1 ? SAR_GP_EEDO : 0)); | ||
434 | udelay(5); | ||
435 | |||
436 | idt77252_write_gp(card, gp | clktab[j++] | | ||
437 | (offset & 1 ? SAR_GP_EEDO : 0)); | ||
438 | udelay(5); | ||
439 | |||
440 | offset >>= 1; | ||
441 | } | ||
442 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
443 | udelay(5); | ||
444 | |||
445 | byte = 0; | ||
446 | for (i = 0, j = 0; i < 8; i++) { | ||
447 | byte <<= 1; | ||
448 | |||
449 | idt77252_write_gp(card, gp | clktab[j++]); | ||
450 | udelay(5); | ||
451 | |||
452 | byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0; | ||
453 | |||
454 | idt77252_write_gp(card, gp | clktab[j++]); | ||
455 | udelay(5); | ||
456 | } | ||
457 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
458 | udelay(5); | ||
459 | |||
460 | return byte; | ||
461 | } | ||
462 | |||
463 | static void | ||
464 | idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data) | ||
465 | { | ||
466 | u32 gp; | ||
467 | int i, j; | ||
468 | |||
469 | gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO); | ||
470 | |||
471 | for (i = 0; i < sizeof(wrentab)/sizeof(wrentab[0]); i++) { | ||
472 | idt77252_write_gp(card, gp | wrentab[i]); | ||
473 | udelay(5); | ||
474 | } | ||
475 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
476 | udelay(5); | ||
477 | |||
478 | for (i = 0; i < sizeof(wrtab)/sizeof(wrtab[0]); i++) { | ||
479 | idt77252_write_gp(card, gp | wrtab[i]); | ||
480 | udelay(5); | ||
481 | } | ||
482 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
483 | udelay(5); | ||
484 | |||
485 | for (i = 0, j = 0; i < 8; i++) { | ||
486 | idt77252_write_gp(card, gp | clktab[j++] | | ||
487 | (offset & 1 ? SAR_GP_EEDO : 0)); | ||
488 | udelay(5); | ||
489 | |||
490 | idt77252_write_gp(card, gp | clktab[j++] | | ||
491 | (offset & 1 ? SAR_GP_EEDO : 0)); | ||
492 | udelay(5); | ||
493 | |||
494 | offset >>= 1; | ||
495 | } | ||
496 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
497 | udelay(5); | ||
498 | |||
499 | for (i = 0, j = 0; i < 8; i++) { | ||
500 | idt77252_write_gp(card, gp | clktab[j++] | | ||
501 | (data & 1 ? SAR_GP_EEDO : 0)); | ||
502 | udelay(5); | ||
503 | |||
504 | idt77252_write_gp(card, gp | clktab[j++] | | ||
505 | (data & 1 ? SAR_GP_EEDO : 0)); | ||
506 | udelay(5); | ||
507 | |||
508 | data >>= 1; | ||
509 | } | ||
510 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
511 | udelay(5); | ||
512 | } | ||
513 | |||
514 | static void | ||
515 | idt77252_eeprom_init(struct idt77252_dev *card) | ||
516 | { | ||
517 | u32 gp; | ||
518 | |||
519 | gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO); | ||
520 | |||
521 | idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK); | ||
522 | udelay(5); | ||
523 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
524 | udelay(5); | ||
525 | idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK); | ||
526 | udelay(5); | ||
527 | idt77252_write_gp(card, gp | SAR_GP_EECS); | ||
528 | udelay(5); | ||
529 | } | ||
530 | #endif /* HAVE_EEPROM */ | ||
531 | |||
532 | |||
533 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
534 | static void | ||
535 | dump_tct(struct idt77252_dev *card, int index) | ||
536 | { | ||
537 | unsigned long tct; | ||
538 | int i; | ||
539 | |||
540 | tct = (unsigned long) (card->tct_base + index * SAR_SRAM_TCT_SIZE); | ||
541 | |||
542 | printk("%s: TCT %x:", card->name, index); | ||
543 | for (i = 0; i < 8; i++) { | ||
544 | printk(" %08x", read_sram(card, tct + i)); | ||
545 | } | ||
546 | printk("\n"); | ||
547 | } | ||
548 | |||
549 | static void | ||
550 | idt77252_tx_dump(struct idt77252_dev *card) | ||
551 | { | ||
552 | struct atm_vcc *vcc; | ||
553 | struct vc_map *vc; | ||
554 | int i; | ||
555 | |||
556 | printk("%s\n", __FUNCTION__); | ||
557 | for (i = 0; i < card->tct_size; i++) { | ||
558 | vc = card->vcs[i]; | ||
559 | if (!vc) | ||
560 | continue; | ||
561 | |||
562 | vcc = NULL; | ||
563 | if (vc->rx_vcc) | ||
564 | vcc = vc->rx_vcc; | ||
565 | else if (vc->tx_vcc) | ||
566 | vcc = vc->tx_vcc; | ||
567 | |||
568 | if (!vcc) | ||
569 | continue; | ||
570 | |||
571 | printk("%s: Connection %d:\n", card->name, vc->index); | ||
572 | dump_tct(card, vc->index); | ||
573 | } | ||
574 | } | ||
575 | #endif | ||
576 | |||
577 | |||
578 | /*****************************************************************************/ | ||
579 | /* */ | ||
580 | /* SCQ Handling */ | ||
581 | /* */ | ||
582 | /*****************************************************************************/ | ||
583 | |||
584 | static int | ||
585 | sb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue) | ||
586 | { | ||
587 | struct sb_pool *pool = &card->sbpool[queue]; | ||
588 | int index; | ||
589 | |||
590 | index = pool->index; | ||
591 | while (pool->skb[index]) { | ||
592 | index = (index + 1) & FBQ_MASK; | ||
593 | if (index == pool->index) | ||
594 | return -ENOBUFS; | ||
595 | } | ||
596 | |||
597 | pool->skb[index] = skb; | ||
598 | IDT77252_PRV_POOL(skb) = POOL_HANDLE(queue, index); | ||
599 | |||
600 | pool->index = (index + 1) & FBQ_MASK; | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static void | ||
605 | sb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb) | ||
606 | { | ||
607 | unsigned int queue, index; | ||
608 | u32 handle; | ||
609 | |||
610 | handle = IDT77252_PRV_POOL(skb); | ||
611 | |||
612 | queue = POOL_QUEUE(handle); | ||
613 | if (queue > 3) | ||
614 | return; | ||
615 | |||
616 | index = POOL_INDEX(handle); | ||
617 | if (index > FBQ_SIZE - 1) | ||
618 | return; | ||
619 | |||
620 | card->sbpool[queue].skb[index] = NULL; | ||
621 | } | ||
622 | |||
623 | static struct sk_buff * | ||
624 | sb_pool_skb(struct idt77252_dev *card, u32 handle) | ||
625 | { | ||
626 | unsigned int queue, index; | ||
627 | |||
628 | queue = POOL_QUEUE(handle); | ||
629 | if (queue > 3) | ||
630 | return NULL; | ||
631 | |||
632 | index = POOL_INDEX(handle); | ||
633 | if (index > FBQ_SIZE - 1) | ||
634 | return NULL; | ||
635 | |||
636 | return card->sbpool[queue].skb[index]; | ||
637 | } | ||
638 | |||
639 | static struct scq_info * | ||
640 | alloc_scq(struct idt77252_dev *card, int class) | ||
641 | { | ||
642 | struct scq_info *scq; | ||
643 | |||
644 | scq = (struct scq_info *) kmalloc(sizeof(struct scq_info), GFP_KERNEL); | ||
645 | if (!scq) | ||
646 | return NULL; | ||
647 | memset(scq, 0, sizeof(struct scq_info)); | ||
648 | |||
649 | scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE, | ||
650 | &scq->paddr); | ||
651 | if (scq->base == NULL) { | ||
652 | kfree(scq); | ||
653 | return NULL; | ||
654 | } | ||
655 | memset(scq->base, 0, SCQ_SIZE); | ||
656 | |||
657 | scq->next = scq->base; | ||
658 | scq->last = scq->base + (SCQ_ENTRIES - 1); | ||
659 | atomic_set(&scq->used, 0); | ||
660 | |||
661 | spin_lock_init(&scq->lock); | ||
662 | spin_lock_init(&scq->skblock); | ||
663 | |||
664 | skb_queue_head_init(&scq->transmit); | ||
665 | skb_queue_head_init(&scq->pending); | ||
666 | |||
667 | TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08llx\n", | ||
668 | scq->base, scq->next, scq->last, (unsigned long long)scq->paddr); | ||
669 | |||
670 | return scq; | ||
671 | } | ||
672 | |||
673 | static void | ||
674 | free_scq(struct idt77252_dev *card, struct scq_info *scq) | ||
675 | { | ||
676 | struct sk_buff *skb; | ||
677 | struct atm_vcc *vcc; | ||
678 | |||
679 | pci_free_consistent(card->pcidev, SCQ_SIZE, | ||
680 | scq->base, scq->paddr); | ||
681 | |||
682 | while ((skb = skb_dequeue(&scq->transmit))) { | ||
683 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
684 | skb->len, PCI_DMA_TODEVICE); | ||
685 | |||
686 | vcc = ATM_SKB(skb)->vcc; | ||
687 | if (vcc->pop) | ||
688 | vcc->pop(vcc, skb); | ||
689 | else | ||
690 | dev_kfree_skb(skb); | ||
691 | } | ||
692 | |||
693 | while ((skb = skb_dequeue(&scq->pending))) { | ||
694 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
695 | skb->len, PCI_DMA_TODEVICE); | ||
696 | |||
697 | vcc = ATM_SKB(skb)->vcc; | ||
698 | if (vcc->pop) | ||
699 | vcc->pop(vcc, skb); | ||
700 | else | ||
701 | dev_kfree_skb(skb); | ||
702 | } | ||
703 | |||
704 | kfree(scq); | ||
705 | } | ||
706 | |||
707 | |||
708 | static int | ||
709 | push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb) | ||
710 | { | ||
711 | struct scq_info *scq = vc->scq; | ||
712 | unsigned long flags; | ||
713 | struct scqe *tbd; | ||
714 | int entries; | ||
715 | |||
716 | TXPRINTK("%s: SCQ: next 0x%p\n", card->name, scq->next); | ||
717 | |||
718 | atomic_inc(&scq->used); | ||
719 | entries = atomic_read(&scq->used); | ||
720 | if (entries > (SCQ_ENTRIES - 1)) { | ||
721 | atomic_dec(&scq->used); | ||
722 | goto out; | ||
723 | } | ||
724 | |||
725 | skb_queue_tail(&scq->transmit, skb); | ||
726 | |||
727 | spin_lock_irqsave(&vc->lock, flags); | ||
728 | if (vc->estimator) { | ||
729 | struct atm_vcc *vcc = vc->tx_vcc; | ||
730 | struct sock *sk = sk_atm(vcc); | ||
731 | |||
732 | vc->estimator->cells += (skb->len + 47) / 48; | ||
733 | if (atomic_read(&sk->sk_wmem_alloc) > | ||
734 | (sk->sk_sndbuf >> 1)) { | ||
735 | u32 cps = vc->estimator->maxcps; | ||
736 | |||
737 | vc->estimator->cps = cps; | ||
738 | vc->estimator->avcps = cps << 5; | ||
739 | if (vc->lacr < vc->init_er) { | ||
740 | vc->lacr = vc->init_er; | ||
741 | writel(TCMDQ_LACR | (vc->lacr << 16) | | ||
742 | vc->index, SAR_REG_TCMDQ); | ||
743 | } | ||
744 | } | ||
745 | } | ||
746 | spin_unlock_irqrestore(&vc->lock, flags); | ||
747 | |||
748 | tbd = &IDT77252_PRV_TBD(skb); | ||
749 | |||
750 | spin_lock_irqsave(&scq->lock, flags); | ||
751 | scq->next->word_1 = cpu_to_le32(tbd->word_1 | | ||
752 | SAR_TBD_TSIF | SAR_TBD_GTSI); | ||
753 | scq->next->word_2 = cpu_to_le32(tbd->word_2); | ||
754 | scq->next->word_3 = cpu_to_le32(tbd->word_3); | ||
755 | scq->next->word_4 = cpu_to_le32(tbd->word_4); | ||
756 | |||
757 | if (scq->next == scq->last) | ||
758 | scq->next = scq->base; | ||
759 | else | ||
760 | scq->next++; | ||
761 | |||
762 | write_sram(card, scq->scd, | ||
763 | scq->paddr + | ||
764 | (u32)((unsigned long)scq->next - (unsigned long)scq->base)); | ||
765 | spin_unlock_irqrestore(&scq->lock, flags); | ||
766 | |||
767 | scq->trans_start = jiffies; | ||
768 | |||
769 | if (test_and_clear_bit(VCF_IDLE, &vc->flags)) { | ||
770 | writel(TCMDQ_START_LACR | (vc->lacr << 16) | vc->index, | ||
771 | SAR_REG_TCMDQ); | ||
772 | } | ||
773 | |||
774 | TXPRINTK("%d entries in SCQ used (push).\n", atomic_read(&scq->used)); | ||
775 | |||
776 | XPRINTK("%s: SCQ (after push %2d) head = 0x%x, next = 0x%p.\n", | ||
777 | card->name, atomic_read(&scq->used), | ||
778 | read_sram(card, scq->scd + 1), scq->next); | ||
779 | |||
780 | return 0; | ||
781 | |||
782 | out: | ||
783 | if (jiffies - scq->trans_start > HZ) { | ||
784 | printk("%s: Error pushing TBD for %d.%d\n", | ||
785 | card->name, vc->tx_vcc->vpi, vc->tx_vcc->vci); | ||
786 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
787 | idt77252_tx_dump(card); | ||
788 | #endif | ||
789 | scq->trans_start = jiffies; | ||
790 | } | ||
791 | |||
792 | return -ENOBUFS; | ||
793 | } | ||
794 | |||
795 | |||
796 | static void | ||
797 | drain_scq(struct idt77252_dev *card, struct vc_map *vc) | ||
798 | { | ||
799 | struct scq_info *scq = vc->scq; | ||
800 | struct sk_buff *skb; | ||
801 | struct atm_vcc *vcc; | ||
802 | |||
803 | TXPRINTK("%s: SCQ (before drain %2d) next = 0x%p.\n", | ||
804 | card->name, atomic_read(&scq->used), scq->next); | ||
805 | |||
806 | skb = skb_dequeue(&scq->transmit); | ||
807 | if (skb) { | ||
808 | TXPRINTK("%s: freeing skb at %p.\n", card->name, skb); | ||
809 | |||
810 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
811 | skb->len, PCI_DMA_TODEVICE); | ||
812 | |||
813 | vcc = ATM_SKB(skb)->vcc; | ||
814 | |||
815 | if (vcc->pop) | ||
816 | vcc->pop(vcc, skb); | ||
817 | else | ||
818 | dev_kfree_skb(skb); | ||
819 | |||
820 | atomic_inc(&vcc->stats->tx); | ||
821 | } | ||
822 | |||
823 | atomic_dec(&scq->used); | ||
824 | |||
825 | spin_lock(&scq->skblock); | ||
826 | while ((skb = skb_dequeue(&scq->pending))) { | ||
827 | if (push_on_scq(card, vc, skb)) { | ||
828 | skb_queue_head(&vc->scq->pending, skb); | ||
829 | break; | ||
830 | } | ||
831 | } | ||
832 | spin_unlock(&scq->skblock); | ||
833 | } | ||
834 | |||
835 | static int | ||
836 | queue_skb(struct idt77252_dev *card, struct vc_map *vc, | ||
837 | struct sk_buff *skb, int oam) | ||
838 | { | ||
839 | struct atm_vcc *vcc; | ||
840 | struct scqe *tbd; | ||
841 | unsigned long flags; | ||
842 | int error; | ||
843 | int aal; | ||
844 | |||
845 | if (skb->len == 0) { | ||
846 | printk("%s: invalid skb->len (%d)\n", card->name, skb->len); | ||
847 | return -EINVAL; | ||
848 | } | ||
849 | |||
850 | TXPRINTK("%s: Sending %d bytes of data.\n", | ||
851 | card->name, skb->len); | ||
852 | |||
853 | tbd = &IDT77252_PRV_TBD(skb); | ||
854 | vcc = ATM_SKB(skb)->vcc; | ||
855 | |||
856 | IDT77252_PRV_PADDR(skb) = pci_map_single(card->pcidev, skb->data, | ||
857 | skb->len, PCI_DMA_TODEVICE); | ||
858 | |||
859 | error = -EINVAL; | ||
860 | |||
861 | if (oam) { | ||
862 | if (skb->len != 52) | ||
863 | goto errout; | ||
864 | |||
865 | tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU; | ||
866 | tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4; | ||
867 | tbd->word_3 = 0x00000000; | ||
868 | tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) | | ||
869 | (skb->data[2] << 8) | (skb->data[3] << 0); | ||
870 | |||
871 | if (test_bit(VCF_RSV, &vc->flags)) | ||
872 | vc = card->vcs[0]; | ||
873 | |||
874 | goto done; | ||
875 | } | ||
876 | |||
877 | if (test_bit(VCF_RSV, &vc->flags)) { | ||
878 | printk("%s: Trying to transmit on reserved VC\n", card->name); | ||
879 | goto errout; | ||
880 | } | ||
881 | |||
882 | aal = vcc->qos.aal; | ||
883 | |||
884 | switch (aal) { | ||
885 | case ATM_AAL0: | ||
886 | case ATM_AAL34: | ||
887 | if (skb->len > 52) | ||
888 | goto errout; | ||
889 | |||
890 | if (aal == ATM_AAL0) | ||
891 | tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL0 | | ||
892 | ATM_CELL_PAYLOAD; | ||
893 | else | ||
894 | tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL34 | | ||
895 | ATM_CELL_PAYLOAD; | ||
896 | |||
897 | tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4; | ||
898 | tbd->word_3 = 0x00000000; | ||
899 | tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) | | ||
900 | (skb->data[2] << 8) | (skb->data[3] << 0); | ||
901 | break; | ||
902 | |||
903 | case ATM_AAL5: | ||
904 | tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL5 | skb->len; | ||
905 | tbd->word_2 = IDT77252_PRV_PADDR(skb); | ||
906 | tbd->word_3 = skb->len; | ||
907 | tbd->word_4 = (vcc->vpi << SAR_TBD_VPI_SHIFT) | | ||
908 | (vcc->vci << SAR_TBD_VCI_SHIFT); | ||
909 | break; | ||
910 | |||
911 | case ATM_AAL1: | ||
912 | case ATM_AAL2: | ||
913 | default: | ||
914 | printk("%s: Traffic type not supported.\n", card->name); | ||
915 | error = -EPROTONOSUPPORT; | ||
916 | goto errout; | ||
917 | } | ||
918 | |||
919 | done: | ||
920 | spin_lock_irqsave(&vc->scq->skblock, flags); | ||
921 | skb_queue_tail(&vc->scq->pending, skb); | ||
922 | |||
923 | while ((skb = skb_dequeue(&vc->scq->pending))) { | ||
924 | if (push_on_scq(card, vc, skb)) { | ||
925 | skb_queue_head(&vc->scq->pending, skb); | ||
926 | break; | ||
927 | } | ||
928 | } | ||
929 | spin_unlock_irqrestore(&vc->scq->skblock, flags); | ||
930 | |||
931 | return 0; | ||
932 | |||
933 | errout: | ||
934 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
935 | skb->len, PCI_DMA_TODEVICE); | ||
936 | return error; | ||
937 | } | ||
938 | |||
939 | static unsigned long | ||
940 | get_free_scd(struct idt77252_dev *card, struct vc_map *vc) | ||
941 | { | ||
942 | int i; | ||
943 | |||
944 | for (i = 0; i < card->scd_size; i++) { | ||
945 | if (!card->scd2vc[i]) { | ||
946 | card->scd2vc[i] = vc; | ||
947 | vc->scd_index = i; | ||
948 | return card->scd_base + i * SAR_SRAM_SCD_SIZE; | ||
949 | } | ||
950 | } | ||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | static void | ||
955 | fill_scd(struct idt77252_dev *card, struct scq_info *scq, int class) | ||
956 | { | ||
957 | write_sram(card, scq->scd, scq->paddr); | ||
958 | write_sram(card, scq->scd + 1, 0x00000000); | ||
959 | write_sram(card, scq->scd + 2, 0xffffffff); | ||
960 | write_sram(card, scq->scd + 3, 0x00000000); | ||
961 | } | ||
962 | |||
963 | static void | ||
964 | clear_scd(struct idt77252_dev *card, struct scq_info *scq, int class) | ||
965 | { | ||
966 | return; | ||
967 | } | ||
968 | |||
969 | /*****************************************************************************/ | ||
970 | /* */ | ||
971 | /* RSQ Handling */ | ||
972 | /* */ | ||
973 | /*****************************************************************************/ | ||
974 | |||
975 | static int | ||
976 | init_rsq(struct idt77252_dev *card) | ||
977 | { | ||
978 | struct rsq_entry *rsqe; | ||
979 | |||
980 | card->rsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE, | ||
981 | &card->rsq.paddr); | ||
982 | if (card->rsq.base == NULL) { | ||
983 | printk("%s: can't allocate RSQ.\n", card->name); | ||
984 | return -1; | ||
985 | } | ||
986 | memset(card->rsq.base, 0, RSQSIZE); | ||
987 | |||
988 | card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1; | ||
989 | card->rsq.next = card->rsq.last; | ||
990 | for (rsqe = card->rsq.base; rsqe <= card->rsq.last; rsqe++) | ||
991 | rsqe->word_4 = 0; | ||
992 | |||
993 | writel((unsigned long) card->rsq.last - (unsigned long) card->rsq.base, | ||
994 | SAR_REG_RSQH); | ||
995 | writel(card->rsq.paddr, SAR_REG_RSQB); | ||
996 | |||
997 | IPRINTK("%s: RSQ base at 0x%lx (0x%x).\n", card->name, | ||
998 | (unsigned long) card->rsq.base, | ||
999 | readl(SAR_REG_RSQB)); | ||
1000 | IPRINTK("%s: RSQ head = 0x%x, base = 0x%x, tail = 0x%x.\n", | ||
1001 | card->name, | ||
1002 | readl(SAR_REG_RSQH), | ||
1003 | readl(SAR_REG_RSQB), | ||
1004 | readl(SAR_REG_RSQT)); | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static void | ||
1010 | deinit_rsq(struct idt77252_dev *card) | ||
1011 | { | ||
1012 | pci_free_consistent(card->pcidev, RSQSIZE, | ||
1013 | card->rsq.base, card->rsq.paddr); | ||
1014 | } | ||
1015 | |||
1016 | static void | ||
1017 | dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) | ||
1018 | { | ||
1019 | struct atm_vcc *vcc; | ||
1020 | struct sk_buff *skb; | ||
1021 | struct rx_pool *rpp; | ||
1022 | struct vc_map *vc; | ||
1023 | u32 header, vpi, vci; | ||
1024 | u32 stat; | ||
1025 | int i; | ||
1026 | |||
1027 | stat = le32_to_cpu(rsqe->word_4); | ||
1028 | |||
1029 | if (stat & SAR_RSQE_IDLE) { | ||
1030 | RXPRINTK("%s: message about inactive connection.\n", | ||
1031 | card->name); | ||
1032 | return; | ||
1033 | } | ||
1034 | |||
1035 | skb = sb_pool_skb(card, le32_to_cpu(rsqe->word_2)); | ||
1036 | if (skb == NULL) { | ||
1037 | printk("%s: NULL skb in %s, rsqe: %08x %08x %08x %08x\n", | ||
1038 | card->name, __FUNCTION__, | ||
1039 | le32_to_cpu(rsqe->word_1), le32_to_cpu(rsqe->word_2), | ||
1040 | le32_to_cpu(rsqe->word_3), le32_to_cpu(rsqe->word_4)); | ||
1041 | return; | ||
1042 | } | ||
1043 | |||
1044 | header = le32_to_cpu(rsqe->word_1); | ||
1045 | vpi = (header >> 16) & 0x00ff; | ||
1046 | vci = (header >> 0) & 0xffff; | ||
1047 | |||
1048 | RXPRINTK("%s: SDU for %d.%d received in buffer 0x%p (data 0x%p).\n", | ||
1049 | card->name, vpi, vci, skb, skb->data); | ||
1050 | |||
1051 | if ((vpi >= (1 << card->vpibits)) || (vci != (vci & card->vcimask))) { | ||
1052 | printk("%s: SDU received for out-of-range vc %u.%u\n", | ||
1053 | card->name, vpi, vci); | ||
1054 | recycle_rx_skb(card, skb); | ||
1055 | return; | ||
1056 | } | ||
1057 | |||
1058 | vc = card->vcs[VPCI2VC(card, vpi, vci)]; | ||
1059 | if (!vc || !test_bit(VCF_RX, &vc->flags)) { | ||
1060 | printk("%s: SDU received on non RX vc %u.%u\n", | ||
1061 | card->name, vpi, vci); | ||
1062 | recycle_rx_skb(card, skb); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1066 | vcc = vc->rx_vcc; | ||
1067 | |||
1068 | pci_dma_sync_single_for_cpu(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
1069 | skb->end - skb->data, PCI_DMA_FROMDEVICE); | ||
1070 | |||
1071 | if ((vcc->qos.aal == ATM_AAL0) || | ||
1072 | (vcc->qos.aal == ATM_AAL34)) { | ||
1073 | struct sk_buff *sb; | ||
1074 | unsigned char *cell; | ||
1075 | u32 aal0; | ||
1076 | |||
1077 | cell = skb->data; | ||
1078 | for (i = (stat & SAR_RSQE_CELLCNT); i; i--) { | ||
1079 | if ((sb = dev_alloc_skb(64)) == NULL) { | ||
1080 | printk("%s: Can't allocate buffers for aal0.\n", | ||
1081 | card->name); | ||
1082 | atomic_add(i, &vcc->stats->rx_drop); | ||
1083 | break; | ||
1084 | } | ||
1085 | if (!atm_charge(vcc, sb->truesize)) { | ||
1086 | RXPRINTK("%s: atm_charge() dropped aal0 packets.\n", | ||
1087 | card->name); | ||
1088 | atomic_add(i - 1, &vcc->stats->rx_drop); | ||
1089 | dev_kfree_skb(sb); | ||
1090 | break; | ||
1091 | } | ||
1092 | aal0 = (vpi << ATM_HDR_VPI_SHIFT) | | ||
1093 | (vci << ATM_HDR_VCI_SHIFT); | ||
1094 | aal0 |= (stat & SAR_RSQE_EPDU) ? 0x00000002 : 0; | ||
1095 | aal0 |= (stat & SAR_RSQE_CLP) ? 0x00000001 : 0; | ||
1096 | |||
1097 | *((u32 *) sb->data) = aal0; | ||
1098 | skb_put(sb, sizeof(u32)); | ||
1099 | memcpy(skb_put(sb, ATM_CELL_PAYLOAD), | ||
1100 | cell, ATM_CELL_PAYLOAD); | ||
1101 | |||
1102 | ATM_SKB(sb)->vcc = vcc; | ||
1103 | do_gettimeofday(&sb->stamp); | ||
1104 | vcc->push(vcc, sb); | ||
1105 | atomic_inc(&vcc->stats->rx); | ||
1106 | |||
1107 | cell += ATM_CELL_PAYLOAD; | ||
1108 | } | ||
1109 | |||
1110 | recycle_rx_skb(card, skb); | ||
1111 | return; | ||
1112 | } | ||
1113 | if (vcc->qos.aal != ATM_AAL5) { | ||
1114 | printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n", | ||
1115 | card->name, vcc->qos.aal); | ||
1116 | recycle_rx_skb(card, skb); | ||
1117 | return; | ||
1118 | } | ||
1119 | skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD; | ||
1120 | |||
1121 | rpp = &vc->rcv.rx_pool; | ||
1122 | |||
1123 | rpp->len += skb->len; | ||
1124 | if (!rpp->count++) | ||
1125 | rpp->first = skb; | ||
1126 | *rpp->last = skb; | ||
1127 | rpp->last = &skb->next; | ||
1128 | |||
1129 | if (stat & SAR_RSQE_EPDU) { | ||
1130 | unsigned char *l1l2; | ||
1131 | unsigned int len; | ||
1132 | |||
1133 | l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6); | ||
1134 | |||
1135 | len = (l1l2[0] << 8) | l1l2[1]; | ||
1136 | len = len ? len : 0x10000; | ||
1137 | |||
1138 | RXPRINTK("%s: PDU has %d bytes.\n", card->name, len); | ||
1139 | |||
1140 | if ((len + 8 > rpp->len) || (len + (47 + 8) < rpp->len)) { | ||
1141 | RXPRINTK("%s: AAL5 PDU size mismatch: %d != %d. " | ||
1142 | "(CDC: %08x)\n", | ||
1143 | card->name, len, rpp->len, readl(SAR_REG_CDC)); | ||
1144 | recycle_rx_pool_skb(card, rpp); | ||
1145 | atomic_inc(&vcc->stats->rx_err); | ||
1146 | return; | ||
1147 | } | ||
1148 | if (stat & SAR_RSQE_CRC) { | ||
1149 | RXPRINTK("%s: AAL5 CRC error.\n", card->name); | ||
1150 | recycle_rx_pool_skb(card, rpp); | ||
1151 | atomic_inc(&vcc->stats->rx_err); | ||
1152 | return; | ||
1153 | } | ||
1154 | if (rpp->count > 1) { | ||
1155 | struct sk_buff *sb; | ||
1156 | |||
1157 | skb = dev_alloc_skb(rpp->len); | ||
1158 | if (!skb) { | ||
1159 | RXPRINTK("%s: Can't alloc RX skb.\n", | ||
1160 | card->name); | ||
1161 | recycle_rx_pool_skb(card, rpp); | ||
1162 | atomic_inc(&vcc->stats->rx_err); | ||
1163 | return; | ||
1164 | } | ||
1165 | if (!atm_charge(vcc, skb->truesize)) { | ||
1166 | recycle_rx_pool_skb(card, rpp); | ||
1167 | dev_kfree_skb(skb); | ||
1168 | return; | ||
1169 | } | ||
1170 | sb = rpp->first; | ||
1171 | for (i = 0; i < rpp->count; i++) { | ||
1172 | memcpy(skb_put(skb, sb->len), | ||
1173 | sb->data, sb->len); | ||
1174 | sb = sb->next; | ||
1175 | } | ||
1176 | |||
1177 | recycle_rx_pool_skb(card, rpp); | ||
1178 | |||
1179 | skb_trim(skb, len); | ||
1180 | ATM_SKB(skb)->vcc = vcc; | ||
1181 | do_gettimeofday(&skb->stamp); | ||
1182 | |||
1183 | vcc->push(vcc, skb); | ||
1184 | atomic_inc(&vcc->stats->rx); | ||
1185 | |||
1186 | return; | ||
1187 | } | ||
1188 | |||
1189 | skb->next = NULL; | ||
1190 | flush_rx_pool(card, rpp); | ||
1191 | |||
1192 | if (!atm_charge(vcc, skb->truesize)) { | ||
1193 | recycle_rx_skb(card, skb); | ||
1194 | return; | ||
1195 | } | ||
1196 | |||
1197 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
1198 | skb->end - skb->data, PCI_DMA_FROMDEVICE); | ||
1199 | sb_pool_remove(card, skb); | ||
1200 | |||
1201 | skb_trim(skb, len); | ||
1202 | ATM_SKB(skb)->vcc = vcc; | ||
1203 | do_gettimeofday(&skb->stamp); | ||
1204 | |||
1205 | vcc->push(vcc, skb); | ||
1206 | atomic_inc(&vcc->stats->rx); | ||
1207 | |||
1208 | if (skb->truesize > SAR_FB_SIZE_3) | ||
1209 | add_rx_skb(card, 3, SAR_FB_SIZE_3, 1); | ||
1210 | else if (skb->truesize > SAR_FB_SIZE_2) | ||
1211 | add_rx_skb(card, 2, SAR_FB_SIZE_2, 1); | ||
1212 | else if (skb->truesize > SAR_FB_SIZE_1) | ||
1213 | add_rx_skb(card, 1, SAR_FB_SIZE_1, 1); | ||
1214 | else | ||
1215 | add_rx_skb(card, 0, SAR_FB_SIZE_0, 1); | ||
1216 | return; | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | static void | ||
1221 | idt77252_rx(struct idt77252_dev *card) | ||
1222 | { | ||
1223 | struct rsq_entry *rsqe; | ||
1224 | |||
1225 | if (card->rsq.next == card->rsq.last) | ||
1226 | rsqe = card->rsq.base; | ||
1227 | else | ||
1228 | rsqe = card->rsq.next + 1; | ||
1229 | |||
1230 | if (!(le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID)) { | ||
1231 | RXPRINTK("%s: no entry in RSQ.\n", card->name); | ||
1232 | return; | ||
1233 | } | ||
1234 | |||
1235 | do { | ||
1236 | dequeue_rx(card, rsqe); | ||
1237 | rsqe->word_4 = 0; | ||
1238 | card->rsq.next = rsqe; | ||
1239 | if (card->rsq.next == card->rsq.last) | ||
1240 | rsqe = card->rsq.base; | ||
1241 | else | ||
1242 | rsqe = card->rsq.next + 1; | ||
1243 | } while (le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID); | ||
1244 | |||
1245 | writel((unsigned long) card->rsq.next - (unsigned long) card->rsq.base, | ||
1246 | SAR_REG_RSQH); | ||
1247 | } | ||
1248 | |||
1249 | static void | ||
1250 | idt77252_rx_raw(struct idt77252_dev *card) | ||
1251 | { | ||
1252 | struct sk_buff *queue; | ||
1253 | u32 head, tail; | ||
1254 | struct atm_vcc *vcc; | ||
1255 | struct vc_map *vc; | ||
1256 | struct sk_buff *sb; | ||
1257 | |||
1258 | if (card->raw_cell_head == NULL) { | ||
1259 | u32 handle = le32_to_cpu(*(card->raw_cell_hnd + 1)); | ||
1260 | card->raw_cell_head = sb_pool_skb(card, handle); | ||
1261 | } | ||
1262 | |||
1263 | queue = card->raw_cell_head; | ||
1264 | if (!queue) | ||
1265 | return; | ||
1266 | |||
1267 | head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16); | ||
1268 | tail = readl(SAR_REG_RAWCT); | ||
1269 | |||
1270 | pci_dma_sync_single_for_cpu(card->pcidev, IDT77252_PRV_PADDR(queue), | ||
1271 | queue->end - queue->head - 16, | ||
1272 | PCI_DMA_FROMDEVICE); | ||
1273 | |||
1274 | while (head != tail) { | ||
1275 | unsigned int vpi, vci, pti; | ||
1276 | u32 header; | ||
1277 | |||
1278 | header = le32_to_cpu(*(u32 *) &queue->data[0]); | ||
1279 | |||
1280 | vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; | ||
1281 | vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; | ||
1282 | pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; | ||
1283 | |||
1284 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
1285 | if (debug & DBG_RAW_CELL) { | ||
1286 | int i; | ||
1287 | |||
1288 | printk("%s: raw cell %x.%02x.%04x.%x.%x\n", | ||
1289 | card->name, (header >> 28) & 0x000f, | ||
1290 | (header >> 20) & 0x00ff, | ||
1291 | (header >> 4) & 0xffff, | ||
1292 | (header >> 1) & 0x0007, | ||
1293 | (header >> 0) & 0x0001); | ||
1294 | for (i = 16; i < 64; i++) | ||
1295 | printk(" %02x", queue->data[i]); | ||
1296 | printk("\n"); | ||
1297 | } | ||
1298 | #endif | ||
1299 | |||
1300 | if (vpi >= (1<<card->vpibits) || vci >= (1<<card->vcibits)) { | ||
1301 | RPRINTK("%s: SDU received for out-of-range vc %u.%u\n", | ||
1302 | card->name, vpi, vci); | ||
1303 | goto drop; | ||
1304 | } | ||
1305 | |||
1306 | vc = card->vcs[VPCI2VC(card, vpi, vci)]; | ||
1307 | if (!vc || !test_bit(VCF_RX, &vc->flags)) { | ||
1308 | RPRINTK("%s: SDU received on non RX vc %u.%u\n", | ||
1309 | card->name, vpi, vci); | ||
1310 | goto drop; | ||
1311 | } | ||
1312 | |||
1313 | vcc = vc->rx_vcc; | ||
1314 | |||
1315 | if (vcc->qos.aal != ATM_AAL0) { | ||
1316 | RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n", | ||
1317 | card->name, vpi, vci); | ||
1318 | atomic_inc(&vcc->stats->rx_drop); | ||
1319 | goto drop; | ||
1320 | } | ||
1321 | |||
1322 | if ((sb = dev_alloc_skb(64)) == NULL) { | ||
1323 | printk("%s: Can't allocate buffers for AAL0.\n", | ||
1324 | card->name); | ||
1325 | atomic_inc(&vcc->stats->rx_err); | ||
1326 | goto drop; | ||
1327 | } | ||
1328 | |||
1329 | if (!atm_charge(vcc, sb->truesize)) { | ||
1330 | RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n", | ||
1331 | card->name); | ||
1332 | dev_kfree_skb(sb); | ||
1333 | goto drop; | ||
1334 | } | ||
1335 | |||
1336 | *((u32 *) sb->data) = header; | ||
1337 | skb_put(sb, sizeof(u32)); | ||
1338 | memcpy(skb_put(sb, ATM_CELL_PAYLOAD), &(queue->data[16]), | ||
1339 | ATM_CELL_PAYLOAD); | ||
1340 | |||
1341 | ATM_SKB(sb)->vcc = vcc; | ||
1342 | do_gettimeofday(&sb->stamp); | ||
1343 | vcc->push(vcc, sb); | ||
1344 | atomic_inc(&vcc->stats->rx); | ||
1345 | |||
1346 | drop: | ||
1347 | skb_pull(queue, 64); | ||
1348 | |||
1349 | head = IDT77252_PRV_PADDR(queue) | ||
1350 | + (queue->data - queue->head - 16); | ||
1351 | |||
1352 | if (queue->len < 128) { | ||
1353 | struct sk_buff *next; | ||
1354 | u32 handle; | ||
1355 | |||
1356 | head = le32_to_cpu(*(u32 *) &queue->data[0]); | ||
1357 | handle = le32_to_cpu(*(u32 *) &queue->data[4]); | ||
1358 | |||
1359 | next = sb_pool_skb(card, handle); | ||
1360 | recycle_rx_skb(card, queue); | ||
1361 | |||
1362 | if (next) { | ||
1363 | card->raw_cell_head = next; | ||
1364 | queue = card->raw_cell_head; | ||
1365 | pci_dma_sync_single_for_cpu(card->pcidev, | ||
1366 | IDT77252_PRV_PADDR(queue), | ||
1367 | queue->end - queue->data, | ||
1368 | PCI_DMA_FROMDEVICE); | ||
1369 | } else { | ||
1370 | card->raw_cell_head = NULL; | ||
1371 | printk("%s: raw cell queue overrun\n", | ||
1372 | card->name); | ||
1373 | break; | ||
1374 | } | ||
1375 | } | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | |||
1380 | /*****************************************************************************/ | ||
1381 | /* */ | ||
1382 | /* TSQ Handling */ | ||
1383 | /* */ | ||
1384 | /*****************************************************************************/ | ||
1385 | |||
1386 | static int | ||
1387 | init_tsq(struct idt77252_dev *card) | ||
1388 | { | ||
1389 | struct tsq_entry *tsqe; | ||
1390 | |||
1391 | card->tsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE, | ||
1392 | &card->tsq.paddr); | ||
1393 | if (card->tsq.base == NULL) { | ||
1394 | printk("%s: can't allocate TSQ.\n", card->name); | ||
1395 | return -1; | ||
1396 | } | ||
1397 | memset(card->tsq.base, 0, TSQSIZE); | ||
1398 | |||
1399 | card->tsq.last = card->tsq.base + TSQ_NUM_ENTRIES - 1; | ||
1400 | card->tsq.next = card->tsq.last; | ||
1401 | for (tsqe = card->tsq.base; tsqe <= card->tsq.last; tsqe++) | ||
1402 | tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID); | ||
1403 | |||
1404 | writel(card->tsq.paddr, SAR_REG_TSQB); | ||
1405 | writel((unsigned long) card->tsq.next - (unsigned long) card->tsq.base, | ||
1406 | SAR_REG_TSQH); | ||
1407 | |||
1408 | return 0; | ||
1409 | } | ||
1410 | |||
1411 | static void | ||
1412 | deinit_tsq(struct idt77252_dev *card) | ||
1413 | { | ||
1414 | pci_free_consistent(card->pcidev, TSQSIZE, | ||
1415 | card->tsq.base, card->tsq.paddr); | ||
1416 | } | ||
1417 | |||
1418 | static void | ||
1419 | idt77252_tx(struct idt77252_dev *card) | ||
1420 | { | ||
1421 | struct tsq_entry *tsqe; | ||
1422 | unsigned int vpi, vci; | ||
1423 | struct vc_map *vc; | ||
1424 | u32 conn, stat; | ||
1425 | |||
1426 | if (card->tsq.next == card->tsq.last) | ||
1427 | tsqe = card->tsq.base; | ||
1428 | else | ||
1429 | tsqe = card->tsq.next + 1; | ||
1430 | |||
1431 | TXPRINTK("idt77252_tx: tsq %p: base %p, next %p, last %p\n", tsqe, | ||
1432 | card->tsq.base, card->tsq.next, card->tsq.last); | ||
1433 | TXPRINTK("idt77252_tx: tsqb %08x, tsqt %08x, tsqh %08x, \n", | ||
1434 | readl(SAR_REG_TSQB), | ||
1435 | readl(SAR_REG_TSQT), | ||
1436 | readl(SAR_REG_TSQH)); | ||
1437 | |||
1438 | stat = le32_to_cpu(tsqe->word_2); | ||
1439 | |||
1440 | if (stat & SAR_TSQE_INVALID) | ||
1441 | return; | ||
1442 | |||
1443 | do { | ||
1444 | TXPRINTK("tsqe: 0x%p [0x%08x 0x%08x]\n", tsqe, | ||
1445 | le32_to_cpu(tsqe->word_1), | ||
1446 | le32_to_cpu(tsqe->word_2)); | ||
1447 | |||
1448 | switch (stat & SAR_TSQE_TYPE) { | ||
1449 | case SAR_TSQE_TYPE_TIMER: | ||
1450 | TXPRINTK("%s: Timer RollOver detected.\n", card->name); | ||
1451 | break; | ||
1452 | |||
1453 | case SAR_TSQE_TYPE_IDLE: | ||
1454 | |||
1455 | conn = le32_to_cpu(tsqe->word_1); | ||
1456 | |||
1457 | if (SAR_TSQE_TAG(stat) == 0x10) { | ||
1458 | #ifdef NOTDEF | ||
1459 | printk("%s: Connection %d halted.\n", | ||
1460 | card->name, | ||
1461 | le32_to_cpu(tsqe->word_1) & 0x1fff); | ||
1462 | #endif | ||
1463 | break; | ||
1464 | } | ||
1465 | |||
1466 | vc = card->vcs[conn & 0x1fff]; | ||
1467 | if (!vc) { | ||
1468 | printk("%s: could not find VC from conn %d\n", | ||
1469 | card->name, conn & 0x1fff); | ||
1470 | break; | ||
1471 | } | ||
1472 | |||
1473 | printk("%s: Connection %d IDLE.\n", | ||
1474 | card->name, vc->index); | ||
1475 | |||
1476 | set_bit(VCF_IDLE, &vc->flags); | ||
1477 | break; | ||
1478 | |||
1479 | case SAR_TSQE_TYPE_TSR: | ||
1480 | |||
1481 | conn = le32_to_cpu(tsqe->word_1); | ||
1482 | |||
1483 | vc = card->vcs[conn & 0x1fff]; | ||
1484 | if (!vc) { | ||
1485 | printk("%s: no VC at index %d\n", | ||
1486 | card->name, | ||
1487 | le32_to_cpu(tsqe->word_1) & 0x1fff); | ||
1488 | break; | ||
1489 | } | ||
1490 | |||
1491 | drain_scq(card, vc); | ||
1492 | break; | ||
1493 | |||
1494 | case SAR_TSQE_TYPE_TBD_COMP: | ||
1495 | |||
1496 | conn = le32_to_cpu(tsqe->word_1); | ||
1497 | |||
1498 | vpi = (conn >> SAR_TBD_VPI_SHIFT) & 0x00ff; | ||
1499 | vci = (conn >> SAR_TBD_VCI_SHIFT) & 0xffff; | ||
1500 | |||
1501 | if (vpi >= (1 << card->vpibits) || | ||
1502 | vci >= (1 << card->vcibits)) { | ||
1503 | printk("%s: TBD complete: " | ||
1504 | "out of range VPI.VCI %u.%u\n", | ||
1505 | card->name, vpi, vci); | ||
1506 | break; | ||
1507 | } | ||
1508 | |||
1509 | vc = card->vcs[VPCI2VC(card, vpi, vci)]; | ||
1510 | if (!vc) { | ||
1511 | printk("%s: TBD complete: " | ||
1512 | "no VC at VPI.VCI %u.%u\n", | ||
1513 | card->name, vpi, vci); | ||
1514 | break; | ||
1515 | } | ||
1516 | |||
1517 | drain_scq(card, vc); | ||
1518 | break; | ||
1519 | } | ||
1520 | |||
1521 | tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID); | ||
1522 | |||
1523 | card->tsq.next = tsqe; | ||
1524 | if (card->tsq.next == card->tsq.last) | ||
1525 | tsqe = card->tsq.base; | ||
1526 | else | ||
1527 | tsqe = card->tsq.next + 1; | ||
1528 | |||
1529 | TXPRINTK("tsqe: %p: base %p, next %p, last %p\n", tsqe, | ||
1530 | card->tsq.base, card->tsq.next, card->tsq.last); | ||
1531 | |||
1532 | stat = le32_to_cpu(tsqe->word_2); | ||
1533 | |||
1534 | } while (!(stat & SAR_TSQE_INVALID)); | ||
1535 | |||
1536 | writel((unsigned long)card->tsq.next - (unsigned long)card->tsq.base, | ||
1537 | SAR_REG_TSQH); | ||
1538 | |||
1539 | XPRINTK("idt77252_tx-after writel%d: TSQ head = 0x%x, tail = 0x%x, next = 0x%p.\n", | ||
1540 | card->index, readl(SAR_REG_TSQH), | ||
1541 | readl(SAR_REG_TSQT), card->tsq.next); | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | static void | ||
1546 | tst_timer(unsigned long data) | ||
1547 | { | ||
1548 | struct idt77252_dev *card = (struct idt77252_dev *)data; | ||
1549 | unsigned long base, idle, jump; | ||
1550 | unsigned long flags; | ||
1551 | u32 pc; | ||
1552 | int e; | ||
1553 | |||
1554 | spin_lock_irqsave(&card->tst_lock, flags); | ||
1555 | |||
1556 | base = card->tst[card->tst_index]; | ||
1557 | idle = card->tst[card->tst_index ^ 1]; | ||
1558 | |||
1559 | if (test_bit(TST_SWITCH_WAIT, &card->tst_state)) { | ||
1560 | jump = base + card->tst_size - 2; | ||
1561 | |||
1562 | pc = readl(SAR_REG_NOW) >> 2; | ||
1563 | if ((pc ^ idle) & ~(card->tst_size - 1)) { | ||
1564 | mod_timer(&card->tst_timer, jiffies + 1); | ||
1565 | goto out; | ||
1566 | } | ||
1567 | |||
1568 | clear_bit(TST_SWITCH_WAIT, &card->tst_state); | ||
1569 | |||
1570 | card->tst_index ^= 1; | ||
1571 | write_sram(card, jump, TSTE_OPC_JMP | (base << 2)); | ||
1572 | |||
1573 | base = card->tst[card->tst_index]; | ||
1574 | idle = card->tst[card->tst_index ^ 1]; | ||
1575 | |||
1576 | for (e = 0; e < card->tst_size - 2; e++) { | ||
1577 | if (card->soft_tst[e].tste & TSTE_PUSH_IDLE) { | ||
1578 | write_sram(card, idle + e, | ||
1579 | card->soft_tst[e].tste & TSTE_MASK); | ||
1580 | card->soft_tst[e].tste &= ~(TSTE_PUSH_IDLE); | ||
1581 | } | ||
1582 | } | ||
1583 | } | ||
1584 | |||
1585 | if (test_and_clear_bit(TST_SWITCH_PENDING, &card->tst_state)) { | ||
1586 | |||
1587 | for (e = 0; e < card->tst_size - 2; e++) { | ||
1588 | if (card->soft_tst[e].tste & TSTE_PUSH_ACTIVE) { | ||
1589 | write_sram(card, idle + e, | ||
1590 | card->soft_tst[e].tste & TSTE_MASK); | ||
1591 | card->soft_tst[e].tste &= ~(TSTE_PUSH_ACTIVE); | ||
1592 | card->soft_tst[e].tste |= TSTE_PUSH_IDLE; | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | jump = base + card->tst_size - 2; | ||
1597 | |||
1598 | write_sram(card, jump, TSTE_OPC_NULL); | ||
1599 | set_bit(TST_SWITCH_WAIT, &card->tst_state); | ||
1600 | |||
1601 | mod_timer(&card->tst_timer, jiffies + 1); | ||
1602 | } | ||
1603 | |||
1604 | out: | ||
1605 | spin_unlock_irqrestore(&card->tst_lock, flags); | ||
1606 | } | ||
1607 | |||
1608 | static int | ||
1609 | __fill_tst(struct idt77252_dev *card, struct vc_map *vc, | ||
1610 | int n, unsigned int opc) | ||
1611 | { | ||
1612 | unsigned long cl, avail; | ||
1613 | unsigned long idle; | ||
1614 | int e, r; | ||
1615 | u32 data; | ||
1616 | |||
1617 | avail = card->tst_size - 2; | ||
1618 | for (e = 0; e < avail; e++) { | ||
1619 | if (card->soft_tst[e].vc == NULL) | ||
1620 | break; | ||
1621 | } | ||
1622 | if (e >= avail) { | ||
1623 | printk("%s: No free TST entries found\n", card->name); | ||
1624 | return -1; | ||
1625 | } | ||
1626 | |||
1627 | NPRINTK("%s: conn %d: first TST entry at %d.\n", | ||
1628 | card->name, vc ? vc->index : -1, e); | ||
1629 | |||
1630 | r = n; | ||
1631 | cl = avail; | ||
1632 | data = opc & TSTE_OPC_MASK; | ||
1633 | if (vc && (opc != TSTE_OPC_NULL)) | ||
1634 | data = opc | vc->index; | ||
1635 | |||
1636 | idle = card->tst[card->tst_index ^ 1]; | ||
1637 | |||
1638 | /* | ||
1639 | * Fill Soft TST. | ||
1640 | */ | ||
1641 | while (r > 0) { | ||
1642 | if ((cl >= avail) && (card->soft_tst[e].vc == NULL)) { | ||
1643 | if (vc) | ||
1644 | card->soft_tst[e].vc = vc; | ||
1645 | else | ||
1646 | card->soft_tst[e].vc = (void *)-1; | ||
1647 | |||
1648 | card->soft_tst[e].tste = data; | ||
1649 | if (timer_pending(&card->tst_timer)) | ||
1650 | card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE; | ||
1651 | else { | ||
1652 | write_sram(card, idle + e, data); | ||
1653 | card->soft_tst[e].tste |= TSTE_PUSH_IDLE; | ||
1654 | } | ||
1655 | |||
1656 | cl -= card->tst_size; | ||
1657 | r--; | ||
1658 | } | ||
1659 | |||
1660 | if (++e == avail) | ||
1661 | e = 0; | ||
1662 | cl += n; | ||
1663 | } | ||
1664 | |||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | static int | ||
1669 | fill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc) | ||
1670 | { | ||
1671 | unsigned long flags; | ||
1672 | int res; | ||
1673 | |||
1674 | spin_lock_irqsave(&card->tst_lock, flags); | ||
1675 | |||
1676 | res = __fill_tst(card, vc, n, opc); | ||
1677 | |||
1678 | set_bit(TST_SWITCH_PENDING, &card->tst_state); | ||
1679 | if (!timer_pending(&card->tst_timer)) | ||
1680 | mod_timer(&card->tst_timer, jiffies + 1); | ||
1681 | |||
1682 | spin_unlock_irqrestore(&card->tst_lock, flags); | ||
1683 | return res; | ||
1684 | } | ||
1685 | |||
1686 | static int | ||
1687 | __clear_tst(struct idt77252_dev *card, struct vc_map *vc) | ||
1688 | { | ||
1689 | unsigned long idle; | ||
1690 | int e; | ||
1691 | |||
1692 | idle = card->tst[card->tst_index ^ 1]; | ||
1693 | |||
1694 | for (e = 0; e < card->tst_size - 2; e++) { | ||
1695 | if (card->soft_tst[e].vc == vc) { | ||
1696 | card->soft_tst[e].vc = NULL; | ||
1697 | |||
1698 | card->soft_tst[e].tste = TSTE_OPC_VAR; | ||
1699 | if (timer_pending(&card->tst_timer)) | ||
1700 | card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE; | ||
1701 | else { | ||
1702 | write_sram(card, idle + e, TSTE_OPC_VAR); | ||
1703 | card->soft_tst[e].tste |= TSTE_PUSH_IDLE; | ||
1704 | } | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | return 0; | ||
1709 | } | ||
1710 | |||
1711 | static int | ||
1712 | clear_tst(struct idt77252_dev *card, struct vc_map *vc) | ||
1713 | { | ||
1714 | unsigned long flags; | ||
1715 | int res; | ||
1716 | |||
1717 | spin_lock_irqsave(&card->tst_lock, flags); | ||
1718 | |||
1719 | res = __clear_tst(card, vc); | ||
1720 | |||
1721 | set_bit(TST_SWITCH_PENDING, &card->tst_state); | ||
1722 | if (!timer_pending(&card->tst_timer)) | ||
1723 | mod_timer(&card->tst_timer, jiffies + 1); | ||
1724 | |||
1725 | spin_unlock_irqrestore(&card->tst_lock, flags); | ||
1726 | return res; | ||
1727 | } | ||
1728 | |||
1729 | static int | ||
1730 | change_tst(struct idt77252_dev *card, struct vc_map *vc, | ||
1731 | int n, unsigned int opc) | ||
1732 | { | ||
1733 | unsigned long flags; | ||
1734 | int res; | ||
1735 | |||
1736 | spin_lock_irqsave(&card->tst_lock, flags); | ||
1737 | |||
1738 | __clear_tst(card, vc); | ||
1739 | res = __fill_tst(card, vc, n, opc); | ||
1740 | |||
1741 | set_bit(TST_SWITCH_PENDING, &card->tst_state); | ||
1742 | if (!timer_pending(&card->tst_timer)) | ||
1743 | mod_timer(&card->tst_timer, jiffies + 1); | ||
1744 | |||
1745 | spin_unlock_irqrestore(&card->tst_lock, flags); | ||
1746 | return res; | ||
1747 | } | ||
1748 | |||
1749 | |||
1750 | static int | ||
1751 | set_tct(struct idt77252_dev *card, struct vc_map *vc) | ||
1752 | { | ||
1753 | unsigned long tct; | ||
1754 | |||
1755 | tct = (unsigned long) (card->tct_base + vc->index * SAR_SRAM_TCT_SIZE); | ||
1756 | |||
1757 | switch (vc->class) { | ||
1758 | case SCHED_CBR: | ||
1759 | OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n", | ||
1760 | card->name, tct, vc->scq->scd); | ||
1761 | |||
1762 | write_sram(card, tct + 0, TCT_CBR | vc->scq->scd); | ||
1763 | write_sram(card, tct + 1, 0); | ||
1764 | write_sram(card, tct + 2, 0); | ||
1765 | write_sram(card, tct + 3, 0); | ||
1766 | write_sram(card, tct + 4, 0); | ||
1767 | write_sram(card, tct + 5, 0); | ||
1768 | write_sram(card, tct + 6, 0); | ||
1769 | write_sram(card, tct + 7, 0); | ||
1770 | break; | ||
1771 | |||
1772 | case SCHED_UBR: | ||
1773 | OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n", | ||
1774 | card->name, tct, vc->scq->scd); | ||
1775 | |||
1776 | write_sram(card, tct + 0, TCT_UBR | vc->scq->scd); | ||
1777 | write_sram(card, tct + 1, 0); | ||
1778 | write_sram(card, tct + 2, TCT_TSIF); | ||
1779 | write_sram(card, tct + 3, TCT_HALT | TCT_IDLE); | ||
1780 | write_sram(card, tct + 4, 0); | ||
1781 | write_sram(card, tct + 5, vc->init_er); | ||
1782 | write_sram(card, tct + 6, 0); | ||
1783 | write_sram(card, tct + 7, TCT_FLAG_UBR); | ||
1784 | break; | ||
1785 | |||
1786 | case SCHED_VBR: | ||
1787 | case SCHED_ABR: | ||
1788 | default: | ||
1789 | return -ENOSYS; | ||
1790 | } | ||
1791 | |||
1792 | return 0; | ||
1793 | } | ||
1794 | |||
1795 | /*****************************************************************************/ | ||
1796 | /* */ | ||
1797 | /* FBQ Handling */ | ||
1798 | /* */ | ||
1799 | /*****************************************************************************/ | ||
1800 | |||
1801 | static __inline__ int | ||
1802 | idt77252_fbq_level(struct idt77252_dev *card, int queue) | ||
1803 | { | ||
1804 | return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) & 0x0f; | ||
1805 | } | ||
1806 | |||
1807 | static __inline__ int | ||
1808 | idt77252_fbq_full(struct idt77252_dev *card, int queue) | ||
1809 | { | ||
1810 | return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) == 0x0f; | ||
1811 | } | ||
1812 | |||
1813 | static int | ||
1814 | push_rx_skb(struct idt77252_dev *card, struct sk_buff *skb, int queue) | ||
1815 | { | ||
1816 | unsigned long flags; | ||
1817 | u32 handle; | ||
1818 | u32 addr; | ||
1819 | |||
1820 | skb->data = skb->tail = skb->head; | ||
1821 | skb->len = 0; | ||
1822 | |||
1823 | skb_reserve(skb, 16); | ||
1824 | |||
1825 | switch (queue) { | ||
1826 | case 0: | ||
1827 | skb_put(skb, SAR_FB_SIZE_0); | ||
1828 | break; | ||
1829 | case 1: | ||
1830 | skb_put(skb, SAR_FB_SIZE_1); | ||
1831 | break; | ||
1832 | case 2: | ||
1833 | skb_put(skb, SAR_FB_SIZE_2); | ||
1834 | break; | ||
1835 | case 3: | ||
1836 | skb_put(skb, SAR_FB_SIZE_3); | ||
1837 | break; | ||
1838 | default: | ||
1839 | dev_kfree_skb(skb); | ||
1840 | return -1; | ||
1841 | } | ||
1842 | |||
1843 | if (idt77252_fbq_full(card, queue)) | ||
1844 | return -1; | ||
1845 | |||
1846 | memset(&skb->data[(skb->len & ~(0x3f)) - 64], 0, 2 * sizeof(u32)); | ||
1847 | |||
1848 | handle = IDT77252_PRV_POOL(skb); | ||
1849 | addr = IDT77252_PRV_PADDR(skb); | ||
1850 | |||
1851 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
1852 | writel(handle, card->fbq[queue]); | ||
1853 | writel(addr, card->fbq[queue]); | ||
1854 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
1855 | |||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | static void | ||
1860 | add_rx_skb(struct idt77252_dev *card, int queue, | ||
1861 | unsigned int size, unsigned int count) | ||
1862 | { | ||
1863 | struct sk_buff *skb; | ||
1864 | dma_addr_t paddr; | ||
1865 | u32 handle; | ||
1866 | |||
1867 | while (count--) { | ||
1868 | skb = dev_alloc_skb(size); | ||
1869 | if (!skb) | ||
1870 | return; | ||
1871 | |||
1872 | if (sb_pool_add(card, skb, queue)) { | ||
1873 | printk("%s: SB POOL full\n", __FUNCTION__); | ||
1874 | goto outfree; | ||
1875 | } | ||
1876 | |||
1877 | paddr = pci_map_single(card->pcidev, skb->data, | ||
1878 | skb->end - skb->data, | ||
1879 | PCI_DMA_FROMDEVICE); | ||
1880 | IDT77252_PRV_PADDR(skb) = paddr; | ||
1881 | |||
1882 | if (push_rx_skb(card, skb, queue)) { | ||
1883 | printk("%s: FB QUEUE full\n", __FUNCTION__); | ||
1884 | goto outunmap; | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | return; | ||
1889 | |||
1890 | outunmap: | ||
1891 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
1892 | skb->end - skb->data, PCI_DMA_FROMDEVICE); | ||
1893 | |||
1894 | handle = IDT77252_PRV_POOL(skb); | ||
1895 | card->sbpool[POOL_QUEUE(handle)].skb[POOL_INDEX(handle)] = NULL; | ||
1896 | |||
1897 | outfree: | ||
1898 | dev_kfree_skb(skb); | ||
1899 | } | ||
1900 | |||
1901 | |||
1902 | static void | ||
1903 | recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb) | ||
1904 | { | ||
1905 | u32 handle = IDT77252_PRV_POOL(skb); | ||
1906 | int err; | ||
1907 | |||
1908 | pci_dma_sync_single_for_device(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
1909 | skb->end - skb->data, PCI_DMA_FROMDEVICE); | ||
1910 | |||
1911 | err = push_rx_skb(card, skb, POOL_QUEUE(handle)); | ||
1912 | if (err) { | ||
1913 | pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb), | ||
1914 | skb->end - skb->data, PCI_DMA_FROMDEVICE); | ||
1915 | sb_pool_remove(card, skb); | ||
1916 | dev_kfree_skb(skb); | ||
1917 | } | ||
1918 | } | ||
1919 | |||
1920 | static void | ||
1921 | flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp) | ||
1922 | { | ||
1923 | rpp->len = 0; | ||
1924 | rpp->count = 0; | ||
1925 | rpp->first = NULL; | ||
1926 | rpp->last = &rpp->first; | ||
1927 | } | ||
1928 | |||
1929 | static void | ||
1930 | recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp) | ||
1931 | { | ||
1932 | struct sk_buff *skb, *next; | ||
1933 | int i; | ||
1934 | |||
1935 | skb = rpp->first; | ||
1936 | for (i = 0; i < rpp->count; i++) { | ||
1937 | next = skb->next; | ||
1938 | skb->next = NULL; | ||
1939 | recycle_rx_skb(card, skb); | ||
1940 | skb = next; | ||
1941 | } | ||
1942 | flush_rx_pool(card, rpp); | ||
1943 | } | ||
1944 | |||
1945 | /*****************************************************************************/ | ||
1946 | /* */ | ||
1947 | /* ATM Interface */ | ||
1948 | /* */ | ||
1949 | /*****************************************************************************/ | ||
1950 | |||
1951 | static void | ||
1952 | idt77252_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr) | ||
1953 | { | ||
1954 | write_utility(dev->dev_data, 0x100 + (addr & 0x1ff), value); | ||
1955 | } | ||
1956 | |||
1957 | static unsigned char | ||
1958 | idt77252_phy_get(struct atm_dev *dev, unsigned long addr) | ||
1959 | { | ||
1960 | return read_utility(dev->dev_data, 0x100 + (addr & 0x1ff)); | ||
1961 | } | ||
1962 | |||
1963 | static inline int | ||
1964 | idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam) | ||
1965 | { | ||
1966 | struct atm_dev *dev = vcc->dev; | ||
1967 | struct idt77252_dev *card = dev->dev_data; | ||
1968 | struct vc_map *vc = vcc->dev_data; | ||
1969 | int err; | ||
1970 | |||
1971 | if (vc == NULL) { | ||
1972 | printk("%s: NULL connection in send().\n", card->name); | ||
1973 | atomic_inc(&vcc->stats->tx_err); | ||
1974 | dev_kfree_skb(skb); | ||
1975 | return -EINVAL; | ||
1976 | } | ||
1977 | if (!test_bit(VCF_TX, &vc->flags)) { | ||
1978 | printk("%s: Trying to transmit on a non-tx VC.\n", card->name); | ||
1979 | atomic_inc(&vcc->stats->tx_err); | ||
1980 | dev_kfree_skb(skb); | ||
1981 | return -EINVAL; | ||
1982 | } | ||
1983 | |||
1984 | switch (vcc->qos.aal) { | ||
1985 | case ATM_AAL0: | ||
1986 | case ATM_AAL1: | ||
1987 | case ATM_AAL5: | ||
1988 | break; | ||
1989 | default: | ||
1990 | printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal); | ||
1991 | atomic_inc(&vcc->stats->tx_err); | ||
1992 | dev_kfree_skb(skb); | ||
1993 | return -EINVAL; | ||
1994 | } | ||
1995 | |||
1996 | if (skb_shinfo(skb)->nr_frags != 0) { | ||
1997 | printk("%s: No scatter-gather yet.\n", card->name); | ||
1998 | atomic_inc(&vcc->stats->tx_err); | ||
1999 | dev_kfree_skb(skb); | ||
2000 | return -EINVAL; | ||
2001 | } | ||
2002 | ATM_SKB(skb)->vcc = vcc; | ||
2003 | |||
2004 | err = queue_skb(card, vc, skb, oam); | ||
2005 | if (err) { | ||
2006 | atomic_inc(&vcc->stats->tx_err); | ||
2007 | dev_kfree_skb(skb); | ||
2008 | return err; | ||
2009 | } | ||
2010 | |||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | int | ||
2015 | idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
2016 | { | ||
2017 | return idt77252_send_skb(vcc, skb, 0); | ||
2018 | } | ||
2019 | |||
2020 | static int | ||
2021 | idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags) | ||
2022 | { | ||
2023 | struct atm_dev *dev = vcc->dev; | ||
2024 | struct idt77252_dev *card = dev->dev_data; | ||
2025 | struct sk_buff *skb; | ||
2026 | |||
2027 | skb = dev_alloc_skb(64); | ||
2028 | if (!skb) { | ||
2029 | printk("%s: Out of memory in send_oam().\n", card->name); | ||
2030 | atomic_inc(&vcc->stats->tx_err); | ||
2031 | return -ENOMEM; | ||
2032 | } | ||
2033 | atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); | ||
2034 | |||
2035 | memcpy(skb_put(skb, 52), cell, 52); | ||
2036 | |||
2037 | return idt77252_send_skb(vcc, skb, 1); | ||
2038 | } | ||
2039 | |||
2040 | static __inline__ unsigned int | ||
2041 | idt77252_fls(unsigned int x) | ||
2042 | { | ||
2043 | int r = 1; | ||
2044 | |||
2045 | if (x == 0) | ||
2046 | return 0; | ||
2047 | if (x & 0xffff0000) { | ||
2048 | x >>= 16; | ||
2049 | r += 16; | ||
2050 | } | ||
2051 | if (x & 0xff00) { | ||
2052 | x >>= 8; | ||
2053 | r += 8; | ||
2054 | } | ||
2055 | if (x & 0xf0) { | ||
2056 | x >>= 4; | ||
2057 | r += 4; | ||
2058 | } | ||
2059 | if (x & 0xc) { | ||
2060 | x >>= 2; | ||
2061 | r += 2; | ||
2062 | } | ||
2063 | if (x & 0x2) | ||
2064 | r += 1; | ||
2065 | return r; | ||
2066 | } | ||
2067 | |||
2068 | static u16 | ||
2069 | idt77252_int_to_atmfp(unsigned int rate) | ||
2070 | { | ||
2071 | u16 m, e; | ||
2072 | |||
2073 | if (rate == 0) | ||
2074 | return 0; | ||
2075 | e = idt77252_fls(rate) - 1; | ||
2076 | if (e < 9) | ||
2077 | m = (rate - (1 << e)) << (9 - e); | ||
2078 | else if (e == 9) | ||
2079 | m = (rate - (1 << e)); | ||
2080 | else /* e > 9 */ | ||
2081 | m = (rate - (1 << e)) >> (e - 9); | ||
2082 | return 0x4000 | (e << 9) | m; | ||
2083 | } | ||
2084 | |||
2085 | static u8 | ||
2086 | idt77252_rate_logindex(struct idt77252_dev *card, int pcr) | ||
2087 | { | ||
2088 | u16 afp; | ||
2089 | |||
2090 | afp = idt77252_int_to_atmfp(pcr < 0 ? -pcr : pcr); | ||
2091 | if (pcr < 0) | ||
2092 | return rate_to_log[(afp >> 5) & 0x1ff]; | ||
2093 | return rate_to_log[((afp >> 5) + 1) & 0x1ff]; | ||
2094 | } | ||
2095 | |||
2096 | static void | ||
2097 | idt77252_est_timer(unsigned long data) | ||
2098 | { | ||
2099 | struct vc_map *vc = (struct vc_map *)data; | ||
2100 | struct idt77252_dev *card = vc->card; | ||
2101 | struct rate_estimator *est; | ||
2102 | unsigned long flags; | ||
2103 | u32 rate, cps; | ||
2104 | u64 ncells; | ||
2105 | u8 lacr; | ||
2106 | |||
2107 | spin_lock_irqsave(&vc->lock, flags); | ||
2108 | est = vc->estimator; | ||
2109 | if (!est) | ||
2110 | goto out; | ||
2111 | |||
2112 | ncells = est->cells; | ||
2113 | |||
2114 | rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval); | ||
2115 | est->last_cells = ncells; | ||
2116 | est->avcps += ((long)rate - (long)est->avcps) >> est->ewma_log; | ||
2117 | est->cps = (est->avcps + 0x1f) >> 5; | ||
2118 | |||
2119 | cps = est->cps; | ||
2120 | if (cps < (est->maxcps >> 4)) | ||
2121 | cps = est->maxcps >> 4; | ||
2122 | |||
2123 | lacr = idt77252_rate_logindex(card, cps); | ||
2124 | if (lacr > vc->max_er) | ||
2125 | lacr = vc->max_er; | ||
2126 | |||
2127 | if (lacr != vc->lacr) { | ||
2128 | vc->lacr = lacr; | ||
2129 | writel(TCMDQ_LACR|(vc->lacr << 16)|vc->index, SAR_REG_TCMDQ); | ||
2130 | } | ||
2131 | |||
2132 | est->timer.expires = jiffies + ((HZ / 4) << est->interval); | ||
2133 | add_timer(&est->timer); | ||
2134 | |||
2135 | out: | ||
2136 | spin_unlock_irqrestore(&vc->lock, flags); | ||
2137 | } | ||
2138 | |||
2139 | static struct rate_estimator * | ||
2140 | idt77252_init_est(struct vc_map *vc, int pcr) | ||
2141 | { | ||
2142 | struct rate_estimator *est; | ||
2143 | |||
2144 | est = kmalloc(sizeof(struct rate_estimator), GFP_KERNEL); | ||
2145 | if (!est) | ||
2146 | return NULL; | ||
2147 | memset(est, 0, sizeof(*est)); | ||
2148 | |||
2149 | est->maxcps = pcr < 0 ? -pcr : pcr; | ||
2150 | est->cps = est->maxcps; | ||
2151 | est->avcps = est->cps << 5; | ||
2152 | |||
2153 | est->interval = 2; /* XXX: make this configurable */ | ||
2154 | est->ewma_log = 2; /* XXX: make this configurable */ | ||
2155 | init_timer(&est->timer); | ||
2156 | est->timer.data = (unsigned long)vc; | ||
2157 | est->timer.function = idt77252_est_timer; | ||
2158 | |||
2159 | est->timer.expires = jiffies + ((HZ / 4) << est->interval); | ||
2160 | add_timer(&est->timer); | ||
2161 | |||
2162 | return est; | ||
2163 | } | ||
2164 | |||
2165 | static int | ||
2166 | idt77252_init_cbr(struct idt77252_dev *card, struct vc_map *vc, | ||
2167 | struct atm_vcc *vcc, struct atm_qos *qos) | ||
2168 | { | ||
2169 | int tst_free, tst_used, tst_entries; | ||
2170 | unsigned long tmpl, modl; | ||
2171 | int tcr, tcra; | ||
2172 | |||
2173 | if ((qos->txtp.max_pcr == 0) && | ||
2174 | (qos->txtp.pcr == 0) && (qos->txtp.min_pcr == 0)) { | ||
2175 | printk("%s: trying to open a CBR VC with cell rate = 0\n", | ||
2176 | card->name); | ||
2177 | return -EINVAL; | ||
2178 | } | ||
2179 | |||
2180 | tst_used = 0; | ||
2181 | tst_free = card->tst_free; | ||
2182 | if (test_bit(VCF_TX, &vc->flags)) | ||
2183 | tst_used = vc->ntste; | ||
2184 | tst_free += tst_used; | ||
2185 | |||
2186 | tcr = atm_pcr_goal(&qos->txtp); | ||
2187 | tcra = tcr >= 0 ? tcr : -tcr; | ||
2188 | |||
2189 | TXPRINTK("%s: CBR target cell rate = %d\n", card->name, tcra); | ||
2190 | |||
2191 | tmpl = (unsigned long) tcra * ((unsigned long) card->tst_size - 2); | ||
2192 | modl = tmpl % (unsigned long)card->utopia_pcr; | ||
2193 | |||
2194 | tst_entries = (int) (tmpl / card->utopia_pcr); | ||
2195 | if (tcr > 0) { | ||
2196 | if (modl > 0) | ||
2197 | tst_entries++; | ||
2198 | } else if (tcr == 0) { | ||
2199 | tst_entries = tst_free - SAR_TST_RESERVED; | ||
2200 | if (tst_entries <= 0) { | ||
2201 | printk("%s: no CBR bandwidth free.\n", card->name); | ||
2202 | return -ENOSR; | ||
2203 | } | ||
2204 | } | ||
2205 | |||
2206 | if (tst_entries == 0) { | ||
2207 | printk("%s: selected CBR bandwidth < granularity.\n", | ||
2208 | card->name); | ||
2209 | return -EINVAL; | ||
2210 | } | ||
2211 | |||
2212 | if (tst_entries > (tst_free - SAR_TST_RESERVED)) { | ||
2213 | printk("%s: not enough CBR bandwidth free.\n", card->name); | ||
2214 | return -ENOSR; | ||
2215 | } | ||
2216 | |||
2217 | vc->ntste = tst_entries; | ||
2218 | |||
2219 | card->tst_free = tst_free - tst_entries; | ||
2220 | if (test_bit(VCF_TX, &vc->flags)) { | ||
2221 | if (tst_used == tst_entries) | ||
2222 | return 0; | ||
2223 | |||
2224 | OPRINTK("%s: modify %d -> %d entries in TST.\n", | ||
2225 | card->name, tst_used, tst_entries); | ||
2226 | change_tst(card, vc, tst_entries, TSTE_OPC_CBR); | ||
2227 | return 0; | ||
2228 | } | ||
2229 | |||
2230 | OPRINTK("%s: setting %d entries in TST.\n", card->name, tst_entries); | ||
2231 | fill_tst(card, vc, tst_entries, TSTE_OPC_CBR); | ||
2232 | return 0; | ||
2233 | } | ||
2234 | |||
2235 | static int | ||
2236 | idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc, | ||
2237 | struct atm_vcc *vcc, struct atm_qos *qos) | ||
2238 | { | ||
2239 | unsigned long flags; | ||
2240 | int tcr; | ||
2241 | |||
2242 | spin_lock_irqsave(&vc->lock, flags); | ||
2243 | if (vc->estimator) { | ||
2244 | del_timer(&vc->estimator->timer); | ||
2245 | kfree(vc->estimator); | ||
2246 | vc->estimator = NULL; | ||
2247 | } | ||
2248 | spin_unlock_irqrestore(&vc->lock, flags); | ||
2249 | |||
2250 | tcr = atm_pcr_goal(&qos->txtp); | ||
2251 | if (tcr == 0) | ||
2252 | tcr = card->link_pcr; | ||
2253 | |||
2254 | vc->estimator = idt77252_init_est(vc, tcr); | ||
2255 | |||
2256 | vc->class = SCHED_UBR; | ||
2257 | vc->init_er = idt77252_rate_logindex(card, tcr); | ||
2258 | vc->lacr = vc->init_er; | ||
2259 | if (tcr < 0) | ||
2260 | vc->max_er = vc->init_er; | ||
2261 | else | ||
2262 | vc->max_er = 0xff; | ||
2263 | |||
2264 | return 0; | ||
2265 | } | ||
2266 | |||
2267 | static int | ||
2268 | idt77252_init_tx(struct idt77252_dev *card, struct vc_map *vc, | ||
2269 | struct atm_vcc *vcc, struct atm_qos *qos) | ||
2270 | { | ||
2271 | int error; | ||
2272 | |||
2273 | if (test_bit(VCF_TX, &vc->flags)) | ||
2274 | return -EBUSY; | ||
2275 | |||
2276 | switch (qos->txtp.traffic_class) { | ||
2277 | case ATM_CBR: | ||
2278 | vc->class = SCHED_CBR; | ||
2279 | break; | ||
2280 | |||
2281 | case ATM_UBR: | ||
2282 | vc->class = SCHED_UBR; | ||
2283 | break; | ||
2284 | |||
2285 | case ATM_VBR: | ||
2286 | case ATM_ABR: | ||
2287 | default: | ||
2288 | return -EPROTONOSUPPORT; | ||
2289 | } | ||
2290 | |||
2291 | vc->scq = alloc_scq(card, vc->class); | ||
2292 | if (!vc->scq) { | ||
2293 | printk("%s: can't get SCQ.\n", card->name); | ||
2294 | return -ENOMEM; | ||
2295 | } | ||
2296 | |||
2297 | vc->scq->scd = get_free_scd(card, vc); | ||
2298 | if (vc->scq->scd == 0) { | ||
2299 | printk("%s: no SCD available.\n", card->name); | ||
2300 | free_scq(card, vc->scq); | ||
2301 | return -ENOMEM; | ||
2302 | } | ||
2303 | |||
2304 | fill_scd(card, vc->scq, vc->class); | ||
2305 | |||
2306 | if (set_tct(card, vc)) { | ||
2307 | printk("%s: class %d not supported.\n", | ||
2308 | card->name, qos->txtp.traffic_class); | ||
2309 | |||
2310 | card->scd2vc[vc->scd_index] = NULL; | ||
2311 | free_scq(card, vc->scq); | ||
2312 | return -EPROTONOSUPPORT; | ||
2313 | } | ||
2314 | |||
2315 | switch (vc->class) { | ||
2316 | case SCHED_CBR: | ||
2317 | error = idt77252_init_cbr(card, vc, vcc, qos); | ||
2318 | if (error) { | ||
2319 | card->scd2vc[vc->scd_index] = NULL; | ||
2320 | free_scq(card, vc->scq); | ||
2321 | return error; | ||
2322 | } | ||
2323 | |||
2324 | clear_bit(VCF_IDLE, &vc->flags); | ||
2325 | writel(TCMDQ_START | vc->index, SAR_REG_TCMDQ); | ||
2326 | break; | ||
2327 | |||
2328 | case SCHED_UBR: | ||
2329 | error = idt77252_init_ubr(card, vc, vcc, qos); | ||
2330 | if (error) { | ||
2331 | card->scd2vc[vc->scd_index] = NULL; | ||
2332 | free_scq(card, vc->scq); | ||
2333 | return error; | ||
2334 | } | ||
2335 | |||
2336 | set_bit(VCF_IDLE, &vc->flags); | ||
2337 | break; | ||
2338 | } | ||
2339 | |||
2340 | vc->tx_vcc = vcc; | ||
2341 | set_bit(VCF_TX, &vc->flags); | ||
2342 | return 0; | ||
2343 | } | ||
2344 | |||
2345 | static int | ||
2346 | idt77252_init_rx(struct idt77252_dev *card, struct vc_map *vc, | ||
2347 | struct atm_vcc *vcc, struct atm_qos *qos) | ||
2348 | { | ||
2349 | unsigned long flags; | ||
2350 | unsigned long addr; | ||
2351 | u32 rcte = 0; | ||
2352 | |||
2353 | if (test_bit(VCF_RX, &vc->flags)) | ||
2354 | return -EBUSY; | ||
2355 | |||
2356 | vc->rx_vcc = vcc; | ||
2357 | set_bit(VCF_RX, &vc->flags); | ||
2358 | |||
2359 | if ((vcc->vci == 3) || (vcc->vci == 4)) | ||
2360 | return 0; | ||
2361 | |||
2362 | flush_rx_pool(card, &vc->rcv.rx_pool); | ||
2363 | |||
2364 | rcte |= SAR_RCTE_CONNECTOPEN; | ||
2365 | rcte |= SAR_RCTE_RAWCELLINTEN; | ||
2366 | |||
2367 | switch (qos->aal) { | ||
2368 | case ATM_AAL0: | ||
2369 | rcte |= SAR_RCTE_RCQ; | ||
2370 | break; | ||
2371 | case ATM_AAL1: | ||
2372 | rcte |= SAR_RCTE_OAM; /* Let SAR drop Video */ | ||
2373 | break; | ||
2374 | case ATM_AAL34: | ||
2375 | rcte |= SAR_RCTE_AAL34; | ||
2376 | break; | ||
2377 | case ATM_AAL5: | ||
2378 | rcte |= SAR_RCTE_AAL5; | ||
2379 | break; | ||
2380 | default: | ||
2381 | rcte |= SAR_RCTE_RCQ; | ||
2382 | break; | ||
2383 | } | ||
2384 | |||
2385 | if (qos->aal != ATM_AAL5) | ||
2386 | rcte |= SAR_RCTE_FBP_1; | ||
2387 | else if (qos->rxtp.max_sdu > SAR_FB_SIZE_2) | ||
2388 | rcte |= SAR_RCTE_FBP_3; | ||
2389 | else if (qos->rxtp.max_sdu > SAR_FB_SIZE_1) | ||
2390 | rcte |= SAR_RCTE_FBP_2; | ||
2391 | else if (qos->rxtp.max_sdu > SAR_FB_SIZE_0) | ||
2392 | rcte |= SAR_RCTE_FBP_1; | ||
2393 | else | ||
2394 | rcte |= SAR_RCTE_FBP_01; | ||
2395 | |||
2396 | addr = card->rct_base + (vc->index << 2); | ||
2397 | |||
2398 | OPRINTK("%s: writing RCT at 0x%lx\n", card->name, addr); | ||
2399 | write_sram(card, addr, rcte); | ||
2400 | |||
2401 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
2402 | writel(SAR_CMD_OPEN_CONNECTION | (addr << 2), SAR_REG_CMD); | ||
2403 | waitfor_idle(card); | ||
2404 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
2405 | |||
2406 | return 0; | ||
2407 | } | ||
2408 | |||
2409 | static int | ||
2410 | idt77252_open(struct atm_vcc *vcc) | ||
2411 | { | ||
2412 | struct atm_dev *dev = vcc->dev; | ||
2413 | struct idt77252_dev *card = dev->dev_data; | ||
2414 | struct vc_map *vc; | ||
2415 | unsigned int index; | ||
2416 | unsigned int inuse; | ||
2417 | int error; | ||
2418 | int vci = vcc->vci; | ||
2419 | short vpi = vcc->vpi; | ||
2420 | |||
2421 | if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) | ||
2422 | return 0; | ||
2423 | |||
2424 | if (vpi >= (1 << card->vpibits)) { | ||
2425 | printk("%s: unsupported VPI: %d\n", card->name, vpi); | ||
2426 | return -EINVAL; | ||
2427 | } | ||
2428 | |||
2429 | if (vci >= (1 << card->vcibits)) { | ||
2430 | printk("%s: unsupported VCI: %d\n", card->name, vci); | ||
2431 | return -EINVAL; | ||
2432 | } | ||
2433 | |||
2434 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
2435 | |||
2436 | down(&card->mutex); | ||
2437 | |||
2438 | OPRINTK("%s: opening vpi.vci: %d.%d\n", card->name, vpi, vci); | ||
2439 | |||
2440 | switch (vcc->qos.aal) { | ||
2441 | case ATM_AAL0: | ||
2442 | case ATM_AAL1: | ||
2443 | case ATM_AAL5: | ||
2444 | break; | ||
2445 | default: | ||
2446 | printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal); | ||
2447 | up(&card->mutex); | ||
2448 | return -EPROTONOSUPPORT; | ||
2449 | } | ||
2450 | |||
2451 | index = VPCI2VC(card, vpi, vci); | ||
2452 | if (!card->vcs[index]) { | ||
2453 | card->vcs[index] = kmalloc(sizeof(struct vc_map), GFP_KERNEL); | ||
2454 | if (!card->vcs[index]) { | ||
2455 | printk("%s: can't alloc vc in open()\n", card->name); | ||
2456 | up(&card->mutex); | ||
2457 | return -ENOMEM; | ||
2458 | } | ||
2459 | memset(card->vcs[index], 0, sizeof(struct vc_map)); | ||
2460 | |||
2461 | card->vcs[index]->card = card; | ||
2462 | card->vcs[index]->index = index; | ||
2463 | |||
2464 | spin_lock_init(&card->vcs[index]->lock); | ||
2465 | } | ||
2466 | vc = card->vcs[index]; | ||
2467 | |||
2468 | vcc->dev_data = vc; | ||
2469 | |||
2470 | IPRINTK("%s: idt77252_open: vc = %d (%d.%d) %s/%s (max RX SDU: %u)\n", | ||
2471 | card->name, vc->index, vcc->vpi, vcc->vci, | ||
2472 | vcc->qos.rxtp.traffic_class != ATM_NONE ? "rx" : "--", | ||
2473 | vcc->qos.txtp.traffic_class != ATM_NONE ? "tx" : "--", | ||
2474 | vcc->qos.rxtp.max_sdu); | ||
2475 | |||
2476 | inuse = 0; | ||
2477 | if (vcc->qos.txtp.traffic_class != ATM_NONE && | ||
2478 | test_bit(VCF_TX, &vc->flags)) | ||
2479 | inuse = 1; | ||
2480 | if (vcc->qos.rxtp.traffic_class != ATM_NONE && | ||
2481 | test_bit(VCF_RX, &vc->flags)) | ||
2482 | inuse += 2; | ||
2483 | |||
2484 | if (inuse) { | ||
2485 | printk("%s: %s vci already in use.\n", card->name, | ||
2486 | inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx"); | ||
2487 | up(&card->mutex); | ||
2488 | return -EADDRINUSE; | ||
2489 | } | ||
2490 | |||
2491 | if (vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2492 | error = idt77252_init_tx(card, vc, vcc, &vcc->qos); | ||
2493 | if (error) { | ||
2494 | up(&card->mutex); | ||
2495 | return error; | ||
2496 | } | ||
2497 | } | ||
2498 | |||
2499 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2500 | error = idt77252_init_rx(card, vc, vcc, &vcc->qos); | ||
2501 | if (error) { | ||
2502 | up(&card->mutex); | ||
2503 | return error; | ||
2504 | } | ||
2505 | } | ||
2506 | |||
2507 | set_bit(ATM_VF_READY, &vcc->flags); | ||
2508 | |||
2509 | up(&card->mutex); | ||
2510 | return 0; | ||
2511 | } | ||
2512 | |||
2513 | static void | ||
2514 | idt77252_close(struct atm_vcc *vcc) | ||
2515 | { | ||
2516 | struct atm_dev *dev = vcc->dev; | ||
2517 | struct idt77252_dev *card = dev->dev_data; | ||
2518 | struct vc_map *vc = vcc->dev_data; | ||
2519 | unsigned long flags; | ||
2520 | unsigned long addr; | ||
2521 | unsigned long timeout; | ||
2522 | |||
2523 | down(&card->mutex); | ||
2524 | |||
2525 | IPRINTK("%s: idt77252_close: vc = %d (%d.%d)\n", | ||
2526 | card->name, vc->index, vcc->vpi, vcc->vci); | ||
2527 | |||
2528 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
2529 | |||
2530 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2531 | |||
2532 | spin_lock_irqsave(&vc->lock, flags); | ||
2533 | clear_bit(VCF_RX, &vc->flags); | ||
2534 | vc->rx_vcc = NULL; | ||
2535 | spin_unlock_irqrestore(&vc->lock, flags); | ||
2536 | |||
2537 | if ((vcc->vci == 3) || (vcc->vci == 4)) | ||
2538 | goto done; | ||
2539 | |||
2540 | addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE; | ||
2541 | |||
2542 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
2543 | writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2), SAR_REG_CMD); | ||
2544 | waitfor_idle(card); | ||
2545 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
2546 | |||
2547 | if (vc->rcv.rx_pool.count) { | ||
2548 | DPRINTK("%s: closing a VC with pending rx buffers.\n", | ||
2549 | card->name); | ||
2550 | |||
2551 | recycle_rx_pool_skb(card, &vc->rcv.rx_pool); | ||
2552 | } | ||
2553 | } | ||
2554 | |||
2555 | done: | ||
2556 | if (vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2557 | |||
2558 | spin_lock_irqsave(&vc->lock, flags); | ||
2559 | clear_bit(VCF_TX, &vc->flags); | ||
2560 | clear_bit(VCF_IDLE, &vc->flags); | ||
2561 | clear_bit(VCF_RSV, &vc->flags); | ||
2562 | vc->tx_vcc = NULL; | ||
2563 | |||
2564 | if (vc->estimator) { | ||
2565 | del_timer(&vc->estimator->timer); | ||
2566 | kfree(vc->estimator); | ||
2567 | vc->estimator = NULL; | ||
2568 | } | ||
2569 | spin_unlock_irqrestore(&vc->lock, flags); | ||
2570 | |||
2571 | timeout = 5 * 1000; | ||
2572 | while (atomic_read(&vc->scq->used) > 0) { | ||
2573 | timeout = msleep_interruptible(timeout); | ||
2574 | if (!timeout) | ||
2575 | break; | ||
2576 | } | ||
2577 | if (!timeout) | ||
2578 | printk("%s: SCQ drain timeout: %u used\n", | ||
2579 | card->name, atomic_read(&vc->scq->used)); | ||
2580 | |||
2581 | writel(TCMDQ_HALT | vc->index, SAR_REG_TCMDQ); | ||
2582 | clear_scd(card, vc->scq, vc->class); | ||
2583 | |||
2584 | if (vc->class == SCHED_CBR) { | ||
2585 | clear_tst(card, vc); | ||
2586 | card->tst_free += vc->ntste; | ||
2587 | vc->ntste = 0; | ||
2588 | } | ||
2589 | |||
2590 | card->scd2vc[vc->scd_index] = NULL; | ||
2591 | free_scq(card, vc->scq); | ||
2592 | } | ||
2593 | |||
2594 | up(&card->mutex); | ||
2595 | } | ||
2596 | |||
2597 | static int | ||
2598 | idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags) | ||
2599 | { | ||
2600 | struct atm_dev *dev = vcc->dev; | ||
2601 | struct idt77252_dev *card = dev->dev_data; | ||
2602 | struct vc_map *vc = vcc->dev_data; | ||
2603 | int error = 0; | ||
2604 | |||
2605 | down(&card->mutex); | ||
2606 | |||
2607 | if (qos->txtp.traffic_class != ATM_NONE) { | ||
2608 | if (!test_bit(VCF_TX, &vc->flags)) { | ||
2609 | error = idt77252_init_tx(card, vc, vcc, qos); | ||
2610 | if (error) | ||
2611 | goto out; | ||
2612 | } else { | ||
2613 | switch (qos->txtp.traffic_class) { | ||
2614 | case ATM_CBR: | ||
2615 | error = idt77252_init_cbr(card, vc, vcc, qos); | ||
2616 | if (error) | ||
2617 | goto out; | ||
2618 | break; | ||
2619 | |||
2620 | case ATM_UBR: | ||
2621 | error = idt77252_init_ubr(card, vc, vcc, qos); | ||
2622 | if (error) | ||
2623 | goto out; | ||
2624 | |||
2625 | if (!test_bit(VCF_IDLE, &vc->flags)) { | ||
2626 | writel(TCMDQ_LACR | (vc->lacr << 16) | | ||
2627 | vc->index, SAR_REG_TCMDQ); | ||
2628 | } | ||
2629 | break; | ||
2630 | |||
2631 | case ATM_VBR: | ||
2632 | case ATM_ABR: | ||
2633 | error = -EOPNOTSUPP; | ||
2634 | goto out; | ||
2635 | } | ||
2636 | } | ||
2637 | } | ||
2638 | |||
2639 | if ((qos->rxtp.traffic_class != ATM_NONE) && | ||
2640 | !test_bit(VCF_RX, &vc->flags)) { | ||
2641 | error = idt77252_init_rx(card, vc, vcc, qos); | ||
2642 | if (error) | ||
2643 | goto out; | ||
2644 | } | ||
2645 | |||
2646 | memcpy(&vcc->qos, qos, sizeof(struct atm_qos)); | ||
2647 | |||
2648 | set_bit(ATM_VF_HASQOS, &vcc->flags); | ||
2649 | |||
2650 | out: | ||
2651 | up(&card->mutex); | ||
2652 | return error; | ||
2653 | } | ||
2654 | |||
2655 | static int | ||
2656 | idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page) | ||
2657 | { | ||
2658 | struct idt77252_dev *card = dev->dev_data; | ||
2659 | int i, left; | ||
2660 | |||
2661 | left = (int) *pos; | ||
2662 | if (!left--) | ||
2663 | return sprintf(page, "IDT77252 Interrupts:\n"); | ||
2664 | if (!left--) | ||
2665 | return sprintf(page, "TSIF: %lu\n", card->irqstat[15]); | ||
2666 | if (!left--) | ||
2667 | return sprintf(page, "TXICP: %lu\n", card->irqstat[14]); | ||
2668 | if (!left--) | ||
2669 | return sprintf(page, "TSQF: %lu\n", card->irqstat[12]); | ||
2670 | if (!left--) | ||
2671 | return sprintf(page, "TMROF: %lu\n", card->irqstat[11]); | ||
2672 | if (!left--) | ||
2673 | return sprintf(page, "PHYI: %lu\n", card->irqstat[10]); | ||
2674 | if (!left--) | ||
2675 | return sprintf(page, "FBQ3A: %lu\n", card->irqstat[8]); | ||
2676 | if (!left--) | ||
2677 | return sprintf(page, "FBQ2A: %lu\n", card->irqstat[7]); | ||
2678 | if (!left--) | ||
2679 | return sprintf(page, "RSQF: %lu\n", card->irqstat[6]); | ||
2680 | if (!left--) | ||
2681 | return sprintf(page, "EPDU: %lu\n", card->irqstat[5]); | ||
2682 | if (!left--) | ||
2683 | return sprintf(page, "RAWCF: %lu\n", card->irqstat[4]); | ||
2684 | if (!left--) | ||
2685 | return sprintf(page, "FBQ1A: %lu\n", card->irqstat[3]); | ||
2686 | if (!left--) | ||
2687 | return sprintf(page, "FBQ0A: %lu\n", card->irqstat[2]); | ||
2688 | if (!left--) | ||
2689 | return sprintf(page, "RSQAF: %lu\n", card->irqstat[1]); | ||
2690 | if (!left--) | ||
2691 | return sprintf(page, "IDT77252 Transmit Connection Table:\n"); | ||
2692 | |||
2693 | for (i = 0; i < card->tct_size; i++) { | ||
2694 | unsigned long tct; | ||
2695 | struct atm_vcc *vcc; | ||
2696 | struct vc_map *vc; | ||
2697 | char *p; | ||
2698 | |||
2699 | vc = card->vcs[i]; | ||
2700 | if (!vc) | ||
2701 | continue; | ||
2702 | |||
2703 | vcc = NULL; | ||
2704 | if (vc->tx_vcc) | ||
2705 | vcc = vc->tx_vcc; | ||
2706 | if (!vcc) | ||
2707 | continue; | ||
2708 | if (left--) | ||
2709 | continue; | ||
2710 | |||
2711 | p = page; | ||
2712 | p += sprintf(p, " %4u: %u.%u: ", i, vcc->vpi, vcc->vci); | ||
2713 | tct = (unsigned long) (card->tct_base + i * SAR_SRAM_TCT_SIZE); | ||
2714 | |||
2715 | for (i = 0; i < 8; i++) | ||
2716 | p += sprintf(p, " %08x", read_sram(card, tct + i)); | ||
2717 | p += sprintf(p, "\n"); | ||
2718 | return p - page; | ||
2719 | } | ||
2720 | return 0; | ||
2721 | } | ||
2722 | |||
2723 | /*****************************************************************************/ | ||
2724 | /* */ | ||
2725 | /* Interrupt handler */ | ||
2726 | /* */ | ||
2727 | /*****************************************************************************/ | ||
2728 | |||
2729 | static void | ||
2730 | idt77252_collect_stat(struct idt77252_dev *card) | ||
2731 | { | ||
2732 | u32 cdc, vpec, icc; | ||
2733 | |||
2734 | cdc = readl(SAR_REG_CDC); | ||
2735 | vpec = readl(SAR_REG_VPEC); | ||
2736 | icc = readl(SAR_REG_ICC); | ||
2737 | |||
2738 | #ifdef NOTDEF | ||
2739 | printk("%s:", card->name); | ||
2740 | |||
2741 | if (cdc & 0x7f0000) { | ||
2742 | char *s = ""; | ||
2743 | |||
2744 | printk(" ["); | ||
2745 | if (cdc & (1 << 22)) { | ||
2746 | printk("%sRM ID", s); | ||
2747 | s = " | "; | ||
2748 | } | ||
2749 | if (cdc & (1 << 21)) { | ||
2750 | printk("%sCON TAB", s); | ||
2751 | s = " | "; | ||
2752 | } | ||
2753 | if (cdc & (1 << 20)) { | ||
2754 | printk("%sNO FB", s); | ||
2755 | s = " | "; | ||
2756 | } | ||
2757 | if (cdc & (1 << 19)) { | ||
2758 | printk("%sOAM CRC", s); | ||
2759 | s = " | "; | ||
2760 | } | ||
2761 | if (cdc & (1 << 18)) { | ||
2762 | printk("%sRM CRC", s); | ||
2763 | s = " | "; | ||
2764 | } | ||
2765 | if (cdc & (1 << 17)) { | ||
2766 | printk("%sRM FIFO", s); | ||
2767 | s = " | "; | ||
2768 | } | ||
2769 | if (cdc & (1 << 16)) { | ||
2770 | printk("%sRX FIFO", s); | ||
2771 | s = " | "; | ||
2772 | } | ||
2773 | printk("]"); | ||
2774 | } | ||
2775 | |||
2776 | printk(" CDC %04x, VPEC %04x, ICC: %04x\n", | ||
2777 | cdc & 0xffff, vpec & 0xffff, icc & 0xffff); | ||
2778 | #endif | ||
2779 | } | ||
2780 | |||
2781 | static irqreturn_t | ||
2782 | idt77252_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) | ||
2783 | { | ||
2784 | struct idt77252_dev *card = dev_id; | ||
2785 | u32 stat; | ||
2786 | |||
2787 | stat = readl(SAR_REG_STAT) & 0xffff; | ||
2788 | if (!stat) /* no interrupt for us */ | ||
2789 | return IRQ_NONE; | ||
2790 | |||
2791 | if (test_and_set_bit(IDT77252_BIT_INTERRUPT, &card->flags)) { | ||
2792 | printk("%s: Re-entering irq_handler()\n", card->name); | ||
2793 | goto out; | ||
2794 | } | ||
2795 | |||
2796 | writel(stat, SAR_REG_STAT); /* reset interrupt */ | ||
2797 | |||
2798 | if (stat & SAR_STAT_TSIF) { /* entry written to TSQ */ | ||
2799 | INTPRINTK("%s: TSIF\n", card->name); | ||
2800 | card->irqstat[15]++; | ||
2801 | idt77252_tx(card); | ||
2802 | } | ||
2803 | if (stat & SAR_STAT_TXICP) { /* Incomplete CS-PDU has */ | ||
2804 | INTPRINTK("%s: TXICP\n", card->name); | ||
2805 | card->irqstat[14]++; | ||
2806 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
2807 | idt77252_tx_dump(card); | ||
2808 | #endif | ||
2809 | } | ||
2810 | if (stat & SAR_STAT_TSQF) { /* TSQ 7/8 full */ | ||
2811 | INTPRINTK("%s: TSQF\n", card->name); | ||
2812 | card->irqstat[12]++; | ||
2813 | idt77252_tx(card); | ||
2814 | } | ||
2815 | if (stat & SAR_STAT_TMROF) { /* Timer overflow */ | ||
2816 | INTPRINTK("%s: TMROF\n", card->name); | ||
2817 | card->irqstat[11]++; | ||
2818 | idt77252_collect_stat(card); | ||
2819 | } | ||
2820 | |||
2821 | if (stat & SAR_STAT_EPDU) { /* Got complete CS-PDU */ | ||
2822 | INTPRINTK("%s: EPDU\n", card->name); | ||
2823 | card->irqstat[5]++; | ||
2824 | idt77252_rx(card); | ||
2825 | } | ||
2826 | if (stat & SAR_STAT_RSQAF) { /* RSQ is 7/8 full */ | ||
2827 | INTPRINTK("%s: RSQAF\n", card->name); | ||
2828 | card->irqstat[1]++; | ||
2829 | idt77252_rx(card); | ||
2830 | } | ||
2831 | if (stat & SAR_STAT_RSQF) { /* RSQ is full */ | ||
2832 | INTPRINTK("%s: RSQF\n", card->name); | ||
2833 | card->irqstat[6]++; | ||
2834 | idt77252_rx(card); | ||
2835 | } | ||
2836 | if (stat & SAR_STAT_RAWCF) { /* Raw cell received */ | ||
2837 | INTPRINTK("%s: RAWCF\n", card->name); | ||
2838 | card->irqstat[4]++; | ||
2839 | idt77252_rx_raw(card); | ||
2840 | } | ||
2841 | |||
2842 | if (stat & SAR_STAT_PHYI) { /* PHY device interrupt */ | ||
2843 | INTPRINTK("%s: PHYI", card->name); | ||
2844 | card->irqstat[10]++; | ||
2845 | if (card->atmdev->phy && card->atmdev->phy->interrupt) | ||
2846 | card->atmdev->phy->interrupt(card->atmdev); | ||
2847 | } | ||
2848 | |||
2849 | if (stat & (SAR_STAT_FBQ0A | SAR_STAT_FBQ1A | | ||
2850 | SAR_STAT_FBQ2A | SAR_STAT_FBQ3A)) { | ||
2851 | |||
2852 | writel(readl(SAR_REG_CFG) & ~(SAR_CFG_FBIE), SAR_REG_CFG); | ||
2853 | |||
2854 | INTPRINTK("%s: FBQA: %04x\n", card->name, stat); | ||
2855 | |||
2856 | if (stat & SAR_STAT_FBQ0A) | ||
2857 | card->irqstat[2]++; | ||
2858 | if (stat & SAR_STAT_FBQ1A) | ||
2859 | card->irqstat[3]++; | ||
2860 | if (stat & SAR_STAT_FBQ2A) | ||
2861 | card->irqstat[7]++; | ||
2862 | if (stat & SAR_STAT_FBQ3A) | ||
2863 | card->irqstat[8]++; | ||
2864 | |||
2865 | schedule_work(&card->tqueue); | ||
2866 | } | ||
2867 | |||
2868 | out: | ||
2869 | clear_bit(IDT77252_BIT_INTERRUPT, &card->flags); | ||
2870 | return IRQ_HANDLED; | ||
2871 | } | ||
2872 | |||
2873 | static void | ||
2874 | idt77252_softint(void *dev_id) | ||
2875 | { | ||
2876 | struct idt77252_dev *card = dev_id; | ||
2877 | u32 stat; | ||
2878 | int done; | ||
2879 | |||
2880 | for (done = 1; ; done = 1) { | ||
2881 | stat = readl(SAR_REG_STAT) >> 16; | ||
2882 | |||
2883 | if ((stat & 0x0f) < SAR_FBQ0_HIGH) { | ||
2884 | add_rx_skb(card, 0, SAR_FB_SIZE_0, 32); | ||
2885 | done = 0; | ||
2886 | } | ||
2887 | |||
2888 | stat >>= 4; | ||
2889 | if ((stat & 0x0f) < SAR_FBQ1_HIGH) { | ||
2890 | add_rx_skb(card, 1, SAR_FB_SIZE_1, 32); | ||
2891 | done = 0; | ||
2892 | } | ||
2893 | |||
2894 | stat >>= 4; | ||
2895 | if ((stat & 0x0f) < SAR_FBQ2_HIGH) { | ||
2896 | add_rx_skb(card, 2, SAR_FB_SIZE_2, 32); | ||
2897 | done = 0; | ||
2898 | } | ||
2899 | |||
2900 | stat >>= 4; | ||
2901 | if ((stat & 0x0f) < SAR_FBQ3_HIGH) { | ||
2902 | add_rx_skb(card, 3, SAR_FB_SIZE_3, 32); | ||
2903 | done = 0; | ||
2904 | } | ||
2905 | |||
2906 | if (done) | ||
2907 | break; | ||
2908 | } | ||
2909 | |||
2910 | writel(readl(SAR_REG_CFG) | SAR_CFG_FBIE, SAR_REG_CFG); | ||
2911 | } | ||
2912 | |||
2913 | |||
2914 | static int | ||
2915 | open_card_oam(struct idt77252_dev *card) | ||
2916 | { | ||
2917 | unsigned long flags; | ||
2918 | unsigned long addr; | ||
2919 | struct vc_map *vc; | ||
2920 | int vpi, vci; | ||
2921 | int index; | ||
2922 | u32 rcte; | ||
2923 | |||
2924 | for (vpi = 0; vpi < (1 << card->vpibits); vpi++) { | ||
2925 | for (vci = 3; vci < 5; vci++) { | ||
2926 | index = VPCI2VC(card, vpi, vci); | ||
2927 | |||
2928 | vc = kmalloc(sizeof(struct vc_map), GFP_KERNEL); | ||
2929 | if (!vc) { | ||
2930 | printk("%s: can't alloc vc\n", card->name); | ||
2931 | return -ENOMEM; | ||
2932 | } | ||
2933 | memset(vc, 0, sizeof(struct vc_map)); | ||
2934 | |||
2935 | vc->index = index; | ||
2936 | card->vcs[index] = vc; | ||
2937 | |||
2938 | flush_rx_pool(card, &vc->rcv.rx_pool); | ||
2939 | |||
2940 | rcte = SAR_RCTE_CONNECTOPEN | | ||
2941 | SAR_RCTE_RAWCELLINTEN | | ||
2942 | SAR_RCTE_RCQ | | ||
2943 | SAR_RCTE_FBP_1; | ||
2944 | |||
2945 | addr = card->rct_base + (vc->index << 2); | ||
2946 | write_sram(card, addr, rcte); | ||
2947 | |||
2948 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
2949 | writel(SAR_CMD_OPEN_CONNECTION | (addr << 2), | ||
2950 | SAR_REG_CMD); | ||
2951 | waitfor_idle(card); | ||
2952 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
2953 | } | ||
2954 | } | ||
2955 | |||
2956 | return 0; | ||
2957 | } | ||
2958 | |||
2959 | static void | ||
2960 | close_card_oam(struct idt77252_dev *card) | ||
2961 | { | ||
2962 | unsigned long flags; | ||
2963 | unsigned long addr; | ||
2964 | struct vc_map *vc; | ||
2965 | int vpi, vci; | ||
2966 | int index; | ||
2967 | |||
2968 | for (vpi = 0; vpi < (1 << card->vpibits); vpi++) { | ||
2969 | for (vci = 3; vci < 5; vci++) { | ||
2970 | index = VPCI2VC(card, vpi, vci); | ||
2971 | vc = card->vcs[index]; | ||
2972 | |||
2973 | addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE; | ||
2974 | |||
2975 | spin_lock_irqsave(&card->cmd_lock, flags); | ||
2976 | writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2), | ||
2977 | SAR_REG_CMD); | ||
2978 | waitfor_idle(card); | ||
2979 | spin_unlock_irqrestore(&card->cmd_lock, flags); | ||
2980 | |||
2981 | if (vc->rcv.rx_pool.count) { | ||
2982 | DPRINTK("%s: closing a VC " | ||
2983 | "with pending rx buffers.\n", | ||
2984 | card->name); | ||
2985 | |||
2986 | recycle_rx_pool_skb(card, &vc->rcv.rx_pool); | ||
2987 | } | ||
2988 | } | ||
2989 | } | ||
2990 | } | ||
2991 | |||
2992 | static int | ||
2993 | open_card_ubr0(struct idt77252_dev *card) | ||
2994 | { | ||
2995 | struct vc_map *vc; | ||
2996 | |||
2997 | vc = kmalloc(sizeof(struct vc_map), GFP_KERNEL); | ||
2998 | if (!vc) { | ||
2999 | printk("%s: can't alloc vc\n", card->name); | ||
3000 | return -ENOMEM; | ||
3001 | } | ||
3002 | memset(vc, 0, sizeof(struct vc_map)); | ||
3003 | card->vcs[0] = vc; | ||
3004 | vc->class = SCHED_UBR0; | ||
3005 | |||
3006 | vc->scq = alloc_scq(card, vc->class); | ||
3007 | if (!vc->scq) { | ||
3008 | printk("%s: can't get SCQ.\n", card->name); | ||
3009 | return -ENOMEM; | ||
3010 | } | ||
3011 | |||
3012 | card->scd2vc[0] = vc; | ||
3013 | vc->scd_index = 0; | ||
3014 | vc->scq->scd = card->scd_base; | ||
3015 | |||
3016 | fill_scd(card, vc->scq, vc->class); | ||
3017 | |||
3018 | write_sram(card, card->tct_base + 0, TCT_UBR | card->scd_base); | ||
3019 | write_sram(card, card->tct_base + 1, 0); | ||
3020 | write_sram(card, card->tct_base + 2, 0); | ||
3021 | write_sram(card, card->tct_base + 3, 0); | ||
3022 | write_sram(card, card->tct_base + 4, 0); | ||
3023 | write_sram(card, card->tct_base + 5, 0); | ||
3024 | write_sram(card, card->tct_base + 6, 0); | ||
3025 | write_sram(card, card->tct_base + 7, TCT_FLAG_UBR); | ||
3026 | |||
3027 | clear_bit(VCF_IDLE, &vc->flags); | ||
3028 | writel(TCMDQ_START | 0, SAR_REG_TCMDQ); | ||
3029 | return 0; | ||
3030 | } | ||
3031 | |||
3032 | static int | ||
3033 | idt77252_dev_open(struct idt77252_dev *card) | ||
3034 | { | ||
3035 | u32 conf; | ||
3036 | |||
3037 | if (!test_bit(IDT77252_BIT_INIT, &card->flags)) { | ||
3038 | printk("%s: SAR not yet initialized.\n", card->name); | ||
3039 | return -1; | ||
3040 | } | ||
3041 | |||
3042 | conf = SAR_CFG_RXPTH| /* enable receive path */ | ||
3043 | SAR_RX_DELAY | /* interrupt on complete PDU */ | ||
3044 | SAR_CFG_RAWIE | /* interrupt enable on raw cells */ | ||
3045 | SAR_CFG_RQFIE | /* interrupt on RSQ almost full */ | ||
3046 | SAR_CFG_TMOIE | /* interrupt on timer overflow */ | ||
3047 | SAR_CFG_FBIE | /* interrupt on low free buffers */ | ||
3048 | SAR_CFG_TXEN | /* transmit operation enable */ | ||
3049 | SAR_CFG_TXINT | /* interrupt on transmit status */ | ||
3050 | SAR_CFG_TXUIE | /* interrupt on transmit underrun */ | ||
3051 | SAR_CFG_TXSFI | /* interrupt on TSQ almost full */ | ||
3052 | SAR_CFG_PHYIE /* enable PHY interrupts */ | ||
3053 | ; | ||
3054 | |||
3055 | #ifdef CONFIG_ATM_IDT77252_RCV_ALL | ||
3056 | /* Test RAW cell receive. */ | ||
3057 | conf |= SAR_CFG_VPECA; | ||
3058 | #endif | ||
3059 | |||
3060 | writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG); | ||
3061 | |||
3062 | if (open_card_oam(card)) { | ||
3063 | printk("%s: Error initializing OAM.\n", card->name); | ||
3064 | return -1; | ||
3065 | } | ||
3066 | |||
3067 | if (open_card_ubr0(card)) { | ||
3068 | printk("%s: Error initializing UBR0.\n", card->name); | ||
3069 | return -1; | ||
3070 | } | ||
3071 | |||
3072 | IPRINTK("%s: opened IDT77252 ABR SAR.\n", card->name); | ||
3073 | return 0; | ||
3074 | } | ||
3075 | |||
3076 | void | ||
3077 | idt77252_dev_close(struct atm_dev *dev) | ||
3078 | { | ||
3079 | struct idt77252_dev *card = dev->dev_data; | ||
3080 | u32 conf; | ||
3081 | |||
3082 | close_card_oam(card); | ||
3083 | |||
3084 | conf = SAR_CFG_RXPTH | /* enable receive path */ | ||
3085 | SAR_RX_DELAY | /* interrupt on complete PDU */ | ||
3086 | SAR_CFG_RAWIE | /* interrupt enable on raw cells */ | ||
3087 | SAR_CFG_RQFIE | /* interrupt on RSQ almost full */ | ||
3088 | SAR_CFG_TMOIE | /* interrupt on timer overflow */ | ||
3089 | SAR_CFG_FBIE | /* interrupt on low free buffers */ | ||
3090 | SAR_CFG_TXEN | /* transmit operation enable */ | ||
3091 | SAR_CFG_TXINT | /* interrupt on transmit status */ | ||
3092 | SAR_CFG_TXUIE | /* interrupt on xmit underrun */ | ||
3093 | SAR_CFG_TXSFI /* interrupt on TSQ almost full */ | ||
3094 | ; | ||
3095 | |||
3096 | writel(readl(SAR_REG_CFG) & ~(conf), SAR_REG_CFG); | ||
3097 | |||
3098 | DIPRINTK("%s: closed IDT77252 ABR SAR.\n", card->name); | ||
3099 | } | ||
3100 | |||
3101 | |||
3102 | /*****************************************************************************/ | ||
3103 | /* */ | ||
3104 | /* Initialisation and Deinitialization of IDT77252 */ | ||
3105 | /* */ | ||
3106 | /*****************************************************************************/ | ||
3107 | |||
3108 | |||
3109 | static void | ||
3110 | deinit_card(struct idt77252_dev *card) | ||
3111 | { | ||
3112 | struct sk_buff *skb; | ||
3113 | int i, j; | ||
3114 | |||
3115 | if (!test_bit(IDT77252_BIT_INIT, &card->flags)) { | ||
3116 | printk("%s: SAR not yet initialized.\n", card->name); | ||
3117 | return; | ||
3118 | } | ||
3119 | DIPRINTK("idt77252: deinitialize card %u\n", card->index); | ||
3120 | |||
3121 | writel(0, SAR_REG_CFG); | ||
3122 | |||
3123 | if (card->atmdev) | ||
3124 | atm_dev_deregister(card->atmdev); | ||
3125 | |||
3126 | for (i = 0; i < 4; i++) { | ||
3127 | for (j = 0; j < FBQ_SIZE; j++) { | ||
3128 | skb = card->sbpool[i].skb[j]; | ||
3129 | if (skb) { | ||
3130 | pci_unmap_single(card->pcidev, | ||
3131 | IDT77252_PRV_PADDR(skb), | ||
3132 | skb->end - skb->data, | ||
3133 | PCI_DMA_FROMDEVICE); | ||
3134 | card->sbpool[i].skb[j] = NULL; | ||
3135 | dev_kfree_skb(skb); | ||
3136 | } | ||
3137 | } | ||
3138 | } | ||
3139 | |||
3140 | vfree(card->soft_tst); | ||
3141 | |||
3142 | vfree(card->scd2vc); | ||
3143 | |||
3144 | vfree(card->vcs); | ||
3145 | |||
3146 | if (card->raw_cell_hnd) { | ||
3147 | pci_free_consistent(card->pcidev, 2 * sizeof(u32), | ||
3148 | card->raw_cell_hnd, card->raw_cell_paddr); | ||
3149 | } | ||
3150 | |||
3151 | if (card->rsq.base) { | ||
3152 | DIPRINTK("%s: Release RSQ ...\n", card->name); | ||
3153 | deinit_rsq(card); | ||
3154 | } | ||
3155 | |||
3156 | if (card->tsq.base) { | ||
3157 | DIPRINTK("%s: Release TSQ ...\n", card->name); | ||
3158 | deinit_tsq(card); | ||
3159 | } | ||
3160 | |||
3161 | DIPRINTK("idt77252: Release IRQ.\n"); | ||
3162 | free_irq(card->pcidev->irq, card); | ||
3163 | |||
3164 | for (i = 0; i < 4; i++) { | ||
3165 | if (card->fbq[i]) | ||
3166 | iounmap(card->fbq[i]); | ||
3167 | } | ||
3168 | |||
3169 | if (card->membase) | ||
3170 | iounmap(card->membase); | ||
3171 | |||
3172 | clear_bit(IDT77252_BIT_INIT, &card->flags); | ||
3173 | DIPRINTK("%s: Card deinitialized.\n", card->name); | ||
3174 | } | ||
3175 | |||
3176 | |||
3177 | static int __devinit | ||
3178 | init_sram(struct idt77252_dev *card) | ||
3179 | { | ||
3180 | int i; | ||
3181 | |||
3182 | for (i = 0; i < card->sramsize; i += 4) | ||
3183 | write_sram(card, (i >> 2), 0); | ||
3184 | |||
3185 | /* set SRAM layout for THIS card */ | ||
3186 | if (card->sramsize == (512 * 1024)) { | ||
3187 | card->tct_base = SAR_SRAM_TCT_128_BASE; | ||
3188 | card->tct_size = (SAR_SRAM_TCT_128_TOP - card->tct_base + 1) | ||
3189 | / SAR_SRAM_TCT_SIZE; | ||
3190 | card->rct_base = SAR_SRAM_RCT_128_BASE; | ||
3191 | card->rct_size = (SAR_SRAM_RCT_128_TOP - card->rct_base + 1) | ||
3192 | / SAR_SRAM_RCT_SIZE; | ||
3193 | card->rt_base = SAR_SRAM_RT_128_BASE; | ||
3194 | card->scd_base = SAR_SRAM_SCD_128_BASE; | ||
3195 | card->scd_size = (SAR_SRAM_SCD_128_TOP - card->scd_base + 1) | ||
3196 | / SAR_SRAM_SCD_SIZE; | ||
3197 | card->tst[0] = SAR_SRAM_TST1_128_BASE; | ||
3198 | card->tst[1] = SAR_SRAM_TST2_128_BASE; | ||
3199 | card->tst_size = SAR_SRAM_TST1_128_TOP - card->tst[0] + 1; | ||
3200 | card->abrst_base = SAR_SRAM_ABRSTD_128_BASE; | ||
3201 | card->abrst_size = SAR_ABRSTD_SIZE_8K; | ||
3202 | card->fifo_base = SAR_SRAM_FIFO_128_BASE; | ||
3203 | card->fifo_size = SAR_RXFD_SIZE_32K; | ||
3204 | } else { | ||
3205 | card->tct_base = SAR_SRAM_TCT_32_BASE; | ||
3206 | card->tct_size = (SAR_SRAM_TCT_32_TOP - card->tct_base + 1) | ||
3207 | / SAR_SRAM_TCT_SIZE; | ||
3208 | card->rct_base = SAR_SRAM_RCT_32_BASE; | ||
3209 | card->rct_size = (SAR_SRAM_RCT_32_TOP - card->rct_base + 1) | ||
3210 | / SAR_SRAM_RCT_SIZE; | ||
3211 | card->rt_base = SAR_SRAM_RT_32_BASE; | ||
3212 | card->scd_base = SAR_SRAM_SCD_32_BASE; | ||
3213 | card->scd_size = (SAR_SRAM_SCD_32_TOP - card->scd_base + 1) | ||
3214 | / SAR_SRAM_SCD_SIZE; | ||
3215 | card->tst[0] = SAR_SRAM_TST1_32_BASE; | ||
3216 | card->tst[1] = SAR_SRAM_TST2_32_BASE; | ||
3217 | card->tst_size = (SAR_SRAM_TST1_32_TOP - card->tst[0] + 1); | ||
3218 | card->abrst_base = SAR_SRAM_ABRSTD_32_BASE; | ||
3219 | card->abrst_size = SAR_ABRSTD_SIZE_1K; | ||
3220 | card->fifo_base = SAR_SRAM_FIFO_32_BASE; | ||
3221 | card->fifo_size = SAR_RXFD_SIZE_4K; | ||
3222 | } | ||
3223 | |||
3224 | /* Initialize TCT */ | ||
3225 | for (i = 0; i < card->tct_size; i++) { | ||
3226 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 0, 0); | ||
3227 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 1, 0); | ||
3228 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 2, 0); | ||
3229 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 3, 0); | ||
3230 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 4, 0); | ||
3231 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 5, 0); | ||
3232 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 6, 0); | ||
3233 | write_sram(card, i * SAR_SRAM_TCT_SIZE + 7, 0); | ||
3234 | } | ||
3235 | |||
3236 | /* Initialize RCT */ | ||
3237 | for (i = 0; i < card->rct_size; i++) { | ||
3238 | write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE, | ||
3239 | (u32) SAR_RCTE_RAWCELLINTEN); | ||
3240 | write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 1, | ||
3241 | (u32) 0); | ||
3242 | write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 2, | ||
3243 | (u32) 0); | ||
3244 | write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 3, | ||
3245 | (u32) 0xffffffff); | ||
3246 | } | ||
3247 | |||
3248 | writel((SAR_FBQ0_LOW << 28) | 0x00000000 | 0x00000000 | | ||
3249 | (SAR_FB_SIZE_0 / 48), SAR_REG_FBQS0); | ||
3250 | writel((SAR_FBQ1_LOW << 28) | 0x00000000 | 0x00000000 | | ||
3251 | (SAR_FB_SIZE_1 / 48), SAR_REG_FBQS1); | ||
3252 | writel((SAR_FBQ2_LOW << 28) | 0x00000000 | 0x00000000 | | ||
3253 | (SAR_FB_SIZE_2 / 48), SAR_REG_FBQS2); | ||
3254 | writel((SAR_FBQ3_LOW << 28) | 0x00000000 | 0x00000000 | | ||
3255 | (SAR_FB_SIZE_3 / 48), SAR_REG_FBQS3); | ||
3256 | |||
3257 | /* Initialize rate table */ | ||
3258 | for (i = 0; i < 256; i++) { | ||
3259 | write_sram(card, card->rt_base + i, log_to_rate[i]); | ||
3260 | } | ||
3261 | |||
3262 | for (i = 0; i < 128; i++) { | ||
3263 | unsigned int tmp; | ||
3264 | |||
3265 | tmp = rate_to_log[(i << 2) + 0] << 0; | ||
3266 | tmp |= rate_to_log[(i << 2) + 1] << 8; | ||
3267 | tmp |= rate_to_log[(i << 2) + 2] << 16; | ||
3268 | tmp |= rate_to_log[(i << 2) + 3] << 24; | ||
3269 | write_sram(card, card->rt_base + 256 + i, tmp); | ||
3270 | } | ||
3271 | |||
3272 | #if 0 /* Fill RDF and AIR tables. */ | ||
3273 | for (i = 0; i < 128; i++) { | ||
3274 | unsigned int tmp; | ||
3275 | |||
3276 | tmp = RDF[0][(i << 1) + 0] << 16; | ||
3277 | tmp |= RDF[0][(i << 1) + 1] << 0; | ||
3278 | write_sram(card, card->rt_base + 512 + i, tmp); | ||
3279 | } | ||
3280 | |||
3281 | for (i = 0; i < 128; i++) { | ||
3282 | unsigned int tmp; | ||
3283 | |||
3284 | tmp = AIR[0][(i << 1) + 0] << 16; | ||
3285 | tmp |= AIR[0][(i << 1) + 1] << 0; | ||
3286 | write_sram(card, card->rt_base + 640 + i, tmp); | ||
3287 | } | ||
3288 | #endif | ||
3289 | |||
3290 | IPRINTK("%s: initialize rate table ...\n", card->name); | ||
3291 | writel(card->rt_base << 2, SAR_REG_RTBL); | ||
3292 | |||
3293 | /* Initialize TSTs */ | ||
3294 | IPRINTK("%s: initialize TST ...\n", card->name); | ||
3295 | card->tst_free = card->tst_size - 2; /* last two are jumps */ | ||
3296 | |||
3297 | for (i = card->tst[0]; i < card->tst[0] + card->tst_size - 2; i++) | ||
3298 | write_sram(card, i, TSTE_OPC_VAR); | ||
3299 | write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2)); | ||
3300 | idt77252_sram_write_errors = 1; | ||
3301 | write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2)); | ||
3302 | idt77252_sram_write_errors = 0; | ||
3303 | for (i = card->tst[1]; i < card->tst[1] + card->tst_size - 2; i++) | ||
3304 | write_sram(card, i, TSTE_OPC_VAR); | ||
3305 | write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2)); | ||
3306 | idt77252_sram_write_errors = 1; | ||
3307 | write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2)); | ||
3308 | idt77252_sram_write_errors = 0; | ||
3309 | |||
3310 | card->tst_index = 0; | ||
3311 | writel(card->tst[0] << 2, SAR_REG_TSTB); | ||
3312 | |||
3313 | /* Initialize ABRSTD and Receive FIFO */ | ||
3314 | IPRINTK("%s: initialize ABRSTD ...\n", card->name); | ||
3315 | writel(card->abrst_size | (card->abrst_base << 2), | ||
3316 | SAR_REG_ABRSTD); | ||
3317 | |||
3318 | IPRINTK("%s: initialize receive fifo ...\n", card->name); | ||
3319 | writel(card->fifo_size | (card->fifo_base << 2), | ||
3320 | SAR_REG_RXFD); | ||
3321 | |||
3322 | IPRINTK("%s: SRAM initialization complete.\n", card->name); | ||
3323 | return 0; | ||
3324 | } | ||
3325 | |||
3326 | static int __devinit | ||
3327 | init_card(struct atm_dev *dev) | ||
3328 | { | ||
3329 | struct idt77252_dev *card = dev->dev_data; | ||
3330 | struct pci_dev *pcidev = card->pcidev; | ||
3331 | unsigned long tmpl, modl; | ||
3332 | unsigned int linkrate, rsvdcr; | ||
3333 | unsigned int tst_entries; | ||
3334 | struct net_device *tmp; | ||
3335 | char tname[10]; | ||
3336 | |||
3337 | u32 size; | ||
3338 | u_char pci_byte; | ||
3339 | u32 conf; | ||
3340 | int i, k; | ||
3341 | |||
3342 | if (test_bit(IDT77252_BIT_INIT, &card->flags)) { | ||
3343 | printk("Error: SAR already initialized.\n"); | ||
3344 | return -1; | ||
3345 | } | ||
3346 | |||
3347 | /*****************************************************************/ | ||
3348 | /* P C I C O N F I G U R A T I O N */ | ||
3349 | /*****************************************************************/ | ||
3350 | |||
3351 | /* Set PCI Retry-Timeout and TRDY timeout */ | ||
3352 | IPRINTK("%s: Checking PCI retries.\n", card->name); | ||
3353 | if (pci_read_config_byte(pcidev, 0x40, &pci_byte) != 0) { | ||
3354 | printk("%s: can't read PCI retry timeout.\n", card->name); | ||
3355 | deinit_card(card); | ||
3356 | return -1; | ||
3357 | } | ||
3358 | if (pci_byte != 0) { | ||
3359 | IPRINTK("%s: PCI retry timeout: %d, set to 0.\n", | ||
3360 | card->name, pci_byte); | ||
3361 | if (pci_write_config_byte(pcidev, 0x40, 0) != 0) { | ||
3362 | printk("%s: can't set PCI retry timeout.\n", | ||
3363 | card->name); | ||
3364 | deinit_card(card); | ||
3365 | return -1; | ||
3366 | } | ||
3367 | } | ||
3368 | IPRINTK("%s: Checking PCI TRDY.\n", card->name); | ||
3369 | if (pci_read_config_byte(pcidev, 0x41, &pci_byte) != 0) { | ||
3370 | printk("%s: can't read PCI TRDY timeout.\n", card->name); | ||
3371 | deinit_card(card); | ||
3372 | return -1; | ||
3373 | } | ||
3374 | if (pci_byte != 0) { | ||
3375 | IPRINTK("%s: PCI TRDY timeout: %d, set to 0.\n", | ||
3376 | card->name, pci_byte); | ||
3377 | if (pci_write_config_byte(pcidev, 0x41, 0) != 0) { | ||
3378 | printk("%s: can't set PCI TRDY timeout.\n", card->name); | ||
3379 | deinit_card(card); | ||
3380 | return -1; | ||
3381 | } | ||
3382 | } | ||
3383 | /* Reset Timer register */ | ||
3384 | if (readl(SAR_REG_STAT) & SAR_STAT_TMROF) { | ||
3385 | printk("%s: resetting timer overflow.\n", card->name); | ||
3386 | writel(SAR_STAT_TMROF, SAR_REG_STAT); | ||
3387 | } | ||
3388 | IPRINTK("%s: Request IRQ ... ", card->name); | ||
3389 | if (request_irq(pcidev->irq, idt77252_interrupt, SA_INTERRUPT|SA_SHIRQ, | ||
3390 | card->name, card) != 0) { | ||
3391 | printk("%s: can't allocate IRQ.\n", card->name); | ||
3392 | deinit_card(card); | ||
3393 | return -1; | ||
3394 | } | ||
3395 | IPRINTK("got %d.\n", pcidev->irq); | ||
3396 | |||
3397 | /*****************************************************************/ | ||
3398 | /* C H E C K A N D I N I T S R A M */ | ||
3399 | /*****************************************************************/ | ||
3400 | |||
3401 | IPRINTK("%s: Initializing SRAM\n", card->name); | ||
3402 | |||
3403 | /* preset size of connecton table, so that init_sram() knows about it */ | ||
3404 | conf = SAR_CFG_TX_FIFO_SIZE_9 | /* Use maximum fifo size */ | ||
3405 | SAR_CFG_RXSTQ_SIZE_8k | /* Receive Status Queue is 8k */ | ||
3406 | SAR_CFG_IDLE_CLP | /* Set CLP on idle cells */ | ||
3407 | #ifndef CONFIG_ATM_IDT77252_SEND_IDLE | ||
3408 | SAR_CFG_NO_IDLE | /* Do not send idle cells */ | ||
3409 | #endif | ||
3410 | 0; | ||
3411 | |||
3412 | if (card->sramsize == (512 * 1024)) | ||
3413 | conf |= SAR_CFG_CNTBL_1k; | ||
3414 | else | ||
3415 | conf |= SAR_CFG_CNTBL_512; | ||
3416 | |||
3417 | switch (vpibits) { | ||
3418 | case 0: | ||
3419 | conf |= SAR_CFG_VPVCS_0; | ||
3420 | break; | ||
3421 | default: | ||
3422 | case 1: | ||
3423 | conf |= SAR_CFG_VPVCS_1; | ||
3424 | break; | ||
3425 | case 2: | ||
3426 | conf |= SAR_CFG_VPVCS_2; | ||
3427 | break; | ||
3428 | case 8: | ||
3429 | conf |= SAR_CFG_VPVCS_8; | ||
3430 | break; | ||
3431 | } | ||
3432 | |||
3433 | writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG); | ||
3434 | |||
3435 | if (init_sram(card) < 0) | ||
3436 | return -1; | ||
3437 | |||
3438 | /********************************************************************/ | ||
3439 | /* A L L O C R A M A N D S E T V A R I O U S T H I N G S */ | ||
3440 | /********************************************************************/ | ||
3441 | /* Initialize TSQ */ | ||
3442 | if (0 != init_tsq(card)) { | ||
3443 | deinit_card(card); | ||
3444 | return -1; | ||
3445 | } | ||
3446 | /* Initialize RSQ */ | ||
3447 | if (0 != init_rsq(card)) { | ||
3448 | deinit_card(card); | ||
3449 | return -1; | ||
3450 | } | ||
3451 | |||
3452 | card->vpibits = vpibits; | ||
3453 | if (card->sramsize == (512 * 1024)) { | ||
3454 | card->vcibits = 10 - card->vpibits; | ||
3455 | } else { | ||
3456 | card->vcibits = 9 - card->vpibits; | ||
3457 | } | ||
3458 | |||
3459 | card->vcimask = 0; | ||
3460 | for (k = 0, i = 1; k < card->vcibits; k++) { | ||
3461 | card->vcimask |= i; | ||
3462 | i <<= 1; | ||
3463 | } | ||
3464 | |||
3465 | IPRINTK("%s: Setting VPI/VCI mask to zero.\n", card->name); | ||
3466 | writel(0, SAR_REG_VPM); | ||
3467 | |||
3468 | /* Little Endian Order */ | ||
3469 | writel(0, SAR_REG_GP); | ||
3470 | |||
3471 | /* Initialize RAW Cell Handle Register */ | ||
3472 | card->raw_cell_hnd = pci_alloc_consistent(card->pcidev, 2 * sizeof(u32), | ||
3473 | &card->raw_cell_paddr); | ||
3474 | if (!card->raw_cell_hnd) { | ||
3475 | printk("%s: memory allocation failure.\n", card->name); | ||
3476 | deinit_card(card); | ||
3477 | return -1; | ||
3478 | } | ||
3479 | memset(card->raw_cell_hnd, 0, 2 * sizeof(u32)); | ||
3480 | writel(card->raw_cell_paddr, SAR_REG_RAWHND); | ||
3481 | IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name, | ||
3482 | card->raw_cell_hnd); | ||
3483 | |||
3484 | size = sizeof(struct vc_map *) * card->tct_size; | ||
3485 | IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size); | ||
3486 | if (NULL == (card->vcs = vmalloc(size))) { | ||
3487 | printk("%s: memory allocation failure.\n", card->name); | ||
3488 | deinit_card(card); | ||
3489 | return -1; | ||
3490 | } | ||
3491 | memset(card->vcs, 0, size); | ||
3492 | |||
3493 | size = sizeof(struct vc_map *) * card->scd_size; | ||
3494 | IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n", | ||
3495 | card->name, size); | ||
3496 | if (NULL == (card->scd2vc = vmalloc(size))) { | ||
3497 | printk("%s: memory allocation failure.\n", card->name); | ||
3498 | deinit_card(card); | ||
3499 | return -1; | ||
3500 | } | ||
3501 | memset(card->scd2vc, 0, size); | ||
3502 | |||
3503 | size = sizeof(struct tst_info) * (card->tst_size - 2); | ||
3504 | IPRINTK("%s: allocate %d byte for TST to VC mapping.\n", | ||
3505 | card->name, size); | ||
3506 | if (NULL == (card->soft_tst = vmalloc(size))) { | ||
3507 | printk("%s: memory allocation failure.\n", card->name); | ||
3508 | deinit_card(card); | ||
3509 | return -1; | ||
3510 | } | ||
3511 | for (i = 0; i < card->tst_size - 2; i++) { | ||
3512 | card->soft_tst[i].tste = TSTE_OPC_VAR; | ||
3513 | card->soft_tst[i].vc = NULL; | ||
3514 | } | ||
3515 | |||
3516 | if (dev->phy == NULL) { | ||
3517 | printk("%s: No LT device defined.\n", card->name); | ||
3518 | deinit_card(card); | ||
3519 | return -1; | ||
3520 | } | ||
3521 | if (dev->phy->ioctl == NULL) { | ||
3522 | printk("%s: LT had no IOCTL funtion defined.\n", card->name); | ||
3523 | deinit_card(card); | ||
3524 | return -1; | ||
3525 | } | ||
3526 | |||
3527 | #ifdef CONFIG_ATM_IDT77252_USE_SUNI | ||
3528 | /* | ||
3529 | * this is a jhs hack to get around special functionality in the | ||
3530 | * phy driver for the atecom hardware; the functionality doesn't | ||
3531 | * exist in the linux atm suni driver | ||
3532 | * | ||
3533 | * it isn't the right way to do things, but as the guy from NIST | ||
3534 | * said, talking about their measurement of the fine structure | ||
3535 | * constant, "it's good enough for government work." | ||
3536 | */ | ||
3537 | linkrate = 149760000; | ||
3538 | #endif | ||
3539 | |||
3540 | card->link_pcr = (linkrate / 8 / 53); | ||
3541 | printk("%s: Linkrate on ATM line : %u bit/s, %u cell/s.\n", | ||
3542 | card->name, linkrate, card->link_pcr); | ||
3543 | |||
3544 | #ifdef CONFIG_ATM_IDT77252_SEND_IDLE | ||
3545 | card->utopia_pcr = card->link_pcr; | ||
3546 | #else | ||
3547 | card->utopia_pcr = (160000000 / 8 / 54); | ||
3548 | #endif | ||
3549 | |||
3550 | rsvdcr = 0; | ||
3551 | if (card->utopia_pcr > card->link_pcr) | ||
3552 | rsvdcr = card->utopia_pcr - card->link_pcr; | ||
3553 | |||
3554 | tmpl = (unsigned long) rsvdcr * ((unsigned long) card->tst_size - 2); | ||
3555 | modl = tmpl % (unsigned long)card->utopia_pcr; | ||
3556 | tst_entries = (int) (tmpl / (unsigned long)card->utopia_pcr); | ||
3557 | if (modl) | ||
3558 | tst_entries++; | ||
3559 | card->tst_free -= tst_entries; | ||
3560 | fill_tst(card, NULL, tst_entries, TSTE_OPC_NULL); | ||
3561 | |||
3562 | #ifdef HAVE_EEPROM | ||
3563 | idt77252_eeprom_init(card); | ||
3564 | printk("%s: EEPROM: %02x:", card->name, | ||
3565 | idt77252_eeprom_read_status(card)); | ||
3566 | |||
3567 | for (i = 0; i < 0x80; i++) { | ||
3568 | printk(" %02x", | ||
3569 | idt77252_eeprom_read_byte(card, i) | ||
3570 | ); | ||
3571 | } | ||
3572 | printk("\n"); | ||
3573 | #endif /* HAVE_EEPROM */ | ||
3574 | |||
3575 | /* | ||
3576 | * XXX: <hack> | ||
3577 | */ | ||
3578 | sprintf(tname, "eth%d", card->index); | ||
3579 | tmp = dev_get_by_name(tname); /* jhs: was "tmp = dev_get(tname);" */ | ||
3580 | if (tmp) { | ||
3581 | memcpy(card->atmdev->esi, tmp->dev_addr, 6); | ||
3582 | |||
3583 | printk("%s: ESI %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
3584 | card->name, card->atmdev->esi[0], card->atmdev->esi[1], | ||
3585 | card->atmdev->esi[2], card->atmdev->esi[3], | ||
3586 | card->atmdev->esi[4], card->atmdev->esi[5]); | ||
3587 | } | ||
3588 | /* | ||
3589 | * XXX: </hack> | ||
3590 | */ | ||
3591 | |||
3592 | /* Set Maximum Deficit Count for now. */ | ||
3593 | writel(0xffff, SAR_REG_MDFCT); | ||
3594 | |||
3595 | set_bit(IDT77252_BIT_INIT, &card->flags); | ||
3596 | |||
3597 | XPRINTK("%s: IDT77252 ABR SAR initialization complete.\n", card->name); | ||
3598 | return 0; | ||
3599 | } | ||
3600 | |||
3601 | |||
3602 | /*****************************************************************************/ | ||
3603 | /* */ | ||
3604 | /* Probing of IDT77252 ABR SAR */ | ||
3605 | /* */ | ||
3606 | /*****************************************************************************/ | ||
3607 | |||
3608 | |||
3609 | static int __devinit | ||
3610 | idt77252_preset(struct idt77252_dev *card) | ||
3611 | { | ||
3612 | u16 pci_command; | ||
3613 | |||
3614 | /*****************************************************************/ | ||
3615 | /* P C I C O N F I G U R A T I O N */ | ||
3616 | /*****************************************************************/ | ||
3617 | |||
3618 | XPRINTK("%s: Enable PCI master and memory access for SAR.\n", | ||
3619 | card->name); | ||
3620 | if (pci_read_config_word(card->pcidev, PCI_COMMAND, &pci_command)) { | ||
3621 | printk("%s: can't read PCI_COMMAND.\n", card->name); | ||
3622 | deinit_card(card); | ||
3623 | return -1; | ||
3624 | } | ||
3625 | if (!(pci_command & PCI_COMMAND_IO)) { | ||
3626 | printk("%s: PCI_COMMAND: %04x (???)\n", | ||
3627 | card->name, pci_command); | ||
3628 | deinit_card(card); | ||
3629 | return (-1); | ||
3630 | } | ||
3631 | pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | ||
3632 | if (pci_write_config_word(card->pcidev, PCI_COMMAND, pci_command)) { | ||
3633 | printk("%s: can't write PCI_COMMAND.\n", card->name); | ||
3634 | deinit_card(card); | ||
3635 | return -1; | ||
3636 | } | ||
3637 | /*****************************************************************/ | ||
3638 | /* G E N E R I C R E S E T */ | ||
3639 | /*****************************************************************/ | ||
3640 | |||
3641 | /* Software reset */ | ||
3642 | writel(SAR_CFG_SWRST, SAR_REG_CFG); | ||
3643 | mdelay(1); | ||
3644 | writel(0, SAR_REG_CFG); | ||
3645 | |||
3646 | IPRINTK("%s: Software resetted.\n", card->name); | ||
3647 | return 0; | ||
3648 | } | ||
3649 | |||
3650 | |||
3651 | static unsigned long __devinit | ||
3652 | probe_sram(struct idt77252_dev *card) | ||
3653 | { | ||
3654 | u32 data, addr; | ||
3655 | |||
3656 | writel(0, SAR_REG_DR0); | ||
3657 | writel(SAR_CMD_WRITE_SRAM | (0 << 2), SAR_REG_CMD); | ||
3658 | |||
3659 | for (addr = 0x4000; addr < 0x80000; addr += 0x4000) { | ||
3660 | writel(0xdeadbeef, SAR_REG_DR0); | ||
3661 | writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD); | ||
3662 | |||
3663 | writel(SAR_CMD_READ_SRAM | (0 << 2), SAR_REG_CMD); | ||
3664 | data = readl(SAR_REG_DR0); | ||
3665 | |||
3666 | if (data != 0) | ||
3667 | break; | ||
3668 | } | ||
3669 | |||
3670 | return addr * sizeof(u32); | ||
3671 | } | ||
3672 | |||
3673 | static int __devinit | ||
3674 | idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) | ||
3675 | { | ||
3676 | static struct idt77252_dev **last = &idt77252_chain; | ||
3677 | static int index = 0; | ||
3678 | |||
3679 | unsigned long membase, srambase; | ||
3680 | struct idt77252_dev *card; | ||
3681 | struct atm_dev *dev; | ||
3682 | ushort revision = 0; | ||
3683 | int i, err; | ||
3684 | |||
3685 | |||
3686 | if ((err = pci_enable_device(pcidev))) { | ||
3687 | printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev)); | ||
3688 | return err; | ||
3689 | } | ||
3690 | |||
3691 | if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) { | ||
3692 | printk("idt77252-%d: can't read PCI_REVISION_ID\n", index); | ||
3693 | err = -ENODEV; | ||
3694 | goto err_out_disable_pdev; | ||
3695 | } | ||
3696 | |||
3697 | card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL); | ||
3698 | if (!card) { | ||
3699 | printk("idt77252-%d: can't allocate private data\n", index); | ||
3700 | err = -ENOMEM; | ||
3701 | goto err_out_disable_pdev; | ||
3702 | } | ||
3703 | memset(card, 0, sizeof(struct idt77252_dev)); | ||
3704 | |||
3705 | card->revision = revision; | ||
3706 | card->index = index; | ||
3707 | card->pcidev = pcidev; | ||
3708 | sprintf(card->name, "idt77252-%d", card->index); | ||
3709 | |||
3710 | INIT_WORK(&card->tqueue, idt77252_softint, (void *)card); | ||
3711 | |||
3712 | membase = pci_resource_start(pcidev, 1); | ||
3713 | srambase = pci_resource_start(pcidev, 2); | ||
3714 | |||
3715 | init_MUTEX(&card->mutex); | ||
3716 | spin_lock_init(&card->cmd_lock); | ||
3717 | spin_lock_init(&card->tst_lock); | ||
3718 | |||
3719 | init_timer(&card->tst_timer); | ||
3720 | card->tst_timer.data = (unsigned long)card; | ||
3721 | card->tst_timer.function = tst_timer; | ||
3722 | |||
3723 | /* Do the I/O remapping... */ | ||
3724 | card->membase = ioremap(membase, 1024); | ||
3725 | if (!card->membase) { | ||
3726 | printk("%s: can't ioremap() membase\n", card->name); | ||
3727 | err = -EIO; | ||
3728 | goto err_out_free_card; | ||
3729 | } | ||
3730 | |||
3731 | if (idt77252_preset(card)) { | ||
3732 | printk("%s: preset failed\n", card->name); | ||
3733 | err = -EIO; | ||
3734 | goto err_out_iounmap; | ||
3735 | } | ||
3736 | |||
3737 | dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL); | ||
3738 | if (!dev) { | ||
3739 | printk("%s: can't register atm device\n", card->name); | ||
3740 | err = -EIO; | ||
3741 | goto err_out_iounmap; | ||
3742 | } | ||
3743 | dev->dev_data = card; | ||
3744 | card->atmdev = dev; | ||
3745 | |||
3746 | #ifdef CONFIG_ATM_IDT77252_USE_SUNI | ||
3747 | suni_init(dev); | ||
3748 | if (!dev->phy) { | ||
3749 | printk("%s: can't init SUNI\n", card->name); | ||
3750 | err = -EIO; | ||
3751 | goto err_out_deinit_card; | ||
3752 | } | ||
3753 | #endif /* CONFIG_ATM_IDT77252_USE_SUNI */ | ||
3754 | |||
3755 | card->sramsize = probe_sram(card); | ||
3756 | |||
3757 | for (i = 0; i < 4; i++) { | ||
3758 | card->fbq[i] = ioremap(srambase | 0x200000 | (i << 18), 4); | ||
3759 | if (!card->fbq[i]) { | ||
3760 | printk("%s: can't ioremap() FBQ%d\n", card->name, i); | ||
3761 | err = -EIO; | ||
3762 | goto err_out_deinit_card; | ||
3763 | } | ||
3764 | } | ||
3765 | |||
3766 | printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n", | ||
3767 | card->name, ((revision > 1) && (revision < 25)) ? | ||
3768 | 'A' + revision - 1 : '?', membase, srambase, | ||
3769 | card->sramsize / 1024); | ||
3770 | |||
3771 | if (init_card(dev)) { | ||
3772 | printk("%s: init_card failed\n", card->name); | ||
3773 | err = -EIO; | ||
3774 | goto err_out_deinit_card; | ||
3775 | } | ||
3776 | |||
3777 | dev->ci_range.vpi_bits = card->vpibits; | ||
3778 | dev->ci_range.vci_bits = card->vcibits; | ||
3779 | dev->link_rate = card->link_pcr; | ||
3780 | |||
3781 | if (dev->phy->start) | ||
3782 | dev->phy->start(dev); | ||
3783 | |||
3784 | if (idt77252_dev_open(card)) { | ||
3785 | printk("%s: dev_open failed\n", card->name); | ||
3786 | err = -EIO; | ||
3787 | goto err_out_stop; | ||
3788 | } | ||
3789 | |||
3790 | *last = card; | ||
3791 | last = &card->next; | ||
3792 | index++; | ||
3793 | |||
3794 | return 0; | ||
3795 | |||
3796 | err_out_stop: | ||
3797 | if (dev->phy->stop) | ||
3798 | dev->phy->stop(dev); | ||
3799 | |||
3800 | err_out_deinit_card: | ||
3801 | deinit_card(card); | ||
3802 | |||
3803 | err_out_iounmap: | ||
3804 | iounmap(card->membase); | ||
3805 | |||
3806 | err_out_free_card: | ||
3807 | kfree(card); | ||
3808 | |||
3809 | err_out_disable_pdev: | ||
3810 | pci_disable_device(pcidev); | ||
3811 | return err; | ||
3812 | } | ||
3813 | |||
3814 | static struct pci_device_id idt77252_pci_tbl[] = | ||
3815 | { | ||
3816 | { PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77252, | ||
3817 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
3818 | { 0, } | ||
3819 | }; | ||
3820 | |||
3821 | MODULE_DEVICE_TABLE(pci, idt77252_pci_tbl); | ||
3822 | |||
3823 | static struct pci_driver idt77252_driver = { | ||
3824 | .name = "idt77252", | ||
3825 | .id_table = idt77252_pci_tbl, | ||
3826 | .probe = idt77252_init_one, | ||
3827 | }; | ||
3828 | |||
3829 | static int __init idt77252_init(void) | ||
3830 | { | ||
3831 | struct sk_buff *skb; | ||
3832 | |||
3833 | printk("%s: at %p\n", __FUNCTION__, idt77252_init); | ||
3834 | |||
3835 | if (sizeof(skb->cb) < sizeof(struct atm_skb_data) + | ||
3836 | sizeof(struct idt77252_skb_prv)) { | ||
3837 | printk(KERN_ERR "%s: skb->cb is too small (%lu < %lu)\n", | ||
3838 | __FUNCTION__, (unsigned long) sizeof(skb->cb), | ||
3839 | (unsigned long) sizeof(struct atm_skb_data) + | ||
3840 | sizeof(struct idt77252_skb_prv)); | ||
3841 | return -EIO; | ||
3842 | } | ||
3843 | |||
3844 | return pci_register_driver(&idt77252_driver); | ||
3845 | } | ||
3846 | |||
3847 | static void __exit idt77252_exit(void) | ||
3848 | { | ||
3849 | struct idt77252_dev *card; | ||
3850 | struct atm_dev *dev; | ||
3851 | |||
3852 | pci_unregister_driver(&idt77252_driver); | ||
3853 | |||
3854 | while (idt77252_chain) { | ||
3855 | card = idt77252_chain; | ||
3856 | dev = card->atmdev; | ||
3857 | idt77252_chain = card->next; | ||
3858 | |||
3859 | if (dev->phy->stop) | ||
3860 | dev->phy->stop(dev); | ||
3861 | deinit_card(card); | ||
3862 | pci_disable_device(card->pcidev); | ||
3863 | kfree(card); | ||
3864 | } | ||
3865 | |||
3866 | DIPRINTK("idt77252: finished cleanup-module().\n"); | ||
3867 | } | ||
3868 | |||
3869 | module_init(idt77252_init); | ||
3870 | module_exit(idt77252_exit); | ||
3871 | |||
3872 | MODULE_LICENSE("GPL"); | ||
3873 | |||
3874 | module_param(vpibits, uint, 0); | ||
3875 | MODULE_PARM_DESC(vpibits, "number of VPI bits supported (0, 1, or 2)"); | ||
3876 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
3877 | module_param(debug, ulong, 0644); | ||
3878 | MODULE_PARM_DESC(debug, "debug bitmap, see drivers/atm/idt77252.h"); | ||
3879 | #endif | ||
3880 | |||
3881 | MODULE_AUTHOR("Eddie C. Dost <ecd@atecom.com>"); | ||
3882 | MODULE_DESCRIPTION("IDT77252 ABR SAR Driver"); | ||
diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h new file mode 100644 index 000000000000..544b39738291 --- /dev/null +++ b/drivers/atm/idt77252.h | |||
@@ -0,0 +1,819 @@ | |||
1 | /******************************************************************* | ||
2 | * ident "$Id: idt77252.h,v 1.2 2001/11/11 08:13:54 ecd Exp $" | ||
3 | * | ||
4 | * $Author: ecd $ | ||
5 | * $Date: 2001/11/11 08:13:54 $ | ||
6 | * | ||
7 | * Copyright (c) 2000 ATecoM GmbH | ||
8 | * | ||
9 | * The author may be reached at ecd@atecom.com. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
19 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License along | ||
28 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | * | ||
31 | *******************************************************************/ | ||
32 | |||
33 | #ifndef _IDT77252_H | ||
34 | #define _IDT77252_H 1 | ||
35 | |||
36 | |||
37 | #include <linux/ptrace.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/workqueue.h> | ||
40 | |||
41 | |||
42 | /*****************************************************************************/ | ||
43 | /* */ | ||
44 | /* Makros */ | ||
45 | /* */ | ||
46 | /*****************************************************************************/ | ||
47 | #define VPCI2VC(card, vpi, vci) \ | ||
48 | (((vpi) << card->vcibits) | ((vci) & card->vcimask)) | ||
49 | |||
50 | /*****************************************************************************/ | ||
51 | /* */ | ||
52 | /* DEBUGGING definitions */ | ||
53 | /* */ | ||
54 | /*****************************************************************************/ | ||
55 | |||
56 | #define DBG_RAW_CELL 0x00000400 | ||
57 | #define DBG_TINY 0x00000200 | ||
58 | #define DBG_GENERAL 0x00000100 | ||
59 | #define DBG_XGENERAL 0x00000080 | ||
60 | #define DBG_INIT 0x00000040 | ||
61 | #define DBG_DEINIT 0x00000020 | ||
62 | #define DBG_INTERRUPT 0x00000010 | ||
63 | #define DBG_OPEN_CONN 0x00000008 | ||
64 | #define DBG_CLOSE_CONN 0x00000004 | ||
65 | #define DBG_RX_DATA 0x00000002 | ||
66 | #define DBG_TX_DATA 0x00000001 | ||
67 | |||
68 | #ifdef CONFIG_ATM_IDT77252_DEBUG | ||
69 | |||
70 | #define CPRINTK(args...) do { if (debug & DBG_CLOSE_CONN) printk(args); } while(0) | ||
71 | #define OPRINTK(args...) do { if (debug & DBG_OPEN_CONN) printk(args); } while(0) | ||
72 | #define IPRINTK(args...) do { if (debug & DBG_INIT) printk(args); } while(0) | ||
73 | #define INTPRINTK(args...) do { if (debug & DBG_INTERRUPT) printk(args); } while(0) | ||
74 | #define DIPRINTK(args...) do { if (debug & DBG_DEINIT) printk(args); } while(0) | ||
75 | #define TXPRINTK(args...) do { if (debug & DBG_TX_DATA) printk(args); } while(0) | ||
76 | #define RXPRINTK(args...) do { if (debug & DBG_RX_DATA) printk(args); } while(0) | ||
77 | #define XPRINTK(args...) do { if (debug & DBG_XGENERAL) printk(args); } while(0) | ||
78 | #define DPRINTK(args...) do { if (debug & DBG_GENERAL) printk(args); } while(0) | ||
79 | #define NPRINTK(args...) do { if (debug & DBG_TINY) printk(args); } while(0) | ||
80 | #define RPRINTK(args...) do { if (debug & DBG_RAW_CELL) printk(args); } while(0) | ||
81 | |||
82 | #else | ||
83 | |||
84 | #define CPRINTK(args...) do { } while(0) | ||
85 | #define OPRINTK(args...) do { } while(0) | ||
86 | #define IPRINTK(args...) do { } while(0) | ||
87 | #define INTPRINTK(args...) do { } while(0) | ||
88 | #define DIPRINTK(args...) do { } while(0) | ||
89 | #define TXPRINTK(args...) do { } while(0) | ||
90 | #define RXPRINTK(args...) do { } while(0) | ||
91 | #define XPRINTK(args...) do { } while(0) | ||
92 | #define DPRINTK(args...) do { } while(0) | ||
93 | #define NPRINTK(args...) do { } while(0) | ||
94 | #define RPRINTK(args...) do { } while(0) | ||
95 | |||
96 | #endif | ||
97 | |||
98 | #define SCHED_UBR0 0 | ||
99 | #define SCHED_UBR 1 | ||
100 | #define SCHED_VBR 2 | ||
101 | #define SCHED_ABR 3 | ||
102 | #define SCHED_CBR 4 | ||
103 | |||
104 | #define SCQFULL_TIMEOUT HZ | ||
105 | |||
106 | /*****************************************************************************/ | ||
107 | /* */ | ||
108 | /* Free Buffer Queue Layout */ | ||
109 | /* */ | ||
110 | /*****************************************************************************/ | ||
111 | #define SAR_FB_SIZE_0 (2048 - 256) | ||
112 | #define SAR_FB_SIZE_1 (4096 - 256) | ||
113 | #define SAR_FB_SIZE_2 (8192 - 256) | ||
114 | #define SAR_FB_SIZE_3 (16384 - 256) | ||
115 | |||
116 | #define SAR_FBQ0_LOW 4 | ||
117 | #define SAR_FBQ0_HIGH 8 | ||
118 | #define SAR_FBQ1_LOW 2 | ||
119 | #define SAR_FBQ1_HIGH 4 | ||
120 | #define SAR_FBQ2_LOW 1 | ||
121 | #define SAR_FBQ2_HIGH 2 | ||
122 | #define SAR_FBQ3_LOW 1 | ||
123 | #define SAR_FBQ3_HIGH 2 | ||
124 | |||
125 | #if 0 | ||
126 | #define SAR_TST_RESERVED 44 /* Num TST reserved for UBR/ABR/VBR */ | ||
127 | #else | ||
128 | #define SAR_TST_RESERVED 0 /* Num TST reserved for UBR/ABR/VBR */ | ||
129 | #endif | ||
130 | |||
131 | #define TCT_CBR 0x00000000 | ||
132 | #define TCT_UBR 0x00000000 | ||
133 | #define TCT_VBR 0x40000000 | ||
134 | #define TCT_ABR 0x80000000 | ||
135 | #define TCT_TYPE 0xc0000000 | ||
136 | |||
137 | #define TCT_RR 0x20000000 | ||
138 | #define TCT_LMCR 0x08000000 | ||
139 | #define TCT_SCD_MASK 0x0007ffff | ||
140 | |||
141 | #define TCT_TSIF 0x00004000 | ||
142 | #define TCT_HALT 0x80000000 | ||
143 | #define TCT_IDLE 0x40000000 | ||
144 | #define TCT_FLAG_UBR 0x80000000 | ||
145 | |||
146 | /*****************************************************************************/ | ||
147 | /* */ | ||
148 | /* Structure describing an IDT77252 */ | ||
149 | /* */ | ||
150 | /*****************************************************************************/ | ||
151 | |||
152 | struct scqe | ||
153 | { | ||
154 | u32 word_1; | ||
155 | u32 word_2; | ||
156 | u32 word_3; | ||
157 | u32 word_4; | ||
158 | }; | ||
159 | |||
160 | #define SCQ_ENTRIES 64 | ||
161 | #define SCQ_SIZE (SCQ_ENTRIES * sizeof(struct scqe)) | ||
162 | #define SCQ_MASK (SCQ_SIZE - 1) | ||
163 | |||
164 | struct scq_info | ||
165 | { | ||
166 | struct scqe *base; | ||
167 | struct scqe *next; | ||
168 | struct scqe *last; | ||
169 | dma_addr_t paddr; | ||
170 | spinlock_t lock; | ||
171 | atomic_t used; | ||
172 | unsigned long trans_start; | ||
173 | unsigned long scd; | ||
174 | spinlock_t skblock; | ||
175 | struct sk_buff_head transmit; | ||
176 | struct sk_buff_head pending; | ||
177 | }; | ||
178 | |||
179 | struct rx_pool { | ||
180 | struct sk_buff *first; | ||
181 | struct sk_buff **last; | ||
182 | unsigned int len; | ||
183 | unsigned int count; | ||
184 | }; | ||
185 | |||
186 | struct aal1 { | ||
187 | unsigned int total; | ||
188 | unsigned int count; | ||
189 | struct sk_buff *data; | ||
190 | unsigned char sequence; | ||
191 | }; | ||
192 | |||
193 | struct rate_estimator { | ||
194 | struct timer_list timer; | ||
195 | unsigned int interval; | ||
196 | unsigned int ewma_log; | ||
197 | u64 cells; | ||
198 | u64 last_cells; | ||
199 | long avcps; | ||
200 | u32 cps; | ||
201 | u32 maxcps; | ||
202 | }; | ||
203 | |||
204 | struct vc_map { | ||
205 | unsigned int index; | ||
206 | unsigned long flags; | ||
207 | #define VCF_TX 0 | ||
208 | #define VCF_RX 1 | ||
209 | #define VCF_IDLE 2 | ||
210 | #define VCF_RSV 3 | ||
211 | unsigned int class; | ||
212 | u8 init_er; | ||
213 | u8 lacr; | ||
214 | u8 max_er; | ||
215 | unsigned int ntste; | ||
216 | spinlock_t lock; | ||
217 | struct atm_vcc *tx_vcc; | ||
218 | struct atm_vcc *rx_vcc; | ||
219 | struct idt77252_dev *card; | ||
220 | struct scq_info *scq; /* To keep track of the SCQ */ | ||
221 | struct rate_estimator *estimator; | ||
222 | int scd_index; | ||
223 | union { | ||
224 | struct rx_pool rx_pool; | ||
225 | struct aal1 aal1; | ||
226 | } rcv; | ||
227 | }; | ||
228 | |||
229 | /*****************************************************************************/ | ||
230 | /* */ | ||
231 | /* RCTE - Receive Connection Table Entry */ | ||
232 | /* */ | ||
233 | /*****************************************************************************/ | ||
234 | |||
235 | struct rct_entry | ||
236 | { | ||
237 | u32 word_1; | ||
238 | u32 buffer_handle; | ||
239 | u32 dma_address; | ||
240 | u32 aal5_crc32; | ||
241 | }; | ||
242 | |||
243 | /*****************************************************************************/ | ||
244 | /* */ | ||
245 | /* RSQ - Receive Status Queue */ | ||
246 | /* */ | ||
247 | /*****************************************************************************/ | ||
248 | |||
249 | #define SAR_RSQE_VALID 0x80000000 | ||
250 | #define SAR_RSQE_IDLE 0x40000000 | ||
251 | #define SAR_RSQE_BUF_MASK 0x00030000 | ||
252 | #define SAR_RSQE_BUF_ASGN 0x00008000 | ||
253 | #define SAR_RSQE_NZGFC 0x00004000 | ||
254 | #define SAR_RSQE_EPDU 0x00002000 | ||
255 | #define SAR_RSQE_BUF_CONT 0x00001000 | ||
256 | #define SAR_RSQE_EFCIE 0x00000800 | ||
257 | #define SAR_RSQE_CLP 0x00000400 | ||
258 | #define SAR_RSQE_CRC 0x00000200 | ||
259 | #define SAR_RSQE_CELLCNT 0x000001FF | ||
260 | |||
261 | |||
262 | #define RSQSIZE 8192 | ||
263 | #define RSQ_NUM_ENTRIES (RSQSIZE / 16) | ||
264 | #define RSQ_ALIGNMENT 8192 | ||
265 | |||
266 | struct rsq_entry { | ||
267 | u32 word_1; | ||
268 | u32 word_2; | ||
269 | u32 word_3; | ||
270 | u32 word_4; | ||
271 | }; | ||
272 | |||
273 | struct rsq_info { | ||
274 | struct rsq_entry *base; | ||
275 | struct rsq_entry *next; | ||
276 | struct rsq_entry *last; | ||
277 | dma_addr_t paddr; | ||
278 | }; | ||
279 | |||
280 | |||
281 | /*****************************************************************************/ | ||
282 | /* */ | ||
283 | /* TSQ - Transmit Status Queue */ | ||
284 | /* */ | ||
285 | /*****************************************************************************/ | ||
286 | |||
287 | #define SAR_TSQE_INVALID 0x80000000 | ||
288 | #define SAR_TSQE_TIMESTAMP 0x00FFFFFF | ||
289 | #define SAR_TSQE_TYPE 0x60000000 | ||
290 | #define SAR_TSQE_TYPE_TIMER 0x00000000 | ||
291 | #define SAR_TSQE_TYPE_TSR 0x20000000 | ||
292 | #define SAR_TSQE_TYPE_IDLE 0x40000000 | ||
293 | #define SAR_TSQE_TYPE_TBD_COMP 0x60000000 | ||
294 | |||
295 | #define SAR_TSQE_TAG(stat) (((stat) >> 24) & 0x1f) | ||
296 | |||
297 | #define TSQSIZE 8192 | ||
298 | #define TSQ_NUM_ENTRIES 1024 | ||
299 | #define TSQ_ALIGNMENT 8192 | ||
300 | |||
301 | struct tsq_entry | ||
302 | { | ||
303 | u32 word_1; | ||
304 | u32 word_2; | ||
305 | }; | ||
306 | |||
307 | struct tsq_info | ||
308 | { | ||
309 | struct tsq_entry *base; | ||
310 | struct tsq_entry *next; | ||
311 | struct tsq_entry *last; | ||
312 | dma_addr_t paddr; | ||
313 | }; | ||
314 | |||
315 | struct tst_info | ||
316 | { | ||
317 | struct vc_map *vc; | ||
318 | u32 tste; | ||
319 | }; | ||
320 | |||
321 | #define TSTE_MASK 0x601fffff | ||
322 | |||
323 | #define TSTE_OPC_MASK 0x60000000 | ||
324 | #define TSTE_OPC_NULL 0x00000000 | ||
325 | #define TSTE_OPC_CBR 0x20000000 | ||
326 | #define TSTE_OPC_VAR 0x40000000 | ||
327 | #define TSTE_OPC_JMP 0x60000000 | ||
328 | |||
329 | #define TSTE_PUSH_IDLE 0x01000000 | ||
330 | #define TSTE_PUSH_ACTIVE 0x02000000 | ||
331 | |||
332 | #define TST_SWITCH_DONE 0 | ||
333 | #define TST_SWITCH_PENDING 1 | ||
334 | #define TST_SWITCH_WAIT 2 | ||
335 | |||
336 | #define FBQ_SHIFT 9 | ||
337 | #define FBQ_SIZE (1 << FBQ_SHIFT) | ||
338 | #define FBQ_MASK (FBQ_SIZE - 1) | ||
339 | |||
340 | struct sb_pool | ||
341 | { | ||
342 | unsigned int index; | ||
343 | struct sk_buff *skb[FBQ_SIZE]; | ||
344 | }; | ||
345 | |||
346 | #define POOL_HANDLE(queue, index) (((queue + 1) << 16) | (index)) | ||
347 | #define POOL_QUEUE(handle) (((handle) >> 16) - 1) | ||
348 | #define POOL_INDEX(handle) ((handle) & 0xffff) | ||
349 | |||
350 | struct idt77252_dev | ||
351 | { | ||
352 | struct tsq_info tsq; /* Transmit Status Queue */ | ||
353 | struct rsq_info rsq; /* Receive Status Queue */ | ||
354 | |||
355 | struct pci_dev *pcidev; /* PCI handle (desriptor) */ | ||
356 | struct atm_dev *atmdev; /* ATM device desriptor */ | ||
357 | |||
358 | void __iomem *membase; /* SAR's memory base address */ | ||
359 | unsigned long srambase; /* SAR's sram base address */ | ||
360 | void __iomem *fbq[4]; /* FBQ fill addresses */ | ||
361 | |||
362 | struct semaphore mutex; | ||
363 | spinlock_t cmd_lock; /* for r/w utility/sram */ | ||
364 | |||
365 | unsigned long softstat; | ||
366 | unsigned long flags; /* see blow */ | ||
367 | |||
368 | struct work_struct tqueue; | ||
369 | |||
370 | unsigned long tct_base; /* TCT base address in SRAM */ | ||
371 | unsigned long rct_base; /* RCT base address in SRAM */ | ||
372 | unsigned long rt_base; /* Rate Table base in SRAM */ | ||
373 | unsigned long scd_base; /* SCD base address in SRAM */ | ||
374 | unsigned long tst[2]; /* TST base address in SRAM */ | ||
375 | unsigned long abrst_base; /* ABRST base address in SRAM */ | ||
376 | unsigned long fifo_base; /* RX FIFO base in SRAM */ | ||
377 | |||
378 | unsigned long irqstat[16]; | ||
379 | |||
380 | unsigned int sramsize; /* SAR's sram size */ | ||
381 | |||
382 | unsigned int tct_size; /* total TCT entries */ | ||
383 | unsigned int rct_size; /* total RCT entries */ | ||
384 | unsigned int scd_size; /* length of SCD */ | ||
385 | unsigned int tst_size; /* total TST entries */ | ||
386 | unsigned int tst_free; /* free TSTEs in TST */ | ||
387 | unsigned int abrst_size; /* size of ABRST in words */ | ||
388 | unsigned int fifo_size; /* size of RX FIFO in words */ | ||
389 | |||
390 | unsigned int vpibits; /* Bits used for VPI index */ | ||
391 | unsigned int vcibits; /* Bits used for VCI index */ | ||
392 | unsigned int vcimask; /* Mask for VCI index */ | ||
393 | |||
394 | unsigned int utopia_pcr; /* Utopia Itf's Cell Rate */ | ||
395 | unsigned int link_pcr; /* PHY's Peek Cell Rate */ | ||
396 | |||
397 | struct vc_map **vcs; /* Open Connections */ | ||
398 | struct vc_map **scd2vc; /* SCD to Connection map */ | ||
399 | |||
400 | struct tst_info *soft_tst; /* TST to Connection map */ | ||
401 | unsigned int tst_index; /* Current TST in use */ | ||
402 | struct timer_list tst_timer; | ||
403 | spinlock_t tst_lock; | ||
404 | unsigned long tst_state; | ||
405 | |||
406 | struct sb_pool sbpool[4]; /* Pool of RX skbuffs */ | ||
407 | struct sk_buff *raw_cell_head; /* Pointer to raw cell queue */ | ||
408 | u32 *raw_cell_hnd; /* Pointer to RCQ handle */ | ||
409 | dma_addr_t raw_cell_paddr; | ||
410 | |||
411 | int index; /* SAR's ID */ | ||
412 | int revision; /* chip revision */ | ||
413 | |||
414 | char name[16]; /* Device name */ | ||
415 | |||
416 | struct idt77252_dev *next; | ||
417 | }; | ||
418 | |||
419 | |||
420 | /* definition for flag field above */ | ||
421 | #define IDT77252_BIT_INIT 1 | ||
422 | #define IDT77252_BIT_INTERRUPT 2 | ||
423 | |||
424 | |||
425 | #define ATM_CELL_PAYLOAD 48 | ||
426 | |||
427 | #define FREEBUF_ALIGNMENT 16 | ||
428 | |||
429 | /*****************************************************************************/ | ||
430 | /* */ | ||
431 | /* Makros */ | ||
432 | /* */ | ||
433 | /*****************************************************************************/ | ||
434 | #define ALIGN_ADDRESS(addr, alignment) \ | ||
435 | ((((u32)(addr)) + (((u32)(alignment))-1)) & ~(((u32)(alignment)) - 1)) | ||
436 | |||
437 | |||
438 | /*****************************************************************************/ | ||
439 | /* */ | ||
440 | /* ABR SAR Network operation Register */ | ||
441 | /* */ | ||
442 | /*****************************************************************************/ | ||
443 | |||
444 | #define SAR_REG_DR0 (card->membase + 0x00) | ||
445 | #define SAR_REG_DR1 (card->membase + 0x04) | ||
446 | #define SAR_REG_DR2 (card->membase + 0x08) | ||
447 | #define SAR_REG_DR3 (card->membase + 0x0C) | ||
448 | #define SAR_REG_CMD (card->membase + 0x10) | ||
449 | #define SAR_REG_CFG (card->membase + 0x14) | ||
450 | #define SAR_REG_STAT (card->membase + 0x18) | ||
451 | #define SAR_REG_RSQB (card->membase + 0x1C) | ||
452 | #define SAR_REG_RSQT (card->membase + 0x20) | ||
453 | #define SAR_REG_RSQH (card->membase + 0x24) | ||
454 | #define SAR_REG_CDC (card->membase + 0x28) | ||
455 | #define SAR_REG_VPEC (card->membase + 0x2C) | ||
456 | #define SAR_REG_ICC (card->membase + 0x30) | ||
457 | #define SAR_REG_RAWCT (card->membase + 0x34) | ||
458 | #define SAR_REG_TMR (card->membase + 0x38) | ||
459 | #define SAR_REG_TSTB (card->membase + 0x3C) | ||
460 | #define SAR_REG_TSQB (card->membase + 0x40) | ||
461 | #define SAR_REG_TSQT (card->membase + 0x44) | ||
462 | #define SAR_REG_TSQH (card->membase + 0x48) | ||
463 | #define SAR_REG_GP (card->membase + 0x4C) | ||
464 | #define SAR_REG_VPM (card->membase + 0x50) | ||
465 | #define SAR_REG_RXFD (card->membase + 0x54) | ||
466 | #define SAR_REG_RXFT (card->membase + 0x58) | ||
467 | #define SAR_REG_RXFH (card->membase + 0x5C) | ||
468 | #define SAR_REG_RAWHND (card->membase + 0x60) | ||
469 | #define SAR_REG_RXSTAT (card->membase + 0x64) | ||
470 | #define SAR_REG_ABRSTD (card->membase + 0x68) | ||
471 | #define SAR_REG_ABRRQ (card->membase + 0x6C) | ||
472 | #define SAR_REG_VBRRQ (card->membase + 0x70) | ||
473 | #define SAR_REG_RTBL (card->membase + 0x74) | ||
474 | #define SAR_REG_MDFCT (card->membase + 0x78) | ||
475 | #define SAR_REG_TXSTAT (card->membase + 0x7C) | ||
476 | #define SAR_REG_TCMDQ (card->membase + 0x80) | ||
477 | #define SAR_REG_IRCP (card->membase + 0x84) | ||
478 | #define SAR_REG_FBQP0 (card->membase + 0x88) | ||
479 | #define SAR_REG_FBQP1 (card->membase + 0x8C) | ||
480 | #define SAR_REG_FBQP2 (card->membase + 0x90) | ||
481 | #define SAR_REG_FBQP3 (card->membase + 0x94) | ||
482 | #define SAR_REG_FBQS0 (card->membase + 0x98) | ||
483 | #define SAR_REG_FBQS1 (card->membase + 0x9C) | ||
484 | #define SAR_REG_FBQS2 (card->membase + 0xA0) | ||
485 | #define SAR_REG_FBQS3 (card->membase + 0xA4) | ||
486 | #define SAR_REG_FBQWP0 (card->membase + 0xA8) | ||
487 | #define SAR_REG_FBQWP1 (card->membase + 0xAC) | ||
488 | #define SAR_REG_FBQWP2 (card->membase + 0xB0) | ||
489 | #define SAR_REG_FBQWP3 (card->membase + 0xB4) | ||
490 | #define SAR_REG_NOW (card->membase + 0xB8) | ||
491 | |||
492 | |||
493 | /*****************************************************************************/ | ||
494 | /* */ | ||
495 | /* Commands */ | ||
496 | /* */ | ||
497 | /*****************************************************************************/ | ||
498 | |||
499 | #define SAR_CMD_NO_OPERATION 0x00000000 | ||
500 | #define SAR_CMD_OPENCLOSE_CONNECTION 0x20000000 | ||
501 | #define SAR_CMD_WRITE_SRAM 0x40000000 | ||
502 | #define SAR_CMD_READ_SRAM 0x50000000 | ||
503 | #define SAR_CMD_READ_UTILITY 0x80000000 | ||
504 | #define SAR_CMD_WRITE_UTILITY 0x90000000 | ||
505 | |||
506 | #define SAR_CMD_OPEN_CONNECTION (SAR_CMD_OPENCLOSE_CONNECTION | 0x00080000) | ||
507 | #define SAR_CMD_CLOSE_CONNECTION SAR_CMD_OPENCLOSE_CONNECTION | ||
508 | |||
509 | |||
510 | /*****************************************************************************/ | ||
511 | /* */ | ||
512 | /* Configuration Register bits */ | ||
513 | /* */ | ||
514 | /*****************************************************************************/ | ||
515 | |||
516 | #define SAR_CFG_SWRST 0x80000000 /* Software reset */ | ||
517 | #define SAR_CFG_LOOP 0x40000000 /* Internal Loopback */ | ||
518 | #define SAR_CFG_RXPTH 0x20000000 /* Receive Path Enable */ | ||
519 | #define SAR_CFG_IDLE_CLP 0x10000000 /* SAR set CLP Bits of Null Cells */ | ||
520 | #define SAR_CFG_TX_FIFO_SIZE_1 0x04000000 /* TX FIFO Size = 1 cell */ | ||
521 | #define SAR_CFG_TX_FIFO_SIZE_2 0x08000000 /* TX FIFO Size = 2 cells */ | ||
522 | #define SAR_CFG_TX_FIFO_SIZE_4 0x0C000000 /* TX FIFO Size = 4 cells */ | ||
523 | #define SAR_CFG_TX_FIFO_SIZE_9 0x00000000 /* TX FIFO Size = 9 cells (full) */ | ||
524 | #define SAR_CFG_NO_IDLE 0x02000000 /* SAR sends no Null Cells */ | ||
525 | #define SAR_CFG_RSVD1 0x01000000 /* Reserved */ | ||
526 | #define SAR_CFG_RXSTQ_SIZE_2k 0x00000000 /* RX Stat Queue Size = 2048 byte */ | ||
527 | #define SAR_CFG_RXSTQ_SIZE_4k 0x00400000 /* RX Stat Queue Size = 4096 byte */ | ||
528 | #define SAR_CFG_RXSTQ_SIZE_8k 0x00800000 /* RX Stat Queue Size = 8192 byte */ | ||
529 | #define SAR_CFG_RXSTQ_SIZE_R 0x00C00000 /* RX Stat Queue Size = reserved */ | ||
530 | #define SAR_CFG_ICAPT 0x00200000 /* accept Invalid Cells */ | ||
531 | #define SAR_CFG_IGGFC 0x00100000 /* Ignore GFC */ | ||
532 | #define SAR_CFG_VPVCS_0 0x00000000 /* VPI/VCI Select bit range */ | ||
533 | #define SAR_CFG_VPVCS_1 0x00040000 /* VPI/VCI Select bit range */ | ||
534 | #define SAR_CFG_VPVCS_2 0x00080000 /* VPI/VCI Select bit range */ | ||
535 | #define SAR_CFG_VPVCS_8 0x000C0000 /* VPI/VCI Select bit range */ | ||
536 | #define SAR_CFG_CNTBL_1k 0x00000000 /* Connection Table Size */ | ||
537 | #define SAR_CFG_CNTBL_4k 0x00010000 /* Connection Table Size */ | ||
538 | #define SAR_CFG_CNTBL_16k 0x00020000 /* Connection Table Size */ | ||
539 | #define SAR_CFG_CNTBL_512 0x00030000 /* Connection Table Size */ | ||
540 | #define SAR_CFG_VPECA 0x00008000 /* VPI/VCI Error Cell Accept */ | ||
541 | #define SAR_CFG_RXINT_NOINT 0x00000000 /* No Interrupt on PDU received */ | ||
542 | #define SAR_CFG_RXINT_NODELAY 0x00001000 /* Interrupt without delay to host*/ | ||
543 | #define SAR_CFG_RXINT_256US 0x00002000 /* Interrupt with delay 256 usec */ | ||
544 | #define SAR_CFG_RXINT_505US 0x00003000 /* Interrupt with delay 505 usec */ | ||
545 | #define SAR_CFG_RXINT_742US 0x00004000 /* Interrupt with delay 742 usec */ | ||
546 | #define SAR_CFG_RAWIE 0x00000800 /* Raw Cell Queue Interrupt Enable*/ | ||
547 | #define SAR_CFG_RQFIE 0x00000400 /* RSQ Almost Full Int Enable */ | ||
548 | #define SAR_CFG_RSVD2 0x00000200 /* Reserved */ | ||
549 | #define SAR_CFG_CACHE 0x00000100 /* DMA on Cache Line Boundary */ | ||
550 | #define SAR_CFG_TMOIE 0x00000080 /* Timer Roll Over Int Enable */ | ||
551 | #define SAR_CFG_FBIE 0x00000040 /* Free Buffer Queue Int Enable */ | ||
552 | #define SAR_CFG_TXEN 0x00000020 /* Transmit Operation Enable */ | ||
553 | #define SAR_CFG_TXINT 0x00000010 /* Transmit status Int Enable */ | ||
554 | #define SAR_CFG_TXUIE 0x00000008 /* Transmit underrun Int Enable */ | ||
555 | #define SAR_CFG_UMODE 0x00000004 /* Utopia Mode Select */ | ||
556 | #define SAR_CFG_TXSFI 0x00000002 /* Transmit status Full Int Enable*/ | ||
557 | #define SAR_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */ | ||
558 | |||
559 | #define SAR_CFG_TX_FIFO_SIZE_MASK 0x0C000000 /* TX FIFO Size Mask */ | ||
560 | #define SAR_CFG_RXSTQSIZE_MASK 0x00C00000 | ||
561 | #define SAR_CFG_CNTBL_MASK 0x00030000 | ||
562 | #define SAR_CFG_RXINT_MASK 0x00007000 | ||
563 | |||
564 | |||
565 | /*****************************************************************************/ | ||
566 | /* */ | ||
567 | /* Status Register bits */ | ||
568 | /* */ | ||
569 | /*****************************************************************************/ | ||
570 | |||
571 | #define SAR_STAT_FRAC_3 0xF0000000 /* Fraction of Free Buffer Queue 3 */ | ||
572 | #define SAR_STAT_FRAC_2 0x0F000000 /* Fraction of Free Buffer Queue 2 */ | ||
573 | #define SAR_STAT_FRAC_1 0x00F00000 /* Fraction of Free Buffer Queue 1 */ | ||
574 | #define SAR_STAT_FRAC_0 0x000F0000 /* Fraction of Free Buffer Queue 0 */ | ||
575 | #define SAR_STAT_TSIF 0x00008000 /* Transmit Status Indicator */ | ||
576 | #define SAR_STAT_TXICP 0x00004000 /* Transmit Status Indicator */ | ||
577 | #define SAR_STAT_RSVD1 0x00002000 /* Reserved */ | ||
578 | #define SAR_STAT_TSQF 0x00001000 /* Transmit Status Queue full */ | ||
579 | #define SAR_STAT_TMROF 0x00000800 /* Timer overflow */ | ||
580 | #define SAR_STAT_PHYI 0x00000400 /* PHY device Interrupt flag */ | ||
581 | #define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Comand Busy Flag */ | ||
582 | #define SAR_STAT_FBQ3A 0x00000100 /* Free Buffer Queue 3 Attention */ | ||
583 | #define SAR_STAT_FBQ2A 0x00000080 /* Free Buffer Queue 2 Attention */ | ||
584 | #define SAR_STAT_RSQF 0x00000040 /* Receive Status Queue full */ | ||
585 | #define SAR_STAT_EPDU 0x00000020 /* End Of PDU Flag */ | ||
586 | #define SAR_STAT_RAWCF 0x00000010 /* Raw Cell Flag */ | ||
587 | #define SAR_STAT_FBQ1A 0x00000008 /* Free Buffer Queue 1 Attention */ | ||
588 | #define SAR_STAT_FBQ0A 0x00000004 /* Free Buffer Queue 0 Attention */ | ||
589 | #define SAR_STAT_RSQAF 0x00000002 /* Receive Status Queue almost full*/ | ||
590 | #define SAR_STAT_RSVD2 0x00000001 /* Reserved */ | ||
591 | |||
592 | |||
593 | /*****************************************************************************/ | ||
594 | /* */ | ||
595 | /* General Purpose Register bits */ | ||
596 | /* */ | ||
597 | /*****************************************************************************/ | ||
598 | |||
599 | #define SAR_GP_TXNCC_MASK 0xff000000 /* Transmit Negative Credit Count */ | ||
600 | #define SAR_GP_EEDI 0x00010000 /* EEPROM Data In */ | ||
601 | #define SAR_GP_BIGE 0x00008000 /* Big Endian Operation */ | ||
602 | #define SAR_GP_RM_NORMAL 0x00000000 /* Normal handling of RM cells */ | ||
603 | #define SAR_GP_RM_TO_RCQ 0x00002000 /* put RM cells into Raw Cell Queue */ | ||
604 | #define SAR_GP_RM_RSVD 0x00004000 /* Reserved */ | ||
605 | #define SAR_GP_RM_INHIBIT 0x00006000 /* Inhibit update of Connection tab */ | ||
606 | #define SAR_GP_PHY_RESET 0x00000008 /* PHY Reset */ | ||
607 | #define SAR_GP_EESCLK 0x00000004 /* EEPROM SCLK */ | ||
608 | #define SAR_GP_EECS 0x00000002 /* EEPROM Chip Select */ | ||
609 | #define SAR_GP_EEDO 0x00000001 /* EEPROM Data Out */ | ||
610 | |||
611 | |||
612 | /*****************************************************************************/ | ||
613 | /* */ | ||
614 | /* SAR local SRAM layout for 128k work SRAM */ | ||
615 | /* */ | ||
616 | /*****************************************************************************/ | ||
617 | |||
618 | #define SAR_SRAM_SCD_SIZE 12 | ||
619 | #define SAR_SRAM_TCT_SIZE 8 | ||
620 | #define SAR_SRAM_RCT_SIZE 4 | ||
621 | |||
622 | #define SAR_SRAM_TCT_128_BASE 0x00000 | ||
623 | #define SAR_SRAM_TCT_128_TOP 0x01fff | ||
624 | #define SAR_SRAM_RCT_128_BASE 0x02000 | ||
625 | #define SAR_SRAM_RCT_128_TOP 0x02fff | ||
626 | #define SAR_SRAM_FB0_128_BASE 0x03000 | ||
627 | #define SAR_SRAM_FB0_128_TOP 0x033ff | ||
628 | #define SAR_SRAM_FB1_128_BASE 0x03400 | ||
629 | #define SAR_SRAM_FB1_128_TOP 0x037ff | ||
630 | #define SAR_SRAM_FB2_128_BASE 0x03800 | ||
631 | #define SAR_SRAM_FB2_128_TOP 0x03bff | ||
632 | #define SAR_SRAM_FB3_128_BASE 0x03c00 | ||
633 | #define SAR_SRAM_FB3_128_TOP 0x03fff | ||
634 | #define SAR_SRAM_SCD_128_BASE 0x04000 | ||
635 | #define SAR_SRAM_SCD_128_TOP 0x07fff | ||
636 | #define SAR_SRAM_TST1_128_BASE 0x08000 | ||
637 | #define SAR_SRAM_TST1_128_TOP 0x0bfff | ||
638 | #define SAR_SRAM_TST2_128_BASE 0x0c000 | ||
639 | #define SAR_SRAM_TST2_128_TOP 0x0ffff | ||
640 | #define SAR_SRAM_ABRSTD_128_BASE 0x10000 | ||
641 | #define SAR_SRAM_ABRSTD_128_TOP 0x13fff | ||
642 | #define SAR_SRAM_RT_128_BASE 0x14000 | ||
643 | #define SAR_SRAM_RT_128_TOP 0x15fff | ||
644 | |||
645 | #define SAR_SRAM_FIFO_128_BASE 0x18000 | ||
646 | #define SAR_SRAM_FIFO_128_TOP 0x1ffff | ||
647 | |||
648 | |||
649 | /*****************************************************************************/ | ||
650 | /* */ | ||
651 | /* SAR local SRAM layout for 32k work SRAM */ | ||
652 | /* */ | ||
653 | /*****************************************************************************/ | ||
654 | |||
655 | #define SAR_SRAM_TCT_32_BASE 0x00000 | ||
656 | #define SAR_SRAM_TCT_32_TOP 0x00fff | ||
657 | #define SAR_SRAM_RCT_32_BASE 0x01000 | ||
658 | #define SAR_SRAM_RCT_32_TOP 0x017ff | ||
659 | #define SAR_SRAM_FB0_32_BASE 0x01800 | ||
660 | #define SAR_SRAM_FB0_32_TOP 0x01bff | ||
661 | #define SAR_SRAM_FB1_32_BASE 0x01c00 | ||
662 | #define SAR_SRAM_FB1_32_TOP 0x01fff | ||
663 | #define SAR_SRAM_FB2_32_BASE 0x02000 | ||
664 | #define SAR_SRAM_FB2_32_TOP 0x023ff | ||
665 | #define SAR_SRAM_FB3_32_BASE 0x02400 | ||
666 | #define SAR_SRAM_FB3_32_TOP 0x027ff | ||
667 | #define SAR_SRAM_SCD_32_BASE 0x02800 | ||
668 | #define SAR_SRAM_SCD_32_TOP 0x03fff | ||
669 | #define SAR_SRAM_TST1_32_BASE 0x04000 | ||
670 | #define SAR_SRAM_TST1_32_TOP 0x04fff | ||
671 | #define SAR_SRAM_TST2_32_BASE 0x05000 | ||
672 | #define SAR_SRAM_TST2_32_TOP 0x05fff | ||
673 | #define SAR_SRAM_ABRSTD_32_BASE 0x06000 | ||
674 | #define SAR_SRAM_ABRSTD_32_TOP 0x067ff | ||
675 | #define SAR_SRAM_RT_32_BASE 0x06800 | ||
676 | #define SAR_SRAM_RT_32_TOP 0x06fff | ||
677 | #define SAR_SRAM_FIFO_32_BASE 0x07000 | ||
678 | #define SAR_SRAM_FIFO_32_TOP 0x07fff | ||
679 | |||
680 | |||
681 | /*****************************************************************************/ | ||
682 | /* */ | ||
683 | /* TSR - Transmit Status Request */ | ||
684 | /* */ | ||
685 | /*****************************************************************************/ | ||
686 | |||
687 | #define SAR_TSR_TYPE_TSR 0x80000000 | ||
688 | #define SAR_TSR_TYPE_TBD 0x00000000 | ||
689 | #define SAR_TSR_TSIF 0x20000000 | ||
690 | #define SAR_TSR_TAG_MASK 0x01F00000 | ||
691 | |||
692 | |||
693 | /*****************************************************************************/ | ||
694 | /* */ | ||
695 | /* TBD - Transmit Buffer Descriptor */ | ||
696 | /* */ | ||
697 | /*****************************************************************************/ | ||
698 | |||
699 | #define SAR_TBD_EPDU 0x40000000 | ||
700 | #define SAR_TBD_TSIF 0x20000000 | ||
701 | #define SAR_TBD_OAM 0x10000000 | ||
702 | #define SAR_TBD_AAL0 0x00000000 | ||
703 | #define SAR_TBD_AAL34 0x04000000 | ||
704 | #define SAR_TBD_AAL5 0x08000000 | ||
705 | #define SAR_TBD_GTSI 0x02000000 | ||
706 | #define SAR_TBD_TAG_MASK 0x01F00000 | ||
707 | |||
708 | #define SAR_TBD_VPI_MASK 0x0FF00000 | ||
709 | #define SAR_TBD_VCI_MASK 0x000FFFF0 | ||
710 | #define SAR_TBD_VC_MASK (SAR_TBD_VPI_MASK | SAR_TBD_VCI_MASK) | ||
711 | |||
712 | #define SAR_TBD_VPI_SHIFT 20 | ||
713 | #define SAR_TBD_VCI_SHIFT 4 | ||
714 | |||
715 | |||
716 | /*****************************************************************************/ | ||
717 | /* */ | ||
718 | /* RXFD - Receive FIFO Descriptor */ | ||
719 | /* */ | ||
720 | /*****************************************************************************/ | ||
721 | |||
722 | #define SAR_RXFD_SIZE_MASK 0x0F000000 | ||
723 | #define SAR_RXFD_SIZE_512 0x00000000 /* 512 words */ | ||
724 | #define SAR_RXFD_SIZE_1K 0x01000000 /* 1k words */ | ||
725 | #define SAR_RXFD_SIZE_2K 0x02000000 /* 2k words */ | ||
726 | #define SAR_RXFD_SIZE_4K 0x03000000 /* 4k words */ | ||
727 | #define SAR_RXFD_SIZE_8K 0x04000000 /* 8k words */ | ||
728 | #define SAR_RXFD_SIZE_16K 0x05000000 /* 16k words */ | ||
729 | #define SAR_RXFD_SIZE_32K 0x06000000 /* 32k words */ | ||
730 | #define SAR_RXFD_SIZE_64K 0x07000000 /* 64k words */ | ||
731 | #define SAR_RXFD_SIZE_128K 0x08000000 /* 128k words */ | ||
732 | #define SAR_RXFD_SIZE_256K 0x09000000 /* 256k words */ | ||
733 | #define SAR_RXFD_ADDR_MASK 0x001ffc00 | ||
734 | |||
735 | |||
736 | /*****************************************************************************/ | ||
737 | /* */ | ||
738 | /* ABRSTD - ABR + VBR Schedule Tables */ | ||
739 | /* */ | ||
740 | /*****************************************************************************/ | ||
741 | |||
742 | #define SAR_ABRSTD_SIZE_MASK 0x07000000 | ||
743 | #define SAR_ABRSTD_SIZE_512 0x00000000 /* 512 words */ | ||
744 | #define SAR_ABRSTD_SIZE_1K 0x01000000 /* 1k words */ | ||
745 | #define SAR_ABRSTD_SIZE_2K 0x02000000 /* 2k words */ | ||
746 | #define SAR_ABRSTD_SIZE_4K 0x03000000 /* 4k words */ | ||
747 | #define SAR_ABRSTD_SIZE_8K 0x04000000 /* 8k words */ | ||
748 | #define SAR_ABRSTD_SIZE_16K 0x05000000 /* 16k words */ | ||
749 | #define SAR_ABRSTD_ADDR_MASK 0x001ffc00 | ||
750 | |||
751 | |||
752 | /*****************************************************************************/ | ||
753 | /* */ | ||
754 | /* RCTE - Receive Connection Table Entry */ | ||
755 | /* */ | ||
756 | /*****************************************************************************/ | ||
757 | |||
758 | #define SAR_RCTE_IL_MASK 0xE0000000 /* inactivity limit */ | ||
759 | #define SAR_RCTE_IC_MASK 0x1C000000 /* inactivity count */ | ||
760 | #define SAR_RCTE_RSVD 0x02000000 /* reserved */ | ||
761 | #define SAR_RCTE_LCD 0x01000000 /* last cell data */ | ||
762 | #define SAR_RCTE_CI_VC 0x00800000 /* EFCI in previous cell of VC */ | ||
763 | #define SAR_RCTE_FBP_01 0x00000000 /* 1. cell->FBQ0, others->FBQ1 */ | ||
764 | #define SAR_RCTE_FBP_1 0x00200000 /* use FBQ 1 for all cells */ | ||
765 | #define SAR_RCTE_FBP_2 0x00400000 /* use FBQ 2 for all cells */ | ||
766 | #define SAR_RCTE_FBP_3 0x00600000 /* use FBQ 3 for all cells */ | ||
767 | #define SAR_RCTE_NZ_GFC 0x00100000 /* non zero GFC in all cell of VC */ | ||
768 | #define SAR_RCTE_CONNECTOPEN 0x00080000 /* VC is open */ | ||
769 | #define SAR_RCTE_AAL_MASK 0x00070000 /* mask for AAL type field s.b. */ | ||
770 | #define SAR_RCTE_RAWCELLINTEN 0x00008000 /* raw cell interrupt enable */ | ||
771 | #define SAR_RCTE_RXCONCELLADDR 0x00004000 /* RX constant cell address */ | ||
772 | #define SAR_RCTE_BUFFSTAT_MASK 0x00003000 /* buffer status */ | ||
773 | #define SAR_RCTE_EFCI 0x00000800 /* EFCI Congestion flag */ | ||
774 | #define SAR_RCTE_CLP 0x00000400 /* Cell Loss Priority flag */ | ||
775 | #define SAR_RCTE_CRC 0x00000200 /* Recieved CRC Error */ | ||
776 | #define SAR_RCTE_CELLCNT_MASK 0x000001FF /* cell Count */ | ||
777 | |||
778 | #define SAR_RCTE_AAL0 0x00000000 /* AAL types for ALL field */ | ||
779 | #define SAR_RCTE_AAL34 0x00010000 | ||
780 | #define SAR_RCTE_AAL5 0x00020000 | ||
781 | #define SAR_RCTE_RCQ 0x00030000 | ||
782 | #define SAR_RCTE_OAM 0x00040000 | ||
783 | |||
784 | #define TCMDQ_START 0x01000000 | ||
785 | #define TCMDQ_LACR 0x02000000 | ||
786 | #define TCMDQ_START_LACR 0x03000000 | ||
787 | #define TCMDQ_INIT_ER 0x04000000 | ||
788 | #define TCMDQ_HALT 0x05000000 | ||
789 | |||
790 | |||
791 | struct idt77252_skb_prv { | ||
792 | struct scqe tbd; /* Transmit Buffer Descriptor */ | ||
793 | dma_addr_t paddr; /* DMA handle */ | ||
794 | u32 pool; /* sb_pool handle */ | ||
795 | }; | ||
796 | |||
797 | #define IDT77252_PRV_TBD(skb) \ | ||
798 | (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->tbd) | ||
799 | #define IDT77252_PRV_PADDR(skb) \ | ||
800 | (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->paddr) | ||
801 | #define IDT77252_PRV_POOL(skb) \ | ||
802 | (((struct idt77252_skb_prv *)(ATM_SKB(skb)+1))->pool) | ||
803 | |||
804 | /*****************************************************************************/ | ||
805 | /* */ | ||
806 | /* PCI related items */ | ||
807 | /* */ | ||
808 | /*****************************************************************************/ | ||
809 | |||
810 | #ifndef PCI_VENDOR_ID_IDT | ||
811 | #define PCI_VENDOR_ID_IDT 0x111D | ||
812 | #endif /* PCI_VENDOR_ID_IDT */ | ||
813 | |||
814 | #ifndef PCI_DEVICE_ID_IDT_IDT77252 | ||
815 | #define PCI_DEVICE_ID_IDT_IDT77252 0x0003 | ||
816 | #endif /* PCI_DEVICE_ID_IDT_IDT772052 */ | ||
817 | |||
818 | |||
819 | #endif /* !(_IDT77252_H) */ | ||
diff --git a/drivers/atm/idt77252_tables.h b/drivers/atm/idt77252_tables.h new file mode 100644 index 000000000000..b6c8ee512fb4 --- /dev/null +++ b/drivers/atm/idt77252_tables.h | |||
@@ -0,0 +1,780 @@ | |||
1 | /* Do not edit, automatically generated by `./genrtbl'. | ||
2 | * | ||
3 | * Cell Line Rate: 353207.55 (155520000 bps) | ||
4 | */ | ||
5 | |||
6 | static unsigned int log_to_rate[] = | ||
7 | { | ||
8 | /* 000 */ 0x8d022e27, /* cps = 10.02, nrm = 3, interval = 35264.00 */ | ||
9 | /* 001 */ 0x8d362e11, /* cps = 10.42, nrm = 3, interval = 33856.00 */ | ||
10 | /* 002 */ 0x8d6e2bf8, /* cps = 10.86, nrm = 3, interval = 32512.00 */ | ||
11 | /* 003 */ 0x8da82bcf, /* cps = 11.31, nrm = 3, interval = 31200.00 */ | ||
12 | /* 004 */ 0x8de42ba8, /* cps = 11.78, nrm = 3, interval = 29952.00 */ | ||
13 | /* 005 */ 0x8e242b82, /* cps = 12.28, nrm = 3, interval = 28736.00 */ | ||
14 | /* 006 */ 0x8e662b5e, /* cps = 12.80, nrm = 3, interval = 27584.00 */ | ||
15 | /* 007 */ 0x8eaa2b3c, /* cps = 13.33, nrm = 3, interval = 26496.00 */ | ||
16 | /* 008 */ 0x8ef22b1a, /* cps = 13.89, nrm = 3, interval = 25408.00 */ | ||
17 | /* 009 */ 0x8f3e2afa, /* cps = 14.48, nrm = 3, interval = 24384.00 */ | ||
18 | /* 010 */ 0x8f8a2adc, /* cps = 15.08, nrm = 3, interval = 23424.00 */ | ||
19 | /* 011 */ 0x8fdc2abe, /* cps = 15.72, nrm = 3, interval = 22464.00 */ | ||
20 | /* 012 */ 0x90182aa2, /* cps = 16.38, nrm = 3, interval = 21568.00 */ | ||
21 | /* 013 */ 0x90422a87, /* cps = 17.03, nrm = 3, interval = 20704.00 */ | ||
22 | /* 014 */ 0x90702a6d, /* cps = 17.75, nrm = 3, interval = 19872.00 */ | ||
23 | /* 015 */ 0x90a02a54, /* cps = 18.50, nrm = 3, interval = 19072.00 */ | ||
24 | /* 016 */ 0x90d22a3c, /* cps = 19.28, nrm = 3, interval = 18304.00 */ | ||
25 | /* 017 */ 0x91062a25, /* cps = 20.09, nrm = 3, interval = 17568.00 */ | ||
26 | /* 018 */ 0x913c2a0f, /* cps = 20.94, nrm = 3, interval = 16864.00 */ | ||
27 | /* 019 */ 0x917427f3, /* cps = 21.81, nrm = 3, interval = 16176.00 */ | ||
28 | /* 020 */ 0x91b027ca, /* cps = 22.75, nrm = 3, interval = 15520.00 */ | ||
29 | /* 021 */ 0x91ec27a3, /* cps = 23.69, nrm = 3, interval = 14896.00 */ | ||
30 | /* 022 */ 0x922c277e, /* cps = 24.69, nrm = 3, interval = 14304.00 */ | ||
31 | /* 023 */ 0x926e275a, /* cps = 25.72, nrm = 3, interval = 13728.00 */ | ||
32 | /* 024 */ 0x92b42737, /* cps = 26.81, nrm = 3, interval = 13168.00 */ | ||
33 | /* 025 */ 0x92fc2716, /* cps = 27.94, nrm = 3, interval = 12640.00 */ | ||
34 | /* 026 */ 0x934626f6, /* cps = 29.09, nrm = 3, interval = 12128.00 */ | ||
35 | /* 027 */ 0x939426d8, /* cps = 30.31, nrm = 3, interval = 11648.00 */ | ||
36 | /* 028 */ 0x93e426bb, /* cps = 31.56, nrm = 3, interval = 11184.00 */ | ||
37 | /* 029 */ 0x941e269e, /* cps = 32.94, nrm = 3, interval = 10720.00 */ | ||
38 | /* 030 */ 0x944a2683, /* cps = 34.31, nrm = 3, interval = 10288.00 */ | ||
39 | /* 031 */ 0x9476266a, /* cps = 35.69, nrm = 3, interval = 9888.00 */ | ||
40 | /* 032 */ 0x94a62651, /* cps = 37.19, nrm = 3, interval = 9488.00 */ | ||
41 | /* 033 */ 0x94d82639, /* cps = 38.75, nrm = 3, interval = 9104.00 */ | ||
42 | /* 034 */ 0x950c6622, /* cps = 40.38, nrm = 4, interval = 8736.00 */ | ||
43 | /* 035 */ 0x9544660c, /* cps = 42.12, nrm = 4, interval = 8384.00 */ | ||
44 | /* 036 */ 0x957c63ee, /* cps = 43.88, nrm = 4, interval = 8048.00 */ | ||
45 | /* 037 */ 0x95b663c6, /* cps = 45.69, nrm = 4, interval = 7728.00 */ | ||
46 | /* 038 */ 0x95f4639f, /* cps = 47.62, nrm = 4, interval = 7416.00 */ | ||
47 | /* 039 */ 0x96346379, /* cps = 49.62, nrm = 4, interval = 7112.00 */ | ||
48 | /* 040 */ 0x96766356, /* cps = 51.69, nrm = 4, interval = 6832.00 */ | ||
49 | /* 041 */ 0x96bc6333, /* cps = 53.88, nrm = 4, interval = 6552.00 */ | ||
50 | /* 042 */ 0x97046312, /* cps = 56.12, nrm = 4, interval = 6288.00 */ | ||
51 | /* 043 */ 0x974e62f3, /* cps = 58.44, nrm = 4, interval = 6040.00 */ | ||
52 | /* 044 */ 0x979e62d4, /* cps = 60.94, nrm = 4, interval = 5792.00 */ | ||
53 | /* 045 */ 0x97f062b7, /* cps = 63.50, nrm = 4, interval = 5560.00 */ | ||
54 | /* 046 */ 0x9822629b, /* cps = 66.12, nrm = 4, interval = 5336.00 */ | ||
55 | /* 047 */ 0x984e6280, /* cps = 68.88, nrm = 4, interval = 5120.00 */ | ||
56 | /* 048 */ 0x987e6266, /* cps = 71.88, nrm = 4, interval = 4912.00 */ | ||
57 | /* 049 */ 0x98ac624e, /* cps = 74.75, nrm = 4, interval = 4720.00 */ | ||
58 | /* 050 */ 0x98e06236, /* cps = 78.00, nrm = 4, interval = 4528.00 */ | ||
59 | /* 051 */ 0x9914a21f, /* cps = 81.25, nrm = 8, interval = 4344.00 */ | ||
60 | /* 052 */ 0x994aa209, /* cps = 84.62, nrm = 8, interval = 4168.00 */ | ||
61 | /* 053 */ 0x99829fe9, /* cps = 88.12, nrm = 8, interval = 4004.00 */ | ||
62 | /* 054 */ 0x99be9fc1, /* cps = 91.88, nrm = 8, interval = 3844.00 */ | ||
63 | /* 055 */ 0x99fc9f9a, /* cps = 95.75, nrm = 8, interval = 3688.00 */ | ||
64 | /* 056 */ 0x9a3c9f75, /* cps = 99.75, nrm = 8, interval = 3540.00 */ | ||
65 | /* 057 */ 0x9a809f51, /* cps = 104.00, nrm = 8, interval = 3396.00 */ | ||
66 | /* 058 */ 0x9ac49f2f, /* cps = 108.25, nrm = 8, interval = 3260.00 */ | ||
67 | /* 059 */ 0x9b0e9f0e, /* cps = 112.88, nrm = 8, interval = 3128.00 */ | ||
68 | /* 060 */ 0x9b589eef, /* cps = 117.50, nrm = 8, interval = 3004.00 */ | ||
69 | /* 061 */ 0x9ba69ed1, /* cps = 122.38, nrm = 8, interval = 2884.00 */ | ||
70 | /* 062 */ 0x9bf89eb4, /* cps = 127.50, nrm = 8, interval = 2768.00 */ | ||
71 | /* 063 */ 0x9c269e98, /* cps = 132.75, nrm = 8, interval = 2656.00 */ | ||
72 | /* 064 */ 0x9c549e7d, /* cps = 138.50, nrm = 8, interval = 2548.00 */ | ||
73 | /* 065 */ 0x9c849e63, /* cps = 144.50, nrm = 8, interval = 2444.00 */ | ||
74 | /* 066 */ 0x9cb29e4b, /* cps = 150.25, nrm = 8, interval = 2348.00 */ | ||
75 | /* 067 */ 0x9ce69e33, /* cps = 156.75, nrm = 8, interval = 2252.00 */ | ||
76 | /* 068 */ 0x9d1cde1c, /* cps = 163.50, nrm = 16, interval = 2160.00 */ | ||
77 | /* 069 */ 0x9d50de07, /* cps = 170.00, nrm = 16, interval = 2076.00 */ | ||
78 | /* 070 */ 0x9d8adbe4, /* cps = 177.25, nrm = 16, interval = 1992.00 */ | ||
79 | /* 071 */ 0x9dc4dbbc, /* cps = 184.50, nrm = 16, interval = 1912.00 */ | ||
80 | /* 072 */ 0x9e02db96, /* cps = 192.25, nrm = 16, interval = 1836.00 */ | ||
81 | /* 073 */ 0x9e42db71, /* cps = 200.25, nrm = 16, interval = 1762.00 */ | ||
82 | /* 074 */ 0x9e86db4d, /* cps = 208.75, nrm = 16, interval = 1690.00 */ | ||
83 | /* 075 */ 0x9ecedb2b, /* cps = 217.75, nrm = 16, interval = 1622.00 */ | ||
84 | /* 076 */ 0x9f16db0a, /* cps = 226.75, nrm = 16, interval = 1556.00 */ | ||
85 | /* 077 */ 0x9f62daeb, /* cps = 236.25, nrm = 16, interval = 1494.00 */ | ||
86 | /* 078 */ 0x9fb2dacd, /* cps = 246.25, nrm = 16, interval = 1434.00 */ | ||
87 | /* 079 */ 0xa002dab0, /* cps = 256.50, nrm = 16, interval = 1376.00 */ | ||
88 | /* 080 */ 0xa02eda94, /* cps = 267.50, nrm = 16, interval = 1320.00 */ | ||
89 | /* 081 */ 0xa05ada7a, /* cps = 278.50, nrm = 16, interval = 1268.00 */ | ||
90 | /* 082 */ 0xa088da60, /* cps = 290.00, nrm = 16, interval = 1216.00 */ | ||
91 | /* 083 */ 0xa0b8da48, /* cps = 302.00, nrm = 16, interval = 1168.00 */ | ||
92 | /* 084 */ 0xa0ecda30, /* cps = 315.00, nrm = 16, interval = 1120.00 */ | ||
93 | /* 085 */ 0xa1211a1a, /* cps = 328.00, nrm = 32, interval = 1076.00 */ | ||
94 | /* 086 */ 0xa1591a04, /* cps = 342.00, nrm = 32, interval = 1032.00 */ | ||
95 | /* 087 */ 0xa19117df, /* cps = 356.00, nrm = 32, interval = 991.00 */ | ||
96 | /* 088 */ 0xa1cd17b7, /* cps = 371.00, nrm = 32, interval = 951.00 */ | ||
97 | /* 089 */ 0xa20b1791, /* cps = 386.50, nrm = 32, interval = 913.00 */ | ||
98 | /* 090 */ 0xa24d176c, /* cps = 403.00, nrm = 32, interval = 876.00 */ | ||
99 | /* 091 */ 0xa28f1749, /* cps = 419.50, nrm = 32, interval = 841.00 */ | ||
100 | /* 092 */ 0xa2d71727, /* cps = 437.50, nrm = 32, interval = 807.00 */ | ||
101 | /* 093 */ 0xa31f1707, /* cps = 455.50, nrm = 32, interval = 775.00 */ | ||
102 | /* 094 */ 0xa36d16e7, /* cps = 475.00, nrm = 32, interval = 743.00 */ | ||
103 | /* 095 */ 0xa3bd16c9, /* cps = 495.00, nrm = 32, interval = 713.00 */ | ||
104 | /* 096 */ 0xa40716ad, /* cps = 515.00, nrm = 32, interval = 685.00 */ | ||
105 | /* 097 */ 0xa4331691, /* cps = 537.00, nrm = 32, interval = 657.00 */ | ||
106 | /* 098 */ 0xa45f1677, /* cps = 559.00, nrm = 32, interval = 631.00 */ | ||
107 | /* 099 */ 0xa48f165d, /* cps = 583.00, nrm = 32, interval = 605.00 */ | ||
108 | /* 100 */ 0xa4bf1645, /* cps = 607.00, nrm = 32, interval = 581.00 */ | ||
109 | /* 101 */ 0xa4f1162e, /* cps = 632.00, nrm = 32, interval = 558.00 */ | ||
110 | /* 102 */ 0xa5291617, /* cps = 660.00, nrm = 32, interval = 535.00 */ | ||
111 | /* 103 */ 0xa55f1602, /* cps = 687.00, nrm = 32, interval = 514.00 */ | ||
112 | /* 104 */ 0xa59913da, /* cps = 716.00, nrm = 32, interval = 493.00 */ | ||
113 | /* 105 */ 0xa5d513b2, /* cps = 746.00, nrm = 32, interval = 473.00 */ | ||
114 | /* 106 */ 0xa613138c, /* cps = 777.00, nrm = 32, interval = 454.00 */ | ||
115 | /* 107 */ 0xa6551368, /* cps = 810.00, nrm = 32, interval = 436.00 */ | ||
116 | /* 108 */ 0xa6971345, /* cps = 843.00, nrm = 32, interval = 418.50 */ | ||
117 | /* 109 */ 0xa6df1323, /* cps = 879.00, nrm = 32, interval = 401.50 */ | ||
118 | /* 110 */ 0xa7291303, /* cps = 916.00, nrm = 32, interval = 385.50 */ | ||
119 | /* 111 */ 0xa77512e4, /* cps = 954.00, nrm = 32, interval = 370.00 */ | ||
120 | /* 112 */ 0xa7c512c6, /* cps = 994.00, nrm = 32, interval = 355.00 */ | ||
121 | /* 113 */ 0xa80d12a9, /* cps = 1036.00, nrm = 32, interval = 340.50 */ | ||
122 | /* 114 */ 0xa839128e, /* cps = 1080.00, nrm = 32, interval = 327.00 */ | ||
123 | /* 115 */ 0xa8651274, /* cps = 1124.00, nrm = 32, interval = 314.00 */ | ||
124 | /* 116 */ 0xa895125a, /* cps = 1172.00, nrm = 32, interval = 301.00 */ | ||
125 | /* 117 */ 0xa8c71242, /* cps = 1222.00, nrm = 32, interval = 289.00 */ | ||
126 | /* 118 */ 0xa8f9122b, /* cps = 1272.00, nrm = 32, interval = 277.50 */ | ||
127 | /* 119 */ 0xa92f1214, /* cps = 1326.00, nrm = 32, interval = 266.00 */ | ||
128 | /* 120 */ 0xa9670ffe, /* cps = 1382.00, nrm = 32, interval = 255.50 */ | ||
129 | /* 121 */ 0xa9a10fd5, /* cps = 1440.00, nrm = 32, interval = 245.25 */ | ||
130 | /* 122 */ 0xa9db0fae, /* cps = 1498.00, nrm = 32, interval = 235.50 */ | ||
131 | /* 123 */ 0xaa1b0f88, /* cps = 1562.00, nrm = 32, interval = 226.00 */ | ||
132 | /* 124 */ 0xaa5d0f63, /* cps = 1628.00, nrm = 32, interval = 216.75 */ | ||
133 | /* 125 */ 0xaaa10f41, /* cps = 1696.00, nrm = 32, interval = 208.25 */ | ||
134 | /* 126 */ 0xaae90f1f, /* cps = 1768.00, nrm = 32, interval = 199.75 */ | ||
135 | /* 127 */ 0xab330eff, /* cps = 1842.00, nrm = 32, interval = 191.75 */ | ||
136 | /* 128 */ 0xab7f0ee0, /* cps = 1918.00, nrm = 32, interval = 184.00 */ | ||
137 | /* 129 */ 0xabd10ec2, /* cps = 2000.00, nrm = 32, interval = 176.50 */ | ||
138 | /* 130 */ 0xac110ea6, /* cps = 2080.00, nrm = 32, interval = 169.50 */ | ||
139 | /* 131 */ 0xac3d0e8b, /* cps = 2168.00, nrm = 32, interval = 162.75 */ | ||
140 | /* 132 */ 0xac6d0e70, /* cps = 2264.00, nrm = 32, interval = 156.00 */ | ||
141 | /* 133 */ 0xac9b0e57, /* cps = 2356.00, nrm = 32, interval = 149.75 */ | ||
142 | /* 134 */ 0xaccd0e3f, /* cps = 2456.00, nrm = 32, interval = 143.75 */ | ||
143 | /* 135 */ 0xacff0e28, /* cps = 2556.00, nrm = 32, interval = 138.00 */ | ||
144 | /* 136 */ 0xad350e12, /* cps = 2664.00, nrm = 32, interval = 132.50 */ | ||
145 | /* 137 */ 0xad6d0bf9, /* cps = 2776.00, nrm = 32, interval = 127.12 */ | ||
146 | /* 138 */ 0xada70bd0, /* cps = 2892.00, nrm = 32, interval = 122.00 */ | ||
147 | /* 139 */ 0xade30ba9, /* cps = 3012.00, nrm = 32, interval = 117.12 */ | ||
148 | /* 140 */ 0xae230b83, /* cps = 3140.00, nrm = 32, interval = 112.38 */ | ||
149 | /* 141 */ 0xae650b5f, /* cps = 3272.00, nrm = 32, interval = 107.88 */ | ||
150 | /* 142 */ 0xaeab0b3c, /* cps = 3412.00, nrm = 32, interval = 103.50 */ | ||
151 | /* 143 */ 0xaef10b1b, /* cps = 3552.00, nrm = 32, interval = 99.38 */ | ||
152 | /* 144 */ 0xaf3b0afb, /* cps = 3700.00, nrm = 32, interval = 95.38 */ | ||
153 | /* 145 */ 0xaf8b0adc, /* cps = 3860.00, nrm = 32, interval = 91.50 */ | ||
154 | /* 146 */ 0xafd90abf, /* cps = 4016.00, nrm = 32, interval = 87.88 */ | ||
155 | /* 147 */ 0xb0170aa3, /* cps = 4184.00, nrm = 32, interval = 84.38 */ | ||
156 | /* 148 */ 0xb0430a87, /* cps = 4360.00, nrm = 32, interval = 80.88 */ | ||
157 | /* 149 */ 0xb0710a6d, /* cps = 4544.00, nrm = 32, interval = 77.62 */ | ||
158 | /* 150 */ 0xb0a10a54, /* cps = 4736.00, nrm = 32, interval = 74.50 */ | ||
159 | /* 151 */ 0xb0d30a3c, /* cps = 4936.00, nrm = 32, interval = 71.50 */ | ||
160 | /* 152 */ 0xb1070a25, /* cps = 5144.00, nrm = 32, interval = 68.62 */ | ||
161 | /* 153 */ 0xb13d0a0f, /* cps = 5360.00, nrm = 32, interval = 65.88 */ | ||
162 | /* 154 */ 0xb17507f4, /* cps = 5584.00, nrm = 32, interval = 63.25 */ | ||
163 | /* 155 */ 0xb1af07cb, /* cps = 5816.00, nrm = 32, interval = 60.69 */ | ||
164 | /* 156 */ 0xb1eb07a4, /* cps = 6056.00, nrm = 32, interval = 58.25 */ | ||
165 | /* 157 */ 0xb22b077f, /* cps = 6312.00, nrm = 32, interval = 55.94 */ | ||
166 | /* 158 */ 0xb26d075b, /* cps = 6576.00, nrm = 32, interval = 53.69 */ | ||
167 | /* 159 */ 0xb2b30738, /* cps = 6856.00, nrm = 32, interval = 51.50 */ | ||
168 | /* 160 */ 0xb2fb0717, /* cps = 7144.00, nrm = 32, interval = 49.44 */ | ||
169 | /* 161 */ 0xb34506f7, /* cps = 7440.00, nrm = 32, interval = 47.44 */ | ||
170 | /* 162 */ 0xb39306d9, /* cps = 7752.00, nrm = 32, interval = 45.56 */ | ||
171 | /* 163 */ 0xb3e506bb, /* cps = 8080.00, nrm = 32, interval = 43.69 */ | ||
172 | /* 164 */ 0xb41d069f, /* cps = 8416.00, nrm = 32, interval = 41.94 */ | ||
173 | /* 165 */ 0xb4490684, /* cps = 8768.00, nrm = 32, interval = 40.25 */ | ||
174 | /* 166 */ 0xb477066a, /* cps = 9136.00, nrm = 32, interval = 38.62 */ | ||
175 | /* 167 */ 0xb4a70651, /* cps = 9520.00, nrm = 32, interval = 37.06 */ | ||
176 | /* 168 */ 0xb4d90639, /* cps = 9920.00, nrm = 32, interval = 35.56 */ | ||
177 | /* 169 */ 0xb50d0622, /* cps = 10336.00, nrm = 32, interval = 34.12 */ | ||
178 | /* 170 */ 0xb545060c, /* cps = 10784.00, nrm = 32, interval = 32.75 */ | ||
179 | /* 171 */ 0xb57b03ef, /* cps = 11216.00, nrm = 32, interval = 31.47 */ | ||
180 | /* 172 */ 0xb5b503c7, /* cps = 11680.00, nrm = 32, interval = 30.22 */ | ||
181 | /* 173 */ 0xb5f303a0, /* cps = 12176.00, nrm = 32, interval = 29.00 */ | ||
182 | /* 174 */ 0xb633037a, /* cps = 12688.00, nrm = 32, interval = 27.81 */ | ||
183 | /* 175 */ 0xb6750357, /* cps = 13216.00, nrm = 32, interval = 26.72 */ | ||
184 | /* 176 */ 0xb6bb0334, /* cps = 13776.00, nrm = 32, interval = 25.62 */ | ||
185 | /* 177 */ 0xb7030313, /* cps = 14352.00, nrm = 32, interval = 24.59 */ | ||
186 | /* 178 */ 0xb74f02f3, /* cps = 14960.00, nrm = 32, interval = 23.59 */ | ||
187 | /* 179 */ 0xb79d02d5, /* cps = 15584.00, nrm = 32, interval = 22.66 */ | ||
188 | /* 180 */ 0xb7ed02b8, /* cps = 16224.00, nrm = 32, interval = 21.75 */ | ||
189 | /* 181 */ 0xb821029c, /* cps = 16896.00, nrm = 32, interval = 20.88 */ | ||
190 | /* 182 */ 0xb84f0281, /* cps = 17632.00, nrm = 32, interval = 20.03 */ | ||
191 | /* 183 */ 0xb87d0267, /* cps = 18368.00, nrm = 32, interval = 19.22 */ | ||
192 | /* 184 */ 0xb8ad024e, /* cps = 19136.00, nrm = 32, interval = 18.44 */ | ||
193 | /* 185 */ 0xb8dd0237, /* cps = 19904.00, nrm = 32, interval = 17.72 */ | ||
194 | /* 186 */ 0xb9130220, /* cps = 20768.00, nrm = 32, interval = 17.00 */ | ||
195 | /* 187 */ 0xb949020a, /* cps = 21632.00, nrm = 32, interval = 16.31 */ | ||
196 | /* 188 */ 0xb98301f5, /* cps = 22560.00, nrm = 32, interval = 15.66 */ | ||
197 | /* 189 */ 0xb9bd01e1, /* cps = 23488.00, nrm = 32, interval = 15.03 */ | ||
198 | /* 190 */ 0xb9fd01cd, /* cps = 24512.00, nrm = 32, interval = 14.41 */ | ||
199 | /* 191 */ 0xba3b01bb, /* cps = 25504.00, nrm = 32, interval = 13.84 */ | ||
200 | /* 192 */ 0xba7f01a9, /* cps = 26592.00, nrm = 32, interval = 13.28 */ | ||
201 | /* 193 */ 0xbac30198, /* cps = 27680.00, nrm = 32, interval = 12.75 */ | ||
202 | /* 194 */ 0xbb0f0187, /* cps = 28896.00, nrm = 32, interval = 12.22 */ | ||
203 | /* 195 */ 0xbb570178, /* cps = 30048.00, nrm = 32, interval = 11.75 */ | ||
204 | /* 196 */ 0xbbab0168, /* cps = 31392.00, nrm = 32, interval = 11.25 */ | ||
205 | /* 197 */ 0xbbf9015a, /* cps = 32640.00, nrm = 32, interval = 10.81 */ | ||
206 | /* 198 */ 0xbc27014c, /* cps = 33984.00, nrm = 32, interval = 10.38 */ | ||
207 | /* 199 */ 0xbc53013f, /* cps = 35392.00, nrm = 32, interval = 9.97 */ | ||
208 | /* 200 */ 0xbc830132, /* cps = 36928.00, nrm = 32, interval = 9.56 */ | ||
209 | /* 201 */ 0xbcb50125, /* cps = 38528.00, nrm = 32, interval = 9.16 */ | ||
210 | /* 202 */ 0xbce5011a, /* cps = 40064.00, nrm = 32, interval = 8.81 */ | ||
211 | /* 203 */ 0xbd1d010e, /* cps = 41856.00, nrm = 32, interval = 8.44 */ | ||
212 | /* 204 */ 0xbd530103, /* cps = 43584.00, nrm = 32, interval = 8.09 */ | ||
213 | /* 205 */ 0xbd8b00f9, /* cps = 45376.00, nrm = 32, interval = 7.78 */ | ||
214 | /* 206 */ 0xbdc500ef, /* cps = 47232.00, nrm = 32, interval = 7.47 */ | ||
215 | /* 207 */ 0xbe0700e5, /* cps = 49344.00, nrm = 32, interval = 7.16 */ | ||
216 | /* 208 */ 0xbe4500dc, /* cps = 51328.00, nrm = 32, interval = 6.88 */ | ||
217 | /* 209 */ 0xbe8900d3, /* cps = 53504.00, nrm = 32, interval = 6.59 */ | ||
218 | /* 210 */ 0xbecb00cb, /* cps = 55616.00, nrm = 32, interval = 6.34 */ | ||
219 | /* 211 */ 0xbf1d00c2, /* cps = 58240.00, nrm = 32, interval = 6.06 */ | ||
220 | /* 212 */ 0xbf6100bb, /* cps = 60416.00, nrm = 32, interval = 5.84 */ | ||
221 | /* 213 */ 0xbfb500b3, /* cps = 63104.00, nrm = 32, interval = 5.59 */ | ||
222 | /* 214 */ 0xc00300ac, /* cps = 65664.00, nrm = 32, interval = 5.38 */ | ||
223 | /* 215 */ 0xc02f00a5, /* cps = 68480.00, nrm = 32, interval = 5.16 */ | ||
224 | /* 216 */ 0xc05d009e, /* cps = 71424.00, nrm = 32, interval = 4.94 */ | ||
225 | /* 217 */ 0xc0890098, /* cps = 74240.00, nrm = 32, interval = 4.75 */ | ||
226 | /* 218 */ 0xc0b90092, /* cps = 77312.00, nrm = 32, interval = 4.56 */ | ||
227 | /* 219 */ 0xc0ed008c, /* cps = 80640.00, nrm = 32, interval = 4.38 */ | ||
228 | /* 220 */ 0xc1250086, /* cps = 84224.00, nrm = 32, interval = 4.19 */ | ||
229 | /* 221 */ 0xc1590081, /* cps = 87552.00, nrm = 32, interval = 4.03 */ | ||
230 | /* 222 */ 0xc191007c, /* cps = 91136.00, nrm = 32, interval = 3.88 */ | ||
231 | /* 223 */ 0xc1cd0077, /* cps = 94976.00, nrm = 32, interval = 3.72 */ | ||
232 | /* 224 */ 0xc20d0072, /* cps = 99072.00, nrm = 32, interval = 3.56 */ | ||
233 | /* 225 */ 0xc255006d, /* cps = 103680.00, nrm = 32, interval = 3.41 */ | ||
234 | /* 226 */ 0xc2910069, /* cps = 107520.00, nrm = 32, interval = 3.28 */ | ||
235 | /* 227 */ 0xc2d50065, /* cps = 111872.00, nrm = 32, interval = 3.16 */ | ||
236 | /* 228 */ 0xc32f0060, /* cps = 117632.00, nrm = 32, interval = 3.00 */ | ||
237 | /* 229 */ 0xc36b005d, /* cps = 121472.00, nrm = 32, interval = 2.91 */ | ||
238 | /* 230 */ 0xc3c10059, /* cps = 126976.00, nrm = 32, interval = 2.78 */ | ||
239 | /* 231 */ 0xc40f0055, /* cps = 132864.00, nrm = 32, interval = 2.66 */ | ||
240 | /* 232 */ 0xc4350052, /* cps = 137728.00, nrm = 32, interval = 2.56 */ | ||
241 | /* 233 */ 0xc46d004e, /* cps = 144896.00, nrm = 32, interval = 2.44 */ | ||
242 | /* 234 */ 0xc499004b, /* cps = 150528.00, nrm = 32, interval = 2.34 */ | ||
243 | /* 235 */ 0xc4cb0048, /* cps = 156928.00, nrm = 32, interval = 2.25 */ | ||
244 | /* 236 */ 0xc4ff0045, /* cps = 163584.00, nrm = 32, interval = 2.16 */ | ||
245 | /* 237 */ 0xc5250043, /* cps = 168448.00, nrm = 32, interval = 2.09 */ | ||
246 | /* 238 */ 0xc5630040, /* cps = 176384.00, nrm = 32, interval = 2.00 */ | ||
247 | /* 239 */ 0xc5a7003d, /* cps = 185088.00, nrm = 32, interval = 1.91 */ | ||
248 | /* 240 */ 0xc5d9003b, /* cps = 191488.00, nrm = 32, interval = 1.84 */ | ||
249 | /* 241 */ 0xc6290038, /* cps = 201728.00, nrm = 32, interval = 1.75 */ | ||
250 | /* 242 */ 0xc6630036, /* cps = 209152.00, nrm = 32, interval = 1.69 */ | ||
251 | /* 243 */ 0xc6a30034, /* cps = 217344.00, nrm = 32, interval = 1.62 */ | ||
252 | /* 244 */ 0xc6e70032, /* cps = 226048.00, nrm = 32, interval = 1.56 */ | ||
253 | /* 245 */ 0xc72f0030, /* cps = 235264.00, nrm = 32, interval = 1.50 */ | ||
254 | /* 246 */ 0xc77f002e, /* cps = 245504.00, nrm = 32, interval = 1.44 */ | ||
255 | /* 247 */ 0xc7d7002c, /* cps = 256768.00, nrm = 32, interval = 1.38 */ | ||
256 | /* 248 */ 0xc81b002a, /* cps = 268800.00, nrm = 32, interval = 1.31 */ | ||
257 | /* 249 */ 0xc84f0028, /* cps = 282112.00, nrm = 32, interval = 1.25 */ | ||
258 | /* 250 */ 0xc86d0027, /* cps = 289792.00, nrm = 32, interval = 1.22 */ | ||
259 | /* 251 */ 0xc8a90025, /* cps = 305152.00, nrm = 32, interval = 1.16 */ | ||
260 | /* 252 */ 0xc8cb0024, /* cps = 313856.00, nrm = 32, interval = 1.12 */ | ||
261 | /* 253 */ 0xc9130022, /* cps = 332288.00, nrm = 32, interval = 1.06 */ | ||
262 | /* 254 */ 0xc9390021, /* cps = 342016.00, nrm = 32, interval = 1.03 */ | ||
263 | /* 255 */ 0xc9630020, /* cps = 352768.00, nrm = 32, interval = 1.00 */ | ||
264 | }; | ||
265 | |||
266 | static unsigned char rate_to_log[] = | ||
267 | { | ||
268 | /* 1.00 => 0 */ 0x00, /* => 10.02 */ | ||
269 | /* 1.06 => 0 */ 0x00, /* => 10.02 */ | ||
270 | /* 1.12 => 0 */ 0x00, /* => 10.02 */ | ||
271 | /* 1.19 => 0 */ 0x00, /* => 10.02 */ | ||
272 | /* 1.25 => 0 */ 0x00, /* => 10.02 */ | ||
273 | /* 1.31 => 0 */ 0x00, /* => 10.02 */ | ||
274 | /* 1.38 => 0 */ 0x00, /* => 10.02 */ | ||
275 | /* 1.44 => 0 */ 0x00, /* => 10.02 */ | ||
276 | /* 1.50 => 0 */ 0x00, /* => 10.02 */ | ||
277 | /* 1.56 => 0 */ 0x00, /* => 10.02 */ | ||
278 | /* 1.62 => 0 */ 0x00, /* => 10.02 */ | ||
279 | /* 1.69 => 0 */ 0x00, /* => 10.02 */ | ||
280 | /* 1.75 => 0 */ 0x00, /* => 10.02 */ | ||
281 | /* 1.81 => 0 */ 0x00, /* => 10.02 */ | ||
282 | /* 1.88 => 0 */ 0x00, /* => 10.02 */ | ||
283 | /* 1.94 => 0 */ 0x00, /* => 10.02 */ | ||
284 | /* 2.00 => 0 */ 0x00, /* => 10.02 */ | ||
285 | /* 2.12 => 0 */ 0x00, /* => 10.02 */ | ||
286 | /* 2.25 => 0 */ 0x00, /* => 10.02 */ | ||
287 | /* 2.38 => 0 */ 0x00, /* => 10.02 */ | ||
288 | /* 2.50 => 0 */ 0x00, /* => 10.02 */ | ||
289 | /* 2.62 => 0 */ 0x00, /* => 10.02 */ | ||
290 | /* 2.75 => 0 */ 0x00, /* => 10.02 */ | ||
291 | /* 2.88 => 0 */ 0x00, /* => 10.02 */ | ||
292 | /* 3.00 => 0 */ 0x00, /* => 10.02 */ | ||
293 | /* 3.12 => 0 */ 0x00, /* => 10.02 */ | ||
294 | /* 3.25 => 0 */ 0x00, /* => 10.02 */ | ||
295 | /* 3.38 => 0 */ 0x00, /* => 10.02 */ | ||
296 | /* 3.50 => 0 */ 0x00, /* => 10.02 */ | ||
297 | /* 3.62 => 0 */ 0x00, /* => 10.02 */ | ||
298 | /* 3.75 => 0 */ 0x00, /* => 10.02 */ | ||
299 | /* 3.88 => 0 */ 0x00, /* => 10.02 */ | ||
300 | /* 4.00 => 0 */ 0x00, /* => 10.02 */ | ||
301 | /* 4.25 => 0 */ 0x00, /* => 10.02 */ | ||
302 | /* 4.50 => 0 */ 0x00, /* => 10.02 */ | ||
303 | /* 4.75 => 0 */ 0x00, /* => 10.02 */ | ||
304 | /* 5.00 => 0 */ 0x00, /* => 10.02 */ | ||
305 | /* 5.25 => 0 */ 0x00, /* => 10.02 */ | ||
306 | /* 5.50 => 0 */ 0x00, /* => 10.02 */ | ||
307 | /* 5.75 => 0 */ 0x00, /* => 10.02 */ | ||
308 | /* 6.00 => 0 */ 0x00, /* => 10.02 */ | ||
309 | /* 6.25 => 0 */ 0x00, /* => 10.02 */ | ||
310 | /* 6.50 => 0 */ 0x00, /* => 10.02 */ | ||
311 | /* 6.75 => 0 */ 0x00, /* => 10.02 */ | ||
312 | /* 7.00 => 0 */ 0x00, /* => 10.02 */ | ||
313 | /* 7.25 => 0 */ 0x00, /* => 10.02 */ | ||
314 | /* 7.50 => 0 */ 0x00, /* => 10.02 */ | ||
315 | /* 7.75 => 0 */ 0x00, /* => 10.02 */ | ||
316 | /* 8.00 => 0 */ 0x00, /* => 10.02 */ | ||
317 | /* 8.50 => 0 */ 0x00, /* => 10.02 */ | ||
318 | /* 9.00 => 0 */ 0x00, /* => 10.02 */ | ||
319 | /* 9.50 => 0 */ 0x00, /* => 10.02 */ | ||
320 | /* 10.00 => 0 */ 0x00, /* => 10.02 */ | ||
321 | /* 10.50 => 1 */ 0x01, /* => 10.42 */ | ||
322 | /* 11.00 => 2 */ 0x02, /* => 10.86 */ | ||
323 | /* 11.50 => 3 */ 0x03, /* => 11.31 */ | ||
324 | /* 12.00 => 4 */ 0x04, /* => 11.78 */ | ||
325 | /* 12.50 => 5 */ 0x05, /* => 12.28 */ | ||
326 | /* 13.00 => 6 */ 0x06, /* => 12.80 */ | ||
327 | /* 13.50 => 7 */ 0x07, /* => 13.33 */ | ||
328 | /* 14.00 => 8 */ 0x08, /* => 13.89 */ | ||
329 | /* 14.50 => 9 */ 0x09, /* => 14.48 */ | ||
330 | /* 15.00 => 9 */ 0x09, /* => 14.48 */ | ||
331 | /* 15.50 => 10 */ 0x0a, /* => 15.08 */ | ||
332 | /* 16.00 => 11 */ 0x0b, /* => 15.72 */ | ||
333 | /* 17.00 => 12 */ 0x0c, /* => 16.38 */ | ||
334 | /* 18.00 => 14 */ 0x0e, /* => 17.75 */ | ||
335 | /* 19.00 => 15 */ 0x0f, /* => 18.50 */ | ||
336 | /* 20.00 => 16 */ 0x10, /* => 19.28 */ | ||
337 | /* 21.00 => 18 */ 0x12, /* => 20.94 */ | ||
338 | /* 22.00 => 19 */ 0x13, /* => 21.81 */ | ||
339 | /* 23.00 => 20 */ 0x14, /* => 22.75 */ | ||
340 | /* 24.00 => 21 */ 0x15, /* => 23.69 */ | ||
341 | /* 25.00 => 22 */ 0x16, /* => 24.69 */ | ||
342 | /* 26.00 => 23 */ 0x17, /* => 25.72 */ | ||
343 | /* 27.00 => 24 */ 0x18, /* => 26.81 */ | ||
344 | /* 28.00 => 25 */ 0x19, /* => 27.94 */ | ||
345 | /* 29.00 => 25 */ 0x19, /* => 27.94 */ | ||
346 | /* 30.00 => 26 */ 0x1a, /* => 29.09 */ | ||
347 | /* 31.00 => 27 */ 0x1b, /* => 30.31 */ | ||
348 | /* 32.00 => 28 */ 0x1c, /* => 31.56 */ | ||
349 | /* 34.00 => 29 */ 0x1d, /* => 32.94 */ | ||
350 | /* 36.00 => 31 */ 0x1f, /* => 35.69 */ | ||
351 | /* 38.00 => 32 */ 0x20, /* => 37.19 */ | ||
352 | /* 40.00 => 33 */ 0x21, /* => 38.75 */ | ||
353 | /* 42.00 => 34 */ 0x22, /* => 40.38 */ | ||
354 | /* 44.00 => 36 */ 0x24, /* => 43.88 */ | ||
355 | /* 46.00 => 37 */ 0x25, /* => 45.69 */ | ||
356 | /* 48.00 => 38 */ 0x26, /* => 47.62 */ | ||
357 | /* 50.00 => 39 */ 0x27, /* => 49.62 */ | ||
358 | /* 52.00 => 40 */ 0x28, /* => 51.69 */ | ||
359 | /* 54.00 => 41 */ 0x29, /* => 53.88 */ | ||
360 | /* 56.00 => 41 */ 0x29, /* => 53.88 */ | ||
361 | /* 58.00 => 42 */ 0x2a, /* => 56.12 */ | ||
362 | /* 60.00 => 43 */ 0x2b, /* => 58.44 */ | ||
363 | /* 62.00 => 44 */ 0x2c, /* => 60.94 */ | ||
364 | /* 64.00 => 45 */ 0x2d, /* => 63.50 */ | ||
365 | /* 68.00 => 46 */ 0x2e, /* => 66.12 */ | ||
366 | /* 72.00 => 48 */ 0x30, /* => 71.88 */ | ||
367 | /* 76.00 => 49 */ 0x31, /* => 74.75 */ | ||
368 | /* 80.00 => 50 */ 0x32, /* => 78.00 */ | ||
369 | /* 84.00 => 51 */ 0x33, /* => 81.25 */ | ||
370 | /* 88.00 => 52 */ 0x34, /* => 84.62 */ | ||
371 | /* 92.00 => 54 */ 0x36, /* => 91.88 */ | ||
372 | /* 96.00 => 55 */ 0x37, /* => 95.75 */ | ||
373 | /* 100.00 => 56 */ 0x38, /* => 99.75 */ | ||
374 | /* 104.00 => 56 */ 0x38, /* => 99.75 */ | ||
375 | /* 108.00 => 57 */ 0x39, /* => 104.00 */ | ||
376 | /* 112.00 => 58 */ 0x3a, /* => 108.25 */ | ||
377 | /* 116.00 => 59 */ 0x3b, /* => 112.88 */ | ||
378 | /* 120.00 => 60 */ 0x3c, /* => 117.50 */ | ||
379 | /* 124.00 => 61 */ 0x3d, /* => 122.38 */ | ||
380 | /* 128.00 => 62 */ 0x3e, /* => 127.50 */ | ||
381 | /* 136.00 => 63 */ 0x3f, /* => 132.75 */ | ||
382 | /* 144.00 => 64 */ 0x40, /* => 138.50 */ | ||
383 | /* 152.00 => 66 */ 0x42, /* => 150.25 */ | ||
384 | /* 160.00 => 67 */ 0x43, /* => 156.75 */ | ||
385 | /* 168.00 => 68 */ 0x44, /* => 163.50 */ | ||
386 | /* 176.00 => 69 */ 0x45, /* => 170.00 */ | ||
387 | /* 184.00 => 70 */ 0x46, /* => 177.25 */ | ||
388 | /* 192.00 => 71 */ 0x47, /* => 184.50 */ | ||
389 | /* 200.00 => 72 */ 0x48, /* => 192.25 */ | ||
390 | /* 208.00 => 73 */ 0x49, /* => 200.25 */ | ||
391 | /* 216.00 => 74 */ 0x4a, /* => 208.75 */ | ||
392 | /* 224.00 => 75 */ 0x4b, /* => 217.75 */ | ||
393 | /* 232.00 => 76 */ 0x4c, /* => 226.75 */ | ||
394 | /* 240.00 => 77 */ 0x4d, /* => 236.25 */ | ||
395 | /* 248.00 => 78 */ 0x4e, /* => 246.25 */ | ||
396 | /* 256.00 => 78 */ 0x4e, /* => 246.25 */ | ||
397 | /* 272.00 => 80 */ 0x50, /* => 267.50 */ | ||
398 | /* 288.00 => 81 */ 0x51, /* => 278.50 */ | ||
399 | /* 304.00 => 83 */ 0x53, /* => 302.00 */ | ||
400 | /* 320.00 => 84 */ 0x54, /* => 315.00 */ | ||
401 | /* 336.00 => 85 */ 0x55, /* => 328.00 */ | ||
402 | /* 352.00 => 86 */ 0x56, /* => 342.00 */ | ||
403 | /* 368.00 => 87 */ 0x57, /* => 356.00 */ | ||
404 | /* 384.00 => 88 */ 0x58, /* => 371.00 */ | ||
405 | /* 400.00 => 89 */ 0x59, /* => 386.50 */ | ||
406 | /* 416.00 => 90 */ 0x5a, /* => 403.00 */ | ||
407 | /* 432.00 => 91 */ 0x5b, /* => 419.50 */ | ||
408 | /* 448.00 => 92 */ 0x5c, /* => 437.50 */ | ||
409 | /* 464.00 => 93 */ 0x5d, /* => 455.50 */ | ||
410 | /* 480.00 => 94 */ 0x5e, /* => 475.00 */ | ||
411 | /* 496.00 => 95 */ 0x5f, /* => 495.00 */ | ||
412 | /* 512.00 => 95 */ 0x5f, /* => 495.00 */ | ||
413 | /* 544.00 => 97 */ 0x61, /* => 537.00 */ | ||
414 | /* 576.00 => 98 */ 0x62, /* => 559.00 */ | ||
415 | /* 608.00 => 100 */ 0x64, /* => 607.00 */ | ||
416 | /* 640.00 => 101 */ 0x65, /* => 632.00 */ | ||
417 | /* 672.00 => 102 */ 0x66, /* => 660.00 */ | ||
418 | /* 704.00 => 103 */ 0x67, /* => 687.00 */ | ||
419 | /* 736.00 => 104 */ 0x68, /* => 716.00 */ | ||
420 | /* 768.00 => 105 */ 0x69, /* => 746.00 */ | ||
421 | /* 800.00 => 106 */ 0x6a, /* => 777.00 */ | ||
422 | /* 832.00 => 107 */ 0x6b, /* => 810.00 */ | ||
423 | /* 864.00 => 108 */ 0x6c, /* => 843.00 */ | ||
424 | /* 896.00 => 109 */ 0x6d, /* => 879.00 */ | ||
425 | /* 928.00 => 110 */ 0x6e, /* => 916.00 */ | ||
426 | /* 960.00 => 111 */ 0x6f, /* => 954.00 */ | ||
427 | /* 992.00 => 111 */ 0x6f, /* => 954.00 */ | ||
428 | /* 1024.00 => 112 */ 0x70, /* => 994.00 */ | ||
429 | /* 1088.00 => 114 */ 0x72, /* => 1080.00 */ | ||
430 | /* 1152.00 => 115 */ 0x73, /* => 1124.00 */ | ||
431 | /* 1216.00 => 116 */ 0x74, /* => 1172.00 */ | ||
432 | /* 1280.00 => 118 */ 0x76, /* => 1272.00 */ | ||
433 | /* 1344.00 => 119 */ 0x77, /* => 1326.00 */ | ||
434 | /* 1408.00 => 120 */ 0x78, /* => 1382.00 */ | ||
435 | /* 1472.00 => 121 */ 0x79, /* => 1440.00 */ | ||
436 | /* 1536.00 => 122 */ 0x7a, /* => 1498.00 */ | ||
437 | /* 1600.00 => 123 */ 0x7b, /* => 1562.00 */ | ||
438 | /* 1664.00 => 124 */ 0x7c, /* => 1628.00 */ | ||
439 | /* 1728.00 => 125 */ 0x7d, /* => 1696.00 */ | ||
440 | /* 1792.00 => 126 */ 0x7e, /* => 1768.00 */ | ||
441 | /* 1856.00 => 127 */ 0x7f, /* => 1842.00 */ | ||
442 | /* 1920.00 => 128 */ 0x80, /* => 1918.00 */ | ||
443 | /* 1984.00 => 128 */ 0x80, /* => 1918.00 */ | ||
444 | /* 2048.00 => 129 */ 0x81, /* => 2000.00 */ | ||
445 | /* 2176.00 => 131 */ 0x83, /* => 2168.00 */ | ||
446 | /* 2304.00 => 132 */ 0x84, /* => 2264.00 */ | ||
447 | /* 2432.00 => 133 */ 0x85, /* => 2356.00 */ | ||
448 | /* 2560.00 => 135 */ 0x87, /* => 2556.00 */ | ||
449 | /* 2688.00 => 136 */ 0x88, /* => 2664.00 */ | ||
450 | /* 2816.00 => 137 */ 0x89, /* => 2776.00 */ | ||
451 | /* 2944.00 => 138 */ 0x8a, /* => 2892.00 */ | ||
452 | /* 3072.00 => 139 */ 0x8b, /* => 3012.00 */ | ||
453 | /* 3200.00 => 140 */ 0x8c, /* => 3140.00 */ | ||
454 | /* 3328.00 => 141 */ 0x8d, /* => 3272.00 */ | ||
455 | /* 3456.00 => 142 */ 0x8e, /* => 3412.00 */ | ||
456 | /* 3584.00 => 143 */ 0x8f, /* => 3552.00 */ | ||
457 | /* 3712.00 => 144 */ 0x90, /* => 3700.00 */ | ||
458 | /* 3840.00 => 144 */ 0x90, /* => 3700.00 */ | ||
459 | /* 3968.00 => 145 */ 0x91, /* => 3860.00 */ | ||
460 | /* 4096.00 => 146 */ 0x92, /* => 4016.00 */ | ||
461 | /* 4352.00 => 147 */ 0x93, /* => 4184.00 */ | ||
462 | /* 4608.00 => 149 */ 0x95, /* => 4544.00 */ | ||
463 | /* 4864.00 => 150 */ 0x96, /* => 4736.00 */ | ||
464 | /* 5120.00 => 151 */ 0x97, /* => 4936.00 */ | ||
465 | /* 5376.00 => 153 */ 0x99, /* => 5360.00 */ | ||
466 | /* 5632.00 => 154 */ 0x9a, /* => 5584.00 */ | ||
467 | /* 5888.00 => 155 */ 0x9b, /* => 5816.00 */ | ||
468 | /* 6144.00 => 156 */ 0x9c, /* => 6056.00 */ | ||
469 | /* 6400.00 => 157 */ 0x9d, /* => 6312.00 */ | ||
470 | /* 6656.00 => 158 */ 0x9e, /* => 6576.00 */ | ||
471 | /* 6912.00 => 159 */ 0x9f, /* => 6856.00 */ | ||
472 | /* 7168.00 => 160 */ 0xa0, /* => 7144.00 */ | ||
473 | /* 7424.00 => 160 */ 0xa0, /* => 7144.00 */ | ||
474 | /* 7680.00 => 161 */ 0xa1, /* => 7440.00 */ | ||
475 | /* 7936.00 => 162 */ 0xa2, /* => 7752.00 */ | ||
476 | /* 8192.00 => 163 */ 0xa3, /* => 8080.00 */ | ||
477 | /* 8704.00 => 164 */ 0xa4, /* => 8416.00 */ | ||
478 | /* 9216.00 => 166 */ 0xa6, /* => 9136.00 */ | ||
479 | /* 9728.00 => 167 */ 0xa7, /* => 9520.00 */ | ||
480 | /* 10240.00 => 168 */ 0xa8, /* => 9920.00 */ | ||
481 | /* 10752.00 => 169 */ 0xa9, /* => 10336.00 */ | ||
482 | /* 11264.00 => 171 */ 0xab, /* => 11216.00 */ | ||
483 | /* 11776.00 => 172 */ 0xac, /* => 11680.00 */ | ||
484 | /* 12288.00 => 173 */ 0xad, /* => 12176.00 */ | ||
485 | /* 12800.00 => 174 */ 0xae, /* => 12688.00 */ | ||
486 | /* 13312.00 => 175 */ 0xaf, /* => 13216.00 */ | ||
487 | /* 13824.00 => 176 */ 0xb0, /* => 13776.00 */ | ||
488 | /* 14336.00 => 176 */ 0xb0, /* => 13776.00 */ | ||
489 | /* 14848.00 => 177 */ 0xb1, /* => 14352.00 */ | ||
490 | /* 15360.00 => 178 */ 0xb2, /* => 14960.00 */ | ||
491 | /* 15872.00 => 179 */ 0xb3, /* => 15584.00 */ | ||
492 | /* 16384.00 => 180 */ 0xb4, /* => 16224.00 */ | ||
493 | /* 17408.00 => 181 */ 0xb5, /* => 16896.00 */ | ||
494 | /* 18432.00 => 183 */ 0xb7, /* => 18368.00 */ | ||
495 | /* 19456.00 => 184 */ 0xb8, /* => 19136.00 */ | ||
496 | /* 20480.00 => 185 */ 0xb9, /* => 19904.00 */ | ||
497 | /* 21504.00 => 186 */ 0xba, /* => 20768.00 */ | ||
498 | /* 22528.00 => 187 */ 0xbb, /* => 21632.00 */ | ||
499 | /* 23552.00 => 189 */ 0xbd, /* => 23488.00 */ | ||
500 | /* 24576.00 => 190 */ 0xbe, /* => 24512.00 */ | ||
501 | /* 25600.00 => 191 */ 0xbf, /* => 25504.00 */ | ||
502 | /* 26624.00 => 192 */ 0xc0, /* => 26592.00 */ | ||
503 | /* 27648.00 => 192 */ 0xc0, /* => 26592.00 */ | ||
504 | /* 28672.00 => 193 */ 0xc1, /* => 27680.00 */ | ||
505 | /* 29696.00 => 194 */ 0xc2, /* => 28896.00 */ | ||
506 | /* 30720.00 => 195 */ 0xc3, /* => 30048.00 */ | ||
507 | /* 31744.00 => 196 */ 0xc4, /* => 31392.00 */ | ||
508 | /* 32768.00 => 197 */ 0xc5, /* => 32640.00 */ | ||
509 | /* 34816.00 => 198 */ 0xc6, /* => 33984.00 */ | ||
510 | /* 36864.00 => 199 */ 0xc7, /* => 35392.00 */ | ||
511 | /* 38912.00 => 201 */ 0xc9, /* => 38528.00 */ | ||
512 | /* 40960.00 => 202 */ 0xca, /* => 40064.00 */ | ||
513 | /* 43008.00 => 203 */ 0xcb, /* => 41856.00 */ | ||
514 | /* 45056.00 => 204 */ 0xcc, /* => 43584.00 */ | ||
515 | /* 47104.00 => 205 */ 0xcd, /* => 45376.00 */ | ||
516 | /* 49152.00 => 206 */ 0xce, /* => 47232.00 */ | ||
517 | /* 51200.00 => 207 */ 0xcf, /* => 49344.00 */ | ||
518 | /* 53248.00 => 208 */ 0xd0, /* => 51328.00 */ | ||
519 | /* 55296.00 => 209 */ 0xd1, /* => 53504.00 */ | ||
520 | /* 57344.00 => 210 */ 0xd2, /* => 55616.00 */ | ||
521 | /* 59392.00 => 211 */ 0xd3, /* => 58240.00 */ | ||
522 | /* 61440.00 => 212 */ 0xd4, /* => 60416.00 */ | ||
523 | /* 63488.00 => 213 */ 0xd5, /* => 63104.00 */ | ||
524 | /* 65536.00 => 213 */ 0xd5, /* => 63104.00 */ | ||
525 | /* 69632.00 => 215 */ 0xd7, /* => 68480.00 */ | ||
526 | /* 73728.00 => 216 */ 0xd8, /* => 71424.00 */ | ||
527 | /* 77824.00 => 218 */ 0xda, /* => 77312.00 */ | ||
528 | /* 81920.00 => 219 */ 0xdb, /* => 80640.00 */ | ||
529 | /* 86016.00 => 220 */ 0xdc, /* => 84224.00 */ | ||
530 | /* 90112.00 => 221 */ 0xdd, /* => 87552.00 */ | ||
531 | /* 94208.00 => 222 */ 0xde, /* => 91136.00 */ | ||
532 | /* 98304.00 => 223 */ 0xdf, /* => 94976.00 */ | ||
533 | /* 102400.00 => 224 */ 0xe0, /* => 99072.00 */ | ||
534 | /* 106496.00 => 225 */ 0xe1, /* => 103680.00 */ | ||
535 | /* 110592.00 => 226 */ 0xe2, /* => 107520.00 */ | ||
536 | /* 114688.00 => 227 */ 0xe3, /* => 111872.00 */ | ||
537 | /* 118784.00 => 228 */ 0xe4, /* => 117632.00 */ | ||
538 | /* 122880.00 => 229 */ 0xe5, /* => 121472.00 */ | ||
539 | /* 126976.00 => 229 */ 0xe5, /* => 121472.00 */ | ||
540 | /* 131072.00 => 230 */ 0xe6, /* => 126976.00 */ | ||
541 | /* 139264.00 => 232 */ 0xe8, /* => 137728.00 */ | ||
542 | /* 147456.00 => 233 */ 0xe9, /* => 144896.00 */ | ||
543 | /* 155648.00 => 234 */ 0xea, /* => 150528.00 */ | ||
544 | /* 163840.00 => 236 */ 0xec, /* => 163584.00 */ | ||
545 | /* 172032.00 => 237 */ 0xed, /* => 168448.00 */ | ||
546 | /* 180224.00 => 238 */ 0xee, /* => 176384.00 */ | ||
547 | /* 188416.00 => 239 */ 0xef, /* => 185088.00 */ | ||
548 | /* 196608.00 => 240 */ 0xf0, /* => 191488.00 */ | ||
549 | /* 204800.00 => 241 */ 0xf1, /* => 201728.00 */ | ||
550 | /* 212992.00 => 242 */ 0xf2, /* => 209152.00 */ | ||
551 | /* 221184.00 => 243 */ 0xf3, /* => 217344.00 */ | ||
552 | /* 229376.00 => 244 */ 0xf4, /* => 226048.00 */ | ||
553 | /* 237568.00 => 245 */ 0xf5, /* => 235264.00 */ | ||
554 | /* 245760.00 => 246 */ 0xf6, /* => 245504.00 */ | ||
555 | /* 253952.00 => 246 */ 0xf6, /* => 245504.00 */ | ||
556 | /* 262144.00 => 247 */ 0xf7, /* => 256768.00 */ | ||
557 | /* 278528.00 => 248 */ 0xf8, /* => 268800.00 */ | ||
558 | /* 294912.00 => 250 */ 0xfa, /* => 289792.00 */ | ||
559 | /* 311296.00 => 251 */ 0xfb, /* => 305152.00 */ | ||
560 | /* 327680.00 => 252 */ 0xfc, /* => 313856.00 */ | ||
561 | /* 344064.00 => 254 */ 0xfe, /* => 342016.00 */ | ||
562 | /* 360448.00 => 255 */ 0xff, /* => 352768.00 */ | ||
563 | /* 376832.00 => 255 */ 0xff, /* => 352768.00 */ | ||
564 | /* 393216.00 => 255 */ 0xff, /* => 352768.00 */ | ||
565 | /* 409600.00 => 255 */ 0xff, /* => 352768.00 */ | ||
566 | /* 425984.00 => 255 */ 0xff, /* => 352768.00 */ | ||
567 | /* 442368.00 => 255 */ 0xff, /* => 352768.00 */ | ||
568 | /* 458752.00 => 255 */ 0xff, /* => 352768.00 */ | ||
569 | /* 475136.00 => 255 */ 0xff, /* => 352768.00 */ | ||
570 | /* 491520.00 => 255 */ 0xff, /* => 352768.00 */ | ||
571 | /* 507904.00 => 255 */ 0xff, /* => 352768.00 */ | ||
572 | /* 524288.00 => 255 */ 0xff, /* => 352768.00 */ | ||
573 | /* 557056.00 => 255 */ 0xff, /* => 352768.00 */ | ||
574 | /* 589824.00 => 255 */ 0xff, /* => 352768.00 */ | ||
575 | /* 622592.00 => 255 */ 0xff, /* => 352768.00 */ | ||
576 | /* 655360.00 => 255 */ 0xff, /* => 352768.00 */ | ||
577 | /* 688128.00 => 255 */ 0xff, /* => 352768.00 */ | ||
578 | /* 720896.00 => 255 */ 0xff, /* => 352768.00 */ | ||
579 | /* 753664.00 => 255 */ 0xff, /* => 352768.00 */ | ||
580 | /* 786432.00 => 255 */ 0xff, /* => 352768.00 */ | ||
581 | /* 819200.00 => 255 */ 0xff, /* => 352768.00 */ | ||
582 | /* 851968.00 => 255 */ 0xff, /* => 352768.00 */ | ||
583 | /* 884736.00 => 255 */ 0xff, /* => 352768.00 */ | ||
584 | /* 917504.00 => 255 */ 0xff, /* => 352768.00 */ | ||
585 | /* 950272.00 => 255 */ 0xff, /* => 352768.00 */ | ||
586 | /* 983040.00 => 255 */ 0xff, /* => 352768.00 */ | ||
587 | /* 1015808.00 => 255 */ 0xff, /* => 352768.00 */ | ||
588 | /* 1048576.00 => 255 */ 0xff, /* => 352768.00 */ | ||
589 | /* 1114112.00 => 255 */ 0xff, /* => 352768.00 */ | ||
590 | /* 1179648.00 => 255 */ 0xff, /* => 352768.00 */ | ||
591 | /* 1245184.00 => 255 */ 0xff, /* => 352768.00 */ | ||
592 | /* 1310720.00 => 255 */ 0xff, /* => 352768.00 */ | ||
593 | /* 1376256.00 => 255 */ 0xff, /* => 352768.00 */ | ||
594 | /* 1441792.00 => 255 */ 0xff, /* => 352768.00 */ | ||
595 | /* 1507328.00 => 255 */ 0xff, /* => 352768.00 */ | ||
596 | /* 1572864.00 => 255 */ 0xff, /* => 352768.00 */ | ||
597 | /* 1638400.00 => 255 */ 0xff, /* => 352768.00 */ | ||
598 | /* 1703936.00 => 255 */ 0xff, /* => 352768.00 */ | ||
599 | /* 1769472.00 => 255 */ 0xff, /* => 352768.00 */ | ||
600 | /* 1835008.00 => 255 */ 0xff, /* => 352768.00 */ | ||
601 | /* 1900544.00 => 255 */ 0xff, /* => 352768.00 */ | ||
602 | /* 1966080.00 => 255 */ 0xff, /* => 352768.00 */ | ||
603 | /* 2031616.00 => 255 */ 0xff, /* => 352768.00 */ | ||
604 | /* 2097152.00 => 255 */ 0xff, /* => 352768.00 */ | ||
605 | /* 2228224.00 => 255 */ 0xff, /* => 352768.00 */ | ||
606 | /* 2359296.00 => 255 */ 0xff, /* => 352768.00 */ | ||
607 | /* 2490368.00 => 255 */ 0xff, /* => 352768.00 */ | ||
608 | /* 2621440.00 => 255 */ 0xff, /* => 352768.00 */ | ||
609 | /* 2752512.00 => 255 */ 0xff, /* => 352768.00 */ | ||
610 | /* 2883584.00 => 255 */ 0xff, /* => 352768.00 */ | ||
611 | /* 3014656.00 => 255 */ 0xff, /* => 352768.00 */ | ||
612 | /* 3145728.00 => 255 */ 0xff, /* => 352768.00 */ | ||
613 | /* 3276800.00 => 255 */ 0xff, /* => 352768.00 */ | ||
614 | /* 3407872.00 => 255 */ 0xff, /* => 352768.00 */ | ||
615 | /* 3538944.00 => 255 */ 0xff, /* => 352768.00 */ | ||
616 | /* 3670016.00 => 255 */ 0xff, /* => 352768.00 */ | ||
617 | /* 3801088.00 => 255 */ 0xff, /* => 352768.00 */ | ||
618 | /* 3932160.00 => 255 */ 0xff, /* => 352768.00 */ | ||
619 | /* 4063232.00 => 255 */ 0xff, /* => 352768.00 */ | ||
620 | /* 4194304.00 => 255 */ 0xff, /* => 352768.00 */ | ||
621 | /* 4456448.00 => 255 */ 0xff, /* => 352768.00 */ | ||
622 | /* 4718592.00 => 255 */ 0xff, /* => 352768.00 */ | ||
623 | /* 4980736.00 => 255 */ 0xff, /* => 352768.00 */ | ||
624 | /* 5242880.00 => 255 */ 0xff, /* => 352768.00 */ | ||
625 | /* 5505024.00 => 255 */ 0xff, /* => 352768.00 */ | ||
626 | /* 5767168.00 => 255 */ 0xff, /* => 352768.00 */ | ||
627 | /* 6029312.00 => 255 */ 0xff, /* => 352768.00 */ | ||
628 | /* 6291456.00 => 255 */ 0xff, /* => 352768.00 */ | ||
629 | /* 6553600.00 => 255 */ 0xff, /* => 352768.00 */ | ||
630 | /* 6815744.00 => 255 */ 0xff, /* => 352768.00 */ | ||
631 | /* 7077888.00 => 255 */ 0xff, /* => 352768.00 */ | ||
632 | /* 7340032.00 => 255 */ 0xff, /* => 352768.00 */ | ||
633 | /* 7602176.00 => 255 */ 0xff, /* => 352768.00 */ | ||
634 | /* 7864320.00 => 255 */ 0xff, /* => 352768.00 */ | ||
635 | /* 8126464.00 => 255 */ 0xff, /* => 352768.00 */ | ||
636 | /* 8388608.00 => 255 */ 0xff, /* => 352768.00 */ | ||
637 | /* 8912896.00 => 255 */ 0xff, /* => 352768.00 */ | ||
638 | /* 9437184.00 => 255 */ 0xff, /* => 352768.00 */ | ||
639 | /* 9961472.00 => 255 */ 0xff, /* => 352768.00 */ | ||
640 | /* 10485760.00 => 255 */ 0xff, /* => 352768.00 */ | ||
641 | /* 11010048.00 => 255 */ 0xff, /* => 352768.00 */ | ||
642 | /* 11534336.00 => 255 */ 0xff, /* => 352768.00 */ | ||
643 | /* 12058624.00 => 255 */ 0xff, /* => 352768.00 */ | ||
644 | /* 12582912.00 => 255 */ 0xff, /* => 352768.00 */ | ||
645 | /* 13107200.00 => 255 */ 0xff, /* => 352768.00 */ | ||
646 | /* 13631488.00 => 255 */ 0xff, /* => 352768.00 */ | ||
647 | /* 14155776.00 => 255 */ 0xff, /* => 352768.00 */ | ||
648 | /* 14680064.00 => 255 */ 0xff, /* => 352768.00 */ | ||
649 | /* 15204352.00 => 255 */ 0xff, /* => 352768.00 */ | ||
650 | /* 15728640.00 => 255 */ 0xff, /* => 352768.00 */ | ||
651 | /* 16252928.00 => 255 */ 0xff, /* => 352768.00 */ | ||
652 | /* 16777216.00 => 255 */ 0xff, /* => 352768.00 */ | ||
653 | /* 17825792.00 => 255 */ 0xff, /* => 352768.00 */ | ||
654 | /* 18874368.00 => 255 */ 0xff, /* => 352768.00 */ | ||
655 | /* 19922944.00 => 255 */ 0xff, /* => 352768.00 */ | ||
656 | /* 20971520.00 => 255 */ 0xff, /* => 352768.00 */ | ||
657 | /* 22020096.00 => 255 */ 0xff, /* => 352768.00 */ | ||
658 | /* 23068672.00 => 255 */ 0xff, /* => 352768.00 */ | ||
659 | /* 24117248.00 => 255 */ 0xff, /* => 352768.00 */ | ||
660 | /* 25165824.00 => 255 */ 0xff, /* => 352768.00 */ | ||
661 | /* 26214400.00 => 255 */ 0xff, /* => 352768.00 */ | ||
662 | /* 27262976.00 => 255 */ 0xff, /* => 352768.00 */ | ||
663 | /* 28311552.00 => 255 */ 0xff, /* => 352768.00 */ | ||
664 | /* 29360128.00 => 255 */ 0xff, /* => 352768.00 */ | ||
665 | /* 30408704.00 => 255 */ 0xff, /* => 352768.00 */ | ||
666 | /* 31457280.00 => 255 */ 0xff, /* => 352768.00 */ | ||
667 | /* 32505856.00 => 255 */ 0xff, /* => 352768.00 */ | ||
668 | /* 33554432.00 => 255 */ 0xff, /* => 352768.00 */ | ||
669 | /* 35651584.00 => 255 */ 0xff, /* => 352768.00 */ | ||
670 | /* 37748736.00 => 255 */ 0xff, /* => 352768.00 */ | ||
671 | /* 39845888.00 => 255 */ 0xff, /* => 352768.00 */ | ||
672 | /* 41943040.00 => 255 */ 0xff, /* => 352768.00 */ | ||
673 | /* 44040192.00 => 255 */ 0xff, /* => 352768.00 */ | ||
674 | /* 46137344.00 => 255 */ 0xff, /* => 352768.00 */ | ||
675 | /* 48234496.00 => 255 */ 0xff, /* => 352768.00 */ | ||
676 | /* 50331648.00 => 255 */ 0xff, /* => 352768.00 */ | ||
677 | /* 52428800.00 => 255 */ 0xff, /* => 352768.00 */ | ||
678 | /* 54525952.00 => 255 */ 0xff, /* => 352768.00 */ | ||
679 | /* 56623104.00 => 255 */ 0xff, /* => 352768.00 */ | ||
680 | /* 58720256.00 => 255 */ 0xff, /* => 352768.00 */ | ||
681 | /* 60817408.00 => 255 */ 0xff, /* => 352768.00 */ | ||
682 | /* 62914560.00 => 255 */ 0xff, /* => 352768.00 */ | ||
683 | /* 65011712.00 => 255 */ 0xff, /* => 352768.00 */ | ||
684 | /* 67108864.00 => 255 */ 0xff, /* => 352768.00 */ | ||
685 | /* 71303168.00 => 255 */ 0xff, /* => 352768.00 */ | ||
686 | /* 75497472.00 => 255 */ 0xff, /* => 352768.00 */ | ||
687 | /* 79691776.00 => 255 */ 0xff, /* => 352768.00 */ | ||
688 | /* 83886080.00 => 255 */ 0xff, /* => 352768.00 */ | ||
689 | /* 88080384.00 => 255 */ 0xff, /* => 352768.00 */ | ||
690 | /* 92274688.00 => 255 */ 0xff, /* => 352768.00 */ | ||
691 | /* 96468992.00 => 255 */ 0xff, /* => 352768.00 */ | ||
692 | /* 100663296.00 => 255 */ 0xff, /* => 352768.00 */ | ||
693 | /* 104857600.00 => 255 */ 0xff, /* => 352768.00 */ | ||
694 | /* 109051904.00 => 255 */ 0xff, /* => 352768.00 */ | ||
695 | /* 113246208.00 => 255 */ 0xff, /* => 352768.00 */ | ||
696 | /* 117440512.00 => 255 */ 0xff, /* => 352768.00 */ | ||
697 | /* 121634816.00 => 255 */ 0xff, /* => 352768.00 */ | ||
698 | /* 125829120.00 => 255 */ 0xff, /* => 352768.00 */ | ||
699 | /* 130023424.00 => 255 */ 0xff, /* => 352768.00 */ | ||
700 | /* 134217728.00 => 255 */ 0xff, /* => 352768.00 */ | ||
701 | /* 142606336.00 => 255 */ 0xff, /* => 352768.00 */ | ||
702 | /* 150994944.00 => 255 */ 0xff, /* => 352768.00 */ | ||
703 | /* 159383552.00 => 255 */ 0xff, /* => 352768.00 */ | ||
704 | /* 167772160.00 => 255 */ 0xff, /* => 352768.00 */ | ||
705 | /* 176160768.00 => 255 */ 0xff, /* => 352768.00 */ | ||
706 | /* 184549376.00 => 255 */ 0xff, /* => 352768.00 */ | ||
707 | /* 192937984.00 => 255 */ 0xff, /* => 352768.00 */ | ||
708 | /* 201326592.00 => 255 */ 0xff, /* => 352768.00 */ | ||
709 | /* 209715200.00 => 255 */ 0xff, /* => 352768.00 */ | ||
710 | /* 218103808.00 => 255 */ 0xff, /* => 352768.00 */ | ||
711 | /* 226492416.00 => 255 */ 0xff, /* => 352768.00 */ | ||
712 | /* 234881024.00 => 255 */ 0xff, /* => 352768.00 */ | ||
713 | /* 243269632.00 => 255 */ 0xff, /* => 352768.00 */ | ||
714 | /* 251658240.00 => 255 */ 0xff, /* => 352768.00 */ | ||
715 | /* 260046848.00 => 255 */ 0xff, /* => 352768.00 */ | ||
716 | /* 268435456.00 => 255 */ 0xff, /* => 352768.00 */ | ||
717 | /* 285212672.00 => 255 */ 0xff, /* => 352768.00 */ | ||
718 | /* 301989888.00 => 255 */ 0xff, /* => 352768.00 */ | ||
719 | /* 318767104.00 => 255 */ 0xff, /* => 352768.00 */ | ||
720 | /* 335544320.00 => 255 */ 0xff, /* => 352768.00 */ | ||
721 | /* 352321536.00 => 255 */ 0xff, /* => 352768.00 */ | ||
722 | /* 369098752.00 => 255 */ 0xff, /* => 352768.00 */ | ||
723 | /* 385875968.00 => 255 */ 0xff, /* => 352768.00 */ | ||
724 | /* 402653184.00 => 255 */ 0xff, /* => 352768.00 */ | ||
725 | /* 419430400.00 => 255 */ 0xff, /* => 352768.00 */ | ||
726 | /* 436207616.00 => 255 */ 0xff, /* => 352768.00 */ | ||
727 | /* 452984832.00 => 255 */ 0xff, /* => 352768.00 */ | ||
728 | /* 469762048.00 => 255 */ 0xff, /* => 352768.00 */ | ||
729 | /* 486539264.00 => 255 */ 0xff, /* => 352768.00 */ | ||
730 | /* 503316480.00 => 255 */ 0xff, /* => 352768.00 */ | ||
731 | /* 520093696.00 => 255 */ 0xff, /* => 352768.00 */ | ||
732 | /* 536870912.00 => 255 */ 0xff, /* => 352768.00 */ | ||
733 | /* 570425344.00 => 255 */ 0xff, /* => 352768.00 */ | ||
734 | /* 603979776.00 => 255 */ 0xff, /* => 352768.00 */ | ||
735 | /* 637534208.00 => 255 */ 0xff, /* => 352768.00 */ | ||
736 | /* 671088640.00 => 255 */ 0xff, /* => 352768.00 */ | ||
737 | /* 704643072.00 => 255 */ 0xff, /* => 352768.00 */ | ||
738 | /* 738197504.00 => 255 */ 0xff, /* => 352768.00 */ | ||
739 | /* 771751936.00 => 255 */ 0xff, /* => 352768.00 */ | ||
740 | /* 805306368.00 => 255 */ 0xff, /* => 352768.00 */ | ||
741 | /* 838860800.00 => 255 */ 0xff, /* => 352768.00 */ | ||
742 | /* 872415232.00 => 255 */ 0xff, /* => 352768.00 */ | ||
743 | /* 905969664.00 => 255 */ 0xff, /* => 352768.00 */ | ||
744 | /* 939524096.00 => 255 */ 0xff, /* => 352768.00 */ | ||
745 | /* 973078528.00 => 255 */ 0xff, /* => 352768.00 */ | ||
746 | /* 1006632960.00 => 255 */ 0xff, /* => 352768.00 */ | ||
747 | /* 1040187392.00 => 255 */ 0xff, /* => 352768.00 */ | ||
748 | /* 1073741824.00 => 255 */ 0xff, /* => 352768.00 */ | ||
749 | /* 1140850688.00 => 255 */ 0xff, /* => 352768.00 */ | ||
750 | /* 1207959552.00 => 255 */ 0xff, /* => 352768.00 */ | ||
751 | /* 1275068416.00 => 255 */ 0xff, /* => 352768.00 */ | ||
752 | /* 1342177280.00 => 255 */ 0xff, /* => 352768.00 */ | ||
753 | /* 1409286144.00 => 255 */ 0xff, /* => 352768.00 */ | ||
754 | /* 1476395008.00 => 255 */ 0xff, /* => 352768.00 */ | ||
755 | /* 1543503872.00 => 255 */ 0xff, /* => 352768.00 */ | ||
756 | /* 1610612736.00 => 255 */ 0xff, /* => 352768.00 */ | ||
757 | /* 1677721600.00 => 255 */ 0xff, /* => 352768.00 */ | ||
758 | /* 1744830464.00 => 255 */ 0xff, /* => 352768.00 */ | ||
759 | /* 1811939328.00 => 255 */ 0xff, /* => 352768.00 */ | ||
760 | /* 1879048192.00 => 255 */ 0xff, /* => 352768.00 */ | ||
761 | /* 1946157056.00 => 255 */ 0xff, /* => 352768.00 */ | ||
762 | /* 2013265920.00 => 255 */ 0xff, /* => 352768.00 */ | ||
763 | /* 2080374784.00 => 255 */ 0xff, /* => 352768.00 */ | ||
764 | /* 2147483648.00 => 255 */ 0xff, /* => 352768.00 */ | ||
765 | /* 2281701376.00 => 255 */ 0xff, /* => 352768.00 */ | ||
766 | /* 2415919104.00 => 255 */ 0xff, /* => 352768.00 */ | ||
767 | /* 2550136832.00 => 255 */ 0xff, /* => 352768.00 */ | ||
768 | /* 2684354560.00 => 255 */ 0xff, /* => 352768.00 */ | ||
769 | /* 2818572288.00 => 255 */ 0xff, /* => 352768.00 */ | ||
770 | /* 2952790016.00 => 255 */ 0xff, /* => 352768.00 */ | ||
771 | /* 3087007744.00 => 255 */ 0xff, /* => 352768.00 */ | ||
772 | /* 3221225472.00 => 255 */ 0xff, /* => 352768.00 */ | ||
773 | /* 3355443200.00 => 255 */ 0xff, /* => 352768.00 */ | ||
774 | /* 3489660928.00 => 255 */ 0xff, /* => 352768.00 */ | ||
775 | /* 3623878656.00 => 255 */ 0xff, /* => 352768.00 */ | ||
776 | /* 3758096384.00 => 255 */ 0xff, /* => 352768.00 */ | ||
777 | /* 3892314112.00 => 255 */ 0xff, /* => 352768.00 */ | ||
778 | /* 4026531840.00 => 255 */ 0xff, /* => 352768.00 */ | ||
779 | /* 4160749568.00 => 255 */ 0xff, /* => 352768.00 */ | ||
780 | }; | ||
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c new file mode 100644 index 000000000000..a43575acb2c1 --- /dev/null +++ b/drivers/atm/iphase.c | |||
@@ -0,0 +1,3296 @@ | |||
1 | /****************************************************************************** | ||
2 | iphase.c: Device driver for Interphase ATM PCI adapter cards | ||
3 | Author: Peter Wang <pwang@iphase.com> | ||
4 | Some fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
5 | Interphase Corporation <www.iphase.com> | ||
6 | Version: 1.0 | ||
7 | ******************************************************************************* | ||
8 | |||
9 | This software may be used and distributed according to the terms | ||
10 | of the GNU General Public License (GPL), incorporated herein by reference. | ||
11 | Drivers based on this skeleton fall under the GPL and must retain | ||
12 | the authorship (implicit copyright) notice. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | General Public License for more details. | ||
18 | |||
19 | Modified from an incomplete driver for Interphase 5575 1KVC 1M card which | ||
20 | was originally written by Monalisa Agrawal at UNH. Now this driver | ||
21 | supports a variety of varients of Interphase ATM PCI (i)Chip adapter | ||
22 | card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM) | ||
23 | in terms of PHY type, the size of control memory and the size of | ||
24 | packet memory. The followings are the change log and history: | ||
25 | |||
26 | Bugfix the Mona's UBR driver. | ||
27 | Modify the basic memory allocation and dma logic. | ||
28 | Port the driver to the latest kernel from 2.0.46. | ||
29 | Complete the ABR logic of the driver, and added the ABR work- | ||
30 | around for the hardware anormalies. | ||
31 | Add the CBR support. | ||
32 | Add the flow control logic to the driver to allow rate-limit VC. | ||
33 | Add 4K VC support to the board with 512K control memory. | ||
34 | Add the support of all the variants of the Interphase ATM PCI | ||
35 | (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525 | ||
36 | (25M UTP25) and x531 (DS3 and E3). | ||
37 | Add SMP support. | ||
38 | |||
39 | Support and updates available at: ftp://ftp.iphase.com/pub/atm | ||
40 | |||
41 | *******************************************************************************/ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/kernel.h> | ||
45 | #include <linux/mm.h> | ||
46 | #include <linux/pci.h> | ||
47 | #include <linux/errno.h> | ||
48 | #include <linux/atm.h> | ||
49 | #include <linux/atmdev.h> | ||
50 | #include <linux/sonet.h> | ||
51 | #include <linux/skbuff.h> | ||
52 | #include <linux/time.h> | ||
53 | #include <linux/delay.h> | ||
54 | #include <linux/uio.h> | ||
55 | #include <linux/init.h> | ||
56 | #include <linux/wait.h> | ||
57 | #include <asm/system.h> | ||
58 | #include <asm/io.h> | ||
59 | #include <asm/atomic.h> | ||
60 | #include <asm/uaccess.h> | ||
61 | #include <asm/string.h> | ||
62 | #include <asm/byteorder.h> | ||
63 | #include <linux/vmalloc.h> | ||
64 | #include "iphase.h" | ||
65 | #include "suni.h" | ||
66 | #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8)) | ||
67 | struct suni_priv { | ||
68 | struct k_sonet_stats sonet_stats; /* link diagnostics */ | ||
69 | unsigned char loop_mode; /* loopback mode */ | ||
70 | struct atm_dev *dev; /* device back-pointer */ | ||
71 | struct suni_priv *next; /* next SUNI */ | ||
72 | }; | ||
73 | #define PRIV(dev) ((struct suni_priv *) dev->phy_data) | ||
74 | |||
75 | static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr); | ||
76 | static void desc_dbg(IADEV *iadev); | ||
77 | |||
78 | static IADEV *ia_dev[8]; | ||
79 | static struct atm_dev *_ia_dev[8]; | ||
80 | static int iadev_count; | ||
81 | static void ia_led_timer(unsigned long arg); | ||
82 | static struct timer_list ia_timer = TIMER_INITIALIZER(ia_led_timer, 0, 0); | ||
83 | static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ; | ||
84 | static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ; | ||
85 | static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER | ||
86 | |IF_IADBG_ABR | IF_IADBG_EVENT*/ 0; | ||
87 | |||
88 | module_param(IA_TX_BUF, int, 0); | ||
89 | module_param(IA_TX_BUF_SZ, int, 0); | ||
90 | module_param(IA_RX_BUF, int, 0); | ||
91 | module_param(IA_RX_BUF_SZ, int, 0); | ||
92 | module_param(IADebugFlag, uint, 0644); | ||
93 | |||
94 | MODULE_LICENSE("GPL"); | ||
95 | |||
96 | #if BITS_PER_LONG != 32 | ||
97 | # error FIXME: this driver only works on 32-bit platforms | ||
98 | #endif | ||
99 | |||
100 | /**************************** IA_LIB **********************************/ | ||
101 | |||
102 | static void ia_init_rtn_q (IARTN_Q *que) | ||
103 | { | ||
104 | que->next = NULL; | ||
105 | que->tail = NULL; | ||
106 | } | ||
107 | |||
108 | static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data) | ||
109 | { | ||
110 | data->next = NULL; | ||
111 | if (que->next == NULL) | ||
112 | que->next = que->tail = data; | ||
113 | else { | ||
114 | data->next = que->next; | ||
115 | que->next = data; | ||
116 | } | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) { | ||
121 | IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_ATOMIC); | ||
122 | if (!entry) return -1; | ||
123 | entry->data = data; | ||
124 | entry->next = NULL; | ||
125 | if (que->next == NULL) | ||
126 | que->next = que->tail = entry; | ||
127 | else { | ||
128 | que->tail->next = entry; | ||
129 | que->tail = que->tail->next; | ||
130 | } | ||
131 | return 1; | ||
132 | } | ||
133 | |||
134 | static IARTN_Q * ia_deque_rtn_q (IARTN_Q *que) { | ||
135 | IARTN_Q *tmpdata; | ||
136 | if (que->next == NULL) | ||
137 | return NULL; | ||
138 | tmpdata = que->next; | ||
139 | if ( que->next == que->tail) | ||
140 | que->next = que->tail = NULL; | ||
141 | else | ||
142 | que->next = que->next->next; | ||
143 | return tmpdata; | ||
144 | } | ||
145 | |||
146 | static void ia_hack_tcq(IADEV *dev) { | ||
147 | |||
148 | u_short desc1; | ||
149 | u_short tcq_wr; | ||
150 | struct ia_vcc *iavcc_r = NULL; | ||
151 | |||
152 | tcq_wr = readl(dev->seg_reg+TCQ_WR_PTR) & 0xffff; | ||
153 | while (dev->host_tcq_wr != tcq_wr) { | ||
154 | desc1 = *(u_short *)(dev->seg_ram + dev->host_tcq_wr); | ||
155 | if (!desc1) ; | ||
156 | else if (!dev->desc_tbl[desc1 -1].timestamp) { | ||
157 | IF_ABR(printk(" Desc %d is reset at %ld\n", desc1 -1, jiffies);) | ||
158 | *(u_short *) (dev->seg_ram + dev->host_tcq_wr) = 0; | ||
159 | } | ||
160 | else if (dev->desc_tbl[desc1 -1].timestamp) { | ||
161 | if (!(iavcc_r = dev->desc_tbl[desc1 -1].iavcc)) { | ||
162 | printk("IA: Fatal err in get_desc\n"); | ||
163 | continue; | ||
164 | } | ||
165 | iavcc_r->vc_desc_cnt--; | ||
166 | dev->desc_tbl[desc1 -1].timestamp = 0; | ||
167 | IF_EVENT(printk("ia_hack: return_q skb = 0x%x desc = %d\n", | ||
168 | (u32)dev->desc_tbl[desc1 -1].txskb, desc1);) | ||
169 | if (iavcc_r->pcr < dev->rate_limit) { | ||
170 | IA_SKB_STATE (dev->desc_tbl[desc1-1].txskb) |= IA_TX_DONE; | ||
171 | if (ia_enque_rtn_q(&dev->tx_return_q, dev->desc_tbl[desc1 -1]) < 0) | ||
172 | printk("ia_hack_tcq: No memory available\n"); | ||
173 | } | ||
174 | dev->desc_tbl[desc1 -1].iavcc = NULL; | ||
175 | dev->desc_tbl[desc1 -1].txskb = NULL; | ||
176 | } | ||
177 | dev->host_tcq_wr += 2; | ||
178 | if (dev->host_tcq_wr > dev->ffL.tcq_ed) | ||
179 | dev->host_tcq_wr = dev->ffL.tcq_st; | ||
180 | } | ||
181 | } /* ia_hack_tcq */ | ||
182 | |||
183 | static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) { | ||
184 | u_short desc_num, i; | ||
185 | struct sk_buff *skb; | ||
186 | struct ia_vcc *iavcc_r = NULL; | ||
187 | unsigned long delta; | ||
188 | static unsigned long timer = 0; | ||
189 | int ltimeout; | ||
190 | |||
191 | ia_hack_tcq (dev); | ||
192 | if(((jiffies - timer)>50)||((dev->ffL.tcq_rd==dev->host_tcq_wr))){ | ||
193 | timer = jiffies; | ||
194 | i=0; | ||
195 | while (i < dev->num_tx_desc) { | ||
196 | if (!dev->desc_tbl[i].timestamp) { | ||
197 | i++; | ||
198 | continue; | ||
199 | } | ||
200 | ltimeout = dev->desc_tbl[i].iavcc->ltimeout; | ||
201 | delta = jiffies - dev->desc_tbl[i].timestamp; | ||
202 | if (delta >= ltimeout) { | ||
203 | IF_ABR(printk("RECOVER run!! desc_tbl %d = %d delta = %ld, time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);) | ||
204 | if (dev->ffL.tcq_rd == dev->ffL.tcq_st) | ||
205 | dev->ffL.tcq_rd = dev->ffL.tcq_ed; | ||
206 | else | ||
207 | dev->ffL.tcq_rd -= 2; | ||
208 | *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd) = i+1; | ||
209 | if (!(skb = dev->desc_tbl[i].txskb) || | ||
210 | !(iavcc_r = dev->desc_tbl[i].iavcc)) | ||
211 | printk("Fatal err, desc table vcc or skb is NULL\n"); | ||
212 | else | ||
213 | iavcc_r->vc_desc_cnt--; | ||
214 | dev->desc_tbl[i].timestamp = 0; | ||
215 | dev->desc_tbl[i].iavcc = NULL; | ||
216 | dev->desc_tbl[i].txskb = NULL; | ||
217 | } | ||
218 | i++; | ||
219 | } /* while */ | ||
220 | } | ||
221 | if (dev->ffL.tcq_rd == dev->host_tcq_wr) | ||
222 | return 0xFFFF; | ||
223 | |||
224 | /* Get the next available descriptor number from TCQ */ | ||
225 | desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd); | ||
226 | |||
227 | while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) { | ||
228 | dev->ffL.tcq_rd += 2; | ||
229 | if (dev->ffL.tcq_rd > dev->ffL.tcq_ed) | ||
230 | dev->ffL.tcq_rd = dev->ffL.tcq_st; | ||
231 | if (dev->ffL.tcq_rd == dev->host_tcq_wr) | ||
232 | return 0xFFFF; | ||
233 | desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd); | ||
234 | } | ||
235 | |||
236 | /* get system time */ | ||
237 | dev->desc_tbl[desc_num -1].timestamp = jiffies; | ||
238 | return desc_num; | ||
239 | } | ||
240 | |||
241 | static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) { | ||
242 | u_char foundLockUp; | ||
243 | vcstatus_t *vcstatus; | ||
244 | u_short *shd_tbl; | ||
245 | u_short tempCellSlot, tempFract; | ||
246 | struct main_vc *abr_vc = (struct main_vc *)dev->MAIN_VC_TABLE_ADDR; | ||
247 | struct ext_vc *eabr_vc = (struct ext_vc *)dev->EXT_VC_TABLE_ADDR; | ||
248 | u_int i; | ||
249 | |||
250 | if (vcc->qos.txtp.traffic_class == ATM_ABR) { | ||
251 | vcstatus = (vcstatus_t *) &(dev->testTable[vcc->vci]->vc_status); | ||
252 | vcstatus->cnt++; | ||
253 | foundLockUp = 0; | ||
254 | if( vcstatus->cnt == 0x05 ) { | ||
255 | abr_vc += vcc->vci; | ||
256 | eabr_vc += vcc->vci; | ||
257 | if( eabr_vc->last_desc ) { | ||
258 | if( (abr_vc->status & 0x07) == ABR_STATE /* 0x2 */ ) { | ||
259 | /* Wait for 10 Micro sec */ | ||
260 | udelay(10); | ||
261 | if ((eabr_vc->last_desc)&&((abr_vc->status & 0x07)==ABR_STATE)) | ||
262 | foundLockUp = 1; | ||
263 | } | ||
264 | else { | ||
265 | tempCellSlot = abr_vc->last_cell_slot; | ||
266 | tempFract = abr_vc->fraction; | ||
267 | if((tempCellSlot == dev->testTable[vcc->vci]->lastTime) | ||
268 | && (tempFract == dev->testTable[vcc->vci]->fract)) | ||
269 | foundLockUp = 1; | ||
270 | dev->testTable[vcc->vci]->lastTime = tempCellSlot; | ||
271 | dev->testTable[vcc->vci]->fract = tempFract; | ||
272 | } | ||
273 | } /* last descriptor */ | ||
274 | vcstatus->cnt = 0; | ||
275 | } /* vcstatus->cnt */ | ||
276 | |||
277 | if (foundLockUp) { | ||
278 | IF_ABR(printk("LOCK UP found\n");) | ||
279 | writew(0xFFFD, dev->seg_reg+MODE_REG_0); | ||
280 | /* Wait for 10 Micro sec */ | ||
281 | udelay(10); | ||
282 | abr_vc->status &= 0xFFF8; | ||
283 | abr_vc->status |= 0x0001; /* state is idle */ | ||
284 | shd_tbl = (u_short *)dev->ABR_SCHED_TABLE_ADDR; | ||
285 | for( i = 0; ((i < dev->num_vc) && (shd_tbl[i])); i++ ); | ||
286 | if (i < dev->num_vc) | ||
287 | shd_tbl[i] = vcc->vci; | ||
288 | else | ||
289 | IF_ERR(printk("ABR Seg. may not continue on VC %x\n",vcc->vci);) | ||
290 | writew(T_ONLINE, dev->seg_reg+MODE_REG_0); | ||
291 | writew(~(TRANSMIT_DONE|TCQ_NOT_EMPTY), dev->seg_reg+SEG_MASK_REG); | ||
292 | writew(TRANSMIT_DONE, dev->seg_reg+SEG_INTR_STATUS_REG); | ||
293 | vcstatus->cnt = 0; | ||
294 | } /* foundLockUp */ | ||
295 | |||
296 | } /* if an ABR VC */ | ||
297 | |||
298 | |||
299 | } | ||
300 | |||
301 | /* | ||
302 | ** Conversion of 24-bit cellrate (cells/sec) to 16-bit floating point format. | ||
303 | ** | ||
304 | ** +----+----+------------------+-------------------------------+ | ||
305 | ** | R | NZ | 5-bit exponent | 9-bit mantissa | | ||
306 | ** +----+----+------------------+-------------------------------+ | ||
307 | ** | ||
308 | ** R = reserverd (written as 0) | ||
309 | ** NZ = 0 if 0 cells/sec; 1 otherwise | ||
310 | ** | ||
311 | ** if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec | ||
312 | */ | ||
313 | static u16 | ||
314 | cellrate_to_float(u32 cr) | ||
315 | { | ||
316 | |||
317 | #define NZ 0x4000 | ||
318 | #define M_BITS 9 /* Number of bits in mantissa */ | ||
319 | #define E_BITS 5 /* Number of bits in exponent */ | ||
320 | #define M_MASK 0x1ff | ||
321 | #define E_MASK 0x1f | ||
322 | u16 flot; | ||
323 | u32 tmp = cr & 0x00ffffff; | ||
324 | int i = 0; | ||
325 | if (cr == 0) | ||
326 | return 0; | ||
327 | while (tmp != 1) { | ||
328 | tmp >>= 1; | ||
329 | i++; | ||
330 | } | ||
331 | if (i == M_BITS) | ||
332 | flot = NZ | (i << M_BITS) | (cr & M_MASK); | ||
333 | else if (i < M_BITS) | ||
334 | flot = NZ | (i << M_BITS) | ((cr << (M_BITS - i)) & M_MASK); | ||
335 | else | ||
336 | flot = NZ | (i << M_BITS) | ((cr >> (i - M_BITS)) & M_MASK); | ||
337 | return flot; | ||
338 | } | ||
339 | |||
340 | #if 0 | ||
341 | /* | ||
342 | ** Conversion of 16-bit floating point format to 24-bit cellrate (cells/sec). | ||
343 | */ | ||
344 | static u32 | ||
345 | float_to_cellrate(u16 rate) | ||
346 | { | ||
347 | u32 exp, mantissa, cps; | ||
348 | if ((rate & NZ) == 0) | ||
349 | return 0; | ||
350 | exp = (rate >> M_BITS) & E_MASK; | ||
351 | mantissa = rate & M_MASK; | ||
352 | if (exp == 0) | ||
353 | return 1; | ||
354 | cps = (1 << M_BITS) | mantissa; | ||
355 | if (exp == M_BITS) | ||
356 | cps = cps; | ||
357 | else if (exp > M_BITS) | ||
358 | cps <<= (exp - M_BITS); | ||
359 | else | ||
360 | cps >>= (M_BITS - exp); | ||
361 | return cps; | ||
362 | } | ||
363 | #endif | ||
364 | |||
365 | static void init_abr_vc (IADEV *dev, srv_cls_param_t *srv_p) { | ||
366 | srv_p->class_type = ATM_ABR; | ||
367 | srv_p->pcr = dev->LineRate; | ||
368 | srv_p->mcr = 0; | ||
369 | srv_p->icr = 0x055cb7; | ||
370 | srv_p->tbe = 0xffffff; | ||
371 | srv_p->frtt = 0x3a; | ||
372 | srv_p->rif = 0xf; | ||
373 | srv_p->rdf = 0xb; | ||
374 | srv_p->nrm = 0x4; | ||
375 | srv_p->trm = 0x7; | ||
376 | srv_p->cdf = 0x3; | ||
377 | srv_p->adtf = 50; | ||
378 | } | ||
379 | |||
380 | static int | ||
381 | ia_open_abr_vc(IADEV *dev, srv_cls_param_t *srv_p, | ||
382 | struct atm_vcc *vcc, u8 flag) | ||
383 | { | ||
384 | f_vc_abr_entry *f_abr_vc; | ||
385 | r_vc_abr_entry *r_abr_vc; | ||
386 | u32 icr; | ||
387 | u8 trm, nrm, crm; | ||
388 | u16 adtf, air, *ptr16; | ||
389 | f_abr_vc =(f_vc_abr_entry *)dev->MAIN_VC_TABLE_ADDR; | ||
390 | f_abr_vc += vcc->vci; | ||
391 | switch (flag) { | ||
392 | case 1: /* FFRED initialization */ | ||
393 | #if 0 /* sanity check */ | ||
394 | if (srv_p->pcr == 0) | ||
395 | return INVALID_PCR; | ||
396 | if (srv_p->pcr > dev->LineRate) | ||
397 | srv_p->pcr = dev->LineRate; | ||
398 | if ((srv_p->mcr + dev->sum_mcr) > dev->LineRate) | ||
399 | return MCR_UNAVAILABLE; | ||
400 | if (srv_p->mcr > srv_p->pcr) | ||
401 | return INVALID_MCR; | ||
402 | if (!(srv_p->icr)) | ||
403 | srv_p->icr = srv_p->pcr; | ||
404 | if ((srv_p->icr < srv_p->mcr) || (srv_p->icr > srv_p->pcr)) | ||
405 | return INVALID_ICR; | ||
406 | if ((srv_p->tbe < MIN_TBE) || (srv_p->tbe > MAX_TBE)) | ||
407 | return INVALID_TBE; | ||
408 | if ((srv_p->frtt < MIN_FRTT) || (srv_p->frtt > MAX_FRTT)) | ||
409 | return INVALID_FRTT; | ||
410 | if (srv_p->nrm > MAX_NRM) | ||
411 | return INVALID_NRM; | ||
412 | if (srv_p->trm > MAX_TRM) | ||
413 | return INVALID_TRM; | ||
414 | if (srv_p->adtf > MAX_ADTF) | ||
415 | return INVALID_ADTF; | ||
416 | else if (srv_p->adtf == 0) | ||
417 | srv_p->adtf = 1; | ||
418 | if (srv_p->cdf > MAX_CDF) | ||
419 | return INVALID_CDF; | ||
420 | if (srv_p->rif > MAX_RIF) | ||
421 | return INVALID_RIF; | ||
422 | if (srv_p->rdf > MAX_RDF) | ||
423 | return INVALID_RDF; | ||
424 | #endif | ||
425 | memset ((caddr_t)f_abr_vc, 0, sizeof(*f_abr_vc)); | ||
426 | f_abr_vc->f_vc_type = ABR; | ||
427 | nrm = 2 << srv_p->nrm; /* (2 ** (srv_p->nrm +1)) */ | ||
428 | /* i.e 2**n = 2 << (n-1) */ | ||
429 | f_abr_vc->f_nrm = nrm << 8 | nrm; | ||
430 | trm = 100000/(2 << (16 - srv_p->trm)); | ||
431 | if ( trm == 0) trm = 1; | ||
432 | f_abr_vc->f_nrmexp =(((srv_p->nrm +1) & 0x0f) << 12)|(MRM << 8) | trm; | ||
433 | crm = srv_p->tbe / nrm; | ||
434 | if (crm == 0) crm = 1; | ||
435 | f_abr_vc->f_crm = crm & 0xff; | ||
436 | f_abr_vc->f_pcr = cellrate_to_float(srv_p->pcr); | ||
437 | icr = min( srv_p->icr, (srv_p->tbe > srv_p->frtt) ? | ||
438 | ((srv_p->tbe/srv_p->frtt)*1000000) : | ||
439 | (1000000/(srv_p->frtt/srv_p->tbe))); | ||
440 | f_abr_vc->f_icr = cellrate_to_float(icr); | ||
441 | adtf = (10000 * srv_p->adtf)/8192; | ||
442 | if (adtf == 0) adtf = 1; | ||
443 | f_abr_vc->f_cdf = ((7 - srv_p->cdf) << 12 | adtf) & 0xfff; | ||
444 | f_abr_vc->f_mcr = cellrate_to_float(srv_p->mcr); | ||
445 | f_abr_vc->f_acr = f_abr_vc->f_icr; | ||
446 | f_abr_vc->f_status = 0x0042; | ||
447 | break; | ||
448 | case 0: /* RFRED initialization */ | ||
449 | ptr16 = (u_short *)(dev->reass_ram + REASS_TABLE*dev->memSize); | ||
450 | *(ptr16 + vcc->vci) = NO_AAL5_PKT | REASS_ABR; | ||
451 | r_abr_vc = (r_vc_abr_entry*)(dev->reass_ram+ABR_VC_TABLE*dev->memSize); | ||
452 | r_abr_vc += vcc->vci; | ||
453 | r_abr_vc->r_status_rdf = (15 - srv_p->rdf) & 0x000f; | ||
454 | air = srv_p->pcr << (15 - srv_p->rif); | ||
455 | if (air == 0) air = 1; | ||
456 | r_abr_vc->r_air = cellrate_to_float(air); | ||
457 | dev->testTable[vcc->vci]->vc_status = VC_ACTIVE | VC_ABR; | ||
458 | dev->sum_mcr += srv_p->mcr; | ||
459 | dev->n_abr++; | ||
460 | break; | ||
461 | default: | ||
462 | break; | ||
463 | } | ||
464 | return 0; | ||
465 | } | ||
466 | static int ia_cbr_setup (IADEV *dev, struct atm_vcc *vcc) { | ||
467 | u32 rateLow=0, rateHigh, rate; | ||
468 | int entries; | ||
469 | struct ia_vcc *ia_vcc; | ||
470 | |||
471 | int idealSlot =0, testSlot, toBeAssigned, inc; | ||
472 | u32 spacing; | ||
473 | u16 *SchedTbl, *TstSchedTbl; | ||
474 | u16 cbrVC, vcIndex; | ||
475 | u32 fracSlot = 0; | ||
476 | u32 sp_mod = 0; | ||
477 | u32 sp_mod2 = 0; | ||
478 | |||
479 | /* IpAdjustTrafficParams */ | ||
480 | if (vcc->qos.txtp.max_pcr <= 0) { | ||
481 | IF_ERR(printk("PCR for CBR not defined\n");) | ||
482 | return -1; | ||
483 | } | ||
484 | rate = vcc->qos.txtp.max_pcr; | ||
485 | entries = rate / dev->Granularity; | ||
486 | IF_CBR(printk("CBR: CBR entries=0x%x for rate=0x%x & Gran=0x%x\n", | ||
487 | entries, rate, dev->Granularity);) | ||
488 | if (entries < 1) | ||
489 | IF_CBR(printk("CBR: Bandwidth smaller than granularity of CBR table\n");) | ||
490 | rateLow = entries * dev->Granularity; | ||
491 | rateHigh = (entries + 1) * dev->Granularity; | ||
492 | if (3*(rate - rateLow) > (rateHigh - rate)) | ||
493 | entries++; | ||
494 | if (entries > dev->CbrRemEntries) { | ||
495 | IF_CBR(printk("CBR: Not enough bandwidth to support this PCR.\n");) | ||
496 | IF_CBR(printk("Entries = 0x%x, CbrRemEntries = 0x%x.\n", | ||
497 | entries, dev->CbrRemEntries);) | ||
498 | return -EBUSY; | ||
499 | } | ||
500 | |||
501 | ia_vcc = INPH_IA_VCC(vcc); | ||
502 | ia_vcc->NumCbrEntry = entries; | ||
503 | dev->sum_mcr += entries * dev->Granularity; | ||
504 | /* IaFFrednInsertCbrSched */ | ||
505 | // Starting at an arbitrary location, place the entries into the table | ||
506 | // as smoothly as possible | ||
507 | cbrVC = 0; | ||
508 | spacing = dev->CbrTotEntries / entries; | ||
509 | sp_mod = dev->CbrTotEntries % entries; // get modulo | ||
510 | toBeAssigned = entries; | ||
511 | fracSlot = 0; | ||
512 | vcIndex = vcc->vci; | ||
513 | IF_CBR(printk("Vci=0x%x,Spacing=0x%x,Sp_mod=0x%x\n",vcIndex,spacing,sp_mod);) | ||
514 | while (toBeAssigned) | ||
515 | { | ||
516 | // If this is the first time, start the table loading for this connection | ||
517 | // as close to entryPoint as possible. | ||
518 | if (toBeAssigned == entries) | ||
519 | { | ||
520 | idealSlot = dev->CbrEntryPt; | ||
521 | dev->CbrEntryPt += 2; // Adding 2 helps to prevent clumping | ||
522 | if (dev->CbrEntryPt >= dev->CbrTotEntries) | ||
523 | dev->CbrEntryPt -= dev->CbrTotEntries;// Wrap if necessary | ||
524 | } else { | ||
525 | idealSlot += (u32)(spacing + fracSlot); // Point to the next location | ||
526 | // in the table that would be smoothest | ||
527 | fracSlot = ((sp_mod + sp_mod2) / entries); // get new integer part | ||
528 | sp_mod2 = ((sp_mod + sp_mod2) % entries); // calc new fractional part | ||
529 | } | ||
530 | if (idealSlot >= (int)dev->CbrTotEntries) | ||
531 | idealSlot -= dev->CbrTotEntries; | ||
532 | // Continuously check around this ideal value until a null | ||
533 | // location is encountered. | ||
534 | SchedTbl = (u16*)(dev->seg_ram+CBR_SCHED_TABLE*dev->memSize); | ||
535 | inc = 0; | ||
536 | testSlot = idealSlot; | ||
537 | TstSchedTbl = (u16*)(SchedTbl+testSlot); //set index and read in value | ||
538 | IF_CBR(printk("CBR Testslot 0x%x AT Location 0x%x, NumToAssign=%d\n", | ||
539 | testSlot, (u32)TstSchedTbl,toBeAssigned);) | ||
540 | memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); | ||
541 | while (cbrVC) // If another VC at this location, we have to keep looking | ||
542 | { | ||
543 | inc++; | ||
544 | testSlot = idealSlot - inc; | ||
545 | if (testSlot < 0) { // Wrap if necessary | ||
546 | testSlot += dev->CbrTotEntries; | ||
547 | IF_CBR(printk("Testslot Wrap. STable Start=0x%x,Testslot=%d\n", | ||
548 | (u32)SchedTbl,testSlot);) | ||
549 | } | ||
550 | TstSchedTbl = (u16 *)(SchedTbl + testSlot); // set table index | ||
551 | memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); | ||
552 | if (!cbrVC) | ||
553 | break; | ||
554 | testSlot = idealSlot + inc; | ||
555 | if (testSlot >= (int)dev->CbrTotEntries) { // Wrap if necessary | ||
556 | testSlot -= dev->CbrTotEntries; | ||
557 | IF_CBR(printk("TotCbrEntries=%d",dev->CbrTotEntries);) | ||
558 | IF_CBR(printk(" Testslot=0x%x ToBeAssgned=%d\n", | ||
559 | testSlot, toBeAssigned);) | ||
560 | } | ||
561 | // set table index and read in value | ||
562 | TstSchedTbl = (u16*)(SchedTbl + testSlot); | ||
563 | IF_CBR(printk("Reading CBR Tbl from 0x%x, CbrVal=0x%x Iteration %d\n", | ||
564 | (u32)TstSchedTbl,cbrVC,inc);) | ||
565 | memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC)); | ||
566 | } /* while */ | ||
567 | // Move this VCI number into this location of the CBR Sched table. | ||
568 | memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex,sizeof(TstSchedTbl)); | ||
569 | dev->CbrRemEntries--; | ||
570 | toBeAssigned--; | ||
571 | } /* while */ | ||
572 | |||
573 | /* IaFFrednCbrEnable */ | ||
574 | dev->NumEnabledCBR++; | ||
575 | if (dev->NumEnabledCBR == 1) { | ||
576 | writew((CBR_EN | UBR_EN | ABR_EN | (0x23 << 2)), dev->seg_reg+STPARMS); | ||
577 | IF_CBR(printk("CBR is enabled\n");) | ||
578 | } | ||
579 | return 0; | ||
580 | } | ||
581 | static void ia_cbrVc_close (struct atm_vcc *vcc) { | ||
582 | IADEV *iadev; | ||
583 | u16 *SchedTbl, NullVci = 0; | ||
584 | u32 i, NumFound; | ||
585 | |||
586 | iadev = INPH_IA_DEV(vcc->dev); | ||
587 | iadev->NumEnabledCBR--; | ||
588 | SchedTbl = (u16*)(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize); | ||
589 | if (iadev->NumEnabledCBR == 0) { | ||
590 | writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS); | ||
591 | IF_CBR (printk("CBR support disabled\n");) | ||
592 | } | ||
593 | NumFound = 0; | ||
594 | for (i=0; i < iadev->CbrTotEntries; i++) | ||
595 | { | ||
596 | if (*SchedTbl == vcc->vci) { | ||
597 | iadev->CbrRemEntries++; | ||
598 | *SchedTbl = NullVci; | ||
599 | IF_CBR(NumFound++;) | ||
600 | } | ||
601 | SchedTbl++; | ||
602 | } | ||
603 | IF_CBR(printk("Exit ia_cbrVc_close, NumRemoved=%d\n",NumFound);) | ||
604 | } | ||
605 | |||
606 | static int ia_avail_descs(IADEV *iadev) { | ||
607 | int tmp = 0; | ||
608 | ia_hack_tcq(iadev); | ||
609 | if (iadev->host_tcq_wr >= iadev->ffL.tcq_rd) | ||
610 | tmp = (iadev->host_tcq_wr - iadev->ffL.tcq_rd) / 2; | ||
611 | else | ||
612 | tmp = (iadev->ffL.tcq_ed - iadev->ffL.tcq_rd + 2 + iadev->host_tcq_wr - | ||
613 | iadev->ffL.tcq_st) / 2; | ||
614 | return tmp; | ||
615 | } | ||
616 | |||
617 | static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb); | ||
618 | |||
619 | static int ia_que_tx (IADEV *iadev) { | ||
620 | struct sk_buff *skb; | ||
621 | int num_desc; | ||
622 | struct atm_vcc *vcc; | ||
623 | struct ia_vcc *iavcc; | ||
624 | num_desc = ia_avail_descs(iadev); | ||
625 | |||
626 | while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { | ||
627 | if (!(vcc = ATM_SKB(skb)->vcc)) { | ||
628 | dev_kfree_skb_any(skb); | ||
629 | printk("ia_que_tx: Null vcc\n"); | ||
630 | break; | ||
631 | } | ||
632 | if (!test_bit(ATM_VF_READY,&vcc->flags)) { | ||
633 | dev_kfree_skb_any(skb); | ||
634 | printk("Free the SKB on closed vci %d \n", vcc->vci); | ||
635 | break; | ||
636 | } | ||
637 | iavcc = INPH_IA_VCC(vcc); | ||
638 | if (ia_pkt_tx (vcc, skb)) { | ||
639 | skb_queue_head(&iadev->tx_backlog, skb); | ||
640 | } | ||
641 | num_desc--; | ||
642 | } | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static void ia_tx_poll (IADEV *iadev) { | ||
647 | struct atm_vcc *vcc = NULL; | ||
648 | struct sk_buff *skb = NULL, *skb1 = NULL; | ||
649 | struct ia_vcc *iavcc; | ||
650 | IARTN_Q * rtne; | ||
651 | |||
652 | ia_hack_tcq(iadev); | ||
653 | while ( (rtne = ia_deque_rtn_q(&iadev->tx_return_q))) { | ||
654 | skb = rtne->data.txskb; | ||
655 | if (!skb) { | ||
656 | printk("ia_tx_poll: skb is null\n"); | ||
657 | goto out; | ||
658 | } | ||
659 | vcc = ATM_SKB(skb)->vcc; | ||
660 | if (!vcc) { | ||
661 | printk("ia_tx_poll: vcc is null\n"); | ||
662 | dev_kfree_skb_any(skb); | ||
663 | goto out; | ||
664 | } | ||
665 | |||
666 | iavcc = INPH_IA_VCC(vcc); | ||
667 | if (!iavcc) { | ||
668 | printk("ia_tx_poll: iavcc is null\n"); | ||
669 | dev_kfree_skb_any(skb); | ||
670 | goto out; | ||
671 | } | ||
672 | |||
673 | skb1 = skb_dequeue(&iavcc->txing_skb); | ||
674 | while (skb1 && (skb1 != skb)) { | ||
675 | if (!(IA_SKB_STATE(skb1) & IA_TX_DONE)) { | ||
676 | printk("IA_tx_intr: Vci %d lost pkt!!!\n", vcc->vci); | ||
677 | } | ||
678 | IF_ERR(printk("Release the SKB not match\n");) | ||
679 | if ((vcc->pop) && (skb1->len != 0)) | ||
680 | { | ||
681 | vcc->pop(vcc, skb1); | ||
682 | IF_EVENT(printk("Tansmit Done - skb 0x%lx return\n", | ||
683 | (long)skb1);) | ||
684 | } | ||
685 | else | ||
686 | dev_kfree_skb_any(skb1); | ||
687 | skb1 = skb_dequeue(&iavcc->txing_skb); | ||
688 | } | ||
689 | if (!skb1) { | ||
690 | IF_EVENT(printk("IA: Vci %d - skb not found requed\n",vcc->vci);) | ||
691 | ia_enque_head_rtn_q (&iadev->tx_return_q, rtne); | ||
692 | break; | ||
693 | } | ||
694 | if ((vcc->pop) && (skb->len != 0)) | ||
695 | { | ||
696 | vcc->pop(vcc, skb); | ||
697 | IF_EVENT(printk("Tx Done - skb 0x%lx return\n",(long)skb);) | ||
698 | } | ||
699 | else | ||
700 | dev_kfree_skb_any(skb); | ||
701 | kfree(rtne); | ||
702 | } | ||
703 | ia_que_tx(iadev); | ||
704 | out: | ||
705 | return; | ||
706 | } | ||
707 | #if 0 | ||
708 | static void ia_eeprom_put (IADEV *iadev, u32 addr, u_short val) | ||
709 | { | ||
710 | u32 t; | ||
711 | int i; | ||
712 | /* | ||
713 | * Issue a command to enable writes to the NOVRAM | ||
714 | */ | ||
715 | NVRAM_CMD (EXTEND + EWEN); | ||
716 | NVRAM_CLR_CE; | ||
717 | /* | ||
718 | * issue the write command | ||
719 | */ | ||
720 | NVRAM_CMD(IAWRITE + addr); | ||
721 | /* | ||
722 | * Send the data, starting with D15, then D14, and so on for 16 bits | ||
723 | */ | ||
724 | for (i=15; i>=0; i--) { | ||
725 | NVRAM_CLKOUT (val & 0x8000); | ||
726 | val <<= 1; | ||
727 | } | ||
728 | NVRAM_CLR_CE; | ||
729 | CFG_OR(NVCE); | ||
730 | t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); | ||
731 | while (!(t & NVDO)) | ||
732 | t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); | ||
733 | |||
734 | NVRAM_CLR_CE; | ||
735 | /* | ||
736 | * disable writes again | ||
737 | */ | ||
738 | NVRAM_CMD(EXTEND + EWDS) | ||
739 | NVRAM_CLR_CE; | ||
740 | CFG_AND(~NVDI); | ||
741 | } | ||
742 | #endif | ||
743 | |||
744 | static u16 ia_eeprom_get (IADEV *iadev, u32 addr) | ||
745 | { | ||
746 | u_short val; | ||
747 | u32 t; | ||
748 | int i; | ||
749 | /* | ||
750 | * Read the first bit that was clocked with the falling edge of the | ||
751 | * the last command data clock | ||
752 | */ | ||
753 | NVRAM_CMD(IAREAD + addr); | ||
754 | /* | ||
755 | * Now read the rest of the bits, the next bit read is D14, then D13, | ||
756 | * and so on. | ||
757 | */ | ||
758 | val = 0; | ||
759 | for (i=15; i>=0; i--) { | ||
760 | NVRAM_CLKIN(t); | ||
761 | val |= (t << i); | ||
762 | } | ||
763 | NVRAM_CLR_CE; | ||
764 | CFG_AND(~NVDI); | ||
765 | return val; | ||
766 | } | ||
767 | |||
768 | static void ia_hw_type(IADEV *iadev) { | ||
769 | u_short memType = ia_eeprom_get(iadev, 25); | ||
770 | iadev->memType = memType; | ||
771 | if ((memType & MEM_SIZE_MASK) == MEM_SIZE_1M) { | ||
772 | iadev->num_tx_desc = IA_TX_BUF; | ||
773 | iadev->tx_buf_sz = IA_TX_BUF_SZ; | ||
774 | iadev->num_rx_desc = IA_RX_BUF; | ||
775 | iadev->rx_buf_sz = IA_RX_BUF_SZ; | ||
776 | } else if ((memType & MEM_SIZE_MASK) == MEM_SIZE_512K) { | ||
777 | if (IA_TX_BUF == DFL_TX_BUFFERS) | ||
778 | iadev->num_tx_desc = IA_TX_BUF / 2; | ||
779 | else | ||
780 | iadev->num_tx_desc = IA_TX_BUF; | ||
781 | iadev->tx_buf_sz = IA_TX_BUF_SZ; | ||
782 | if (IA_RX_BUF == DFL_RX_BUFFERS) | ||
783 | iadev->num_rx_desc = IA_RX_BUF / 2; | ||
784 | else | ||
785 | iadev->num_rx_desc = IA_RX_BUF; | ||
786 | iadev->rx_buf_sz = IA_RX_BUF_SZ; | ||
787 | } | ||
788 | else { | ||
789 | if (IA_TX_BUF == DFL_TX_BUFFERS) | ||
790 | iadev->num_tx_desc = IA_TX_BUF / 8; | ||
791 | else | ||
792 | iadev->num_tx_desc = IA_TX_BUF; | ||
793 | iadev->tx_buf_sz = IA_TX_BUF_SZ; | ||
794 | if (IA_RX_BUF == DFL_RX_BUFFERS) | ||
795 | iadev->num_rx_desc = IA_RX_BUF / 8; | ||
796 | else | ||
797 | iadev->num_rx_desc = IA_RX_BUF; | ||
798 | iadev->rx_buf_sz = IA_RX_BUF_SZ; | ||
799 | } | ||
800 | iadev->rx_pkt_ram = TX_PACKET_RAM + (iadev->num_tx_desc * iadev->tx_buf_sz); | ||
801 | IF_INIT(printk("BUF: tx=%d,sz=%d rx=%d sz= %d rx_pkt_ram=%d\n", | ||
802 | iadev->num_tx_desc, iadev->tx_buf_sz, iadev->num_rx_desc, | ||
803 | iadev->rx_buf_sz, iadev->rx_pkt_ram);) | ||
804 | |||
805 | #if 0 | ||
806 | if ((memType & FE_MASK) == FE_SINGLE_MODE) { | ||
807 | iadev->phy_type = PHY_OC3C_S; | ||
808 | else if ((memType & FE_MASK) == FE_UTP_OPTION) | ||
809 | iadev->phy_type = PHY_UTP155; | ||
810 | else | ||
811 | iadev->phy_type = PHY_OC3C_M; | ||
812 | #endif | ||
813 | |||
814 | iadev->phy_type = memType & FE_MASK; | ||
815 | IF_INIT(printk("memType = 0x%x iadev->phy_type = 0x%x\n", | ||
816 | memType,iadev->phy_type);) | ||
817 | if (iadev->phy_type == FE_25MBIT_PHY) | ||
818 | iadev->LineRate = (u32)(((25600000/8)*26)/(27*53)); | ||
819 | else if (iadev->phy_type == FE_DS3_PHY) | ||
820 | iadev->LineRate = (u32)(((44736000/8)*26)/(27*53)); | ||
821 | else if (iadev->phy_type == FE_E3_PHY) | ||
822 | iadev->LineRate = (u32)(((34368000/8)*26)/(27*53)); | ||
823 | else | ||
824 | iadev->LineRate = (u32)(ATM_OC3_PCR); | ||
825 | IF_INIT(printk("iadev->LineRate = %d \n", iadev->LineRate);) | ||
826 | |||
827 | } | ||
828 | |||
829 | static void IaFrontEndIntr(IADEV *iadev) { | ||
830 | volatile IA_SUNI *suni; | ||
831 | volatile ia_mb25_t *mb25; | ||
832 | volatile suni_pm7345_t *suni_pm7345; | ||
833 | u32 intr_status; | ||
834 | u_int frmr_intr; | ||
835 | |||
836 | if(iadev->phy_type & FE_25MBIT_PHY) { | ||
837 | mb25 = (ia_mb25_t*)iadev->phy; | ||
838 | iadev->carrier_detect = Boolean(mb25->mb25_intr_status & MB25_IS_GSB); | ||
839 | } else if (iadev->phy_type & FE_DS3_PHY) { | ||
840 | suni_pm7345 = (suni_pm7345_t *)iadev->phy; | ||
841 | /* clear FRMR interrupts */ | ||
842 | frmr_intr = suni_pm7345->suni_ds3_frm_intr_stat; | ||
843 | iadev->carrier_detect = | ||
844 | Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); | ||
845 | } else if (iadev->phy_type & FE_E3_PHY ) { | ||
846 | suni_pm7345 = (suni_pm7345_t *)iadev->phy; | ||
847 | frmr_intr = suni_pm7345->suni_e3_frm_maint_intr_ind; | ||
848 | iadev->carrier_detect = | ||
849 | Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS)); | ||
850 | } | ||
851 | else { | ||
852 | suni = (IA_SUNI *)iadev->phy; | ||
853 | intr_status = suni->suni_rsop_status & 0xff; | ||
854 | iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV)); | ||
855 | } | ||
856 | if (iadev->carrier_detect) | ||
857 | printk("IA: SUNI carrier detected\n"); | ||
858 | else | ||
859 | printk("IA: SUNI carrier lost signal\n"); | ||
860 | return; | ||
861 | } | ||
862 | |||
863 | static void ia_mb25_init (IADEV *iadev) | ||
864 | { | ||
865 | volatile ia_mb25_t *mb25 = (ia_mb25_t*)iadev->phy; | ||
866 | #if 0 | ||
867 | mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED; | ||
868 | #endif | ||
869 | mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC; | ||
870 | mb25->mb25_diag_control = 0; | ||
871 | /* | ||
872 | * Initialize carrier detect state | ||
873 | */ | ||
874 | iadev->carrier_detect = Boolean(mb25->mb25_intr_status & MB25_IS_GSB); | ||
875 | return; | ||
876 | } | ||
877 | |||
878 | static void ia_suni_pm7345_init (IADEV *iadev) | ||
879 | { | ||
880 | volatile suni_pm7345_t *suni_pm7345 = (suni_pm7345_t *)iadev->phy; | ||
881 | if (iadev->phy_type & FE_DS3_PHY) | ||
882 | { | ||
883 | iadev->carrier_detect = | ||
884 | Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); | ||
885 | suni_pm7345->suni_ds3_frm_intr_enbl = 0x17; | ||
886 | suni_pm7345->suni_ds3_frm_cfg = 1; | ||
887 | suni_pm7345->suni_ds3_tran_cfg = 1; | ||
888 | suni_pm7345->suni_config = 0; | ||
889 | suni_pm7345->suni_splr_cfg = 0; | ||
890 | suni_pm7345->suni_splt_cfg = 0; | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | iadev->carrier_detect = | ||
895 | Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat & SUNI_E3_LOS)); | ||
896 | suni_pm7345->suni_e3_frm_fram_options = 0x4; | ||
897 | suni_pm7345->suni_e3_frm_maint_options = 0x20; | ||
898 | suni_pm7345->suni_e3_frm_fram_intr_enbl = 0x1d; | ||
899 | suni_pm7345->suni_e3_frm_maint_intr_enbl = 0x30; | ||
900 | suni_pm7345->suni_e3_tran_stat_diag_options = 0x0; | ||
901 | suni_pm7345->suni_e3_tran_fram_options = 0x1; | ||
902 | suni_pm7345->suni_config = SUNI_PM7345_E3ENBL; | ||
903 | suni_pm7345->suni_splr_cfg = 0x41; | ||
904 | suni_pm7345->suni_splt_cfg = 0x41; | ||
905 | } | ||
906 | /* | ||
907 | * Enable RSOP loss of signal interrupt. | ||
908 | */ | ||
909 | suni_pm7345->suni_intr_enbl = 0x28; | ||
910 | |||
911 | /* | ||
912 | * Clear error counters | ||
913 | */ | ||
914 | suni_pm7345->suni_id_reset = 0; | ||
915 | |||
916 | /* | ||
917 | * Clear "PMCTST" in master test register. | ||
918 | */ | ||
919 | suni_pm7345->suni_master_test = 0; | ||
920 | |||
921 | suni_pm7345->suni_rxcp_ctrl = 0x2c; | ||
922 | suni_pm7345->suni_rxcp_fctrl = 0x81; | ||
923 | |||
924 | suni_pm7345->suni_rxcp_idle_pat_h1 = | ||
925 | suni_pm7345->suni_rxcp_idle_pat_h2 = | ||
926 | suni_pm7345->suni_rxcp_idle_pat_h3 = 0; | ||
927 | suni_pm7345->suni_rxcp_idle_pat_h4 = 1; | ||
928 | |||
929 | suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff; | ||
930 | suni_pm7345->suni_rxcp_idle_mask_h2 = 0xff; | ||
931 | suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff; | ||
932 | suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe; | ||
933 | |||
934 | suni_pm7345->suni_rxcp_cell_pat_h1 = | ||
935 | suni_pm7345->suni_rxcp_cell_pat_h2 = | ||
936 | suni_pm7345->suni_rxcp_cell_pat_h3 = 0; | ||
937 | suni_pm7345->suni_rxcp_cell_pat_h4 = 1; | ||
938 | |||
939 | suni_pm7345->suni_rxcp_cell_mask_h1 = | ||
940 | suni_pm7345->suni_rxcp_cell_mask_h2 = | ||
941 | suni_pm7345->suni_rxcp_cell_mask_h3 = | ||
942 | suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff; | ||
943 | |||
944 | suni_pm7345->suni_txcp_ctrl = 0xa4; | ||
945 | suni_pm7345->suni_txcp_intr_en_sts = 0x10; | ||
946 | suni_pm7345->suni_txcp_idle_pat_h5 = 0x55; | ||
947 | |||
948 | suni_pm7345->suni_config &= ~(SUNI_PM7345_LLB | | ||
949 | SUNI_PM7345_CLB | | ||
950 | SUNI_PM7345_DLB | | ||
951 | SUNI_PM7345_PLB); | ||
952 | #ifdef __SNMP__ | ||
953 | suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE; | ||
954 | #endif /* __SNMP__ */ | ||
955 | return; | ||
956 | } | ||
957 | |||
958 | |||
959 | /***************************** IA_LIB END *****************************/ | ||
960 | |||
961 | static int tcnter = 0; | ||
962 | static void xdump( u_char* cp, int length, char* prefix ) | ||
963 | { | ||
964 | int col, count; | ||
965 | u_char prntBuf[120]; | ||
966 | u_char* pBuf = prntBuf; | ||
967 | count = 0; | ||
968 | while(count < length){ | ||
969 | pBuf += sprintf( pBuf, "%s", prefix ); | ||
970 | for(col = 0;count + col < length && col < 16; col++){ | ||
971 | if (col != 0 && (col % 4) == 0) | ||
972 | pBuf += sprintf( pBuf, " " ); | ||
973 | pBuf += sprintf( pBuf, "%02X ", cp[count + col] ); | ||
974 | } | ||
975 | while(col++ < 16){ /* pad end of buffer with blanks */ | ||
976 | if ((col % 4) == 0) | ||
977 | sprintf( pBuf, " " ); | ||
978 | pBuf += sprintf( pBuf, " " ); | ||
979 | } | ||
980 | pBuf += sprintf( pBuf, " " ); | ||
981 | for(col = 0;count + col < length && col < 16; col++){ | ||
982 | if (isprint((int)cp[count + col])) | ||
983 | pBuf += sprintf( pBuf, "%c", cp[count + col] ); | ||
984 | else | ||
985 | pBuf += sprintf( pBuf, "." ); | ||
986 | } | ||
987 | sprintf( pBuf, "\n" ); | ||
988 | // SPrint(prntBuf); | ||
989 | printk(prntBuf); | ||
990 | count += col; | ||
991 | pBuf = prntBuf; | ||
992 | } | ||
993 | |||
994 | } /* close xdump(... */ | ||
995 | |||
996 | |||
997 | static struct atm_dev *ia_boards = NULL; | ||
998 | |||
999 | #define ACTUAL_RAM_BASE \ | ||
1000 | RAM_BASE*((iadev->mem)/(128 * 1024)) | ||
1001 | #define ACTUAL_SEG_RAM_BASE \ | ||
1002 | IPHASE5575_FRAG_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024)) | ||
1003 | #define ACTUAL_REASS_RAM_BASE \ | ||
1004 | IPHASE5575_REASS_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024)) | ||
1005 | |||
1006 | |||
1007 | /*-- some utilities and memory allocation stuff will come here -------------*/ | ||
1008 | |||
1009 | static void desc_dbg(IADEV *iadev) { | ||
1010 | |||
1011 | u_short tcq_wr_ptr, tcq_st_ptr, tcq_ed_ptr; | ||
1012 | u32 i; | ||
1013 | void __iomem *tmp; | ||
1014 | // regval = readl((u32)ia_cmds->maddr); | ||
1015 | tcq_wr_ptr = readw(iadev->seg_reg+TCQ_WR_PTR); | ||
1016 | printk("B_tcq_wr = 0x%x desc = %d last desc = %d\n", | ||
1017 | tcq_wr_ptr, readw(iadev->seg_ram+tcq_wr_ptr), | ||
1018 | readw(iadev->seg_ram+tcq_wr_ptr-2)); | ||
1019 | printk(" host_tcq_wr = 0x%x host_tcq_rd = 0x%x \n", iadev->host_tcq_wr, | ||
1020 | iadev->ffL.tcq_rd); | ||
1021 | tcq_st_ptr = readw(iadev->seg_reg+TCQ_ST_ADR); | ||
1022 | tcq_ed_ptr = readw(iadev->seg_reg+TCQ_ED_ADR); | ||
1023 | printk("tcq_st_ptr = 0x%x tcq_ed_ptr = 0x%x \n", tcq_st_ptr, tcq_ed_ptr); | ||
1024 | i = 0; | ||
1025 | while (tcq_st_ptr != tcq_ed_ptr) { | ||
1026 | tmp = iadev->seg_ram+tcq_st_ptr; | ||
1027 | printk("TCQ slot %d desc = %d Addr = %p\n", i++, readw(tmp), tmp); | ||
1028 | tcq_st_ptr += 2; | ||
1029 | } | ||
1030 | for(i=0; i <iadev->num_tx_desc; i++) | ||
1031 | printk("Desc_tbl[%d] = %d \n", i, iadev->desc_tbl[i].timestamp); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | /*----------------------------- Recieving side stuff --------------------------*/ | ||
1036 | |||
1037 | static void rx_excp_rcvd(struct atm_dev *dev) | ||
1038 | { | ||
1039 | #if 0 /* closing the receiving size will cause too many excp int */ | ||
1040 | IADEV *iadev; | ||
1041 | u_short state; | ||
1042 | u_short excpq_rd_ptr; | ||
1043 | //u_short *ptr; | ||
1044 | int vci, error = 1; | ||
1045 | iadev = INPH_IA_DEV(dev); | ||
1046 | state = readl(iadev->reass_reg + STATE_REG) & 0xffff; | ||
1047 | while((state & EXCPQ_EMPTY) != EXCPQ_EMPTY) | ||
1048 | { printk("state = %x \n", state); | ||
1049 | excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_RD_PTR) & 0xffff; | ||
1050 | printk("state = %x excpq_rd_ptr = %x \n", state, excpq_rd_ptr); | ||
1051 | if (excpq_rd_ptr == *(u16*)(iadev->reass_reg + EXCP_Q_WR_PTR)) | ||
1052 | IF_ERR(printk("excpq_rd_ptr is wrong!!!\n");) | ||
1053 | // TODO: update exception stat | ||
1054 | vci = readw(iadev->reass_ram+excpq_rd_ptr); | ||
1055 | error = readw(iadev->reass_ram+excpq_rd_ptr+2) & 0x0007; | ||
1056 | // pwang_test | ||
1057 | excpq_rd_ptr += 4; | ||
1058 | if (excpq_rd_ptr > (readw(iadev->reass_reg + EXCP_Q_ED_ADR)& 0xffff)) | ||
1059 | excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_ST_ADR)& 0xffff; | ||
1060 | writew( excpq_rd_ptr, iadev->reass_reg + EXCP_Q_RD_PTR); | ||
1061 | state = readl(iadev->reass_reg + STATE_REG) & 0xffff; | ||
1062 | } | ||
1063 | #endif | ||
1064 | } | ||
1065 | |||
1066 | static void free_desc(struct atm_dev *dev, int desc) | ||
1067 | { | ||
1068 | IADEV *iadev; | ||
1069 | iadev = INPH_IA_DEV(dev); | ||
1070 | writew(desc, iadev->reass_ram+iadev->rfL.fdq_wr); | ||
1071 | iadev->rfL.fdq_wr +=2; | ||
1072 | if (iadev->rfL.fdq_wr > iadev->rfL.fdq_ed) | ||
1073 | iadev->rfL.fdq_wr = iadev->rfL.fdq_st; | ||
1074 | writew(iadev->rfL.fdq_wr, iadev->reass_reg+FREEQ_WR_PTR); | ||
1075 | } | ||
1076 | |||
1077 | |||
1078 | static int rx_pkt(struct atm_dev *dev) | ||
1079 | { | ||
1080 | IADEV *iadev; | ||
1081 | struct atm_vcc *vcc; | ||
1082 | unsigned short status; | ||
1083 | struct rx_buf_desc __iomem *buf_desc_ptr; | ||
1084 | int desc; | ||
1085 | struct dle* wr_ptr; | ||
1086 | int len; | ||
1087 | struct sk_buff *skb; | ||
1088 | u_int buf_addr, dma_addr; | ||
1089 | |||
1090 | iadev = INPH_IA_DEV(dev); | ||
1091 | if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff)) | ||
1092 | { | ||
1093 | printk(KERN_ERR DEV_LABEL "(itf %d) Receive queue empty\n", dev->number); | ||
1094 | return -EINVAL; | ||
1095 | } | ||
1096 | /* mask 1st 3 bits to get the actual descno. */ | ||
1097 | desc = readw(iadev->reass_ram+iadev->rfL.pcq_rd) & 0x1fff; | ||
1098 | IF_RX(printk("reass_ram = %p iadev->rfL.pcq_rd = 0x%x desc = %d\n", | ||
1099 | iadev->reass_ram, iadev->rfL.pcq_rd, desc); | ||
1100 | printk(" pcq_wr_ptr = 0x%x\n", | ||
1101 | readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff);) | ||
1102 | /* update the read pointer - maybe we shud do this in the end*/ | ||
1103 | if ( iadev->rfL.pcq_rd== iadev->rfL.pcq_ed) | ||
1104 | iadev->rfL.pcq_rd = iadev->rfL.pcq_st; | ||
1105 | else | ||
1106 | iadev->rfL.pcq_rd += 2; | ||
1107 | writew(iadev->rfL.pcq_rd, iadev->reass_reg+PCQ_RD_PTR); | ||
1108 | |||
1109 | /* get the buffer desc entry. | ||
1110 | update stuff. - doesn't seem to be any update necessary | ||
1111 | */ | ||
1112 | buf_desc_ptr = iadev->RX_DESC_BASE_ADDR; | ||
1113 | /* make the ptr point to the corresponding buffer desc entry */ | ||
1114 | buf_desc_ptr += desc; | ||
1115 | if (!desc || (desc > iadev->num_rx_desc) || | ||
1116 | ((buf_desc_ptr->vc_index & 0xffff) > iadev->num_vc)) { | ||
1117 | free_desc(dev, desc); | ||
1118 | IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);) | ||
1119 | return -1; | ||
1120 | } | ||
1121 | vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff]; | ||
1122 | if (!vcc) | ||
1123 | { | ||
1124 | free_desc(dev, desc); | ||
1125 | printk("IA: null vcc, drop PDU\n"); | ||
1126 | return -1; | ||
1127 | } | ||
1128 | |||
1129 | |||
1130 | /* might want to check the status bits for errors */ | ||
1131 | status = (u_short) (buf_desc_ptr->desc_mode); | ||
1132 | if (status & (RX_CER | RX_PTE | RX_OFL)) | ||
1133 | { | ||
1134 | atomic_inc(&vcc->stats->rx_err); | ||
1135 | IF_ERR(printk("IA: bad packet, dropping it");) | ||
1136 | if (status & RX_CER) { | ||
1137 | IF_ERR(printk(" cause: packet CRC error\n");) | ||
1138 | } | ||
1139 | else if (status & RX_PTE) { | ||
1140 | IF_ERR(printk(" cause: packet time out\n");) | ||
1141 | } | ||
1142 | else { | ||
1143 | IF_ERR(printk(" cause: buffer over flow\n");) | ||
1144 | } | ||
1145 | goto out_free_desc; | ||
1146 | } | ||
1147 | |||
1148 | /* | ||
1149 | build DLE. | ||
1150 | */ | ||
1151 | |||
1152 | buf_addr = (buf_desc_ptr->buf_start_hi << 16) | buf_desc_ptr->buf_start_lo; | ||
1153 | dma_addr = (buf_desc_ptr->dma_start_hi << 16) | buf_desc_ptr->dma_start_lo; | ||
1154 | len = dma_addr - buf_addr; | ||
1155 | if (len > iadev->rx_buf_sz) { | ||
1156 | printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz); | ||
1157 | atomic_inc(&vcc->stats->rx_err); | ||
1158 | goto out_free_desc; | ||
1159 | } | ||
1160 | |||
1161 | if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) { | ||
1162 | if (vcc->vci < 32) | ||
1163 | printk("Drop control packets\n"); | ||
1164 | goto out_free_desc; | ||
1165 | } | ||
1166 | skb_put(skb,len); | ||
1167 | // pwang_test | ||
1168 | ATM_SKB(skb)->vcc = vcc; | ||
1169 | ATM_DESC(skb) = desc; | ||
1170 | skb_queue_tail(&iadev->rx_dma_q, skb); | ||
1171 | |||
1172 | /* Build the DLE structure */ | ||
1173 | wr_ptr = iadev->rx_dle_q.write; | ||
1174 | wr_ptr->sys_pkt_addr = pci_map_single(iadev->pci, skb->data, | ||
1175 | len, PCI_DMA_FROMDEVICE); | ||
1176 | wr_ptr->local_pkt_addr = buf_addr; | ||
1177 | wr_ptr->bytes = len; /* We don't know this do we ?? */ | ||
1178 | wr_ptr->mode = DMA_INT_ENABLE; | ||
1179 | |||
1180 | /* shud take care of wrap around here too. */ | ||
1181 | if(++wr_ptr == iadev->rx_dle_q.end) | ||
1182 | wr_ptr = iadev->rx_dle_q.start; | ||
1183 | iadev->rx_dle_q.write = wr_ptr; | ||
1184 | udelay(1); | ||
1185 | /* Increment transaction counter */ | ||
1186 | writel(1, iadev->dma+IPHASE5575_RX_COUNTER); | ||
1187 | out: return 0; | ||
1188 | out_free_desc: | ||
1189 | free_desc(dev, desc); | ||
1190 | goto out; | ||
1191 | } | ||
1192 | |||
1193 | static void rx_intr(struct atm_dev *dev) | ||
1194 | { | ||
1195 | IADEV *iadev; | ||
1196 | u_short status; | ||
1197 | u_short state, i; | ||
1198 | |||
1199 | iadev = INPH_IA_DEV(dev); | ||
1200 | status = readl(iadev->reass_reg+REASS_INTR_STATUS_REG) & 0xffff; | ||
1201 | IF_EVENT(printk("rx_intr: status = 0x%x\n", status);) | ||
1202 | if (status & RX_PKT_RCVD) | ||
1203 | { | ||
1204 | /* do something */ | ||
1205 | /* Basically recvd an interrupt for receving a packet. | ||
1206 | A descriptor would have been written to the packet complete | ||
1207 | queue. Get all the descriptors and set up dma to move the | ||
1208 | packets till the packet complete queue is empty.. | ||
1209 | */ | ||
1210 | state = readl(iadev->reass_reg + STATE_REG) & 0xffff; | ||
1211 | IF_EVENT(printk("Rx intr status: RX_PKT_RCVD %08x\n", status);) | ||
1212 | while(!(state & PCQ_EMPTY)) | ||
1213 | { | ||
1214 | rx_pkt(dev); | ||
1215 | state = readl(iadev->reass_reg + STATE_REG) & 0xffff; | ||
1216 | } | ||
1217 | iadev->rxing = 1; | ||
1218 | } | ||
1219 | if (status & RX_FREEQ_EMPT) | ||
1220 | { | ||
1221 | if (iadev->rxing) { | ||
1222 | iadev->rx_tmp_cnt = iadev->rx_pkt_cnt; | ||
1223 | iadev->rx_tmp_jif = jiffies; | ||
1224 | iadev->rxing = 0; | ||
1225 | } | ||
1226 | else if (((jiffies - iadev->rx_tmp_jif) > 50) && | ||
1227 | ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) { | ||
1228 | for (i = 1; i <= iadev->num_rx_desc; i++) | ||
1229 | free_desc(dev, i); | ||
1230 | printk("Test logic RUN!!!!\n"); | ||
1231 | writew( ~(RX_FREEQ_EMPT|RX_EXCP_RCVD),iadev->reass_reg+REASS_MASK_REG); | ||
1232 | iadev->rxing = 1; | ||
1233 | } | ||
1234 | IF_EVENT(printk("Rx intr status: RX_FREEQ_EMPT %08x\n", status);) | ||
1235 | } | ||
1236 | |||
1237 | if (status & RX_EXCP_RCVD) | ||
1238 | { | ||
1239 | /* probably need to handle the exception queue also. */ | ||
1240 | IF_EVENT(printk("Rx intr status: RX_EXCP_RCVD %08x\n", status);) | ||
1241 | rx_excp_rcvd(dev); | ||
1242 | } | ||
1243 | |||
1244 | |||
1245 | if (status & RX_RAW_RCVD) | ||
1246 | { | ||
1247 | /* need to handle the raw incoming cells. This deepnds on | ||
1248 | whether we have programmed to receive the raw cells or not. | ||
1249 | Else ignore. */ | ||
1250 | IF_EVENT(printk("Rx intr status: RX_RAW_RCVD %08x\n", status);) | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | |||
1255 | static void rx_dle_intr(struct atm_dev *dev) | ||
1256 | { | ||
1257 | IADEV *iadev; | ||
1258 | struct atm_vcc *vcc; | ||
1259 | struct sk_buff *skb; | ||
1260 | int desc; | ||
1261 | u_short state; | ||
1262 | struct dle *dle, *cur_dle; | ||
1263 | u_int dle_lp; | ||
1264 | int len; | ||
1265 | iadev = INPH_IA_DEV(dev); | ||
1266 | |||
1267 | /* free all the dles done, that is just update our own dle read pointer | ||
1268 | - do we really need to do this. Think not. */ | ||
1269 | /* DMA is done, just get all the recevie buffers from the rx dma queue | ||
1270 | and push them up to the higher layer protocol. Also free the desc | ||
1271 | associated with the buffer. */ | ||
1272 | dle = iadev->rx_dle_q.read; | ||
1273 | dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1); | ||
1274 | cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4)); | ||
1275 | while(dle != cur_dle) | ||
1276 | { | ||
1277 | /* free the DMAed skb */ | ||
1278 | skb = skb_dequeue(&iadev->rx_dma_q); | ||
1279 | if (!skb) | ||
1280 | goto INCR_DLE; | ||
1281 | desc = ATM_DESC(skb); | ||
1282 | free_desc(dev, desc); | ||
1283 | |||
1284 | if (!(len = skb->len)) | ||
1285 | { | ||
1286 | printk("rx_dle_intr: skb len 0\n"); | ||
1287 | dev_kfree_skb_any(skb); | ||
1288 | } | ||
1289 | else | ||
1290 | { | ||
1291 | struct cpcs_trailer *trailer; | ||
1292 | u_short length; | ||
1293 | struct ia_vcc *ia_vcc; | ||
1294 | |||
1295 | pci_unmap_single(iadev->pci, iadev->rx_dle_q.write->sys_pkt_addr, | ||
1296 | len, PCI_DMA_FROMDEVICE); | ||
1297 | /* no VCC related housekeeping done as yet. lets see */ | ||
1298 | vcc = ATM_SKB(skb)->vcc; | ||
1299 | if (!vcc) { | ||
1300 | printk("IA: null vcc\n"); | ||
1301 | dev_kfree_skb_any(skb); | ||
1302 | goto INCR_DLE; | ||
1303 | } | ||
1304 | ia_vcc = INPH_IA_VCC(vcc); | ||
1305 | if (ia_vcc == NULL) | ||
1306 | { | ||
1307 | atomic_inc(&vcc->stats->rx_err); | ||
1308 | dev_kfree_skb_any(skb); | ||
1309 | atm_return(vcc, atm_guess_pdu2truesize(len)); | ||
1310 | goto INCR_DLE; | ||
1311 | } | ||
1312 | // get real pkt length pwang_test | ||
1313 | trailer = (struct cpcs_trailer*)((u_char *)skb->data + | ||
1314 | skb->len - sizeof(*trailer)); | ||
1315 | length = swap(trailer->length); | ||
1316 | if ((length > iadev->rx_buf_sz) || (length > | ||
1317 | (skb->len - sizeof(struct cpcs_trailer)))) | ||
1318 | { | ||
1319 | atomic_inc(&vcc->stats->rx_err); | ||
1320 | IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)", | ||
1321 | length, skb->len);) | ||
1322 | dev_kfree_skb_any(skb); | ||
1323 | atm_return(vcc, atm_guess_pdu2truesize(len)); | ||
1324 | goto INCR_DLE; | ||
1325 | } | ||
1326 | skb_trim(skb, length); | ||
1327 | |||
1328 | /* Display the packet */ | ||
1329 | IF_RXPKT(printk("\nDmad Recvd data: len = %d \n", skb->len); | ||
1330 | xdump(skb->data, skb->len, "RX: "); | ||
1331 | printk("\n");) | ||
1332 | |||
1333 | IF_RX(printk("rx_dle_intr: skb push");) | ||
1334 | vcc->push(vcc,skb); | ||
1335 | atomic_inc(&vcc->stats->rx); | ||
1336 | iadev->rx_pkt_cnt++; | ||
1337 | } | ||
1338 | INCR_DLE: | ||
1339 | if (++dle == iadev->rx_dle_q.end) | ||
1340 | dle = iadev->rx_dle_q.start; | ||
1341 | } | ||
1342 | iadev->rx_dle_q.read = dle; | ||
1343 | |||
1344 | /* if the interrupts are masked because there were no free desc available, | ||
1345 | unmask them now. */ | ||
1346 | if (!iadev->rxing) { | ||
1347 | state = readl(iadev->reass_reg + STATE_REG) & 0xffff; | ||
1348 | if (!(state & FREEQ_EMPTY)) { | ||
1349 | state = readl(iadev->reass_reg + REASS_MASK_REG) & 0xffff; | ||
1350 | writel(state & ~(RX_FREEQ_EMPT |/* RX_EXCP_RCVD |*/ RX_PKT_RCVD), | ||
1351 | iadev->reass_reg+REASS_MASK_REG); | ||
1352 | iadev->rxing++; | ||
1353 | } | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | |||
1358 | static int open_rx(struct atm_vcc *vcc) | ||
1359 | { | ||
1360 | IADEV *iadev; | ||
1361 | u_short __iomem *vc_table; | ||
1362 | u_short __iomem *reass_ptr; | ||
1363 | IF_EVENT(printk("iadev: open_rx %d.%d\n", vcc->vpi, vcc->vci);) | ||
1364 | |||
1365 | if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0; | ||
1366 | iadev = INPH_IA_DEV(vcc->dev); | ||
1367 | if (vcc->qos.rxtp.traffic_class == ATM_ABR) { | ||
1368 | if (iadev->phy_type & FE_25MBIT_PHY) { | ||
1369 | printk("IA: ABR not support\n"); | ||
1370 | return -EINVAL; | ||
1371 | } | ||
1372 | } | ||
1373 | /* Make only this VCI in the vc table valid and let all | ||
1374 | others be invalid entries */ | ||
1375 | vc_table = iadev->reass_ram+RX_VC_TABLE*iadev->memSize; | ||
1376 | vc_table += vcc->vci; | ||
1377 | /* mask the last 6 bits and OR it with 3 for 1K VCs */ | ||
1378 | |||
1379 | *vc_table = vcc->vci << 6; | ||
1380 | /* Also keep a list of open rx vcs so that we can attach them with | ||
1381 | incoming PDUs later. */ | ||
1382 | if ((vcc->qos.rxtp.traffic_class == ATM_ABR) || | ||
1383 | (vcc->qos.txtp.traffic_class == ATM_ABR)) | ||
1384 | { | ||
1385 | srv_cls_param_t srv_p; | ||
1386 | init_abr_vc(iadev, &srv_p); | ||
1387 | ia_open_abr_vc(iadev, &srv_p, vcc, 0); | ||
1388 | } | ||
1389 | else { /* for UBR later may need to add CBR logic */ | ||
1390 | reass_ptr = iadev->reass_ram+REASS_TABLE*iadev->memSize; | ||
1391 | reass_ptr += vcc->vci; | ||
1392 | *reass_ptr = NO_AAL5_PKT; | ||
1393 | } | ||
1394 | |||
1395 | if (iadev->rx_open[vcc->vci]) | ||
1396 | printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n", | ||
1397 | vcc->dev->number, vcc->vci); | ||
1398 | iadev->rx_open[vcc->vci] = vcc; | ||
1399 | return 0; | ||
1400 | } | ||
1401 | |||
1402 | static int rx_init(struct atm_dev *dev) | ||
1403 | { | ||
1404 | IADEV *iadev; | ||
1405 | struct rx_buf_desc __iomem *buf_desc_ptr; | ||
1406 | unsigned long rx_pkt_start = 0; | ||
1407 | void *dle_addr; | ||
1408 | struct abr_vc_table *abr_vc_table; | ||
1409 | u16 *vc_table; | ||
1410 | u16 *reass_table; | ||
1411 | u16 *ptr16; | ||
1412 | int i,j, vcsize_sel; | ||
1413 | u_short freeq_st_adr; | ||
1414 | u_short *freeq_start; | ||
1415 | |||
1416 | iadev = INPH_IA_DEV(dev); | ||
1417 | // spin_lock_init(&iadev->rx_lock); | ||
1418 | |||
1419 | /* Allocate 4k bytes - more aligned than needed (4k boundary) */ | ||
1420 | dle_addr = pci_alloc_consistent(iadev->pci, DLE_TOTAL_SIZE, | ||
1421 | &iadev->rx_dle_dma); | ||
1422 | if (!dle_addr) { | ||
1423 | printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n"); | ||
1424 | goto err_out; | ||
1425 | } | ||
1426 | iadev->rx_dle_q.start = (struct dle*)dle_addr; | ||
1427 | iadev->rx_dle_q.read = iadev->rx_dle_q.start; | ||
1428 | iadev->rx_dle_q.write = iadev->rx_dle_q.start; | ||
1429 | iadev->rx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES); | ||
1430 | /* the end of the dle q points to the entry after the last | ||
1431 | DLE that can be used. */ | ||
1432 | |||
1433 | /* write the upper 20 bits of the start address to rx list address register */ | ||
1434 | writel(iadev->rx_dle_dma & 0xfffff000, | ||
1435 | iadev->dma + IPHASE5575_RX_LIST_ADDR); | ||
1436 | IF_INIT(printk("Tx Dle list addr: 0x%08x value: 0x%0x\n", | ||
1437 | (u32)(iadev->dma+IPHASE5575_TX_LIST_ADDR), | ||
1438 | *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR)); | ||
1439 | printk("Rx Dle list addr: 0x%08x value: 0x%0x\n", | ||
1440 | (u32)(iadev->dma+IPHASE5575_RX_LIST_ADDR), | ||
1441 | *(u32*)(iadev->dma+IPHASE5575_RX_LIST_ADDR));) | ||
1442 | |||
1443 | writew(0xffff, iadev->reass_reg+REASS_MASK_REG); | ||
1444 | writew(0, iadev->reass_reg+MODE_REG); | ||
1445 | writew(RESET_REASS, iadev->reass_reg+REASS_COMMAND_REG); | ||
1446 | |||
1447 | /* Receive side control memory map | ||
1448 | ------------------------------- | ||
1449 | |||
1450 | Buffer descr 0x0000 (736 - 23K) | ||
1451 | VP Table 0x5c00 (256 - 512) | ||
1452 | Except q 0x5e00 (128 - 512) | ||
1453 | Free buffer q 0x6000 (1K - 2K) | ||
1454 | Packet comp q 0x6800 (1K - 2K) | ||
1455 | Reass Table 0x7000 (1K - 2K) | ||
1456 | VC Table 0x7800 (1K - 2K) | ||
1457 | ABR VC Table 0x8000 (1K - 32K) | ||
1458 | */ | ||
1459 | |||
1460 | /* Base address for Buffer Descriptor Table */ | ||
1461 | writew(RX_DESC_BASE >> 16, iadev->reass_reg+REASS_DESC_BASE); | ||
1462 | /* Set the buffer size register */ | ||
1463 | writew(iadev->rx_buf_sz, iadev->reass_reg+BUF_SIZE); | ||
1464 | |||
1465 | /* Initialize each entry in the Buffer Descriptor Table */ | ||
1466 | iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize; | ||
1467 | buf_desc_ptr = iadev->RX_DESC_BASE_ADDR; | ||
1468 | memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); | ||
1469 | buf_desc_ptr++; | ||
1470 | rx_pkt_start = iadev->rx_pkt_ram; | ||
1471 | for(i=1; i<=iadev->num_rx_desc; i++) | ||
1472 | { | ||
1473 | memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); | ||
1474 | buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16; | ||
1475 | buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff; | ||
1476 | buf_desc_ptr++; | ||
1477 | rx_pkt_start += iadev->rx_buf_sz; | ||
1478 | } | ||
1479 | IF_INIT(printk("Rx Buffer desc ptr: 0x%0x\n", (u32)(buf_desc_ptr));) | ||
1480 | i = FREE_BUF_DESC_Q*iadev->memSize; | ||
1481 | writew(i >> 16, iadev->reass_reg+REASS_QUEUE_BASE); | ||
1482 | writew(i, iadev->reass_reg+FREEQ_ST_ADR); | ||
1483 | writew(i+iadev->num_rx_desc*sizeof(u_short), | ||
1484 | iadev->reass_reg+FREEQ_ED_ADR); | ||
1485 | writew(i, iadev->reass_reg+FREEQ_RD_PTR); | ||
1486 | writew(i+iadev->num_rx_desc*sizeof(u_short), | ||
1487 | iadev->reass_reg+FREEQ_WR_PTR); | ||
1488 | /* Fill the FREEQ with all the free descriptors. */ | ||
1489 | freeq_st_adr = readw(iadev->reass_reg+FREEQ_ST_ADR); | ||
1490 | freeq_start = (u_short *)(iadev->reass_ram+freeq_st_adr); | ||
1491 | for(i=1; i<=iadev->num_rx_desc; i++) | ||
1492 | { | ||
1493 | *freeq_start = (u_short)i; | ||
1494 | freeq_start++; | ||
1495 | } | ||
1496 | IF_INIT(printk("freeq_start: 0x%0x\n", (u32)freeq_start);) | ||
1497 | /* Packet Complete Queue */ | ||
1498 | i = (PKT_COMP_Q * iadev->memSize) & 0xffff; | ||
1499 | writew(i, iadev->reass_reg+PCQ_ST_ADR); | ||
1500 | writew(i+iadev->num_vc*sizeof(u_short), iadev->reass_reg+PCQ_ED_ADR); | ||
1501 | writew(i, iadev->reass_reg+PCQ_RD_PTR); | ||
1502 | writew(i, iadev->reass_reg+PCQ_WR_PTR); | ||
1503 | |||
1504 | /* Exception Queue */ | ||
1505 | i = (EXCEPTION_Q * iadev->memSize) & 0xffff; | ||
1506 | writew(i, iadev->reass_reg+EXCP_Q_ST_ADR); | ||
1507 | writew(i + NUM_RX_EXCP * sizeof(RX_ERROR_Q), | ||
1508 | iadev->reass_reg+EXCP_Q_ED_ADR); | ||
1509 | writew(i, iadev->reass_reg+EXCP_Q_RD_PTR); | ||
1510 | writew(i, iadev->reass_reg+EXCP_Q_WR_PTR); | ||
1511 | |||
1512 | /* Load local copy of FREEQ and PCQ ptrs */ | ||
1513 | iadev->rfL.fdq_st = readw(iadev->reass_reg+FREEQ_ST_ADR) & 0xffff; | ||
1514 | iadev->rfL.fdq_ed = readw(iadev->reass_reg+FREEQ_ED_ADR) & 0xffff ; | ||
1515 | iadev->rfL.fdq_rd = readw(iadev->reass_reg+FREEQ_RD_PTR) & 0xffff; | ||
1516 | iadev->rfL.fdq_wr = readw(iadev->reass_reg+FREEQ_WR_PTR) & 0xffff; | ||
1517 | iadev->rfL.pcq_st = readw(iadev->reass_reg+PCQ_ST_ADR) & 0xffff; | ||
1518 | iadev->rfL.pcq_ed = readw(iadev->reass_reg+PCQ_ED_ADR) & 0xffff; | ||
1519 | iadev->rfL.pcq_rd = readw(iadev->reass_reg+PCQ_RD_PTR) & 0xffff; | ||
1520 | iadev->rfL.pcq_wr = readw(iadev->reass_reg+PCQ_WR_PTR) & 0xffff; | ||
1521 | |||
1522 | IF_INIT(printk("INIT:pcq_st:0x%x pcq_ed:0x%x pcq_rd:0x%x pcq_wr:0x%x", | ||
1523 | iadev->rfL.pcq_st, iadev->rfL.pcq_ed, iadev->rfL.pcq_rd, | ||
1524 | iadev->rfL.pcq_wr);) | ||
1525 | /* just for check - no VP TBL */ | ||
1526 | /* VP Table */ | ||
1527 | /* writew(0x0b80, iadev->reass_reg+VP_LKUP_BASE); */ | ||
1528 | /* initialize VP Table for invalid VPIs | ||
1529 | - I guess we can write all 1s or 0x000f in the entire memory | ||
1530 | space or something similar. | ||
1531 | */ | ||
1532 | |||
1533 | /* This seems to work and looks right to me too !!! */ | ||
1534 | i = REASS_TABLE * iadev->memSize; | ||
1535 | writew((i >> 3), iadev->reass_reg+REASS_TABLE_BASE); | ||
1536 | /* initialize Reassembly table to I don't know what ???? */ | ||
1537 | reass_table = (u16 *)(iadev->reass_ram+i); | ||
1538 | j = REASS_TABLE_SZ * iadev->memSize; | ||
1539 | for(i=0; i < j; i++) | ||
1540 | *reass_table++ = NO_AAL5_PKT; | ||
1541 | i = 8*1024; | ||
1542 | vcsize_sel = 0; | ||
1543 | while (i != iadev->num_vc) { | ||
1544 | i /= 2; | ||
1545 | vcsize_sel++; | ||
1546 | } | ||
1547 | i = RX_VC_TABLE * iadev->memSize; | ||
1548 | writew(((i>>3) & 0xfff8) | vcsize_sel, iadev->reass_reg+VC_LKUP_BASE); | ||
1549 | vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize); | ||
1550 | j = RX_VC_TABLE_SZ * iadev->memSize; | ||
1551 | for(i = 0; i < j; i++) | ||
1552 | { | ||
1553 | /* shift the reassembly pointer by 3 + lower 3 bits of | ||
1554 | vc_lkup_base register (=3 for 1K VCs) and the last byte | ||
1555 | is those low 3 bits. | ||
1556 | Shall program this later. | ||
1557 | */ | ||
1558 | *vc_table = (i << 6) | 15; /* for invalid VCI */ | ||
1559 | vc_table++; | ||
1560 | } | ||
1561 | /* ABR VC table */ | ||
1562 | i = ABR_VC_TABLE * iadev->memSize; | ||
1563 | writew(i >> 3, iadev->reass_reg+ABR_LKUP_BASE); | ||
1564 | |||
1565 | i = ABR_VC_TABLE * iadev->memSize; | ||
1566 | abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i); | ||
1567 | j = REASS_TABLE_SZ * iadev->memSize; | ||
1568 | memset ((char*)abr_vc_table, 0, j * sizeof(*abr_vc_table)); | ||
1569 | for(i = 0; i < j; i++) { | ||
1570 | abr_vc_table->rdf = 0x0003; | ||
1571 | abr_vc_table->air = 0x5eb1; | ||
1572 | abr_vc_table++; | ||
1573 | } | ||
1574 | |||
1575 | /* Initialize other registers */ | ||
1576 | |||
1577 | /* VP Filter Register set for VC Reassembly only */ | ||
1578 | writew(0xff00, iadev->reass_reg+VP_FILTER); | ||
1579 | writew(0, iadev->reass_reg+XTRA_RM_OFFSET); | ||
1580 | writew(0x1, iadev->reass_reg+PROTOCOL_ID); | ||
1581 | |||
1582 | /* Packet Timeout Count related Registers : | ||
1583 | Set packet timeout to occur in about 3 seconds | ||
1584 | Set Packet Aging Interval count register to overflow in about 4 us | ||
1585 | */ | ||
1586 | writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT ); | ||
1587 | ptr16 = (u16*)j; | ||
1588 | i = ((u32)ptr16 >> 6) & 0xff; | ||
1589 | ptr16 += j - 1; | ||
1590 | i |=(((u32)ptr16 << 2) & 0xff00); | ||
1591 | writew(i, iadev->reass_reg+TMOUT_RANGE); | ||
1592 | /* initiate the desc_tble */ | ||
1593 | for(i=0; i<iadev->num_tx_desc;i++) | ||
1594 | iadev->desc_tbl[i].timestamp = 0; | ||
1595 | |||
1596 | /* to clear the interrupt status register - read it */ | ||
1597 | readw(iadev->reass_reg+REASS_INTR_STATUS_REG); | ||
1598 | |||
1599 | /* Mask Register - clear it */ | ||
1600 | writew(~(RX_FREEQ_EMPT|RX_PKT_RCVD), iadev->reass_reg+REASS_MASK_REG); | ||
1601 | |||
1602 | skb_queue_head_init(&iadev->rx_dma_q); | ||
1603 | iadev->rx_free_desc_qhead = NULL; | ||
1604 | iadev->rx_open = kmalloc(4*iadev->num_vc,GFP_KERNEL); | ||
1605 | if (!iadev->rx_open) | ||
1606 | { | ||
1607 | printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n", | ||
1608 | dev->number); | ||
1609 | goto err_free_dle; | ||
1610 | } | ||
1611 | memset(iadev->rx_open, 0, 4*iadev->num_vc); | ||
1612 | iadev->rxing = 1; | ||
1613 | iadev->rx_pkt_cnt = 0; | ||
1614 | /* Mode Register */ | ||
1615 | writew(R_ONLINE, iadev->reass_reg+MODE_REG); | ||
1616 | return 0; | ||
1617 | |||
1618 | err_free_dle: | ||
1619 | pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->rx_dle_q.start, | ||
1620 | iadev->rx_dle_dma); | ||
1621 | err_out: | ||
1622 | return -ENOMEM; | ||
1623 | } | ||
1624 | |||
1625 | |||
1626 | /* | ||
1627 | The memory map suggested in appendix A and the coding for it. | ||
1628 | Keeping it around just in case we change our mind later. | ||
1629 | |||
1630 | Buffer descr 0x0000 (128 - 4K) | ||
1631 | UBR sched 0x1000 (1K - 4K) | ||
1632 | UBR Wait q 0x2000 (1K - 4K) | ||
1633 | Commn queues 0x3000 Packet Ready, Trasmit comp(0x3100) | ||
1634 | (128 - 256) each | ||
1635 | extended VC 0x4000 (1K - 8K) | ||
1636 | ABR sched 0x6000 and ABR wait queue (1K - 2K) each | ||
1637 | CBR sched 0x7000 (as needed) | ||
1638 | VC table 0x8000 (1K - 32K) | ||
1639 | */ | ||
1640 | |||
1641 | static void tx_intr(struct atm_dev *dev) | ||
1642 | { | ||
1643 | IADEV *iadev; | ||
1644 | unsigned short status; | ||
1645 | unsigned long flags; | ||
1646 | |||
1647 | iadev = INPH_IA_DEV(dev); | ||
1648 | |||
1649 | status = readl(iadev->seg_reg+SEG_INTR_STATUS_REG); | ||
1650 | if (status & TRANSMIT_DONE){ | ||
1651 | |||
1652 | IF_EVENT(printk("Tansmit Done Intr logic run\n");) | ||
1653 | spin_lock_irqsave(&iadev->tx_lock, flags); | ||
1654 | ia_tx_poll(iadev); | ||
1655 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
1656 | writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG); | ||
1657 | if (iadev->close_pending) | ||
1658 | wake_up(&iadev->close_wait); | ||
1659 | } | ||
1660 | if (status & TCQ_NOT_EMPTY) | ||
1661 | { | ||
1662 | IF_EVENT(printk("TCQ_NOT_EMPTY int received\n");) | ||
1663 | } | ||
1664 | } | ||
1665 | |||
1666 | static void tx_dle_intr(struct atm_dev *dev) | ||
1667 | { | ||
1668 | IADEV *iadev; | ||
1669 | struct dle *dle, *cur_dle; | ||
1670 | struct sk_buff *skb; | ||
1671 | struct atm_vcc *vcc; | ||
1672 | struct ia_vcc *iavcc; | ||
1673 | u_int dle_lp; | ||
1674 | unsigned long flags; | ||
1675 | |||
1676 | iadev = INPH_IA_DEV(dev); | ||
1677 | spin_lock_irqsave(&iadev->tx_lock, flags); | ||
1678 | dle = iadev->tx_dle_q.read; | ||
1679 | dle_lp = readl(iadev->dma+IPHASE5575_TX_LIST_ADDR) & | ||
1680 | (sizeof(struct dle)*DLE_ENTRIES - 1); | ||
1681 | cur_dle = (struct dle*)(iadev->tx_dle_q.start + (dle_lp >> 4)); | ||
1682 | while (dle != cur_dle) | ||
1683 | { | ||
1684 | /* free the DMAed skb */ | ||
1685 | skb = skb_dequeue(&iadev->tx_dma_q); | ||
1686 | if (!skb) break; | ||
1687 | |||
1688 | /* Revenge of the 2 dle (skb + trailer) used in ia_pkt_tx() */ | ||
1689 | if (!((dle - iadev->tx_dle_q.start)%(2*sizeof(struct dle)))) { | ||
1690 | pci_unmap_single(iadev->pci, dle->sys_pkt_addr, skb->len, | ||
1691 | PCI_DMA_TODEVICE); | ||
1692 | } | ||
1693 | vcc = ATM_SKB(skb)->vcc; | ||
1694 | if (!vcc) { | ||
1695 | printk("tx_dle_intr: vcc is null\n"); | ||
1696 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
1697 | dev_kfree_skb_any(skb); | ||
1698 | |||
1699 | return; | ||
1700 | } | ||
1701 | iavcc = INPH_IA_VCC(vcc); | ||
1702 | if (!iavcc) { | ||
1703 | printk("tx_dle_intr: iavcc is null\n"); | ||
1704 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
1705 | dev_kfree_skb_any(skb); | ||
1706 | return; | ||
1707 | } | ||
1708 | if (vcc->qos.txtp.pcr >= iadev->rate_limit) { | ||
1709 | if ((vcc->pop) && (skb->len != 0)) | ||
1710 | { | ||
1711 | vcc->pop(vcc, skb); | ||
1712 | } | ||
1713 | else { | ||
1714 | dev_kfree_skb_any(skb); | ||
1715 | } | ||
1716 | } | ||
1717 | else { /* Hold the rate-limited skb for flow control */ | ||
1718 | IA_SKB_STATE(skb) |= IA_DLED; | ||
1719 | skb_queue_tail(&iavcc->txing_skb, skb); | ||
1720 | } | ||
1721 | IF_EVENT(printk("tx_dle_intr: enque skb = 0x%x \n", (u32)skb);) | ||
1722 | if (++dle == iadev->tx_dle_q.end) | ||
1723 | dle = iadev->tx_dle_q.start; | ||
1724 | } | ||
1725 | iadev->tx_dle_q.read = dle; | ||
1726 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
1727 | } | ||
1728 | |||
1729 | static int open_tx(struct atm_vcc *vcc) | ||
1730 | { | ||
1731 | struct ia_vcc *ia_vcc; | ||
1732 | IADEV *iadev; | ||
1733 | struct main_vc *vc; | ||
1734 | struct ext_vc *evc; | ||
1735 | int ret; | ||
1736 | IF_EVENT(printk("iadev: open_tx entered vcc->vci = %d\n", vcc->vci);) | ||
1737 | if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; | ||
1738 | iadev = INPH_IA_DEV(vcc->dev); | ||
1739 | |||
1740 | if (iadev->phy_type & FE_25MBIT_PHY) { | ||
1741 | if (vcc->qos.txtp.traffic_class == ATM_ABR) { | ||
1742 | printk("IA: ABR not support\n"); | ||
1743 | return -EINVAL; | ||
1744 | } | ||
1745 | if (vcc->qos.txtp.traffic_class == ATM_CBR) { | ||
1746 | printk("IA: CBR not support\n"); | ||
1747 | return -EINVAL; | ||
1748 | } | ||
1749 | } | ||
1750 | ia_vcc = INPH_IA_VCC(vcc); | ||
1751 | memset((caddr_t)ia_vcc, 0, sizeof(*ia_vcc)); | ||
1752 | if (vcc->qos.txtp.max_sdu > | ||
1753 | (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){ | ||
1754 | printk("IA: SDU size over (%d) the configured SDU size %d\n", | ||
1755 | vcc->qos.txtp.max_sdu,iadev->tx_buf_sz); | ||
1756 | vcc->dev_data = NULL; | ||
1757 | kfree(ia_vcc); | ||
1758 | return -EINVAL; | ||
1759 | } | ||
1760 | ia_vcc->vc_desc_cnt = 0; | ||
1761 | ia_vcc->txing = 1; | ||
1762 | |||
1763 | /* find pcr */ | ||
1764 | if (vcc->qos.txtp.max_pcr == ATM_MAX_PCR) | ||
1765 | vcc->qos.txtp.pcr = iadev->LineRate; | ||
1766 | else if ((vcc->qos.txtp.max_pcr == 0)&&( vcc->qos.txtp.pcr <= 0)) | ||
1767 | vcc->qos.txtp.pcr = iadev->LineRate; | ||
1768 | else if ((vcc->qos.txtp.max_pcr > vcc->qos.txtp.pcr) && (vcc->qos.txtp.max_pcr> 0)) | ||
1769 | vcc->qos.txtp.pcr = vcc->qos.txtp.max_pcr; | ||
1770 | if (vcc->qos.txtp.pcr > iadev->LineRate) | ||
1771 | vcc->qos.txtp.pcr = iadev->LineRate; | ||
1772 | ia_vcc->pcr = vcc->qos.txtp.pcr; | ||
1773 | |||
1774 | if (ia_vcc->pcr > (iadev->LineRate / 6) ) ia_vcc->ltimeout = HZ / 10; | ||
1775 | else if (ia_vcc->pcr > (iadev->LineRate / 130)) ia_vcc->ltimeout = HZ; | ||
1776 | else if (ia_vcc->pcr <= 170) ia_vcc->ltimeout = 16 * HZ; | ||
1777 | else ia_vcc->ltimeout = 2700 * HZ / ia_vcc->pcr; | ||
1778 | if (ia_vcc->pcr < iadev->rate_limit) | ||
1779 | skb_queue_head_init (&ia_vcc->txing_skb); | ||
1780 | if (ia_vcc->pcr < iadev->rate_limit) { | ||
1781 | struct sock *sk = sk_atm(vcc); | ||
1782 | |||
1783 | if (vcc->qos.txtp.max_sdu != 0) { | ||
1784 | if (ia_vcc->pcr > 60000) | ||
1785 | sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5; | ||
1786 | else if (ia_vcc->pcr > 2000) | ||
1787 | sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4; | ||
1788 | else | ||
1789 | sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3; | ||
1790 | } | ||
1791 | else | ||
1792 | sk->sk_sndbuf = 24576; | ||
1793 | } | ||
1794 | |||
1795 | vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR; | ||
1796 | evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR; | ||
1797 | vc += vcc->vci; | ||
1798 | evc += vcc->vci; | ||
1799 | memset((caddr_t)vc, 0, sizeof(*vc)); | ||
1800 | memset((caddr_t)evc, 0, sizeof(*evc)); | ||
1801 | |||
1802 | /* store the most significant 4 bits of vci as the last 4 bits | ||
1803 | of first part of atm header. | ||
1804 | store the last 12 bits of vci as first 12 bits of the second | ||
1805 | part of the atm header. | ||
1806 | */ | ||
1807 | evc->atm_hdr1 = (vcc->vci >> 12) & 0x000f; | ||
1808 | evc->atm_hdr2 = (vcc->vci & 0x0fff) << 4; | ||
1809 | |||
1810 | /* check the following for different traffic classes */ | ||
1811 | if (vcc->qos.txtp.traffic_class == ATM_UBR) | ||
1812 | { | ||
1813 | vc->type = UBR; | ||
1814 | vc->status = CRC_APPEND; | ||
1815 | vc->acr = cellrate_to_float(iadev->LineRate); | ||
1816 | if (vcc->qos.txtp.pcr > 0) | ||
1817 | vc->acr = cellrate_to_float(vcc->qos.txtp.pcr); | ||
1818 | IF_UBR(printk("UBR: txtp.pcr = 0x%x f_rate = 0x%x\n", | ||
1819 | vcc->qos.txtp.max_pcr,vc->acr);) | ||
1820 | } | ||
1821 | else if (vcc->qos.txtp.traffic_class == ATM_ABR) | ||
1822 | { srv_cls_param_t srv_p; | ||
1823 | IF_ABR(printk("Tx ABR VCC\n");) | ||
1824 | init_abr_vc(iadev, &srv_p); | ||
1825 | if (vcc->qos.txtp.pcr > 0) | ||
1826 | srv_p.pcr = vcc->qos.txtp.pcr; | ||
1827 | if (vcc->qos.txtp.min_pcr > 0) { | ||
1828 | int tmpsum = iadev->sum_mcr+iadev->sum_cbr+vcc->qos.txtp.min_pcr; | ||
1829 | if (tmpsum > iadev->LineRate) | ||
1830 | return -EBUSY; | ||
1831 | srv_p.mcr = vcc->qos.txtp.min_pcr; | ||
1832 | iadev->sum_mcr += vcc->qos.txtp.min_pcr; | ||
1833 | } | ||
1834 | else srv_p.mcr = 0; | ||
1835 | if (vcc->qos.txtp.icr) | ||
1836 | srv_p.icr = vcc->qos.txtp.icr; | ||
1837 | if (vcc->qos.txtp.tbe) | ||
1838 | srv_p.tbe = vcc->qos.txtp.tbe; | ||
1839 | if (vcc->qos.txtp.frtt) | ||
1840 | srv_p.frtt = vcc->qos.txtp.frtt; | ||
1841 | if (vcc->qos.txtp.rif) | ||
1842 | srv_p.rif = vcc->qos.txtp.rif; | ||
1843 | if (vcc->qos.txtp.rdf) | ||
1844 | srv_p.rdf = vcc->qos.txtp.rdf; | ||
1845 | if (vcc->qos.txtp.nrm_pres) | ||
1846 | srv_p.nrm = vcc->qos.txtp.nrm; | ||
1847 | if (vcc->qos.txtp.trm_pres) | ||
1848 | srv_p.trm = vcc->qos.txtp.trm; | ||
1849 | if (vcc->qos.txtp.adtf_pres) | ||
1850 | srv_p.adtf = vcc->qos.txtp.adtf; | ||
1851 | if (vcc->qos.txtp.cdf_pres) | ||
1852 | srv_p.cdf = vcc->qos.txtp.cdf; | ||
1853 | if (srv_p.icr > srv_p.pcr) | ||
1854 | srv_p.icr = srv_p.pcr; | ||
1855 | IF_ABR(printk("ABR:vcc->qos.txtp.max_pcr = %d mcr = %d\n", | ||
1856 | srv_p.pcr, srv_p.mcr);) | ||
1857 | ia_open_abr_vc(iadev, &srv_p, vcc, 1); | ||
1858 | } else if (vcc->qos.txtp.traffic_class == ATM_CBR) { | ||
1859 | if (iadev->phy_type & FE_25MBIT_PHY) { | ||
1860 | printk("IA: CBR not support\n"); | ||
1861 | return -EINVAL; | ||
1862 | } | ||
1863 | if (vcc->qos.txtp.max_pcr > iadev->LineRate) { | ||
1864 | IF_CBR(printk("PCR is not availble\n");) | ||
1865 | return -1; | ||
1866 | } | ||
1867 | vc->type = CBR; | ||
1868 | vc->status = CRC_APPEND; | ||
1869 | if ((ret = ia_cbr_setup (iadev, vcc)) < 0) { | ||
1870 | return ret; | ||
1871 | } | ||
1872 | } | ||
1873 | else | ||
1874 | printk("iadev: Non UBR, ABR and CBR traffic not supportedn"); | ||
1875 | |||
1876 | iadev->testTable[vcc->vci]->vc_status |= VC_ACTIVE; | ||
1877 | IF_EVENT(printk("ia open_tx returning \n");) | ||
1878 | return 0; | ||
1879 | } | ||
1880 | |||
1881 | |||
1882 | static int tx_init(struct atm_dev *dev) | ||
1883 | { | ||
1884 | IADEV *iadev; | ||
1885 | struct tx_buf_desc *buf_desc_ptr; | ||
1886 | unsigned int tx_pkt_start; | ||
1887 | void *dle_addr; | ||
1888 | int i; | ||
1889 | u_short tcq_st_adr; | ||
1890 | u_short *tcq_start; | ||
1891 | u_short prq_st_adr; | ||
1892 | u_short *prq_start; | ||
1893 | struct main_vc *vc; | ||
1894 | struct ext_vc *evc; | ||
1895 | u_short tmp16; | ||
1896 | u32 vcsize_sel; | ||
1897 | |||
1898 | iadev = INPH_IA_DEV(dev); | ||
1899 | spin_lock_init(&iadev->tx_lock); | ||
1900 | |||
1901 | IF_INIT(printk("Tx MASK REG: 0x%0x\n", | ||
1902 | readw(iadev->seg_reg+SEG_MASK_REG));) | ||
1903 | |||
1904 | /* Allocate 4k (boundary aligned) bytes */ | ||
1905 | dle_addr = pci_alloc_consistent(iadev->pci, DLE_TOTAL_SIZE, | ||
1906 | &iadev->tx_dle_dma); | ||
1907 | if (!dle_addr) { | ||
1908 | printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n"); | ||
1909 | goto err_out; | ||
1910 | } | ||
1911 | iadev->tx_dle_q.start = (struct dle*)dle_addr; | ||
1912 | iadev->tx_dle_q.read = iadev->tx_dle_q.start; | ||
1913 | iadev->tx_dle_q.write = iadev->tx_dle_q.start; | ||
1914 | iadev->tx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES); | ||
1915 | |||
1916 | /* write the upper 20 bits of the start address to tx list address register */ | ||
1917 | writel(iadev->tx_dle_dma & 0xfffff000, | ||
1918 | iadev->dma + IPHASE5575_TX_LIST_ADDR); | ||
1919 | writew(0xffff, iadev->seg_reg+SEG_MASK_REG); | ||
1920 | writew(0, iadev->seg_reg+MODE_REG_0); | ||
1921 | writew(RESET_SEG, iadev->seg_reg+SEG_COMMAND_REG); | ||
1922 | iadev->MAIN_VC_TABLE_ADDR = iadev->seg_ram+MAIN_VC_TABLE*iadev->memSize; | ||
1923 | iadev->EXT_VC_TABLE_ADDR = iadev->seg_ram+EXT_VC_TABLE*iadev->memSize; | ||
1924 | iadev->ABR_SCHED_TABLE_ADDR=iadev->seg_ram+ABR_SCHED_TABLE*iadev->memSize; | ||
1925 | |||
1926 | /* | ||
1927 | Transmit side control memory map | ||
1928 | -------------------------------- | ||
1929 | Buffer descr 0x0000 (128 - 4K) | ||
1930 | Commn queues 0x1000 Transmit comp, Packet ready(0x1400) | ||
1931 | (512 - 1K) each | ||
1932 | TCQ - 4K, PRQ - 5K | ||
1933 | CBR Table 0x1800 (as needed) - 6K | ||
1934 | UBR Table 0x3000 (1K - 4K) - 12K | ||
1935 | UBR Wait queue 0x4000 (1K - 4K) - 16K | ||
1936 | ABR sched 0x5000 and ABR wait queue (1K - 2K) each | ||
1937 | ABR Tbl - 20K, ABR Wq - 22K | ||
1938 | extended VC 0x6000 (1K - 8K) - 24K | ||
1939 | VC Table 0x8000 (1K - 32K) - 32K | ||
1940 | |||
1941 | Between 0x2000 (8K) and 0x3000 (12K) there is 4K space left for VBR Tbl | ||
1942 | and Wait q, which can be allotted later. | ||
1943 | */ | ||
1944 | |||
1945 | /* Buffer Descriptor Table Base address */ | ||
1946 | writew(TX_DESC_BASE, iadev->seg_reg+SEG_DESC_BASE); | ||
1947 | |||
1948 | /* initialize each entry in the buffer descriptor table */ | ||
1949 | buf_desc_ptr =(struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE); | ||
1950 | memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); | ||
1951 | buf_desc_ptr++; | ||
1952 | tx_pkt_start = TX_PACKET_RAM; | ||
1953 | for(i=1; i<=iadev->num_tx_desc; i++) | ||
1954 | { | ||
1955 | memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); | ||
1956 | buf_desc_ptr->desc_mode = AAL5; | ||
1957 | buf_desc_ptr->buf_start_hi = tx_pkt_start >> 16; | ||
1958 | buf_desc_ptr->buf_start_lo = tx_pkt_start & 0x0000ffff; | ||
1959 | buf_desc_ptr++; | ||
1960 | tx_pkt_start += iadev->tx_buf_sz; | ||
1961 | } | ||
1962 | iadev->tx_buf = kmalloc(iadev->num_tx_desc*sizeof(struct cpcs_trailer_desc), GFP_KERNEL); | ||
1963 | if (!iadev->tx_buf) { | ||
1964 | printk(KERN_ERR DEV_LABEL " couldn't get mem\n"); | ||
1965 | goto err_free_dle; | ||
1966 | } | ||
1967 | for (i= 0; i< iadev->num_tx_desc; i++) | ||
1968 | { | ||
1969 | struct cpcs_trailer *cpcs; | ||
1970 | |||
1971 | cpcs = kmalloc(sizeof(*cpcs), GFP_KERNEL|GFP_DMA); | ||
1972 | if(!cpcs) { | ||
1973 | printk(KERN_ERR DEV_LABEL " couldn't get freepage\n"); | ||
1974 | goto err_free_tx_bufs; | ||
1975 | } | ||
1976 | iadev->tx_buf[i].cpcs = cpcs; | ||
1977 | iadev->tx_buf[i].dma_addr = pci_map_single(iadev->pci, | ||
1978 | cpcs, sizeof(*cpcs), PCI_DMA_TODEVICE); | ||
1979 | } | ||
1980 | iadev->desc_tbl = kmalloc(iadev->num_tx_desc * | ||
1981 | sizeof(struct desc_tbl_t), GFP_KERNEL); | ||
1982 | if (!iadev->desc_tbl) { | ||
1983 | printk(KERN_ERR DEV_LABEL " couldn't get mem\n"); | ||
1984 | goto err_free_all_tx_bufs; | ||
1985 | } | ||
1986 | |||
1987 | /* Communication Queues base address */ | ||
1988 | i = TX_COMP_Q * iadev->memSize; | ||
1989 | writew(i >> 16, iadev->seg_reg+SEG_QUEUE_BASE); | ||
1990 | |||
1991 | /* Transmit Complete Queue */ | ||
1992 | writew(i, iadev->seg_reg+TCQ_ST_ADR); | ||
1993 | writew(i, iadev->seg_reg+TCQ_RD_PTR); | ||
1994 | writew(i+iadev->num_tx_desc*sizeof(u_short),iadev->seg_reg+TCQ_WR_PTR); | ||
1995 | iadev->host_tcq_wr = i + iadev->num_tx_desc*sizeof(u_short); | ||
1996 | writew(i+2 * iadev->num_tx_desc * sizeof(u_short), | ||
1997 | iadev->seg_reg+TCQ_ED_ADR); | ||
1998 | /* Fill the TCQ with all the free descriptors. */ | ||
1999 | tcq_st_adr = readw(iadev->seg_reg+TCQ_ST_ADR); | ||
2000 | tcq_start = (u_short *)(iadev->seg_ram+tcq_st_adr); | ||
2001 | for(i=1; i<=iadev->num_tx_desc; i++) | ||
2002 | { | ||
2003 | *tcq_start = (u_short)i; | ||
2004 | tcq_start++; | ||
2005 | } | ||
2006 | |||
2007 | /* Packet Ready Queue */ | ||
2008 | i = PKT_RDY_Q * iadev->memSize; | ||
2009 | writew(i, iadev->seg_reg+PRQ_ST_ADR); | ||
2010 | writew(i+2 * iadev->num_tx_desc * sizeof(u_short), | ||
2011 | iadev->seg_reg+PRQ_ED_ADR); | ||
2012 | writew(i, iadev->seg_reg+PRQ_RD_PTR); | ||
2013 | writew(i, iadev->seg_reg+PRQ_WR_PTR); | ||
2014 | |||
2015 | /* Load local copy of PRQ and TCQ ptrs */ | ||
2016 | iadev->ffL.prq_st = readw(iadev->seg_reg+PRQ_ST_ADR) & 0xffff; | ||
2017 | iadev->ffL.prq_ed = readw(iadev->seg_reg+PRQ_ED_ADR) & 0xffff; | ||
2018 | iadev->ffL.prq_wr = readw(iadev->seg_reg+PRQ_WR_PTR) & 0xffff; | ||
2019 | |||
2020 | iadev->ffL.tcq_st = readw(iadev->seg_reg+TCQ_ST_ADR) & 0xffff; | ||
2021 | iadev->ffL.tcq_ed = readw(iadev->seg_reg+TCQ_ED_ADR) & 0xffff; | ||
2022 | iadev->ffL.tcq_rd = readw(iadev->seg_reg+TCQ_RD_PTR) & 0xffff; | ||
2023 | |||
2024 | /* Just for safety initializing the queue to have desc 1 always */ | ||
2025 | /* Fill the PRQ with all the free descriptors. */ | ||
2026 | prq_st_adr = readw(iadev->seg_reg+PRQ_ST_ADR); | ||
2027 | prq_start = (u_short *)(iadev->seg_ram+prq_st_adr); | ||
2028 | for(i=1; i<=iadev->num_tx_desc; i++) | ||
2029 | { | ||
2030 | *prq_start = (u_short)0; /* desc 1 in all entries */ | ||
2031 | prq_start++; | ||
2032 | } | ||
2033 | /* CBR Table */ | ||
2034 | IF_INIT(printk("Start CBR Init\n");) | ||
2035 | #if 1 /* for 1K VC board, CBR_PTR_BASE is 0 */ | ||
2036 | writew(0,iadev->seg_reg+CBR_PTR_BASE); | ||
2037 | #else /* Charlie's logic is wrong ? */ | ||
2038 | tmp16 = (iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize)>>17; | ||
2039 | IF_INIT(printk("cbr_ptr_base = 0x%x ", tmp16);) | ||
2040 | writew(tmp16,iadev->seg_reg+CBR_PTR_BASE); | ||
2041 | #endif | ||
2042 | |||
2043 | IF_INIT(printk("value in register = 0x%x\n", | ||
2044 | readw(iadev->seg_reg+CBR_PTR_BASE));) | ||
2045 | tmp16 = (CBR_SCHED_TABLE*iadev->memSize) >> 1; | ||
2046 | writew(tmp16, iadev->seg_reg+CBR_TAB_BEG); | ||
2047 | IF_INIT(printk("cbr_tab_beg = 0x%x in reg = 0x%x \n", tmp16, | ||
2048 | readw(iadev->seg_reg+CBR_TAB_BEG));) | ||
2049 | writew(tmp16, iadev->seg_reg+CBR_TAB_END+1); // CBR_PTR; | ||
2050 | tmp16 = (CBR_SCHED_TABLE*iadev->memSize + iadev->num_vc*6 - 2) >> 1; | ||
2051 | writew(tmp16, iadev->seg_reg+CBR_TAB_END); | ||
2052 | IF_INIT(printk("iadev->seg_reg = 0x%x CBR_PTR_BASE = 0x%x\n", | ||
2053 | (u32)iadev->seg_reg, readw(iadev->seg_reg+CBR_PTR_BASE));) | ||
2054 | IF_INIT(printk("CBR_TAB_BEG = 0x%x, CBR_TAB_END = 0x%x, CBR_PTR = 0x%x\n", | ||
2055 | readw(iadev->seg_reg+CBR_TAB_BEG), readw(iadev->seg_reg+CBR_TAB_END), | ||
2056 | readw(iadev->seg_reg+CBR_TAB_END+1));) | ||
2057 | |||
2058 | /* Initialize the CBR Schedualing Table */ | ||
2059 | memset_io(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize, | ||
2060 | 0, iadev->num_vc*6); | ||
2061 | iadev->CbrRemEntries = iadev->CbrTotEntries = iadev->num_vc*3; | ||
2062 | iadev->CbrEntryPt = 0; | ||
2063 | iadev->Granularity = MAX_ATM_155 / iadev->CbrTotEntries; | ||
2064 | iadev->NumEnabledCBR = 0; | ||
2065 | |||
2066 | /* UBR scheduling Table and wait queue */ | ||
2067 | /* initialize all bytes of UBR scheduler table and wait queue to 0 | ||
2068 | - SCHEDSZ is 1K (# of entries). | ||
2069 | - UBR Table size is 4K | ||
2070 | - UBR wait queue is 4K | ||
2071 | since the table and wait queues are contiguous, all the bytes | ||
2072 | can be initialized by one memeset. | ||
2073 | */ | ||
2074 | |||
2075 | vcsize_sel = 0; | ||
2076 | i = 8*1024; | ||
2077 | while (i != iadev->num_vc) { | ||
2078 | i /= 2; | ||
2079 | vcsize_sel++; | ||
2080 | } | ||
2081 | |||
2082 | i = MAIN_VC_TABLE * iadev->memSize; | ||
2083 | writew(vcsize_sel | ((i >> 8) & 0xfff8),iadev->seg_reg+VCT_BASE); | ||
2084 | i = EXT_VC_TABLE * iadev->memSize; | ||
2085 | writew((i >> 8) & 0xfffe, iadev->seg_reg+VCTE_BASE); | ||
2086 | i = UBR_SCHED_TABLE * iadev->memSize; | ||
2087 | writew((i & 0xffff) >> 11, iadev->seg_reg+UBR_SBPTR_BASE); | ||
2088 | i = UBR_WAIT_Q * iadev->memSize; | ||
2089 | writew((i >> 7) & 0xffff, iadev->seg_reg+UBRWQ_BASE); | ||
2090 | memset((caddr_t)(iadev->seg_ram+UBR_SCHED_TABLE*iadev->memSize), | ||
2091 | 0, iadev->num_vc*8); | ||
2092 | /* ABR scheduling Table(0x5000-0x57ff) and wait queue(0x5800-0x5fff)*/ | ||
2093 | /* initialize all bytes of ABR scheduler table and wait queue to 0 | ||
2094 | - SCHEDSZ is 1K (# of entries). | ||
2095 | - ABR Table size is 2K | ||
2096 | - ABR wait queue is 2K | ||
2097 | since the table and wait queues are contiguous, all the bytes | ||
2098 | can be intialized by one memeset. | ||
2099 | */ | ||
2100 | i = ABR_SCHED_TABLE * iadev->memSize; | ||
2101 | writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE); | ||
2102 | i = ABR_WAIT_Q * iadev->memSize; | ||
2103 | writew((i >> 7) & 0xffff, iadev->seg_reg+ABRWQ_BASE); | ||
2104 | |||
2105 | i = ABR_SCHED_TABLE*iadev->memSize; | ||
2106 | memset((caddr_t)(iadev->seg_ram+i), 0, iadev->num_vc*4); | ||
2107 | vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR; | ||
2108 | evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR; | ||
2109 | iadev->testTable = kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL); | ||
2110 | if (!iadev->testTable) { | ||
2111 | printk("Get freepage failed\n"); | ||
2112 | goto err_free_desc_tbl; | ||
2113 | } | ||
2114 | for(i=0; i<iadev->num_vc; i++) | ||
2115 | { | ||
2116 | memset((caddr_t)vc, 0, sizeof(*vc)); | ||
2117 | memset((caddr_t)evc, 0, sizeof(*evc)); | ||
2118 | iadev->testTable[i] = kmalloc(sizeof(struct testTable_t), | ||
2119 | GFP_KERNEL); | ||
2120 | if (!iadev->testTable[i]) | ||
2121 | goto err_free_test_tables; | ||
2122 | iadev->testTable[i]->lastTime = 0; | ||
2123 | iadev->testTable[i]->fract = 0; | ||
2124 | iadev->testTable[i]->vc_status = VC_UBR; | ||
2125 | vc++; | ||
2126 | evc++; | ||
2127 | } | ||
2128 | |||
2129 | /* Other Initialization */ | ||
2130 | |||
2131 | /* Max Rate Register */ | ||
2132 | if (iadev->phy_type & FE_25MBIT_PHY) { | ||
2133 | writew(RATE25, iadev->seg_reg+MAXRATE); | ||
2134 | writew((UBR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS); | ||
2135 | } | ||
2136 | else { | ||
2137 | writew(cellrate_to_float(iadev->LineRate),iadev->seg_reg+MAXRATE); | ||
2138 | writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS); | ||
2139 | } | ||
2140 | /* Set Idle Header Reigisters to be sure */ | ||
2141 | writew(0, iadev->seg_reg+IDLEHEADHI); | ||
2142 | writew(0, iadev->seg_reg+IDLEHEADLO); | ||
2143 | |||
2144 | /* Program ABR UBR Priority Register as PRI_ABR_UBR_EQUAL */ | ||
2145 | writew(0xaa00, iadev->seg_reg+ABRUBR_ARB); | ||
2146 | |||
2147 | iadev->close_pending = 0; | ||
2148 | init_waitqueue_head(&iadev->close_wait); | ||
2149 | init_waitqueue_head(&iadev->timeout_wait); | ||
2150 | skb_queue_head_init(&iadev->tx_dma_q); | ||
2151 | ia_init_rtn_q(&iadev->tx_return_q); | ||
2152 | |||
2153 | /* RM Cell Protocol ID and Message Type */ | ||
2154 | writew(RM_TYPE_4_0, iadev->seg_reg+RM_TYPE); | ||
2155 | skb_queue_head_init (&iadev->tx_backlog); | ||
2156 | |||
2157 | /* Mode Register 1 */ | ||
2158 | writew(MODE_REG_1_VAL, iadev->seg_reg+MODE_REG_1); | ||
2159 | |||
2160 | /* Mode Register 0 */ | ||
2161 | writew(T_ONLINE, iadev->seg_reg+MODE_REG_0); | ||
2162 | |||
2163 | /* Interrupt Status Register - read to clear */ | ||
2164 | readw(iadev->seg_reg+SEG_INTR_STATUS_REG); | ||
2165 | |||
2166 | /* Interrupt Mask Reg- don't mask TCQ_NOT_EMPTY interrupt generation */ | ||
2167 | writew(~(TRANSMIT_DONE | TCQ_NOT_EMPTY), iadev->seg_reg+SEG_MASK_REG); | ||
2168 | writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG); | ||
2169 | iadev->tx_pkt_cnt = 0; | ||
2170 | iadev->rate_limit = iadev->LineRate / 3; | ||
2171 | |||
2172 | return 0; | ||
2173 | |||
2174 | err_free_test_tables: | ||
2175 | while (--i >= 0) | ||
2176 | kfree(iadev->testTable[i]); | ||
2177 | kfree(iadev->testTable); | ||
2178 | err_free_desc_tbl: | ||
2179 | kfree(iadev->desc_tbl); | ||
2180 | err_free_all_tx_bufs: | ||
2181 | i = iadev->num_tx_desc; | ||
2182 | err_free_tx_bufs: | ||
2183 | while (--i >= 0) { | ||
2184 | struct cpcs_trailer_desc *desc = iadev->tx_buf + i; | ||
2185 | |||
2186 | pci_unmap_single(iadev->pci, desc->dma_addr, | ||
2187 | sizeof(*desc->cpcs), PCI_DMA_TODEVICE); | ||
2188 | kfree(desc->cpcs); | ||
2189 | } | ||
2190 | kfree(iadev->tx_buf); | ||
2191 | err_free_dle: | ||
2192 | pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->tx_dle_q.start, | ||
2193 | iadev->tx_dle_dma); | ||
2194 | err_out: | ||
2195 | return -ENOMEM; | ||
2196 | } | ||
2197 | |||
2198 | static irqreturn_t ia_int(int irq, void *dev_id, struct pt_regs *regs) | ||
2199 | { | ||
2200 | struct atm_dev *dev; | ||
2201 | IADEV *iadev; | ||
2202 | unsigned int status; | ||
2203 | int handled = 0; | ||
2204 | |||
2205 | dev = dev_id; | ||
2206 | iadev = INPH_IA_DEV(dev); | ||
2207 | while( (status = readl(iadev->reg+IPHASE5575_BUS_STATUS_REG) & 0x7f)) | ||
2208 | { | ||
2209 | handled = 1; | ||
2210 | IF_EVENT(printk("ia_int: status = 0x%x\n", status);) | ||
2211 | if (status & STAT_REASSINT) | ||
2212 | { | ||
2213 | /* do something */ | ||
2214 | IF_EVENT(printk("REASSINT Bus status reg: %08x\n", status);) | ||
2215 | rx_intr(dev); | ||
2216 | } | ||
2217 | if (status & STAT_DLERINT) | ||
2218 | { | ||
2219 | /* Clear this bit by writing a 1 to it. */ | ||
2220 | *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLERINT; | ||
2221 | rx_dle_intr(dev); | ||
2222 | } | ||
2223 | if (status & STAT_SEGINT) | ||
2224 | { | ||
2225 | /* do something */ | ||
2226 | IF_EVENT(printk("IA: tx_intr \n");) | ||
2227 | tx_intr(dev); | ||
2228 | } | ||
2229 | if (status & STAT_DLETINT) | ||
2230 | { | ||
2231 | *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLETINT; | ||
2232 | tx_dle_intr(dev); | ||
2233 | } | ||
2234 | if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT)) | ||
2235 | { | ||
2236 | if (status & STAT_FEINT) | ||
2237 | IaFrontEndIntr(iadev); | ||
2238 | } | ||
2239 | } | ||
2240 | return IRQ_RETVAL(handled); | ||
2241 | } | ||
2242 | |||
2243 | |||
2244 | |||
2245 | /*----------------------------- entries --------------------------------*/ | ||
2246 | static int get_esi(struct atm_dev *dev) | ||
2247 | { | ||
2248 | IADEV *iadev; | ||
2249 | int i; | ||
2250 | u32 mac1; | ||
2251 | u16 mac2; | ||
2252 | |||
2253 | iadev = INPH_IA_DEV(dev); | ||
2254 | mac1 = cpu_to_be32(le32_to_cpu(readl( | ||
2255 | iadev->reg+IPHASE5575_MAC1))); | ||
2256 | mac2 = cpu_to_be16(le16_to_cpu(readl(iadev->reg+IPHASE5575_MAC2))); | ||
2257 | IF_INIT(printk("ESI: 0x%08x%04x\n", mac1, mac2);) | ||
2258 | for (i=0; i<MAC1_LEN; i++) | ||
2259 | dev->esi[i] = mac1 >>(8*(MAC1_LEN-1-i)); | ||
2260 | |||
2261 | for (i=0; i<MAC2_LEN; i++) | ||
2262 | dev->esi[i+MAC1_LEN] = mac2 >>(8*(MAC2_LEN - 1 -i)); | ||
2263 | return 0; | ||
2264 | } | ||
2265 | |||
2266 | static int reset_sar(struct atm_dev *dev) | ||
2267 | { | ||
2268 | IADEV *iadev; | ||
2269 | int i, error = 1; | ||
2270 | unsigned int pci[64]; | ||
2271 | |||
2272 | iadev = INPH_IA_DEV(dev); | ||
2273 | for(i=0; i<64; i++) | ||
2274 | if ((error = pci_read_config_dword(iadev->pci, | ||
2275 | i*4, &pci[i])) != PCIBIOS_SUCCESSFUL) | ||
2276 | return error; | ||
2277 | writel(0, iadev->reg+IPHASE5575_EXT_RESET); | ||
2278 | for(i=0; i<64; i++) | ||
2279 | if ((error = pci_write_config_dword(iadev->pci, | ||
2280 | i*4, pci[i])) != PCIBIOS_SUCCESSFUL) | ||
2281 | return error; | ||
2282 | udelay(5); | ||
2283 | return 0; | ||
2284 | } | ||
2285 | |||
2286 | |||
2287 | static int __init ia_init(struct atm_dev *dev) | ||
2288 | { | ||
2289 | IADEV *iadev; | ||
2290 | unsigned long real_base; | ||
2291 | void __iomem *base; | ||
2292 | unsigned short command; | ||
2293 | unsigned char revision; | ||
2294 | int error, i; | ||
2295 | |||
2296 | /* The device has been identified and registered. Now we read | ||
2297 | necessary configuration info like memory base address, | ||
2298 | interrupt number etc */ | ||
2299 | |||
2300 | IF_INIT(printk(">ia_init\n");) | ||
2301 | dev->ci_range.vpi_bits = 0; | ||
2302 | dev->ci_range.vci_bits = NR_VCI_LD; | ||
2303 | |||
2304 | iadev = INPH_IA_DEV(dev); | ||
2305 | real_base = pci_resource_start (iadev->pci, 0); | ||
2306 | iadev->irq = iadev->pci->irq; | ||
2307 | |||
2308 | if ((error = pci_read_config_word(iadev->pci, PCI_COMMAND,&command)) | ||
2309 | || (error = pci_read_config_byte(iadev->pci, | ||
2310 | PCI_REVISION_ID,&revision))) | ||
2311 | { | ||
2312 | printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n", | ||
2313 | dev->number,error); | ||
2314 | return -EINVAL; | ||
2315 | } | ||
2316 | IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n", | ||
2317 | dev->number, revision, real_base, iadev->irq);) | ||
2318 | |||
2319 | /* find mapping size of board */ | ||
2320 | |||
2321 | iadev->pci_map_size = pci_resource_len(iadev->pci, 0); | ||
2322 | |||
2323 | if (iadev->pci_map_size == 0x100000){ | ||
2324 | iadev->num_vc = 4096; | ||
2325 | dev->ci_range.vci_bits = NR_VCI_4K_LD; | ||
2326 | iadev->memSize = 4; | ||
2327 | } | ||
2328 | else if (iadev->pci_map_size == 0x40000) { | ||
2329 | iadev->num_vc = 1024; | ||
2330 | iadev->memSize = 1; | ||
2331 | } | ||
2332 | else { | ||
2333 | printk("Unknown pci_map_size = 0x%x\n", iadev->pci_map_size); | ||
2334 | return -EINVAL; | ||
2335 | } | ||
2336 | IF_INIT(printk (DEV_LABEL "map size: %i\n", iadev->pci_map_size);) | ||
2337 | |||
2338 | /* enable bus mastering */ | ||
2339 | pci_set_master(iadev->pci); | ||
2340 | |||
2341 | /* | ||
2342 | * Delay at least 1us before doing any mem accesses (how 'bout 10?) | ||
2343 | */ | ||
2344 | udelay(10); | ||
2345 | |||
2346 | /* mapping the physical address to a virtual address in address space */ | ||
2347 | base = ioremap(real_base,iadev->pci_map_size); /* ioremap is not resolved ??? */ | ||
2348 | |||
2349 | if (!base) | ||
2350 | { | ||
2351 | printk(DEV_LABEL " (itf %d): can't set up page mapping\n", | ||
2352 | dev->number); | ||
2353 | return error; | ||
2354 | } | ||
2355 | IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n", | ||
2356 | dev->number, revision, base, iadev->irq);) | ||
2357 | |||
2358 | /* filling the iphase dev structure */ | ||
2359 | iadev->mem = iadev->pci_map_size /2; | ||
2360 | iadev->real_base = real_base; | ||
2361 | iadev->base = base; | ||
2362 | |||
2363 | /* Bus Interface Control Registers */ | ||
2364 | iadev->reg = base + REG_BASE; | ||
2365 | /* Segmentation Control Registers */ | ||
2366 | iadev->seg_reg = base + SEG_BASE; | ||
2367 | /* Reassembly Control Registers */ | ||
2368 | iadev->reass_reg = base + REASS_BASE; | ||
2369 | /* Front end/ DMA control registers */ | ||
2370 | iadev->phy = base + PHY_BASE; | ||
2371 | iadev->dma = base + PHY_BASE; | ||
2372 | /* RAM - Segmentation RAm and Reassembly RAM */ | ||
2373 | iadev->ram = base + ACTUAL_RAM_BASE; | ||
2374 | iadev->seg_ram = base + ACTUAL_SEG_RAM_BASE; | ||
2375 | iadev->reass_ram = base + ACTUAL_REASS_RAM_BASE; | ||
2376 | |||
2377 | /* lets print out the above */ | ||
2378 | IF_INIT(printk("Base addrs: %p %p %p \n %p %p %p %p\n", | ||
2379 | iadev->reg,iadev->seg_reg,iadev->reass_reg, | ||
2380 | iadev->phy, iadev->ram, iadev->seg_ram, | ||
2381 | iadev->reass_ram);) | ||
2382 | |||
2383 | /* lets try reading the MAC address */ | ||
2384 | error = get_esi(dev); | ||
2385 | if (error) { | ||
2386 | iounmap(iadev->base); | ||
2387 | return error; | ||
2388 | } | ||
2389 | printk("IA: "); | ||
2390 | for (i=0; i < ESI_LEN; i++) | ||
2391 | printk("%s%02X",i ? "-" : "",dev->esi[i]); | ||
2392 | printk("\n"); | ||
2393 | |||
2394 | /* reset SAR */ | ||
2395 | if (reset_sar(dev)) { | ||
2396 | iounmap(iadev->base); | ||
2397 | printk("IA: reset SAR fail, please try again\n"); | ||
2398 | return 1; | ||
2399 | } | ||
2400 | return 0; | ||
2401 | } | ||
2402 | |||
2403 | static void ia_update_stats(IADEV *iadev) { | ||
2404 | if (!iadev->carrier_detect) | ||
2405 | return; | ||
2406 | iadev->rx_cell_cnt += readw(iadev->reass_reg+CELL_CTR0)&0xffff; | ||
2407 | iadev->rx_cell_cnt += (readw(iadev->reass_reg+CELL_CTR1) & 0xffff) << 16; | ||
2408 | iadev->drop_rxpkt += readw(iadev->reass_reg + DRP_PKT_CNTR ) & 0xffff; | ||
2409 | iadev->drop_rxcell += readw(iadev->reass_reg + ERR_CNTR) & 0xffff; | ||
2410 | iadev->tx_cell_cnt += readw(iadev->seg_reg + CELL_CTR_LO_AUTO)&0xffff; | ||
2411 | iadev->tx_cell_cnt += (readw(iadev->seg_reg+CELL_CTR_HIGH_AUTO)&0xffff)<<16; | ||
2412 | return; | ||
2413 | } | ||
2414 | |||
2415 | static void ia_led_timer(unsigned long arg) { | ||
2416 | unsigned long flags; | ||
2417 | static u_char blinking[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
2418 | u_char i; | ||
2419 | static u32 ctrl_reg; | ||
2420 | for (i = 0; i < iadev_count; i++) { | ||
2421 | if (ia_dev[i]) { | ||
2422 | ctrl_reg = readl(ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2423 | if (blinking[i] == 0) { | ||
2424 | blinking[i]++; | ||
2425 | ctrl_reg &= (~CTRL_LED); | ||
2426 | writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2427 | ia_update_stats(ia_dev[i]); | ||
2428 | } | ||
2429 | else { | ||
2430 | blinking[i] = 0; | ||
2431 | ctrl_reg |= CTRL_LED; | ||
2432 | writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2433 | spin_lock_irqsave(&ia_dev[i]->tx_lock, flags); | ||
2434 | if (ia_dev[i]->close_pending) | ||
2435 | wake_up(&ia_dev[i]->close_wait); | ||
2436 | ia_tx_poll(ia_dev[i]); | ||
2437 | spin_unlock_irqrestore(&ia_dev[i]->tx_lock, flags); | ||
2438 | } | ||
2439 | } | ||
2440 | } | ||
2441 | mod_timer(&ia_timer, jiffies + HZ / 4); | ||
2442 | return; | ||
2443 | } | ||
2444 | |||
2445 | static void ia_phy_put(struct atm_dev *dev, unsigned char value, | ||
2446 | unsigned long addr) | ||
2447 | { | ||
2448 | writel(value, INPH_IA_DEV(dev)->phy+addr); | ||
2449 | } | ||
2450 | |||
2451 | static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr) | ||
2452 | { | ||
2453 | return readl(INPH_IA_DEV(dev)->phy+addr); | ||
2454 | } | ||
2455 | |||
2456 | static void ia_free_tx(IADEV *iadev) | ||
2457 | { | ||
2458 | int i; | ||
2459 | |||
2460 | kfree(iadev->desc_tbl); | ||
2461 | for (i = 0; i < iadev->num_vc; i++) | ||
2462 | kfree(iadev->testTable[i]); | ||
2463 | kfree(iadev->testTable); | ||
2464 | for (i = 0; i < iadev->num_tx_desc; i++) { | ||
2465 | struct cpcs_trailer_desc *desc = iadev->tx_buf + i; | ||
2466 | |||
2467 | pci_unmap_single(iadev->pci, desc->dma_addr, | ||
2468 | sizeof(*desc->cpcs), PCI_DMA_TODEVICE); | ||
2469 | kfree(desc->cpcs); | ||
2470 | } | ||
2471 | kfree(iadev->tx_buf); | ||
2472 | pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->tx_dle_q.start, | ||
2473 | iadev->tx_dle_dma); | ||
2474 | } | ||
2475 | |||
2476 | static void ia_free_rx(IADEV *iadev) | ||
2477 | { | ||
2478 | kfree(iadev->rx_open); | ||
2479 | pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->rx_dle_q.start, | ||
2480 | iadev->rx_dle_dma); | ||
2481 | } | ||
2482 | |||
2483 | static int __init ia_start(struct atm_dev *dev) | ||
2484 | { | ||
2485 | IADEV *iadev; | ||
2486 | int error; | ||
2487 | unsigned char phy; | ||
2488 | u32 ctrl_reg; | ||
2489 | IF_EVENT(printk(">ia_start\n");) | ||
2490 | iadev = INPH_IA_DEV(dev); | ||
2491 | if (request_irq(iadev->irq, &ia_int, SA_SHIRQ, DEV_LABEL, dev)) { | ||
2492 | printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", | ||
2493 | dev->number, iadev->irq); | ||
2494 | error = -EAGAIN; | ||
2495 | goto err_out; | ||
2496 | } | ||
2497 | /* @@@ should release IRQ on error */ | ||
2498 | /* enabling memory + master */ | ||
2499 | if ((error = pci_write_config_word(iadev->pci, | ||
2500 | PCI_COMMAND, | ||
2501 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER ))) | ||
2502 | { | ||
2503 | printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+" | ||
2504 | "master (0x%x)\n",dev->number, error); | ||
2505 | error = -EIO; | ||
2506 | goto err_free_irq; | ||
2507 | } | ||
2508 | udelay(10); | ||
2509 | |||
2510 | /* Maybe we should reset the front end, initialize Bus Interface Control | ||
2511 | Registers and see. */ | ||
2512 | |||
2513 | IF_INIT(printk("Bus ctrl reg: %08x\n", | ||
2514 | readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));) | ||
2515 | ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2516 | ctrl_reg = (ctrl_reg & (CTRL_LED | CTRL_FE_RST)) | ||
2517 | | CTRL_B8 | ||
2518 | | CTRL_B16 | ||
2519 | | CTRL_B32 | ||
2520 | | CTRL_B48 | ||
2521 | | CTRL_B64 | ||
2522 | | CTRL_B128 | ||
2523 | | CTRL_ERRMASK | ||
2524 | | CTRL_DLETMASK /* shud be removed l8r */ | ||
2525 | | CTRL_DLERMASK | ||
2526 | | CTRL_SEGMASK | ||
2527 | | CTRL_REASSMASK | ||
2528 | | CTRL_FEMASK | ||
2529 | | CTRL_CSPREEMPT; | ||
2530 | |||
2531 | writel(ctrl_reg, iadev->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2532 | |||
2533 | IF_INIT(printk("Bus ctrl reg after initializing: %08x\n", | ||
2534 | readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG)); | ||
2535 | printk("Bus status reg after init: %08x\n", | ||
2536 | readl(iadev->reg+IPHASE5575_BUS_STATUS_REG));) | ||
2537 | |||
2538 | ia_hw_type(iadev); | ||
2539 | error = tx_init(dev); | ||
2540 | if (error) | ||
2541 | goto err_free_irq; | ||
2542 | error = rx_init(dev); | ||
2543 | if (error) | ||
2544 | goto err_free_tx; | ||
2545 | |||
2546 | ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2547 | writel(ctrl_reg | CTRL_FE_RST, iadev->reg+IPHASE5575_BUS_CONTROL_REG); | ||
2548 | IF_INIT(printk("Bus ctrl reg after initializing: %08x\n", | ||
2549 | readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));) | ||
2550 | phy = 0; /* resolve compiler complaint */ | ||
2551 | IF_INIT ( | ||
2552 | if ((phy=ia_phy_get(dev,0)) == 0x30) | ||
2553 | printk("IA: pm5346,rev.%d\n",phy&0x0f); | ||
2554 | else | ||
2555 | printk("IA: utopia,rev.%0x\n",phy);) | ||
2556 | |||
2557 | if (iadev->phy_type & FE_25MBIT_PHY) | ||
2558 | ia_mb25_init(iadev); | ||
2559 | else if (iadev->phy_type & (FE_DS3_PHY | FE_E3_PHY)) | ||
2560 | ia_suni_pm7345_init(iadev); | ||
2561 | else { | ||
2562 | error = suni_init(dev); | ||
2563 | if (error) | ||
2564 | goto err_free_rx; | ||
2565 | /* | ||
2566 | * Enable interrupt on loss of signal | ||
2567 | * SUNI_RSOP_CIE - 0x10 | ||
2568 | * SUNI_RSOP_CIE_LOSE - 0x04 | ||
2569 | */ | ||
2570 | ia_phy_put(dev, ia_phy_get(dev, 0x10) | 0x04, 0x10); | ||
2571 | #ifndef MODULE | ||
2572 | error = dev->phy->start(dev); | ||
2573 | if (error) | ||
2574 | goto err_free_rx; | ||
2575 | #endif | ||
2576 | /* Get iadev->carrier_detect status */ | ||
2577 | IaFrontEndIntr(iadev); | ||
2578 | } | ||
2579 | return 0; | ||
2580 | |||
2581 | err_free_rx: | ||
2582 | ia_free_rx(iadev); | ||
2583 | err_free_tx: | ||
2584 | ia_free_tx(iadev); | ||
2585 | err_free_irq: | ||
2586 | free_irq(iadev->irq, dev); | ||
2587 | err_out: | ||
2588 | return error; | ||
2589 | } | ||
2590 | |||
2591 | static void ia_close(struct atm_vcc *vcc) | ||
2592 | { | ||
2593 | DEFINE_WAIT(wait); | ||
2594 | u16 *vc_table; | ||
2595 | IADEV *iadev; | ||
2596 | struct ia_vcc *ia_vcc; | ||
2597 | struct sk_buff *skb = NULL; | ||
2598 | struct sk_buff_head tmp_tx_backlog, tmp_vcc_backlog; | ||
2599 | unsigned long closetime, flags; | ||
2600 | |||
2601 | iadev = INPH_IA_DEV(vcc->dev); | ||
2602 | ia_vcc = INPH_IA_VCC(vcc); | ||
2603 | if (!ia_vcc) return; | ||
2604 | |||
2605 | IF_EVENT(printk("ia_close: ia_vcc->vc_desc_cnt = %d vci = %d\n", | ||
2606 | ia_vcc->vc_desc_cnt,vcc->vci);) | ||
2607 | clear_bit(ATM_VF_READY,&vcc->flags); | ||
2608 | skb_queue_head_init (&tmp_tx_backlog); | ||
2609 | skb_queue_head_init (&tmp_vcc_backlog); | ||
2610 | if (vcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2611 | iadev->close_pending++; | ||
2612 | prepare_to_wait(&iadev->timeout_wait, &wait, TASK_UNINTERRUPTIBLE); | ||
2613 | schedule_timeout(50); | ||
2614 | finish_wait(&iadev->timeout_wait, &wait); | ||
2615 | spin_lock_irqsave(&iadev->tx_lock, flags); | ||
2616 | while((skb = skb_dequeue(&iadev->tx_backlog))) { | ||
2617 | if (ATM_SKB(skb)->vcc == vcc){ | ||
2618 | if (vcc->pop) vcc->pop(vcc, skb); | ||
2619 | else dev_kfree_skb_any(skb); | ||
2620 | } | ||
2621 | else | ||
2622 | skb_queue_tail(&tmp_tx_backlog, skb); | ||
2623 | } | ||
2624 | while((skb = skb_dequeue(&tmp_tx_backlog))) | ||
2625 | skb_queue_tail(&iadev->tx_backlog, skb); | ||
2626 | IF_EVENT(printk("IA TX Done decs_cnt = %d\n", ia_vcc->vc_desc_cnt);) | ||
2627 | closetime = 300000 / ia_vcc->pcr; | ||
2628 | if (closetime == 0) | ||
2629 | closetime = 1; | ||
2630 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
2631 | wait_event_timeout(iadev->close_wait, (ia_vcc->vc_desc_cnt <= 0), closetime); | ||
2632 | spin_lock_irqsave(&iadev->tx_lock, flags); | ||
2633 | iadev->close_pending--; | ||
2634 | iadev->testTable[vcc->vci]->lastTime = 0; | ||
2635 | iadev->testTable[vcc->vci]->fract = 0; | ||
2636 | iadev->testTable[vcc->vci]->vc_status = VC_UBR; | ||
2637 | if (vcc->qos.txtp.traffic_class == ATM_ABR) { | ||
2638 | if (vcc->qos.txtp.min_pcr > 0) | ||
2639 | iadev->sum_mcr -= vcc->qos.txtp.min_pcr; | ||
2640 | } | ||
2641 | if (vcc->qos.txtp.traffic_class == ATM_CBR) { | ||
2642 | ia_vcc = INPH_IA_VCC(vcc); | ||
2643 | iadev->sum_mcr -= ia_vcc->NumCbrEntry*iadev->Granularity; | ||
2644 | ia_cbrVc_close (vcc); | ||
2645 | } | ||
2646 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
2647 | } | ||
2648 | |||
2649 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2650 | // reset reass table | ||
2651 | vc_table = (u16 *)(iadev->reass_ram+REASS_TABLE*iadev->memSize); | ||
2652 | vc_table += vcc->vci; | ||
2653 | *vc_table = NO_AAL5_PKT; | ||
2654 | // reset vc table | ||
2655 | vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize); | ||
2656 | vc_table += vcc->vci; | ||
2657 | *vc_table = (vcc->vci << 6) | 15; | ||
2658 | if (vcc->qos.rxtp.traffic_class == ATM_ABR) { | ||
2659 | struct abr_vc_table __iomem *abr_vc_table = | ||
2660 | (iadev->reass_ram+ABR_VC_TABLE*iadev->memSize); | ||
2661 | abr_vc_table += vcc->vci; | ||
2662 | abr_vc_table->rdf = 0x0003; | ||
2663 | abr_vc_table->air = 0x5eb1; | ||
2664 | } | ||
2665 | // Drain the packets | ||
2666 | rx_dle_intr(vcc->dev); | ||
2667 | iadev->rx_open[vcc->vci] = NULL; | ||
2668 | } | ||
2669 | kfree(INPH_IA_VCC(vcc)); | ||
2670 | ia_vcc = NULL; | ||
2671 | vcc->dev_data = NULL; | ||
2672 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
2673 | return; | ||
2674 | } | ||
2675 | |||
2676 | static int ia_open(struct atm_vcc *vcc) | ||
2677 | { | ||
2678 | IADEV *iadev; | ||
2679 | struct ia_vcc *ia_vcc; | ||
2680 | int error; | ||
2681 | if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) | ||
2682 | { | ||
2683 | IF_EVENT(printk("ia: not partially allocated resources\n");) | ||
2684 | vcc->dev_data = NULL; | ||
2685 | } | ||
2686 | iadev = INPH_IA_DEV(vcc->dev); | ||
2687 | if (vcc->vci != ATM_VPI_UNSPEC && vcc->vpi != ATM_VCI_UNSPEC) | ||
2688 | { | ||
2689 | IF_EVENT(printk("iphase open: unspec part\n");) | ||
2690 | set_bit(ATM_VF_ADDR,&vcc->flags); | ||
2691 | } | ||
2692 | if (vcc->qos.aal != ATM_AAL5) | ||
2693 | return -EINVAL; | ||
2694 | IF_EVENT(printk(DEV_LABEL "(itf %d): open %d.%d\n", | ||
2695 | vcc->dev->number, vcc->vpi, vcc->vci);) | ||
2696 | |||
2697 | /* Device dependent initialization */ | ||
2698 | ia_vcc = kmalloc(sizeof(*ia_vcc), GFP_KERNEL); | ||
2699 | if (!ia_vcc) return -ENOMEM; | ||
2700 | vcc->dev_data = ia_vcc; | ||
2701 | |||
2702 | if ((error = open_rx(vcc))) | ||
2703 | { | ||
2704 | IF_EVENT(printk("iadev: error in open_rx, closing\n");) | ||
2705 | ia_close(vcc); | ||
2706 | return error; | ||
2707 | } | ||
2708 | |||
2709 | if ((error = open_tx(vcc))) | ||
2710 | { | ||
2711 | IF_EVENT(printk("iadev: error in open_tx, closing\n");) | ||
2712 | ia_close(vcc); | ||
2713 | return error; | ||
2714 | } | ||
2715 | |||
2716 | set_bit(ATM_VF_READY,&vcc->flags); | ||
2717 | |||
2718 | #if 0 | ||
2719 | { | ||
2720 | static u8 first = 1; | ||
2721 | if (first) { | ||
2722 | ia_timer.expires = jiffies + 3*HZ; | ||
2723 | add_timer(&ia_timer); | ||
2724 | first = 0; | ||
2725 | } | ||
2726 | } | ||
2727 | #endif | ||
2728 | IF_EVENT(printk("ia open returning\n");) | ||
2729 | return 0; | ||
2730 | } | ||
2731 | |||
2732 | static int ia_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags) | ||
2733 | { | ||
2734 | IF_EVENT(printk(">ia_change_qos\n");) | ||
2735 | return 0; | ||
2736 | } | ||
2737 | |||
2738 | static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) | ||
2739 | { | ||
2740 | IA_CMDBUF ia_cmds; | ||
2741 | IADEV *iadev; | ||
2742 | int i, board; | ||
2743 | u16 __user *tmps; | ||
2744 | IF_EVENT(printk(">ia_ioctl\n");) | ||
2745 | if (cmd != IA_CMD) { | ||
2746 | if (!dev->phy->ioctl) return -EINVAL; | ||
2747 | return dev->phy->ioctl(dev,cmd,arg); | ||
2748 | } | ||
2749 | if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT; | ||
2750 | board = ia_cmds.status; | ||
2751 | if ((board < 0) || (board > iadev_count)) | ||
2752 | board = 0; | ||
2753 | iadev = ia_dev[board]; | ||
2754 | switch (ia_cmds.cmd) { | ||
2755 | case MEMDUMP: | ||
2756 | { | ||
2757 | switch (ia_cmds.sub_cmd) { | ||
2758 | case MEMDUMP_DEV: | ||
2759 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2760 | if (copy_to_user(ia_cmds.buf, iadev, sizeof(IADEV))) | ||
2761 | return -EFAULT; | ||
2762 | ia_cmds.status = 0; | ||
2763 | break; | ||
2764 | case MEMDUMP_SEGREG: | ||
2765 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2766 | tmps = (u16 __user *)ia_cmds.buf; | ||
2767 | for(i=0; i<0x80; i+=2, tmps++) | ||
2768 | if(put_user((u16)(readl(iadev->seg_reg+i) & 0xffff), tmps)) return -EFAULT; | ||
2769 | ia_cmds.status = 0; | ||
2770 | ia_cmds.len = 0x80; | ||
2771 | break; | ||
2772 | case MEMDUMP_REASSREG: | ||
2773 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2774 | tmps = (u16 __user *)ia_cmds.buf; | ||
2775 | for(i=0; i<0x80; i+=2, tmps++) | ||
2776 | if(put_user((u16)(readl(iadev->reass_reg+i) & 0xffff), tmps)) return -EFAULT; | ||
2777 | ia_cmds.status = 0; | ||
2778 | ia_cmds.len = 0x80; | ||
2779 | break; | ||
2780 | case MEMDUMP_FFL: | ||
2781 | { | ||
2782 | ia_regs_t *regs_local; | ||
2783 | ffredn_t *ffL; | ||
2784 | rfredn_t *rfL; | ||
2785 | |||
2786 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2787 | regs_local = kmalloc(sizeof(*regs_local), GFP_KERNEL); | ||
2788 | if (!regs_local) return -ENOMEM; | ||
2789 | ffL = ®s_local->ffredn; | ||
2790 | rfL = ®s_local->rfredn; | ||
2791 | /* Copy real rfred registers into the local copy */ | ||
2792 | for (i=0; i<(sizeof (rfredn_t))/4; i++) | ||
2793 | ((u_int *)rfL)[i] = readl(iadev->reass_reg + i) & 0xffff; | ||
2794 | /* Copy real ffred registers into the local copy */ | ||
2795 | for (i=0; i<(sizeof (ffredn_t))/4; i++) | ||
2796 | ((u_int *)ffL)[i] = readl(iadev->seg_reg + i) & 0xffff; | ||
2797 | |||
2798 | if (copy_to_user(ia_cmds.buf, regs_local,sizeof(ia_regs_t))) { | ||
2799 | kfree(regs_local); | ||
2800 | return -EFAULT; | ||
2801 | } | ||
2802 | kfree(regs_local); | ||
2803 | printk("Board %d registers dumped\n", board); | ||
2804 | ia_cmds.status = 0; | ||
2805 | } | ||
2806 | break; | ||
2807 | case READ_REG: | ||
2808 | { | ||
2809 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2810 | desc_dbg(iadev); | ||
2811 | ia_cmds.status = 0; | ||
2812 | } | ||
2813 | break; | ||
2814 | case 0x6: | ||
2815 | { | ||
2816 | ia_cmds.status = 0; | ||
2817 | printk("skb = 0x%lx\n", (long)skb_peek(&iadev->tx_backlog)); | ||
2818 | printk("rtn_q: 0x%lx\n",(long)ia_deque_rtn_q(&iadev->tx_return_q)); | ||
2819 | } | ||
2820 | break; | ||
2821 | case 0x8: | ||
2822 | { | ||
2823 | struct k_sonet_stats *stats; | ||
2824 | stats = &PRIV(_ia_dev[board])->sonet_stats; | ||
2825 | printk("section_bip: %d\n", atomic_read(&stats->section_bip)); | ||
2826 | printk("line_bip : %d\n", atomic_read(&stats->line_bip)); | ||
2827 | printk("path_bip : %d\n", atomic_read(&stats->path_bip)); | ||
2828 | printk("line_febe : %d\n", atomic_read(&stats->line_febe)); | ||
2829 | printk("path_febe : %d\n", atomic_read(&stats->path_febe)); | ||
2830 | printk("corr_hcs : %d\n", atomic_read(&stats->corr_hcs)); | ||
2831 | printk("uncorr_hcs : %d\n", atomic_read(&stats->uncorr_hcs)); | ||
2832 | printk("tx_cells : %d\n", atomic_read(&stats->tx_cells)); | ||
2833 | printk("rx_cells : %d\n", atomic_read(&stats->rx_cells)); | ||
2834 | } | ||
2835 | ia_cmds.status = 0; | ||
2836 | break; | ||
2837 | case 0x9: | ||
2838 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2839 | for (i = 1; i <= iadev->num_rx_desc; i++) | ||
2840 | free_desc(_ia_dev[board], i); | ||
2841 | writew( ~(RX_FREEQ_EMPT | RX_EXCP_RCVD), | ||
2842 | iadev->reass_reg+REASS_MASK_REG); | ||
2843 | iadev->rxing = 1; | ||
2844 | |||
2845 | ia_cmds.status = 0; | ||
2846 | break; | ||
2847 | |||
2848 | case 0xb: | ||
2849 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2850 | IaFrontEndIntr(iadev); | ||
2851 | break; | ||
2852 | case 0xa: | ||
2853 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
2854 | { | ||
2855 | ia_cmds.status = 0; | ||
2856 | IADebugFlag = ia_cmds.maddr; | ||
2857 | printk("New debug option loaded\n"); | ||
2858 | } | ||
2859 | break; | ||
2860 | default: | ||
2861 | ia_cmds.status = 0; | ||
2862 | break; | ||
2863 | } | ||
2864 | } | ||
2865 | break; | ||
2866 | default: | ||
2867 | break; | ||
2868 | |||
2869 | } | ||
2870 | return 0; | ||
2871 | } | ||
2872 | |||
2873 | static int ia_getsockopt(struct atm_vcc *vcc, int level, int optname, | ||
2874 | void __user *optval, int optlen) | ||
2875 | { | ||
2876 | IF_EVENT(printk(">ia_getsockopt\n");) | ||
2877 | return -EINVAL; | ||
2878 | } | ||
2879 | |||
2880 | static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname, | ||
2881 | void __user *optval, int optlen) | ||
2882 | { | ||
2883 | IF_EVENT(printk(">ia_setsockopt\n");) | ||
2884 | return -EINVAL; | ||
2885 | } | ||
2886 | |||
2887 | static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { | ||
2888 | IADEV *iadev; | ||
2889 | struct dle *wr_ptr; | ||
2890 | struct tx_buf_desc __iomem *buf_desc_ptr; | ||
2891 | int desc; | ||
2892 | int comp_code; | ||
2893 | int total_len; | ||
2894 | struct cpcs_trailer *trailer; | ||
2895 | struct ia_vcc *iavcc; | ||
2896 | |||
2897 | iadev = INPH_IA_DEV(vcc->dev); | ||
2898 | iavcc = INPH_IA_VCC(vcc); | ||
2899 | if (!iavcc->txing) { | ||
2900 | printk("discard packet on closed VC\n"); | ||
2901 | if (vcc->pop) | ||
2902 | vcc->pop(vcc, skb); | ||
2903 | else | ||
2904 | dev_kfree_skb_any(skb); | ||
2905 | return 0; | ||
2906 | } | ||
2907 | |||
2908 | if (skb->len > iadev->tx_buf_sz - 8) { | ||
2909 | printk("Transmit size over tx buffer size\n"); | ||
2910 | if (vcc->pop) | ||
2911 | vcc->pop(vcc, skb); | ||
2912 | else | ||
2913 | dev_kfree_skb_any(skb); | ||
2914 | return 0; | ||
2915 | } | ||
2916 | if ((u32)skb->data & 3) { | ||
2917 | printk("Misaligned SKB\n"); | ||
2918 | if (vcc->pop) | ||
2919 | vcc->pop(vcc, skb); | ||
2920 | else | ||
2921 | dev_kfree_skb_any(skb); | ||
2922 | return 0; | ||
2923 | } | ||
2924 | /* Get a descriptor number from our free descriptor queue | ||
2925 | We get the descr number from the TCQ now, since I am using | ||
2926 | the TCQ as a free buffer queue. Initially TCQ will be | ||
2927 | initialized with all the descriptors and is hence, full. | ||
2928 | */ | ||
2929 | desc = get_desc (iadev, iavcc); | ||
2930 | if (desc == 0xffff) | ||
2931 | return 1; | ||
2932 | comp_code = desc >> 13; | ||
2933 | desc &= 0x1fff; | ||
2934 | |||
2935 | if ((desc == 0) || (desc > iadev->num_tx_desc)) | ||
2936 | { | ||
2937 | IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);) | ||
2938 | atomic_inc(&vcc->stats->tx); | ||
2939 | if (vcc->pop) | ||
2940 | vcc->pop(vcc, skb); | ||
2941 | else | ||
2942 | dev_kfree_skb_any(skb); | ||
2943 | return 0; /* return SUCCESS */ | ||
2944 | } | ||
2945 | |||
2946 | if (comp_code) | ||
2947 | { | ||
2948 | IF_ERR(printk(DEV_LABEL "send desc:%d completion code %d error\n", | ||
2949 | desc, comp_code);) | ||
2950 | } | ||
2951 | |||
2952 | /* remember the desc and vcc mapping */ | ||
2953 | iavcc->vc_desc_cnt++; | ||
2954 | iadev->desc_tbl[desc-1].iavcc = iavcc; | ||
2955 | iadev->desc_tbl[desc-1].txskb = skb; | ||
2956 | IA_SKB_STATE(skb) = 0; | ||
2957 | |||
2958 | iadev->ffL.tcq_rd += 2; | ||
2959 | if (iadev->ffL.tcq_rd > iadev->ffL.tcq_ed) | ||
2960 | iadev->ffL.tcq_rd = iadev->ffL.tcq_st; | ||
2961 | writew(iadev->ffL.tcq_rd, iadev->seg_reg+TCQ_RD_PTR); | ||
2962 | |||
2963 | /* Put the descriptor number in the packet ready queue | ||
2964 | and put the updated write pointer in the DLE field | ||
2965 | */ | ||
2966 | *(u16*)(iadev->seg_ram+iadev->ffL.prq_wr) = desc; | ||
2967 | |||
2968 | iadev->ffL.prq_wr += 2; | ||
2969 | if (iadev->ffL.prq_wr > iadev->ffL.prq_ed) | ||
2970 | iadev->ffL.prq_wr = iadev->ffL.prq_st; | ||
2971 | |||
2972 | /* Figure out the exact length of the packet and padding required to | ||
2973 | make it aligned on a 48 byte boundary. */ | ||
2974 | total_len = skb->len + sizeof(struct cpcs_trailer); | ||
2975 | total_len = ((total_len + 47) / 48) * 48; | ||
2976 | IF_TX(printk("ia packet len:%d padding:%d\n", total_len, total_len - skb->len);) | ||
2977 | |||
2978 | /* Put the packet in a tx buffer */ | ||
2979 | trailer = iadev->tx_buf[desc-1].cpcs; | ||
2980 | IF_TX(printk("Sent: skb = 0x%x skb->data: 0x%x len: %d, desc: %d\n", | ||
2981 | (u32)skb, (u32)skb->data, skb->len, desc);) | ||
2982 | trailer->control = 0; | ||
2983 | /*big endian*/ | ||
2984 | trailer->length = ((skb->len & 0xff) << 8) | ((skb->len & 0xff00) >> 8); | ||
2985 | trailer->crc32 = 0; /* not needed - dummy bytes */ | ||
2986 | |||
2987 | /* Display the packet */ | ||
2988 | IF_TXPKT(printk("Sent data: len = %d MsgNum = %d\n", | ||
2989 | skb->len, tcnter++); | ||
2990 | xdump(skb->data, skb->len, "TX: "); | ||
2991 | printk("\n");) | ||
2992 | |||
2993 | /* Build the buffer descriptor */ | ||
2994 | buf_desc_ptr = iadev->seg_ram+TX_DESC_BASE; | ||
2995 | buf_desc_ptr += desc; /* points to the corresponding entry */ | ||
2996 | buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT; | ||
2997 | /* Huh ? p.115 of users guide describes this as a read-only register */ | ||
2998 | writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG); | ||
2999 | buf_desc_ptr->vc_index = vcc->vci; | ||
3000 | buf_desc_ptr->bytes = total_len; | ||
3001 | |||
3002 | if (vcc->qos.txtp.traffic_class == ATM_ABR) | ||
3003 | clear_lockup (vcc, iadev); | ||
3004 | |||
3005 | /* Build the DLE structure */ | ||
3006 | wr_ptr = iadev->tx_dle_q.write; | ||
3007 | memset((caddr_t)wr_ptr, 0, sizeof(*wr_ptr)); | ||
3008 | wr_ptr->sys_pkt_addr = pci_map_single(iadev->pci, skb->data, | ||
3009 | skb->len, PCI_DMA_TODEVICE); | ||
3010 | wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) | | ||
3011 | buf_desc_ptr->buf_start_lo; | ||
3012 | /* wr_ptr->bytes = swap(total_len); didn't seem to affect ?? */ | ||
3013 | wr_ptr->bytes = skb->len; | ||
3014 | |||
3015 | /* hw bug - DLEs of 0x2d, 0x2e, 0x2f cause DMA lockup */ | ||
3016 | if ((wr_ptr->bytes >> 2) == 0xb) | ||
3017 | wr_ptr->bytes = 0x30; | ||
3018 | |||
3019 | wr_ptr->mode = TX_DLE_PSI; | ||
3020 | wr_ptr->prq_wr_ptr_data = 0; | ||
3021 | |||
3022 | /* end is not to be used for the DLE q */ | ||
3023 | if (++wr_ptr == iadev->tx_dle_q.end) | ||
3024 | wr_ptr = iadev->tx_dle_q.start; | ||
3025 | |||
3026 | /* Build trailer dle */ | ||
3027 | wr_ptr->sys_pkt_addr = iadev->tx_buf[desc-1].dma_addr; | ||
3028 | wr_ptr->local_pkt_addr = ((buf_desc_ptr->buf_start_hi << 16) | | ||
3029 | buf_desc_ptr->buf_start_lo) + total_len - sizeof(struct cpcs_trailer); | ||
3030 | |||
3031 | wr_ptr->bytes = sizeof(struct cpcs_trailer); | ||
3032 | wr_ptr->mode = DMA_INT_ENABLE; | ||
3033 | wr_ptr->prq_wr_ptr_data = iadev->ffL.prq_wr; | ||
3034 | |||
3035 | /* end is not to be used for the DLE q */ | ||
3036 | if (++wr_ptr == iadev->tx_dle_q.end) | ||
3037 | wr_ptr = iadev->tx_dle_q.start; | ||
3038 | |||
3039 | iadev->tx_dle_q.write = wr_ptr; | ||
3040 | ATM_DESC(skb) = vcc->vci; | ||
3041 | skb_queue_tail(&iadev->tx_dma_q, skb); | ||
3042 | |||
3043 | atomic_inc(&vcc->stats->tx); | ||
3044 | iadev->tx_pkt_cnt++; | ||
3045 | /* Increment transaction counter */ | ||
3046 | writel(2, iadev->dma+IPHASE5575_TX_COUNTER); | ||
3047 | |||
3048 | #if 0 | ||
3049 | /* add flow control logic */ | ||
3050 | if (atomic_read(&vcc->stats->tx) % 20 == 0) { | ||
3051 | if (iavcc->vc_desc_cnt > 10) { | ||
3052 | vcc->tx_quota = vcc->tx_quota * 3 / 4; | ||
3053 | printk("Tx1: vcc->tx_quota = %d \n", (u32)vcc->tx_quota ); | ||
3054 | iavcc->flow_inc = -1; | ||
3055 | iavcc->saved_tx_quota = vcc->tx_quota; | ||
3056 | } else if ((iavcc->flow_inc < 0) && (iavcc->vc_desc_cnt < 3)) { | ||
3057 | // vcc->tx_quota = 3 * iavcc->saved_tx_quota / 4; | ||
3058 | printk("Tx2: vcc->tx_quota = %d \n", (u32)vcc->tx_quota ); | ||
3059 | iavcc->flow_inc = 0; | ||
3060 | } | ||
3061 | } | ||
3062 | #endif | ||
3063 | IF_TX(printk("ia send done\n");) | ||
3064 | return 0; | ||
3065 | } | ||
3066 | |||
3067 | static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
3068 | { | ||
3069 | IADEV *iadev; | ||
3070 | struct ia_vcc *iavcc; | ||
3071 | unsigned long flags; | ||
3072 | |||
3073 | iadev = INPH_IA_DEV(vcc->dev); | ||
3074 | iavcc = INPH_IA_VCC(vcc); | ||
3075 | if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer)))) | ||
3076 | { | ||
3077 | if (!skb) | ||
3078 | printk(KERN_CRIT "null skb in ia_send\n"); | ||
3079 | else dev_kfree_skb_any(skb); | ||
3080 | return -EINVAL; | ||
3081 | } | ||
3082 | spin_lock_irqsave(&iadev->tx_lock, flags); | ||
3083 | if (!test_bit(ATM_VF_READY,&vcc->flags)){ | ||
3084 | dev_kfree_skb_any(skb); | ||
3085 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
3086 | return -EINVAL; | ||
3087 | } | ||
3088 | ATM_SKB(skb)->vcc = vcc; | ||
3089 | |||
3090 | if (skb_peek(&iadev->tx_backlog)) { | ||
3091 | skb_queue_tail(&iadev->tx_backlog, skb); | ||
3092 | } | ||
3093 | else { | ||
3094 | if (ia_pkt_tx (vcc, skb)) { | ||
3095 | skb_queue_tail(&iadev->tx_backlog, skb); | ||
3096 | } | ||
3097 | } | ||
3098 | spin_unlock_irqrestore(&iadev->tx_lock, flags); | ||
3099 | return 0; | ||
3100 | |||
3101 | } | ||
3102 | |||
3103 | static int ia_proc_read(struct atm_dev *dev,loff_t *pos,char *page) | ||
3104 | { | ||
3105 | int left = *pos, n; | ||
3106 | char *tmpPtr; | ||
3107 | IADEV *iadev = INPH_IA_DEV(dev); | ||
3108 | if(!left--) { | ||
3109 | if (iadev->phy_type == FE_25MBIT_PHY) { | ||
3110 | n = sprintf(page, " Board Type : Iphase5525-1KVC-128K\n"); | ||
3111 | return n; | ||
3112 | } | ||
3113 | if (iadev->phy_type == FE_DS3_PHY) | ||
3114 | n = sprintf(page, " Board Type : Iphase-ATM-DS3"); | ||
3115 | else if (iadev->phy_type == FE_E3_PHY) | ||
3116 | n = sprintf(page, " Board Type : Iphase-ATM-E3"); | ||
3117 | else if (iadev->phy_type == FE_UTP_OPTION) | ||
3118 | n = sprintf(page, " Board Type : Iphase-ATM-UTP155"); | ||
3119 | else | ||
3120 | n = sprintf(page, " Board Type : Iphase-ATM-OC3"); | ||
3121 | tmpPtr = page + n; | ||
3122 | if (iadev->pci_map_size == 0x40000) | ||
3123 | n += sprintf(tmpPtr, "-1KVC-"); | ||
3124 | else | ||
3125 | n += sprintf(tmpPtr, "-4KVC-"); | ||
3126 | tmpPtr = page + n; | ||
3127 | if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_1M) | ||
3128 | n += sprintf(tmpPtr, "1M \n"); | ||
3129 | else if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_512K) | ||
3130 | n += sprintf(tmpPtr, "512K\n"); | ||
3131 | else | ||
3132 | n += sprintf(tmpPtr, "128K\n"); | ||
3133 | return n; | ||
3134 | } | ||
3135 | if (!left) { | ||
3136 | return sprintf(page, " Number of Tx Buffer: %u\n" | ||
3137 | " Size of Tx Buffer : %u\n" | ||
3138 | " Number of Rx Buffer: %u\n" | ||
3139 | " Size of Rx Buffer : %u\n" | ||
3140 | " Packets Receiverd : %u\n" | ||
3141 | " Packets Transmitted: %u\n" | ||
3142 | " Cells Received : %u\n" | ||
3143 | " Cells Transmitted : %u\n" | ||
3144 | " Board Dropped Cells: %u\n" | ||
3145 | " Board Dropped Pkts : %u\n", | ||
3146 | iadev->num_tx_desc, iadev->tx_buf_sz, | ||
3147 | iadev->num_rx_desc, iadev->rx_buf_sz, | ||
3148 | iadev->rx_pkt_cnt, iadev->tx_pkt_cnt, | ||
3149 | iadev->rx_cell_cnt, iadev->tx_cell_cnt, | ||
3150 | iadev->drop_rxcell, iadev->drop_rxpkt); | ||
3151 | } | ||
3152 | return 0; | ||
3153 | } | ||
3154 | |||
3155 | static const struct atmdev_ops ops = { | ||
3156 | .open = ia_open, | ||
3157 | .close = ia_close, | ||
3158 | .ioctl = ia_ioctl, | ||
3159 | .getsockopt = ia_getsockopt, | ||
3160 | .setsockopt = ia_setsockopt, | ||
3161 | .send = ia_send, | ||
3162 | .phy_put = ia_phy_put, | ||
3163 | .phy_get = ia_phy_get, | ||
3164 | .change_qos = ia_change_qos, | ||
3165 | .proc_read = ia_proc_read, | ||
3166 | .owner = THIS_MODULE, | ||
3167 | }; | ||
3168 | |||
3169 | static int __devinit ia_init_one(struct pci_dev *pdev, | ||
3170 | const struct pci_device_id *ent) | ||
3171 | { | ||
3172 | struct atm_dev *dev; | ||
3173 | IADEV *iadev; | ||
3174 | unsigned long flags; | ||
3175 | int ret; | ||
3176 | |||
3177 | iadev = kmalloc(sizeof(*iadev), GFP_KERNEL); | ||
3178 | if (!iadev) { | ||
3179 | ret = -ENOMEM; | ||
3180 | goto err_out; | ||
3181 | } | ||
3182 | memset(iadev, 0, sizeof(*iadev)); | ||
3183 | iadev->pci = pdev; | ||
3184 | |||
3185 | IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n", | ||
3186 | pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));) | ||
3187 | if (pci_enable_device(pdev)) { | ||
3188 | ret = -ENODEV; | ||
3189 | goto err_out_free_iadev; | ||
3190 | } | ||
3191 | dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); | ||
3192 | if (!dev) { | ||
3193 | ret = -ENOMEM; | ||
3194 | goto err_out_disable_dev; | ||
3195 | } | ||
3196 | dev->dev_data = iadev; | ||
3197 | IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", dev->number);) | ||
3198 | IF_INIT(printk("dev_id = 0x%x iadev->LineRate = %d \n", (u32)dev, | ||
3199 | iadev->LineRate);) | ||
3200 | |||
3201 | ia_dev[iadev_count] = iadev; | ||
3202 | _ia_dev[iadev_count] = dev; | ||
3203 | iadev_count++; | ||
3204 | spin_lock_init(&iadev->misc_lock); | ||
3205 | /* First fixes first. I don't want to think about this now. */ | ||
3206 | spin_lock_irqsave(&iadev->misc_lock, flags); | ||
3207 | if (ia_init(dev) || ia_start(dev)) { | ||
3208 | IF_INIT(printk("IA register failed!\n");) | ||
3209 | iadev_count--; | ||
3210 | ia_dev[iadev_count] = NULL; | ||
3211 | _ia_dev[iadev_count] = NULL; | ||
3212 | spin_unlock_irqrestore(&iadev->misc_lock, flags); | ||
3213 | ret = -EINVAL; | ||
3214 | goto err_out_deregister_dev; | ||
3215 | } | ||
3216 | spin_unlock_irqrestore(&iadev->misc_lock, flags); | ||
3217 | IF_EVENT(printk("iadev_count = %d\n", iadev_count);) | ||
3218 | |||
3219 | iadev->next_board = ia_boards; | ||
3220 | ia_boards = dev; | ||
3221 | |||
3222 | pci_set_drvdata(pdev, dev); | ||
3223 | |||
3224 | return 0; | ||
3225 | |||
3226 | err_out_deregister_dev: | ||
3227 | atm_dev_deregister(dev); | ||
3228 | err_out_disable_dev: | ||
3229 | pci_disable_device(pdev); | ||
3230 | err_out_free_iadev: | ||
3231 | kfree(iadev); | ||
3232 | err_out: | ||
3233 | return ret; | ||
3234 | } | ||
3235 | |||
3236 | static void __devexit ia_remove_one(struct pci_dev *pdev) | ||
3237 | { | ||
3238 | struct atm_dev *dev = pci_get_drvdata(pdev); | ||
3239 | IADEV *iadev = INPH_IA_DEV(dev); | ||
3240 | |||
3241 | ia_phy_put(dev, ia_phy_get(dev,0x10) & ~(0x4), 0x10); | ||
3242 | udelay(1); | ||
3243 | |||
3244 | /* De-register device */ | ||
3245 | free_irq(iadev->irq, dev); | ||
3246 | iadev_count--; | ||
3247 | ia_dev[iadev_count] = NULL; | ||
3248 | _ia_dev[iadev_count] = NULL; | ||
3249 | IF_EVENT(printk("deregistering iav at (itf:%d)\n", dev->number);) | ||
3250 | atm_dev_deregister(dev); | ||
3251 | |||
3252 | iounmap(iadev->base); | ||
3253 | pci_disable_device(pdev); | ||
3254 | |||
3255 | ia_free_rx(iadev); | ||
3256 | ia_free_tx(iadev); | ||
3257 | |||
3258 | kfree(iadev); | ||
3259 | } | ||
3260 | |||
3261 | static struct pci_device_id ia_pci_tbl[] = { | ||
3262 | { PCI_VENDOR_ID_IPHASE, 0x0008, PCI_ANY_ID, PCI_ANY_ID, }, | ||
3263 | { PCI_VENDOR_ID_IPHASE, 0x0009, PCI_ANY_ID, PCI_ANY_ID, }, | ||
3264 | { 0,} | ||
3265 | }; | ||
3266 | MODULE_DEVICE_TABLE(pci, ia_pci_tbl); | ||
3267 | |||
3268 | static struct pci_driver ia_driver = { | ||
3269 | .name = DEV_LABEL, | ||
3270 | .id_table = ia_pci_tbl, | ||
3271 | .probe = ia_init_one, | ||
3272 | .remove = __devexit_p(ia_remove_one), | ||
3273 | }; | ||
3274 | |||
3275 | static int __init ia_module_init(void) | ||
3276 | { | ||
3277 | int ret; | ||
3278 | |||
3279 | ret = pci_register_driver(&ia_driver); | ||
3280 | if (ret >= 0) { | ||
3281 | ia_timer.expires = jiffies + 3*HZ; | ||
3282 | add_timer(&ia_timer); | ||
3283 | } else | ||
3284 | printk(KERN_ERR DEV_LABEL ": no adapter found\n"); | ||
3285 | return ret; | ||
3286 | } | ||
3287 | |||
3288 | static void __exit ia_module_exit(void) | ||
3289 | { | ||
3290 | pci_unregister_driver(&ia_driver); | ||
3291 | |||
3292 | del_timer(&ia_timer); | ||
3293 | } | ||
3294 | |||
3295 | module_init(ia_module_init); | ||
3296 | module_exit(ia_module_exit); | ||
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h new file mode 100644 index 000000000000..b8d0bd4d6c30 --- /dev/null +++ b/drivers/atm/iphase.h | |||
@@ -0,0 +1,1464 @@ | |||
1 | /****************************************************************************** | ||
2 | Device driver for Interphase ATM PCI adapter cards | ||
3 | Author: Peter Wang <pwang@iphase.com> | ||
4 | Interphase Corporation <www.iphase.com> | ||
5 | Version: 1.0 | ||
6 | iphase.h: This is the header file for iphase.c. | ||
7 | ******************************************************************************* | ||
8 | |||
9 | This software may be used and distributed according to the terms | ||
10 | of the GNU General Public License (GPL), incorporated herein by reference. | ||
11 | Drivers based on this skeleton fall under the GPL and must retain | ||
12 | the authorship (implicit copyright) notice. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | General Public License for more details. | ||
18 | |||
19 | Modified from an incomplete driver for Interphase 5575 1KVC 1M card which | ||
20 | was originally written by Monalisa Agrawal at UNH. Now this driver | ||
21 | supports a variety of varients of Interphase ATM PCI (i)Chip adapter | ||
22 | card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM) | ||
23 | in terms of PHY type, the size of control memory and the size of | ||
24 | packet memory. The followings are the change log and history: | ||
25 | |||
26 | Bugfix the Mona's UBR driver. | ||
27 | Modify the basic memory allocation and dma logic. | ||
28 | Port the driver to the latest kernel from 2.0.46. | ||
29 | Complete the ABR logic of the driver, and added the ABR work- | ||
30 | around for the hardware anormalies. | ||
31 | Add the CBR support. | ||
32 | Add the flow control logic to the driver to allow rate-limit VC. | ||
33 | Add 4K VC support to the board with 512K control memory. | ||
34 | Add the support of all the variants of the Interphase ATM PCI | ||
35 | (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525 | ||
36 | (25M UTP25) and x531 (DS3 and E3). | ||
37 | Add SMP support. | ||
38 | |||
39 | Support and updates available at: ftp://ftp.iphase.com/pub/atm | ||
40 | |||
41 | *******************************************************************************/ | ||
42 | |||
43 | #ifndef IPHASE_H | ||
44 | #define IPHASE_H | ||
45 | |||
46 | #include <linux/config.h> | ||
47 | |||
48 | /************************ IADBG DEFINE *********************************/ | ||
49 | /* IADebugFlag Bit Map */ | ||
50 | #define IF_IADBG_INIT_ADAPTER 0x00000001 // init adapter info | ||
51 | #define IF_IADBG_TX 0x00000002 // debug TX | ||
52 | #define IF_IADBG_RX 0x00000004 // debug RX | ||
53 | #define IF_IADBG_QUERY_INFO 0x00000008 // debug Request call | ||
54 | #define IF_IADBG_SHUTDOWN 0x00000010 // debug shutdown event | ||
55 | #define IF_IADBG_INTR 0x00000020 // debug interrupt DPC | ||
56 | #define IF_IADBG_TXPKT 0x00000040 // debug TX PKT | ||
57 | #define IF_IADBG_RXPKT 0x00000080 // debug RX PKT | ||
58 | #define IF_IADBG_ERR 0x00000100 // debug system error | ||
59 | #define IF_IADBG_EVENT 0x00000200 // debug event | ||
60 | #define IF_IADBG_DIS_INTR 0x00001000 // debug disable interrupt | ||
61 | #define IF_IADBG_EN_INTR 0x00002000 // debug enable interrupt | ||
62 | #define IF_IADBG_LOUD 0x00004000 // debugging info | ||
63 | #define IF_IADBG_VERY_LOUD 0x00008000 // excessive debugging info | ||
64 | #define IF_IADBG_CBR 0x00100000 // | ||
65 | #define IF_IADBG_UBR 0x00200000 // | ||
66 | #define IF_IADBG_ABR 0x00400000 // | ||
67 | #define IF_IADBG_DESC 0x01000000 // | ||
68 | #define IF_IADBG_SUNI_STAT 0x02000000 // suni statistics | ||
69 | #define IF_IADBG_RESET 0x04000000 | ||
70 | |||
71 | #define IF_IADBG(f) if (IADebugFlag & (f)) | ||
72 | |||
73 | #ifdef CONFIG_ATM_IA_DEBUG /* Debug build */ | ||
74 | |||
75 | #define IF_LOUD(A) IF_IADBG(IF_IADBG_LOUD) { A } | ||
76 | #define IF_ERR(A) IF_IADBG(IF_IADBG_ERR) { A } | ||
77 | #define IF_VERY_LOUD(A) IF_IADBG( IF_IADBG_VERY_LOUD ) { A } | ||
78 | |||
79 | #define IF_INIT_ADAPTER(A) IF_IADBG( IF_IADBG_INIT_ADAPTER ) { A } | ||
80 | #define IF_INIT(A) IF_IADBG( IF_IADBG_INIT_ADAPTER ) { A } | ||
81 | #define IF_SUNI_STAT(A) IF_IADBG( IF_IADBG_SUNI_STAT ) { A } | ||
82 | #define IF_QUERY_INFO(A) IF_IADBG( IF_IADBG_QUERY_INFO ) { A } | ||
83 | #define IF_COPY_OVER(A) IF_IADBG( IF_IADBG_COPY_OVER ) { A } | ||
84 | |||
85 | #define IF_INTR(A) IF_IADBG( IF_IADBG_INTR ) { A } | ||
86 | #define IF_DIS_INTR(A) IF_IADBG( IF_IADBG_DIS_INTR ) { A } | ||
87 | #define IF_EN_INTR(A) IF_IADBG( IF_IADBG_EN_INTR ) { A } | ||
88 | |||
89 | #define IF_TX(A) IF_IADBG( IF_IADBG_TX ) { A } | ||
90 | #define IF_RX(A) IF_IADBG( IF_IADBG_RX ) { A } | ||
91 | #define IF_TXPKT(A) IF_IADBG( IF_IADBG_TXPKT ) { A } | ||
92 | #define IF_RXPKT(A) IF_IADBG( IF_IADBG_RXPKT ) { A } | ||
93 | |||
94 | #define IF_SHUTDOWN(A) IF_IADBG(IF_IADBG_SHUTDOWN) { A } | ||
95 | #define IF_CBR(A) IF_IADBG( IF_IADBG_CBR ) { A } | ||
96 | #define IF_UBR(A) IF_IADBG( IF_IADBG_UBR ) { A } | ||
97 | #define IF_ABR(A) IF_IADBG( IF_IADBG_ABR ) { A } | ||
98 | #define IF_EVENT(A) IF_IADBG( IF_IADBG_EVENT) { A } | ||
99 | |||
100 | #else /* free build */ | ||
101 | #define IF_LOUD(A) | ||
102 | #define IF_VERY_LOUD(A) | ||
103 | #define IF_INIT_ADAPTER(A) | ||
104 | #define IF_INIT(A) | ||
105 | #define IF_SUNI_STAT(A) | ||
106 | #define IF_PVC_CHKPKT(A) | ||
107 | #define IF_QUERY_INFO(A) | ||
108 | #define IF_COPY_OVER(A) | ||
109 | #define IF_HANG(A) | ||
110 | #define IF_INTR(A) | ||
111 | #define IF_DIS_INTR(A) | ||
112 | #define IF_EN_INTR(A) | ||
113 | #define IF_TX(A) | ||
114 | #define IF_RX(A) | ||
115 | #define IF_TXDEBUG(A) | ||
116 | #define IF_VC(A) | ||
117 | #define IF_ERR(A) | ||
118 | #define IF_CBR(A) | ||
119 | #define IF_UBR(A) | ||
120 | #define IF_ABR(A) | ||
121 | #define IF_SHUTDOWN(A) | ||
122 | #define DbgPrint(A) | ||
123 | #define IF_EVENT(A) | ||
124 | #define IF_TXPKT(A) | ||
125 | #define IF_RXPKT(A) | ||
126 | #endif /* CONFIG_ATM_IA_DEBUG */ | ||
127 | |||
128 | #define isprint(a) ((a >=' ')&&(a <= '~')) | ||
129 | #define ATM_DESC(skb) (skb->protocol) | ||
130 | #define IA_SKB_STATE(skb) (skb->protocol) | ||
131 | #define IA_DLED 1 | ||
132 | #define IA_TX_DONE 2 | ||
133 | |||
134 | /* iadbg defines */ | ||
135 | #define IA_CMD 0x7749 | ||
136 | typedef struct { | ||
137 | int cmd; | ||
138 | int sub_cmd; | ||
139 | int len; | ||
140 | u32 maddr; | ||
141 | int status; | ||
142 | void __user *buf; | ||
143 | } IA_CMDBUF, *PIA_CMDBUF; | ||
144 | |||
145 | /* cmds */ | ||
146 | #define MEMDUMP 0x01 | ||
147 | |||
148 | /* sub_cmds */ | ||
149 | #define MEMDUMP_SEGREG 0x2 | ||
150 | #define MEMDUMP_DEV 0x1 | ||
151 | #define MEMDUMP_REASSREG 0x3 | ||
152 | #define MEMDUMP_FFL 0x4 | ||
153 | #define READ_REG 0x5 | ||
154 | #define WAKE_DBG_WAIT 0x6 | ||
155 | |||
156 | /************************ IADBG DEFINE END ***************************/ | ||
157 | |||
158 | #define Boolean(x) ((x) ? 1 : 0) | ||
159 | #define NR_VCI 1024 /* number of VCIs */ | ||
160 | #define NR_VCI_LD 10 /* log2(NR_VCI) */ | ||
161 | #define NR_VCI_4K 4096 /* number of VCIs */ | ||
162 | #define NR_VCI_4K_LD 12 /* log2(NR_VCI) */ | ||
163 | #define MEM_VALID 0xfffffff0 /* mask base address with this */ | ||
164 | |||
165 | #ifndef PCI_VENDOR_ID_IPHASE | ||
166 | #define PCI_VENDOR_ID_IPHASE 0x107e | ||
167 | #endif | ||
168 | #ifndef PCI_DEVICE_ID_IPHASE_5575 | ||
169 | #define PCI_DEVICE_ID_IPHASE_5575 0x0008 | ||
170 | #endif | ||
171 | #define DEV_LABEL "ia" | ||
172 | #define PCR 207692 | ||
173 | #define ICR 100000 | ||
174 | #define MCR 0 | ||
175 | #define TBE 1000 | ||
176 | #define FRTT 1 | ||
177 | #define RIF 2 | ||
178 | #define RDF 4 | ||
179 | #define NRMCODE 5 /* 0 - 7 */ | ||
180 | #define TRMCODE 3 /* 0 - 7 */ | ||
181 | #define CDFCODE 6 | ||
182 | #define ATDFCODE 2 /* 0 - 15 */ | ||
183 | |||
184 | /*---------------------- Packet/Cell Memory ------------------------*/ | ||
185 | #define TX_PACKET_RAM 0x00000 /* start of Trasnmit Packet memory - 0 */ | ||
186 | #define DFL_TX_BUF_SZ 10240 /* 10 K buffers */ | ||
187 | #define DFL_TX_BUFFERS 50 /* number of packet buffers for Tx | ||
188 | - descriptor 0 unused */ | ||
189 | #define REASS_RAM_SIZE 0x10000 /* for 64K 1K VC board */ | ||
190 | #define RX_PACKET_RAM 0x80000 /* start of Receive Packet memory - 512K */ | ||
191 | #define DFL_RX_BUF_SZ 10240 /* 10k buffers */ | ||
192 | #define DFL_RX_BUFFERS 50 /* number of packet buffers for Rx | ||
193 | - descriptor 0 unused */ | ||
194 | |||
195 | struct cpcs_trailer | ||
196 | { | ||
197 | u_short control; | ||
198 | u_short length; | ||
199 | u_int crc32; | ||
200 | }; | ||
201 | |||
202 | struct cpcs_trailer_desc | ||
203 | { | ||
204 | struct cpcs_trailer *cpcs; | ||
205 | dma_addr_t dma_addr; | ||
206 | }; | ||
207 | |||
208 | struct ia_vcc | ||
209 | { | ||
210 | int rxing; | ||
211 | int txing; | ||
212 | int NumCbrEntry; | ||
213 | u32 pcr; | ||
214 | u32 saved_tx_quota; | ||
215 | int flow_inc; | ||
216 | struct sk_buff_head txing_skb; | ||
217 | int ltimeout; | ||
218 | u8 vc_desc_cnt; | ||
219 | |||
220 | }; | ||
221 | |||
222 | struct abr_vc_table | ||
223 | { | ||
224 | u_char status; | ||
225 | u_char rdf; | ||
226 | u_short air; | ||
227 | u_int res[3]; | ||
228 | u_int req_rm_cell_data1; | ||
229 | u_int req_rm_cell_data2; | ||
230 | u_int add_rm_cell_data1; | ||
231 | u_int add_rm_cell_data2; | ||
232 | }; | ||
233 | |||
234 | /* 32 byte entries */ | ||
235 | struct main_vc | ||
236 | { | ||
237 | u_short type; | ||
238 | #define ABR 0x8000 | ||
239 | #define UBR 0xc000 | ||
240 | #define CBR 0x0000 | ||
241 | /* ABR fields */ | ||
242 | u_short nrm; | ||
243 | u_short trm; | ||
244 | u_short rm_timestamp_hi; | ||
245 | u_short rm_timestamp_lo:8, | ||
246 | crm:8; | ||
247 | u_short remainder; /* ABR and UBR fields - last 10 bits*/ | ||
248 | u_short next_vc_sched; | ||
249 | u_short present_desc; /* all classes */ | ||
250 | u_short last_cell_slot; /* ABR and UBR */ | ||
251 | u_short pcr; | ||
252 | u_short fraction; | ||
253 | u_short icr; | ||
254 | u_short atdf; | ||
255 | u_short mcr; | ||
256 | u_short acr; | ||
257 | u_short unack:8, | ||
258 | status:8; /* all classes */ | ||
259 | #define UIOLI 0x80 | ||
260 | #define CRC_APPEND 0x40 /* for status field - CRC-32 append */ | ||
261 | #define ABR_STATE 0x02 | ||
262 | |||
263 | }; | ||
264 | |||
265 | |||
266 | /* 8 byte entries */ | ||
267 | struct ext_vc | ||
268 | { | ||
269 | u_short atm_hdr1; | ||
270 | u_short atm_hdr2; | ||
271 | u_short last_desc; | ||
272 | u_short out_of_rate_link; /* reserved for UBR and CBR */ | ||
273 | }; | ||
274 | |||
275 | |||
276 | #define DLE_ENTRIES 256 | ||
277 | #define DMA_INT_ENABLE 0x0002 /* use for both Tx and Rx */ | ||
278 | #define TX_DLE_PSI 0x0001 | ||
279 | #define DLE_TOTAL_SIZE (sizeof(struct dle)*DLE_ENTRIES) | ||
280 | |||
281 | /* Descriptor List Entries (DLE) */ | ||
282 | struct dle | ||
283 | { | ||
284 | u32 sys_pkt_addr; | ||
285 | u32 local_pkt_addr; | ||
286 | u32 bytes; | ||
287 | u16 prq_wr_ptr_data; | ||
288 | u16 mode; | ||
289 | }; | ||
290 | |||
291 | struct dle_q | ||
292 | { | ||
293 | struct dle *start; | ||
294 | struct dle *end; | ||
295 | struct dle *read; | ||
296 | struct dle *write; | ||
297 | }; | ||
298 | |||
299 | struct free_desc_q | ||
300 | { | ||
301 | int desc; /* Descriptor number */ | ||
302 | struct free_desc_q *next; | ||
303 | }; | ||
304 | |||
305 | struct tx_buf_desc { | ||
306 | unsigned short desc_mode; | ||
307 | unsigned short vc_index; | ||
308 | unsigned short res1; /* reserved field */ | ||
309 | unsigned short bytes; | ||
310 | unsigned short buf_start_hi; | ||
311 | unsigned short buf_start_lo; | ||
312 | unsigned short res2[10]; /* reserved field */ | ||
313 | }; | ||
314 | |||
315 | |||
316 | struct rx_buf_desc { | ||
317 | unsigned short desc_mode; | ||
318 | unsigned short vc_index; | ||
319 | unsigned short vpi; | ||
320 | unsigned short bytes; | ||
321 | unsigned short buf_start_hi; | ||
322 | unsigned short buf_start_lo; | ||
323 | unsigned short dma_start_hi; | ||
324 | unsigned short dma_start_lo; | ||
325 | unsigned short crc_upper; | ||
326 | unsigned short crc_lower; | ||
327 | unsigned short res:8, timeout:8; | ||
328 | unsigned short res2[5]; /* reserved field */ | ||
329 | }; | ||
330 | |||
331 | /*--------SAR stuff ---------------------*/ | ||
332 | |||
333 | #define EPROM_SIZE 0x40000 /* says 64K in the docs ??? */ | ||
334 | #define MAC1_LEN 4 | ||
335 | #define MAC2_LEN 2 | ||
336 | |||
337 | /*------------ PCI Memory Space Map, 128K SAR memory ----------------*/ | ||
338 | #define IPHASE5575_PCI_CONFIG_REG_BASE 0x0000 | ||
339 | #define IPHASE5575_BUS_CONTROL_REG_BASE 0x1000 /* offsets 0x00 - 0x3c */ | ||
340 | #define IPHASE5575_FRAG_CONTROL_REG_BASE 0x2000 | ||
341 | #define IPHASE5575_REASS_CONTROL_REG_BASE 0x3000 | ||
342 | #define IPHASE5575_DMA_CONTROL_REG_BASE 0x4000 | ||
343 | #define IPHASE5575_FRONT_END_REG_BASE IPHASE5575_DMA_CONTROL_REG_BASE | ||
344 | #define IPHASE5575_FRAG_CONTROL_RAM_BASE 0x10000 | ||
345 | #define IPHASE5575_REASS_CONTROL_RAM_BASE 0x20000 | ||
346 | |||
347 | /*------------ Bus interface control registers -----------------*/ | ||
348 | #define IPHASE5575_BUS_CONTROL_REG 0x00 | ||
349 | #define IPHASE5575_BUS_STATUS_REG 0x01 /* actual offset 0x04 */ | ||
350 | #define IPHASE5575_MAC1 0x02 | ||
351 | #define IPHASE5575_REV 0x03 | ||
352 | #define IPHASE5575_MAC2 0x03 /*actual offset 0x0e-reg 0x0c*/ | ||
353 | #define IPHASE5575_EXT_RESET 0x04 | ||
354 | #define IPHASE5575_INT_RESET 0x05 /* addr 1c ?? reg 0x06 */ | ||
355 | #define IPHASE5575_PCI_ADDR_PAGE 0x07 /* reg 0x08, 0x09 ?? */ | ||
356 | #define IPHASE5575_EEPROM_ACCESS 0x0a /* actual offset 0x28 */ | ||
357 | #define IPHASE5575_CELL_FIFO_QUEUE_SZ 0x0b | ||
358 | #define IPHASE5575_CELL_FIFO_MARK_STATE 0x0c | ||
359 | #define IPHASE5575_CELL_FIFO_READ_PTR 0x0d | ||
360 | #define IPHASE5575_CELL_FIFO_WRITE_PTR 0x0e | ||
361 | #define IPHASE5575_CELL_FIFO_CELLS_AVL 0x0f /* actual offset 0x3c */ | ||
362 | |||
363 | /* Bus Interface Control Register bits */ | ||
364 | #define CTRL_FE_RST 0x80000000 | ||
365 | #define CTRL_LED 0x40000000 | ||
366 | #define CTRL_25MBPHY 0x10000000 | ||
367 | #define CTRL_ENCMBMEM 0x08000000 | ||
368 | #define CTRL_ENOFFSEG 0x01000000 | ||
369 | #define CTRL_ERRMASK 0x00400000 | ||
370 | #define CTRL_DLETMASK 0x00100000 | ||
371 | #define CTRL_DLERMASK 0x00080000 | ||
372 | #define CTRL_FEMASK 0x00040000 | ||
373 | #define CTRL_SEGMASK 0x00020000 | ||
374 | #define CTRL_REASSMASK 0x00010000 | ||
375 | #define CTRL_CSPREEMPT 0x00002000 | ||
376 | #define CTRL_B128 0x00000200 | ||
377 | #define CTRL_B64 0x00000100 | ||
378 | #define CTRL_B48 0x00000080 | ||
379 | #define CTRL_B32 0x00000040 | ||
380 | #define CTRL_B16 0x00000020 | ||
381 | #define CTRL_B8 0x00000010 | ||
382 | |||
383 | /* Bus Interface Status Register bits */ | ||
384 | #define STAT_CMEMSIZ 0xc0000000 | ||
385 | #define STAT_ADPARCK 0x20000000 | ||
386 | #define STAT_RESVD 0x1fffff80 | ||
387 | #define STAT_ERRINT 0x00000040 | ||
388 | #define STAT_MARKINT 0x00000020 | ||
389 | #define STAT_DLETINT 0x00000010 | ||
390 | #define STAT_DLERINT 0x00000008 | ||
391 | #define STAT_FEINT 0x00000004 | ||
392 | #define STAT_SEGINT 0x00000002 | ||
393 | #define STAT_REASSINT 0x00000001 | ||
394 | |||
395 | |||
396 | /*--------------- Segmentation control registers -----------------*/ | ||
397 | /* The segmentation registers are 16 bits access and the addresses | ||
398 | are defined as such so the addresses are the actual "offsets" */ | ||
399 | #define IDLEHEADHI 0x00 | ||
400 | #define IDLEHEADLO 0x01 | ||
401 | #define MAXRATE 0x02 | ||
402 | /* Values for MAXRATE register for 155Mbps and 25.6 Mbps operation */ | ||
403 | #define RATE155 0x64b1 // 16 bits float format | ||
404 | #define MAX_ATM_155 352768 // Cells/second p.118 | ||
405 | #define RATE25 0x5f9d | ||
406 | |||
407 | #define STPARMS 0x03 | ||
408 | #define STPARMS_1K 0x008c | ||
409 | #define STPARMS_2K 0x0049 | ||
410 | #define STPARMS_4K 0x0026 | ||
411 | #define COMP_EN 0x4000 | ||
412 | #define CBR_EN 0x2000 | ||
413 | #define ABR_EN 0x0800 | ||
414 | #define UBR_EN 0x0400 | ||
415 | |||
416 | #define ABRUBR_ARB 0x04 | ||
417 | #define RM_TYPE 0x05 | ||
418 | /*Value for RM_TYPE register for ATM Forum Traffic Mangement4.0 support*/ | ||
419 | #define RM_TYPE_4_0 0x0100 | ||
420 | |||
421 | #define SEG_COMMAND_REG 0x17 | ||
422 | /* Values for the command register */ | ||
423 | #define RESET_SEG 0x0055 | ||
424 | #define RESET_SEG_STATE 0x00aa | ||
425 | #define RESET_TX_CELL_CTR 0x00cc | ||
426 | |||
427 | #define CBR_PTR_BASE 0x20 | ||
428 | #define ABR_SBPTR_BASE 0x22 | ||
429 | #define UBR_SBPTR_BASE 0x23 | ||
430 | #define ABRWQ_BASE 0x26 | ||
431 | #define UBRWQ_BASE 0x27 | ||
432 | #define VCT_BASE 0x28 | ||
433 | #define VCTE_BASE 0x29 | ||
434 | #define CBR_TAB_BEG 0x2c | ||
435 | #define CBR_TAB_END 0x2d | ||
436 | #define PRQ_ST_ADR 0x30 | ||
437 | #define PRQ_ED_ADR 0x31 | ||
438 | #define PRQ_RD_PTR 0x32 | ||
439 | #define PRQ_WR_PTR 0x33 | ||
440 | #define TCQ_ST_ADR 0x34 | ||
441 | #define TCQ_ED_ADR 0x35 | ||
442 | #define TCQ_RD_PTR 0x36 | ||
443 | #define TCQ_WR_PTR 0x37 | ||
444 | #define SEG_QUEUE_BASE 0x40 | ||
445 | #define SEG_DESC_BASE 0x41 | ||
446 | #define MODE_REG_0 0x45 | ||
447 | #define T_ONLINE 0x0002 /* (i)chipSAR is online */ | ||
448 | |||
449 | #define MODE_REG_1 0x46 | ||
450 | #define MODE_REG_1_VAL 0x0400 /*for propoer device operation*/ | ||
451 | |||
452 | #define SEG_INTR_STATUS_REG 0x47 | ||
453 | #define SEG_MASK_REG 0x48 | ||
454 | #define TRANSMIT_DONE 0x0200 | ||
455 | #define TCQ_NOT_EMPTY 0x1000 /* this can be used for both the interrupt | ||
456 | status registers as well as the mask register */ | ||
457 | |||
458 | #define CELL_CTR_HIGH_AUTO 0x49 | ||
459 | #define CELL_CTR_HIGH_NOAUTO 0xc9 | ||
460 | #define CELL_CTR_LO_AUTO 0x4a | ||
461 | #define CELL_CTR_LO_NOAUTO 0xca | ||
462 | |||
463 | /* Diagnostic registers */ | ||
464 | #define NEXTDESC 0x59 | ||
465 | #define NEXTVC 0x5a | ||
466 | #define PSLOTCNT 0x5d | ||
467 | #define NEWDN 0x6a | ||
468 | #define NEWVC 0x6b | ||
469 | #define SBPTR 0x6c | ||
470 | #define ABRWQ_WRPTR 0x6f | ||
471 | #define ABRWQ_RDPTR 0x70 | ||
472 | #define UBRWQ_WRPTR 0x71 | ||
473 | #define UBRWQ_RDPTR 0x72 | ||
474 | #define CBR_VC 0x73 | ||
475 | #define ABR_SBVC 0x75 | ||
476 | #define UBR_SBVC 0x76 | ||
477 | #define ABRNEXTLINK 0x78 | ||
478 | #define UBRNEXTLINK 0x79 | ||
479 | |||
480 | |||
481 | /*----------------- Reassembly control registers ---------------------*/ | ||
482 | /* The reassembly registers are 16 bits access and the addresses | ||
483 | are defined as such so the addresses are the actual "offsets" */ | ||
484 | #define MODE_REG 0x00 | ||
485 | #define R_ONLINE 0x0002 /* (i)chip is online */ | ||
486 | #define IGN_RAW_FL 0x0004 | ||
487 | |||
488 | #define PROTOCOL_ID 0x01 | ||
489 | #define REASS_MASK_REG 0x02 | ||
490 | #define REASS_INTR_STATUS_REG 0x03 | ||
491 | /* Interrupt Status register bits */ | ||
492 | #define RX_PKT_CTR_OF 0x8000 | ||
493 | #define RX_ERR_CTR_OF 0x4000 | ||
494 | #define RX_CELL_CTR_OF 0x1000 | ||
495 | #define RX_FREEQ_EMPT 0x0200 | ||
496 | #define RX_EXCPQ_FL 0x0080 | ||
497 | #define RX_RAWQ_FL 0x0010 | ||
498 | #define RX_EXCP_RCVD 0x0008 | ||
499 | #define RX_PKT_RCVD 0x0004 | ||
500 | #define RX_RAW_RCVD 0x0001 | ||
501 | |||
502 | #define DRP_PKT_CNTR 0x04 | ||
503 | #define ERR_CNTR 0x05 | ||
504 | #define RAW_BASE_ADR 0x08 | ||
505 | #define CELL_CTR0 0x0c | ||
506 | #define CELL_CTR1 0x0d | ||
507 | #define REASS_COMMAND_REG 0x0f | ||
508 | /* Values for command register */ | ||
509 | #define RESET_REASS 0x0055 | ||
510 | #define RESET_REASS_STATE 0x00aa | ||
511 | #define RESET_DRP_PKT_CNTR 0x00f1 | ||
512 | #define RESET_ERR_CNTR 0x00f2 | ||
513 | #define RESET_CELL_CNTR 0x00f8 | ||
514 | #define RESET_REASS_ALL_REGS 0x00ff | ||
515 | |||
516 | #define REASS_DESC_BASE 0x10 | ||
517 | #define VC_LKUP_BASE 0x11 | ||
518 | #define REASS_TABLE_BASE 0x12 | ||
519 | #define REASS_QUEUE_BASE 0x13 | ||
520 | #define PKT_TM_CNT 0x16 | ||
521 | #define TMOUT_RANGE 0x17 | ||
522 | #define INTRVL_CNTR 0x18 | ||
523 | #define TMOUT_INDX 0x19 | ||
524 | #define VP_LKUP_BASE 0x1c | ||
525 | #define VP_FILTER 0x1d | ||
526 | #define ABR_LKUP_BASE 0x1e | ||
527 | #define FREEQ_ST_ADR 0x24 | ||
528 | #define FREEQ_ED_ADR 0x25 | ||
529 | #define FREEQ_RD_PTR 0x26 | ||
530 | #define FREEQ_WR_PTR 0x27 | ||
531 | #define PCQ_ST_ADR 0x28 | ||
532 | #define PCQ_ED_ADR 0x29 | ||
533 | #define PCQ_RD_PTR 0x2a | ||
534 | #define PCQ_WR_PTR 0x2b | ||
535 | #define EXCP_Q_ST_ADR 0x2c | ||
536 | #define EXCP_Q_ED_ADR 0x2d | ||
537 | #define EXCP_Q_RD_PTR 0x2e | ||
538 | #define EXCP_Q_WR_PTR 0x2f | ||
539 | #define CC_FIFO_ST_ADR 0x34 | ||
540 | #define CC_FIFO_ED_ADR 0x35 | ||
541 | #define CC_FIFO_RD_PTR 0x36 | ||
542 | #define CC_FIFO_WR_PTR 0x37 | ||
543 | #define STATE_REG 0x38 | ||
544 | #define BUF_SIZE 0x42 | ||
545 | #define XTRA_RM_OFFSET 0x44 | ||
546 | #define DRP_PKT_CNTR_NC 0x84 | ||
547 | #define ERR_CNTR_NC 0x85 | ||
548 | #define CELL_CNTR0_NC 0x8c | ||
549 | #define CELL_CNTR1_NC 0x8d | ||
550 | |||
551 | /* State Register bits */ | ||
552 | #define EXCPQ_EMPTY 0x0040 | ||
553 | #define PCQ_EMPTY 0x0010 | ||
554 | #define FREEQ_EMPTY 0x0004 | ||
555 | |||
556 | |||
557 | /*----------------- Front End registers/ DMA control --------------*/ | ||
558 | /* There is a lot of documentation error regarding these offsets ??? | ||
559 | eg:- 2 offsets given 800, a00 for rx counter | ||
560 | similarly many others | ||
561 | Remember again that the offsets are to be 4*register number, so | ||
562 | correct the #defines here | ||
563 | */ | ||
564 | #define IPHASE5575_TX_COUNTER 0x200 /* offset - 0x800 */ | ||
565 | #define IPHASE5575_RX_COUNTER 0x280 /* offset - 0xa00 */ | ||
566 | #define IPHASE5575_TX_LIST_ADDR 0x300 /* offset - 0xc00 */ | ||
567 | #define IPHASE5575_RX_LIST_ADDR 0x380 /* offset - 0xe00 */ | ||
568 | |||
569 | /*--------------------------- RAM ---------------------------*/ | ||
570 | /* These memory maps are actually offsets from the segmentation and reassembly RAM base addresses */ | ||
571 | |||
572 | /* Segmentation Control Memory map */ | ||
573 | #define TX_DESC_BASE 0x0000 /* Buffer Decriptor Table */ | ||
574 | #define TX_COMP_Q 0x1000 /* Transmit Complete Queue */ | ||
575 | #define PKT_RDY_Q 0x1400 /* Packet Ready Queue */ | ||
576 | #define CBR_SCHED_TABLE 0x1800 /* CBR Table */ | ||
577 | #define UBR_SCHED_TABLE 0x3000 /* UBR Table */ | ||
578 | #define UBR_WAIT_Q 0x4000 /* UBR Wait Queue */ | ||
579 | #define ABR_SCHED_TABLE 0x5000 /* ABR Table */ | ||
580 | #define ABR_WAIT_Q 0x5800 /* ABR Wait Queue */ | ||
581 | #define EXT_VC_TABLE 0x6000 /* Extended VC Table */ | ||
582 | #define MAIN_VC_TABLE 0x8000 /* Main VC Table */ | ||
583 | #define SCHEDSZ 1024 /* ABR and UBR Scheduling Table size */ | ||
584 | #define TX_DESC_TABLE_SZ 128 /* Number of entries in the Transmit | ||
585 | Buffer Descriptor Table */ | ||
586 | |||
587 | /* These are used as table offsets in Descriptor Table address generation */ | ||
588 | #define DESC_MODE 0x0 | ||
589 | #define VC_INDEX 0x1 | ||
590 | #define BYTE_CNT 0x3 | ||
591 | #define PKT_START_HI 0x4 | ||
592 | #define PKT_START_LO 0x5 | ||
593 | |||
594 | /* Descriptor Mode Word Bits */ | ||
595 | #define EOM_EN 0x0800 | ||
596 | #define AAL5 0x0100 | ||
597 | #define APP_CRC32 0x0400 | ||
598 | #define CMPL_INT 0x1000 | ||
599 | |||
600 | #define TABLE_ADDRESS(db, dn, to) \ | ||
601 | (((unsigned long)(db & 0x04)) << 16) | (dn << 5) | (to << 1) | ||
602 | |||
603 | /* Reassembly Control Memory Map */ | ||
604 | #define RX_DESC_BASE 0x0000 /* Buffer Descriptor Table */ | ||
605 | #define VP_TABLE 0x5c00 /* VP Table */ | ||
606 | #define EXCEPTION_Q 0x5e00 /* Exception Queue */ | ||
607 | #define FREE_BUF_DESC_Q 0x6000 /* Free Buffer Descriptor Queue */ | ||
608 | #define PKT_COMP_Q 0x6800 /* Packet Complete Queue */ | ||
609 | #define REASS_TABLE 0x7000 /* Reassembly Table */ | ||
610 | #define RX_VC_TABLE 0x7800 /* VC Table */ | ||
611 | #define ABR_VC_TABLE 0x8000 /* ABR VC Table */ | ||
612 | #define RX_DESC_TABLE_SZ 736 /* Number of entries in the Receive | ||
613 | Buffer Descriptor Table */ | ||
614 | #define VP_TABLE_SZ 256 /* Number of entries in VPTable */ | ||
615 | #define RX_VC_TABLE_SZ 1024 /* Number of entries in VC Table */ | ||
616 | #define REASS_TABLE_SZ 1024 /* Number of entries in Reassembly Table */ | ||
617 | /* Buffer Descriptor Table */ | ||
618 | #define RX_ACT 0x8000 | ||
619 | #define RX_VPVC 0x4000 | ||
620 | #define RX_CNG 0x0040 | ||
621 | #define RX_CER 0x0008 | ||
622 | #define RX_PTE 0x0004 | ||
623 | #define RX_OFL 0x0002 | ||
624 | #define NUM_RX_EXCP 32 | ||
625 | |||
626 | /* Reassembly Table */ | ||
627 | #define NO_AAL5_PKT 0x0000 | ||
628 | #define AAL5_PKT_REASSEMBLED 0x4000 | ||
629 | #define AAL5_PKT_TERMINATED 0x8000 | ||
630 | #define RAW_PKT 0xc000 | ||
631 | #define REASS_ABR 0x2000 | ||
632 | |||
633 | /*-------------------- Base Registers --------------------*/ | ||
634 | #define REG_BASE IPHASE5575_BUS_CONTROL_REG_BASE | ||
635 | #define RAM_BASE IPHASE5575_FRAG_CONTROL_RAM_BASE | ||
636 | #define PHY_BASE IPHASE5575_FRONT_END_REG_BASE | ||
637 | #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE | ||
638 | #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE | ||
639 | |||
640 | typedef volatile u_int freg_t; | ||
641 | typedef u_int rreg_t; | ||
642 | |||
643 | typedef struct _ffredn_t { | ||
644 | freg_t idlehead_high; /* Idle cell header (high) */ | ||
645 | freg_t idlehead_low; /* Idle cell header (low) */ | ||
646 | freg_t maxrate; /* Maximum rate */ | ||
647 | freg_t stparms; /* Traffic Management Parameters */ | ||
648 | freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ | ||
649 | freg_t rm_type; /* */ | ||
650 | u_int filler5[0x17 - 0x06]; | ||
651 | freg_t cmd_reg; /* Command register */ | ||
652 | u_int filler18[0x20 - 0x18]; | ||
653 | freg_t cbr_base; /* CBR Pointer Base */ | ||
654 | freg_t vbr_base; /* VBR Pointer Base */ | ||
655 | freg_t abr_base; /* ABR Pointer Base */ | ||
656 | freg_t ubr_base; /* UBR Pointer Base */ | ||
657 | u_int filler24; | ||
658 | freg_t vbrwq_base; /* VBR Wait Queue Base */ | ||
659 | freg_t abrwq_base; /* ABR Wait Queue Base */ | ||
660 | freg_t ubrwq_base; /* UBR Wait Queue Base */ | ||
661 | freg_t vct_base; /* Main VC Table Base */ | ||
662 | freg_t vcte_base; /* Extended Main VC Table Base */ | ||
663 | u_int filler2a[0x2C - 0x2A]; | ||
664 | freg_t cbr_tab_beg; /* CBR Table Begin */ | ||
665 | freg_t cbr_tab_end; /* CBR Table End */ | ||
666 | freg_t cbr_pointer; /* CBR Pointer */ | ||
667 | u_int filler2f[0x30 - 0x2F]; | ||
668 | freg_t prq_st_adr; /* Packet Ready Queue Start Address */ | ||
669 | freg_t prq_ed_adr; /* Packet Ready Queue End Address */ | ||
670 | freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ | ||
671 | freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ | ||
672 | freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ | ||
673 | freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ | ||
674 | freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ | ||
675 | freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ | ||
676 | u_int filler38[0x40 - 0x38]; | ||
677 | freg_t queue_base; /* Base address for PRQ and TCQ */ | ||
678 | freg_t desc_base; /* Base address of descriptor table */ | ||
679 | u_int filler42[0x45 - 0x42]; | ||
680 | freg_t mode_reg_0; /* Mode register 0 */ | ||
681 | freg_t mode_reg_1; /* Mode register 1 */ | ||
682 | freg_t intr_status_reg;/* Interrupt Status register */ | ||
683 | freg_t mask_reg; /* Mask Register */ | ||
684 | freg_t cell_ctr_high1; /* Total cell transfer count (high) */ | ||
685 | freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ | ||
686 | freg_t state_reg; /* Status register */ | ||
687 | u_int filler4c[0x58 - 0x4c]; | ||
688 | freg_t curr_desc_num; /* Contains the current descriptor num */ | ||
689 | freg_t next_desc; /* Next descriptor */ | ||
690 | freg_t next_vc; /* Next VC */ | ||
691 | u_int filler5b[0x5d - 0x5b]; | ||
692 | freg_t present_slot_cnt;/* Present slot count */ | ||
693 | u_int filler5e[0x6a - 0x5e]; | ||
694 | freg_t new_desc_num; /* New descriptor number */ | ||
695 | freg_t new_vc; /* New VC */ | ||
696 | freg_t sched_tbl_ptr; /* Schedule table pointer */ | ||
697 | freg_t vbrwq_wptr; /* VBR wait queue write pointer */ | ||
698 | freg_t vbrwq_rptr; /* VBR wait queue read pointer */ | ||
699 | freg_t abrwq_wptr; /* ABR wait queue write pointer */ | ||
700 | freg_t abrwq_rptr; /* ABR wait queue read pointer */ | ||
701 | freg_t ubrwq_wptr; /* UBR wait queue write pointer */ | ||
702 | freg_t ubrwq_rptr; /* UBR wait queue read pointer */ | ||
703 | freg_t cbr_vc; /* CBR VC */ | ||
704 | freg_t vbr_sb_vc; /* VBR SB VC */ | ||
705 | freg_t abr_sb_vc; /* ABR SB VC */ | ||
706 | freg_t ubr_sb_vc; /* UBR SB VC */ | ||
707 | freg_t vbr_next_link; /* VBR next link */ | ||
708 | freg_t abr_next_link; /* ABR next link */ | ||
709 | freg_t ubr_next_link; /* UBR next link */ | ||
710 | u_int filler7a[0x7c-0x7a]; | ||
711 | freg_t out_rate_head; /* Out of rate head */ | ||
712 | u_int filler7d[0xca-0x7d]; /* pad out to full address space */ | ||
713 | freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ | ||
714 | freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ | ||
715 | u_int fillercc[0x100-0xcc]; /* pad out to full address space */ | ||
716 | } ffredn_t; | ||
717 | |||
718 | typedef struct _rfredn_t { | ||
719 | rreg_t mode_reg_0; /* Mode register 0 */ | ||
720 | rreg_t protocol_id; /* Protocol ID */ | ||
721 | rreg_t mask_reg; /* Mask Register */ | ||
722 | rreg_t intr_status_reg;/* Interrupt status register */ | ||
723 | rreg_t drp_pkt_cntr; /* Dropped packet cntr (clear on read) */ | ||
724 | rreg_t err_cntr; /* Error Counter (cleared on read) */ | ||
725 | u_int filler6[0x08 - 0x06]; | ||
726 | rreg_t raw_base_adr; /* Base addr for raw cell Q */ | ||
727 | u_int filler2[0x0c - 0x09]; | ||
728 | rreg_t cell_ctr0; /* Cell Counter 0 (cleared when read) */ | ||
729 | rreg_t cell_ctr1; /* Cell Counter 1 (cleared when read) */ | ||
730 | u_int filler3[0x0f - 0x0e]; | ||
731 | rreg_t cmd_reg; /* Command register */ | ||
732 | rreg_t desc_base; /* Base address for description table */ | ||
733 | rreg_t vc_lkup_base; /* Base address for VC lookup table */ | ||
734 | rreg_t reass_base; /* Base address for reassembler table */ | ||
735 | rreg_t queue_base; /* Base address for Communication queue */ | ||
736 | u_int filler14[0x16 - 0x14]; | ||
737 | rreg_t pkt_tm_cnt; /* Packet Timeout and count register */ | ||
738 | rreg_t tmout_range; /* Range of reassembley IDs for timeout */ | ||
739 | rreg_t intrvl_cntr; /* Packet aging interval counter */ | ||
740 | rreg_t tmout_indx; /* index of pkt being tested for aging */ | ||
741 | u_int filler1a[0x1c - 0x1a]; | ||
742 | rreg_t vp_lkup_base; /* Base address for VP lookup table */ | ||
743 | rreg_t vp_filter; /* VP filter register */ | ||
744 | rreg_t abr_lkup_base; /* Base address of ABR VC Table */ | ||
745 | u_int filler1f[0x24 - 0x1f]; | ||
746 | rreg_t fdq_st_adr; /* Free desc queue start address */ | ||
747 | rreg_t fdq_ed_adr; /* Free desc queue end address */ | ||
748 | rreg_t fdq_rd_ptr; /* Free desc queue read pointer */ | ||
749 | rreg_t fdq_wr_ptr; /* Free desc queue write pointer */ | ||
750 | rreg_t pcq_st_adr; /* Packet Complete queue start address */ | ||
751 | rreg_t pcq_ed_adr; /* Packet Complete queue end address */ | ||
752 | rreg_t pcq_rd_ptr; /* Packet Complete queue read pointer */ | ||
753 | rreg_t pcq_wr_ptr; /* Packet Complete queue write pointer */ | ||
754 | rreg_t excp_st_adr; /* Exception queue start address */ | ||
755 | rreg_t excp_ed_adr; /* Exception queue end address */ | ||
756 | rreg_t excp_rd_ptr; /* Exception queue read pointer */ | ||
757 | rreg_t excp_wr_ptr; /* Exception queue write pointer */ | ||
758 | u_int filler30[0x34 - 0x30]; | ||
759 | rreg_t raw_st_adr; /* Raw Cell start address */ | ||
760 | rreg_t raw_ed_adr; /* Raw Cell end address */ | ||
761 | rreg_t raw_rd_ptr; /* Raw Cell read pointer */ | ||
762 | rreg_t raw_wr_ptr; /* Raw Cell write pointer */ | ||
763 | rreg_t state_reg; /* State Register */ | ||
764 | u_int filler39[0x42 - 0x39]; | ||
765 | rreg_t buf_size; /* Buffer size */ | ||
766 | u_int filler43; | ||
767 | rreg_t xtra_rm_offset; /* Offset of the additional turnaround RM */ | ||
768 | u_int filler45[0x84 - 0x45]; | ||
769 | rreg_t drp_pkt_cntr_nc;/* Dropped Packet cntr, Not clear on rd */ | ||
770 | rreg_t err_cntr_nc; /* Error Counter, Not clear on read */ | ||
771 | u_int filler86[0x8c - 0x86]; | ||
772 | rreg_t cell_ctr0_nc; /* Cell Counter 0, Not clear on read */ | ||
773 | rreg_t cell_ctr1_nc; /* Cell Counter 1, Not clear on read */ | ||
774 | u_int filler8e[0x100-0x8e]; /* pad out to full address space */ | ||
775 | } rfredn_t; | ||
776 | |||
777 | typedef struct { | ||
778 | /* Atlantic */ | ||
779 | ffredn_t ffredn; /* F FRED */ | ||
780 | rfredn_t rfredn; /* R FRED */ | ||
781 | } ia_regs_t; | ||
782 | |||
783 | typedef struct { | ||
784 | u_short f_vc_type; /* VC type */ | ||
785 | u_short f_nrm; /* Nrm */ | ||
786 | u_short f_nrmexp; /* Nrm Exp */ | ||
787 | u_short reserved6; /* */ | ||
788 | u_short f_crm; /* Crm */ | ||
789 | u_short reserved10; /* Reserved */ | ||
790 | u_short reserved12; /* Reserved */ | ||
791 | u_short reserved14; /* Reserved */ | ||
792 | u_short last_cell_slot; /* last_cell_slot_count */ | ||
793 | u_short f_pcr; /* Peak Cell Rate */ | ||
794 | u_short fraction; /* fraction */ | ||
795 | u_short f_icr; /* Initial Cell Rate */ | ||
796 | u_short f_cdf; /* */ | ||
797 | u_short f_mcr; /* Minimum Cell Rate */ | ||
798 | u_short f_acr; /* Allowed Cell Rate */ | ||
799 | u_short f_status; /* */ | ||
800 | } f_vc_abr_entry; | ||
801 | |||
802 | typedef struct { | ||
803 | u_short r_status_rdf; /* status + RDF */ | ||
804 | u_short r_air; /* AIR */ | ||
805 | u_short reserved4[14]; /* Reserved */ | ||
806 | } r_vc_abr_entry; | ||
807 | |||
808 | #define MRM 3 | ||
809 | |||
810 | typedef struct srv_cls_param { | ||
811 | u32 class_type; /* CBR/VBR/ABR/UBR; use the enum above */ | ||
812 | u32 pcr; /* Peak Cell Rate (24-bit) */ | ||
813 | /* VBR parameters */ | ||
814 | u32 scr; /* sustainable cell rate */ | ||
815 | u32 max_burst_size; /* ?? cell rate or data rate */ | ||
816 | |||
817 | /* ABR only UNI 4.0 Parameters */ | ||
818 | u32 mcr; /* Min Cell Rate (24-bit) */ | ||
819 | u32 icr; /* Initial Cell Rate (24-bit) */ | ||
820 | u32 tbe; /* Transient Buffer Exposure (24-bit) */ | ||
821 | u32 frtt; /* Fixed Round Trip Time (24-bit) */ | ||
822 | |||
823 | #if 0 /* Additional Parameters of TM 4.0 */ | ||
824 | bits 31 30 29 28 27-25 24-22 21-19 18-9 | ||
825 | ----------------------------------------------------------------------------- | ||
826 | | NRM present | TRM prsnt | CDF prsnt | ADTF prsnt | NRM | TRM | CDF | ADTF | | ||
827 | ----------------------------------------------------------------------------- | ||
828 | #endif /* 0 */ | ||
829 | |||
830 | u8 nrm; /* Max # of Cells for each forward RM | ||
831 | cell (3-bit) */ | ||
832 | u8 trm; /* Time between forward RM cells (3-bit) */ | ||
833 | u16 adtf; /* ACR Decrease Time Factor (10-bit) */ | ||
834 | u8 cdf; /* Cutoff Decrease Factor (3-bit) */ | ||
835 | u8 rif; /* Rate Increment Factor (4-bit) */ | ||
836 | u8 rdf; /* Rate Decrease Factor (4-bit) */ | ||
837 | u8 reserved; /* 8 bits to keep structure word aligned */ | ||
838 | } srv_cls_param_t; | ||
839 | |||
840 | struct testTable_t { | ||
841 | u16 lastTime; | ||
842 | u16 fract; | ||
843 | u8 vc_status; | ||
844 | }; | ||
845 | |||
846 | typedef struct { | ||
847 | u16 vci; | ||
848 | u16 error; | ||
849 | } RX_ERROR_Q; | ||
850 | |||
851 | typedef struct { | ||
852 | u8 active: 1; | ||
853 | u8 abr: 1; | ||
854 | u8 ubr: 1; | ||
855 | u8 cnt: 5; | ||
856 | #define VC_ACTIVE 0x01 | ||
857 | #define VC_ABR 0x02 | ||
858 | #define VC_UBR 0x04 | ||
859 | } vcstatus_t; | ||
860 | |||
861 | struct ia_rfL_t { | ||
862 | u32 fdq_st; /* Free desc queue start address */ | ||
863 | u32 fdq_ed; /* Free desc queue end address */ | ||
864 | u32 fdq_rd; /* Free desc queue read pointer */ | ||
865 | u32 fdq_wr; /* Free desc queue write pointer */ | ||
866 | u32 pcq_st; /* Packet Complete queue start address */ | ||
867 | u32 pcq_ed; /* Packet Complete queue end address */ | ||
868 | u32 pcq_rd; /* Packet Complete queue read pointer */ | ||
869 | u32 pcq_wr; /* Packet Complete queue write pointer */ | ||
870 | }; | ||
871 | |||
872 | struct ia_ffL_t { | ||
873 | u32 prq_st; /* Packet Ready Queue Start Address */ | ||
874 | u32 prq_ed; /* Packet Ready Queue End Address */ | ||
875 | u32 prq_wr; /* Packet Ready Queue write pointer */ | ||
876 | u32 tcq_st; /* Transmit Complete Queue Start Address*/ | ||
877 | u32 tcq_ed; /* Transmit Complete Queue End Address */ | ||
878 | u32 tcq_rd; /* Transmit Complete Queue read pointer */ | ||
879 | }; | ||
880 | |||
881 | struct desc_tbl_t { | ||
882 | u32 timestamp; | ||
883 | struct ia_vcc *iavcc; | ||
884 | struct sk_buff *txskb; | ||
885 | }; | ||
886 | |||
887 | typedef struct ia_rtn_q { | ||
888 | struct desc_tbl_t data; | ||
889 | struct ia_rtn_q *next, *tail; | ||
890 | } IARTN_Q; | ||
891 | |||
892 | #define SUNI_LOSV 0x04 | ||
893 | typedef struct { | ||
894 | u32 suni_master_reset; /* SUNI Master Reset and Identity */ | ||
895 | u32 suni_master_config; /* SUNI Master Configuration */ | ||
896 | u32 suni_master_intr_stat; /* SUNI Master Interrupt Status */ | ||
897 | u32 suni_reserved1; /* Reserved */ | ||
898 | u32 suni_master_clk_monitor;/* SUNI Master Clock Monitor */ | ||
899 | u32 suni_master_control; /* SUNI Master Clock Monitor */ | ||
900 | u32 suni_reserved2[10]; /* Reserved */ | ||
901 | |||
902 | u32 suni_rsop_control; /* RSOP Control/Interrupt Enable */ | ||
903 | u32 suni_rsop_status; /* RSOP Status/Interrupt States */ | ||
904 | u32 suni_rsop_section_bip8l;/* RSOP Section BIP-8 LSB */ | ||
905 | u32 suni_rsop_section_bip8m;/* RSOP Section BIP-8 MSB */ | ||
906 | |||
907 | u32 suni_tsop_control; /* TSOP Control */ | ||
908 | u32 suni_tsop_diag; /* TSOP Disgnostics */ | ||
909 | u32 suni_tsop_reserved[2]; /* TSOP Reserved */ | ||
910 | |||
911 | u32 suni_rlop_cs; /* RLOP Control/Status */ | ||
912 | u32 suni_rlop_intr; /* RLOP Interrupt Enable/Status */ | ||
913 | u32 suni_rlop_line_bip24l; /* RLOP Line BIP-24 LSB */ | ||
914 | u32 suni_rlop_line_bip24; /* RLOP Line BIP-24 */ | ||
915 | u32 suni_rlop_line_bip24m; /* RLOP Line BIP-24 MSB */ | ||
916 | u32 suni_rlop_line_febel; /* RLOP Line FEBE LSB */ | ||
917 | u32 suni_rlop_line_febe; /* RLOP Line FEBE */ | ||
918 | u32 suni_rlop_line_febem; /* RLOP Line FEBE MSB */ | ||
919 | |||
920 | u32 suni_tlop_control; /* TLOP Control */ | ||
921 | u32 suni_tlop_disg; /* TLOP Disgnostics */ | ||
922 | u32 suni_tlop_reserved[14]; /* TLOP Reserved */ | ||
923 | |||
924 | u32 suni_rpop_cs; /* RPOP Status/Control */ | ||
925 | u32 suni_rpop_intr; /* RPOP Interrupt/Status */ | ||
926 | u32 suni_rpop_reserved; /* RPOP Reserved */ | ||
927 | u32 suni_rpop_intr_ena; /* RPOP Interrupt Enable */ | ||
928 | u32 suni_rpop_reserved1[3]; /* RPOP Reserved */ | ||
929 | u32 suni_rpop_path_sig; /* RPOP Path Signal Label */ | ||
930 | u32 suni_rpop_bip8l; /* RPOP Path BIP-8 LSB */ | ||
931 | u32 suni_rpop_bip8m; /* RPOP Path BIP-8 MSB */ | ||
932 | u32 suni_rpop_febel; /* RPOP Path FEBE LSB */ | ||
933 | u32 suni_rpop_febem; /* RPOP Path FEBE MSB */ | ||
934 | u32 suni_rpop_reserved2[4]; /* RPOP Reserved */ | ||
935 | |||
936 | u32 suni_tpop_cntrl_daig; /* TPOP Control/Disgnostics */ | ||
937 | u32 suni_tpop_pointer_ctrl; /* TPOP Pointer Control */ | ||
938 | u32 suni_tpop_sourcer_ctrl; /* TPOP Source Control */ | ||
939 | u32 suni_tpop_reserved1[2]; /* TPOP Reserved */ | ||
940 | u32 suni_tpop_arb_prtl; /* TPOP Arbitrary Pointer LSB */ | ||
941 | u32 suni_tpop_arb_prtm; /* TPOP Arbitrary Pointer MSB */ | ||
942 | u32 suni_tpop_reserved2; /* TPOP Reserved */ | ||
943 | u32 suni_tpop_path_sig; /* TPOP Path Signal Lable */ | ||
944 | u32 suni_tpop_path_status; /* TPOP Path Status */ | ||
945 | u32 suni_tpop_reserved3[6]; /* TPOP Reserved */ | ||
946 | |||
947 | u32 suni_racp_cs; /* RACP Control/Status */ | ||
948 | u32 suni_racp_intr; /* RACP Interrupt Enable/Status */ | ||
949 | u32 suni_racp_hdr_pattern; /* RACP Match Header Pattern */ | ||
950 | u32 suni_racp_hdr_mask; /* RACP Match Header Mask */ | ||
951 | u32 suni_racp_corr_hcs; /* RACP Correctable HCS Error Count */ | ||
952 | u32 suni_racp_uncorr_hcs; /* RACP Uncorrectable HCS Error Count */ | ||
953 | u32 suni_racp_reserved[10]; /* RACP Reserved */ | ||
954 | |||
955 | u32 suni_tacp_control; /* TACP Control */ | ||
956 | u32 suni_tacp_idle_hdr_pat; /* TACP Idle Cell Header Pattern */ | ||
957 | u32 suni_tacp_idle_pay_pay; /* TACP Idle Cell Payld Octet Pattern */ | ||
958 | u32 suni_tacp_reserved[5]; /* TACP Reserved */ | ||
959 | |||
960 | u32 suni_reserved3[24]; /* Reserved */ | ||
961 | |||
962 | u32 suni_master_test; /* SUNI Master Test */ | ||
963 | u32 suni_reserved_test; /* SUNI Reserved for Test */ | ||
964 | } IA_SUNI; | ||
965 | |||
966 | |||
967 | typedef struct _SUNI_STATS_ | ||
968 | { | ||
969 | u32 valid; // 1 = oc3 PHY card | ||
970 | u32 carrier_detect; // GPIN input | ||
971 | // RSOP: receive section overhead processor | ||
972 | u16 rsop_oof_state; // 1 = out of frame | ||
973 | u16 rsop_lof_state; // 1 = loss of frame | ||
974 | u16 rsop_los_state; // 1 = loss of signal | ||
975 | u32 rsop_los_count; // loss of signal count | ||
976 | u32 rsop_bse_count; // section BIP-8 error count | ||
977 | // RLOP: receive line overhead processor | ||
978 | u16 rlop_ferf_state; // 1 = far end receive failure | ||
979 | u16 rlop_lais_state; // 1 = line AIS | ||
980 | u32 rlop_lbe_count; // BIP-24 count | ||
981 | u32 rlop_febe_count; // FEBE count; | ||
982 | // RPOP: receive path overhead processor | ||
983 | u16 rpop_lop_state; // 1 = LOP | ||
984 | u16 rpop_pais_state; // 1 = path AIS | ||
985 | u16 rpop_pyel_state; // 1 = path yellow alert | ||
986 | u32 rpop_bip_count; // path BIP-8 error count | ||
987 | u32 rpop_febe_count; // path FEBE error count | ||
988 | u16 rpop_psig; // path signal label value | ||
989 | // RACP: receive ATM cell processor | ||
990 | u16 racp_hp_state; // hunt/presync state | ||
991 | u32 racp_fu_count; // FIFO underrun count | ||
992 | u32 racp_fo_count; // FIFO overrun count | ||
993 | u32 racp_chcs_count; // correctable HCS error count | ||
994 | u32 racp_uchcs_count; // uncorrectable HCS error count | ||
995 | } IA_SUNI_STATS; | ||
996 | |||
997 | typedef struct iadev_t { | ||
998 | /*-----base pointers into (i)chipSAR+ address space */ | ||
999 | u32 __iomem *phy; /* base pointer into phy(SUNI) */ | ||
1000 | u32 __iomem *dma; /* base pointer into DMA control | ||
1001 | registers */ | ||
1002 | u32 __iomem *reg; /* base pointer to SAR registers | ||
1003 | - Bus Interface Control Regs */ | ||
1004 | u32 __iomem *seg_reg; /* base pointer to segmentation engine | ||
1005 | internal registers */ | ||
1006 | u32 __iomem *reass_reg; /* base pointer to reassemble engine | ||
1007 | internal registers */ | ||
1008 | u32 __iomem *ram; /* base pointer to SAR RAM */ | ||
1009 | void __iomem *seg_ram; | ||
1010 | void __iomem *reass_ram; | ||
1011 | struct dle_q tx_dle_q; | ||
1012 | struct free_desc_q *tx_free_desc_qhead; | ||
1013 | struct sk_buff_head tx_dma_q, tx_backlog; | ||
1014 | spinlock_t tx_lock; | ||
1015 | IARTN_Q tx_return_q; | ||
1016 | u32 close_pending; | ||
1017 | wait_queue_head_t close_wait; | ||
1018 | wait_queue_head_t timeout_wait; | ||
1019 | struct cpcs_trailer_desc *tx_buf; | ||
1020 | u16 num_tx_desc, tx_buf_sz, rate_limit; | ||
1021 | u32 tx_cell_cnt, tx_pkt_cnt; | ||
1022 | void __iomem *MAIN_VC_TABLE_ADDR, *EXT_VC_TABLE_ADDR, *ABR_SCHED_TABLE_ADDR; | ||
1023 | struct dle_q rx_dle_q; | ||
1024 | struct free_desc_q *rx_free_desc_qhead; | ||
1025 | struct sk_buff_head rx_dma_q; | ||
1026 | spinlock_t rx_lock, misc_lock; | ||
1027 | struct atm_vcc **rx_open; /* list of all open VCs */ | ||
1028 | u16 num_rx_desc, rx_buf_sz, rxing; | ||
1029 | u32 rx_pkt_ram, rx_tmp_cnt, rx_tmp_jif; | ||
1030 | void __iomem *RX_DESC_BASE_ADDR; | ||
1031 | u32 drop_rxpkt, drop_rxcell, rx_cell_cnt, rx_pkt_cnt; | ||
1032 | struct atm_dev *next_board; /* other iphase devices */ | ||
1033 | struct pci_dev *pci; | ||
1034 | int mem; | ||
1035 | unsigned int real_base; /* real and virtual base address */ | ||
1036 | void __iomem *base; | ||
1037 | unsigned int pci_map_size; /*pci map size of board */ | ||
1038 | unsigned char irq; | ||
1039 | unsigned char bus; | ||
1040 | unsigned char dev_fn; | ||
1041 | u_short phy_type; | ||
1042 | u_short num_vc, memSize, memType; | ||
1043 | struct ia_ffL_t ffL; | ||
1044 | struct ia_rfL_t rfL; | ||
1045 | /* Suni stat */ | ||
1046 | // IA_SUNI_STATS suni_stats; | ||
1047 | unsigned char carrier_detect; | ||
1048 | /* CBR related */ | ||
1049 | // transmit DMA & Receive | ||
1050 | unsigned int tx_dma_cnt; // number of elements on dma queue | ||
1051 | unsigned int rx_dma_cnt; // number of elements on rx dma queue | ||
1052 | unsigned int NumEnabledCBR; // number of CBR VCI's enabled. CBR | ||
1053 | // receive MARK for Cell FIFO | ||
1054 | unsigned int rx_mark_cnt; // number of elements on mark queue | ||
1055 | unsigned int CbrTotEntries; // Total CBR Entries in Scheduling Table. | ||
1056 | unsigned int CbrRemEntries; // Remaining CBR Entries in Scheduling Table. | ||
1057 | unsigned int CbrEntryPt; // CBR Sched Table Entry Point. | ||
1058 | unsigned int Granularity; // CBR Granularity given Table Size. | ||
1059 | /* ABR related */ | ||
1060 | unsigned int sum_mcr, sum_cbr, LineRate; | ||
1061 | unsigned int n_abr; | ||
1062 | struct desc_tbl_t *desc_tbl; | ||
1063 | u_short host_tcq_wr; | ||
1064 | struct testTable_t **testTable; | ||
1065 | dma_addr_t tx_dle_dma; | ||
1066 | dma_addr_t rx_dle_dma; | ||
1067 | } IADEV; | ||
1068 | |||
1069 | |||
1070 | #define INPH_IA_DEV(d) ((IADEV *) (d)->dev_data) | ||
1071 | #define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data) | ||
1072 | |||
1073 | /******************* IDT77105 25MB/s PHY DEFINE *****************************/ | ||
1074 | typedef struct { | ||
1075 | u_int mb25_master_ctrl; /* Master control */ | ||
1076 | u_int mb25_intr_status; /* Interrupt status */ | ||
1077 | u_int mb25_diag_control; /* Diagnostic control */ | ||
1078 | u_int mb25_led_hec; /* LED driver and HEC status/control */ | ||
1079 | u_int mb25_low_byte_counter; /* Low byte counter */ | ||
1080 | u_int mb25_high_byte_counter; /* High byte counter */ | ||
1081 | } ia_mb25_t; | ||
1082 | |||
1083 | /* | ||
1084 | * Master Control | ||
1085 | */ | ||
1086 | #define MB25_MC_UPLO 0x80 /* UPLO */ | ||
1087 | #define MB25_MC_DREC 0x40 /* Discard receive cell errors */ | ||
1088 | #define MB25_MC_ECEIO 0x20 /* Enable Cell Error Interrupts Only */ | ||
1089 | #define MB25_MC_TDPC 0x10 /* Transmit data parity check */ | ||
1090 | #define MB25_MC_DRIC 0x08 /* Discard receive idle cells */ | ||
1091 | #define MB25_MC_HALTTX 0x04 /* Halt Tx */ | ||
1092 | #define MB25_MC_UMS 0x02 /* UTOPIA mode select */ | ||
1093 | #define MB25_MC_ENABLED 0x01 /* Enable interrupt */ | ||
1094 | |||
1095 | /* | ||
1096 | * Interrupt Status | ||
1097 | */ | ||
1098 | #define MB25_IS_GSB 0x40 /* GOOD Symbol Bit */ | ||
1099 | #define MB25_IS_HECECR 0x20 /* HEC error cell received */ | ||
1100 | #define MB25_IS_SCR 0x10 /* "Short Cell" Received */ | ||
1101 | #define MB25_IS_TPE 0x08 /* Trnamsit Parity Error */ | ||
1102 | #define MB25_IS_RSCC 0x04 /* Receive Signal Condition change */ | ||
1103 | #define MB25_IS_RCSE 0x02 /* Received Cell Symbol Error */ | ||
1104 | #define MB25_IS_RFIFOO 0x01 /* Received FIFO Overrun */ | ||
1105 | |||
1106 | /* | ||
1107 | * Diagnostic Control | ||
1108 | */ | ||
1109 | #define MB25_DC_FTXCD 0x80 /* Force TxClav deassert */ | ||
1110 | #define MB25_DC_RXCOS 0x40 /* RxClav operation select */ | ||
1111 | #define MB25_DC_ECEIO 0x20 /* Single/Multi-PHY config select */ | ||
1112 | #define MB25_DC_RLFLUSH 0x10 /* Clear receive FIFO */ | ||
1113 | #define MB25_DC_IXPE 0x08 /* Insert xmit payload error */ | ||
1114 | #define MB25_DC_IXHECE 0x04 /* Insert Xmit HEC Error */ | ||
1115 | #define MB25_DC_LB_MASK 0x03 /* Loopback control mask */ | ||
1116 | |||
1117 | #define MB25_DC_LL 0x03 /* Line Loopback */ | ||
1118 | #define MB25_DC_PL 0x02 /* PHY Loopback */ | ||
1119 | #define MB25_DC_NM 0x00 | ||
1120 | |||
1121 | #define FE_MASK 0x00F0 | ||
1122 | #define FE_MULTI_MODE 0x0000 | ||
1123 | #define FE_SINGLE_MODE 0x0010 | ||
1124 | #define FE_UTP_OPTION 0x0020 | ||
1125 | #define FE_25MBIT_PHY 0x0040 | ||
1126 | #define FE_DS3_PHY 0x0080 /* DS3 */ | ||
1127 | #define FE_E3_PHY 0x0090 /* E3 */ | ||
1128 | |||
1129 | /*********************** SUNI_PM7345 PHY DEFINE HERE *********************/ | ||
1130 | typedef struct _suni_pm7345_t | ||
1131 | { | ||
1132 | u_int suni_config; /* SUNI Configuration */ | ||
1133 | u_int suni_intr_enbl; /* SUNI Interrupt Enable */ | ||
1134 | u_int suni_intr_stat; /* SUNI Interrupt Status */ | ||
1135 | u_int suni_control; /* SUNI Control */ | ||
1136 | u_int suni_id_reset; /* SUNI Reset and Identity */ | ||
1137 | u_int suni_data_link_ctrl; | ||
1138 | u_int suni_rboc_conf_intr_enbl; | ||
1139 | u_int suni_rboc_stat; | ||
1140 | u_int suni_ds3_frm_cfg; | ||
1141 | u_int suni_ds3_frm_intr_enbl; | ||
1142 | u_int suni_ds3_frm_intr_stat; | ||
1143 | u_int suni_ds3_frm_stat; | ||
1144 | u_int suni_rfdl_cfg; | ||
1145 | u_int suni_rfdl_enbl_stat; | ||
1146 | u_int suni_rfdl_stat; | ||
1147 | u_int suni_rfdl_data; | ||
1148 | u_int suni_pmon_chng; | ||
1149 | u_int suni_pmon_intr_enbl_stat; | ||
1150 | u_int suni_reserved1[0x13-0x11]; | ||
1151 | u_int suni_pmon_lcv_evt_cnt_lsb; | ||
1152 | u_int suni_pmon_lcv_evt_cnt_msb; | ||
1153 | u_int suni_pmon_fbe_evt_cnt_lsb; | ||
1154 | u_int suni_pmon_fbe_evt_cnt_msb; | ||
1155 | u_int suni_pmon_sez_det_cnt_lsb; | ||
1156 | u_int suni_pmon_sez_det_cnt_msb; | ||
1157 | u_int suni_pmon_pe_evt_cnt_lsb; | ||
1158 | u_int suni_pmon_pe_evt_cnt_msb; | ||
1159 | u_int suni_pmon_ppe_evt_cnt_lsb; | ||
1160 | u_int suni_pmon_ppe_evt_cnt_msb; | ||
1161 | u_int suni_pmon_febe_evt_cnt_lsb; | ||
1162 | u_int suni_pmon_febe_evt_cnt_msb; | ||
1163 | u_int suni_ds3_tran_cfg; | ||
1164 | u_int suni_ds3_tran_diag; | ||
1165 | u_int suni_reserved2[0x23-0x21]; | ||
1166 | u_int suni_xfdl_cfg; | ||
1167 | u_int suni_xfdl_intr_st; | ||
1168 | u_int suni_xfdl_xmit_data; | ||
1169 | u_int suni_xboc_code; | ||
1170 | u_int suni_splr_cfg; | ||
1171 | u_int suni_splr_intr_en; | ||
1172 | u_int suni_splr_intr_st; | ||
1173 | u_int suni_splr_status; | ||
1174 | u_int suni_splt_cfg; | ||
1175 | u_int suni_splt_cntl; | ||
1176 | u_int suni_splt_diag_g1; | ||
1177 | u_int suni_splt_f1; | ||
1178 | u_int suni_cppm_loc_meters; | ||
1179 | u_int suni_cppm_chng_of_cppm_perf_meter; | ||
1180 | u_int suni_cppm_b1_err_cnt_lsb; | ||
1181 | u_int suni_cppm_b1_err_cnt_msb; | ||
1182 | u_int suni_cppm_framing_err_cnt_lsb; | ||
1183 | u_int suni_cppm_framing_err_cnt_msb; | ||
1184 | u_int suni_cppm_febe_cnt_lsb; | ||
1185 | u_int suni_cppm_febe_cnt_msb; | ||
1186 | u_int suni_cppm_hcs_err_cnt_lsb; | ||
1187 | u_int suni_cppm_hcs_err_cnt_msb; | ||
1188 | u_int suni_cppm_idle_un_cell_cnt_lsb; | ||
1189 | u_int suni_cppm_idle_un_cell_cnt_msb; | ||
1190 | u_int suni_cppm_rcv_cell_cnt_lsb; | ||
1191 | u_int suni_cppm_rcv_cell_cnt_msb; | ||
1192 | u_int suni_cppm_xmit_cell_cnt_lsb; | ||
1193 | u_int suni_cppm_xmit_cell_cnt_msb; | ||
1194 | u_int suni_rxcp_ctrl; | ||
1195 | u_int suni_rxcp_fctrl; | ||
1196 | u_int suni_rxcp_intr_en_sts; | ||
1197 | u_int suni_rxcp_idle_pat_h1; | ||
1198 | u_int suni_rxcp_idle_pat_h2; | ||
1199 | u_int suni_rxcp_idle_pat_h3; | ||
1200 | u_int suni_rxcp_idle_pat_h4; | ||
1201 | u_int suni_rxcp_idle_mask_h1; | ||
1202 | u_int suni_rxcp_idle_mask_h2; | ||
1203 | u_int suni_rxcp_idle_mask_h3; | ||
1204 | u_int suni_rxcp_idle_mask_h4; | ||
1205 | u_int suni_rxcp_cell_pat_h1; | ||
1206 | u_int suni_rxcp_cell_pat_h2; | ||
1207 | u_int suni_rxcp_cell_pat_h3; | ||
1208 | u_int suni_rxcp_cell_pat_h4; | ||
1209 | u_int suni_rxcp_cell_mask_h1; | ||
1210 | u_int suni_rxcp_cell_mask_h2; | ||
1211 | u_int suni_rxcp_cell_mask_h3; | ||
1212 | u_int suni_rxcp_cell_mask_h4; | ||
1213 | u_int suni_rxcp_hcs_cs; | ||
1214 | u_int suni_rxcp_lcd_cnt_threshold; | ||
1215 | u_int suni_reserved3[0x57-0x54]; | ||
1216 | u_int suni_txcp_ctrl; | ||
1217 | u_int suni_txcp_intr_en_sts; | ||
1218 | u_int suni_txcp_idle_pat_h1; | ||
1219 | u_int suni_txcp_idle_pat_h2; | ||
1220 | u_int suni_txcp_idle_pat_h3; | ||
1221 | u_int suni_txcp_idle_pat_h4; | ||
1222 | u_int suni_txcp_idle_pat_h5; | ||
1223 | u_int suni_txcp_idle_payload; | ||
1224 | u_int suni_e3_frm_fram_options; | ||
1225 | u_int suni_e3_frm_maint_options; | ||
1226 | u_int suni_e3_frm_fram_intr_enbl; | ||
1227 | u_int suni_e3_frm_fram_intr_ind_stat; | ||
1228 | u_int suni_e3_frm_maint_intr_enbl; | ||
1229 | u_int suni_e3_frm_maint_intr_ind; | ||
1230 | u_int suni_e3_frm_maint_stat; | ||
1231 | u_int suni_reserved4; | ||
1232 | u_int suni_e3_tran_fram_options; | ||
1233 | u_int suni_e3_tran_stat_diag_options; | ||
1234 | u_int suni_e3_tran_bip_8_err_mask; | ||
1235 | u_int suni_e3_tran_maint_adapt_options; | ||
1236 | u_int suni_ttb_ctrl; | ||
1237 | u_int suni_ttb_trail_trace_id_stat; | ||
1238 | u_int suni_ttb_ind_addr; | ||
1239 | u_int suni_ttb_ind_data; | ||
1240 | u_int suni_ttb_exp_payload_type; | ||
1241 | u_int suni_ttb_payload_type_ctrl_stat; | ||
1242 | u_int suni_pad5[0x7f-0x71]; | ||
1243 | u_int suni_master_test; | ||
1244 | u_int suni_pad6[0xff-0x80]; | ||
1245 | }suni_pm7345_t; | ||
1246 | |||
1247 | #define SUNI_PM7345_T suni_pm7345_t | ||
1248 | #define SUNI_PM7345 0x20 /* Suni chip type */ | ||
1249 | #define SUNI_PM5346 0x30 /* Suni chip type */ | ||
1250 | /* | ||
1251 | * SUNI_PM7345 Configuration | ||
1252 | */ | ||
1253 | #define SUNI_PM7345_CLB 0x01 /* Cell loopback */ | ||
1254 | #define SUNI_PM7345_PLB 0x02 /* Payload loopback */ | ||
1255 | #define SUNI_PM7345_DLB 0x04 /* Diagnostic loopback */ | ||
1256 | #define SUNI_PM7345_LLB 0x80 /* Line loopback */ | ||
1257 | #define SUNI_PM7345_E3ENBL 0x40 /* E3 enable bit */ | ||
1258 | #define SUNI_PM7345_LOOPT 0x10 /* LOOPT enable bit */ | ||
1259 | #define SUNI_PM7345_FIFOBP 0x20 /* FIFO bypass */ | ||
1260 | #define SUNI_PM7345_FRMRBP 0x08 /* Framer bypass */ | ||
1261 | /* | ||
1262 | * DS3 FRMR Interrupt Enable | ||
1263 | */ | ||
1264 | #define SUNI_DS3_COFAE 0x80 /* Enable change of frame align */ | ||
1265 | #define SUNI_DS3_REDE 0x40 /* Enable DS3 RED state intr */ | ||
1266 | #define SUNI_DS3_CBITE 0x20 /* Enable Appl ID channel intr */ | ||
1267 | #define SUNI_DS3_FERFE 0x10 /* Enable Far End Receive Failure intr*/ | ||
1268 | #define SUNI_DS3_IDLE 0x08 /* Enable Idle signal intr */ | ||
1269 | #define SUNI_DS3_AISE 0x04 /* Enable Alarm Indication signal intr*/ | ||
1270 | #define SUNI_DS3_OOFE 0x02 /* Enable Out of frame intr */ | ||
1271 | #define SUNI_DS3_LOSE 0x01 /* Enable Loss of signal intr */ | ||
1272 | |||
1273 | /* | ||
1274 | * DS3 FRMR Status | ||
1275 | */ | ||
1276 | #define SUNI_DS3_ACE 0x80 /* Additional Configuration Reg */ | ||
1277 | #define SUNI_DS3_REDV 0x40 /* DS3 RED state */ | ||
1278 | #define SUNI_DS3_CBITV 0x20 /* Application ID channel state */ | ||
1279 | #define SUNI_DS3_FERFV 0x10 /* Far End Receive Failure state*/ | ||
1280 | #define SUNI_DS3_IDLV 0x08 /* Idle signal state */ | ||
1281 | #define SUNI_DS3_AISV 0x04 /* Alarm Indication signal state*/ | ||
1282 | #define SUNI_DS3_OOFV 0x02 /* Out of frame state */ | ||
1283 | #define SUNI_DS3_LOSV 0x01 /* Loss of signal state */ | ||
1284 | |||
1285 | /* | ||
1286 | * E3 FRMR Interrupt/Status | ||
1287 | */ | ||
1288 | #define SUNI_E3_CZDI 0x40 /* Consecutive Zeros indicator */ | ||
1289 | #define SUNI_E3_LOSI 0x20 /* Loss of signal intr status */ | ||
1290 | #define SUNI_E3_LCVI 0x10 /* Line code violation intr */ | ||
1291 | #define SUNI_E3_COFAI 0x08 /* Change of frame align intr */ | ||
1292 | #define SUNI_E3_OOFI 0x04 /* Out of frame intr status */ | ||
1293 | #define SUNI_E3_LOS 0x02 /* Loss of signal state */ | ||
1294 | #define SUNI_E3_OOF 0x01 /* Out of frame state */ | ||
1295 | |||
1296 | /* | ||
1297 | * E3 FRMR Maintenance Status | ||
1298 | */ | ||
1299 | #define SUNI_E3_AISD 0x80 /* Alarm Indication signal state*/ | ||
1300 | #define SUNI_E3_FERF_RAI 0x40 /* FERF/RAI indicator */ | ||
1301 | #define SUNI_E3_FEBE 0x20 /* Far End Block Error indicator*/ | ||
1302 | |||
1303 | /* | ||
1304 | * RXCP Control/Status | ||
1305 | */ | ||
1306 | #define SUNI_DS3_HCSPASS 0x80 /* Pass cell with HEC errors */ | ||
1307 | #define SUNI_DS3_HCSDQDB 0x40 /* Control octets in HCS calc */ | ||
1308 | #define SUNI_DS3_HCSADD 0x20 /* Add coset poly */ | ||
1309 | #define SUNI_DS3_HCK 0x10 /* Control FIFO data path integ chk*/ | ||
1310 | #define SUNI_DS3_BLOCK 0x08 /* Enable cell filtering */ | ||
1311 | #define SUNI_DS3_DSCR 0x04 /* Disable payload descrambling */ | ||
1312 | #define SUNI_DS3_OOCDV 0x02 /* Cell delineation state */ | ||
1313 | #define SUNI_DS3_FIFORST 0x01 /* Cell FIFO reset */ | ||
1314 | |||
1315 | /* | ||
1316 | * RXCP Interrupt Enable/Status | ||
1317 | */ | ||
1318 | #define SUNI_DS3_OOCDE 0x80 /* Intr enable, change in CDS */ | ||
1319 | #define SUNI_DS3_HCSE 0x40 /* Intr enable, corr HCS errors */ | ||
1320 | #define SUNI_DS3_FIFOE 0x20 /* Intr enable, unco HCS errors */ | ||
1321 | #define SUNI_DS3_OOCDI 0x10 /* SYNC state */ | ||
1322 | #define SUNI_DS3_UHCSI 0x08 /* Uncorr. HCS errors detected */ | ||
1323 | #define SUNI_DS3_COCAI 0x04 /* Corr. HCS errors detected */ | ||
1324 | #define SUNI_DS3_FOVRI 0x02 /* FIFO overrun */ | ||
1325 | #define SUNI_DS3_FUDRI 0x01 /* FIFO underrun */ | ||
1326 | |||
1327 | ///////////////////SUNI_PM7345 PHY DEFINE END ///////////////////////////// | ||
1328 | |||
1329 | /* ia_eeprom define*/ | ||
1330 | #define MEM_SIZE_MASK 0x000F /* mask of 4 bits defining memory size*/ | ||
1331 | #define MEM_SIZE_128K 0x0000 /* board has 128k buffer */ | ||
1332 | #define MEM_SIZE_512K 0x0001 /* board has 512K of buffer */ | ||
1333 | #define MEM_SIZE_1M 0x0002 /* board has 1M of buffer */ | ||
1334 | /* 0x3 to 0xF are reserved for future */ | ||
1335 | |||
1336 | #define FE_MASK 0x00F0 /* mask of 4 bits defining FE type */ | ||
1337 | #define FE_MULTI_MODE 0x0000 /* 155 MBit multimode fiber */ | ||
1338 | #define FE_SINGLE_MODE 0x0010 /* 155 MBit single mode laser */ | ||
1339 | #define FE_UTP_OPTION 0x0020 /* 155 MBit UTP front end */ | ||
1340 | |||
1341 | #define NOVRAM_SIZE 64 | ||
1342 | #define CMD_LEN 10 | ||
1343 | |||
1344 | /*********** | ||
1345 | * | ||
1346 | * Switches and defines for header files. | ||
1347 | * | ||
1348 | * The following defines are used to turn on and off | ||
1349 | * various options in the header files. Primarily useful | ||
1350 | * for debugging. | ||
1351 | * | ||
1352 | ***********/ | ||
1353 | |||
1354 | /* | ||
1355 | * a list of the commands that can be sent to the NOVRAM | ||
1356 | */ | ||
1357 | |||
1358 | #define EXTEND 0x100 | ||
1359 | #define IAWRITE 0x140 | ||
1360 | #define IAREAD 0x180 | ||
1361 | #define ERASE 0x1c0 | ||
1362 | |||
1363 | #define EWDS 0x00 | ||
1364 | #define WRAL 0x10 | ||
1365 | #define ERAL 0x20 | ||
1366 | #define EWEN 0x30 | ||
1367 | |||
1368 | /* | ||
1369 | * these bits duplicate the hw_flip.h register settings | ||
1370 | * note: how the data in / out bits are defined in the flipper specification | ||
1371 | */ | ||
1372 | |||
1373 | #define NVCE 0x02 | ||
1374 | #define NVSK 0x01 | ||
1375 | #define NVDO 0x08 | ||
1376 | #define NVDI 0x04 | ||
1377 | /*********************** | ||
1378 | * | ||
1379 | * This define ands the value and the current config register and puts | ||
1380 | * the result in the config register | ||
1381 | * | ||
1382 | ***********************/ | ||
1383 | |||
1384 | #define CFG_AND(val) { \ | ||
1385 | u32 t; \ | ||
1386 | t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \ | ||
1387 | t &= (val); \ | ||
1388 | writel(t, iadev->reg+IPHASE5575_EEPROM_ACCESS); \ | ||
1389 | } | ||
1390 | |||
1391 | /*********************** | ||
1392 | * | ||
1393 | * This define ors the value and the current config register and puts | ||
1394 | * the result in the config register | ||
1395 | * | ||
1396 | ***********************/ | ||
1397 | |||
1398 | #define CFG_OR(val) { \ | ||
1399 | u32 t; \ | ||
1400 | t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \ | ||
1401 | t |= (val); \ | ||
1402 | writel(t, iadev->reg+IPHASE5575_EEPROM_ACCESS); \ | ||
1403 | } | ||
1404 | |||
1405 | /*********************** | ||
1406 | * | ||
1407 | * Send a command to the NOVRAM, the command is in cmd. | ||
1408 | * | ||
1409 | * clear CE and SK. Then assert CE. | ||
1410 | * Clock each of the command bits out in the correct order with SK | ||
1411 | * exit with CE still asserted | ||
1412 | * | ||
1413 | ***********************/ | ||
1414 | |||
1415 | #define NVRAM_CMD(cmd) { \ | ||
1416 | int i; \ | ||
1417 | u_short c = cmd; \ | ||
1418 | CFG_AND(~(NVCE|NVSK)); \ | ||
1419 | CFG_OR(NVCE); \ | ||
1420 | for (i=0; i<CMD_LEN; i++) { \ | ||
1421 | NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0); \ | ||
1422 | c <<= 1; \ | ||
1423 | } \ | ||
1424 | } | ||
1425 | |||
1426 | /*********************** | ||
1427 | * | ||
1428 | * clear the CE, this must be used after each command is complete | ||
1429 | * | ||
1430 | ***********************/ | ||
1431 | |||
1432 | #define NVRAM_CLR_CE {CFG_AND(~NVCE)} | ||
1433 | |||
1434 | /*********************** | ||
1435 | * | ||
1436 | * clock the data bit in bitval out to the NOVRAM. The bitval must be | ||
1437 | * a 1 or 0, or the clockout operation is undefined | ||
1438 | * | ||
1439 | ***********************/ | ||
1440 | |||
1441 | #define NVRAM_CLKOUT(bitval) { \ | ||
1442 | CFG_AND(~NVDI); \ | ||
1443 | CFG_OR((bitval) ? NVDI : 0); \ | ||
1444 | CFG_OR(NVSK); \ | ||
1445 | CFG_AND( ~NVSK); \ | ||
1446 | } | ||
1447 | |||
1448 | /*********************** | ||
1449 | * | ||
1450 | * clock the data bit in and return a 1 or 0, depending on the value | ||
1451 | * that was received from the NOVRAM | ||
1452 | * | ||
1453 | ***********************/ | ||
1454 | |||
1455 | #define NVRAM_CLKIN(value) { \ | ||
1456 | u32 _t; \ | ||
1457 | CFG_OR(NVSK); \ | ||
1458 | CFG_AND(~NVSK); \ | ||
1459 | _t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \ | ||
1460 | value = (_t & NVDO) ? 1 : 0; \ | ||
1461 | } | ||
1462 | |||
1463 | |||
1464 | #endif /* IPHASE_H */ | ||
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c new file mode 100644 index 000000000000..ffe3afa723b8 --- /dev/null +++ b/drivers/atm/lanai.c | |||
@@ -0,0 +1,2770 @@ | |||
1 | /* lanai.c -- Copyright 1999-2003 by Mitchell Blank Jr <mitch@sfgoth.com> | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version | ||
6 | * 2 of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This driver supports ATM cards based on the Efficient "Lanai" | ||
9 | * chipset such as the Speedstream 3010 and the ENI-25p. The | ||
10 | * Speedstream 3060 is currently not supported since we don't | ||
11 | * have the code to drive the on-board Alcatel DSL chipset (yet). | ||
12 | * | ||
13 | * Thanks to Efficient for supporting this project with hardware, | ||
14 | * documentation, and by answering my questions. | ||
15 | * | ||
16 | * Things not working yet: | ||
17 | * | ||
18 | * o We don't support the Speedstream 3060 yet - this card has | ||
19 | * an on-board DSL modem chip by Alcatel and the driver will | ||
20 | * need some extra code added to handle it | ||
21 | * | ||
22 | * o Note that due to limitations of the Lanai only one VCC can be | ||
23 | * in CBR at once | ||
24 | * | ||
25 | * o We don't currently parse the EEPROM at all. The code is all | ||
26 | * there as per the spec, but it doesn't actually work. I think | ||
27 | * there may be some issues with the docs. Anyway, do NOT | ||
28 | * enable it yet - bugs in that code may actually damage your | ||
29 | * hardware! Because of this you should hardware an ESI before | ||
30 | * trying to use this in a LANE or MPOA environment. | ||
31 | * | ||
32 | * o AAL0 is stubbed in but the actual rx/tx path isn't written yet: | ||
33 | * vcc_tx_aal0() needs to send or queue a SKB | ||
34 | * vcc_tx_unqueue_aal0() needs to attempt to send queued SKBs | ||
35 | * vcc_rx_aal0() needs to handle AAL0 interrupts | ||
36 | * This isn't too much work - I just wanted to get other things | ||
37 | * done first. | ||
38 | * | ||
39 | * o lanai_change_qos() isn't written yet | ||
40 | * | ||
41 | * o There aren't any ioctl's yet -- I'd like to eventually support | ||
42 | * setting loopback and LED modes that way. (see lanai_ioctl) | ||
43 | * | ||
44 | * o If the segmentation engine or DMA gets shut down we should restart | ||
45 | * card as per section 17.0i. (see lanai_reset) | ||
46 | * | ||
47 | * o setsockopt(SO_CIRANGE) isn't done (although despite what the | ||
48 | * API says it isn't exactly commonly implemented) | ||
49 | */ | ||
50 | |||
51 | /* Version history: | ||
52 | * v.1.00 -- 26-JUL-2003 -- PCI/DMA updates | ||
53 | * v.0.02 -- 11-JAN-2000 -- Endian fixes | ||
54 | * v.0.01 -- 30-NOV-1999 -- Initial release | ||
55 | */ | ||
56 | |||
57 | #include <linux/module.h> | ||
58 | #include <linux/mm.h> | ||
59 | #include <linux/atmdev.h> | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/byteorder.h> | ||
62 | #include <linux/spinlock.h> | ||
63 | #include <linux/pci.h> | ||
64 | #include <linux/dma-mapping.h> | ||
65 | #include <linux/init.h> | ||
66 | #include <linux/delay.h> | ||
67 | #include <linux/interrupt.h> | ||
68 | #include <linux/dma-mapping.h> | ||
69 | |||
70 | /* -------------------- TUNABLE PARAMATERS: */ | ||
71 | |||
72 | /* | ||
73 | * Maximum number of VCIs per card. Setting it lower could theoretically | ||
74 | * save some memory, but since we allocate our vcc list with get_free_pages, | ||
75 | * it's not really likely for most architectures | ||
76 | */ | ||
77 | #define NUM_VCI (1024) | ||
78 | |||
79 | /* | ||
80 | * Enable extra debugging | ||
81 | */ | ||
82 | #define DEBUG | ||
83 | /* | ||
84 | * Debug _all_ register operations with card, except the memory test. | ||
85 | * Also disables the timed poll to prevent extra chattiness. This | ||
86 | * isn't for normal use | ||
87 | */ | ||
88 | #undef DEBUG_RW | ||
89 | |||
90 | /* | ||
91 | * The programming guide specifies a full test of the on-board SRAM | ||
92 | * at initialization time. Undefine to remove this | ||
93 | */ | ||
94 | #define FULL_MEMORY_TEST | ||
95 | |||
96 | /* | ||
97 | * This is the number of (4 byte) service entries that we will | ||
98 | * try to allocate at startup. Note that we will end up with | ||
99 | * one PAGE_SIZE's worth regardless of what this is set to | ||
100 | */ | ||
101 | #define SERVICE_ENTRIES (1024) | ||
102 | /* TODO: make above a module load-time option */ | ||
103 | |||
104 | /* | ||
105 | * We normally read the onboard EEPROM in order to discover our MAC | ||
106 | * address. Undefine to _not_ do this | ||
107 | */ | ||
108 | /* #define READ_EEPROM */ /* ***DONT ENABLE YET*** */ | ||
109 | /* TODO: make above a module load-time option (also) */ | ||
110 | |||
111 | /* | ||
112 | * Depth of TX fifo (in 128 byte units; range 2-31) | ||
113 | * Smaller numbers are better for network latency | ||
114 | * Larger numbers are better for PCI latency | ||
115 | * I'm really sure where the best tradeoff is, but the BSD driver uses | ||
116 | * 7 and it seems to work ok. | ||
117 | */ | ||
118 | #define TX_FIFO_DEPTH (7) | ||
119 | /* TODO: make above a module load-time option */ | ||
120 | |||
121 | /* | ||
122 | * How often (in jiffies) we will try to unstick stuck connections - | ||
123 | * shouldn't need to happen much | ||
124 | */ | ||
125 | #define LANAI_POLL_PERIOD (10*HZ) | ||
126 | /* TODO: make above a module load-time option */ | ||
127 | |||
128 | /* | ||
129 | * When allocating an AAL5 receiving buffer, try to make it at least | ||
130 | * large enough to hold this many max_sdu sized PDUs | ||
131 | */ | ||
132 | #define AAL5_RX_MULTIPLIER (3) | ||
133 | /* TODO: make above a module load-time option */ | ||
134 | |||
135 | /* | ||
136 | * Same for transmitting buffer | ||
137 | */ | ||
138 | #define AAL5_TX_MULTIPLIER (3) | ||
139 | /* TODO: make above a module load-time option */ | ||
140 | |||
141 | /* | ||
142 | * When allocating an AAL0 transmiting buffer, how many cells should fit. | ||
143 | * Remember we'll end up with a PAGE_SIZE of them anyway, so this isn't | ||
144 | * really critical | ||
145 | */ | ||
146 | #define AAL0_TX_MULTIPLIER (40) | ||
147 | /* TODO: make above a module load-time option */ | ||
148 | |||
149 | /* | ||
150 | * How large should we make the AAL0 receiving buffer. Remember that this | ||
151 | * is shared between all AAL0 VC's | ||
152 | */ | ||
153 | #define AAL0_RX_BUFFER_SIZE (PAGE_SIZE) | ||
154 | /* TODO: make above a module load-time option */ | ||
155 | |||
156 | /* | ||
157 | * Should we use Lanai's "powerdown" feature when no vcc's are bound? | ||
158 | */ | ||
159 | /* #define USE_POWERDOWN */ | ||
160 | /* TODO: make above a module load-time option (also) */ | ||
161 | |||
162 | /* -------------------- DEBUGGING AIDS: */ | ||
163 | |||
164 | #define DEV_LABEL "lanai" | ||
165 | |||
166 | #ifdef DEBUG | ||
167 | |||
168 | #define DPRINTK(format, args...) \ | ||
169 | printk(KERN_DEBUG DEV_LABEL ": " format, ##args) | ||
170 | #define APRINTK(truth, format, args...) \ | ||
171 | do { \ | ||
172 | if (unlikely(!(truth))) \ | ||
173 | printk(KERN_ERR DEV_LABEL ": " format, ##args); \ | ||
174 | } while (0) | ||
175 | |||
176 | #else /* !DEBUG */ | ||
177 | |||
178 | #define DPRINTK(format, args...) | ||
179 | #define APRINTK(truth, format, args...) | ||
180 | |||
181 | #endif /* DEBUG */ | ||
182 | |||
183 | #ifdef DEBUG_RW | ||
184 | #define RWDEBUG(format, args...) \ | ||
185 | printk(KERN_DEBUG DEV_LABEL ": " format, ##args) | ||
186 | #else /* !DEBUG_RW */ | ||
187 | #define RWDEBUG(format, args...) | ||
188 | #endif | ||
189 | |||
190 | /* -------------------- DATA DEFINITIONS: */ | ||
191 | |||
192 | #define LANAI_MAPPING_SIZE (0x40000) | ||
193 | #define LANAI_EEPROM_SIZE (128) | ||
194 | |||
195 | typedef int vci_t; | ||
196 | typedef void __iomem *bus_addr_t; | ||
197 | |||
198 | /* DMA buffer in host memory for TX, RX, or service list. */ | ||
199 | struct lanai_buffer { | ||
200 | u32 *start; /* From get_free_pages */ | ||
201 | u32 *end; /* One past last byte */ | ||
202 | u32 *ptr; /* Pointer to current host location */ | ||
203 | dma_addr_t dmaaddr; | ||
204 | }; | ||
205 | |||
206 | struct lanai_vcc_stats { | ||
207 | unsigned rx_nomem; | ||
208 | union { | ||
209 | struct { | ||
210 | unsigned rx_badlen; | ||
211 | unsigned service_trash; | ||
212 | unsigned service_stream; | ||
213 | unsigned service_rxcrc; | ||
214 | } aal5; | ||
215 | struct { | ||
216 | } aal0; | ||
217 | } x; | ||
218 | }; | ||
219 | |||
220 | struct lanai_dev; /* Forward declaration */ | ||
221 | |||
222 | /* | ||
223 | * This is the card-specific per-vcc data. Note that unlike some other | ||
224 | * drivers there is NOT a 1-to-1 correspondance between these and | ||
225 | * atm_vcc's - each one of these represents an actual 2-way vcc, but | ||
226 | * an atm_vcc can be 1-way and share with a 1-way vcc in the other | ||
227 | * direction. To make it weirder, there can even be 0-way vccs | ||
228 | * bound to us, waiting to do a change_qos | ||
229 | */ | ||
230 | struct lanai_vcc { | ||
231 | bus_addr_t vbase; /* Base of VCC's registers */ | ||
232 | struct lanai_vcc_stats stats; | ||
233 | int nref; /* # of atm_vcc's who reference us */ | ||
234 | vci_t vci; | ||
235 | struct { | ||
236 | struct lanai_buffer buf; | ||
237 | struct atm_vcc *atmvcc; /* atm_vcc who is receiver */ | ||
238 | } rx; | ||
239 | struct { | ||
240 | struct lanai_buffer buf; | ||
241 | struct atm_vcc *atmvcc; /* atm_vcc who is transmitter */ | ||
242 | int endptr; /* last endptr from service entry */ | ||
243 | struct sk_buff_head backlog; | ||
244 | void (*unqueue)(struct lanai_dev *, struct lanai_vcc *, int); | ||
245 | } tx; | ||
246 | }; | ||
247 | |||
248 | enum lanai_type { | ||
249 | lanai2 = PCI_VENDOR_ID_EF_ATM_LANAI2, | ||
250 | lanaihb = PCI_VENDOR_ID_EF_ATM_LANAIHB | ||
251 | }; | ||
252 | |||
253 | struct lanai_dev_stats { | ||
254 | unsigned ovfl_trash; /* # of cells dropped - buffer overflow */ | ||
255 | unsigned vci_trash; /* # of cells dropped - closed vci */ | ||
256 | unsigned hec_err; /* # of cells dropped - bad HEC */ | ||
257 | unsigned atm_ovfl; /* # of cells dropped - rx fifo overflow */ | ||
258 | unsigned pcierr_parity_detect; | ||
259 | unsigned pcierr_serr_set; | ||
260 | unsigned pcierr_master_abort; | ||
261 | unsigned pcierr_m_target_abort; | ||
262 | unsigned pcierr_s_target_abort; | ||
263 | unsigned pcierr_master_parity; | ||
264 | unsigned service_notx; | ||
265 | unsigned service_norx; | ||
266 | unsigned service_rxnotaal5; | ||
267 | unsigned dma_reenable; | ||
268 | unsigned card_reset; | ||
269 | }; | ||
270 | |||
271 | struct lanai_dev { | ||
272 | bus_addr_t base; | ||
273 | struct lanai_dev_stats stats; | ||
274 | struct lanai_buffer service; | ||
275 | struct lanai_vcc **vccs; | ||
276 | #ifdef USE_POWERDOWN | ||
277 | int nbound; /* number of bound vccs */ | ||
278 | #endif | ||
279 | enum lanai_type type; | ||
280 | vci_t num_vci; /* Currently just NUM_VCI */ | ||
281 | u8 eeprom[LANAI_EEPROM_SIZE]; | ||
282 | u32 serialno, magicno; | ||
283 | struct pci_dev *pci; | ||
284 | DECLARE_BITMAP(backlog_vccs, NUM_VCI); /* VCCs with tx backlog */ | ||
285 | DECLARE_BITMAP(transmit_ready, NUM_VCI); /* VCCs with transmit space */ | ||
286 | struct timer_list timer; | ||
287 | int naal0; | ||
288 | struct lanai_buffer aal0buf; /* AAL0 RX buffers */ | ||
289 | u32 conf1, conf2; /* CONFIG[12] registers */ | ||
290 | u32 status; /* STATUS register */ | ||
291 | spinlock_t endtxlock; | ||
292 | spinlock_t servicelock; | ||
293 | struct atm_vcc *cbrvcc; | ||
294 | int number; | ||
295 | int board_rev; | ||
296 | u8 pci_revision; | ||
297 | /* TODO - look at race conditions with maintence of conf1/conf2 */ | ||
298 | /* TODO - transmit locking: should we use _irq not _irqsave? */ | ||
299 | /* TODO - organize above in some rational fashion (see <asm/cache.h>) */ | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Each device has two bitmaps for each VCC (baclog_vccs and transmit_ready) | ||
304 | * This function iterates one of these, calling a given function for each | ||
305 | * vci with their bit set | ||
306 | */ | ||
307 | static void vci_bitfield_iterate(struct lanai_dev *lanai, | ||
308 | /*const*/ unsigned long *lp, | ||
309 | void (*func)(struct lanai_dev *,vci_t vci)) | ||
310 | { | ||
311 | vci_t vci = find_first_bit(lp, NUM_VCI); | ||
312 | while (vci < NUM_VCI) { | ||
313 | func(lanai, vci); | ||
314 | vci = find_next_bit(lp, NUM_VCI, vci + 1); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /* -------------------- BUFFER UTILITIES: */ | ||
319 | |||
320 | /* | ||
321 | * Lanai needs DMA buffers aligned to 256 bytes of at least 1024 bytes - | ||
322 | * usually any page allocation will do. Just to be safe in case | ||
323 | * PAGE_SIZE is insanely tiny, though... | ||
324 | */ | ||
325 | #define LANAI_PAGE_SIZE ((PAGE_SIZE >= 1024) ? PAGE_SIZE : 1024) | ||
326 | |||
327 | /* | ||
328 | * Allocate a buffer in host RAM for service list, RX, or TX | ||
329 | * Returns buf->start==NULL if no memory | ||
330 | * Note that the size will be rounded up 2^n bytes, and | ||
331 | * if we can't allocate that we'll settle for something smaller | ||
332 | * until minbytes | ||
333 | */ | ||
334 | static void lanai_buf_allocate(struct lanai_buffer *buf, | ||
335 | size_t bytes, size_t minbytes, struct pci_dev *pci) | ||
336 | { | ||
337 | int size; | ||
338 | |||
339 | if (bytes > (128 * 1024)) /* max lanai buffer size */ | ||
340 | bytes = 128 * 1024; | ||
341 | for (size = LANAI_PAGE_SIZE; size < bytes; size *= 2) | ||
342 | ; | ||
343 | if (minbytes < LANAI_PAGE_SIZE) | ||
344 | minbytes = LANAI_PAGE_SIZE; | ||
345 | do { | ||
346 | /* | ||
347 | * Technically we could use non-consistent mappings for | ||
348 | * everything, but the way the lanai uses DMA memory would | ||
349 | * make that a terrific pain. This is much simpler. | ||
350 | */ | ||
351 | buf->start = pci_alloc_consistent(pci, size, &buf->dmaaddr); | ||
352 | if (buf->start != NULL) { /* Success */ | ||
353 | /* Lanai requires 256-byte alignment of DMA bufs */ | ||
354 | APRINTK((buf->dmaaddr & ~0xFFFFFF00) == 0, | ||
355 | "bad dmaaddr: 0x%lx\n", | ||
356 | (unsigned long) buf->dmaaddr); | ||
357 | buf->ptr = buf->start; | ||
358 | buf->end = (u32 *) | ||
359 | (&((unsigned char *) buf->start)[size]); | ||
360 | memset(buf->start, 0, size); | ||
361 | break; | ||
362 | } | ||
363 | size /= 2; | ||
364 | } while (size >= minbytes); | ||
365 | } | ||
366 | |||
367 | /* size of buffer in bytes */ | ||
368 | static inline size_t lanai_buf_size(const struct lanai_buffer *buf) | ||
369 | { | ||
370 | return ((unsigned long) buf->end) - ((unsigned long) buf->start); | ||
371 | } | ||
372 | |||
373 | static void lanai_buf_deallocate(struct lanai_buffer *buf, | ||
374 | struct pci_dev *pci) | ||
375 | { | ||
376 | if (buf->start != NULL) { | ||
377 | pci_free_consistent(pci, lanai_buf_size(buf), | ||
378 | buf->start, buf->dmaaddr); | ||
379 | buf->start = buf->end = buf->ptr = NULL; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | /* size of buffer as "card order" (0=1k .. 7=128k) */ | ||
384 | static int lanai_buf_size_cardorder(const struct lanai_buffer *buf) | ||
385 | { | ||
386 | int order = get_order(lanai_buf_size(buf)) + (PAGE_SHIFT - 10); | ||
387 | |||
388 | /* This can only happen if PAGE_SIZE is gigantic, but just in case */ | ||
389 | if (order > 7) | ||
390 | order = 7; | ||
391 | return order; | ||
392 | } | ||
393 | |||
394 | /* -------------------- PORT I/O UTILITIES: */ | ||
395 | |||
396 | /* Registers (and their bit-fields) */ | ||
397 | enum lanai_register { | ||
398 | Reset_Reg = 0x00, /* Reset; read for chip type; bits: */ | ||
399 | #define RESET_GET_BOARD_REV(x) (((x)>> 0)&0x03) /* Board revision */ | ||
400 | #define RESET_GET_BOARD_ID(x) (((x)>> 2)&0x03) /* Board ID */ | ||
401 | #define BOARD_ID_LANAI256 (0) /* 25.6M adapter card */ | ||
402 | Endian_Reg = 0x04, /* Endian setting */ | ||
403 | IntStatus_Reg = 0x08, /* Interrupt status */ | ||
404 | IntStatusMasked_Reg = 0x0C, /* Interrupt status (masked) */ | ||
405 | IntAck_Reg = 0x10, /* Interrupt acknowledge */ | ||
406 | IntAckMasked_Reg = 0x14, /* Interrupt acknowledge (masked) */ | ||
407 | IntStatusSet_Reg = 0x18, /* Get status + enable/disable */ | ||
408 | IntStatusSetMasked_Reg = 0x1C, /* Get status + en/di (masked) */ | ||
409 | IntControlEna_Reg = 0x20, /* Interrupt control enable */ | ||
410 | IntControlDis_Reg = 0x24, /* Interrupt control disable */ | ||
411 | Status_Reg = 0x28, /* Status */ | ||
412 | #define STATUS_PROMDATA (0x00000001) /* PROM_DATA pin */ | ||
413 | #define STATUS_WAITING (0x00000002) /* Interrupt being delayed */ | ||
414 | #define STATUS_SOOL (0x00000004) /* SOOL alarm */ | ||
415 | #define STATUS_LOCD (0x00000008) /* LOCD alarm */ | ||
416 | #define STATUS_LED (0x00000010) /* LED (HAPPI) output */ | ||
417 | #define STATUS_GPIN (0x00000020) /* GPIN pin */ | ||
418 | #define STATUS_BUTTBUSY (0x00000040) /* Butt register is pending */ | ||
419 | Config1_Reg = 0x2C, /* Config word 1; bits: */ | ||
420 | #define CONFIG1_PROMDATA (0x00000001) /* PROM_DATA pin */ | ||
421 | #define CONFIG1_PROMCLK (0x00000002) /* PROM_CLK pin */ | ||
422 | #define CONFIG1_SET_READMODE(x) ((x)*0x004) /* PCI BM reads; values: */ | ||
423 | #define READMODE_PLAIN (0) /* Plain memory read */ | ||
424 | #define READMODE_LINE (2) /* Memory read line */ | ||
425 | #define READMODE_MULTIPLE (3) /* Memory read multiple */ | ||
426 | #define CONFIG1_DMA_ENABLE (0x00000010) /* Turn on DMA */ | ||
427 | #define CONFIG1_POWERDOWN (0x00000020) /* Turn off clocks */ | ||
428 | #define CONFIG1_SET_LOOPMODE(x) ((x)*0x080) /* Clock&loop mode; values: */ | ||
429 | #define LOOPMODE_NORMAL (0) /* Normal - no loop */ | ||
430 | #define LOOPMODE_TIME (1) | ||
431 | #define LOOPMODE_DIAG (2) | ||
432 | #define LOOPMODE_LINE (3) | ||
433 | #define CONFIG1_MASK_LOOPMODE (0x00000180) | ||
434 | #define CONFIG1_SET_LEDMODE(x) ((x)*0x0200) /* Mode of LED; values: */ | ||
435 | #define LEDMODE_NOT_SOOL (0) /* !SOOL */ | ||
436 | #define LEDMODE_OFF (1) /* 0 */ | ||
437 | #define LEDMODE_ON (2) /* 1 */ | ||
438 | #define LEDMODE_NOT_LOCD (3) /* !LOCD */ | ||
439 | #define LEDMORE_GPIN (4) /* GPIN */ | ||
440 | #define LEDMODE_NOT_GPIN (7) /* !GPIN */ | ||
441 | #define CONFIG1_MASK_LEDMODE (0x00000E00) | ||
442 | #define CONFIG1_GPOUT1 (0x00001000) /* Toggle for reset */ | ||
443 | #define CONFIG1_GPOUT2 (0x00002000) /* Loopback PHY */ | ||
444 | #define CONFIG1_GPOUT3 (0x00004000) /* Loopback lanai */ | ||
445 | Config2_Reg = 0x30, /* Config word 2; bits: */ | ||
446 | #define CONFIG2_HOWMANY (0x00000001) /* >512 VCIs? */ | ||
447 | #define CONFIG2_PTI7_MODE (0x00000002) /* Make PTI=7 RM, not OAM */ | ||
448 | #define CONFIG2_VPI_CHK_DIS (0x00000004) /* Ignore RX VPI value */ | ||
449 | #define CONFIG2_HEC_DROP (0x00000008) /* Drop cells w/ HEC errors */ | ||
450 | #define CONFIG2_VCI0_NORMAL (0x00000010) /* Treat VCI=0 normally */ | ||
451 | #define CONFIG2_CBR_ENABLE (0x00000020) /* Deal with CBR traffic */ | ||
452 | #define CONFIG2_TRASH_ALL (0x00000040) /* Trashing incoming cells */ | ||
453 | #define CONFIG2_TX_DISABLE (0x00000080) /* Trashing outgoing cells */ | ||
454 | #define CONFIG2_SET_TRASH (0x00000100) /* Turn trashing on */ | ||
455 | Statistics_Reg = 0x34, /* Statistics; bits: */ | ||
456 | #define STATS_GET_FIFO_OVFL(x) (((x)>> 0)&0xFF) /* FIFO overflowed */ | ||
457 | #define STATS_GET_HEC_ERR(x) (((x)>> 8)&0xFF) /* HEC was bad */ | ||
458 | #define STATS_GET_BAD_VCI(x) (((x)>>16)&0xFF) /* VCI not open */ | ||
459 | #define STATS_GET_BUF_OVFL(x) (((x)>>24)&0xFF) /* VCC buffer full */ | ||
460 | ServiceStuff_Reg = 0x38, /* Service stuff; bits: */ | ||
461 | #define SSTUFF_SET_SIZE(x) ((x)*0x20000000) /* size of service buffer */ | ||
462 | #define SSTUFF_SET_ADDR(x) ((x)>>8) /* set address of buffer */ | ||
463 | ServWrite_Reg = 0x3C, /* ServWrite Pointer */ | ||
464 | ServRead_Reg = 0x40, /* ServRead Pointer */ | ||
465 | TxDepth_Reg = 0x44, /* FIFO Transmit Depth */ | ||
466 | Butt_Reg = 0x48, /* Butt register */ | ||
467 | CBR_ICG_Reg = 0x50, | ||
468 | CBR_PTR_Reg = 0x54, | ||
469 | PingCount_Reg = 0x58, /* Ping count */ | ||
470 | DMA_Addr_Reg = 0x5C /* DMA address */ | ||
471 | }; | ||
472 | |||
473 | static inline bus_addr_t reg_addr(const struct lanai_dev *lanai, | ||
474 | enum lanai_register reg) | ||
475 | { | ||
476 | return lanai->base + reg; | ||
477 | } | ||
478 | |||
479 | static inline u32 reg_read(const struct lanai_dev *lanai, | ||
480 | enum lanai_register reg) | ||
481 | { | ||
482 | u32 t; | ||
483 | t = readl(reg_addr(lanai, reg)); | ||
484 | RWDEBUG("R [0x%08X] 0x%02X = 0x%08X\n", (unsigned int) lanai->base, | ||
485 | (int) reg, t); | ||
486 | return t; | ||
487 | } | ||
488 | |||
489 | static inline void reg_write(const struct lanai_dev *lanai, u32 val, | ||
490 | enum lanai_register reg) | ||
491 | { | ||
492 | RWDEBUG("W [0x%08X] 0x%02X < 0x%08X\n", (unsigned int) lanai->base, | ||
493 | (int) reg, val); | ||
494 | writel(val, reg_addr(lanai, reg)); | ||
495 | } | ||
496 | |||
497 | static inline void conf1_write(const struct lanai_dev *lanai) | ||
498 | { | ||
499 | reg_write(lanai, lanai->conf1, Config1_Reg); | ||
500 | } | ||
501 | |||
502 | static inline void conf2_write(const struct lanai_dev *lanai) | ||
503 | { | ||
504 | reg_write(lanai, lanai->conf2, Config2_Reg); | ||
505 | } | ||
506 | |||
507 | /* Same as conf2_write(), but defers I/O if we're powered down */ | ||
508 | static inline void conf2_write_if_powerup(const struct lanai_dev *lanai) | ||
509 | { | ||
510 | #ifdef USE_POWERDOWN | ||
511 | if (unlikely((lanai->conf1 & CONFIG1_POWERDOWN) != 0)) | ||
512 | return; | ||
513 | #endif /* USE_POWERDOWN */ | ||
514 | conf2_write(lanai); | ||
515 | } | ||
516 | |||
517 | static inline void reset_board(const struct lanai_dev *lanai) | ||
518 | { | ||
519 | DPRINTK("about to reset board\n"); | ||
520 | reg_write(lanai, 0, Reset_Reg); | ||
521 | /* | ||
522 | * If we don't delay a little while here then we can end up | ||
523 | * leaving the card in a VERY weird state and lock up the | ||
524 | * PCI bus. This isn't documented anywhere but I've convinced | ||
525 | * myself after a lot of painful experimentation | ||
526 | */ | ||
527 | udelay(5); | ||
528 | } | ||
529 | |||
530 | /* -------------------- CARD SRAM UTILITIES: */ | ||
531 | |||
532 | /* The SRAM is mapped into normal PCI memory space - the only catch is | ||
533 | * that it is only 16-bits wide but must be accessed as 32-bit. The | ||
534 | * 16 high bits will be zero. We don't hide this, since they get | ||
535 | * programmed mostly like discrete registers anyway | ||
536 | */ | ||
537 | #define SRAM_START (0x20000) | ||
538 | #define SRAM_BYTES (0x20000) /* Again, half don't really exist */ | ||
539 | |||
540 | static inline bus_addr_t sram_addr(const struct lanai_dev *lanai, int offset) | ||
541 | { | ||
542 | return lanai->base + SRAM_START + offset; | ||
543 | } | ||
544 | |||
545 | static inline u32 sram_read(const struct lanai_dev *lanai, int offset) | ||
546 | { | ||
547 | return readl(sram_addr(lanai, offset)); | ||
548 | } | ||
549 | |||
550 | static inline void sram_write(const struct lanai_dev *lanai, | ||
551 | u32 val, int offset) | ||
552 | { | ||
553 | writel(val, sram_addr(lanai, offset)); | ||
554 | } | ||
555 | |||
556 | static int __init sram_test_word( | ||
557 | const struct lanai_dev *lanai, int offset, u32 pattern) | ||
558 | { | ||
559 | u32 readback; | ||
560 | sram_write(lanai, pattern, offset); | ||
561 | readback = sram_read(lanai, offset); | ||
562 | if (likely(readback == pattern)) | ||
563 | return 0; | ||
564 | printk(KERN_ERR DEV_LABEL | ||
565 | "(itf %d): SRAM word at %d bad: wrote 0x%X, read 0x%X\n", | ||
566 | lanai->number, offset, | ||
567 | (unsigned int) pattern, (unsigned int) readback); | ||
568 | return -EIO; | ||
569 | } | ||
570 | |||
571 | static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern) | ||
572 | { | ||
573 | int offset, result = 0; | ||
574 | for (offset = 0; offset < SRAM_BYTES && result == 0; offset += 4) | ||
575 | result = sram_test_word(lanai, offset, pattern); | ||
576 | return result; | ||
577 | } | ||
578 | |||
579 | static int __devinit sram_test_and_clear(const struct lanai_dev *lanai) | ||
580 | { | ||
581 | #ifdef FULL_MEMORY_TEST | ||
582 | int result; | ||
583 | DPRINTK("testing SRAM\n"); | ||
584 | if ((result = sram_test_pass(lanai, 0x5555)) != 0) | ||
585 | return result; | ||
586 | if ((result = sram_test_pass(lanai, 0xAAAA)) != 0) | ||
587 | return result; | ||
588 | #endif | ||
589 | DPRINTK("clearing SRAM\n"); | ||
590 | return sram_test_pass(lanai, 0x0000); | ||
591 | } | ||
592 | |||
593 | /* -------------------- CARD-BASED VCC TABLE UTILITIES: */ | ||
594 | |||
595 | /* vcc table */ | ||
596 | enum lanai_vcc_offset { | ||
597 | vcc_rxaddr1 = 0x00, /* Location1, plus bits: */ | ||
598 | #define RXADDR1_SET_SIZE(x) ((x)*0x0000100) /* size of RX buffer */ | ||
599 | #define RXADDR1_SET_RMMODE(x) ((x)*0x00800) /* RM cell action; values: */ | ||
600 | #define RMMODE_TRASH (0) /* discard */ | ||
601 | #define RMMODE_PRESERVE (1) /* input as AAL0 */ | ||
602 | #define RMMODE_PIPE (2) /* pipe to coscheduler */ | ||
603 | #define RMMODE_PIPEALL (3) /* pipe non-RM too */ | ||
604 | #define RXADDR1_OAM_PRESERVE (0x00002000) /* Input OAM cells as AAL0 */ | ||
605 | #define RXADDR1_SET_MODE(x) ((x)*0x0004000) /* Reassembly mode */ | ||
606 | #define RXMODE_TRASH (0) /* discard */ | ||
607 | #define RXMODE_AAL0 (1) /* non-AAL5 mode */ | ||
608 | #define RXMODE_AAL5 (2) /* AAL5, intr. each PDU */ | ||
609 | #define RXMODE_AAL5_STREAM (3) /* AAL5 w/o per-PDU intr */ | ||
610 | vcc_rxaddr2 = 0x04, /* Location2 */ | ||
611 | vcc_rxcrc1 = 0x08, /* RX CRC claculation space */ | ||
612 | vcc_rxcrc2 = 0x0C, | ||
613 | vcc_rxwriteptr = 0x10, /* RX writeptr, plus bits: */ | ||
614 | #define RXWRITEPTR_LASTEFCI (0x00002000) /* Last PDU had EFCI bit */ | ||
615 | #define RXWRITEPTR_DROPPING (0x00004000) /* Had error, dropping */ | ||
616 | #define RXWRITEPTR_TRASHING (0x00008000) /* Trashing */ | ||
617 | vcc_rxbufstart = 0x14, /* RX bufstart, plus bits: */ | ||
618 | #define RXBUFSTART_CLP (0x00004000) | ||
619 | #define RXBUFSTART_CI (0x00008000) | ||
620 | vcc_rxreadptr = 0x18, /* RX readptr */ | ||
621 | vcc_txicg = 0x1C, /* TX ICG */ | ||
622 | vcc_txaddr1 = 0x20, /* Location1, plus bits: */ | ||
623 | #define TXADDR1_SET_SIZE(x) ((x)*0x0000100) /* size of TX buffer */ | ||
624 | #define TXADDR1_ABR (0x00008000) /* use ABR (doesn't work) */ | ||
625 | vcc_txaddr2 = 0x24, /* Location2 */ | ||
626 | vcc_txcrc1 = 0x28, /* TX CRC claculation space */ | ||
627 | vcc_txcrc2 = 0x2C, | ||
628 | vcc_txreadptr = 0x30, /* TX Readptr, plus bits: */ | ||
629 | #define TXREADPTR_GET_PTR(x) ((x)&0x01FFF) | ||
630 | #define TXREADPTR_MASK_DELTA (0x0000E000) /* ? */ | ||
631 | vcc_txendptr = 0x34, /* TX Endptr, plus bits: */ | ||
632 | #define TXENDPTR_CLP (0x00002000) | ||
633 | #define TXENDPTR_MASK_PDUMODE (0x0000C000) /* PDU mode; values: */ | ||
634 | #define PDUMODE_AAL0 (0*0x04000) | ||
635 | #define PDUMODE_AAL5 (2*0x04000) | ||
636 | #define PDUMODE_AAL5STREAM (3*0x04000) | ||
637 | vcc_txwriteptr = 0x38, /* TX Writeptr */ | ||
638 | #define TXWRITEPTR_GET_PTR(x) ((x)&0x1FFF) | ||
639 | vcc_txcbr_next = 0x3C /* # of next CBR VCI in ring */ | ||
640 | #define TXCBR_NEXT_BOZO (0x00008000) /* "bozo bit" */ | ||
641 | }; | ||
642 | |||
643 | #define CARDVCC_SIZE (0x40) | ||
644 | |||
645 | static inline bus_addr_t cardvcc_addr(const struct lanai_dev *lanai, | ||
646 | vci_t vci) | ||
647 | { | ||
648 | return sram_addr(lanai, vci * CARDVCC_SIZE); | ||
649 | } | ||
650 | |||
651 | static inline u32 cardvcc_read(const struct lanai_vcc *lvcc, | ||
652 | enum lanai_vcc_offset offset) | ||
653 | { | ||
654 | u32 val; | ||
655 | APRINTK(lvcc->vbase != NULL, "cardvcc_read: unbound vcc!\n"); | ||
656 | val= readl(lvcc->vbase + offset); | ||
657 | RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n", | ||
658 | lvcc->vci, (int) offset, val); | ||
659 | return val; | ||
660 | } | ||
661 | |||
662 | static inline void cardvcc_write(const struct lanai_vcc *lvcc, | ||
663 | u32 val, enum lanai_vcc_offset offset) | ||
664 | { | ||
665 | APRINTK(lvcc->vbase != NULL, "cardvcc_write: unbound vcc!\n"); | ||
666 | APRINTK((val & ~0xFFFF) == 0, | ||
667 | "cardvcc_write: bad val 0x%X (vci=%d, addr=0x%02X)\n", | ||
668 | (unsigned int) val, lvcc->vci, (unsigned int) offset); | ||
669 | RWDEBUG("VW vci=%04d 0x%02X > 0x%08X\n", | ||
670 | lvcc->vci, (unsigned int) offset, (unsigned int) val); | ||
671 | writel(val, lvcc->vbase + offset); | ||
672 | } | ||
673 | |||
674 | /* -------------------- COMPUTE SIZE OF AN AAL5 PDU: */ | ||
675 | |||
676 | /* How many bytes will an AAL5 PDU take to transmit - remember that: | ||
677 | * o we need to add 8 bytes for length, CPI, UU, and CRC | ||
678 | * o we need to round up to 48 bytes for cells | ||
679 | */ | ||
680 | static inline int aal5_size(int size) | ||
681 | { | ||
682 | int cells = (size + 8 + 47) / 48; | ||
683 | return cells * 48; | ||
684 | } | ||
685 | |||
686 | /* How many bytes can we send if we have "space" space, assuming we have | ||
687 | * to send full cells | ||
688 | */ | ||
689 | static inline int aal5_spacefor(int space) | ||
690 | { | ||
691 | int cells = space / 48; | ||
692 | return cells * 48; | ||
693 | } | ||
694 | |||
695 | /* -------------------- FREE AN ATM SKB: */ | ||
696 | |||
697 | static inline void lanai_free_skb(struct atm_vcc *atmvcc, struct sk_buff *skb) | ||
698 | { | ||
699 | if (atmvcc->pop != NULL) | ||
700 | atmvcc->pop(atmvcc, skb); | ||
701 | else | ||
702 | dev_kfree_skb_any(skb); | ||
703 | } | ||
704 | |||
705 | /* -------------------- TURN VCCS ON AND OFF: */ | ||
706 | |||
707 | static void host_vcc_start_rx(const struct lanai_vcc *lvcc) | ||
708 | { | ||
709 | u32 addr1; | ||
710 | if (lvcc->rx.atmvcc->qos.aal == ATM_AAL5) { | ||
711 | dma_addr_t dmaaddr = lvcc->rx.buf.dmaaddr; | ||
712 | cardvcc_write(lvcc, 0xFFFF, vcc_rxcrc1); | ||
713 | cardvcc_write(lvcc, 0xFFFF, vcc_rxcrc2); | ||
714 | cardvcc_write(lvcc, 0, vcc_rxwriteptr); | ||
715 | cardvcc_write(lvcc, 0, vcc_rxbufstart); | ||
716 | cardvcc_write(lvcc, 0, vcc_rxreadptr); | ||
717 | cardvcc_write(lvcc, (dmaaddr >> 16) & 0xFFFF, vcc_rxaddr2); | ||
718 | addr1 = ((dmaaddr >> 8) & 0xFF) | | ||
719 | RXADDR1_SET_SIZE(lanai_buf_size_cardorder(&lvcc->rx.buf))| | ||
720 | RXADDR1_SET_RMMODE(RMMODE_TRASH) | /* ??? */ | ||
721 | /* RXADDR1_OAM_PRESERVE | --- no OAM support yet */ | ||
722 | RXADDR1_SET_MODE(RXMODE_AAL5); | ||
723 | } else | ||
724 | addr1 = RXADDR1_SET_RMMODE(RMMODE_PRESERVE) | /* ??? */ | ||
725 | RXADDR1_OAM_PRESERVE | /* ??? */ | ||
726 | RXADDR1_SET_MODE(RXMODE_AAL0); | ||
727 | /* This one must be last! */ | ||
728 | cardvcc_write(lvcc, addr1, vcc_rxaddr1); | ||
729 | } | ||
730 | |||
731 | static void host_vcc_start_tx(const struct lanai_vcc *lvcc) | ||
732 | { | ||
733 | dma_addr_t dmaaddr = lvcc->tx.buf.dmaaddr; | ||
734 | cardvcc_write(lvcc, 0, vcc_txicg); | ||
735 | cardvcc_write(lvcc, 0xFFFF, vcc_txcrc1); | ||
736 | cardvcc_write(lvcc, 0xFFFF, vcc_txcrc2); | ||
737 | cardvcc_write(lvcc, 0, vcc_txreadptr); | ||
738 | cardvcc_write(lvcc, 0, vcc_txendptr); | ||
739 | cardvcc_write(lvcc, 0, vcc_txwriteptr); | ||
740 | cardvcc_write(lvcc, | ||
741 | (lvcc->tx.atmvcc->qos.txtp.traffic_class == ATM_CBR) ? | ||
742 | TXCBR_NEXT_BOZO | lvcc->vci : 0, vcc_txcbr_next); | ||
743 | cardvcc_write(lvcc, (dmaaddr >> 16) & 0xFFFF, vcc_txaddr2); | ||
744 | cardvcc_write(lvcc, | ||
745 | ((dmaaddr >> 8) & 0xFF) | | ||
746 | TXADDR1_SET_SIZE(lanai_buf_size_cardorder(&lvcc->tx.buf)), | ||
747 | vcc_txaddr1); | ||
748 | } | ||
749 | |||
750 | /* Shutdown receiving on card */ | ||
751 | static void lanai_shutdown_rx_vci(const struct lanai_vcc *lvcc) | ||
752 | { | ||
753 | if (lvcc->vbase == NULL) /* We were never bound to a VCI */ | ||
754 | return; | ||
755 | /* 15.1.1 - set to trashing, wait one cell time (15us) */ | ||
756 | cardvcc_write(lvcc, | ||
757 | RXADDR1_SET_RMMODE(RMMODE_TRASH) | | ||
758 | RXADDR1_SET_MODE(RXMODE_TRASH), vcc_rxaddr1); | ||
759 | udelay(15); | ||
760 | /* 15.1.2 - clear rest of entries */ | ||
761 | cardvcc_write(lvcc, 0, vcc_rxaddr2); | ||
762 | cardvcc_write(lvcc, 0, vcc_rxcrc1); | ||
763 | cardvcc_write(lvcc, 0, vcc_rxcrc2); | ||
764 | cardvcc_write(lvcc, 0, vcc_rxwriteptr); | ||
765 | cardvcc_write(lvcc, 0, vcc_rxbufstart); | ||
766 | cardvcc_write(lvcc, 0, vcc_rxreadptr); | ||
767 | } | ||
768 | |||
769 | /* Shutdown transmitting on card. | ||
770 | * Unfortunately the lanai needs us to wait until all the data | ||
771 | * drains out of the buffer before we can dealloc it, so this | ||
772 | * can take awhile -- up to 370ms for a full 128KB buffer | ||
773 | * assuming everone else is quiet. In theory the time is | ||
774 | * boundless if there's a CBR VCC holding things up. | ||
775 | */ | ||
776 | static void lanai_shutdown_tx_vci(struct lanai_dev *lanai, | ||
777 | struct lanai_vcc *lvcc) | ||
778 | { | ||
779 | struct sk_buff *skb; | ||
780 | unsigned long flags, timeout; | ||
781 | int read, write, lastread = -1; | ||
782 | APRINTK(!in_interrupt(), | ||
783 | "lanai_shutdown_tx_vci called w/o process context!\n"); | ||
784 | if (lvcc->vbase == NULL) /* We were never bound to a VCI */ | ||
785 | return; | ||
786 | /* 15.2.1 - wait for queue to drain */ | ||
787 | while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL) | ||
788 | lanai_free_skb(lvcc->tx.atmvcc, skb); | ||
789 | read_lock_irqsave(&vcc_sklist_lock, flags); | ||
790 | __clear_bit(lvcc->vci, lanai->backlog_vccs); | ||
791 | read_unlock_irqrestore(&vcc_sklist_lock, flags); | ||
792 | /* | ||
793 | * We need to wait for the VCC to drain but don't wait forever. We | ||
794 | * give each 1K of buffer size 1/128th of a second to clear out. | ||
795 | * TODO: maybe disable CBR if we're about to timeout? | ||
796 | */ | ||
797 | timeout = jiffies + | ||
798 | (((lanai_buf_size(&lvcc->tx.buf) / 1024) * HZ) >> 7); | ||
799 | write = TXWRITEPTR_GET_PTR(cardvcc_read(lvcc, vcc_txwriteptr)); | ||
800 | for (;;) { | ||
801 | read = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)); | ||
802 | if (read == write && /* Is TX buffer empty? */ | ||
803 | (lvcc->tx.atmvcc->qos.txtp.traffic_class != ATM_CBR || | ||
804 | (cardvcc_read(lvcc, vcc_txcbr_next) & | ||
805 | TXCBR_NEXT_BOZO) == 0)) | ||
806 | break; | ||
807 | if (read != lastread) { /* Has there been any progress? */ | ||
808 | lastread = read; | ||
809 | timeout += HZ / 10; | ||
810 | } | ||
811 | if (unlikely(time_after(jiffies, timeout))) { | ||
812 | printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on " | ||
813 | "backlog closing vci %d\n", | ||
814 | lvcc->tx.atmvcc->dev->number, lvcc->vci); | ||
815 | DPRINTK("read, write = %d, %d\n", read, write); | ||
816 | break; | ||
817 | } | ||
818 | msleep(40); | ||
819 | } | ||
820 | /* 15.2.2 - clear out all tx registers */ | ||
821 | cardvcc_write(lvcc, 0, vcc_txreadptr); | ||
822 | cardvcc_write(lvcc, 0, vcc_txwriteptr); | ||
823 | cardvcc_write(lvcc, 0, vcc_txendptr); | ||
824 | cardvcc_write(lvcc, 0, vcc_txcrc1); | ||
825 | cardvcc_write(lvcc, 0, vcc_txcrc2); | ||
826 | cardvcc_write(lvcc, 0, vcc_txaddr2); | ||
827 | cardvcc_write(lvcc, 0, vcc_txaddr1); | ||
828 | } | ||
829 | |||
830 | /* -------------------- MANAGING AAL0 RX BUFFER: */ | ||
831 | |||
832 | static inline int aal0_buffer_allocate(struct lanai_dev *lanai) | ||
833 | { | ||
834 | DPRINTK("aal0_buffer_allocate: allocating AAL0 RX buffer\n"); | ||
835 | lanai_buf_allocate(&lanai->aal0buf, AAL0_RX_BUFFER_SIZE, 80, | ||
836 | lanai->pci); | ||
837 | return (lanai->aal0buf.start == NULL) ? -ENOMEM : 0; | ||
838 | } | ||
839 | |||
840 | static inline void aal0_buffer_free(struct lanai_dev *lanai) | ||
841 | { | ||
842 | DPRINTK("aal0_buffer_allocate: freeing AAL0 RX buffer\n"); | ||
843 | lanai_buf_deallocate(&lanai->aal0buf, lanai->pci); | ||
844 | } | ||
845 | |||
846 | /* -------------------- EEPROM UTILITIES: */ | ||
847 | |||
848 | /* Offsets of data in the EEPROM */ | ||
849 | #define EEPROM_COPYRIGHT (0) | ||
850 | #define EEPROM_COPYRIGHT_LEN (44) | ||
851 | #define EEPROM_CHECKSUM (62) | ||
852 | #define EEPROM_CHECKSUM_REV (63) | ||
853 | #define EEPROM_MAC (64) | ||
854 | #define EEPROM_MAC_REV (70) | ||
855 | #define EEPROM_SERIAL (112) | ||
856 | #define EEPROM_SERIAL_REV (116) | ||
857 | #define EEPROM_MAGIC (120) | ||
858 | #define EEPROM_MAGIC_REV (124) | ||
859 | |||
860 | #define EEPROM_MAGIC_VALUE (0x5AB478D2) | ||
861 | |||
862 | #ifndef READ_EEPROM | ||
863 | |||
864 | /* Stub functions to use if EEPROM reading is disabled */ | ||
865 | static int __devinit eeprom_read(struct lanai_dev *lanai) | ||
866 | { | ||
867 | printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n", | ||
868 | lanai->number); | ||
869 | memset(&lanai->eeprom[EEPROM_MAC], 0, 6); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | static int __devinit eeprom_validate(struct lanai_dev *lanai) | ||
874 | { | ||
875 | lanai->serialno = 0; | ||
876 | lanai->magicno = EEPROM_MAGIC_VALUE; | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | #else /* READ_EEPROM */ | ||
881 | |||
882 | static int __devinit eeprom_read(struct lanai_dev *lanai) | ||
883 | { | ||
884 | int i, address; | ||
885 | u8 data; | ||
886 | u32 tmp; | ||
887 | #define set_config1(x) do { lanai->conf1 = x; conf1_write(lanai); \ | ||
888 | } while (0) | ||
889 | #define clock_h() set_config1(lanai->conf1 | CONFIG1_PROMCLK) | ||
890 | #define clock_l() set_config1(lanai->conf1 &~ CONFIG1_PROMCLK) | ||
891 | #define data_h() set_config1(lanai->conf1 | CONFIG1_PROMDATA) | ||
892 | #define data_l() set_config1(lanai->conf1 &~ CONFIG1_PROMDATA) | ||
893 | #define pre_read() do { data_h(); clock_h(); udelay(5); } while (0) | ||
894 | #define read_pin() (reg_read(lanai, Status_Reg) & STATUS_PROMDATA) | ||
895 | #define send_stop() do { data_l(); udelay(5); clock_h(); udelay(5); \ | ||
896 | data_h(); udelay(5); } while (0) | ||
897 | /* start with both clock and data high */ | ||
898 | data_h(); clock_h(); udelay(5); | ||
899 | for (address = 0; address < LANAI_EEPROM_SIZE; address++) { | ||
900 | data = (address << 1) | 1; /* Command=read + address */ | ||
901 | /* send start bit */ | ||
902 | data_l(); udelay(5); | ||
903 | clock_l(); udelay(5); | ||
904 | for (i = 128; i != 0; i >>= 1) { /* write command out */ | ||
905 | tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) | | ||
906 | (data & i) ? CONFIG1_PROMDATA : 0; | ||
907 | if (lanai->conf1 != tmp) { | ||
908 | set_config1(tmp); | ||
909 | udelay(5); /* Let new data settle */ | ||
910 | } | ||
911 | clock_h(); udelay(5); clock_l(); udelay(5); | ||
912 | } | ||
913 | /* look for ack */ | ||
914 | data_h(); clock_h(); udelay(5); | ||
915 | if (read_pin() != 0) | ||
916 | goto error; /* No ack seen */ | ||
917 | clock_l(); udelay(5); | ||
918 | /* read back result */ | ||
919 | for (data = 0, i = 7; i >= 0; i--) { | ||
920 | data_h(); clock_h(); udelay(5); | ||
921 | data = (data << 1) | !!read_pin(); | ||
922 | clock_l(); udelay(5); | ||
923 | } | ||
924 | /* look again for ack */ | ||
925 | data_h(); clock_h(); udelay(5); | ||
926 | if (read_pin() == 0) | ||
927 | goto error; /* Spurious ack */ | ||
928 | clock_l(); udelay(5); | ||
929 | send_stop(); | ||
930 | lanai->eeprom[address] = data; | ||
931 | DPRINTK("EEPROM 0x%04X %02X\n", | ||
932 | (unsigned int) address, (unsigned int) data); | ||
933 | } | ||
934 | return 0; | ||
935 | error: | ||
936 | clock_l(); udelay(5); /* finish read */ | ||
937 | send_stop(); | ||
938 | printk(KERN_ERR DEV_LABEL "(itf %d): error reading EEPROM byte %d\n", | ||
939 | lanai->number, address); | ||
940 | return -EIO; | ||
941 | #undef set_config1 | ||
942 | #undef clock_h | ||
943 | #undef clock_l | ||
944 | #undef data_h | ||
945 | #undef data_l | ||
946 | #undef pre_read | ||
947 | #undef read_pin | ||
948 | #undef send_stop | ||
949 | } | ||
950 | |||
951 | /* read a big-endian 4-byte value out of eeprom */ | ||
952 | static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address) | ||
953 | { | ||
954 | return be32_to_cpup((u32 *) (&lanai->eeprom[address])); | ||
955 | } | ||
956 | |||
957 | /* Checksum/validate EEPROM contents */ | ||
958 | static int __devinit eeprom_validate(struct lanai_dev *lanai) | ||
959 | { | ||
960 | int i, s; | ||
961 | u32 v; | ||
962 | const u8 *e = lanai->eeprom; | ||
963 | #ifdef DEBUG | ||
964 | /* First, see if we can get an ASCIIZ string out of the copyright */ | ||
965 | for (i = EEPROM_COPYRIGHT; | ||
966 | i < (EEPROM_COPYRIGHT + EEPROM_COPYRIGHT_LEN); i++) | ||
967 | if (e[i] < 0x20 || e[i] > 0x7E) | ||
968 | break; | ||
969 | if ( i != EEPROM_COPYRIGHT && | ||
970 | i != EEPROM_COPYRIGHT + EEPROM_COPYRIGHT_LEN && e[i] == '\0') | ||
971 | DPRINTK("eeprom: copyright = \"%s\"\n", | ||
972 | (char *) &e[EEPROM_COPYRIGHT]); | ||
973 | else | ||
974 | DPRINTK("eeprom: copyright not found\n"); | ||
975 | #endif | ||
976 | /* Validate checksum */ | ||
977 | for (i = s = 0; i < EEPROM_CHECKSUM; i++) | ||
978 | s += e[i]; | ||
979 | s &= 0xFF; | ||
980 | if (s != e[EEPROM_CHECKSUM]) { | ||
981 | printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM checksum bad " | ||
982 | "(wanted 0x%02X, got 0x%02X)\n", lanai->number, | ||
983 | (unsigned int) s, (unsigned int) e[EEPROM_CHECKSUM]); | ||
984 | return -EIO; | ||
985 | } | ||
986 | s ^= 0xFF; | ||
987 | if (s != e[EEPROM_CHECKSUM_REV]) { | ||
988 | printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM inverse checksum " | ||
989 | "bad (wanted 0x%02X, got 0x%02X)\n", lanai->number, | ||
990 | (unsigned int) s, (unsigned int) e[EEPROM_CHECKSUM_REV]); | ||
991 | return -EIO; | ||
992 | } | ||
993 | /* Verify MAC address */ | ||
994 | for (i = 0; i < 6; i++) | ||
995 | if ((e[EEPROM_MAC + i] ^ e[EEPROM_MAC_REV + i]) != 0xFF) { | ||
996 | printk(KERN_ERR DEV_LABEL | ||
997 | "(itf %d) : EEPROM MAC addresses don't match " | ||
998 | "(0x%02X, inverse 0x%02X)\n", lanai->number, | ||
999 | (unsigned int) e[EEPROM_MAC + i], | ||
1000 | (unsigned int) e[EEPROM_MAC_REV + i]); | ||
1001 | return -EIO; | ||
1002 | } | ||
1003 | DPRINTK("eeprom: MAC address = %02X:%02X:%02X:%02X:%02X:%02X\n", | ||
1004 | e[EEPROM_MAC + 0], e[EEPROM_MAC + 1], e[EEPROM_MAC + 2], | ||
1005 | e[EEPROM_MAC + 3], e[EEPROM_MAC + 4], e[EEPROM_MAC + 5]); | ||
1006 | /* Verify serial number */ | ||
1007 | lanai->serialno = eeprom_be4(lanai, EEPROM_SERIAL); | ||
1008 | v = eeprom_be4(lanai, EEPROM_SERIAL_REV); | ||
1009 | if ((lanai->serialno ^ v) != 0xFFFFFFFF) { | ||
1010 | printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM serial numbers " | ||
1011 | "don't match (0x%08X, inverse 0x%08X)\n", lanai->number, | ||
1012 | (unsigned int) lanai->serialno, (unsigned int) v); | ||
1013 | return -EIO; | ||
1014 | } | ||
1015 | DPRINTK("eeprom: Serial number = %d\n", (unsigned int) lanai->serialno); | ||
1016 | /* Verify magic number */ | ||
1017 | lanai->magicno = eeprom_be4(lanai, EEPROM_MAGIC); | ||
1018 | v = eeprom_be4(lanai, EEPROM_MAGIC_REV); | ||
1019 | if ((lanai->magicno ^ v) != 0xFFFFFFFF) { | ||
1020 | printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM magic numbers " | ||
1021 | "don't match (0x%08X, inverse 0x%08X)\n", lanai->number, | ||
1022 | lanai->magicno, v); | ||
1023 | return -EIO; | ||
1024 | } | ||
1025 | DPRINTK("eeprom: Magic number = 0x%08X\n", lanai->magicno); | ||
1026 | if (lanai->magicno != EEPROM_MAGIC_VALUE) | ||
1027 | printk(KERN_WARNING DEV_LABEL "(itf %d): warning - EEPROM " | ||
1028 | "magic not what expected (got 0x%08X, not 0x%08X)\n", | ||
1029 | lanai->number, (unsigned int) lanai->magicno, | ||
1030 | (unsigned int) EEPROM_MAGIC_VALUE); | ||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | #endif /* READ_EEPROM */ | ||
1035 | |||
1036 | static inline const u8 *eeprom_mac(const struct lanai_dev *lanai) | ||
1037 | { | ||
1038 | return &lanai->eeprom[EEPROM_MAC]; | ||
1039 | } | ||
1040 | |||
1041 | /* -------------------- INTERRUPT HANDLING UTILITIES: */ | ||
1042 | |||
1043 | /* Interrupt types */ | ||
1044 | #define INT_STATS (0x00000002) /* Statistics counter overflow */ | ||
1045 | #define INT_SOOL (0x00000004) /* SOOL changed state */ | ||
1046 | #define INT_LOCD (0x00000008) /* LOCD changed state */ | ||
1047 | #define INT_LED (0x00000010) /* LED (HAPPI) changed state */ | ||
1048 | #define INT_GPIN (0x00000020) /* GPIN changed state */ | ||
1049 | #define INT_PING (0x00000040) /* PING_COUNT fulfilled */ | ||
1050 | #define INT_WAKE (0x00000080) /* Lanai wants bus */ | ||
1051 | #define INT_CBR0 (0x00000100) /* CBR sched hit VCI 0 */ | ||
1052 | #define INT_LOCK (0x00000200) /* Service list overflow */ | ||
1053 | #define INT_MISMATCH (0x00000400) /* TX magic list mismatch */ | ||
1054 | #define INT_AAL0_STR (0x00000800) /* Non-AAL5 buffer half filled */ | ||
1055 | #define INT_AAL0 (0x00001000) /* Non-AAL5 data available */ | ||
1056 | #define INT_SERVICE (0x00002000) /* Service list entries available */ | ||
1057 | #define INT_TABORTSENT (0x00004000) /* Target abort sent by lanai */ | ||
1058 | #define INT_TABORTBM (0x00008000) /* Abort rcv'd as bus master */ | ||
1059 | #define INT_TIMEOUTBM (0x00010000) /* No response to bus master */ | ||
1060 | #define INT_PCIPARITY (0x00020000) /* Parity error on PCI */ | ||
1061 | |||
1062 | /* Sets of the above */ | ||
1063 | #define INT_ALL (0x0003FFFE) /* All interrupts */ | ||
1064 | #define INT_STATUS (0x0000003C) /* Some status pin changed */ | ||
1065 | #define INT_DMASHUT (0x00038000) /* DMA engine got shut down */ | ||
1066 | #define INT_SEGSHUT (0x00000700) /* Segmentation got shut down */ | ||
1067 | |||
1068 | static inline u32 intr_pending(const struct lanai_dev *lanai) | ||
1069 | { | ||
1070 | return reg_read(lanai, IntStatusMasked_Reg); | ||
1071 | } | ||
1072 | |||
1073 | static inline void intr_enable(const struct lanai_dev *lanai, u32 i) | ||
1074 | { | ||
1075 | reg_write(lanai, i, IntControlEna_Reg); | ||
1076 | } | ||
1077 | |||
1078 | static inline void intr_disable(const struct lanai_dev *lanai, u32 i) | ||
1079 | { | ||
1080 | reg_write(lanai, i, IntControlDis_Reg); | ||
1081 | } | ||
1082 | |||
1083 | /* -------------------- CARD/PCI STATUS: */ | ||
1084 | |||
1085 | static void status_message(int itf, const char *name, int status) | ||
1086 | { | ||
1087 | static const char *onoff[2] = { "off to on", "on to off" }; | ||
1088 | printk(KERN_INFO DEV_LABEL "(itf %d): %s changed from %s\n", | ||
1089 | itf, name, onoff[!status]); | ||
1090 | } | ||
1091 | |||
1092 | static void lanai_check_status(struct lanai_dev *lanai) | ||
1093 | { | ||
1094 | u32 new = reg_read(lanai, Status_Reg); | ||
1095 | u32 changes = new ^ lanai->status; | ||
1096 | lanai->status = new; | ||
1097 | #define e(flag, name) \ | ||
1098 | if (changes & flag) \ | ||
1099 | status_message(lanai->number, name, new & flag) | ||
1100 | e(STATUS_SOOL, "SOOL"); | ||
1101 | e(STATUS_LOCD, "LOCD"); | ||
1102 | e(STATUS_LED, "LED"); | ||
1103 | e(STATUS_GPIN, "GPIN"); | ||
1104 | #undef e | ||
1105 | } | ||
1106 | |||
1107 | static void pcistatus_got(int itf, const char *name) | ||
1108 | { | ||
1109 | printk(KERN_INFO DEV_LABEL "(itf %d): PCI got %s error\n", itf, name); | ||
1110 | } | ||
1111 | |||
1112 | static void pcistatus_check(struct lanai_dev *lanai, int clearonly) | ||
1113 | { | ||
1114 | u16 s; | ||
1115 | int result; | ||
1116 | result = pci_read_config_word(lanai->pci, PCI_STATUS, &s); | ||
1117 | if (result != PCIBIOS_SUCCESSFUL) { | ||
1118 | printk(KERN_ERR DEV_LABEL "(itf %d): can't read PCI_STATUS: " | ||
1119 | "%d\n", lanai->number, result); | ||
1120 | return; | ||
1121 | } | ||
1122 | s &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | | ||
1123 | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT | | ||
1124 | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_PARITY; | ||
1125 | if (s == 0) | ||
1126 | return; | ||
1127 | result = pci_write_config_word(lanai->pci, PCI_STATUS, s); | ||
1128 | if (result != PCIBIOS_SUCCESSFUL) | ||
1129 | printk(KERN_ERR DEV_LABEL "(itf %d): can't write PCI_STATUS: " | ||
1130 | "%d\n", lanai->number, result); | ||
1131 | if (clearonly) | ||
1132 | return; | ||
1133 | #define e(flag, name, stat) \ | ||
1134 | if (s & flag) { \ | ||
1135 | pcistatus_got(lanai->number, name); \ | ||
1136 | ++lanai->stats.pcierr_##stat; \ | ||
1137 | } | ||
1138 | e(PCI_STATUS_DETECTED_PARITY, "parity", parity_detect); | ||
1139 | e(PCI_STATUS_SIG_SYSTEM_ERROR, "signalled system", serr_set); | ||
1140 | e(PCI_STATUS_REC_MASTER_ABORT, "master", master_abort); | ||
1141 | e(PCI_STATUS_REC_TARGET_ABORT, "master target", m_target_abort); | ||
1142 | e(PCI_STATUS_SIG_TARGET_ABORT, "slave", s_target_abort); | ||
1143 | e(PCI_STATUS_PARITY, "master parity", master_parity); | ||
1144 | #undef e | ||
1145 | } | ||
1146 | |||
1147 | /* -------------------- VCC TX BUFFER UTILITIES: */ | ||
1148 | |||
1149 | /* space left in tx buffer in bytes */ | ||
1150 | static inline int vcc_tx_space(const struct lanai_vcc *lvcc, int endptr) | ||
1151 | { | ||
1152 | int r; | ||
1153 | r = endptr * 16; | ||
1154 | r -= ((unsigned long) lvcc->tx.buf.ptr) - | ||
1155 | ((unsigned long) lvcc->tx.buf.start); | ||
1156 | r -= 16; /* Leave "bubble" - if start==end it looks empty */ | ||
1157 | if (r < 0) | ||
1158 | r += lanai_buf_size(&lvcc->tx.buf); | ||
1159 | return r; | ||
1160 | } | ||
1161 | |||
1162 | /* test if VCC is currently backlogged */ | ||
1163 | static inline int vcc_is_backlogged(/*const*/ struct lanai_vcc *lvcc) | ||
1164 | { | ||
1165 | return !skb_queue_empty(&lvcc->tx.backlog); | ||
1166 | } | ||
1167 | |||
1168 | /* Bit fields in the segmentation buffer descriptor */ | ||
1169 | #define DESCRIPTOR_MAGIC (0xD0000000) | ||
1170 | #define DESCRIPTOR_AAL5 (0x00008000) | ||
1171 | #define DESCRIPTOR_AAL5_STREAM (0x00004000) | ||
1172 | #define DESCRIPTOR_CLP (0x00002000) | ||
1173 | |||
1174 | /* Add 32-bit descriptor with its padding */ | ||
1175 | static inline void vcc_tx_add_aal5_descriptor(struct lanai_vcc *lvcc, | ||
1176 | u32 flags, int len) | ||
1177 | { | ||
1178 | int pos; | ||
1179 | APRINTK((((unsigned long) lvcc->tx.buf.ptr) & 15) == 0, | ||
1180 | "vcc_tx_add_aal5_descriptor: bad ptr=%p\n", lvcc->tx.buf.ptr); | ||
1181 | lvcc->tx.buf.ptr += 4; /* Hope the values REALLY don't matter */ | ||
1182 | pos = ((unsigned char *) lvcc->tx.buf.ptr) - | ||
1183 | (unsigned char *) lvcc->tx.buf.start; | ||
1184 | APRINTK((pos & ~0x0001FFF0) == 0, | ||
1185 | "vcc_tx_add_aal5_descriptor: bad pos (%d) before, vci=%d, " | ||
1186 | "start,ptr,end=%p,%p,%p\n", pos, lvcc->vci, | ||
1187 | lvcc->tx.buf.start, lvcc->tx.buf.ptr, lvcc->tx.buf.end); | ||
1188 | pos = (pos + len) & (lanai_buf_size(&lvcc->tx.buf) - 1); | ||
1189 | APRINTK((pos & ~0x0001FFF0) == 0, | ||
1190 | "vcc_tx_add_aal5_descriptor: bad pos (%d) after, vci=%d, " | ||
1191 | "start,ptr,end=%p,%p,%p\n", pos, lvcc->vci, | ||
1192 | lvcc->tx.buf.start, lvcc->tx.buf.ptr, lvcc->tx.buf.end); | ||
1193 | lvcc->tx.buf.ptr[-1] = | ||
1194 | cpu_to_le32(DESCRIPTOR_MAGIC | DESCRIPTOR_AAL5 | | ||
1195 | ((lvcc->tx.atmvcc->atm_options & ATM_ATMOPT_CLP) ? | ||
1196 | DESCRIPTOR_CLP : 0) | flags | pos >> 4); | ||
1197 | if (lvcc->tx.buf.ptr >= lvcc->tx.buf.end) | ||
1198 | lvcc->tx.buf.ptr = lvcc->tx.buf.start; | ||
1199 | } | ||
1200 | |||
1201 | /* Add 32-bit AAL5 trailer and leave room for its CRC */ | ||
1202 | static inline void vcc_tx_add_aal5_trailer(struct lanai_vcc *lvcc, | ||
1203 | int len, int cpi, int uu) | ||
1204 | { | ||
1205 | APRINTK((((unsigned long) lvcc->tx.buf.ptr) & 15) == 8, | ||
1206 | "vcc_tx_add_aal5_trailer: bad ptr=%p\n", lvcc->tx.buf.ptr); | ||
1207 | lvcc->tx.buf.ptr += 2; | ||
1208 | lvcc->tx.buf.ptr[-2] = cpu_to_be32((uu << 24) | (cpi << 16) | len); | ||
1209 | if (lvcc->tx.buf.ptr >= lvcc->tx.buf.end) | ||
1210 | lvcc->tx.buf.ptr = lvcc->tx.buf.start; | ||
1211 | } | ||
1212 | |||
1213 | static inline void vcc_tx_memcpy(struct lanai_vcc *lvcc, | ||
1214 | const unsigned char *src, int n) | ||
1215 | { | ||
1216 | unsigned char *e; | ||
1217 | int m; | ||
1218 | e = ((unsigned char *) lvcc->tx.buf.ptr) + n; | ||
1219 | m = e - (unsigned char *) lvcc->tx.buf.end; | ||
1220 | if (m < 0) | ||
1221 | m = 0; | ||
1222 | memcpy(lvcc->tx.buf.ptr, src, n - m); | ||
1223 | if (m != 0) { | ||
1224 | memcpy(lvcc->tx.buf.start, src + n - m, m); | ||
1225 | e = ((unsigned char *) lvcc->tx.buf.start) + m; | ||
1226 | } | ||
1227 | lvcc->tx.buf.ptr = (u32 *) e; | ||
1228 | } | ||
1229 | |||
1230 | static inline void vcc_tx_memzero(struct lanai_vcc *lvcc, int n) | ||
1231 | { | ||
1232 | unsigned char *e; | ||
1233 | int m; | ||
1234 | if (n == 0) | ||
1235 | return; | ||
1236 | e = ((unsigned char *) lvcc->tx.buf.ptr) + n; | ||
1237 | m = e - (unsigned char *) lvcc->tx.buf.end; | ||
1238 | if (m < 0) | ||
1239 | m = 0; | ||
1240 | memset(lvcc->tx.buf.ptr, 0, n - m); | ||
1241 | if (m != 0) { | ||
1242 | memset(lvcc->tx.buf.start, 0, m); | ||
1243 | e = ((unsigned char *) lvcc->tx.buf.start) + m; | ||
1244 | } | ||
1245 | lvcc->tx.buf.ptr = (u32 *) e; | ||
1246 | } | ||
1247 | |||
1248 | /* Update "butt" register to specify new WritePtr */ | ||
1249 | static inline void lanai_endtx(struct lanai_dev *lanai, | ||
1250 | const struct lanai_vcc *lvcc) | ||
1251 | { | ||
1252 | int i, ptr = ((unsigned char *) lvcc->tx.buf.ptr) - | ||
1253 | (unsigned char *) lvcc->tx.buf.start; | ||
1254 | APRINTK((ptr & ~0x0001FFF0) == 0, | ||
1255 | "lanai_endtx: bad ptr (%d), vci=%d, start,ptr,end=%p,%p,%p\n", | ||
1256 | ptr, lvcc->vci, lvcc->tx.buf.start, lvcc->tx.buf.ptr, | ||
1257 | lvcc->tx.buf.end); | ||
1258 | |||
1259 | /* | ||
1260 | * Since the "butt register" is a shared resounce on the card we | ||
1261 | * serialize all accesses to it through this spinlock. This is | ||
1262 | * mostly just paranoia sicne the register is rarely "busy" anyway | ||
1263 | * but is needed for correctness. | ||
1264 | */ | ||
1265 | spin_lock(&lanai->endtxlock); | ||
1266 | /* | ||
1267 | * We need to check if the "butt busy" bit is set before | ||
1268 | * updating the butt register. In theory this should | ||
1269 | * never happen because the ATM card is plenty fast at | ||
1270 | * updating the register. Still, we should make sure | ||
1271 | */ | ||
1272 | for (i = 0; reg_read(lanai, Status_Reg) & STATUS_BUTTBUSY; i++) { | ||
1273 | if (unlikely(i > 50)) { | ||
1274 | printk(KERN_ERR DEV_LABEL "(itf %d): butt register " | ||
1275 | "always busy!\n", lanai->number); | ||
1276 | break; | ||
1277 | } | ||
1278 | udelay(5); | ||
1279 | } | ||
1280 | /* | ||
1281 | * Before we tall the card to start work we need to be sure 100% of | ||
1282 | * the info in the service buffer has been written before we tell | ||
1283 | * the card about it | ||
1284 | */ | ||
1285 | wmb(); | ||
1286 | reg_write(lanai, (ptr << 12) | lvcc->vci, Butt_Reg); | ||
1287 | spin_unlock(&lanai->endtxlock); | ||
1288 | } | ||
1289 | |||
1290 | /* | ||
1291 | * Add one AAL5 PDU to lvcc's transmit buffer. Caller garauntees there's | ||
1292 | * space available. "pdusize" is the number of bytes the PDU will take | ||
1293 | */ | ||
1294 | static void lanai_send_one_aal5(struct lanai_dev *lanai, | ||
1295 | struct lanai_vcc *lvcc, struct sk_buff *skb, int pdusize) | ||
1296 | { | ||
1297 | int pad; | ||
1298 | APRINTK(pdusize == aal5_size(skb->len), | ||
1299 | "lanai_send_one_aal5: wrong size packet (%d != %d)\n", | ||
1300 | pdusize, aal5_size(skb->len)); | ||
1301 | vcc_tx_add_aal5_descriptor(lvcc, 0, pdusize); | ||
1302 | pad = pdusize - skb->len - 8; | ||
1303 | APRINTK(pad >= 0, "pad is negative (%d)\n", pad); | ||
1304 | APRINTK(pad < 48, "pad is too big (%d)\n", pad); | ||
1305 | vcc_tx_memcpy(lvcc, skb->data, skb->len); | ||
1306 | vcc_tx_memzero(lvcc, pad); | ||
1307 | vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0); | ||
1308 | lanai_endtx(lanai, lvcc); | ||
1309 | lanai_free_skb(lvcc->tx.atmvcc, skb); | ||
1310 | atomic_inc(&lvcc->tx.atmvcc->stats->tx); | ||
1311 | } | ||
1312 | |||
1313 | /* Try to fill the buffer - don't call unless there is backlog */ | ||
1314 | static void vcc_tx_unqueue_aal5(struct lanai_dev *lanai, | ||
1315 | struct lanai_vcc *lvcc, int endptr) | ||
1316 | { | ||
1317 | int n; | ||
1318 | struct sk_buff *skb; | ||
1319 | int space = vcc_tx_space(lvcc, endptr); | ||
1320 | APRINTK(vcc_is_backlogged(lvcc), | ||
1321 | "vcc_tx_unqueue() called with empty backlog (vci=%d)\n", | ||
1322 | lvcc->vci); | ||
1323 | while (space >= 64) { | ||
1324 | skb = skb_dequeue(&lvcc->tx.backlog); | ||
1325 | if (skb == NULL) | ||
1326 | goto no_backlog; | ||
1327 | n = aal5_size(skb->len); | ||
1328 | if (n + 16 > space) { | ||
1329 | /* No room for this packet - put it back on queue */ | ||
1330 | skb_queue_head(&lvcc->tx.backlog, skb); | ||
1331 | return; | ||
1332 | } | ||
1333 | lanai_send_one_aal5(lanai, lvcc, skb, n); | ||
1334 | space -= n + 16; | ||
1335 | } | ||
1336 | if (!vcc_is_backlogged(lvcc)) { | ||
1337 | no_backlog: | ||
1338 | __clear_bit(lvcc->vci, lanai->backlog_vccs); | ||
1339 | } | ||
1340 | } | ||
1341 | |||
1342 | /* Given an skb that we want to transmit either send it now or queue */ | ||
1343 | static void vcc_tx_aal5(struct lanai_dev *lanai, struct lanai_vcc *lvcc, | ||
1344 | struct sk_buff *skb) | ||
1345 | { | ||
1346 | int space, n; | ||
1347 | if (vcc_is_backlogged(lvcc)) /* Already backlogged */ | ||
1348 | goto queue_it; | ||
1349 | space = vcc_tx_space(lvcc, | ||
1350 | TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr))); | ||
1351 | n = aal5_size(skb->len); | ||
1352 | APRINTK(n + 16 >= 64, "vcc_tx_aal5: n too small (%d)\n", n); | ||
1353 | if (space < n + 16) { /* No space for this PDU */ | ||
1354 | __set_bit(lvcc->vci, lanai->backlog_vccs); | ||
1355 | queue_it: | ||
1356 | skb_queue_tail(&lvcc->tx.backlog, skb); | ||
1357 | return; | ||
1358 | } | ||
1359 | lanai_send_one_aal5(lanai, lvcc, skb, n); | ||
1360 | } | ||
1361 | |||
1362 | static void vcc_tx_unqueue_aal0(struct lanai_dev *lanai, | ||
1363 | struct lanai_vcc *lvcc, int endptr) | ||
1364 | { | ||
1365 | printk(KERN_INFO DEV_LABEL | ||
1366 | ": vcc_tx_unqueue_aal0: not implemented\n"); | ||
1367 | } | ||
1368 | |||
1369 | static void vcc_tx_aal0(struct lanai_dev *lanai, struct lanai_vcc *lvcc, | ||
1370 | struct sk_buff *skb) | ||
1371 | { | ||
1372 | printk(KERN_INFO DEV_LABEL ": vcc_tx_aal0: not implemented\n"); | ||
1373 | /* Remember to increment lvcc->tx.atmvcc->stats->tx */ | ||
1374 | lanai_free_skb(lvcc->tx.atmvcc, skb); | ||
1375 | } | ||
1376 | |||
1377 | /* -------------------- VCC RX BUFFER UTILITIES: */ | ||
1378 | |||
1379 | /* unlike the _tx_ cousins, this doesn't update ptr */ | ||
1380 | static inline void vcc_rx_memcpy(unsigned char *dest, | ||
1381 | const struct lanai_vcc *lvcc, int n) | ||
1382 | { | ||
1383 | int m = ((const unsigned char *) lvcc->rx.buf.ptr) + n - | ||
1384 | ((const unsigned char *) (lvcc->rx.buf.end)); | ||
1385 | if (m < 0) | ||
1386 | m = 0; | ||
1387 | memcpy(dest, lvcc->rx.buf.ptr, n - m); | ||
1388 | memcpy(dest + n - m, lvcc->rx.buf.start, m); | ||
1389 | /* Make sure that these copies don't get reordered */ | ||
1390 | barrier(); | ||
1391 | } | ||
1392 | |||
1393 | /* Receive AAL5 data on a VCC with a particular endptr */ | ||
1394 | static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr) | ||
1395 | { | ||
1396 | int size; | ||
1397 | struct sk_buff *skb; | ||
1398 | /*const*/ u32 *x, *end = &lvcc->rx.buf.start[endptr * 4]; | ||
1399 | int n = ((unsigned long) end) - ((unsigned long) lvcc->rx.buf.ptr); | ||
1400 | if (n < 0) | ||
1401 | n += lanai_buf_size(&lvcc->rx.buf); | ||
1402 | APRINTK(n >= 0 && n < lanai_buf_size(&lvcc->rx.buf) && !(n & 15), | ||
1403 | "vcc_rx_aal5: n out of range (%d/%Zu)\n", | ||
1404 | n, lanai_buf_size(&lvcc->rx.buf)); | ||
1405 | /* Recover the second-to-last word to get true pdu length */ | ||
1406 | if ((x = &end[-2]) < lvcc->rx.buf.start) | ||
1407 | x = &lvcc->rx.buf.end[-2]; | ||
1408 | /* | ||
1409 | * Before we actually read from the buffer, make sure the memory | ||
1410 | * changes have arrived | ||
1411 | */ | ||
1412 | rmb(); | ||
1413 | size = be32_to_cpup(x) & 0xffff; | ||
1414 | if (unlikely(n != aal5_size(size))) { | ||
1415 | /* Make sure size matches padding */ | ||
1416 | printk(KERN_INFO DEV_LABEL "(itf %d): Got bad AAL5 length " | ||
1417 | "on vci=%d - size=%d n=%d\n", | ||
1418 | lvcc->rx.atmvcc->dev->number, lvcc->vci, size, n); | ||
1419 | lvcc->stats.x.aal5.rx_badlen++; | ||
1420 | goto out; | ||
1421 | } | ||
1422 | skb = atm_alloc_charge(lvcc->rx.atmvcc, size, GFP_ATOMIC); | ||
1423 | if (unlikely(skb == NULL)) { | ||
1424 | lvcc->stats.rx_nomem++; | ||
1425 | goto out; | ||
1426 | } | ||
1427 | skb_put(skb, size); | ||
1428 | vcc_rx_memcpy(skb->data, lvcc, size); | ||
1429 | ATM_SKB(skb)->vcc = lvcc->rx.atmvcc; | ||
1430 | do_gettimeofday(&skb->stamp); | ||
1431 | lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb); | ||
1432 | atomic_inc(&lvcc->rx.atmvcc->stats->rx); | ||
1433 | out: | ||
1434 | lvcc->rx.buf.ptr = end; | ||
1435 | cardvcc_write(lvcc, endptr, vcc_rxreadptr); | ||
1436 | } | ||
1437 | |||
1438 | static void vcc_rx_aal0(struct lanai_dev *lanai) | ||
1439 | { | ||
1440 | printk(KERN_INFO DEV_LABEL ": vcc_rx_aal0: not implemented\n"); | ||
1441 | /* Remember to get read_lock(&vcc_sklist_lock) while looking up VC */ | ||
1442 | /* Remember to increment lvcc->rx.atmvcc->stats->rx */ | ||
1443 | } | ||
1444 | |||
1445 | /* -------------------- MANAGING HOST-BASED VCC TABLE: */ | ||
1446 | |||
1447 | /* Decide whether to use vmalloc or get_zeroed_page for VCC table */ | ||
1448 | #if (NUM_VCI * BITS_PER_LONG) <= PAGE_SIZE | ||
1449 | #define VCCTABLE_GETFREEPAGE | ||
1450 | #else | ||
1451 | #include <linux/vmalloc.h> | ||
1452 | #endif | ||
1453 | |||
1454 | static int __devinit vcc_table_allocate(struct lanai_dev *lanai) | ||
1455 | { | ||
1456 | #ifdef VCCTABLE_GETFREEPAGE | ||
1457 | APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE, | ||
1458 | "vcc table > PAGE_SIZE!"); | ||
1459 | lanai->vccs = (struct lanai_vcc **) get_zeroed_page(GFP_KERNEL); | ||
1460 | return (lanai->vccs == NULL) ? -ENOMEM : 0; | ||
1461 | #else | ||
1462 | int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *); | ||
1463 | lanai->vccs = (struct lanai_vcc **) vmalloc(bytes); | ||
1464 | if (unlikely(lanai->vccs == NULL)) | ||
1465 | return -ENOMEM; | ||
1466 | memset(lanai->vccs, 0, bytes); | ||
1467 | return 0; | ||
1468 | #endif | ||
1469 | } | ||
1470 | |||
1471 | static inline void vcc_table_deallocate(const struct lanai_dev *lanai) | ||
1472 | { | ||
1473 | #ifdef VCCTABLE_GETFREEPAGE | ||
1474 | free_page((unsigned long) lanai->vccs); | ||
1475 | #else | ||
1476 | vfree(lanai->vccs); | ||
1477 | #endif | ||
1478 | } | ||
1479 | |||
1480 | /* Allocate a fresh lanai_vcc, with the appropriate things cleared */ | ||
1481 | static inline struct lanai_vcc *new_lanai_vcc(void) | ||
1482 | { | ||
1483 | struct lanai_vcc *lvcc; | ||
1484 | lvcc = (struct lanai_vcc *) kmalloc(sizeof(*lvcc), GFP_KERNEL); | ||
1485 | if (likely(lvcc != NULL)) { | ||
1486 | lvcc->vbase = NULL; | ||
1487 | lvcc->rx.atmvcc = lvcc->tx.atmvcc = NULL; | ||
1488 | lvcc->nref = 0; | ||
1489 | memset(&lvcc->stats, 0, sizeof lvcc->stats); | ||
1490 | lvcc->rx.buf.start = lvcc->tx.buf.start = NULL; | ||
1491 | skb_queue_head_init(&lvcc->tx.backlog); | ||
1492 | #ifdef DEBUG | ||
1493 | lvcc->tx.unqueue = NULL; | ||
1494 | lvcc->vci = -1; | ||
1495 | #endif | ||
1496 | } | ||
1497 | return lvcc; | ||
1498 | } | ||
1499 | |||
1500 | static int lanai_get_sized_buffer(struct lanai_dev *lanai, | ||
1501 | struct lanai_buffer *buf, int max_sdu, int multiplier, | ||
1502 | const char *name) | ||
1503 | { | ||
1504 | int size; | ||
1505 | if (unlikely(max_sdu < 1)) | ||
1506 | max_sdu = 1; | ||
1507 | max_sdu = aal5_size(max_sdu); | ||
1508 | size = (max_sdu + 16) * multiplier + 16; | ||
1509 | lanai_buf_allocate(buf, size, max_sdu + 32, lanai->pci); | ||
1510 | if (unlikely(buf->start == NULL)) | ||
1511 | return -ENOMEM; | ||
1512 | if (unlikely(lanai_buf_size(buf) < size)) | ||
1513 | printk(KERN_WARNING DEV_LABEL "(itf %d): wanted %d bytes " | ||
1514 | "for %s buffer, got only %Zu\n", lanai->number, size, | ||
1515 | name, lanai_buf_size(buf)); | ||
1516 | DPRINTK("Allocated %Zu byte %s buffer\n", lanai_buf_size(buf), name); | ||
1517 | return 0; | ||
1518 | } | ||
1519 | |||
1520 | /* Setup a RX buffer for a currently unbound AAL5 vci */ | ||
1521 | static inline int lanai_setup_rx_vci_aal5(struct lanai_dev *lanai, | ||
1522 | struct lanai_vcc *lvcc, const struct atm_qos *qos) | ||
1523 | { | ||
1524 | return lanai_get_sized_buffer(lanai, &lvcc->rx.buf, | ||
1525 | qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, "RX"); | ||
1526 | } | ||
1527 | |||
1528 | /* Setup a TX buffer for a currently unbound AAL5 vci */ | ||
1529 | static int lanai_setup_tx_vci(struct lanai_dev *lanai, struct lanai_vcc *lvcc, | ||
1530 | const struct atm_qos *qos) | ||
1531 | { | ||
1532 | int max_sdu, multiplier; | ||
1533 | if (qos->aal == ATM_AAL0) { | ||
1534 | lvcc->tx.unqueue = vcc_tx_unqueue_aal0; | ||
1535 | max_sdu = ATM_CELL_SIZE - 1; | ||
1536 | multiplier = AAL0_TX_MULTIPLIER; | ||
1537 | } else { | ||
1538 | lvcc->tx.unqueue = vcc_tx_unqueue_aal5; | ||
1539 | max_sdu = qos->txtp.max_sdu; | ||
1540 | multiplier = AAL5_TX_MULTIPLIER; | ||
1541 | } | ||
1542 | return lanai_get_sized_buffer(lanai, &lvcc->tx.buf, max_sdu, | ||
1543 | multiplier, "TX"); | ||
1544 | } | ||
1545 | |||
1546 | static inline void host_vcc_bind(struct lanai_dev *lanai, | ||
1547 | struct lanai_vcc *lvcc, vci_t vci) | ||
1548 | { | ||
1549 | if (lvcc->vbase != NULL) | ||
1550 | return; /* We already were bound in the other direction */ | ||
1551 | DPRINTK("Binding vci %d\n", vci); | ||
1552 | #ifdef USE_POWERDOWN | ||
1553 | if (lanai->nbound++ == 0) { | ||
1554 | DPRINTK("Coming out of powerdown\n"); | ||
1555 | lanai->conf1 &= ~CONFIG1_POWERDOWN; | ||
1556 | conf1_write(lanai); | ||
1557 | conf2_write(lanai); | ||
1558 | } | ||
1559 | #endif | ||
1560 | lvcc->vbase = cardvcc_addr(lanai, vci); | ||
1561 | lanai->vccs[lvcc->vci = vci] = lvcc; | ||
1562 | } | ||
1563 | |||
1564 | static inline void host_vcc_unbind(struct lanai_dev *lanai, | ||
1565 | struct lanai_vcc *lvcc) | ||
1566 | { | ||
1567 | if (lvcc->vbase == NULL) | ||
1568 | return; /* This vcc was never bound */ | ||
1569 | DPRINTK("Unbinding vci %d\n", lvcc->vci); | ||
1570 | lvcc->vbase = NULL; | ||
1571 | lanai->vccs[lvcc->vci] = NULL; | ||
1572 | #ifdef USE_POWERDOWN | ||
1573 | if (--lanai->nbound == 0) { | ||
1574 | DPRINTK("Going into powerdown\n"); | ||
1575 | lanai->conf1 |= CONFIG1_POWERDOWN; | ||
1576 | conf1_write(lanai); | ||
1577 | } | ||
1578 | #endif | ||
1579 | } | ||
1580 | |||
1581 | /* -------------------- RESET CARD: */ | ||
1582 | |||
1583 | static void lanai_reset(struct lanai_dev *lanai) | ||
1584 | { | ||
1585 | printk(KERN_CRIT DEV_LABEL "(itf %d): *NOT* reseting - not " | ||
1586 | "implemented\n", lanai->number); | ||
1587 | /* TODO */ | ||
1588 | /* The following is just a hack until we write the real | ||
1589 | * resetter - at least ack whatever interrupt sent us | ||
1590 | * here | ||
1591 | */ | ||
1592 | reg_write(lanai, INT_ALL, IntAck_Reg); | ||
1593 | lanai->stats.card_reset++; | ||
1594 | } | ||
1595 | |||
1596 | /* -------------------- SERVICE LIST UTILITIES: */ | ||
1597 | |||
1598 | /* | ||
1599 | * Allocate service buffer and tell card about it | ||
1600 | */ | ||
1601 | static int __devinit service_buffer_allocate(struct lanai_dev *lanai) | ||
1602 | { | ||
1603 | lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 8, | ||
1604 | lanai->pci); | ||
1605 | if (unlikely(lanai->service.start == NULL)) | ||
1606 | return -ENOMEM; | ||
1607 | DPRINTK("allocated service buffer at 0x%08lX, size %Zu(%d)\n", | ||
1608 | (unsigned long) lanai->service.start, | ||
1609 | lanai_buf_size(&lanai->service), | ||
1610 | lanai_buf_size_cardorder(&lanai->service)); | ||
1611 | /* Clear ServWrite register to be safe */ | ||
1612 | reg_write(lanai, 0, ServWrite_Reg); | ||
1613 | /* ServiceStuff register contains size and address of buffer */ | ||
1614 | reg_write(lanai, | ||
1615 | SSTUFF_SET_SIZE(lanai_buf_size_cardorder(&lanai->service)) | | ||
1616 | SSTUFF_SET_ADDR(lanai->service.dmaaddr), | ||
1617 | ServiceStuff_Reg); | ||
1618 | return 0; | ||
1619 | } | ||
1620 | |||
1621 | static inline void service_buffer_deallocate(struct lanai_dev *lanai) | ||
1622 | { | ||
1623 | lanai_buf_deallocate(&lanai->service, lanai->pci); | ||
1624 | } | ||
1625 | |||
1626 | /* Bitfields in service list */ | ||
1627 | #define SERVICE_TX (0x80000000) /* Was from transmission */ | ||
1628 | #define SERVICE_TRASH (0x40000000) /* RXed PDU was trashed */ | ||
1629 | #define SERVICE_CRCERR (0x20000000) /* RXed PDU had CRC error */ | ||
1630 | #define SERVICE_CI (0x10000000) /* RXed PDU had CI set */ | ||
1631 | #define SERVICE_CLP (0x08000000) /* RXed PDU had CLP set */ | ||
1632 | #define SERVICE_STREAM (0x04000000) /* RX Stream mode */ | ||
1633 | #define SERVICE_GET_VCI(x) (((x)>>16)&0x3FF) | ||
1634 | #define SERVICE_GET_END(x) ((x)&0x1FFF) | ||
1635 | |||
1636 | /* Handle one thing from the service list - returns true if it marked a | ||
1637 | * VCC ready for xmit | ||
1638 | */ | ||
1639 | static int handle_service(struct lanai_dev *lanai, u32 s) | ||
1640 | { | ||
1641 | vci_t vci = SERVICE_GET_VCI(s); | ||
1642 | struct lanai_vcc *lvcc; | ||
1643 | read_lock(&vcc_sklist_lock); | ||
1644 | lvcc = lanai->vccs[vci]; | ||
1645 | if (unlikely(lvcc == NULL)) { | ||
1646 | read_unlock(&vcc_sklist_lock); | ||
1647 | DPRINTK("(itf %d) got service entry 0x%X for nonexistent " | ||
1648 | "vcc %d\n", lanai->number, (unsigned int) s, vci); | ||
1649 | if (s & SERVICE_TX) | ||
1650 | lanai->stats.service_notx++; | ||
1651 | else | ||
1652 | lanai->stats.service_norx++; | ||
1653 | return 0; | ||
1654 | } | ||
1655 | if (s & SERVICE_TX) { /* segmentation interrupt */ | ||
1656 | if (unlikely(lvcc->tx.atmvcc == NULL)) { | ||
1657 | read_unlock(&vcc_sklist_lock); | ||
1658 | DPRINTK("(itf %d) got service entry 0x%X for non-TX " | ||
1659 | "vcc %d\n", lanai->number, (unsigned int) s, vci); | ||
1660 | lanai->stats.service_notx++; | ||
1661 | return 0; | ||
1662 | } | ||
1663 | __set_bit(vci, lanai->transmit_ready); | ||
1664 | lvcc->tx.endptr = SERVICE_GET_END(s); | ||
1665 | read_unlock(&vcc_sklist_lock); | ||
1666 | return 1; | ||
1667 | } | ||
1668 | if (unlikely(lvcc->rx.atmvcc == NULL)) { | ||
1669 | read_unlock(&vcc_sklist_lock); | ||
1670 | DPRINTK("(itf %d) got service entry 0x%X for non-RX " | ||
1671 | "vcc %d\n", lanai->number, (unsigned int) s, vci); | ||
1672 | lanai->stats.service_norx++; | ||
1673 | return 0; | ||
1674 | } | ||
1675 | if (unlikely(lvcc->rx.atmvcc->qos.aal != ATM_AAL5)) { | ||
1676 | read_unlock(&vcc_sklist_lock); | ||
1677 | DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 " | ||
1678 | "vcc %d\n", lanai->number, (unsigned int) s, vci); | ||
1679 | lanai->stats.service_rxnotaal5++; | ||
1680 | atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); | ||
1681 | return 0; | ||
1682 | } | ||
1683 | if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) { | ||
1684 | vcc_rx_aal5(lvcc, SERVICE_GET_END(s)); | ||
1685 | read_unlock(&vcc_sklist_lock); | ||
1686 | return 0; | ||
1687 | } | ||
1688 | if (s & SERVICE_TRASH) { | ||
1689 | int bytes; | ||
1690 | read_unlock(&vcc_sklist_lock); | ||
1691 | DPRINTK("got trashed rx pdu on vci %d\n", vci); | ||
1692 | atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); | ||
1693 | lvcc->stats.x.aal5.service_trash++; | ||
1694 | bytes = (SERVICE_GET_END(s) * 16) - | ||
1695 | (((unsigned long) lvcc->rx.buf.ptr) - | ||
1696 | ((unsigned long) lvcc->rx.buf.start)) + 47; | ||
1697 | if (bytes < 0) | ||
1698 | bytes += lanai_buf_size(&lvcc->rx.buf); | ||
1699 | lanai->stats.ovfl_trash += (bytes / 48); | ||
1700 | return 0; | ||
1701 | } | ||
1702 | if (s & SERVICE_STREAM) { | ||
1703 | read_unlock(&vcc_sklist_lock); | ||
1704 | atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); | ||
1705 | lvcc->stats.x.aal5.service_stream++; | ||
1706 | printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream " | ||
1707 | "PDU on VCI %d!\n", lanai->number, vci); | ||
1708 | lanai_reset(lanai); | ||
1709 | return 0; | ||
1710 | } | ||
1711 | DPRINTK("got rx crc error on vci %d\n", vci); | ||
1712 | atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); | ||
1713 | lvcc->stats.x.aal5.service_rxcrc++; | ||
1714 | lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4]; | ||
1715 | cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr); | ||
1716 | read_unlock(&vcc_sklist_lock); | ||
1717 | return 0; | ||
1718 | } | ||
1719 | |||
1720 | /* Try transmitting on all VCIs that we marked ready to serve */ | ||
1721 | static void iter_transmit(struct lanai_dev *lanai, vci_t vci) | ||
1722 | { | ||
1723 | struct lanai_vcc *lvcc = lanai->vccs[vci]; | ||
1724 | if (vcc_is_backlogged(lvcc)) | ||
1725 | lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr); | ||
1726 | } | ||
1727 | |||
1728 | /* Run service queue -- called from interrupt context or with | ||
1729 | * interrupts otherwise disabled and with the lanai->servicelock | ||
1730 | * lock held | ||
1731 | */ | ||
1732 | static void run_service(struct lanai_dev *lanai) | ||
1733 | { | ||
1734 | int ntx = 0; | ||
1735 | u32 wreg = reg_read(lanai, ServWrite_Reg); | ||
1736 | const u32 *end = lanai->service.start + wreg; | ||
1737 | while (lanai->service.ptr != end) { | ||
1738 | ntx += handle_service(lanai, | ||
1739 | le32_to_cpup(lanai->service.ptr++)); | ||
1740 | if (lanai->service.ptr >= lanai->service.end) | ||
1741 | lanai->service.ptr = lanai->service.start; | ||
1742 | } | ||
1743 | reg_write(lanai, wreg, ServRead_Reg); | ||
1744 | if (ntx != 0) { | ||
1745 | read_lock(&vcc_sklist_lock); | ||
1746 | vci_bitfield_iterate(lanai, lanai->transmit_ready, | ||
1747 | iter_transmit); | ||
1748 | bitmap_zero(lanai->transmit_ready, NUM_VCI); | ||
1749 | read_unlock(&vcc_sklist_lock); | ||
1750 | } | ||
1751 | } | ||
1752 | |||
1753 | /* -------------------- GATHER STATISTICS: */ | ||
1754 | |||
1755 | static void get_statistics(struct lanai_dev *lanai) | ||
1756 | { | ||
1757 | u32 statreg = reg_read(lanai, Statistics_Reg); | ||
1758 | lanai->stats.atm_ovfl += STATS_GET_FIFO_OVFL(statreg); | ||
1759 | lanai->stats.hec_err += STATS_GET_HEC_ERR(statreg); | ||
1760 | lanai->stats.vci_trash += STATS_GET_BAD_VCI(statreg); | ||
1761 | lanai->stats.ovfl_trash += STATS_GET_BUF_OVFL(statreg); | ||
1762 | } | ||
1763 | |||
1764 | /* -------------------- POLLING TIMER: */ | ||
1765 | |||
1766 | #ifndef DEBUG_RW | ||
1767 | /* Try to undequeue 1 backlogged vcc */ | ||
1768 | static void iter_dequeue(struct lanai_dev *lanai, vci_t vci) | ||
1769 | { | ||
1770 | struct lanai_vcc *lvcc = lanai->vccs[vci]; | ||
1771 | int endptr; | ||
1772 | if (lvcc == NULL || lvcc->tx.atmvcc == NULL || | ||
1773 | !vcc_is_backlogged(lvcc)) { | ||
1774 | __clear_bit(vci, lanai->backlog_vccs); | ||
1775 | return; | ||
1776 | } | ||
1777 | endptr = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)); | ||
1778 | lvcc->tx.unqueue(lanai, lvcc, endptr); | ||
1779 | } | ||
1780 | #endif /* !DEBUG_RW */ | ||
1781 | |||
1782 | static void lanai_timed_poll(unsigned long arg) | ||
1783 | { | ||
1784 | struct lanai_dev *lanai = (struct lanai_dev *) arg; | ||
1785 | #ifndef DEBUG_RW | ||
1786 | unsigned long flags; | ||
1787 | #ifdef USE_POWERDOWN | ||
1788 | if (lanai->conf1 & CONFIG1_POWERDOWN) | ||
1789 | return; | ||
1790 | #endif /* USE_POWERDOWN */ | ||
1791 | local_irq_save(flags); | ||
1792 | /* If we can grab the spinlock, check if any services need to be run */ | ||
1793 | if (spin_trylock(&lanai->servicelock)) { | ||
1794 | run_service(lanai); | ||
1795 | spin_unlock(&lanai->servicelock); | ||
1796 | } | ||
1797 | /* ...and see if any backlogged VCs can make progress */ | ||
1798 | /* unfortunately linux has no read_trylock() currently */ | ||
1799 | read_lock(&vcc_sklist_lock); | ||
1800 | vci_bitfield_iterate(lanai, lanai->backlog_vccs, iter_dequeue); | ||
1801 | read_unlock(&vcc_sklist_lock); | ||
1802 | local_irq_restore(flags); | ||
1803 | |||
1804 | get_statistics(lanai); | ||
1805 | #endif /* !DEBUG_RW */ | ||
1806 | mod_timer(&lanai->timer, jiffies + LANAI_POLL_PERIOD); | ||
1807 | } | ||
1808 | |||
1809 | static inline void lanai_timed_poll_start(struct lanai_dev *lanai) | ||
1810 | { | ||
1811 | init_timer(&lanai->timer); | ||
1812 | lanai->timer.expires = jiffies + LANAI_POLL_PERIOD; | ||
1813 | lanai->timer.data = (unsigned long) lanai; | ||
1814 | lanai->timer.function = lanai_timed_poll; | ||
1815 | add_timer(&lanai->timer); | ||
1816 | } | ||
1817 | |||
1818 | static inline void lanai_timed_poll_stop(struct lanai_dev *lanai) | ||
1819 | { | ||
1820 | del_timer_sync(&lanai->timer); | ||
1821 | } | ||
1822 | |||
1823 | /* -------------------- INTERRUPT SERVICE: */ | ||
1824 | |||
1825 | static inline void lanai_int_1(struct lanai_dev *lanai, u32 reason) | ||
1826 | { | ||
1827 | u32 ack = 0; | ||
1828 | if (reason & INT_SERVICE) { | ||
1829 | ack = INT_SERVICE; | ||
1830 | spin_lock(&lanai->servicelock); | ||
1831 | run_service(lanai); | ||
1832 | spin_unlock(&lanai->servicelock); | ||
1833 | } | ||
1834 | if (reason & (INT_AAL0_STR | INT_AAL0)) { | ||
1835 | ack |= reason & (INT_AAL0_STR | INT_AAL0); | ||
1836 | vcc_rx_aal0(lanai); | ||
1837 | } | ||
1838 | /* The rest of the interrupts are pretty rare */ | ||
1839 | if (ack == reason) | ||
1840 | goto done; | ||
1841 | if (reason & INT_STATS) { | ||
1842 | reason &= ~INT_STATS; /* No need to ack */ | ||
1843 | get_statistics(lanai); | ||
1844 | } | ||
1845 | if (reason & INT_STATUS) { | ||
1846 | ack |= reason & INT_STATUS; | ||
1847 | lanai_check_status(lanai); | ||
1848 | } | ||
1849 | if (unlikely(reason & INT_DMASHUT)) { | ||
1850 | printk(KERN_ERR DEV_LABEL "(itf %d): driver error - DMA " | ||
1851 | "shutdown, reason=0x%08X, address=0x%08X\n", | ||
1852 | lanai->number, (unsigned int) (reason & INT_DMASHUT), | ||
1853 | (unsigned int) reg_read(lanai, DMA_Addr_Reg)); | ||
1854 | if (reason & INT_TABORTBM) { | ||
1855 | lanai_reset(lanai); | ||
1856 | return; | ||
1857 | } | ||
1858 | ack |= (reason & INT_DMASHUT); | ||
1859 | printk(KERN_ERR DEV_LABEL "(itf %d): re-enabling DMA\n", | ||
1860 | lanai->number); | ||
1861 | conf1_write(lanai); | ||
1862 | lanai->stats.dma_reenable++; | ||
1863 | pcistatus_check(lanai, 0); | ||
1864 | } | ||
1865 | if (unlikely(reason & INT_TABORTSENT)) { | ||
1866 | ack |= (reason & INT_TABORTSENT); | ||
1867 | printk(KERN_ERR DEV_LABEL "(itf %d): sent PCI target abort\n", | ||
1868 | lanai->number); | ||
1869 | pcistatus_check(lanai, 0); | ||
1870 | } | ||
1871 | if (unlikely(reason & INT_SEGSHUT)) { | ||
1872 | printk(KERN_ERR DEV_LABEL "(itf %d): driver error - " | ||
1873 | "segmentation shutdown, reason=0x%08X\n", lanai->number, | ||
1874 | (unsigned int) (reason & INT_SEGSHUT)); | ||
1875 | lanai_reset(lanai); | ||
1876 | return; | ||
1877 | } | ||
1878 | if (unlikely(reason & (INT_PING | INT_WAKE))) { | ||
1879 | printk(KERN_ERR DEV_LABEL "(itf %d): driver error - " | ||
1880 | "unexpected interrupt 0x%08X, resetting\n", | ||
1881 | lanai->number, | ||
1882 | (unsigned int) (reason & (INT_PING | INT_WAKE))); | ||
1883 | lanai_reset(lanai); | ||
1884 | return; | ||
1885 | } | ||
1886 | #ifdef DEBUG | ||
1887 | if (unlikely(ack != reason)) { | ||
1888 | DPRINTK("unacked ints: 0x%08X\n", | ||
1889 | (unsigned int) (reason & ~ack)); | ||
1890 | ack = reason; | ||
1891 | } | ||
1892 | #endif | ||
1893 | done: | ||
1894 | if (ack != 0) | ||
1895 | reg_write(lanai, ack, IntAck_Reg); | ||
1896 | } | ||
1897 | |||
1898 | static irqreturn_t lanai_int(int irq, void *devid, struct pt_regs *regs) | ||
1899 | { | ||
1900 | struct lanai_dev *lanai = (struct lanai_dev *) devid; | ||
1901 | u32 reason; | ||
1902 | |||
1903 | (void) irq; (void) regs; /* unused variables */ | ||
1904 | |||
1905 | #ifdef USE_POWERDOWN | ||
1906 | /* | ||
1907 | * If we're powered down we shouldn't be generating any interrupts - | ||
1908 | * so assume that this is a shared interrupt line and it's for someone | ||
1909 | * else | ||
1910 | */ | ||
1911 | if (unlikely(lanai->conf1 & CONFIG1_POWERDOWN)) | ||
1912 | return IRQ_NONE; | ||
1913 | #endif | ||
1914 | |||
1915 | reason = intr_pending(lanai); | ||
1916 | if (reason == 0) | ||
1917 | return IRQ_NONE; /* Must be for someone else */ | ||
1918 | |||
1919 | do { | ||
1920 | if (unlikely(reason == 0xFFFFFFFF)) | ||
1921 | break; /* Maybe we've been unplugged? */ | ||
1922 | lanai_int_1(lanai, reason); | ||
1923 | reason = intr_pending(lanai); | ||
1924 | } while (reason != 0); | ||
1925 | |||
1926 | return IRQ_HANDLED; | ||
1927 | } | ||
1928 | |||
1929 | /* TODO - it would be nice if we could use the "delayed interrupt" system | ||
1930 | * to some advantage | ||
1931 | */ | ||
1932 | |||
1933 | /* -------------------- CHECK BOARD ID/REV: */ | ||
1934 | |||
1935 | /* | ||
1936 | * The board id and revision are stored both in the reset register and | ||
1937 | * in the PCI configuration space - the documentation says to check | ||
1938 | * each of them. If revp!=NULL we store the revision there | ||
1939 | */ | ||
1940 | static int check_board_id_and_rev(const char *name, u32 val, int *revp) | ||
1941 | { | ||
1942 | DPRINTK("%s says board_id=%d, board_rev=%d\n", name, | ||
1943 | (int) RESET_GET_BOARD_ID(val), | ||
1944 | (int) RESET_GET_BOARD_REV(val)); | ||
1945 | if (RESET_GET_BOARD_ID(val) != BOARD_ID_LANAI256) { | ||
1946 | printk(KERN_ERR DEV_LABEL ": Found %s board-id %d -- not a " | ||
1947 | "Lanai 25.6\n", name, (int) RESET_GET_BOARD_ID(val)); | ||
1948 | return -ENODEV; | ||
1949 | } | ||
1950 | if (revp != NULL) | ||
1951 | *revp = RESET_GET_BOARD_REV(val); | ||
1952 | return 0; | ||
1953 | } | ||
1954 | |||
1955 | /* -------------------- PCI INITIALIZATION/SHUTDOWN: */ | ||
1956 | |||
1957 | static int __devinit lanai_pci_start(struct lanai_dev *lanai) | ||
1958 | { | ||
1959 | struct pci_dev *pci = lanai->pci; | ||
1960 | int result; | ||
1961 | u16 w; | ||
1962 | |||
1963 | if (pci_enable_device(pci) != 0) { | ||
1964 | printk(KERN_ERR DEV_LABEL "(itf %d): can't enable " | ||
1965 | "PCI device", lanai->number); | ||
1966 | return -ENXIO; | ||
1967 | } | ||
1968 | pci_set_master(pci); | ||
1969 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) != 0) { | ||
1970 | printk(KERN_WARNING DEV_LABEL | ||
1971 | "(itf %d): No suitable DMA available.\n", lanai->number); | ||
1972 | return -EBUSY; | ||
1973 | } | ||
1974 | if (pci_set_consistent_dma_mask(pci, 0xFFFFFFFF) != 0) { | ||
1975 | printk(KERN_WARNING DEV_LABEL | ||
1976 | "(itf %d): No suitable DMA available.\n", lanai->number); | ||
1977 | return -EBUSY; | ||
1978 | } | ||
1979 | /* Get the pci revision byte */ | ||
1980 | result = pci_read_config_byte(pci, PCI_REVISION_ID, | ||
1981 | &lanai->pci_revision); | ||
1982 | if (result != PCIBIOS_SUCCESSFUL) { | ||
1983 | printk(KERN_ERR DEV_LABEL "(itf %d): can't read " | ||
1984 | "PCI_REVISION_ID: %d\n", lanai->number, result); | ||
1985 | return -EINVAL; | ||
1986 | } | ||
1987 | result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w); | ||
1988 | if (result != PCIBIOS_SUCCESSFUL) { | ||
1989 | printk(KERN_ERR DEV_LABEL "(itf %d): can't read " | ||
1990 | "PCI_SUBSYSTEM_ID: %d\n", lanai->number, result); | ||
1991 | return -EINVAL; | ||
1992 | } | ||
1993 | result = check_board_id_and_rev("PCI", w, NULL); | ||
1994 | if (result != 0) | ||
1995 | return result; | ||
1996 | /* Set latency timer to zero as per lanai docs */ | ||
1997 | result = pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0); | ||
1998 | if (result != PCIBIOS_SUCCESSFUL) { | ||
1999 | printk(KERN_ERR DEV_LABEL "(itf %d): can't write " | ||
2000 | "PCI_LATENCY_TIMER: %d\n", lanai->number, result); | ||
2001 | return -EINVAL; | ||
2002 | } | ||
2003 | pcistatus_check(lanai, 1); | ||
2004 | pcistatus_check(lanai, 0); | ||
2005 | return 0; | ||
2006 | } | ||
2007 | |||
2008 | /* -------------------- VPI/VCI ALLOCATION: */ | ||
2009 | |||
2010 | /* | ||
2011 | * We _can_ use VCI==0 for normal traffic, but only for UBR (or we'll | ||
2012 | * get a CBRZERO interrupt), and we can use it only if noone is receiving | ||
2013 | * AAL0 traffic (since they will use the same queue) - according to the | ||
2014 | * docs we shouldn't even use it for AAL0 traffic | ||
2015 | */ | ||
2016 | static inline int vci0_is_ok(struct lanai_dev *lanai, | ||
2017 | const struct atm_qos *qos) | ||
2018 | { | ||
2019 | if (qos->txtp.traffic_class == ATM_CBR || qos->aal == ATM_AAL0) | ||
2020 | return 0; | ||
2021 | if (qos->rxtp.traffic_class != ATM_NONE) { | ||
2022 | if (lanai->naal0 != 0) | ||
2023 | return 0; | ||
2024 | lanai->conf2 |= CONFIG2_VCI0_NORMAL; | ||
2025 | conf2_write_if_powerup(lanai); | ||
2026 | } | ||
2027 | return 1; | ||
2028 | } | ||
2029 | |||
2030 | /* return true if vci is currently unused, or if requested qos is | ||
2031 | * compatible | ||
2032 | */ | ||
2033 | static int vci_is_ok(struct lanai_dev *lanai, vci_t vci, | ||
2034 | const struct atm_vcc *atmvcc) | ||
2035 | { | ||
2036 | const struct atm_qos *qos = &atmvcc->qos; | ||
2037 | const struct lanai_vcc *lvcc = lanai->vccs[vci]; | ||
2038 | if (vci == 0 && !vci0_is_ok(lanai, qos)) | ||
2039 | return 0; | ||
2040 | if (unlikely(lvcc != NULL)) { | ||
2041 | if (qos->rxtp.traffic_class != ATM_NONE && | ||
2042 | lvcc->rx.atmvcc != NULL && lvcc->rx.atmvcc != atmvcc) | ||
2043 | return 0; | ||
2044 | if (qos->txtp.traffic_class != ATM_NONE && | ||
2045 | lvcc->tx.atmvcc != NULL && lvcc->tx.atmvcc != atmvcc) | ||
2046 | return 0; | ||
2047 | if (qos->txtp.traffic_class == ATM_CBR && | ||
2048 | lanai->cbrvcc != NULL && lanai->cbrvcc != atmvcc) | ||
2049 | return 0; | ||
2050 | } | ||
2051 | if (qos->aal == ATM_AAL0 && lanai->naal0 == 0 && | ||
2052 | qos->rxtp.traffic_class != ATM_NONE) { | ||
2053 | const struct lanai_vcc *vci0 = lanai->vccs[0]; | ||
2054 | if (vci0 != NULL && vci0->rx.atmvcc != NULL) | ||
2055 | return 0; | ||
2056 | lanai->conf2 &= ~CONFIG2_VCI0_NORMAL; | ||
2057 | conf2_write_if_powerup(lanai); | ||
2058 | } | ||
2059 | return 1; | ||
2060 | } | ||
2061 | |||
2062 | static int lanai_normalize_ci(struct lanai_dev *lanai, | ||
2063 | const struct atm_vcc *atmvcc, short *vpip, vci_t *vcip) | ||
2064 | { | ||
2065 | switch (*vpip) { | ||
2066 | case ATM_VPI_ANY: | ||
2067 | *vpip = 0; | ||
2068 | /* FALLTHROUGH */ | ||
2069 | case 0: | ||
2070 | break; | ||
2071 | default: | ||
2072 | return -EADDRINUSE; | ||
2073 | } | ||
2074 | switch (*vcip) { | ||
2075 | case ATM_VCI_ANY: | ||
2076 | for (*vcip = ATM_NOT_RSV_VCI; *vcip < lanai->num_vci; | ||
2077 | (*vcip)++) | ||
2078 | if (vci_is_ok(lanai, *vcip, atmvcc)) | ||
2079 | return 0; | ||
2080 | return -EADDRINUSE; | ||
2081 | default: | ||
2082 | if (*vcip >= lanai->num_vci || *vcip < 0 || | ||
2083 | !vci_is_ok(lanai, *vcip, atmvcc)) | ||
2084 | return -EADDRINUSE; | ||
2085 | } | ||
2086 | return 0; | ||
2087 | } | ||
2088 | |||
2089 | /* -------------------- MANAGE CBR: */ | ||
2090 | |||
2091 | /* | ||
2092 | * CBR ICG is stored as a fixed-point number with 4 fractional bits. | ||
2093 | * Note that storing a number greater than 2046.0 will result in | ||
2094 | * incorrect shaping | ||
2095 | */ | ||
2096 | #define CBRICG_FRAC_BITS (4) | ||
2097 | #define CBRICG_MAX (2046 << CBRICG_FRAC_BITS) | ||
2098 | |||
2099 | /* | ||
2100 | * ICG is related to PCR with the formula PCR = MAXPCR / (ICG + 1) | ||
2101 | * where MAXPCR is (according to the docs) 25600000/(54*8), | ||
2102 | * which is equal to (3125<<9)/27. | ||
2103 | * | ||
2104 | * Solving for ICG, we get: | ||
2105 | * ICG = MAXPCR/PCR - 1 | ||
2106 | * ICG = (3125<<9)/(27*PCR) - 1 | ||
2107 | * ICG = ((3125<<9) - (27*PCR)) / (27*PCR) | ||
2108 | * | ||
2109 | * The end result is supposed to be a fixed-point number with FRAC_BITS | ||
2110 | * bits of a fractional part, so we keep everything in the numerator | ||
2111 | * shifted by that much as we compute | ||
2112 | * | ||
2113 | */ | ||
2114 | static int pcr_to_cbricg(/*const*/ struct atm_qos *qos) | ||
2115 | { | ||
2116 | int rounddown = 0; /* 1 = Round PCR down, i.e. round ICG _up_ */ | ||
2117 | int x, icg, pcr = atm_pcr_goal(&qos->txtp); | ||
2118 | if (pcr == 0) /* Use maximum bandwidth */ | ||
2119 | return 0; | ||
2120 | if (pcr < 0) { | ||
2121 | rounddown = 1; | ||
2122 | pcr = -pcr; | ||
2123 | } | ||
2124 | x = pcr * 27; | ||
2125 | icg = (3125 << (9 + CBRICG_FRAC_BITS)) - (x << CBRICG_FRAC_BITS); | ||
2126 | if (rounddown) | ||
2127 | icg += x - 1; | ||
2128 | icg /= x; | ||
2129 | if (icg > CBRICG_MAX) | ||
2130 | icg = CBRICG_MAX; | ||
2131 | DPRINTK("pcr_to_cbricg: pcr=%d rounddown=%c icg=%d\n", | ||
2132 | pcr, rounddown ? 'Y' : 'N', icg); | ||
2133 | return icg; | ||
2134 | } | ||
2135 | |||
2136 | static inline void lanai_cbr_setup(struct lanai_dev *lanai) | ||
2137 | { | ||
2138 | reg_write(lanai, pcr_to_cbricg(&lanai->cbrvcc->qos), CBR_ICG_Reg); | ||
2139 | reg_write(lanai, lanai->cbrvcc->vci, CBR_PTR_Reg); | ||
2140 | lanai->conf2 |= CONFIG2_CBR_ENABLE; | ||
2141 | conf2_write(lanai); | ||
2142 | } | ||
2143 | |||
2144 | static inline void lanai_cbr_shutdown(struct lanai_dev *lanai) | ||
2145 | { | ||
2146 | lanai->conf2 &= ~CONFIG2_CBR_ENABLE; | ||
2147 | conf2_write(lanai); | ||
2148 | } | ||
2149 | |||
2150 | /* -------------------- OPERATIONS: */ | ||
2151 | |||
2152 | /* setup a newly detected device */ | ||
2153 | static int __devinit lanai_dev_open(struct atm_dev *atmdev) | ||
2154 | { | ||
2155 | struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; | ||
2156 | unsigned long raw_base; | ||
2157 | int result; | ||
2158 | |||
2159 | DPRINTK("In lanai_dev_open()\n"); | ||
2160 | /* Basic device fields */ | ||
2161 | lanai->number = atmdev->number; | ||
2162 | lanai->num_vci = NUM_VCI; | ||
2163 | bitmap_zero(lanai->backlog_vccs, NUM_VCI); | ||
2164 | bitmap_zero(lanai->transmit_ready, NUM_VCI); | ||
2165 | lanai->naal0 = 0; | ||
2166 | #ifdef USE_POWERDOWN | ||
2167 | lanai->nbound = 0; | ||
2168 | #endif | ||
2169 | lanai->cbrvcc = NULL; | ||
2170 | memset(&lanai->stats, 0, sizeof lanai->stats); | ||
2171 | spin_lock_init(&lanai->endtxlock); | ||
2172 | spin_lock_init(&lanai->servicelock); | ||
2173 | atmdev->ci_range.vpi_bits = 0; | ||
2174 | atmdev->ci_range.vci_bits = 0; | ||
2175 | while (1 << atmdev->ci_range.vci_bits < lanai->num_vci) | ||
2176 | atmdev->ci_range.vci_bits++; | ||
2177 | atmdev->link_rate = ATM_25_PCR; | ||
2178 | |||
2179 | /* 3.2: PCI initialization */ | ||
2180 | if ((result = lanai_pci_start(lanai)) != 0) | ||
2181 | goto error; | ||
2182 | raw_base = lanai->pci->resource[0].start; | ||
2183 | lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE); | ||
2184 | if (lanai->base == NULL) { | ||
2185 | printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n"); | ||
2186 | goto error_pci; | ||
2187 | } | ||
2188 | /* 3.3: Reset lanai and PHY */ | ||
2189 | reset_board(lanai); | ||
2190 | lanai->conf1 = reg_read(lanai, Config1_Reg); | ||
2191 | lanai->conf1 &= ~(CONFIG1_GPOUT1 | CONFIG1_POWERDOWN | | ||
2192 | CONFIG1_MASK_LEDMODE); | ||
2193 | lanai->conf1 |= CONFIG1_SET_LEDMODE(LEDMODE_NOT_SOOL); | ||
2194 | reg_write(lanai, lanai->conf1 | CONFIG1_GPOUT1, Config1_Reg); | ||
2195 | udelay(1000); | ||
2196 | conf1_write(lanai); | ||
2197 | |||
2198 | /* | ||
2199 | * 3.4: Turn on endian mode for big-endian hardware | ||
2200 | * We don't actually want to do this - the actual bit fields | ||
2201 | * in the endian register are not documented anywhere. | ||
2202 | * Instead we do the bit-flipping ourselves on big-endian | ||
2203 | * hardware. | ||
2204 | * | ||
2205 | * 3.5: get the board ID/rev by reading the reset register | ||
2206 | */ | ||
2207 | result = check_board_id_and_rev("register", | ||
2208 | reg_read(lanai, Reset_Reg), &lanai->board_rev); | ||
2209 | if (result != 0) | ||
2210 | goto error_unmap; | ||
2211 | |||
2212 | /* 3.6: read EEPROM */ | ||
2213 | if ((result = eeprom_read(lanai)) != 0) | ||
2214 | goto error_unmap; | ||
2215 | if ((result = eeprom_validate(lanai)) != 0) | ||
2216 | goto error_unmap; | ||
2217 | |||
2218 | /* 3.7: re-reset PHY, do loopback tests, setup PHY */ | ||
2219 | reg_write(lanai, lanai->conf1 | CONFIG1_GPOUT1, Config1_Reg); | ||
2220 | udelay(1000); | ||
2221 | conf1_write(lanai); | ||
2222 | /* TODO - loopback tests */ | ||
2223 | lanai->conf1 |= (CONFIG1_GPOUT2 | CONFIG1_GPOUT3 | CONFIG1_DMA_ENABLE); | ||
2224 | conf1_write(lanai); | ||
2225 | |||
2226 | /* 3.8/3.9: test and initialize card SRAM */ | ||
2227 | if ((result = sram_test_and_clear(lanai)) != 0) | ||
2228 | goto error_unmap; | ||
2229 | |||
2230 | /* 3.10: initialize lanai registers */ | ||
2231 | lanai->conf1 |= CONFIG1_DMA_ENABLE; | ||
2232 | conf1_write(lanai); | ||
2233 | if ((result = service_buffer_allocate(lanai)) != 0) | ||
2234 | goto error_unmap; | ||
2235 | if ((result = vcc_table_allocate(lanai)) != 0) | ||
2236 | goto error_service; | ||
2237 | lanai->conf2 = (lanai->num_vci >= 512 ? CONFIG2_HOWMANY : 0) | | ||
2238 | CONFIG2_HEC_DROP | /* ??? */ CONFIG2_PTI7_MODE; | ||
2239 | conf2_write(lanai); | ||
2240 | reg_write(lanai, TX_FIFO_DEPTH, TxDepth_Reg); | ||
2241 | reg_write(lanai, 0, CBR_ICG_Reg); /* CBR defaults to no limit */ | ||
2242 | if ((result = request_irq(lanai->pci->irq, lanai_int, SA_SHIRQ, | ||
2243 | DEV_LABEL, lanai)) != 0) { | ||
2244 | printk(KERN_ERR DEV_LABEL ": can't allocate interrupt\n"); | ||
2245 | goto error_vcctable; | ||
2246 | } | ||
2247 | mb(); /* Make sure that all that made it */ | ||
2248 | intr_enable(lanai, INT_ALL & ~(INT_PING | INT_WAKE)); | ||
2249 | /* 3.11: initialize loop mode (i.e. turn looping off) */ | ||
2250 | lanai->conf1 = (lanai->conf1 & ~CONFIG1_MASK_LOOPMODE) | | ||
2251 | CONFIG1_SET_LOOPMODE(LOOPMODE_NORMAL) | | ||
2252 | CONFIG1_GPOUT2 | CONFIG1_GPOUT3; | ||
2253 | conf1_write(lanai); | ||
2254 | lanai->status = reg_read(lanai, Status_Reg); | ||
2255 | /* We're now done initializing this card */ | ||
2256 | #ifdef USE_POWERDOWN | ||
2257 | lanai->conf1 |= CONFIG1_POWERDOWN; | ||
2258 | conf1_write(lanai); | ||
2259 | #endif | ||
2260 | memcpy(atmdev->esi, eeprom_mac(lanai), ESI_LEN); | ||
2261 | lanai_timed_poll_start(lanai); | ||
2262 | printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=0x%lx, irq=%u " | ||
2263 | "(%02X-%02X-%02X-%02X-%02X-%02X)\n", lanai->number, | ||
2264 | (int) lanai->pci_revision, (unsigned long) lanai->base, | ||
2265 | lanai->pci->irq, | ||
2266 | atmdev->esi[0], atmdev->esi[1], atmdev->esi[2], | ||
2267 | atmdev->esi[3], atmdev->esi[4], atmdev->esi[5]); | ||
2268 | printk(KERN_NOTICE DEV_LABEL "(itf %d): LANAI%s, serialno=%u(0x%X), " | ||
2269 | "board_rev=%d\n", lanai->number, | ||
2270 | lanai->type==lanai2 ? "2" : "HB", (unsigned int) lanai->serialno, | ||
2271 | (unsigned int) lanai->serialno, lanai->board_rev); | ||
2272 | return 0; | ||
2273 | |||
2274 | error_vcctable: | ||
2275 | vcc_table_deallocate(lanai); | ||
2276 | error_service: | ||
2277 | service_buffer_deallocate(lanai); | ||
2278 | error_unmap: | ||
2279 | reset_board(lanai); | ||
2280 | #ifdef USE_POWERDOWN | ||
2281 | lanai->conf1 = reg_read(lanai, Config1_Reg) | CONFIG1_POWERDOWN; | ||
2282 | conf1_write(lanai); | ||
2283 | #endif | ||
2284 | iounmap(lanai->base); | ||
2285 | error_pci: | ||
2286 | pci_disable_device(lanai->pci); | ||
2287 | error: | ||
2288 | return result; | ||
2289 | } | ||
2290 | |||
2291 | /* called when device is being shutdown, and all vcc's are gone - higher | ||
2292 | * levels will deallocate the atm device for us | ||
2293 | */ | ||
2294 | static void lanai_dev_close(struct atm_dev *atmdev) | ||
2295 | { | ||
2296 | struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; | ||
2297 | printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n", | ||
2298 | lanai->number); | ||
2299 | lanai_timed_poll_stop(lanai); | ||
2300 | #ifdef USE_POWERDOWN | ||
2301 | lanai->conf1 = reg_read(lanai, Config1_Reg) & ~CONFIG1_POWERDOWN; | ||
2302 | conf1_write(lanai); | ||
2303 | #endif | ||
2304 | intr_disable(lanai, INT_ALL); | ||
2305 | free_irq(lanai->pci->irq, lanai); | ||
2306 | reset_board(lanai); | ||
2307 | #ifdef USE_POWERDOWN | ||
2308 | lanai->conf1 |= CONFIG1_POWERDOWN; | ||
2309 | conf1_write(lanai); | ||
2310 | #endif | ||
2311 | pci_disable_device(lanai->pci); | ||
2312 | vcc_table_deallocate(lanai); | ||
2313 | service_buffer_deallocate(lanai); | ||
2314 | iounmap(lanai->base); | ||
2315 | kfree(lanai); | ||
2316 | } | ||
2317 | |||
2318 | /* close a vcc */ | ||
2319 | static void lanai_close(struct atm_vcc *atmvcc) | ||
2320 | { | ||
2321 | struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data; | ||
2322 | struct lanai_dev *lanai = (struct lanai_dev *) atmvcc->dev->dev_data; | ||
2323 | if (lvcc == NULL) | ||
2324 | return; | ||
2325 | clear_bit(ATM_VF_READY, &atmvcc->flags); | ||
2326 | clear_bit(ATM_VF_PARTIAL, &atmvcc->flags); | ||
2327 | if (lvcc->rx.atmvcc == atmvcc) { | ||
2328 | lanai_shutdown_rx_vci(lvcc); | ||
2329 | if (atmvcc->qos.aal == ATM_AAL0) { | ||
2330 | if (--lanai->naal0 <= 0) | ||
2331 | aal0_buffer_free(lanai); | ||
2332 | } else | ||
2333 | lanai_buf_deallocate(&lvcc->rx.buf, lanai->pci); | ||
2334 | lvcc->rx.atmvcc = NULL; | ||
2335 | } | ||
2336 | if (lvcc->tx.atmvcc == atmvcc) { | ||
2337 | if (atmvcc == lanai->cbrvcc) { | ||
2338 | if (lvcc->vbase != NULL) | ||
2339 | lanai_cbr_shutdown(lanai); | ||
2340 | lanai->cbrvcc = NULL; | ||
2341 | } | ||
2342 | lanai_shutdown_tx_vci(lanai, lvcc); | ||
2343 | lanai_buf_deallocate(&lvcc->tx.buf, lanai->pci); | ||
2344 | lvcc->tx.atmvcc = NULL; | ||
2345 | } | ||
2346 | if (--lvcc->nref == 0) { | ||
2347 | host_vcc_unbind(lanai, lvcc); | ||
2348 | kfree(lvcc); | ||
2349 | } | ||
2350 | atmvcc->dev_data = NULL; | ||
2351 | clear_bit(ATM_VF_ADDR, &atmvcc->flags); | ||
2352 | } | ||
2353 | |||
2354 | /* open a vcc on the card to vpi/vci */ | ||
2355 | static int lanai_open(struct atm_vcc *atmvcc) | ||
2356 | { | ||
2357 | struct lanai_dev *lanai; | ||
2358 | struct lanai_vcc *lvcc; | ||
2359 | int result = 0; | ||
2360 | int vci = atmvcc->vci; | ||
2361 | short vpi = atmvcc->vpi; | ||
2362 | /* we don't support partial open - it's not really useful anyway */ | ||
2363 | if ((test_bit(ATM_VF_PARTIAL, &atmvcc->flags)) || | ||
2364 | (vpi == ATM_VPI_UNSPEC) || (vci == ATM_VCI_UNSPEC)) | ||
2365 | return -EINVAL; | ||
2366 | lanai = (struct lanai_dev *) atmvcc->dev->dev_data; | ||
2367 | result = lanai_normalize_ci(lanai, atmvcc, &vpi, &vci); | ||
2368 | if (unlikely(result != 0)) | ||
2369 | goto out; | ||
2370 | set_bit(ATM_VF_ADDR, &atmvcc->flags); | ||
2371 | if (atmvcc->qos.aal != ATM_AAL0 && atmvcc->qos.aal != ATM_AAL5) | ||
2372 | return -EINVAL; | ||
2373 | DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n", lanai->number, | ||
2374 | (int) vpi, vci); | ||
2375 | lvcc = lanai->vccs[vci]; | ||
2376 | if (lvcc == NULL) { | ||
2377 | lvcc = new_lanai_vcc(); | ||
2378 | if (unlikely(lvcc == NULL)) | ||
2379 | return -ENOMEM; | ||
2380 | atmvcc->dev_data = lvcc; | ||
2381 | } | ||
2382 | lvcc->nref++; | ||
2383 | if (atmvcc->qos.rxtp.traffic_class != ATM_NONE) { | ||
2384 | APRINTK(lvcc->rx.atmvcc == NULL, "rx.atmvcc!=NULL, vci=%d\n", | ||
2385 | vci); | ||
2386 | if (atmvcc->qos.aal == ATM_AAL0) { | ||
2387 | if (lanai->naal0 == 0) | ||
2388 | result = aal0_buffer_allocate(lanai); | ||
2389 | } else | ||
2390 | result = lanai_setup_rx_vci_aal5( | ||
2391 | lanai, lvcc, &atmvcc->qos); | ||
2392 | if (unlikely(result != 0)) | ||
2393 | goto out_free; | ||
2394 | lvcc->rx.atmvcc = atmvcc; | ||
2395 | lvcc->stats.rx_nomem = 0; | ||
2396 | lvcc->stats.x.aal5.rx_badlen = 0; | ||
2397 | lvcc->stats.x.aal5.service_trash = 0; | ||
2398 | lvcc->stats.x.aal5.service_stream = 0; | ||
2399 | lvcc->stats.x.aal5.service_rxcrc = 0; | ||
2400 | if (atmvcc->qos.aal == ATM_AAL0) | ||
2401 | lanai->naal0++; | ||
2402 | } | ||
2403 | if (atmvcc->qos.txtp.traffic_class != ATM_NONE) { | ||
2404 | APRINTK(lvcc->tx.atmvcc == NULL, "tx.atmvcc!=NULL, vci=%d\n", | ||
2405 | vci); | ||
2406 | result = lanai_setup_tx_vci(lanai, lvcc, &atmvcc->qos); | ||
2407 | if (unlikely(result != 0)) | ||
2408 | goto out_free; | ||
2409 | lvcc->tx.atmvcc = atmvcc; | ||
2410 | if (atmvcc->qos.txtp.traffic_class == ATM_CBR) { | ||
2411 | APRINTK(lanai->cbrvcc == NULL, | ||
2412 | "cbrvcc!=NULL, vci=%d\n", vci); | ||
2413 | lanai->cbrvcc = atmvcc; | ||
2414 | } | ||
2415 | } | ||
2416 | host_vcc_bind(lanai, lvcc, vci); | ||
2417 | /* | ||
2418 | * Make sure everything made it to RAM before we tell the card about | ||
2419 | * the VCC | ||
2420 | */ | ||
2421 | wmb(); | ||
2422 | if (atmvcc == lvcc->rx.atmvcc) | ||
2423 | host_vcc_start_rx(lvcc); | ||
2424 | if (atmvcc == lvcc->tx.atmvcc) { | ||
2425 | host_vcc_start_tx(lvcc); | ||
2426 | if (lanai->cbrvcc == atmvcc) | ||
2427 | lanai_cbr_setup(lanai); | ||
2428 | } | ||
2429 | set_bit(ATM_VF_READY, &atmvcc->flags); | ||
2430 | return 0; | ||
2431 | out_free: | ||
2432 | lanai_close(atmvcc); | ||
2433 | out: | ||
2434 | return result; | ||
2435 | } | ||
2436 | |||
2437 | #if 0 | ||
2438 | /* ioctl operations for card */ | ||
2439 | /* NOTE: these are all DEBUGGING ONLY currently */ | ||
2440 | static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void __user *arg) | ||
2441 | { | ||
2442 | int result = 0; | ||
2443 | struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; | ||
2444 | switch(cmd) { | ||
2445 | case 2106275: | ||
2446 | shutdown_atm_dev(atmdev); | ||
2447 | return 0; | ||
2448 | case 2200000: { | ||
2449 | unsigned long flags; | ||
2450 | spin_lock_irqsave(&lanai->servicelock, flags); | ||
2451 | run_service(lanai); | ||
2452 | spin_unlock_irqrestore(&lanai->servicelock, flags); | ||
2453 | return 0; } | ||
2454 | case 2200002: | ||
2455 | get_statistics(lanai); | ||
2456 | return 0; | ||
2457 | case 2200003: { | ||
2458 | unsigned int i; | ||
2459 | for (i = 0; i <= 0x5C ; i += 4) { | ||
2460 | if (i==0x48) /* Write-only butt reg */ | ||
2461 | continue; | ||
2462 | printk(KERN_CRIT DEV_LABEL " 0x%02X: " | ||
2463 | "0x%08X\n", i, | ||
2464 | (unsigned int) readl(lanai->base + i)); | ||
2465 | barrier(); mb(); | ||
2466 | pcistatus_check(lanai, 0); | ||
2467 | barrier(); mb(); | ||
2468 | } | ||
2469 | return 0; } | ||
2470 | case 2200004: { | ||
2471 | u8 b; | ||
2472 | u16 w; | ||
2473 | u32 dw; | ||
2474 | struct pci_dev *pci = lanai->pci; | ||
2475 | (void) pci_read_config_word(pci, PCI_VENDOR_ID, &w); | ||
2476 | DPRINTK("vendor = 0x%X\n", (unsigned int) w); | ||
2477 | (void) pci_read_config_word(pci, PCI_DEVICE_ID, &w); | ||
2478 | DPRINTK("device = 0x%X\n", (unsigned int) w); | ||
2479 | (void) pci_read_config_word(pci, PCI_COMMAND, &w); | ||
2480 | DPRINTK("command = 0x%X\n", (unsigned int) w); | ||
2481 | (void) pci_read_config_word(pci, PCI_STATUS, &w); | ||
2482 | DPRINTK("status = 0x%X\n", (unsigned int) w); | ||
2483 | (void) pci_read_config_dword(pci, | ||
2484 | PCI_CLASS_REVISION, &dw); | ||
2485 | DPRINTK("class/revision = 0x%X\n", (unsigned int) dw); | ||
2486 | (void) pci_read_config_byte(pci, | ||
2487 | PCI_CACHE_LINE_SIZE, &b); | ||
2488 | DPRINTK("cache line size = 0x%X\n", (unsigned int) b); | ||
2489 | (void) pci_read_config_byte(pci, PCI_LATENCY_TIMER, &b); | ||
2490 | DPRINTK("latency = %d (0x%X)\n", | ||
2491 | (int) b, (unsigned int) b); | ||
2492 | (void) pci_read_config_byte(pci, PCI_HEADER_TYPE, &b); | ||
2493 | DPRINTK("header type = 0x%X\n", (unsigned int) b); | ||
2494 | (void) pci_read_config_byte(pci, PCI_BIST, &b); | ||
2495 | DPRINTK("bist = 0x%X\n", (unsigned int) b); | ||
2496 | /* skipping a few here */ | ||
2497 | (void) pci_read_config_byte(pci, | ||
2498 | PCI_INTERRUPT_LINE, &b); | ||
2499 | DPRINTK("pci_int_line = 0x%X\n", (unsigned int) b); | ||
2500 | (void) pci_read_config_byte(pci, | ||
2501 | PCI_INTERRUPT_PIN, &b); | ||
2502 | DPRINTK("pci_int_pin = 0x%X\n", (unsigned int) b); | ||
2503 | (void) pci_read_config_byte(pci, PCI_MIN_GNT, &b); | ||
2504 | DPRINTK("min_gnt = 0x%X\n", (unsigned int) b); | ||
2505 | (void) pci_read_config_byte(pci, PCI_MAX_LAT, &b); | ||
2506 | DPRINTK("max_lat = 0x%X\n", (unsigned int) b); } | ||
2507 | return 0; | ||
2508 | #ifdef USE_POWERDOWN | ||
2509 | case 2200005: | ||
2510 | DPRINTK("Coming out of powerdown\n"); | ||
2511 | lanai->conf1 &= ~CONFIG1_POWERDOWN; | ||
2512 | conf1_write(lanai); | ||
2513 | return 0; | ||
2514 | #endif | ||
2515 | default: | ||
2516 | result = -ENOIOCTLCMD; | ||
2517 | } | ||
2518 | return result; | ||
2519 | } | ||
2520 | #else /* !0 */ | ||
2521 | #define lanai_ioctl NULL | ||
2522 | #endif /* 0 */ | ||
2523 | |||
2524 | static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb) | ||
2525 | { | ||
2526 | struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data; | ||
2527 | struct lanai_dev *lanai = (struct lanai_dev *) atmvcc->dev->dev_data; | ||
2528 | unsigned long flags; | ||
2529 | if (unlikely(lvcc == NULL || lvcc->vbase == NULL || | ||
2530 | lvcc->tx.atmvcc != atmvcc)) | ||
2531 | goto einval; | ||
2532 | #ifdef DEBUG | ||
2533 | if (unlikely(skb == NULL)) { | ||
2534 | DPRINTK("lanai_send: skb==NULL for vci=%d\n", atmvcc->vci); | ||
2535 | goto einval; | ||
2536 | } | ||
2537 | if (unlikely(lanai == NULL)) { | ||
2538 | DPRINTK("lanai_send: lanai==NULL for vci=%d\n", atmvcc->vci); | ||
2539 | goto einval; | ||
2540 | } | ||
2541 | #endif | ||
2542 | ATM_SKB(skb)->vcc = atmvcc; | ||
2543 | switch (atmvcc->qos.aal) { | ||
2544 | case ATM_AAL5: | ||
2545 | read_lock_irqsave(&vcc_sklist_lock, flags); | ||
2546 | vcc_tx_aal5(lanai, lvcc, skb); | ||
2547 | read_unlock_irqrestore(&vcc_sklist_lock, flags); | ||
2548 | return 0; | ||
2549 | case ATM_AAL0: | ||
2550 | if (unlikely(skb->len != ATM_CELL_SIZE-1)) | ||
2551 | goto einval; | ||
2552 | /* NOTE - this next line is technically invalid - we haven't unshared skb */ | ||
2553 | cpu_to_be32s((u32 *) skb->data); | ||
2554 | read_lock_irqsave(&vcc_sklist_lock, flags); | ||
2555 | vcc_tx_aal0(lanai, lvcc, skb); | ||
2556 | read_unlock_irqrestore(&vcc_sklist_lock, flags); | ||
2557 | return 0; | ||
2558 | } | ||
2559 | DPRINTK("lanai_send: bad aal=%d on vci=%d\n", (int) atmvcc->qos.aal, | ||
2560 | atmvcc->vci); | ||
2561 | einval: | ||
2562 | lanai_free_skb(atmvcc, skb); | ||
2563 | return -EINVAL; | ||
2564 | } | ||
2565 | |||
2566 | static int lanai_change_qos(struct atm_vcc *atmvcc, | ||
2567 | /*const*/ struct atm_qos *qos, int flags) | ||
2568 | { | ||
2569 | return -EBUSY; /* TODO: need to write this */ | ||
2570 | } | ||
2571 | |||
2572 | #ifndef CONFIG_PROC_FS | ||
2573 | #define lanai_proc_read NULL | ||
2574 | #else | ||
2575 | static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page) | ||
2576 | { | ||
2577 | struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; | ||
2578 | loff_t left = *pos; | ||
2579 | struct lanai_vcc *lvcc; | ||
2580 | if (left-- == 0) | ||
2581 | return sprintf(page, DEV_LABEL "(itf %d): chip=LANAI%s, " | ||
2582 | "serial=%u, magic=0x%08X, num_vci=%d\n", | ||
2583 | atmdev->number, lanai->type==lanai2 ? "2" : "HB", | ||
2584 | (unsigned int) lanai->serialno, | ||
2585 | (unsigned int) lanai->magicno, lanai->num_vci); | ||
2586 | if (left-- == 0) | ||
2587 | return sprintf(page, "revision: board=%d, pci_if=%d\n", | ||
2588 | lanai->board_rev, (int) lanai->pci_revision); | ||
2589 | if (left-- == 0) | ||
2590 | return sprintf(page, "EEPROM ESI: " | ||
2591 | "%02X:%02X:%02X:%02X:%02X:%02X\n", | ||
2592 | lanai->eeprom[EEPROM_MAC + 0], | ||
2593 | lanai->eeprom[EEPROM_MAC + 1], | ||
2594 | lanai->eeprom[EEPROM_MAC + 2], | ||
2595 | lanai->eeprom[EEPROM_MAC + 3], | ||
2596 | lanai->eeprom[EEPROM_MAC + 4], | ||
2597 | lanai->eeprom[EEPROM_MAC + 5]); | ||
2598 | if (left-- == 0) | ||
2599 | return sprintf(page, "status: SOOL=%d, LOCD=%d, LED=%d, " | ||
2600 | "GPIN=%d\n", (lanai->status & STATUS_SOOL) ? 1 : 0, | ||
2601 | (lanai->status & STATUS_LOCD) ? 1 : 0, | ||
2602 | (lanai->status & STATUS_LED) ? 1 : 0, | ||
2603 | (lanai->status & STATUS_GPIN) ? 1 : 0); | ||
2604 | if (left-- == 0) | ||
2605 | return sprintf(page, "global buffer sizes: service=%Zu, " | ||
2606 | "aal0_rx=%Zu\n", lanai_buf_size(&lanai->service), | ||
2607 | lanai->naal0 ? lanai_buf_size(&lanai->aal0buf) : 0); | ||
2608 | if (left-- == 0) { | ||
2609 | get_statistics(lanai); | ||
2610 | return sprintf(page, "cells in error: overflow=%u, " | ||
2611 | "closed_vci=%u, bad_HEC=%u, rx_fifo=%u\n", | ||
2612 | lanai->stats.ovfl_trash, lanai->stats.vci_trash, | ||
2613 | lanai->stats.hec_err, lanai->stats.atm_ovfl); | ||
2614 | } | ||
2615 | if (left-- == 0) | ||
2616 | return sprintf(page, "PCI errors: parity_detect=%u, " | ||
2617 | "master_abort=%u, master_target_abort=%u,\n", | ||
2618 | lanai->stats.pcierr_parity_detect, | ||
2619 | lanai->stats.pcierr_serr_set, | ||
2620 | lanai->stats.pcierr_m_target_abort); | ||
2621 | if (left-- == 0) | ||
2622 | return sprintf(page, " slave_target_abort=%u, " | ||
2623 | "master_parity=%u\n", lanai->stats.pcierr_s_target_abort, | ||
2624 | lanai->stats.pcierr_master_parity); | ||
2625 | if (left-- == 0) | ||
2626 | return sprintf(page, " no_tx=%u, " | ||
2627 | "no_rx=%u, bad_rx_aal=%u\n", lanai->stats.service_norx, | ||
2628 | lanai->stats.service_notx, | ||
2629 | lanai->stats.service_rxnotaal5); | ||
2630 | if (left-- == 0) | ||
2631 | return sprintf(page, "resets: dma=%u, card=%u\n", | ||
2632 | lanai->stats.dma_reenable, lanai->stats.card_reset); | ||
2633 | /* At this point, "left" should be the VCI we're looking for */ | ||
2634 | read_lock(&vcc_sklist_lock); | ||
2635 | for (; ; left++) { | ||
2636 | if (left >= NUM_VCI) { | ||
2637 | left = 0; | ||
2638 | goto out; | ||
2639 | } | ||
2640 | if ((lvcc = lanai->vccs[left]) != NULL) | ||
2641 | break; | ||
2642 | (*pos)++; | ||
2643 | } | ||
2644 | /* Note that we re-use "left" here since we're done with it */ | ||
2645 | left = sprintf(page, "VCI %4d: nref=%d, rx_nomem=%u", (vci_t) left, | ||
2646 | lvcc->nref, lvcc->stats.rx_nomem); | ||
2647 | if (lvcc->rx.atmvcc != NULL) { | ||
2648 | left += sprintf(&page[left], ",\n rx_AAL=%d", | ||
2649 | lvcc->rx.atmvcc->qos.aal == ATM_AAL5 ? 5 : 0); | ||
2650 | if (lvcc->rx.atmvcc->qos.aal == ATM_AAL5) | ||
2651 | left += sprintf(&page[left], ", rx_buf_size=%Zu, " | ||
2652 | "rx_bad_len=%u,\n rx_service_trash=%u, " | ||
2653 | "rx_service_stream=%u, rx_bad_crc=%u", | ||
2654 | lanai_buf_size(&lvcc->rx.buf), | ||
2655 | lvcc->stats.x.aal5.rx_badlen, | ||
2656 | lvcc->stats.x.aal5.service_trash, | ||
2657 | lvcc->stats.x.aal5.service_stream, | ||
2658 | lvcc->stats.x.aal5.service_rxcrc); | ||
2659 | } | ||
2660 | if (lvcc->tx.atmvcc != NULL) | ||
2661 | left += sprintf(&page[left], ",\n tx_AAL=%d, " | ||
2662 | "tx_buf_size=%Zu, tx_qos=%cBR, tx_backlogged=%c", | ||
2663 | lvcc->tx.atmvcc->qos.aal == ATM_AAL5 ? 5 : 0, | ||
2664 | lanai_buf_size(&lvcc->tx.buf), | ||
2665 | lvcc->tx.atmvcc == lanai->cbrvcc ? 'C' : 'U', | ||
2666 | vcc_is_backlogged(lvcc) ? 'Y' : 'N'); | ||
2667 | page[left++] = '\n'; | ||
2668 | page[left] = '\0'; | ||
2669 | out: | ||
2670 | read_unlock(&vcc_sklist_lock); | ||
2671 | return left; | ||
2672 | } | ||
2673 | #endif /* CONFIG_PROC_FS */ | ||
2674 | |||
2675 | /* -------------------- HOOKS: */ | ||
2676 | |||
2677 | static const struct atmdev_ops ops = { | ||
2678 | .dev_close = lanai_dev_close, | ||
2679 | .open = lanai_open, | ||
2680 | .close = lanai_close, | ||
2681 | .ioctl = lanai_ioctl, | ||
2682 | .getsockopt = NULL, | ||
2683 | .setsockopt = NULL, | ||
2684 | .send = lanai_send, | ||
2685 | .phy_put = NULL, | ||
2686 | .phy_get = NULL, | ||
2687 | .change_qos = lanai_change_qos, | ||
2688 | .proc_read = lanai_proc_read, | ||
2689 | .owner = THIS_MODULE | ||
2690 | }; | ||
2691 | |||
2692 | /* initialize one probed card */ | ||
2693 | static int __devinit lanai_init_one(struct pci_dev *pci, | ||
2694 | const struct pci_device_id *ident) | ||
2695 | { | ||
2696 | struct lanai_dev *lanai; | ||
2697 | struct atm_dev *atmdev; | ||
2698 | int result; | ||
2699 | |||
2700 | lanai = (struct lanai_dev *) kmalloc(sizeof(*lanai), GFP_KERNEL); | ||
2701 | if (lanai == NULL) { | ||
2702 | printk(KERN_ERR DEV_LABEL | ||
2703 | ": couldn't allocate dev_data structure!\n"); | ||
2704 | return -ENOMEM; | ||
2705 | } | ||
2706 | |||
2707 | atmdev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); | ||
2708 | if (atmdev == NULL) { | ||
2709 | printk(KERN_ERR DEV_LABEL | ||
2710 | ": couldn't register atm device!\n"); | ||
2711 | kfree(lanai); | ||
2712 | return -EBUSY; | ||
2713 | } | ||
2714 | |||
2715 | atmdev->dev_data = lanai; | ||
2716 | lanai->pci = pci; | ||
2717 | lanai->type = (enum lanai_type) ident->device; | ||
2718 | |||
2719 | result = lanai_dev_open(atmdev); | ||
2720 | if (result != 0) { | ||
2721 | DPRINTK("lanai_start() failed, err=%d\n", -result); | ||
2722 | atm_dev_deregister(atmdev); | ||
2723 | kfree(lanai); | ||
2724 | } | ||
2725 | return result; | ||
2726 | } | ||
2727 | |||
2728 | static struct pci_device_id lanai_pci_tbl[] = { | ||
2729 | { | ||
2730 | PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAI2, | ||
2731 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 | ||
2732 | }, | ||
2733 | { | ||
2734 | PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAIHB, | ||
2735 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 | ||
2736 | }, | ||
2737 | { 0, } /* terminal entry */ | ||
2738 | }; | ||
2739 | MODULE_DEVICE_TABLE(pci, lanai_pci_tbl); | ||
2740 | |||
2741 | static struct pci_driver lanai_driver = { | ||
2742 | .name = DEV_LABEL, | ||
2743 | .id_table = lanai_pci_tbl, | ||
2744 | .probe = lanai_init_one, | ||
2745 | }; | ||
2746 | |||
2747 | static int __init lanai_module_init(void) | ||
2748 | { | ||
2749 | int x; | ||
2750 | |||
2751 | x = pci_register_driver(&lanai_driver); | ||
2752 | if (x != 0) | ||
2753 | printk(KERN_ERR DEV_LABEL ": no adapter found\n"); | ||
2754 | return x; | ||
2755 | } | ||
2756 | |||
2757 | static void __exit lanai_module_exit(void) | ||
2758 | { | ||
2759 | /* We'll only get called when all the interfaces are already | ||
2760 | * gone, so there isn't much to do | ||
2761 | */ | ||
2762 | DPRINTK("cleanup_module()\n"); | ||
2763 | } | ||
2764 | |||
2765 | module_init(lanai_module_init); | ||
2766 | module_exit(lanai_module_exit); | ||
2767 | |||
2768 | MODULE_AUTHOR("Mitchell Blank Jr <mitch@sfgoth.com>"); | ||
2769 | MODULE_DESCRIPTION("Efficient Networks Speedstream 3010 driver"); | ||
2770 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/atm/midway.h b/drivers/atm/midway.h new file mode 100644 index 000000000000..432525ad5e46 --- /dev/null +++ b/drivers/atm/midway.h | |||
@@ -0,0 +1,265 @@ | |||
1 | /* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */ | ||
2 | |||
3 | /* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVERS_ATM_MIDWAY_H | ||
7 | #define DRIVERS_ATM_MIDWAY_H | ||
8 | |||
9 | |||
10 | #define NR_VCI 1024 /* number of VCIs */ | ||
11 | #define NR_VCI_LD 10 /* log2(NR_VCI) */ | ||
12 | #define NR_DMA_RX 512 /* RX DMA queue entries */ | ||
13 | #define NR_DMA_TX 512 /* TX DMA queue entries */ | ||
14 | #define NR_SERVICE NR_VCI /* service list size */ | ||
15 | #define NR_CHAN 8 /* number of TX channels */ | ||
16 | #define TS_CLOCK 25000000 /* traffic shaper clock (cell/sec) */ | ||
17 | |||
18 | #define MAP_MAX_SIZE 0x00400000 /* memory window for max config */ | ||
19 | #define EPROM_SIZE 0x00010000 | ||
20 | #define MEM_VALID 0xffc00000 /* mask base address with this */ | ||
21 | #define PHY_BASE 0x00020000 /* offset of PHY register are */ | ||
22 | #define REG_BASE 0x00040000 /* offset of Midway register area */ | ||
23 | #define RAM_BASE 0x00200000 /* offset of RAM area */ | ||
24 | #define RAM_INCREMENT 0x00020000 /* probe for RAM every 128kB */ | ||
25 | |||
26 | #define MID_VCI_BASE RAM_BASE | ||
27 | #define MID_DMA_RX_BASE (MID_VCI_BASE+NR_VCI*16) | ||
28 | #define MID_DMA_TX_BASE (MID_DMA_RX_BASE+NR_DMA_RX*8) | ||
29 | #define MID_SERVICE_BASE (MID_DMA_TX_BASE+NR_DMA_TX*8) | ||
30 | #define MID_FREE_BASE (MID_SERVICE_BASE+NR_SERVICE*4) | ||
31 | |||
32 | #define MAC_LEN 6 /* atm.h */ | ||
33 | |||
34 | #define MID_MIN_BUF_SIZE (1024) /* 1 kB is minimum */ | ||
35 | #define MID_MAX_BUF_SIZE (128*1024) /* 128 kB is maximum */ | ||
36 | |||
37 | #define RX_DESCR_SIZE 1 /* RX PDU descr is 1 longword */ | ||
38 | #define TX_DESCR_SIZE 2 /* TX PDU descr is 2 longwords */ | ||
39 | #define AAL5_TRAILER (ATM_AAL5_TRAILER/4) /* AAL5 trailer is 2 longwords */ | ||
40 | |||
41 | #define TX_GAP 8 /* TX buffer gap (words) */ | ||
42 | |||
43 | /* | ||
44 | * Midway Reset/ID | ||
45 | * | ||
46 | * All values read-only. Writing to this register resets Midway chip. | ||
47 | */ | ||
48 | |||
49 | #define MID_RES_ID_MCON 0x00 /* Midway Reset/ID */ | ||
50 | |||
51 | #define MID_ID 0xf0000000 /* Midway version */ | ||
52 | #define MID_SHIFT 24 | ||
53 | #define MID_MOTHER_ID 0x00000700 /* mother board id */ | ||
54 | #define MID_MOTHER_SHIFT 8 | ||
55 | #define MID_CON_TI 0x00000080 /* 0: normal ctrl; 1: SABRE */ | ||
56 | #define MID_CON_SUNI 0x00000040 /* 0: UTOPIA; 1: SUNI */ | ||
57 | #define MID_CON_V6 0x00000020 /* 0: non-pipel UTOPIA (required iff | ||
58 | !CON_SUNI; 1: UTOPIA */ | ||
59 | #define DAUGTHER_ID 0x0000001f /* daugther board id */ | ||
60 | |||
61 | /* | ||
62 | * Interrupt Status Acknowledge, Interrupt Status & Interrupt Enable | ||
63 | */ | ||
64 | |||
65 | #define MID_ISA 0x01 /* Interrupt Status Acknowledge */ | ||
66 | #define MID_IS 0x02 /* Interrupt Status */ | ||
67 | #define MID_IE 0x03 /* Interrupt Enable */ | ||
68 | |||
69 | #define MID_TX_COMPLETE_7 0x00010000 /* channel N completed a PDU */ | ||
70 | #define MID_TX_COMPLETE_6 0x00008000 /* transmission */ | ||
71 | #define MID_TX_COMPLETE_5 0x00004000 | ||
72 | #define MID_TX_COMPLETE_4 0x00002000 | ||
73 | #define MID_TX_COMPLETE_3 0x00001000 | ||
74 | #define MID_TX_COMPLETE_2 0x00000800 | ||
75 | #define MID_TX_COMPLETE_1 0x00000400 | ||
76 | #define MID_TX_COMPLETE_0 0x00000200 | ||
77 | #define MID_TX_COMPLETE 0x0001fe00 /* any TX */ | ||
78 | #define MID_TX_DMA_OVFL 0x00000100 /* DMA to adapter overflow */ | ||
79 | #define MID_TX_IDENT_MISM 0x00000080 /* TX: ident mismatch => halted */ | ||
80 | #define MID_DMA_LERR_ACK 0x00000040 /* LERR - SBus ? */ | ||
81 | #define MID_DMA_ERR_ACK 0x00000020 /* DMA error */ | ||
82 | #define MID_RX_DMA_COMPLETE 0x00000010 /* DMA to host done */ | ||
83 | #define MID_TX_DMA_COMPLETE 0x00000008 /* DMA from host done */ | ||
84 | #define MID_SERVICE 0x00000004 /* something in service list */ | ||
85 | #define MID_SUNI_INT 0x00000002 /* interrupt from SUNI */ | ||
86 | #define MID_STAT_OVFL 0x00000001 /* statistics overflow */ | ||
87 | |||
88 | /* | ||
89 | * Master Control/Status | ||
90 | */ | ||
91 | |||
92 | #define MID_MC_S 0x04 | ||
93 | |||
94 | #define MID_INT_SELECT 0x000001C0 /* Interrupt level (000: off) */ | ||
95 | #define MID_INT_SEL_SHIFT 6 | ||
96 | #define MID_TX_LOCK_MODE 0x00000020 /* 0: streaming; 1: TX ovfl->lock */ | ||
97 | #define MID_DMA_ENABLE 0x00000010 /* R: 0: disable; 1: enable | ||
98 | W: 0: no change; 1: enable */ | ||
99 | #define MID_TX_ENABLE 0x00000008 /* R: 0: TX disabled; 1: enabled | ||
100 | W: 0: no change; 1: enable */ | ||
101 | #define MID_RX_ENABLE 0x00000004 /* like TX */ | ||
102 | #define MID_WAIT_1MS 0x00000002 /* R: 0: timer not running; 1: running | ||
103 | W: 0: no change; 1: no interrupts | ||
104 | for 1 ms */ | ||
105 | #define MID_WAIT_500US 0x00000001 /* like WAIT_1MS, but 0.5 ms */ | ||
106 | |||
107 | /* | ||
108 | * Statistics | ||
109 | * | ||
110 | * Cleared when reading. | ||
111 | */ | ||
112 | |||
113 | #define MID_STAT 0x05 | ||
114 | |||
115 | #define MID_VCI_TRASH 0xFFFF0000 /* trashed cells because of VCI mode */ | ||
116 | #define MID_VCI_TRASH_SHIFT 16 | ||
117 | #define MID_OVFL_TRASH 0x0000FFFF /* trashed cells because of overflow */ | ||
118 | |||
119 | /* | ||
120 | * Address registers | ||
121 | */ | ||
122 | |||
123 | #define MID_SERV_WRITE 0x06 /* free pos in service area (R, 10 bits) */ | ||
124 | #define MID_DMA_ADDR 0x07 /* virtual DMA address (R, 32 bits) */ | ||
125 | #define MID_DMA_WR_RX 0x08 /* (RW, 9 bits) */ | ||
126 | #define MID_DMA_RD_RX 0x09 | ||
127 | #define MID_DMA_WR_TX 0x0A | ||
128 | #define MID_DMA_RD_TX 0x0B | ||
129 | |||
130 | /* | ||
131 | * Transmit Place Registers (0x10+4*channel) | ||
132 | */ | ||
133 | |||
134 | #define MID_TX_PLACE(c) (0x10+4*(c)) | ||
135 | |||
136 | #define MID_SIZE 0x00003800 /* size, N*256 x 32 bit */ | ||
137 | #define MID_SIZE_SHIFT 11 | ||
138 | #define MID_LOCATION 0x000007FF /* location in adapter memory (word) */ | ||
139 | |||
140 | #define MID_LOC_SKIP 8 /* 8 bits of location are always zero | ||
141 | (applies to all uses of location) */ | ||
142 | |||
143 | /* | ||
144 | * Transmit ReadPtr Registers (0x11+4*channel) | ||
145 | */ | ||
146 | |||
147 | #define MID_TX_RDPTR(c) (0x11+4*(c)) | ||
148 | |||
149 | #define MID_READ_PTR 0x00007FFF /* next word for PHY */ | ||
150 | |||
151 | /* | ||
152 | * Transmit DescrStart Registers (0x12+4*channel) | ||
153 | */ | ||
154 | |||
155 | #define MID_TX_DESCRSTART(c) (0x12+4*(c)) | ||
156 | |||
157 | #define MID_DESCR_START 0x00007FFF /* seg buffer being DMAed */ | ||
158 | |||
159 | #define ENI155_MAGIC 0xa54b872d | ||
160 | |||
161 | struct midway_eprom { | ||
162 | unsigned char mac[MAC_LEN],inv_mac[MAC_LEN]; | ||
163 | unsigned char pad[36]; | ||
164 | u32 serial,inv_serial; | ||
165 | u32 magic,inv_magic; | ||
166 | }; | ||
167 | |||
168 | |||
169 | /* | ||
170 | * VCI table entry | ||
171 | */ | ||
172 | |||
173 | #define MID_VCI_IN_SERVICE 0x00000001 /* set if VCI is currently in | ||
174 | service list */ | ||
175 | #define MID_VCI_SIZE 0x00038000 /* reassembly buffer size, | ||
176 | 2*<size> kB */ | ||
177 | #define MID_VCI_SIZE_SHIFT 15 | ||
178 | #define MID_VCI_LOCATION 0x1ffc0000 /* buffer location */ | ||
179 | #define MID_VCI_LOCATION_SHIFT 18 | ||
180 | #define MID_VCI_PTI_MODE 0x20000000 /* 0: trash, 1: preserve */ | ||
181 | #define MID_VCI_MODE 0xc0000000 | ||
182 | #define MID_VCI_MODE_SHIFT 30 | ||
183 | #define MID_VCI_READ 0x00007fff | ||
184 | #define MID_VCI_READ_SHIFT 0 | ||
185 | #define MID_VCI_DESCR 0x7fff0000 | ||
186 | #define MID_VCI_DESCR_SHIFT 16 | ||
187 | #define MID_VCI_COUNT 0x000007ff | ||
188 | #define MID_VCI_COUNT_SHIFT 0 | ||
189 | #define MID_VCI_STATE 0x0000c000 | ||
190 | #define MID_VCI_STATE_SHIFT 14 | ||
191 | #define MID_VCI_WRITE 0x7fff0000 | ||
192 | #define MID_VCI_WRITE_SHIFT 16 | ||
193 | |||
194 | #define MID_MODE_TRASH 0 | ||
195 | #define MID_MODE_RAW 1 | ||
196 | #define MID_MODE_AAL5 2 | ||
197 | |||
198 | /* | ||
199 | * Reassembly buffer descriptor | ||
200 | */ | ||
201 | |||
202 | #define MID_RED_COUNT 0x000007ff | ||
203 | #define MID_RED_CRC_ERR 0x00000800 | ||
204 | #define MID_RED_T 0x00001000 | ||
205 | #define MID_RED_CE 0x00010000 | ||
206 | #define MID_RED_CLP 0x01000000 | ||
207 | #define MID_RED_IDEN 0xfe000000 | ||
208 | #define MID_RED_SHIFT 25 | ||
209 | |||
210 | #define MID_RED_RX_ID 0x1b /* constant identifier */ | ||
211 | |||
212 | /* | ||
213 | * Segmentation buffer descriptor | ||
214 | */ | ||
215 | |||
216 | #define MID_SEG_COUNT MID_RED_COUNT | ||
217 | #define MID_SEG_RATE 0x01f80000 | ||
218 | #define MID_SEG_RATE_SHIFT 19 | ||
219 | #define MID_SEG_PR 0x06000000 | ||
220 | #define MID_SEG_PR_SHIFT 25 | ||
221 | #define MID_SEG_AAL5 0x08000000 | ||
222 | #define MID_SEG_ID 0xf0000000 | ||
223 | #define MID_SEG_ID_SHIFT 28 | ||
224 | #define MID_SEG_MAX_RATE 63 | ||
225 | |||
226 | #define MID_SEG_CLP 0x00000001 | ||
227 | #define MID_SEG_PTI 0x0000000e | ||
228 | #define MID_SEG_PTI_SHIFT 1 | ||
229 | #define MID_SEG_VCI 0x00003ff0 | ||
230 | #define MID_SEG_VCI_SHIFT 4 | ||
231 | |||
232 | #define MID_SEG_TX_ID 0xb /* constant identifier */ | ||
233 | |||
234 | /* | ||
235 | * DMA entry | ||
236 | */ | ||
237 | |||
238 | #define MID_DMA_COUNT 0xffff0000 | ||
239 | #define MID_DMA_COUNT_SHIFT 16 | ||
240 | #define MID_DMA_END 0x00000020 | ||
241 | #define MID_DMA_TYPE 0x0000000f | ||
242 | |||
243 | #define MID_DT_JK 0x3 | ||
244 | #define MID_DT_WORD 0x0 | ||
245 | #define MID_DT_2W 0x7 | ||
246 | #define MID_DT_4W 0x4 | ||
247 | #define MID_DT_8W 0x5 | ||
248 | #define MID_DT_16W 0x6 | ||
249 | #define MID_DT_2WM 0xf | ||
250 | #define MID_DT_4WM 0xc | ||
251 | #define MID_DT_8WM 0xd | ||
252 | #define MID_DT_16WM 0xe | ||
253 | |||
254 | /* only for RX*/ | ||
255 | #define MID_DMA_VCI 0x0000ffc0 | ||
256 | #define MID_DMA_VCI_SHIFT 6 | ||
257 | |||
258 | /* only for TX */ | ||
259 | #define MID_DMA_CHAN 0x000001c0 | ||
260 | #define MID_DMA_CHAN_SHIFT 6 | ||
261 | |||
262 | #define MID_DT_BYTE 0x1 | ||
263 | #define MID_DT_HWORD 0x2 | ||
264 | |||
265 | #endif | ||
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c new file mode 100644 index 000000000000..85bf5c8442b0 --- /dev/null +++ b/drivers/atm/nicstar.c | |||
@@ -0,0 +1,3105 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * nicstar.c | ||
4 | * | ||
5 | * Device driver supporting CBR for IDT 77201/77211 "NICStAR" based cards. | ||
6 | * | ||
7 | * IMPORTANT: The included file nicstarmac.c was NOT WRITTEN BY ME. | ||
8 | * It was taken from the frle-0.22 device driver. | ||
9 | * As the file doesn't have a copyright notice, in the file | ||
10 | * nicstarmac.copyright I put the copyright notice from the | ||
11 | * frle-0.22 device driver. | ||
12 | * Some code is based on the nicstar driver by M. Welsh. | ||
13 | * | ||
14 | * Author: Rui Prior (rprior@inescn.pt) | ||
15 | * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999 | ||
16 | * | ||
17 | * | ||
18 | * (C) INESC 1999 | ||
19 | * | ||
20 | * | ||
21 | ******************************************************************************/ | ||
22 | |||
23 | |||
24 | /**** IMPORTANT INFORMATION *************************************************** | ||
25 | * | ||
26 | * There are currently three types of spinlocks: | ||
27 | * | ||
28 | * 1 - Per card interrupt spinlock (to protect structures and such) | ||
29 | * 2 - Per SCQ scq spinlock | ||
30 | * 3 - Per card resource spinlock (to access registers, etc.) | ||
31 | * | ||
32 | * These must NEVER be grabbed in reverse order. | ||
33 | * | ||
34 | ******************************************************************************/ | ||
35 | |||
36 | /* Header files ***************************************************************/ | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/config.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/skbuff.h> | ||
42 | #include <linux/atmdev.h> | ||
43 | #include <linux/atm.h> | ||
44 | #include <linux/pci.h> | ||
45 | #include <linux/types.h> | ||
46 | #include <linux/string.h> | ||
47 | #include <linux/delay.h> | ||
48 | #include <linux/init.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/timer.h> | ||
51 | #include <linux/interrupt.h> | ||
52 | #include <linux/bitops.h> | ||
53 | #include <asm/io.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | #include <asm/atomic.h> | ||
56 | #include "nicstar.h" | ||
57 | #ifdef CONFIG_ATM_NICSTAR_USE_SUNI | ||
58 | #include "suni.h" | ||
59 | #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ | ||
60 | #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 | ||
61 | #include "idt77105.h" | ||
62 | #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ | ||
63 | |||
64 | #if BITS_PER_LONG != 32 | ||
65 | # error FIXME: this driver requires a 32-bit platform | ||
66 | #endif | ||
67 | |||
68 | /* Additional code ************************************************************/ | ||
69 | |||
70 | #include "nicstarmac.c" | ||
71 | |||
72 | |||
73 | /* Configurable parameters ****************************************************/ | ||
74 | |||
75 | #undef PHY_LOOPBACK | ||
76 | #undef TX_DEBUG | ||
77 | #undef RX_DEBUG | ||
78 | #undef GENERAL_DEBUG | ||
79 | #undef EXTRA_DEBUG | ||
80 | |||
81 | #undef NS_USE_DESTRUCTORS /* For now keep this undefined unless you know | ||
82 | you're going to use only raw ATM */ | ||
83 | |||
84 | |||
85 | /* Do not touch these *********************************************************/ | ||
86 | |||
87 | #ifdef TX_DEBUG | ||
88 | #define TXPRINTK(args...) printk(args) | ||
89 | #else | ||
90 | #define TXPRINTK(args...) | ||
91 | #endif /* TX_DEBUG */ | ||
92 | |||
93 | #ifdef RX_DEBUG | ||
94 | #define RXPRINTK(args...) printk(args) | ||
95 | #else | ||
96 | #define RXPRINTK(args...) | ||
97 | #endif /* RX_DEBUG */ | ||
98 | |||
99 | #ifdef GENERAL_DEBUG | ||
100 | #define PRINTK(args...) printk(args) | ||
101 | #else | ||
102 | #define PRINTK(args...) | ||
103 | #endif /* GENERAL_DEBUG */ | ||
104 | |||
105 | #ifdef EXTRA_DEBUG | ||
106 | #define XPRINTK(args...) printk(args) | ||
107 | #else | ||
108 | #define XPRINTK(args...) | ||
109 | #endif /* EXTRA_DEBUG */ | ||
110 | |||
111 | |||
112 | /* Macros *********************************************************************/ | ||
113 | |||
114 | #define CMD_BUSY(card) (readl((card)->membase + STAT) & NS_STAT_CMDBZ) | ||
115 | |||
116 | #define NS_DELAY mdelay(1) | ||
117 | |||
118 | #define ALIGN_BUS_ADDR(addr, alignment) \ | ||
119 | ((((u32) (addr)) + (((u32) (alignment)) - 1)) & ~(((u32) (alignment)) - 1)) | ||
120 | #define ALIGN_ADDRESS(addr, alignment) \ | ||
121 | bus_to_virt(ALIGN_BUS_ADDR(virt_to_bus(addr), alignment)) | ||
122 | |||
123 | #undef CEIL | ||
124 | |||
125 | #ifndef ATM_SKB | ||
126 | #define ATM_SKB(s) (&(s)->atm) | ||
127 | #endif | ||
128 | |||
129 | /* Spinlock debugging stuff */ | ||
130 | #ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */ | ||
131 | #define ns_grab_int_lock(card,flags) \ | ||
132 | do { \ | ||
133 | unsigned long nsdsf, nsdsf2; \ | ||
134 | local_irq_save(flags); \ | ||
135 | save_flags(nsdsf); cli();\ | ||
136 | if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ | ||
137 | (flags)&(1<<9)?"en":"dis"); \ | ||
138 | if (spin_is_locked(&(card)->int_lock) && \ | ||
139 | (card)->cpu_int == smp_processor_id()) { \ | ||
140 | printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \ | ||
141 | __LINE__, smp_processor_id(), (card)->has_int_lock, \ | ||
142 | (card)->cpu_int); \ | ||
143 | printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | ||
144 | } \ | ||
145 | if (spin_is_locked(&(card)->res_lock) && \ | ||
146 | (card)->cpu_res == smp_processor_id()) { \ | ||
147 | printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \ | ||
148 | __LINE__, smp_processor_id(), (card)->has_res_lock, \ | ||
149 | (card)->cpu_res); \ | ||
150 | printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | ||
151 | } \ | ||
152 | spin_lock_irq(&(card)->int_lock); \ | ||
153 | (card)->has_int_lock = __LINE__; \ | ||
154 | (card)->cpu_int = smp_processor_id(); \ | ||
155 | restore_flags(nsdsf); } while (0) | ||
156 | #define ns_grab_res_lock(card,flags) \ | ||
157 | do { \ | ||
158 | unsigned long nsdsf, nsdsf2; \ | ||
159 | local_irq_save(flags); \ | ||
160 | save_flags(nsdsf); cli();\ | ||
161 | if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ | ||
162 | (flags)&(1<<9)?"en":"dis"); \ | ||
163 | if (spin_is_locked(&(card)->res_lock) && \ | ||
164 | (card)->cpu_res == smp_processor_id()) { \ | ||
165 | printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \ | ||
166 | __LINE__, smp_processor_id(), (card)->has_res_lock, \ | ||
167 | (card)->cpu_res); \ | ||
168 | printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | ||
169 | } \ | ||
170 | spin_lock_irq(&(card)->res_lock); \ | ||
171 | (card)->has_res_lock = __LINE__; \ | ||
172 | (card)->cpu_res = smp_processor_id(); \ | ||
173 | restore_flags(nsdsf); } while (0) | ||
174 | #define ns_grab_scq_lock(card,scq,flags) \ | ||
175 | do { \ | ||
176 | unsigned long nsdsf, nsdsf2; \ | ||
177 | local_irq_save(flags); \ | ||
178 | save_flags(nsdsf); cli();\ | ||
179 | if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ | ||
180 | (flags)&(1<<9)?"en":"dis"); \ | ||
181 | if (spin_is_locked(&(scq)->lock) && \ | ||
182 | (scq)->cpu_lock == smp_processor_id()) { \ | ||
183 | printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \ | ||
184 | __LINE__, smp_processor_id(), (scq)->has_lock, \ | ||
185 | (scq)->cpu_lock); \ | ||
186 | printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | ||
187 | } \ | ||
188 | if (spin_is_locked(&(card)->res_lock) && \ | ||
189 | (card)->cpu_res == smp_processor_id()) { \ | ||
190 | printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \ | ||
191 | __LINE__, smp_processor_id(), (card)->has_res_lock, \ | ||
192 | (card)->cpu_res); \ | ||
193 | printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ | ||
194 | } \ | ||
195 | spin_lock_irq(&(scq)->lock); \ | ||
196 | (scq)->has_lock = __LINE__; \ | ||
197 | (scq)->cpu_lock = smp_processor_id(); \ | ||
198 | restore_flags(nsdsf); } while (0) | ||
199 | #else /* !NS_DEBUG_SPINLOCKS */ | ||
200 | #define ns_grab_int_lock(card,flags) \ | ||
201 | spin_lock_irqsave(&(card)->int_lock,(flags)) | ||
202 | #define ns_grab_res_lock(card,flags) \ | ||
203 | spin_lock_irqsave(&(card)->res_lock,(flags)) | ||
204 | #define ns_grab_scq_lock(card,scq,flags) \ | ||
205 | spin_lock_irqsave(&(scq)->lock,flags) | ||
206 | #endif /* NS_DEBUG_SPINLOCKS */ | ||
207 | |||
208 | |||
209 | /* Function declarations ******************************************************/ | ||
210 | |||
211 | static u32 ns_read_sram(ns_dev *card, u32 sram_address); | ||
212 | static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count); | ||
213 | static int __devinit ns_init_card(int i, struct pci_dev *pcidev); | ||
214 | static void __devinit ns_init_card_error(ns_dev *card, int error); | ||
215 | static scq_info *get_scq(int size, u32 scd); | ||
216 | static void free_scq(scq_info *scq, struct atm_vcc *vcc); | ||
217 | static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, | ||
218 | u32 handle2, u32 addr2); | ||
219 | static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs); | ||
220 | static int ns_open(struct atm_vcc *vcc); | ||
221 | static void ns_close(struct atm_vcc *vcc); | ||
222 | static void fill_tst(ns_dev *card, int n, vc_map *vc); | ||
223 | static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
224 | static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, | ||
225 | struct sk_buff *skb); | ||
226 | static void process_tsq(ns_dev *card); | ||
227 | static void drain_scq(ns_dev *card, scq_info *scq, int pos); | ||
228 | static void process_rsq(ns_dev *card); | ||
229 | static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe); | ||
230 | #ifdef NS_USE_DESTRUCTORS | ||
231 | static void ns_sb_destructor(struct sk_buff *sb); | ||
232 | static void ns_lb_destructor(struct sk_buff *lb); | ||
233 | static void ns_hb_destructor(struct sk_buff *hb); | ||
234 | #endif /* NS_USE_DESTRUCTORS */ | ||
235 | static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb); | ||
236 | static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count); | ||
237 | static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb); | ||
238 | static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb); | ||
239 | static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb); | ||
240 | static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page); | ||
241 | static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg); | ||
242 | static void which_list(ns_dev *card, struct sk_buff *skb); | ||
243 | static void ns_poll(unsigned long arg); | ||
244 | static int ns_parse_mac(char *mac, unsigned char *esi); | ||
245 | static short ns_h2i(char c); | ||
246 | static void ns_phy_put(struct atm_dev *dev, unsigned char value, | ||
247 | unsigned long addr); | ||
248 | static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr); | ||
249 | |||
250 | |||
251 | |||
252 | /* Global variables ***********************************************************/ | ||
253 | |||
254 | static struct ns_dev *cards[NS_MAX_CARDS]; | ||
255 | static unsigned num_cards; | ||
256 | static struct atmdev_ops atm_ops = | ||
257 | { | ||
258 | .open = ns_open, | ||
259 | .close = ns_close, | ||
260 | .ioctl = ns_ioctl, | ||
261 | .send = ns_send, | ||
262 | .phy_put = ns_phy_put, | ||
263 | .phy_get = ns_phy_get, | ||
264 | .proc_read = ns_proc_read, | ||
265 | .owner = THIS_MODULE, | ||
266 | }; | ||
267 | static struct timer_list ns_timer; | ||
268 | static char *mac[NS_MAX_CARDS]; | ||
269 | module_param_array(mac, charp, NULL, 0); | ||
270 | MODULE_LICENSE("GPL"); | ||
271 | |||
272 | |||
273 | /* Functions*******************************************************************/ | ||
274 | |||
275 | static int __devinit nicstar_init_one(struct pci_dev *pcidev, | ||
276 | const struct pci_device_id *ent) | ||
277 | { | ||
278 | static int index = -1; | ||
279 | unsigned int error; | ||
280 | |||
281 | index++; | ||
282 | cards[index] = NULL; | ||
283 | |||
284 | error = ns_init_card(index, pcidev); | ||
285 | if (error) { | ||
286 | cards[index--] = NULL; /* don't increment index */ | ||
287 | goto err_out; | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | err_out: | ||
292 | return -ENODEV; | ||
293 | } | ||
294 | |||
295 | |||
296 | |||
297 | static void __devexit nicstar_remove_one(struct pci_dev *pcidev) | ||
298 | { | ||
299 | int i, j; | ||
300 | ns_dev *card = pci_get_drvdata(pcidev); | ||
301 | struct sk_buff *hb; | ||
302 | struct sk_buff *iovb; | ||
303 | struct sk_buff *lb; | ||
304 | struct sk_buff *sb; | ||
305 | |||
306 | i = card->index; | ||
307 | |||
308 | if (cards[i] == NULL) | ||
309 | return; | ||
310 | |||
311 | if (card->atmdev->phy && card->atmdev->phy->stop) | ||
312 | card->atmdev->phy->stop(card->atmdev); | ||
313 | |||
314 | /* Stop everything */ | ||
315 | writel(0x00000000, card->membase + CFG); | ||
316 | |||
317 | /* De-register device */ | ||
318 | atm_dev_deregister(card->atmdev); | ||
319 | |||
320 | /* Disable PCI device */ | ||
321 | pci_disable_device(pcidev); | ||
322 | |||
323 | /* Free up resources */ | ||
324 | j = 0; | ||
325 | PRINTK("nicstar%d: freeing %d huge buffers.\n", i, card->hbpool.count); | ||
326 | while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) | ||
327 | { | ||
328 | dev_kfree_skb_any(hb); | ||
329 | j++; | ||
330 | } | ||
331 | PRINTK("nicstar%d: %d huge buffers freed.\n", i, j); | ||
332 | j = 0; | ||
333 | PRINTK("nicstar%d: freeing %d iovec buffers.\n", i, card->iovpool.count); | ||
334 | while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) | ||
335 | { | ||
336 | dev_kfree_skb_any(iovb); | ||
337 | j++; | ||
338 | } | ||
339 | PRINTK("nicstar%d: %d iovec buffers freed.\n", i, j); | ||
340 | while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) | ||
341 | dev_kfree_skb_any(lb); | ||
342 | while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) | ||
343 | dev_kfree_skb_any(sb); | ||
344 | free_scq(card->scq0, NULL); | ||
345 | for (j = 0; j < NS_FRSCD_NUM; j++) | ||
346 | { | ||
347 | if (card->scd2vc[j] != NULL) | ||
348 | free_scq(card->scd2vc[j]->scq, card->scd2vc[j]->tx_vcc); | ||
349 | } | ||
350 | kfree(card->rsq.org); | ||
351 | kfree(card->tsq.org); | ||
352 | free_irq(card->pcidev->irq, card); | ||
353 | iounmap(card->membase); | ||
354 | kfree(card); | ||
355 | } | ||
356 | |||
357 | |||
358 | |||
359 | static struct pci_device_id nicstar_pci_tbl[] __devinitdata = | ||
360 | { | ||
361 | {PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77201, | ||
362 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
363 | {0,} /* terminate list */ | ||
364 | }; | ||
365 | MODULE_DEVICE_TABLE(pci, nicstar_pci_tbl); | ||
366 | |||
367 | |||
368 | |||
369 | static struct pci_driver nicstar_driver = { | ||
370 | .name = "nicstar", | ||
371 | .id_table = nicstar_pci_tbl, | ||
372 | .probe = nicstar_init_one, | ||
373 | .remove = __devexit_p(nicstar_remove_one), | ||
374 | }; | ||
375 | |||
376 | |||
377 | |||
378 | static int __init nicstar_init(void) | ||
379 | { | ||
380 | unsigned error = 0; /* Initialized to remove compile warning */ | ||
381 | |||
382 | XPRINTK("nicstar: nicstar_init() called.\n"); | ||
383 | |||
384 | error = pci_register_driver(&nicstar_driver); | ||
385 | |||
386 | TXPRINTK("nicstar: TX debug enabled.\n"); | ||
387 | RXPRINTK("nicstar: RX debug enabled.\n"); | ||
388 | PRINTK("nicstar: General debug enabled.\n"); | ||
389 | #ifdef PHY_LOOPBACK | ||
390 | printk("nicstar: using PHY loopback.\n"); | ||
391 | #endif /* PHY_LOOPBACK */ | ||
392 | XPRINTK("nicstar: nicstar_init() returned.\n"); | ||
393 | |||
394 | if (!error) { | ||
395 | init_timer(&ns_timer); | ||
396 | ns_timer.expires = jiffies + NS_POLL_PERIOD; | ||
397 | ns_timer.data = 0UL; | ||
398 | ns_timer.function = ns_poll; | ||
399 | add_timer(&ns_timer); | ||
400 | } | ||
401 | |||
402 | return error; | ||
403 | } | ||
404 | |||
405 | |||
406 | |||
407 | static void __exit nicstar_cleanup(void) | ||
408 | { | ||
409 | XPRINTK("nicstar: nicstar_cleanup() called.\n"); | ||
410 | |||
411 | del_timer(&ns_timer); | ||
412 | |||
413 | pci_unregister_driver(&nicstar_driver); | ||
414 | |||
415 | XPRINTK("nicstar: nicstar_cleanup() returned.\n"); | ||
416 | } | ||
417 | |||
418 | |||
419 | |||
420 | static u32 ns_read_sram(ns_dev *card, u32 sram_address) | ||
421 | { | ||
422 | unsigned long flags; | ||
423 | u32 data; | ||
424 | sram_address <<= 2; | ||
425 | sram_address &= 0x0007FFFC; /* address must be dword aligned */ | ||
426 | sram_address |= 0x50000000; /* SRAM read command */ | ||
427 | ns_grab_res_lock(card, flags); | ||
428 | while (CMD_BUSY(card)); | ||
429 | writel(sram_address, card->membase + CMD); | ||
430 | while (CMD_BUSY(card)); | ||
431 | data = readl(card->membase + DR0); | ||
432 | spin_unlock_irqrestore(&card->res_lock, flags); | ||
433 | return data; | ||
434 | } | ||
435 | |||
436 | |||
437 | |||
438 | static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count) | ||
439 | { | ||
440 | unsigned long flags; | ||
441 | int i, c; | ||
442 | count--; /* count range now is 0..3 instead of 1..4 */ | ||
443 | c = count; | ||
444 | c <<= 2; /* to use increments of 4 */ | ||
445 | ns_grab_res_lock(card, flags); | ||
446 | while (CMD_BUSY(card)); | ||
447 | for (i = 0; i <= c; i += 4) | ||
448 | writel(*(value++), card->membase + i); | ||
449 | /* Note: DR# registers are the first 4 dwords in nicstar's memspace, | ||
450 | so card->membase + DR0 == card->membase */ | ||
451 | sram_address <<= 2; | ||
452 | sram_address &= 0x0007FFFC; | ||
453 | sram_address |= (0x40000000 | count); | ||
454 | writel(sram_address, card->membase + CMD); | ||
455 | spin_unlock_irqrestore(&card->res_lock, flags); | ||
456 | } | ||
457 | |||
458 | |||
459 | static int __devinit ns_init_card(int i, struct pci_dev *pcidev) | ||
460 | { | ||
461 | int j; | ||
462 | struct ns_dev *card = NULL; | ||
463 | unsigned char pci_latency; | ||
464 | unsigned error; | ||
465 | u32 data; | ||
466 | u32 u32d[4]; | ||
467 | u32 ns_cfg_rctsize; | ||
468 | int bcount; | ||
469 | unsigned long membase; | ||
470 | |||
471 | error = 0; | ||
472 | |||
473 | if (pci_enable_device(pcidev)) | ||
474 | { | ||
475 | printk("nicstar%d: can't enable PCI device\n", i); | ||
476 | error = 2; | ||
477 | ns_init_card_error(card, error); | ||
478 | return error; | ||
479 | } | ||
480 | |||
481 | if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) | ||
482 | { | ||
483 | printk("nicstar%d: can't allocate memory for device structure.\n", i); | ||
484 | error = 2; | ||
485 | ns_init_card_error(card, error); | ||
486 | return error; | ||
487 | } | ||
488 | cards[i] = card; | ||
489 | spin_lock_init(&card->int_lock); | ||
490 | spin_lock_init(&card->res_lock); | ||
491 | |||
492 | pci_set_drvdata(pcidev, card); | ||
493 | |||
494 | card->index = i; | ||
495 | card->atmdev = NULL; | ||
496 | card->pcidev = pcidev; | ||
497 | membase = pci_resource_start(pcidev, 1); | ||
498 | card->membase = ioremap(membase, NS_IOREMAP_SIZE); | ||
499 | if (card->membase == 0) | ||
500 | { | ||
501 | printk("nicstar%d: can't ioremap() membase.\n",i); | ||
502 | error = 3; | ||
503 | ns_init_card_error(card, error); | ||
504 | return error; | ||
505 | } | ||
506 | PRINTK("nicstar%d: membase at 0x%x.\n", i, card->membase); | ||
507 | |||
508 | pci_set_master(pcidev); | ||
509 | |||
510 | if (pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency) != 0) | ||
511 | { | ||
512 | printk("nicstar%d: can't read PCI latency timer.\n", i); | ||
513 | error = 6; | ||
514 | ns_init_card_error(card, error); | ||
515 | return error; | ||
516 | } | ||
517 | #ifdef NS_PCI_LATENCY | ||
518 | if (pci_latency < NS_PCI_LATENCY) | ||
519 | { | ||
520 | PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, NS_PCI_LATENCY); | ||
521 | for (j = 1; j < 4; j++) | ||
522 | { | ||
523 | if (pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0) | ||
524 | break; | ||
525 | } | ||
526 | if (j == 4) | ||
527 | { | ||
528 | printk("nicstar%d: can't set PCI latency timer to %d.\n", i, NS_PCI_LATENCY); | ||
529 | error = 7; | ||
530 | ns_init_card_error(card, error); | ||
531 | return error; | ||
532 | } | ||
533 | } | ||
534 | #endif /* NS_PCI_LATENCY */ | ||
535 | |||
536 | /* Clear timer overflow */ | ||
537 | data = readl(card->membase + STAT); | ||
538 | if (data & NS_STAT_TMROF) | ||
539 | writel(NS_STAT_TMROF, card->membase + STAT); | ||
540 | |||
541 | /* Software reset */ | ||
542 | writel(NS_CFG_SWRST, card->membase + CFG); | ||
543 | NS_DELAY; | ||
544 | writel(0x00000000, card->membase + CFG); | ||
545 | |||
546 | /* PHY reset */ | ||
547 | writel(0x00000008, card->membase + GP); | ||
548 | NS_DELAY; | ||
549 | writel(0x00000001, card->membase + GP); | ||
550 | NS_DELAY; | ||
551 | while (CMD_BUSY(card)); | ||
552 | writel(NS_CMD_WRITE_UTILITY | 0x00000100, card->membase + CMD); /* Sync UTOPIA with SAR clock */ | ||
553 | NS_DELAY; | ||
554 | |||
555 | /* Detect PHY type */ | ||
556 | while (CMD_BUSY(card)); | ||
557 | writel(NS_CMD_READ_UTILITY | 0x00000200, card->membase + CMD); | ||
558 | while (CMD_BUSY(card)); | ||
559 | data = readl(card->membase + DR0); | ||
560 | switch(data) { | ||
561 | case 0x00000009: | ||
562 | printk("nicstar%d: PHY seems to be 25 Mbps.\n", i); | ||
563 | card->max_pcr = ATM_25_PCR; | ||
564 | while(CMD_BUSY(card)); | ||
565 | writel(0x00000008, card->membase + DR0); | ||
566 | writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD); | ||
567 | /* Clear an eventual pending interrupt */ | ||
568 | writel(NS_STAT_SFBQF, card->membase + STAT); | ||
569 | #ifdef PHY_LOOPBACK | ||
570 | while(CMD_BUSY(card)); | ||
571 | writel(0x00000022, card->membase + DR0); | ||
572 | writel(NS_CMD_WRITE_UTILITY | 0x00000202, card->membase + CMD); | ||
573 | #endif /* PHY_LOOPBACK */ | ||
574 | break; | ||
575 | case 0x00000030: | ||
576 | case 0x00000031: | ||
577 | printk("nicstar%d: PHY seems to be 155 Mbps.\n", i); | ||
578 | card->max_pcr = ATM_OC3_PCR; | ||
579 | #ifdef PHY_LOOPBACK | ||
580 | while(CMD_BUSY(card)); | ||
581 | writel(0x00000002, card->membase + DR0); | ||
582 | writel(NS_CMD_WRITE_UTILITY | 0x00000205, card->membase + CMD); | ||
583 | #endif /* PHY_LOOPBACK */ | ||
584 | break; | ||
585 | default: | ||
586 | printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data); | ||
587 | error = 8; | ||
588 | ns_init_card_error(card, error); | ||
589 | return error; | ||
590 | } | ||
591 | writel(0x00000000, card->membase + GP); | ||
592 | |||
593 | /* Determine SRAM size */ | ||
594 | data = 0x76543210; | ||
595 | ns_write_sram(card, 0x1C003, &data, 1); | ||
596 | data = 0x89ABCDEF; | ||
597 | ns_write_sram(card, 0x14003, &data, 1); | ||
598 | if (ns_read_sram(card, 0x14003) == 0x89ABCDEF && | ||
599 | ns_read_sram(card, 0x1C003) == 0x76543210) | ||
600 | card->sram_size = 128; | ||
601 | else | ||
602 | card->sram_size = 32; | ||
603 | PRINTK("nicstar%d: %dK x 32bit SRAM size.\n", i, card->sram_size); | ||
604 | |||
605 | card->rct_size = NS_MAX_RCTSIZE; | ||
606 | |||
607 | #if (NS_MAX_RCTSIZE == 4096) | ||
608 | if (card->sram_size == 128) | ||
609 | printk("nicstar%d: limiting maximum VCI. See NS_MAX_RCTSIZE in nicstar.h\n", i); | ||
610 | #elif (NS_MAX_RCTSIZE == 16384) | ||
611 | if (card->sram_size == 32) | ||
612 | { | ||
613 | printk("nicstar%d: wasting memory. See NS_MAX_RCTSIZE in nicstar.h\n", i); | ||
614 | card->rct_size = 4096; | ||
615 | } | ||
616 | #else | ||
617 | #error NS_MAX_RCTSIZE must be either 4096 or 16384 in nicstar.c | ||
618 | #endif | ||
619 | |||
620 | card->vpibits = NS_VPIBITS; | ||
621 | if (card->rct_size == 4096) | ||
622 | card->vcibits = 12 - NS_VPIBITS; | ||
623 | else /* card->rct_size == 16384 */ | ||
624 | card->vcibits = 14 - NS_VPIBITS; | ||
625 | |||
626 | /* Initialize the nicstar eeprom/eprom stuff, for the MAC addr */ | ||
627 | if (mac[i] == NULL) | ||
628 | nicstar_init_eprom(card->membase); | ||
629 | |||
630 | if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT | SA_SHIRQ, "nicstar", card) != 0) | ||
631 | { | ||
632 | printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); | ||
633 | error = 9; | ||
634 | ns_init_card_error(card, error); | ||
635 | return error; | ||
636 | } | ||
637 | |||
638 | /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ | ||
639 | writel(0x00000000, card->membase + VPM); | ||
640 | |||
641 | /* Initialize TSQ */ | ||
642 | card->tsq.org = kmalloc(NS_TSQSIZE + NS_TSQ_ALIGNMENT, GFP_KERNEL); | ||
643 | if (card->tsq.org == NULL) | ||
644 | { | ||
645 | printk("nicstar%d: can't allocate TSQ.\n", i); | ||
646 | error = 10; | ||
647 | ns_init_card_error(card, error); | ||
648 | return error; | ||
649 | } | ||
650 | card->tsq.base = (ns_tsi *) ALIGN_ADDRESS(card->tsq.org, NS_TSQ_ALIGNMENT); | ||
651 | card->tsq.next = card->tsq.base; | ||
652 | card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1); | ||
653 | for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++) | ||
654 | ns_tsi_init(card->tsq.base + j); | ||
655 | writel(0x00000000, card->membase + TSQH); | ||
656 | writel((u32) virt_to_bus(card->tsq.base), card->membase + TSQB); | ||
657 | PRINTK("nicstar%d: TSQ base at 0x%x 0x%x 0x%x.\n", i, (u32) card->tsq.base, | ||
658 | (u32) virt_to_bus(card->tsq.base), readl(card->membase + TSQB)); | ||
659 | |||
660 | /* Initialize RSQ */ | ||
661 | card->rsq.org = kmalloc(NS_RSQSIZE + NS_RSQ_ALIGNMENT, GFP_KERNEL); | ||
662 | if (card->rsq.org == NULL) | ||
663 | { | ||
664 | printk("nicstar%d: can't allocate RSQ.\n", i); | ||
665 | error = 11; | ||
666 | ns_init_card_error(card, error); | ||
667 | return error; | ||
668 | } | ||
669 | card->rsq.base = (ns_rsqe *) ALIGN_ADDRESS(card->rsq.org, NS_RSQ_ALIGNMENT); | ||
670 | card->rsq.next = card->rsq.base; | ||
671 | card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1); | ||
672 | for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++) | ||
673 | ns_rsqe_init(card->rsq.base + j); | ||
674 | writel(0x00000000, card->membase + RSQH); | ||
675 | writel((u32) virt_to_bus(card->rsq.base), card->membase + RSQB); | ||
676 | PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base); | ||
677 | |||
678 | /* Initialize SCQ0, the only VBR SCQ used */ | ||
679 | card->scq1 = (scq_info *) NULL; | ||
680 | card->scq2 = (scq_info *) NULL; | ||
681 | card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0); | ||
682 | if (card->scq0 == (scq_info *) NULL) | ||
683 | { | ||
684 | printk("nicstar%d: can't get SCQ0.\n", i); | ||
685 | error = 12; | ||
686 | ns_init_card_error(card, error); | ||
687 | return error; | ||
688 | } | ||
689 | u32d[0] = (u32) virt_to_bus(card->scq0->base); | ||
690 | u32d[1] = (u32) 0x00000000; | ||
691 | u32d[2] = (u32) 0xffffffff; | ||
692 | u32d[3] = (u32) 0x00000000; | ||
693 | ns_write_sram(card, NS_VRSCD0, u32d, 4); | ||
694 | ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */ | ||
695 | ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */ | ||
696 | card->scq0->scd = NS_VRSCD0; | ||
697 | PRINTK("nicstar%d: VBR-SCQ0 base at 0x%x.\n", i, (u32) card->scq0->base); | ||
698 | |||
699 | /* Initialize TSTs */ | ||
700 | card->tst_addr = NS_TST0; | ||
701 | card->tst_free_entries = NS_TST_NUM_ENTRIES; | ||
702 | data = NS_TST_OPCODE_VARIABLE; | ||
703 | for (j = 0; j < NS_TST_NUM_ENTRIES; j++) | ||
704 | ns_write_sram(card, NS_TST0 + j, &data, 1); | ||
705 | data = ns_tste_make(NS_TST_OPCODE_END, NS_TST0); | ||
706 | ns_write_sram(card, NS_TST0 + NS_TST_NUM_ENTRIES, &data, 1); | ||
707 | for (j = 0; j < NS_TST_NUM_ENTRIES; j++) | ||
708 | ns_write_sram(card, NS_TST1 + j, &data, 1); | ||
709 | data = ns_tste_make(NS_TST_OPCODE_END, NS_TST1); | ||
710 | ns_write_sram(card, NS_TST1 + NS_TST_NUM_ENTRIES, &data, 1); | ||
711 | for (j = 0; j < NS_TST_NUM_ENTRIES; j++) | ||
712 | card->tste2vc[j] = NULL; | ||
713 | writel(NS_TST0 << 2, card->membase + TSTB); | ||
714 | |||
715 | |||
716 | /* Initialize RCT. AAL type is set on opening the VC. */ | ||
717 | #ifdef RCQ_SUPPORT | ||
718 | u32d[0] = NS_RCTE_RAWCELLINTEN; | ||
719 | #else | ||
720 | u32d[0] = 0x00000000; | ||
721 | #endif /* RCQ_SUPPORT */ | ||
722 | u32d[1] = 0x00000000; | ||
723 | u32d[2] = 0x00000000; | ||
724 | u32d[3] = 0xFFFFFFFF; | ||
725 | for (j = 0; j < card->rct_size; j++) | ||
726 | ns_write_sram(card, j * 4, u32d, 4); | ||
727 | |||
728 | memset(card->vcmap, 0, NS_MAX_RCTSIZE * sizeof(vc_map)); | ||
729 | |||
730 | for (j = 0; j < NS_FRSCD_NUM; j++) | ||
731 | card->scd2vc[j] = NULL; | ||
732 | |||
733 | /* Initialize buffer levels */ | ||
734 | card->sbnr.min = MIN_SB; | ||
735 | card->sbnr.init = NUM_SB; | ||
736 | card->sbnr.max = MAX_SB; | ||
737 | card->lbnr.min = MIN_LB; | ||
738 | card->lbnr.init = NUM_LB; | ||
739 | card->lbnr.max = MAX_LB; | ||
740 | card->iovnr.min = MIN_IOVB; | ||
741 | card->iovnr.init = NUM_IOVB; | ||
742 | card->iovnr.max = MAX_IOVB; | ||
743 | card->hbnr.min = MIN_HB; | ||
744 | card->hbnr.init = NUM_HB; | ||
745 | card->hbnr.max = MAX_HB; | ||
746 | |||
747 | card->sm_handle = 0x00000000; | ||
748 | card->sm_addr = 0x00000000; | ||
749 | card->lg_handle = 0x00000000; | ||
750 | card->lg_addr = 0x00000000; | ||
751 | |||
752 | card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */ | ||
753 | |||
754 | /* Pre-allocate some huge buffers */ | ||
755 | skb_queue_head_init(&card->hbpool.queue); | ||
756 | card->hbpool.count = 0; | ||
757 | for (j = 0; j < NUM_HB; j++) | ||
758 | { | ||
759 | struct sk_buff *hb; | ||
760 | hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); | ||
761 | if (hb == NULL) | ||
762 | { | ||
763 | printk("nicstar%d: can't allocate %dth of %d huge buffers.\n", | ||
764 | i, j, NUM_HB); | ||
765 | error = 13; | ||
766 | ns_init_card_error(card, error); | ||
767 | return error; | ||
768 | } | ||
769 | skb_queue_tail(&card->hbpool.queue, hb); | ||
770 | card->hbpool.count++; | ||
771 | } | ||
772 | |||
773 | |||
774 | /* Allocate large buffers */ | ||
775 | skb_queue_head_init(&card->lbpool.queue); | ||
776 | card->lbpool.count = 0; /* Not used */ | ||
777 | for (j = 0; j < NUM_LB; j++) | ||
778 | { | ||
779 | struct sk_buff *lb; | ||
780 | lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); | ||
781 | if (lb == NULL) | ||
782 | { | ||
783 | printk("nicstar%d: can't allocate %dth of %d large buffers.\n", | ||
784 | i, j, NUM_LB); | ||
785 | error = 14; | ||
786 | ns_init_card_error(card, error); | ||
787 | return error; | ||
788 | } | ||
789 | skb_queue_tail(&card->lbpool.queue, lb); | ||
790 | skb_reserve(lb, NS_SMBUFSIZE); | ||
791 | push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | ||
792 | /* Due to the implementation of push_rxbufs() this is 1, not 0 */ | ||
793 | if (j == 1) | ||
794 | { | ||
795 | card->rcbuf = lb; | ||
796 | card->rawch = (u32) virt_to_bus(lb->data); | ||
797 | } | ||
798 | } | ||
799 | /* Test for strange behaviour which leads to crashes */ | ||
800 | if ((bcount = ns_stat_lfbqc_get(readl(card->membase + STAT))) < card->lbnr.min) | ||
801 | { | ||
802 | printk("nicstar%d: Strange... Just allocated %d large buffers and lfbqc = %d.\n", | ||
803 | i, j, bcount); | ||
804 | error = 14; | ||
805 | ns_init_card_error(card, error); | ||
806 | return error; | ||
807 | } | ||
808 | |||
809 | |||
810 | /* Allocate small buffers */ | ||
811 | skb_queue_head_init(&card->sbpool.queue); | ||
812 | card->sbpool.count = 0; /* Not used */ | ||
813 | for (j = 0; j < NUM_SB; j++) | ||
814 | { | ||
815 | struct sk_buff *sb; | ||
816 | sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); | ||
817 | if (sb == NULL) | ||
818 | { | ||
819 | printk("nicstar%d: can't allocate %dth of %d small buffers.\n", | ||
820 | i, j, NUM_SB); | ||
821 | error = 15; | ||
822 | ns_init_card_error(card, error); | ||
823 | return error; | ||
824 | } | ||
825 | skb_queue_tail(&card->sbpool.queue, sb); | ||
826 | skb_reserve(sb, NS_AAL0_HEADER); | ||
827 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | ||
828 | } | ||
829 | /* Test for strange behaviour which leads to crashes */ | ||
830 | if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min) | ||
831 | { | ||
832 | printk("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n", | ||
833 | i, j, bcount); | ||
834 | error = 15; | ||
835 | ns_init_card_error(card, error); | ||
836 | return error; | ||
837 | } | ||
838 | |||
839 | |||
840 | /* Allocate iovec buffers */ | ||
841 | skb_queue_head_init(&card->iovpool.queue); | ||
842 | card->iovpool.count = 0; | ||
843 | for (j = 0; j < NUM_IOVB; j++) | ||
844 | { | ||
845 | struct sk_buff *iovb; | ||
846 | iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); | ||
847 | if (iovb == NULL) | ||
848 | { | ||
849 | printk("nicstar%d: can't allocate %dth of %d iovec buffers.\n", | ||
850 | i, j, NUM_IOVB); | ||
851 | error = 16; | ||
852 | ns_init_card_error(card, error); | ||
853 | return error; | ||
854 | } | ||
855 | skb_queue_tail(&card->iovpool.queue, iovb); | ||
856 | card->iovpool.count++; | ||
857 | } | ||
858 | |||
859 | card->intcnt = 0; | ||
860 | |||
861 | /* Configure NICStAR */ | ||
862 | if (card->rct_size == 4096) | ||
863 | ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES; | ||
864 | else /* (card->rct_size == 16384) */ | ||
865 | ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES; | ||
866 | |||
867 | card->efbie = 1; | ||
868 | |||
869 | /* Register device */ | ||
870 | card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL); | ||
871 | if (card->atmdev == NULL) | ||
872 | { | ||
873 | printk("nicstar%d: can't register device.\n", i); | ||
874 | error = 17; | ||
875 | ns_init_card_error(card, error); | ||
876 | return error; | ||
877 | } | ||
878 | |||
879 | if (ns_parse_mac(mac[i], card->atmdev->esi)) { | ||
880 | nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET, | ||
881 | card->atmdev->esi, 6); | ||
882 | if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) == 0) { | ||
883 | nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT, | ||
884 | card->atmdev->esi, 6); | ||
885 | } | ||
886 | } | ||
887 | |||
888 | printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i, | ||
889 | card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2], | ||
890 | card->atmdev->esi[3], card->atmdev->esi[4], card->atmdev->esi[5]); | ||
891 | |||
892 | card->atmdev->dev_data = card; | ||
893 | card->atmdev->ci_range.vpi_bits = card->vpibits; | ||
894 | card->atmdev->ci_range.vci_bits = card->vcibits; | ||
895 | card->atmdev->link_rate = card->max_pcr; | ||
896 | card->atmdev->phy = NULL; | ||
897 | |||
898 | #ifdef CONFIG_ATM_NICSTAR_USE_SUNI | ||
899 | if (card->max_pcr == ATM_OC3_PCR) | ||
900 | suni_init(card->atmdev); | ||
901 | #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ | ||
902 | |||
903 | #ifdef CONFIG_ATM_NICSTAR_USE_IDT77105 | ||
904 | if (card->max_pcr == ATM_25_PCR) | ||
905 | idt77105_init(card->atmdev); | ||
906 | #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ | ||
907 | |||
908 | if (card->atmdev->phy && card->atmdev->phy->start) | ||
909 | card->atmdev->phy->start(card->atmdev); | ||
910 | |||
911 | writel(NS_CFG_RXPATH | | ||
912 | NS_CFG_SMBUFSIZE | | ||
913 | NS_CFG_LGBUFSIZE | | ||
914 | NS_CFG_EFBIE | | ||
915 | NS_CFG_RSQSIZE | | ||
916 | NS_CFG_VPIBITS | | ||
917 | ns_cfg_rctsize | | ||
918 | NS_CFG_RXINT_NODELAY | | ||
919 | NS_CFG_RAWIE | /* Only enabled if RCQ_SUPPORT */ | ||
920 | NS_CFG_RSQAFIE | | ||
921 | NS_CFG_TXEN | | ||
922 | NS_CFG_TXIE | | ||
923 | NS_CFG_TSQFIE_OPT | /* Only enabled if ENABLE_TSQFIE */ | ||
924 | NS_CFG_PHYIE, | ||
925 | card->membase + CFG); | ||
926 | |||
927 | num_cards++; | ||
928 | |||
929 | return error; | ||
930 | } | ||
931 | |||
932 | |||
933 | |||
934 | static void __devinit ns_init_card_error(ns_dev *card, int error) | ||
935 | { | ||
936 | if (error >= 17) | ||
937 | { | ||
938 | writel(0x00000000, card->membase + CFG); | ||
939 | } | ||
940 | if (error >= 16) | ||
941 | { | ||
942 | struct sk_buff *iovb; | ||
943 | while ((iovb = skb_dequeue(&card->iovpool.queue)) != NULL) | ||
944 | dev_kfree_skb_any(iovb); | ||
945 | } | ||
946 | if (error >= 15) | ||
947 | { | ||
948 | struct sk_buff *sb; | ||
949 | while ((sb = skb_dequeue(&card->sbpool.queue)) != NULL) | ||
950 | dev_kfree_skb_any(sb); | ||
951 | free_scq(card->scq0, NULL); | ||
952 | } | ||
953 | if (error >= 14) | ||
954 | { | ||
955 | struct sk_buff *lb; | ||
956 | while ((lb = skb_dequeue(&card->lbpool.queue)) != NULL) | ||
957 | dev_kfree_skb_any(lb); | ||
958 | } | ||
959 | if (error >= 13) | ||
960 | { | ||
961 | struct sk_buff *hb; | ||
962 | while ((hb = skb_dequeue(&card->hbpool.queue)) != NULL) | ||
963 | dev_kfree_skb_any(hb); | ||
964 | } | ||
965 | if (error >= 12) | ||
966 | { | ||
967 | kfree(card->rsq.org); | ||
968 | } | ||
969 | if (error >= 11) | ||
970 | { | ||
971 | kfree(card->tsq.org); | ||
972 | } | ||
973 | if (error >= 10) | ||
974 | { | ||
975 | free_irq(card->pcidev->irq, card); | ||
976 | } | ||
977 | if (error >= 4) | ||
978 | { | ||
979 | iounmap(card->membase); | ||
980 | } | ||
981 | if (error >= 3) | ||
982 | { | ||
983 | pci_disable_device(card->pcidev); | ||
984 | kfree(card); | ||
985 | } | ||
986 | } | ||
987 | |||
988 | |||
989 | |||
990 | static scq_info *get_scq(int size, u32 scd) | ||
991 | { | ||
992 | scq_info *scq; | ||
993 | int i; | ||
994 | |||
995 | if (size != VBR_SCQSIZE && size != CBR_SCQSIZE) | ||
996 | return (scq_info *) NULL; | ||
997 | |||
998 | scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL); | ||
999 | if (scq == (scq_info *) NULL) | ||
1000 | return (scq_info *) NULL; | ||
1001 | scq->org = kmalloc(2 * size, GFP_KERNEL); | ||
1002 | if (scq->org == NULL) | ||
1003 | { | ||
1004 | kfree(scq); | ||
1005 | return (scq_info *) NULL; | ||
1006 | } | ||
1007 | scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) * | ||
1008 | (size / NS_SCQE_SIZE), GFP_KERNEL); | ||
1009 | if (scq->skb == (struct sk_buff **) NULL) | ||
1010 | { | ||
1011 | kfree(scq->org); | ||
1012 | kfree(scq); | ||
1013 | return (scq_info *) NULL; | ||
1014 | } | ||
1015 | scq->num_entries = size / NS_SCQE_SIZE; | ||
1016 | scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size); | ||
1017 | scq->next = scq->base; | ||
1018 | scq->last = scq->base + (scq->num_entries - 1); | ||
1019 | scq->tail = scq->last; | ||
1020 | scq->scd = scd; | ||
1021 | scq->num_entries = size / NS_SCQE_SIZE; | ||
1022 | scq->tbd_count = 0; | ||
1023 | init_waitqueue_head(&scq->scqfull_waitq); | ||
1024 | scq->full = 0; | ||
1025 | spin_lock_init(&scq->lock); | ||
1026 | |||
1027 | for (i = 0; i < scq->num_entries; i++) | ||
1028 | scq->skb[i] = NULL; | ||
1029 | |||
1030 | return scq; | ||
1031 | } | ||
1032 | |||
1033 | |||
1034 | |||
1035 | /* For variable rate SCQ vcc must be NULL */ | ||
1036 | static void free_scq(scq_info *scq, struct atm_vcc *vcc) | ||
1037 | { | ||
1038 | int i; | ||
1039 | |||
1040 | if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) | ||
1041 | for (i = 0; i < scq->num_entries; i++) | ||
1042 | { | ||
1043 | if (scq->skb[i] != NULL) | ||
1044 | { | ||
1045 | vcc = ATM_SKB(scq->skb[i])->vcc; | ||
1046 | if (vcc->pop != NULL) | ||
1047 | vcc->pop(vcc, scq->skb[i]); | ||
1048 | else | ||
1049 | dev_kfree_skb_any(scq->skb[i]); | ||
1050 | } | ||
1051 | } | ||
1052 | else /* vcc must be != NULL */ | ||
1053 | { | ||
1054 | if (vcc == NULL) | ||
1055 | { | ||
1056 | printk("nicstar: free_scq() called with vcc == NULL for fixed rate scq."); | ||
1057 | for (i = 0; i < scq->num_entries; i++) | ||
1058 | dev_kfree_skb_any(scq->skb[i]); | ||
1059 | } | ||
1060 | else | ||
1061 | for (i = 0; i < scq->num_entries; i++) | ||
1062 | { | ||
1063 | if (scq->skb[i] != NULL) | ||
1064 | { | ||
1065 | if (vcc->pop != NULL) | ||
1066 | vcc->pop(vcc, scq->skb[i]); | ||
1067 | else | ||
1068 | dev_kfree_skb_any(scq->skb[i]); | ||
1069 | } | ||
1070 | } | ||
1071 | } | ||
1072 | kfree(scq->skb); | ||
1073 | kfree(scq->org); | ||
1074 | kfree(scq); | ||
1075 | } | ||
1076 | |||
1077 | |||
1078 | |||
1079 | /* The handles passed must be pointers to the sk_buff containing the small | ||
1080 | or large buffer(s) cast to u32. */ | ||
1081 | static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, | ||
1082 | u32 handle2, u32 addr2) | ||
1083 | { | ||
1084 | u32 stat; | ||
1085 | unsigned long flags; | ||
1086 | |||
1087 | |||
1088 | #ifdef GENERAL_DEBUG | ||
1089 | if (!addr1) | ||
1090 | printk("nicstar%d: push_rxbufs called with addr1 = 0.\n", card->index); | ||
1091 | #endif /* GENERAL_DEBUG */ | ||
1092 | |||
1093 | stat = readl(card->membase + STAT); | ||
1094 | card->sbfqc = ns_stat_sfbqc_get(stat); | ||
1095 | card->lbfqc = ns_stat_lfbqc_get(stat); | ||
1096 | if (type == BUF_SM) | ||
1097 | { | ||
1098 | if (!addr2) | ||
1099 | { | ||
1100 | if (card->sm_addr) | ||
1101 | { | ||
1102 | addr2 = card->sm_addr; | ||
1103 | handle2 = card->sm_handle; | ||
1104 | card->sm_addr = 0x00000000; | ||
1105 | card->sm_handle = 0x00000000; | ||
1106 | } | ||
1107 | else /* (!sm_addr) */ | ||
1108 | { | ||
1109 | card->sm_addr = addr1; | ||
1110 | card->sm_handle = handle1; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | else /* type == BUF_LG */ | ||
1115 | { | ||
1116 | if (!addr2) | ||
1117 | { | ||
1118 | if (card->lg_addr) | ||
1119 | { | ||
1120 | addr2 = card->lg_addr; | ||
1121 | handle2 = card->lg_handle; | ||
1122 | card->lg_addr = 0x00000000; | ||
1123 | card->lg_handle = 0x00000000; | ||
1124 | } | ||
1125 | else /* (!lg_addr) */ | ||
1126 | { | ||
1127 | card->lg_addr = addr1; | ||
1128 | card->lg_handle = handle1; | ||
1129 | } | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1133 | if (addr2) | ||
1134 | { | ||
1135 | if (type == BUF_SM) | ||
1136 | { | ||
1137 | if (card->sbfqc >= card->sbnr.max) | ||
1138 | { | ||
1139 | skb_unlink((struct sk_buff *) handle1); | ||
1140 | dev_kfree_skb_any((struct sk_buff *) handle1); | ||
1141 | skb_unlink((struct sk_buff *) handle2); | ||
1142 | dev_kfree_skb_any((struct sk_buff *) handle2); | ||
1143 | return; | ||
1144 | } | ||
1145 | else | ||
1146 | card->sbfqc += 2; | ||
1147 | } | ||
1148 | else /* (type == BUF_LG) */ | ||
1149 | { | ||
1150 | if (card->lbfqc >= card->lbnr.max) | ||
1151 | { | ||
1152 | skb_unlink((struct sk_buff *) handle1); | ||
1153 | dev_kfree_skb_any((struct sk_buff *) handle1); | ||
1154 | skb_unlink((struct sk_buff *) handle2); | ||
1155 | dev_kfree_skb_any((struct sk_buff *) handle2); | ||
1156 | return; | ||
1157 | } | ||
1158 | else | ||
1159 | card->lbfqc += 2; | ||
1160 | } | ||
1161 | |||
1162 | ns_grab_res_lock(card, flags); | ||
1163 | |||
1164 | while (CMD_BUSY(card)); | ||
1165 | writel(addr2, card->membase + DR3); | ||
1166 | writel(handle2, card->membase + DR2); | ||
1167 | writel(addr1, card->membase + DR1); | ||
1168 | writel(handle1, card->membase + DR0); | ||
1169 | writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD); | ||
1170 | |||
1171 | spin_unlock_irqrestore(&card->res_lock, flags); | ||
1172 | |||
1173 | XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index, | ||
1174 | (type == BUF_SM ? "small" : "large"), addr1, addr2); | ||
1175 | } | ||
1176 | |||
1177 | if (!card->efbie && card->sbfqc >= card->sbnr.min && | ||
1178 | card->lbfqc >= card->lbnr.min) | ||
1179 | { | ||
1180 | card->efbie = 1; | ||
1181 | writel((readl(card->membase + CFG) | NS_CFG_EFBIE), card->membase + CFG); | ||
1182 | } | ||
1183 | |||
1184 | return; | ||
1185 | } | ||
1186 | |||
1187 | |||
1188 | |||
1189 | static irqreturn_t ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
1190 | { | ||
1191 | u32 stat_r; | ||
1192 | ns_dev *card; | ||
1193 | struct atm_dev *dev; | ||
1194 | unsigned long flags; | ||
1195 | |||
1196 | card = (ns_dev *) dev_id; | ||
1197 | dev = card->atmdev; | ||
1198 | card->intcnt++; | ||
1199 | |||
1200 | PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); | ||
1201 | |||
1202 | ns_grab_int_lock(card, flags); | ||
1203 | |||
1204 | stat_r = readl(card->membase + STAT); | ||
1205 | |||
1206 | /* Transmit Status Indicator has been written to T. S. Queue */ | ||
1207 | if (stat_r & NS_STAT_TSIF) | ||
1208 | { | ||
1209 | TXPRINTK("nicstar%d: TSI interrupt\n", card->index); | ||
1210 | process_tsq(card); | ||
1211 | writel(NS_STAT_TSIF, card->membase + STAT); | ||
1212 | } | ||
1213 | |||
1214 | /* Incomplete CS-PDU has been transmitted */ | ||
1215 | if (stat_r & NS_STAT_TXICP) | ||
1216 | { | ||
1217 | writel(NS_STAT_TXICP, card->membase + STAT); | ||
1218 | TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n", | ||
1219 | card->index); | ||
1220 | } | ||
1221 | |||
1222 | /* Transmit Status Queue 7/8 full */ | ||
1223 | if (stat_r & NS_STAT_TSQF) | ||
1224 | { | ||
1225 | writel(NS_STAT_TSQF, card->membase + STAT); | ||
1226 | PRINTK("nicstar%d: TSQ full.\n", card->index); | ||
1227 | process_tsq(card); | ||
1228 | } | ||
1229 | |||
1230 | /* Timer overflow */ | ||
1231 | if (stat_r & NS_STAT_TMROF) | ||
1232 | { | ||
1233 | writel(NS_STAT_TMROF, card->membase + STAT); | ||
1234 | PRINTK("nicstar%d: Timer overflow.\n", card->index); | ||
1235 | } | ||
1236 | |||
1237 | /* PHY device interrupt signal active */ | ||
1238 | if (stat_r & NS_STAT_PHYI) | ||
1239 | { | ||
1240 | writel(NS_STAT_PHYI, card->membase + STAT); | ||
1241 | PRINTK("nicstar%d: PHY interrupt.\n", card->index); | ||
1242 | if (dev->phy && dev->phy->interrupt) { | ||
1243 | dev->phy->interrupt(dev); | ||
1244 | } | ||
1245 | } | ||
1246 | |||
1247 | /* Small Buffer Queue is full */ | ||
1248 | if (stat_r & NS_STAT_SFBQF) | ||
1249 | { | ||
1250 | writel(NS_STAT_SFBQF, card->membase + STAT); | ||
1251 | printk("nicstar%d: Small free buffer queue is full.\n", card->index); | ||
1252 | } | ||
1253 | |||
1254 | /* Large Buffer Queue is full */ | ||
1255 | if (stat_r & NS_STAT_LFBQF) | ||
1256 | { | ||
1257 | writel(NS_STAT_LFBQF, card->membase + STAT); | ||
1258 | printk("nicstar%d: Large free buffer queue is full.\n", card->index); | ||
1259 | } | ||
1260 | |||
1261 | /* Receive Status Queue is full */ | ||
1262 | if (stat_r & NS_STAT_RSQF) | ||
1263 | { | ||
1264 | writel(NS_STAT_RSQF, card->membase + STAT); | ||
1265 | printk("nicstar%d: RSQ full.\n", card->index); | ||
1266 | process_rsq(card); | ||
1267 | } | ||
1268 | |||
1269 | /* Complete CS-PDU received */ | ||
1270 | if (stat_r & NS_STAT_EOPDU) | ||
1271 | { | ||
1272 | RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index); | ||
1273 | process_rsq(card); | ||
1274 | writel(NS_STAT_EOPDU, card->membase + STAT); | ||
1275 | } | ||
1276 | |||
1277 | /* Raw cell received */ | ||
1278 | if (stat_r & NS_STAT_RAWCF) | ||
1279 | { | ||
1280 | writel(NS_STAT_RAWCF, card->membase + STAT); | ||
1281 | #ifndef RCQ_SUPPORT | ||
1282 | printk("nicstar%d: Raw cell received and no support yet...\n", | ||
1283 | card->index); | ||
1284 | #endif /* RCQ_SUPPORT */ | ||
1285 | /* NOTE: the following procedure may keep a raw cell pending until the | ||
1286 | next interrupt. As this preliminary support is only meant to | ||
1287 | avoid buffer leakage, this is not an issue. */ | ||
1288 | while (readl(card->membase + RAWCT) != card->rawch) | ||
1289 | { | ||
1290 | ns_rcqe *rawcell; | ||
1291 | |||
1292 | rawcell = (ns_rcqe *) bus_to_virt(card->rawch); | ||
1293 | if (ns_rcqe_islast(rawcell)) | ||
1294 | { | ||
1295 | struct sk_buff *oldbuf; | ||
1296 | |||
1297 | oldbuf = card->rcbuf; | ||
1298 | card->rcbuf = (struct sk_buff *) ns_rcqe_nextbufhandle(rawcell); | ||
1299 | card->rawch = (u32) virt_to_bus(card->rcbuf->data); | ||
1300 | recycle_rx_buf(card, oldbuf); | ||
1301 | } | ||
1302 | else | ||
1303 | card->rawch += NS_RCQE_SIZE; | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | /* Small buffer queue is empty */ | ||
1308 | if (stat_r & NS_STAT_SFBQE) | ||
1309 | { | ||
1310 | int i; | ||
1311 | struct sk_buff *sb; | ||
1312 | |||
1313 | writel(NS_STAT_SFBQE, card->membase + STAT); | ||
1314 | printk("nicstar%d: Small free buffer queue empty.\n", | ||
1315 | card->index); | ||
1316 | for (i = 0; i < card->sbnr.min; i++) | ||
1317 | { | ||
1318 | sb = dev_alloc_skb(NS_SMSKBSIZE); | ||
1319 | if (sb == NULL) | ||
1320 | { | ||
1321 | writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG); | ||
1322 | card->efbie = 0; | ||
1323 | break; | ||
1324 | } | ||
1325 | skb_queue_tail(&card->sbpool.queue, sb); | ||
1326 | skb_reserve(sb, NS_AAL0_HEADER); | ||
1327 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | ||
1328 | } | ||
1329 | card->sbfqc = i; | ||
1330 | process_rsq(card); | ||
1331 | } | ||
1332 | |||
1333 | /* Large buffer queue empty */ | ||
1334 | if (stat_r & NS_STAT_LFBQE) | ||
1335 | { | ||
1336 | int i; | ||
1337 | struct sk_buff *lb; | ||
1338 | |||
1339 | writel(NS_STAT_LFBQE, card->membase + STAT); | ||
1340 | printk("nicstar%d: Large free buffer queue empty.\n", | ||
1341 | card->index); | ||
1342 | for (i = 0; i < card->lbnr.min; i++) | ||
1343 | { | ||
1344 | lb = dev_alloc_skb(NS_LGSKBSIZE); | ||
1345 | if (lb == NULL) | ||
1346 | { | ||
1347 | writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG); | ||
1348 | card->efbie = 0; | ||
1349 | break; | ||
1350 | } | ||
1351 | skb_queue_tail(&card->lbpool.queue, lb); | ||
1352 | skb_reserve(lb, NS_SMBUFSIZE); | ||
1353 | push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | ||
1354 | } | ||
1355 | card->lbfqc = i; | ||
1356 | process_rsq(card); | ||
1357 | } | ||
1358 | |||
1359 | /* Receive Status Queue is 7/8 full */ | ||
1360 | if (stat_r & NS_STAT_RSQAF) | ||
1361 | { | ||
1362 | writel(NS_STAT_RSQAF, card->membase + STAT); | ||
1363 | RXPRINTK("nicstar%d: RSQ almost full.\n", card->index); | ||
1364 | process_rsq(card); | ||
1365 | } | ||
1366 | |||
1367 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
1368 | PRINTK("nicstar%d: end of interrupt service\n", card->index); | ||
1369 | return IRQ_HANDLED; | ||
1370 | } | ||
1371 | |||
1372 | |||
1373 | |||
1374 | static int ns_open(struct atm_vcc *vcc) | ||
1375 | { | ||
1376 | ns_dev *card; | ||
1377 | vc_map *vc; | ||
1378 | unsigned long tmpl, modl; | ||
1379 | int tcr, tcra; /* target cell rate, and absolute value */ | ||
1380 | int n = 0; /* Number of entries in the TST. Initialized to remove | ||
1381 | the compiler warning. */ | ||
1382 | u32 u32d[4]; | ||
1383 | int frscdi = 0; /* Index of the SCD. Initialized to remove the compiler | ||
1384 | warning. How I wish compilers were clever enough to | ||
1385 | tell which variables can truly be used | ||
1386 | uninitialized... */ | ||
1387 | int inuse; /* tx or rx vc already in use by another vcc */ | ||
1388 | short vpi = vcc->vpi; | ||
1389 | int vci = vcc->vci; | ||
1390 | |||
1391 | card = (ns_dev *) vcc->dev->dev_data; | ||
1392 | PRINTK("nicstar%d: opening vpi.vci %d.%d \n", card->index, (int) vpi, vci); | ||
1393 | if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) | ||
1394 | { | ||
1395 | PRINTK("nicstar%d: unsupported AAL.\n", card->index); | ||
1396 | return -EINVAL; | ||
1397 | } | ||
1398 | |||
1399 | vc = &(card->vcmap[vpi << card->vcibits | vci]); | ||
1400 | vcc->dev_data = vc; | ||
1401 | |||
1402 | inuse = 0; | ||
1403 | if (vcc->qos.txtp.traffic_class != ATM_NONE && vc->tx) | ||
1404 | inuse = 1; | ||
1405 | if (vcc->qos.rxtp.traffic_class != ATM_NONE && vc->rx) | ||
1406 | inuse += 2; | ||
1407 | if (inuse) | ||
1408 | { | ||
1409 | printk("nicstar%d: %s vci already in use.\n", card->index, | ||
1410 | inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx"); | ||
1411 | return -EINVAL; | ||
1412 | } | ||
1413 | |||
1414 | set_bit(ATM_VF_ADDR,&vcc->flags); | ||
1415 | |||
1416 | /* NOTE: You are not allowed to modify an open connection's QOS. To change | ||
1417 | that, remove the ATM_VF_PARTIAL flag checking. There may be other changes | ||
1418 | needed to do that. */ | ||
1419 | if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) | ||
1420 | { | ||
1421 | scq_info *scq; | ||
1422 | |||
1423 | set_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1424 | if (vcc->qos.txtp.traffic_class == ATM_CBR) | ||
1425 | { | ||
1426 | /* Check requested cell rate and availability of SCD */ | ||
1427 | if (vcc->qos.txtp.max_pcr == 0 && vcc->qos.txtp.pcr == 0 && | ||
1428 | vcc->qos.txtp.min_pcr == 0) | ||
1429 | { | ||
1430 | PRINTK("nicstar%d: trying to open a CBR vc with cell rate = 0 \n", | ||
1431 | card->index); | ||
1432 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1433 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | |||
1437 | tcr = atm_pcr_goal(&(vcc->qos.txtp)); | ||
1438 | tcra = tcr >= 0 ? tcr : -tcr; | ||
1439 | |||
1440 | PRINTK("nicstar%d: target cell rate = %d.\n", card->index, | ||
1441 | vcc->qos.txtp.max_pcr); | ||
1442 | |||
1443 | tmpl = (unsigned long)tcra * (unsigned long)NS_TST_NUM_ENTRIES; | ||
1444 | modl = tmpl % card->max_pcr; | ||
1445 | |||
1446 | n = (int)(tmpl / card->max_pcr); | ||
1447 | if (tcr > 0) | ||
1448 | { | ||
1449 | if (modl > 0) n++; | ||
1450 | } | ||
1451 | else if (tcr == 0) | ||
1452 | { | ||
1453 | if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0) | ||
1454 | { | ||
1455 | PRINTK("nicstar%d: no CBR bandwidth free.\n", card->index); | ||
1456 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1457 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1458 | return -EINVAL; | ||
1459 | } | ||
1460 | } | ||
1461 | |||
1462 | if (n == 0) | ||
1463 | { | ||
1464 | printk("nicstar%d: selected bandwidth < granularity.\n", card->index); | ||
1465 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1466 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1467 | return -EINVAL; | ||
1468 | } | ||
1469 | |||
1470 | if (n > (card->tst_free_entries - NS_TST_RESERVED)) | ||
1471 | { | ||
1472 | PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index); | ||
1473 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1474 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1475 | return -EINVAL; | ||
1476 | } | ||
1477 | else | ||
1478 | card->tst_free_entries -= n; | ||
1479 | |||
1480 | XPRINTK("nicstar%d: writing %d tst entries.\n", card->index, n); | ||
1481 | for (frscdi = 0; frscdi < NS_FRSCD_NUM; frscdi++) | ||
1482 | { | ||
1483 | if (card->scd2vc[frscdi] == NULL) | ||
1484 | { | ||
1485 | card->scd2vc[frscdi] = vc; | ||
1486 | break; | ||
1487 | } | ||
1488 | } | ||
1489 | if (frscdi == NS_FRSCD_NUM) | ||
1490 | { | ||
1491 | PRINTK("nicstar%d: no SCD available for CBR channel.\n", card->index); | ||
1492 | card->tst_free_entries += n; | ||
1493 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1494 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1495 | return -EBUSY; | ||
1496 | } | ||
1497 | |||
1498 | vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE; | ||
1499 | |||
1500 | scq = get_scq(CBR_SCQSIZE, vc->cbr_scd); | ||
1501 | if (scq == (scq_info *) NULL) | ||
1502 | { | ||
1503 | PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index); | ||
1504 | card->scd2vc[frscdi] = NULL; | ||
1505 | card->tst_free_entries += n; | ||
1506 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1507 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1508 | return -ENOMEM; | ||
1509 | } | ||
1510 | vc->scq = scq; | ||
1511 | u32d[0] = (u32) virt_to_bus(scq->base); | ||
1512 | u32d[1] = (u32) 0x00000000; | ||
1513 | u32d[2] = (u32) 0xffffffff; | ||
1514 | u32d[3] = (u32) 0x00000000; | ||
1515 | ns_write_sram(card, vc->cbr_scd, u32d, 4); | ||
1516 | |||
1517 | fill_tst(card, n, vc); | ||
1518 | } | ||
1519 | else if (vcc->qos.txtp.traffic_class == ATM_UBR) | ||
1520 | { | ||
1521 | vc->cbr_scd = 0x00000000; | ||
1522 | vc->scq = card->scq0; | ||
1523 | } | ||
1524 | |||
1525 | if (vcc->qos.txtp.traffic_class != ATM_NONE) | ||
1526 | { | ||
1527 | vc->tx = 1; | ||
1528 | vc->tx_vcc = vcc; | ||
1529 | vc->tbd_count = 0; | ||
1530 | } | ||
1531 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) | ||
1532 | { | ||
1533 | u32 status; | ||
1534 | |||
1535 | vc->rx = 1; | ||
1536 | vc->rx_vcc = vcc; | ||
1537 | vc->rx_iov = NULL; | ||
1538 | |||
1539 | /* Open the connection in hardware */ | ||
1540 | if (vcc->qos.aal == ATM_AAL5) | ||
1541 | status = NS_RCTE_AAL5 | NS_RCTE_CONNECTOPEN; | ||
1542 | else /* vcc->qos.aal == ATM_AAL0 */ | ||
1543 | status = NS_RCTE_AAL0 | NS_RCTE_CONNECTOPEN; | ||
1544 | #ifdef RCQ_SUPPORT | ||
1545 | status |= NS_RCTE_RAWCELLINTEN; | ||
1546 | #endif /* RCQ_SUPPORT */ | ||
1547 | ns_write_sram(card, NS_RCT + (vpi << card->vcibits | vci) * | ||
1548 | NS_RCT_ENTRY_SIZE, &status, 1); | ||
1549 | } | ||
1550 | |||
1551 | } | ||
1552 | |||
1553 | set_bit(ATM_VF_READY,&vcc->flags); | ||
1554 | return 0; | ||
1555 | } | ||
1556 | |||
1557 | |||
1558 | |||
1559 | static void ns_close(struct atm_vcc *vcc) | ||
1560 | { | ||
1561 | vc_map *vc; | ||
1562 | ns_dev *card; | ||
1563 | u32 data; | ||
1564 | int i; | ||
1565 | |||
1566 | vc = vcc->dev_data; | ||
1567 | card = vcc->dev->dev_data; | ||
1568 | PRINTK("nicstar%d: closing vpi.vci %d.%d \n", card->index, | ||
1569 | (int) vcc->vpi, vcc->vci); | ||
1570 | |||
1571 | clear_bit(ATM_VF_READY,&vcc->flags); | ||
1572 | |||
1573 | if (vcc->qos.rxtp.traffic_class != ATM_NONE) | ||
1574 | { | ||
1575 | u32 addr; | ||
1576 | unsigned long flags; | ||
1577 | |||
1578 | addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE; | ||
1579 | ns_grab_res_lock(card, flags); | ||
1580 | while(CMD_BUSY(card)); | ||
1581 | writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD); | ||
1582 | spin_unlock_irqrestore(&card->res_lock, flags); | ||
1583 | |||
1584 | vc->rx = 0; | ||
1585 | if (vc->rx_iov != NULL) | ||
1586 | { | ||
1587 | struct sk_buff *iovb; | ||
1588 | u32 stat; | ||
1589 | |||
1590 | stat = readl(card->membase + STAT); | ||
1591 | card->sbfqc = ns_stat_sfbqc_get(stat); | ||
1592 | card->lbfqc = ns_stat_lfbqc_get(stat); | ||
1593 | |||
1594 | PRINTK("nicstar%d: closing a VC with pending rx buffers.\n", | ||
1595 | card->index); | ||
1596 | iovb = vc->rx_iov; | ||
1597 | recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | ||
1598 | NS_SKB(iovb)->iovcnt); | ||
1599 | NS_SKB(iovb)->iovcnt = 0; | ||
1600 | NS_SKB(iovb)->vcc = NULL; | ||
1601 | ns_grab_int_lock(card, flags); | ||
1602 | recycle_iov_buf(card, iovb); | ||
1603 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
1604 | vc->rx_iov = NULL; | ||
1605 | } | ||
1606 | } | ||
1607 | |||
1608 | if (vcc->qos.txtp.traffic_class != ATM_NONE) | ||
1609 | { | ||
1610 | vc->tx = 0; | ||
1611 | } | ||
1612 | |||
1613 | if (vcc->qos.txtp.traffic_class == ATM_CBR) | ||
1614 | { | ||
1615 | unsigned long flags; | ||
1616 | ns_scqe *scqep; | ||
1617 | scq_info *scq; | ||
1618 | |||
1619 | scq = vc->scq; | ||
1620 | |||
1621 | for (;;) | ||
1622 | { | ||
1623 | ns_grab_scq_lock(card, scq, flags); | ||
1624 | scqep = scq->next; | ||
1625 | if (scqep == scq->base) | ||
1626 | scqep = scq->last; | ||
1627 | else | ||
1628 | scqep--; | ||
1629 | if (scqep == scq->tail) | ||
1630 | { | ||
1631 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1632 | break; | ||
1633 | } | ||
1634 | /* If the last entry is not a TSR, place one in the SCQ in order to | ||
1635 | be able to completely drain it and then close. */ | ||
1636 | if (!ns_scqe_is_tsr(scqep) && scq->tail != scq->next) | ||
1637 | { | ||
1638 | ns_scqe tsr; | ||
1639 | u32 scdi, scqi; | ||
1640 | u32 data; | ||
1641 | int index; | ||
1642 | |||
1643 | tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); | ||
1644 | scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; | ||
1645 | scqi = scq->next - scq->base; | ||
1646 | tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); | ||
1647 | tsr.word_3 = 0x00000000; | ||
1648 | tsr.word_4 = 0x00000000; | ||
1649 | *scq->next = tsr; | ||
1650 | index = (int) scqi; | ||
1651 | scq->skb[index] = NULL; | ||
1652 | if (scq->next == scq->last) | ||
1653 | scq->next = scq->base; | ||
1654 | else | ||
1655 | scq->next++; | ||
1656 | data = (u32) virt_to_bus(scq->next); | ||
1657 | ns_write_sram(card, scq->scd, &data, 1); | ||
1658 | } | ||
1659 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1660 | schedule(); | ||
1661 | } | ||
1662 | |||
1663 | /* Free all TST entries */ | ||
1664 | data = NS_TST_OPCODE_VARIABLE; | ||
1665 | for (i = 0; i < NS_TST_NUM_ENTRIES; i++) | ||
1666 | { | ||
1667 | if (card->tste2vc[i] == vc) | ||
1668 | { | ||
1669 | ns_write_sram(card, card->tst_addr + i, &data, 1); | ||
1670 | card->tste2vc[i] = NULL; | ||
1671 | card->tst_free_entries++; | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | card->scd2vc[(vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE] = NULL; | ||
1676 | free_scq(vc->scq, vcc); | ||
1677 | } | ||
1678 | |||
1679 | /* remove all references to vcc before deleting it */ | ||
1680 | if (vcc->qos.txtp.traffic_class != ATM_NONE) | ||
1681 | { | ||
1682 | unsigned long flags; | ||
1683 | scq_info *scq = card->scq0; | ||
1684 | |||
1685 | ns_grab_scq_lock(card, scq, flags); | ||
1686 | |||
1687 | for(i = 0; i < scq->num_entries; i++) { | ||
1688 | if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) { | ||
1689 | ATM_SKB(scq->skb[i])->vcc = NULL; | ||
1690 | atm_return(vcc, scq->skb[i]->truesize); | ||
1691 | PRINTK("nicstar: deleted pending vcc mapping\n"); | ||
1692 | } | ||
1693 | } | ||
1694 | |||
1695 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1696 | } | ||
1697 | |||
1698 | vcc->dev_data = NULL; | ||
1699 | clear_bit(ATM_VF_PARTIAL,&vcc->flags); | ||
1700 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1701 | |||
1702 | #ifdef RX_DEBUG | ||
1703 | { | ||
1704 | u32 stat, cfg; | ||
1705 | stat = readl(card->membase + STAT); | ||
1706 | cfg = readl(card->membase + CFG); | ||
1707 | printk("STAT = 0x%08X CFG = 0x%08X \n", stat, cfg); | ||
1708 | printk("TSQ: base = 0x%08X next = 0x%08X last = 0x%08X TSQT = 0x%08X \n", | ||
1709 | (u32) card->tsq.base, (u32) card->tsq.next,(u32) card->tsq.last, | ||
1710 | readl(card->membase + TSQT)); | ||
1711 | printk("RSQ: base = 0x%08X next = 0x%08X last = 0x%08X RSQT = 0x%08X \n", | ||
1712 | (u32) card->rsq.base, (u32) card->rsq.next,(u32) card->rsq.last, | ||
1713 | readl(card->membase + RSQT)); | ||
1714 | printk("Empty free buffer queue interrupt %s \n", | ||
1715 | card->efbie ? "enabled" : "disabled"); | ||
1716 | printk("SBCNT = %d count = %d LBCNT = %d count = %d \n", | ||
1717 | ns_stat_sfbqc_get(stat), card->sbpool.count, | ||
1718 | ns_stat_lfbqc_get(stat), card->lbpool.count); | ||
1719 | printk("hbpool.count = %d iovpool.count = %d \n", | ||
1720 | card->hbpool.count, card->iovpool.count); | ||
1721 | } | ||
1722 | #endif /* RX_DEBUG */ | ||
1723 | } | ||
1724 | |||
1725 | |||
1726 | |||
1727 | static void fill_tst(ns_dev *card, int n, vc_map *vc) | ||
1728 | { | ||
1729 | u32 new_tst; | ||
1730 | unsigned long cl; | ||
1731 | int e, r; | ||
1732 | u32 data; | ||
1733 | |||
1734 | /* It would be very complicated to keep the two TSTs synchronized while | ||
1735 | assuring that writes are only made to the inactive TST. So, for now I | ||
1736 | will use only one TST. If problems occur, I will change this again */ | ||
1737 | |||
1738 | new_tst = card->tst_addr; | ||
1739 | |||
1740 | /* Fill procedure */ | ||
1741 | |||
1742 | for (e = 0; e < NS_TST_NUM_ENTRIES; e++) | ||
1743 | { | ||
1744 | if (card->tste2vc[e] == NULL) | ||
1745 | break; | ||
1746 | } | ||
1747 | if (e == NS_TST_NUM_ENTRIES) { | ||
1748 | printk("nicstar%d: No free TST entries found. \n", card->index); | ||
1749 | return; | ||
1750 | } | ||
1751 | |||
1752 | r = n; | ||
1753 | cl = NS_TST_NUM_ENTRIES; | ||
1754 | data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd); | ||
1755 | |||
1756 | while (r > 0) | ||
1757 | { | ||
1758 | if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL) | ||
1759 | { | ||
1760 | card->tste2vc[e] = vc; | ||
1761 | ns_write_sram(card, new_tst + e, &data, 1); | ||
1762 | cl -= NS_TST_NUM_ENTRIES; | ||
1763 | r--; | ||
1764 | } | ||
1765 | |||
1766 | if (++e == NS_TST_NUM_ENTRIES) { | ||
1767 | e = 0; | ||
1768 | } | ||
1769 | cl += n; | ||
1770 | } | ||
1771 | |||
1772 | /* End of fill procedure */ | ||
1773 | |||
1774 | data = ns_tste_make(NS_TST_OPCODE_END, new_tst); | ||
1775 | ns_write_sram(card, new_tst + NS_TST_NUM_ENTRIES, &data, 1); | ||
1776 | ns_write_sram(card, card->tst_addr + NS_TST_NUM_ENTRIES, &data, 1); | ||
1777 | card->tst_addr = new_tst; | ||
1778 | } | ||
1779 | |||
1780 | |||
1781 | |||
1782 | static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
1783 | { | ||
1784 | ns_dev *card; | ||
1785 | vc_map *vc; | ||
1786 | scq_info *scq; | ||
1787 | unsigned long buflen; | ||
1788 | ns_scqe scqe; | ||
1789 | u32 flags; /* TBD flags, not CPU flags */ | ||
1790 | |||
1791 | card = vcc->dev->dev_data; | ||
1792 | TXPRINTK("nicstar%d: ns_send() called.\n", card->index); | ||
1793 | if ((vc = (vc_map *) vcc->dev_data) == NULL) | ||
1794 | { | ||
1795 | printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", card->index); | ||
1796 | atomic_inc(&vcc->stats->tx_err); | ||
1797 | dev_kfree_skb_any(skb); | ||
1798 | return -EINVAL; | ||
1799 | } | ||
1800 | |||
1801 | if (!vc->tx) | ||
1802 | { | ||
1803 | printk("nicstar%d: Trying to transmit on a non-tx VC.\n", card->index); | ||
1804 | atomic_inc(&vcc->stats->tx_err); | ||
1805 | dev_kfree_skb_any(skb); | ||
1806 | return -EINVAL; | ||
1807 | } | ||
1808 | |||
1809 | if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) | ||
1810 | { | ||
1811 | printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", card->index); | ||
1812 | atomic_inc(&vcc->stats->tx_err); | ||
1813 | dev_kfree_skb_any(skb); | ||
1814 | return -EINVAL; | ||
1815 | } | ||
1816 | |||
1817 | if (skb_shinfo(skb)->nr_frags != 0) | ||
1818 | { | ||
1819 | printk("nicstar%d: No scatter-gather yet.\n", card->index); | ||
1820 | atomic_inc(&vcc->stats->tx_err); | ||
1821 | dev_kfree_skb_any(skb); | ||
1822 | return -EINVAL; | ||
1823 | } | ||
1824 | |||
1825 | ATM_SKB(skb)->vcc = vcc; | ||
1826 | |||
1827 | if (vcc->qos.aal == ATM_AAL5) | ||
1828 | { | ||
1829 | buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */ | ||
1830 | flags = NS_TBD_AAL5; | ||
1831 | scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data)); | ||
1832 | scqe.word_3 = cpu_to_le32((u32) skb->len); | ||
1833 | scqe.word_4 = ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0, | ||
1834 | ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? 1 : 0); | ||
1835 | flags |= NS_TBD_EOPDU; | ||
1836 | } | ||
1837 | else /* (vcc->qos.aal == ATM_AAL0) */ | ||
1838 | { | ||
1839 | buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */ | ||
1840 | flags = NS_TBD_AAL0; | ||
1841 | scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data) + NS_AAL0_HEADER); | ||
1842 | scqe.word_3 = cpu_to_le32(0x00000000); | ||
1843 | if (*skb->data & 0x02) /* Payload type 1 - end of pdu */ | ||
1844 | flags |= NS_TBD_EOPDU; | ||
1845 | scqe.word_4 = cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK); | ||
1846 | /* Force the VPI/VCI to be the same as in VCC struct */ | ||
1847 | scqe.word_4 |= cpu_to_le32((((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | | ||
1848 | ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) & | ||
1849 | NS_TBD_VC_MASK); | ||
1850 | } | ||
1851 | |||
1852 | if (vcc->qos.txtp.traffic_class == ATM_CBR) | ||
1853 | { | ||
1854 | scqe.word_1 = ns_tbd_mkword_1_novbr(flags, (u32) buflen); | ||
1855 | scq = ((vc_map *) vcc->dev_data)->scq; | ||
1856 | } | ||
1857 | else | ||
1858 | { | ||
1859 | scqe.word_1 = ns_tbd_mkword_1(flags, (u32) 1, (u32) 1, (u32) buflen); | ||
1860 | scq = card->scq0; | ||
1861 | } | ||
1862 | |||
1863 | if (push_scqe(card, vc, scq, &scqe, skb) != 0) | ||
1864 | { | ||
1865 | atomic_inc(&vcc->stats->tx_err); | ||
1866 | dev_kfree_skb_any(skb); | ||
1867 | return -EIO; | ||
1868 | } | ||
1869 | atomic_inc(&vcc->stats->tx); | ||
1870 | |||
1871 | return 0; | ||
1872 | } | ||
1873 | |||
1874 | |||
1875 | |||
1876 | static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, | ||
1877 | struct sk_buff *skb) | ||
1878 | { | ||
1879 | unsigned long flags; | ||
1880 | ns_scqe tsr; | ||
1881 | u32 scdi, scqi; | ||
1882 | int scq_is_vbr; | ||
1883 | u32 data; | ||
1884 | int index; | ||
1885 | |||
1886 | ns_grab_scq_lock(card, scq, flags); | ||
1887 | while (scq->tail == scq->next) | ||
1888 | { | ||
1889 | if (in_interrupt()) { | ||
1890 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1891 | printk("nicstar%d: Error pushing TBD.\n", card->index); | ||
1892 | return 1; | ||
1893 | } | ||
1894 | |||
1895 | scq->full = 1; | ||
1896 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1897 | interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); | ||
1898 | ns_grab_scq_lock(card, scq, flags); | ||
1899 | |||
1900 | if (scq->full) { | ||
1901 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1902 | printk("nicstar%d: Timeout pushing TBD.\n", card->index); | ||
1903 | return 1; | ||
1904 | } | ||
1905 | } | ||
1906 | *scq->next = *tbd; | ||
1907 | index = (int) (scq->next - scq->base); | ||
1908 | scq->skb[index] = skb; | ||
1909 | XPRINTK("nicstar%d: sending skb at 0x%x (pos %d).\n", | ||
1910 | card->index, (u32) skb, index); | ||
1911 | XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", | ||
1912 | card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2), | ||
1913 | le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4), | ||
1914 | (u32) scq->next); | ||
1915 | if (scq->next == scq->last) | ||
1916 | scq->next = scq->base; | ||
1917 | else | ||
1918 | scq->next++; | ||
1919 | |||
1920 | vc->tbd_count++; | ||
1921 | if (scq->num_entries == VBR_SCQ_NUM_ENTRIES) | ||
1922 | { | ||
1923 | scq->tbd_count++; | ||
1924 | scq_is_vbr = 1; | ||
1925 | } | ||
1926 | else | ||
1927 | scq_is_vbr = 0; | ||
1928 | |||
1929 | if (vc->tbd_count >= MAX_TBD_PER_VC || scq->tbd_count >= MAX_TBD_PER_SCQ) | ||
1930 | { | ||
1931 | int has_run = 0; | ||
1932 | |||
1933 | while (scq->tail == scq->next) | ||
1934 | { | ||
1935 | if (in_interrupt()) { | ||
1936 | data = (u32) virt_to_bus(scq->next); | ||
1937 | ns_write_sram(card, scq->scd, &data, 1); | ||
1938 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1939 | printk("nicstar%d: Error pushing TSR.\n", card->index); | ||
1940 | return 0; | ||
1941 | } | ||
1942 | |||
1943 | scq->full = 1; | ||
1944 | if (has_run++) break; | ||
1945 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1946 | interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); | ||
1947 | ns_grab_scq_lock(card, scq, flags); | ||
1948 | } | ||
1949 | |||
1950 | if (!scq->full) | ||
1951 | { | ||
1952 | tsr.word_1 = ns_tsr_mkword_1(NS_TSR_INTENABLE); | ||
1953 | if (scq_is_vbr) | ||
1954 | scdi = NS_TSR_SCDISVBR; | ||
1955 | else | ||
1956 | scdi = (vc->cbr_scd - NS_FRSCD) / NS_FRSCD_SIZE; | ||
1957 | scqi = scq->next - scq->base; | ||
1958 | tsr.word_2 = ns_tsr_mkword_2(scdi, scqi); | ||
1959 | tsr.word_3 = 0x00000000; | ||
1960 | tsr.word_4 = 0x00000000; | ||
1961 | |||
1962 | *scq->next = tsr; | ||
1963 | index = (int) scqi; | ||
1964 | scq->skb[index] = NULL; | ||
1965 | XPRINTK("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", | ||
1966 | card->index, le32_to_cpu(tsr.word_1), le32_to_cpu(tsr.word_2), | ||
1967 | le32_to_cpu(tsr.word_3), le32_to_cpu(tsr.word_4), | ||
1968 | (u32) scq->next); | ||
1969 | if (scq->next == scq->last) | ||
1970 | scq->next = scq->base; | ||
1971 | else | ||
1972 | scq->next++; | ||
1973 | vc->tbd_count = 0; | ||
1974 | scq->tbd_count = 0; | ||
1975 | } | ||
1976 | else | ||
1977 | PRINTK("nicstar%d: Timeout pushing TSR.\n", card->index); | ||
1978 | } | ||
1979 | data = (u32) virt_to_bus(scq->next); | ||
1980 | ns_write_sram(card, scq->scd, &data, 1); | ||
1981 | |||
1982 | spin_unlock_irqrestore(&scq->lock, flags); | ||
1983 | |||
1984 | return 0; | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | |||
1989 | static void process_tsq(ns_dev *card) | ||
1990 | { | ||
1991 | u32 scdi; | ||
1992 | scq_info *scq; | ||
1993 | ns_tsi *previous = NULL, *one_ahead, *two_ahead; | ||
1994 | int serviced_entries; /* flag indicating at least on entry was serviced */ | ||
1995 | |||
1996 | serviced_entries = 0; | ||
1997 | |||
1998 | if (card->tsq.next == card->tsq.last) | ||
1999 | one_ahead = card->tsq.base; | ||
2000 | else | ||
2001 | one_ahead = card->tsq.next + 1; | ||
2002 | |||
2003 | if (one_ahead == card->tsq.last) | ||
2004 | two_ahead = card->tsq.base; | ||
2005 | else | ||
2006 | two_ahead = one_ahead + 1; | ||
2007 | |||
2008 | while (!ns_tsi_isempty(card->tsq.next) || !ns_tsi_isempty(one_ahead) || | ||
2009 | !ns_tsi_isempty(two_ahead)) | ||
2010 | /* At most two empty, as stated in the 77201 errata */ | ||
2011 | { | ||
2012 | serviced_entries = 1; | ||
2013 | |||
2014 | /* Skip the one or two possible empty entries */ | ||
2015 | while (ns_tsi_isempty(card->tsq.next)) { | ||
2016 | if (card->tsq.next == card->tsq.last) | ||
2017 | card->tsq.next = card->tsq.base; | ||
2018 | else | ||
2019 | card->tsq.next++; | ||
2020 | } | ||
2021 | |||
2022 | if (!ns_tsi_tmrof(card->tsq.next)) | ||
2023 | { | ||
2024 | scdi = ns_tsi_getscdindex(card->tsq.next); | ||
2025 | if (scdi == NS_TSI_SCDISVBR) | ||
2026 | scq = card->scq0; | ||
2027 | else | ||
2028 | { | ||
2029 | if (card->scd2vc[scdi] == NULL) | ||
2030 | { | ||
2031 | printk("nicstar%d: could not find VC from SCD index.\n", | ||
2032 | card->index); | ||
2033 | ns_tsi_init(card->tsq.next); | ||
2034 | return; | ||
2035 | } | ||
2036 | scq = card->scd2vc[scdi]->scq; | ||
2037 | } | ||
2038 | drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next)); | ||
2039 | scq->full = 0; | ||
2040 | wake_up_interruptible(&(scq->scqfull_waitq)); | ||
2041 | } | ||
2042 | |||
2043 | ns_tsi_init(card->tsq.next); | ||
2044 | previous = card->tsq.next; | ||
2045 | if (card->tsq.next == card->tsq.last) | ||
2046 | card->tsq.next = card->tsq.base; | ||
2047 | else | ||
2048 | card->tsq.next++; | ||
2049 | |||
2050 | if (card->tsq.next == card->tsq.last) | ||
2051 | one_ahead = card->tsq.base; | ||
2052 | else | ||
2053 | one_ahead = card->tsq.next + 1; | ||
2054 | |||
2055 | if (one_ahead == card->tsq.last) | ||
2056 | two_ahead = card->tsq.base; | ||
2057 | else | ||
2058 | two_ahead = one_ahead + 1; | ||
2059 | } | ||
2060 | |||
2061 | if (serviced_entries) { | ||
2062 | writel((((u32) previous) - ((u32) card->tsq.base)), | ||
2063 | card->membase + TSQH); | ||
2064 | } | ||
2065 | } | ||
2066 | |||
2067 | |||
2068 | |||
2069 | static void drain_scq(ns_dev *card, scq_info *scq, int pos) | ||
2070 | { | ||
2071 | struct atm_vcc *vcc; | ||
2072 | struct sk_buff *skb; | ||
2073 | int i; | ||
2074 | unsigned long flags; | ||
2075 | |||
2076 | XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n", | ||
2077 | card->index, (u32) scq, pos); | ||
2078 | if (pos >= scq->num_entries) | ||
2079 | { | ||
2080 | printk("nicstar%d: Bad index on drain_scq().\n", card->index); | ||
2081 | return; | ||
2082 | } | ||
2083 | |||
2084 | ns_grab_scq_lock(card, scq, flags); | ||
2085 | i = (int) (scq->tail - scq->base); | ||
2086 | if (++i == scq->num_entries) | ||
2087 | i = 0; | ||
2088 | while (i != pos) | ||
2089 | { | ||
2090 | skb = scq->skb[i]; | ||
2091 | XPRINTK("nicstar%d: freeing skb at 0x%x (index %d).\n", | ||
2092 | card->index, (u32) skb, i); | ||
2093 | if (skb != NULL) | ||
2094 | { | ||
2095 | vcc = ATM_SKB(skb)->vcc; | ||
2096 | if (vcc && vcc->pop != NULL) { | ||
2097 | vcc->pop(vcc, skb); | ||
2098 | } else { | ||
2099 | dev_kfree_skb_irq(skb); | ||
2100 | } | ||
2101 | scq->skb[i] = NULL; | ||
2102 | } | ||
2103 | if (++i == scq->num_entries) | ||
2104 | i = 0; | ||
2105 | } | ||
2106 | scq->tail = scq->base + pos; | ||
2107 | spin_unlock_irqrestore(&scq->lock, flags); | ||
2108 | } | ||
2109 | |||
2110 | |||
2111 | |||
2112 | static void process_rsq(ns_dev *card) | ||
2113 | { | ||
2114 | ns_rsqe *previous; | ||
2115 | |||
2116 | if (!ns_rsqe_valid(card->rsq.next)) | ||
2117 | return; | ||
2118 | while (ns_rsqe_valid(card->rsq.next)) | ||
2119 | { | ||
2120 | dequeue_rx(card, card->rsq.next); | ||
2121 | ns_rsqe_init(card->rsq.next); | ||
2122 | previous = card->rsq.next; | ||
2123 | if (card->rsq.next == card->rsq.last) | ||
2124 | card->rsq.next = card->rsq.base; | ||
2125 | else | ||
2126 | card->rsq.next++; | ||
2127 | } | ||
2128 | writel((((u32) previous) - ((u32) card->rsq.base)), | ||
2129 | card->membase + RSQH); | ||
2130 | } | ||
2131 | |||
2132 | |||
2133 | |||
2134 | static void dequeue_rx(ns_dev *card, ns_rsqe *rsqe) | ||
2135 | { | ||
2136 | u32 vpi, vci; | ||
2137 | vc_map *vc; | ||
2138 | struct sk_buff *iovb; | ||
2139 | struct iovec *iov; | ||
2140 | struct atm_vcc *vcc; | ||
2141 | struct sk_buff *skb; | ||
2142 | unsigned short aal5_len; | ||
2143 | int len; | ||
2144 | u32 stat; | ||
2145 | |||
2146 | stat = readl(card->membase + STAT); | ||
2147 | card->sbfqc = ns_stat_sfbqc_get(stat); | ||
2148 | card->lbfqc = ns_stat_lfbqc_get(stat); | ||
2149 | |||
2150 | skb = (struct sk_buff *) le32_to_cpu(rsqe->buffer_handle); | ||
2151 | vpi = ns_rsqe_vpi(rsqe); | ||
2152 | vci = ns_rsqe_vci(rsqe); | ||
2153 | if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) | ||
2154 | { | ||
2155 | printk("nicstar%d: SDU received for out-of-range vc %d.%d.\n", | ||
2156 | card->index, vpi, vci); | ||
2157 | recycle_rx_buf(card, skb); | ||
2158 | return; | ||
2159 | } | ||
2160 | |||
2161 | vc = &(card->vcmap[vpi << card->vcibits | vci]); | ||
2162 | if (!vc->rx) | ||
2163 | { | ||
2164 | RXPRINTK("nicstar%d: SDU received on non-rx vc %d.%d.\n", | ||
2165 | card->index, vpi, vci); | ||
2166 | recycle_rx_buf(card, skb); | ||
2167 | return; | ||
2168 | } | ||
2169 | |||
2170 | vcc = vc->rx_vcc; | ||
2171 | |||
2172 | if (vcc->qos.aal == ATM_AAL0) | ||
2173 | { | ||
2174 | struct sk_buff *sb; | ||
2175 | unsigned char *cell; | ||
2176 | int i; | ||
2177 | |||
2178 | cell = skb->data; | ||
2179 | for (i = ns_rsqe_cellcount(rsqe); i; i--) | ||
2180 | { | ||
2181 | if ((sb = dev_alloc_skb(NS_SMSKBSIZE)) == NULL) | ||
2182 | { | ||
2183 | printk("nicstar%d: Can't allocate buffers for aal0.\n", | ||
2184 | card->index); | ||
2185 | atomic_add(i,&vcc->stats->rx_drop); | ||
2186 | break; | ||
2187 | } | ||
2188 | if (!atm_charge(vcc, sb->truesize)) | ||
2189 | { | ||
2190 | RXPRINTK("nicstar%d: atm_charge() dropped aal0 packets.\n", | ||
2191 | card->index); | ||
2192 | atomic_add(i-1,&vcc->stats->rx_drop); /* already increased by 1 */ | ||
2193 | dev_kfree_skb_any(sb); | ||
2194 | break; | ||
2195 | } | ||
2196 | /* Rebuild the header */ | ||
2197 | *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 | | ||
2198 | (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000); | ||
2199 | if (i == 1 && ns_rsqe_eopdu(rsqe)) | ||
2200 | *((u32 *) sb->data) |= 0x00000002; | ||
2201 | skb_put(sb, NS_AAL0_HEADER); | ||
2202 | memcpy(sb->tail, cell, ATM_CELL_PAYLOAD); | ||
2203 | skb_put(sb, ATM_CELL_PAYLOAD); | ||
2204 | ATM_SKB(sb)->vcc = vcc; | ||
2205 | do_gettimeofday(&sb->stamp); | ||
2206 | vcc->push(vcc, sb); | ||
2207 | atomic_inc(&vcc->stats->rx); | ||
2208 | cell += ATM_CELL_PAYLOAD; | ||
2209 | } | ||
2210 | |||
2211 | recycle_rx_buf(card, skb); | ||
2212 | return; | ||
2213 | } | ||
2214 | |||
2215 | /* To reach this point, the AAL layer can only be AAL5 */ | ||
2216 | |||
2217 | if ((iovb = vc->rx_iov) == NULL) | ||
2218 | { | ||
2219 | iovb = skb_dequeue(&(card->iovpool.queue)); | ||
2220 | if (iovb == NULL) /* No buffers in the queue */ | ||
2221 | { | ||
2222 | iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC); | ||
2223 | if (iovb == NULL) | ||
2224 | { | ||
2225 | printk("nicstar%d: Out of iovec buffers.\n", card->index); | ||
2226 | atomic_inc(&vcc->stats->rx_drop); | ||
2227 | recycle_rx_buf(card, skb); | ||
2228 | return; | ||
2229 | } | ||
2230 | } | ||
2231 | else | ||
2232 | if (--card->iovpool.count < card->iovnr.min) | ||
2233 | { | ||
2234 | struct sk_buff *new_iovb; | ||
2235 | if ((new_iovb = alloc_skb(NS_IOVBUFSIZE, GFP_ATOMIC)) != NULL) | ||
2236 | { | ||
2237 | skb_queue_tail(&card->iovpool.queue, new_iovb); | ||
2238 | card->iovpool.count++; | ||
2239 | } | ||
2240 | } | ||
2241 | vc->rx_iov = iovb; | ||
2242 | NS_SKB(iovb)->iovcnt = 0; | ||
2243 | iovb->len = 0; | ||
2244 | iovb->tail = iovb->data = iovb->head; | ||
2245 | NS_SKB(iovb)->vcc = vcc; | ||
2246 | /* IMPORTANT: a pointer to the sk_buff containing the small or large | ||
2247 | buffer is stored as iovec base, NOT a pointer to the | ||
2248 | small or large buffer itself. */ | ||
2249 | } | ||
2250 | else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) | ||
2251 | { | ||
2252 | printk("nicstar%d: received too big AAL5 SDU.\n", card->index); | ||
2253 | atomic_inc(&vcc->stats->rx_err); | ||
2254 | recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS); | ||
2255 | NS_SKB(iovb)->iovcnt = 0; | ||
2256 | iovb->len = 0; | ||
2257 | iovb->tail = iovb->data = iovb->head; | ||
2258 | NS_SKB(iovb)->vcc = vcc; | ||
2259 | } | ||
2260 | iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++]; | ||
2261 | iov->iov_base = (void *) skb; | ||
2262 | iov->iov_len = ns_rsqe_cellcount(rsqe) * 48; | ||
2263 | iovb->len += iov->iov_len; | ||
2264 | |||
2265 | if (NS_SKB(iovb)->iovcnt == 1) | ||
2266 | { | ||
2267 | if (skb->list != &card->sbpool.queue) | ||
2268 | { | ||
2269 | printk("nicstar%d: Expected a small buffer, and this is not one.\n", | ||
2270 | card->index); | ||
2271 | which_list(card, skb); | ||
2272 | atomic_inc(&vcc->stats->rx_err); | ||
2273 | recycle_rx_buf(card, skb); | ||
2274 | vc->rx_iov = NULL; | ||
2275 | recycle_iov_buf(card, iovb); | ||
2276 | return; | ||
2277 | } | ||
2278 | } | ||
2279 | else /* NS_SKB(iovb)->iovcnt >= 2 */ | ||
2280 | { | ||
2281 | if (skb->list != &card->lbpool.queue) | ||
2282 | { | ||
2283 | printk("nicstar%d: Expected a large buffer, and this is not one.\n", | ||
2284 | card->index); | ||
2285 | which_list(card, skb); | ||
2286 | atomic_inc(&vcc->stats->rx_err); | ||
2287 | recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | ||
2288 | NS_SKB(iovb)->iovcnt); | ||
2289 | vc->rx_iov = NULL; | ||
2290 | recycle_iov_buf(card, iovb); | ||
2291 | return; | ||
2292 | } | ||
2293 | } | ||
2294 | |||
2295 | if (ns_rsqe_eopdu(rsqe)) | ||
2296 | { | ||
2297 | /* This works correctly regardless of the endianness of the host */ | ||
2298 | unsigned char *L1L2 = (unsigned char *)((u32)skb->data + | ||
2299 | iov->iov_len - 6); | ||
2300 | aal5_len = L1L2[0] << 8 | L1L2[1]; | ||
2301 | len = (aal5_len == 0x0000) ? 0x10000 : aal5_len; | ||
2302 | if (ns_rsqe_crcerr(rsqe) || | ||
2303 | len + 8 > iovb->len || len + (47 + 8) < iovb->len) | ||
2304 | { | ||
2305 | printk("nicstar%d: AAL5 CRC error", card->index); | ||
2306 | if (len + 8 > iovb->len || len + (47 + 8) < iovb->len) | ||
2307 | printk(" - PDU size mismatch.\n"); | ||
2308 | else | ||
2309 | printk(".\n"); | ||
2310 | atomic_inc(&vcc->stats->rx_err); | ||
2311 | recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | ||
2312 | NS_SKB(iovb)->iovcnt); | ||
2313 | vc->rx_iov = NULL; | ||
2314 | recycle_iov_buf(card, iovb); | ||
2315 | return; | ||
2316 | } | ||
2317 | |||
2318 | /* By this point we (hopefully) have a complete SDU without errors. */ | ||
2319 | |||
2320 | if (NS_SKB(iovb)->iovcnt == 1) /* Just a small buffer */ | ||
2321 | { | ||
2322 | /* skb points to a small buffer */ | ||
2323 | if (!atm_charge(vcc, skb->truesize)) | ||
2324 | { | ||
2325 | push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), | ||
2326 | 0, 0); | ||
2327 | atomic_inc(&vcc->stats->rx_drop); | ||
2328 | } | ||
2329 | else | ||
2330 | { | ||
2331 | skb_put(skb, len); | ||
2332 | dequeue_sm_buf(card, skb); | ||
2333 | #ifdef NS_USE_DESTRUCTORS | ||
2334 | skb->destructor = ns_sb_destructor; | ||
2335 | #endif /* NS_USE_DESTRUCTORS */ | ||
2336 | ATM_SKB(skb)->vcc = vcc; | ||
2337 | do_gettimeofday(&skb->stamp); | ||
2338 | vcc->push(vcc, skb); | ||
2339 | atomic_inc(&vcc->stats->rx); | ||
2340 | } | ||
2341 | } | ||
2342 | else if (NS_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */ | ||
2343 | { | ||
2344 | struct sk_buff *sb; | ||
2345 | |||
2346 | sb = (struct sk_buff *) (iov - 1)->iov_base; | ||
2347 | /* skb points to a large buffer */ | ||
2348 | |||
2349 | if (len <= NS_SMBUFSIZE) | ||
2350 | { | ||
2351 | if (!atm_charge(vcc, sb->truesize)) | ||
2352 | { | ||
2353 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), | ||
2354 | 0, 0); | ||
2355 | atomic_inc(&vcc->stats->rx_drop); | ||
2356 | } | ||
2357 | else | ||
2358 | { | ||
2359 | skb_put(sb, len); | ||
2360 | dequeue_sm_buf(card, sb); | ||
2361 | #ifdef NS_USE_DESTRUCTORS | ||
2362 | sb->destructor = ns_sb_destructor; | ||
2363 | #endif /* NS_USE_DESTRUCTORS */ | ||
2364 | ATM_SKB(sb)->vcc = vcc; | ||
2365 | do_gettimeofday(&sb->stamp); | ||
2366 | vcc->push(vcc, sb); | ||
2367 | atomic_inc(&vcc->stats->rx); | ||
2368 | } | ||
2369 | |||
2370 | push_rxbufs(card, BUF_LG, (u32) skb, | ||
2371 | (u32) virt_to_bus(skb->data), 0, 0); | ||
2372 | |||
2373 | } | ||
2374 | else /* len > NS_SMBUFSIZE, the usual case */ | ||
2375 | { | ||
2376 | if (!atm_charge(vcc, skb->truesize)) | ||
2377 | { | ||
2378 | push_rxbufs(card, BUF_LG, (u32) skb, | ||
2379 | (u32) virt_to_bus(skb->data), 0, 0); | ||
2380 | atomic_inc(&vcc->stats->rx_drop); | ||
2381 | } | ||
2382 | else | ||
2383 | { | ||
2384 | dequeue_lg_buf(card, skb); | ||
2385 | #ifdef NS_USE_DESTRUCTORS | ||
2386 | skb->destructor = ns_lb_destructor; | ||
2387 | #endif /* NS_USE_DESTRUCTORS */ | ||
2388 | skb_push(skb, NS_SMBUFSIZE); | ||
2389 | memcpy(skb->data, sb->data, NS_SMBUFSIZE); | ||
2390 | skb_put(skb, len - NS_SMBUFSIZE); | ||
2391 | ATM_SKB(skb)->vcc = vcc; | ||
2392 | do_gettimeofday(&skb->stamp); | ||
2393 | vcc->push(vcc, skb); | ||
2394 | atomic_inc(&vcc->stats->rx); | ||
2395 | } | ||
2396 | |||
2397 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), | ||
2398 | 0, 0); | ||
2399 | |||
2400 | } | ||
2401 | |||
2402 | } | ||
2403 | else /* Must push a huge buffer */ | ||
2404 | { | ||
2405 | struct sk_buff *hb, *sb, *lb; | ||
2406 | int remaining, tocopy; | ||
2407 | int j; | ||
2408 | |||
2409 | hb = skb_dequeue(&(card->hbpool.queue)); | ||
2410 | if (hb == NULL) /* No buffers in the queue */ | ||
2411 | { | ||
2412 | |||
2413 | hb = dev_alloc_skb(NS_HBUFSIZE); | ||
2414 | if (hb == NULL) | ||
2415 | { | ||
2416 | printk("nicstar%d: Out of huge buffers.\n", card->index); | ||
2417 | atomic_inc(&vcc->stats->rx_drop); | ||
2418 | recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, | ||
2419 | NS_SKB(iovb)->iovcnt); | ||
2420 | vc->rx_iov = NULL; | ||
2421 | recycle_iov_buf(card, iovb); | ||
2422 | return; | ||
2423 | } | ||
2424 | else if (card->hbpool.count < card->hbnr.min) | ||
2425 | { | ||
2426 | struct sk_buff *new_hb; | ||
2427 | if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) | ||
2428 | { | ||
2429 | skb_queue_tail(&card->hbpool.queue, new_hb); | ||
2430 | card->hbpool.count++; | ||
2431 | } | ||
2432 | } | ||
2433 | } | ||
2434 | else | ||
2435 | if (--card->hbpool.count < card->hbnr.min) | ||
2436 | { | ||
2437 | struct sk_buff *new_hb; | ||
2438 | if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) | ||
2439 | { | ||
2440 | skb_queue_tail(&card->hbpool.queue, new_hb); | ||
2441 | card->hbpool.count++; | ||
2442 | } | ||
2443 | if (card->hbpool.count < card->hbnr.min) | ||
2444 | { | ||
2445 | if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL) | ||
2446 | { | ||
2447 | skb_queue_tail(&card->hbpool.queue, new_hb); | ||
2448 | card->hbpool.count++; | ||
2449 | } | ||
2450 | } | ||
2451 | } | ||
2452 | |||
2453 | iov = (struct iovec *) iovb->data; | ||
2454 | |||
2455 | if (!atm_charge(vcc, hb->truesize)) | ||
2456 | { | ||
2457 | recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt); | ||
2458 | if (card->hbpool.count < card->hbnr.max) | ||
2459 | { | ||
2460 | skb_queue_tail(&card->hbpool.queue, hb); | ||
2461 | card->hbpool.count++; | ||
2462 | } | ||
2463 | else | ||
2464 | dev_kfree_skb_any(hb); | ||
2465 | atomic_inc(&vcc->stats->rx_drop); | ||
2466 | } | ||
2467 | else | ||
2468 | { | ||
2469 | /* Copy the small buffer to the huge buffer */ | ||
2470 | sb = (struct sk_buff *) iov->iov_base; | ||
2471 | memcpy(hb->data, sb->data, iov->iov_len); | ||
2472 | skb_put(hb, iov->iov_len); | ||
2473 | remaining = len - iov->iov_len; | ||
2474 | iov++; | ||
2475 | /* Free the small buffer */ | ||
2476 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), | ||
2477 | 0, 0); | ||
2478 | |||
2479 | /* Copy all large buffers to the huge buffer and free them */ | ||
2480 | for (j = 1; j < NS_SKB(iovb)->iovcnt; j++) | ||
2481 | { | ||
2482 | lb = (struct sk_buff *) iov->iov_base; | ||
2483 | tocopy = min_t(int, remaining, iov->iov_len); | ||
2484 | memcpy(hb->tail, lb->data, tocopy); | ||
2485 | skb_put(hb, tocopy); | ||
2486 | iov++; | ||
2487 | remaining -= tocopy; | ||
2488 | push_rxbufs(card, BUF_LG, (u32) lb, | ||
2489 | (u32) virt_to_bus(lb->data), 0, 0); | ||
2490 | } | ||
2491 | #ifdef EXTRA_DEBUG | ||
2492 | if (remaining != 0 || hb->len != len) | ||
2493 | printk("nicstar%d: Huge buffer len mismatch.\n", card->index); | ||
2494 | #endif /* EXTRA_DEBUG */ | ||
2495 | ATM_SKB(hb)->vcc = vcc; | ||
2496 | #ifdef NS_USE_DESTRUCTORS | ||
2497 | hb->destructor = ns_hb_destructor; | ||
2498 | #endif /* NS_USE_DESTRUCTORS */ | ||
2499 | do_gettimeofday(&hb->stamp); | ||
2500 | vcc->push(vcc, hb); | ||
2501 | atomic_inc(&vcc->stats->rx); | ||
2502 | } | ||
2503 | } | ||
2504 | |||
2505 | vc->rx_iov = NULL; | ||
2506 | recycle_iov_buf(card, iovb); | ||
2507 | } | ||
2508 | |||
2509 | } | ||
2510 | |||
2511 | |||
2512 | |||
2513 | #ifdef NS_USE_DESTRUCTORS | ||
2514 | |||
2515 | static void ns_sb_destructor(struct sk_buff *sb) | ||
2516 | { | ||
2517 | ns_dev *card; | ||
2518 | u32 stat; | ||
2519 | |||
2520 | card = (ns_dev *) ATM_SKB(sb)->vcc->dev->dev_data; | ||
2521 | stat = readl(card->membase + STAT); | ||
2522 | card->sbfqc = ns_stat_sfbqc_get(stat); | ||
2523 | card->lbfqc = ns_stat_lfbqc_get(stat); | ||
2524 | |||
2525 | do | ||
2526 | { | ||
2527 | sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); | ||
2528 | if (sb == NULL) | ||
2529 | break; | ||
2530 | skb_queue_tail(&card->sbpool.queue, sb); | ||
2531 | skb_reserve(sb, NS_AAL0_HEADER); | ||
2532 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | ||
2533 | } while (card->sbfqc < card->sbnr.min); | ||
2534 | } | ||
2535 | |||
2536 | |||
2537 | |||
2538 | static void ns_lb_destructor(struct sk_buff *lb) | ||
2539 | { | ||
2540 | ns_dev *card; | ||
2541 | u32 stat; | ||
2542 | |||
2543 | card = (ns_dev *) ATM_SKB(lb)->vcc->dev->dev_data; | ||
2544 | stat = readl(card->membase + STAT); | ||
2545 | card->sbfqc = ns_stat_sfbqc_get(stat); | ||
2546 | card->lbfqc = ns_stat_lfbqc_get(stat); | ||
2547 | |||
2548 | do | ||
2549 | { | ||
2550 | lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); | ||
2551 | if (lb == NULL) | ||
2552 | break; | ||
2553 | skb_queue_tail(&card->lbpool.queue, lb); | ||
2554 | skb_reserve(lb, NS_SMBUFSIZE); | ||
2555 | push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | ||
2556 | } while (card->lbfqc < card->lbnr.min); | ||
2557 | } | ||
2558 | |||
2559 | |||
2560 | |||
2561 | static void ns_hb_destructor(struct sk_buff *hb) | ||
2562 | { | ||
2563 | ns_dev *card; | ||
2564 | |||
2565 | card = (ns_dev *) ATM_SKB(hb)->vcc->dev->dev_data; | ||
2566 | |||
2567 | while (card->hbpool.count < card->hbnr.init) | ||
2568 | { | ||
2569 | hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); | ||
2570 | if (hb == NULL) | ||
2571 | break; | ||
2572 | skb_queue_tail(&card->hbpool.queue, hb); | ||
2573 | card->hbpool.count++; | ||
2574 | } | ||
2575 | } | ||
2576 | |||
2577 | #endif /* NS_USE_DESTRUCTORS */ | ||
2578 | |||
2579 | |||
2580 | |||
2581 | static void recycle_rx_buf(ns_dev *card, struct sk_buff *skb) | ||
2582 | { | ||
2583 | if (skb->list == &card->sbpool.queue) | ||
2584 | push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0); | ||
2585 | else if (skb->list == &card->lbpool.queue) | ||
2586 | push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data), 0, 0); | ||
2587 | else | ||
2588 | { | ||
2589 | printk("nicstar%d: What kind of rx buffer is this?\n", card->index); | ||
2590 | dev_kfree_skb_any(skb); | ||
2591 | } | ||
2592 | } | ||
2593 | |||
2594 | |||
2595 | |||
2596 | static void recycle_iovec_rx_bufs(ns_dev *card, struct iovec *iov, int count) | ||
2597 | { | ||
2598 | struct sk_buff *skb; | ||
2599 | |||
2600 | for (; count > 0; count--) | ||
2601 | { | ||
2602 | skb = (struct sk_buff *) (iov++)->iov_base; | ||
2603 | if (skb->list == &card->sbpool.queue) | ||
2604 | push_rxbufs(card, BUF_SM, (u32) skb, (u32) virt_to_bus(skb->data), | ||
2605 | 0, 0); | ||
2606 | else if (skb->list == &card->lbpool.queue) | ||
2607 | push_rxbufs(card, BUF_LG, (u32) skb, (u32) virt_to_bus(skb->data), | ||
2608 | 0, 0); | ||
2609 | else | ||
2610 | { | ||
2611 | printk("nicstar%d: What kind of rx buffer is this?\n", card->index); | ||
2612 | dev_kfree_skb_any(skb); | ||
2613 | } | ||
2614 | } | ||
2615 | } | ||
2616 | |||
2617 | |||
2618 | |||
2619 | static void recycle_iov_buf(ns_dev *card, struct sk_buff *iovb) | ||
2620 | { | ||
2621 | if (card->iovpool.count < card->iovnr.max) | ||
2622 | { | ||
2623 | skb_queue_tail(&card->iovpool.queue, iovb); | ||
2624 | card->iovpool.count++; | ||
2625 | } | ||
2626 | else | ||
2627 | dev_kfree_skb_any(iovb); | ||
2628 | } | ||
2629 | |||
2630 | |||
2631 | |||
2632 | static void dequeue_sm_buf(ns_dev *card, struct sk_buff *sb) | ||
2633 | { | ||
2634 | skb_unlink(sb); | ||
2635 | #ifdef NS_USE_DESTRUCTORS | ||
2636 | if (card->sbfqc < card->sbnr.min) | ||
2637 | #else | ||
2638 | if (card->sbfqc < card->sbnr.init) | ||
2639 | { | ||
2640 | struct sk_buff *new_sb; | ||
2641 | if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) | ||
2642 | { | ||
2643 | skb_queue_tail(&card->sbpool.queue, new_sb); | ||
2644 | skb_reserve(new_sb, NS_AAL0_HEADER); | ||
2645 | push_rxbufs(card, BUF_SM, (u32) new_sb, | ||
2646 | (u32) virt_to_bus(new_sb->data), 0, 0); | ||
2647 | } | ||
2648 | } | ||
2649 | if (card->sbfqc < card->sbnr.init) | ||
2650 | #endif /* NS_USE_DESTRUCTORS */ | ||
2651 | { | ||
2652 | struct sk_buff *new_sb; | ||
2653 | if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL) | ||
2654 | { | ||
2655 | skb_queue_tail(&card->sbpool.queue, new_sb); | ||
2656 | skb_reserve(new_sb, NS_AAL0_HEADER); | ||
2657 | push_rxbufs(card, BUF_SM, (u32) new_sb, | ||
2658 | (u32) virt_to_bus(new_sb->data), 0, 0); | ||
2659 | } | ||
2660 | } | ||
2661 | } | ||
2662 | |||
2663 | |||
2664 | |||
2665 | static void dequeue_lg_buf(ns_dev *card, struct sk_buff *lb) | ||
2666 | { | ||
2667 | skb_unlink(lb); | ||
2668 | #ifdef NS_USE_DESTRUCTORS | ||
2669 | if (card->lbfqc < card->lbnr.min) | ||
2670 | #else | ||
2671 | if (card->lbfqc < card->lbnr.init) | ||
2672 | { | ||
2673 | struct sk_buff *new_lb; | ||
2674 | if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) | ||
2675 | { | ||
2676 | skb_queue_tail(&card->lbpool.queue, new_lb); | ||
2677 | skb_reserve(new_lb, NS_SMBUFSIZE); | ||
2678 | push_rxbufs(card, BUF_LG, (u32) new_lb, | ||
2679 | (u32) virt_to_bus(new_lb->data), 0, 0); | ||
2680 | } | ||
2681 | } | ||
2682 | if (card->lbfqc < card->lbnr.init) | ||
2683 | #endif /* NS_USE_DESTRUCTORS */ | ||
2684 | { | ||
2685 | struct sk_buff *new_lb; | ||
2686 | if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL) | ||
2687 | { | ||
2688 | skb_queue_tail(&card->lbpool.queue, new_lb); | ||
2689 | skb_reserve(new_lb, NS_SMBUFSIZE); | ||
2690 | push_rxbufs(card, BUF_LG, (u32) new_lb, | ||
2691 | (u32) virt_to_bus(new_lb->data), 0, 0); | ||
2692 | } | ||
2693 | } | ||
2694 | } | ||
2695 | |||
2696 | |||
2697 | |||
2698 | static int ns_proc_read(struct atm_dev *dev, loff_t *pos, char *page) | ||
2699 | { | ||
2700 | u32 stat; | ||
2701 | ns_dev *card; | ||
2702 | int left; | ||
2703 | |||
2704 | left = (int) *pos; | ||
2705 | card = (ns_dev *) dev->dev_data; | ||
2706 | stat = readl(card->membase + STAT); | ||
2707 | if (!left--) | ||
2708 | return sprintf(page, "Pool count min init max \n"); | ||
2709 | if (!left--) | ||
2710 | return sprintf(page, "Small %5d %5d %5d %5d \n", | ||
2711 | ns_stat_sfbqc_get(stat), card->sbnr.min, card->sbnr.init, | ||
2712 | card->sbnr.max); | ||
2713 | if (!left--) | ||
2714 | return sprintf(page, "Large %5d %5d %5d %5d \n", | ||
2715 | ns_stat_lfbqc_get(stat), card->lbnr.min, card->lbnr.init, | ||
2716 | card->lbnr.max); | ||
2717 | if (!left--) | ||
2718 | return sprintf(page, "Huge %5d %5d %5d %5d \n", card->hbpool.count, | ||
2719 | card->hbnr.min, card->hbnr.init, card->hbnr.max); | ||
2720 | if (!left--) | ||
2721 | return sprintf(page, "Iovec %5d %5d %5d %5d \n", card->iovpool.count, | ||
2722 | card->iovnr.min, card->iovnr.init, card->iovnr.max); | ||
2723 | if (!left--) | ||
2724 | { | ||
2725 | int retval; | ||
2726 | retval = sprintf(page, "Interrupt counter: %u \n", card->intcnt); | ||
2727 | card->intcnt = 0; | ||
2728 | return retval; | ||
2729 | } | ||
2730 | #if 0 | ||
2731 | /* Dump 25.6 Mbps PHY registers */ | ||
2732 | /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it | ||
2733 | here just in case it's needed for debugging. */ | ||
2734 | if (card->max_pcr == ATM_25_PCR && !left--) | ||
2735 | { | ||
2736 | u32 phy_regs[4]; | ||
2737 | u32 i; | ||
2738 | |||
2739 | for (i = 0; i < 4; i++) | ||
2740 | { | ||
2741 | while (CMD_BUSY(card)); | ||
2742 | writel(NS_CMD_READ_UTILITY | 0x00000200 | i, card->membase + CMD); | ||
2743 | while (CMD_BUSY(card)); | ||
2744 | phy_regs[i] = readl(card->membase + DR0) & 0x000000FF; | ||
2745 | } | ||
2746 | |||
2747 | return sprintf(page, "PHY regs: 0x%02X 0x%02X 0x%02X 0x%02X \n", | ||
2748 | phy_regs[0], phy_regs[1], phy_regs[2], phy_regs[3]); | ||
2749 | } | ||
2750 | #endif /* 0 - Dump 25.6 Mbps PHY registers */ | ||
2751 | #if 0 | ||
2752 | /* Dump TST */ | ||
2753 | if (left-- < NS_TST_NUM_ENTRIES) | ||
2754 | { | ||
2755 | if (card->tste2vc[left + 1] == NULL) | ||
2756 | return sprintf(page, "%5d - VBR/UBR \n", left + 1); | ||
2757 | else | ||
2758 | return sprintf(page, "%5d - %d %d \n", left + 1, | ||
2759 | card->tste2vc[left + 1]->tx_vcc->vpi, | ||
2760 | card->tste2vc[left + 1]->tx_vcc->vci); | ||
2761 | } | ||
2762 | #endif /* 0 */ | ||
2763 | return 0; | ||
2764 | } | ||
2765 | |||
2766 | |||
2767 | |||
2768 | static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) | ||
2769 | { | ||
2770 | ns_dev *card; | ||
2771 | pool_levels pl; | ||
2772 | int btype; | ||
2773 | unsigned long flags; | ||
2774 | |||
2775 | card = dev->dev_data; | ||
2776 | switch (cmd) | ||
2777 | { | ||
2778 | case NS_GETPSTAT: | ||
2779 | if (get_user(pl.buftype, &((pool_levels __user *) arg)->buftype)) | ||
2780 | return -EFAULT; | ||
2781 | switch (pl.buftype) | ||
2782 | { | ||
2783 | case NS_BUFTYPE_SMALL: | ||
2784 | pl.count = ns_stat_sfbqc_get(readl(card->membase + STAT)); | ||
2785 | pl.level.min = card->sbnr.min; | ||
2786 | pl.level.init = card->sbnr.init; | ||
2787 | pl.level.max = card->sbnr.max; | ||
2788 | break; | ||
2789 | |||
2790 | case NS_BUFTYPE_LARGE: | ||
2791 | pl.count = ns_stat_lfbqc_get(readl(card->membase + STAT)); | ||
2792 | pl.level.min = card->lbnr.min; | ||
2793 | pl.level.init = card->lbnr.init; | ||
2794 | pl.level.max = card->lbnr.max; | ||
2795 | break; | ||
2796 | |||
2797 | case NS_BUFTYPE_HUGE: | ||
2798 | pl.count = card->hbpool.count; | ||
2799 | pl.level.min = card->hbnr.min; | ||
2800 | pl.level.init = card->hbnr.init; | ||
2801 | pl.level.max = card->hbnr.max; | ||
2802 | break; | ||
2803 | |||
2804 | case NS_BUFTYPE_IOVEC: | ||
2805 | pl.count = card->iovpool.count; | ||
2806 | pl.level.min = card->iovnr.min; | ||
2807 | pl.level.init = card->iovnr.init; | ||
2808 | pl.level.max = card->iovnr.max; | ||
2809 | break; | ||
2810 | |||
2811 | default: | ||
2812 | return -ENOIOCTLCMD; | ||
2813 | |||
2814 | } | ||
2815 | if (!copy_to_user((pool_levels __user *) arg, &pl, sizeof(pl))) | ||
2816 | return (sizeof(pl)); | ||
2817 | else | ||
2818 | return -EFAULT; | ||
2819 | |||
2820 | case NS_SETBUFLEV: | ||
2821 | if (!capable(CAP_NET_ADMIN)) | ||
2822 | return -EPERM; | ||
2823 | if (copy_from_user(&pl, (pool_levels __user *) arg, sizeof(pl))) | ||
2824 | return -EFAULT; | ||
2825 | if (pl.level.min >= pl.level.init || pl.level.init >= pl.level.max) | ||
2826 | return -EINVAL; | ||
2827 | if (pl.level.min == 0) | ||
2828 | return -EINVAL; | ||
2829 | switch (pl.buftype) | ||
2830 | { | ||
2831 | case NS_BUFTYPE_SMALL: | ||
2832 | if (pl.level.max > TOP_SB) | ||
2833 | return -EINVAL; | ||
2834 | card->sbnr.min = pl.level.min; | ||
2835 | card->sbnr.init = pl.level.init; | ||
2836 | card->sbnr.max = pl.level.max; | ||
2837 | break; | ||
2838 | |||
2839 | case NS_BUFTYPE_LARGE: | ||
2840 | if (pl.level.max > TOP_LB) | ||
2841 | return -EINVAL; | ||
2842 | card->lbnr.min = pl.level.min; | ||
2843 | card->lbnr.init = pl.level.init; | ||
2844 | card->lbnr.max = pl.level.max; | ||
2845 | break; | ||
2846 | |||
2847 | case NS_BUFTYPE_HUGE: | ||
2848 | if (pl.level.max > TOP_HB) | ||
2849 | return -EINVAL; | ||
2850 | card->hbnr.min = pl.level.min; | ||
2851 | card->hbnr.init = pl.level.init; | ||
2852 | card->hbnr.max = pl.level.max; | ||
2853 | break; | ||
2854 | |||
2855 | case NS_BUFTYPE_IOVEC: | ||
2856 | if (pl.level.max > TOP_IOVB) | ||
2857 | return -EINVAL; | ||
2858 | card->iovnr.min = pl.level.min; | ||
2859 | card->iovnr.init = pl.level.init; | ||
2860 | card->iovnr.max = pl.level.max; | ||
2861 | break; | ||
2862 | |||
2863 | default: | ||
2864 | return -EINVAL; | ||
2865 | |||
2866 | } | ||
2867 | return 0; | ||
2868 | |||
2869 | case NS_ADJBUFLEV: | ||
2870 | if (!capable(CAP_NET_ADMIN)) | ||
2871 | return -EPERM; | ||
2872 | btype = (int) arg; /* an int is the same size as a pointer */ | ||
2873 | switch (btype) | ||
2874 | { | ||
2875 | case NS_BUFTYPE_SMALL: | ||
2876 | while (card->sbfqc < card->sbnr.init) | ||
2877 | { | ||
2878 | struct sk_buff *sb; | ||
2879 | |||
2880 | sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); | ||
2881 | if (sb == NULL) | ||
2882 | return -ENOMEM; | ||
2883 | skb_queue_tail(&card->sbpool.queue, sb); | ||
2884 | skb_reserve(sb, NS_AAL0_HEADER); | ||
2885 | push_rxbufs(card, BUF_SM, (u32) sb, (u32) virt_to_bus(sb->data), 0, 0); | ||
2886 | } | ||
2887 | break; | ||
2888 | |||
2889 | case NS_BUFTYPE_LARGE: | ||
2890 | while (card->lbfqc < card->lbnr.init) | ||
2891 | { | ||
2892 | struct sk_buff *lb; | ||
2893 | |||
2894 | lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); | ||
2895 | if (lb == NULL) | ||
2896 | return -ENOMEM; | ||
2897 | skb_queue_tail(&card->lbpool.queue, lb); | ||
2898 | skb_reserve(lb, NS_SMBUFSIZE); | ||
2899 | push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); | ||
2900 | } | ||
2901 | break; | ||
2902 | |||
2903 | case NS_BUFTYPE_HUGE: | ||
2904 | while (card->hbpool.count > card->hbnr.init) | ||
2905 | { | ||
2906 | struct sk_buff *hb; | ||
2907 | |||
2908 | ns_grab_int_lock(card, flags); | ||
2909 | hb = skb_dequeue(&card->hbpool.queue); | ||
2910 | card->hbpool.count--; | ||
2911 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
2912 | if (hb == NULL) | ||
2913 | printk("nicstar%d: huge buffer count inconsistent.\n", | ||
2914 | card->index); | ||
2915 | else | ||
2916 | dev_kfree_skb_any(hb); | ||
2917 | |||
2918 | } | ||
2919 | while (card->hbpool.count < card->hbnr.init) | ||
2920 | { | ||
2921 | struct sk_buff *hb; | ||
2922 | |||
2923 | hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL); | ||
2924 | if (hb == NULL) | ||
2925 | return -ENOMEM; | ||
2926 | ns_grab_int_lock(card, flags); | ||
2927 | skb_queue_tail(&card->hbpool.queue, hb); | ||
2928 | card->hbpool.count++; | ||
2929 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
2930 | } | ||
2931 | break; | ||
2932 | |||
2933 | case NS_BUFTYPE_IOVEC: | ||
2934 | while (card->iovpool.count > card->iovnr.init) | ||
2935 | { | ||
2936 | struct sk_buff *iovb; | ||
2937 | |||
2938 | ns_grab_int_lock(card, flags); | ||
2939 | iovb = skb_dequeue(&card->iovpool.queue); | ||
2940 | card->iovpool.count--; | ||
2941 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
2942 | if (iovb == NULL) | ||
2943 | printk("nicstar%d: iovec buffer count inconsistent.\n", | ||
2944 | card->index); | ||
2945 | else | ||
2946 | dev_kfree_skb_any(iovb); | ||
2947 | |||
2948 | } | ||
2949 | while (card->iovpool.count < card->iovnr.init) | ||
2950 | { | ||
2951 | struct sk_buff *iovb; | ||
2952 | |||
2953 | iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); | ||
2954 | if (iovb == NULL) | ||
2955 | return -ENOMEM; | ||
2956 | ns_grab_int_lock(card, flags); | ||
2957 | skb_queue_tail(&card->iovpool.queue, iovb); | ||
2958 | card->iovpool.count++; | ||
2959 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
2960 | } | ||
2961 | break; | ||
2962 | |||
2963 | default: | ||
2964 | return -EINVAL; | ||
2965 | |||
2966 | } | ||
2967 | return 0; | ||
2968 | |||
2969 | default: | ||
2970 | if (dev->phy && dev->phy->ioctl) { | ||
2971 | return dev->phy->ioctl(dev, cmd, arg); | ||
2972 | } | ||
2973 | else { | ||
2974 | printk("nicstar%d: %s == NULL \n", card->index, | ||
2975 | dev->phy ? "dev->phy->ioctl" : "dev->phy"); | ||
2976 | return -ENOIOCTLCMD; | ||
2977 | } | ||
2978 | } | ||
2979 | } | ||
2980 | |||
2981 | |||
2982 | |||
2983 | static void which_list(ns_dev *card, struct sk_buff *skb) | ||
2984 | { | ||
2985 | printk("It's a %s buffer.\n", skb->list == &card->sbpool.queue ? | ||
2986 | "small" : skb->list == &card->lbpool.queue ? "large" : | ||
2987 | skb->list == &card->hbpool.queue ? "huge" : | ||
2988 | skb->list == &card->iovpool.queue ? "iovec" : "unknown"); | ||
2989 | } | ||
2990 | |||
2991 | |||
2992 | |||
2993 | static void ns_poll(unsigned long arg) | ||
2994 | { | ||
2995 | int i; | ||
2996 | ns_dev *card; | ||
2997 | unsigned long flags; | ||
2998 | u32 stat_r, stat_w; | ||
2999 | |||
3000 | PRINTK("nicstar: Entering ns_poll().\n"); | ||
3001 | for (i = 0; i < num_cards; i++) | ||
3002 | { | ||
3003 | card = cards[i]; | ||
3004 | if (spin_is_locked(&card->int_lock)) { | ||
3005 | /* Probably it isn't worth spinning */ | ||
3006 | continue; | ||
3007 | } | ||
3008 | ns_grab_int_lock(card, flags); | ||
3009 | |||
3010 | stat_w = 0; | ||
3011 | stat_r = readl(card->membase + STAT); | ||
3012 | if (stat_r & NS_STAT_TSIF) | ||
3013 | stat_w |= NS_STAT_TSIF; | ||
3014 | if (stat_r & NS_STAT_EOPDU) | ||
3015 | stat_w |= NS_STAT_EOPDU; | ||
3016 | |||
3017 | process_tsq(card); | ||
3018 | process_rsq(card); | ||
3019 | |||
3020 | writel(stat_w, card->membase + STAT); | ||
3021 | spin_unlock_irqrestore(&card->int_lock, flags); | ||
3022 | } | ||
3023 | mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD); | ||
3024 | PRINTK("nicstar: Leaving ns_poll().\n"); | ||
3025 | } | ||
3026 | |||
3027 | |||
3028 | |||
3029 | static int ns_parse_mac(char *mac, unsigned char *esi) | ||
3030 | { | ||
3031 | int i, j; | ||
3032 | short byte1, byte0; | ||
3033 | |||
3034 | if (mac == NULL || esi == NULL) | ||
3035 | return -1; | ||
3036 | j = 0; | ||
3037 | for (i = 0; i < 6; i++) | ||
3038 | { | ||
3039 | if ((byte1 = ns_h2i(mac[j++])) < 0) | ||
3040 | return -1; | ||
3041 | if ((byte0 = ns_h2i(mac[j++])) < 0) | ||
3042 | return -1; | ||
3043 | esi[i] = (unsigned char) (byte1 * 16 + byte0); | ||
3044 | if (i < 5) | ||
3045 | { | ||
3046 | if (mac[j++] != ':') | ||
3047 | return -1; | ||
3048 | } | ||
3049 | } | ||
3050 | return 0; | ||
3051 | } | ||
3052 | |||
3053 | |||
3054 | |||
3055 | static short ns_h2i(char c) | ||
3056 | { | ||
3057 | if (c >= '0' && c <= '9') | ||
3058 | return (short) (c - '0'); | ||
3059 | if (c >= 'A' && c <= 'F') | ||
3060 | return (short) (c - 'A' + 10); | ||
3061 | if (c >= 'a' && c <= 'f') | ||
3062 | return (short) (c - 'a' + 10); | ||
3063 | return -1; | ||
3064 | } | ||
3065 | |||
3066 | |||
3067 | |||
3068 | static void ns_phy_put(struct atm_dev *dev, unsigned char value, | ||
3069 | unsigned long addr) | ||
3070 | { | ||
3071 | ns_dev *card; | ||
3072 | unsigned long flags; | ||
3073 | |||
3074 | card = dev->dev_data; | ||
3075 | ns_grab_res_lock(card, flags); | ||
3076 | while(CMD_BUSY(card)); | ||
3077 | writel((unsigned long) value, card->membase + DR0); | ||
3078 | writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), | ||
3079 | card->membase + CMD); | ||
3080 | spin_unlock_irqrestore(&card->res_lock, flags); | ||
3081 | } | ||
3082 | |||
3083 | |||
3084 | |||
3085 | static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr) | ||
3086 | { | ||
3087 | ns_dev *card; | ||
3088 | unsigned long flags; | ||
3089 | unsigned long data; | ||
3090 | |||
3091 | card = dev->dev_data; | ||
3092 | ns_grab_res_lock(card, flags); | ||
3093 | while(CMD_BUSY(card)); | ||
3094 | writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), | ||
3095 | card->membase + CMD); | ||
3096 | while(CMD_BUSY(card)); | ||
3097 | data = readl(card->membase + DR0) & 0x000000FF; | ||
3098 | spin_unlock_irqrestore(&card->res_lock, flags); | ||
3099 | return (unsigned char) data; | ||
3100 | } | ||
3101 | |||
3102 | |||
3103 | |||
3104 | module_init(nicstar_init); | ||
3105 | module_exit(nicstar_cleanup); | ||
diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h new file mode 100644 index 000000000000..ea83c46c8ba5 --- /dev/null +++ b/drivers/atm/nicstar.h | |||
@@ -0,0 +1,820 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * nicstar.h | ||
4 | * | ||
5 | * Header file for the nicstar device driver. | ||
6 | * | ||
7 | * Author: Rui Prior (rprior@inescn.pt) | ||
8 | * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999 | ||
9 | * | ||
10 | * (C) INESC 1998 | ||
11 | * | ||
12 | ******************************************************************************/ | ||
13 | |||
14 | |||
15 | #ifndef _LINUX_NICSTAR_H_ | ||
16 | #define _LINUX_NICSTAR_H_ | ||
17 | |||
18 | |||
19 | /* Includes *******************************************************************/ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/uio.h> | ||
24 | #include <linux/skbuff.h> | ||
25 | #include <linux/atmdev.h> | ||
26 | #include <linux/atm_nicstar.h> | ||
27 | |||
28 | |||
29 | /* Options ********************************************************************/ | ||
30 | |||
31 | #undef NS_DEBUG_SPINLOCKS | ||
32 | |||
33 | #define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards | ||
34 | controlled by the device driver. Must | ||
35 | be <= 5 */ | ||
36 | |||
37 | #undef RCQ_SUPPORT /* Do not define this for now */ | ||
38 | |||
39 | #define NS_TST_NUM_ENTRIES 2340 /* + 1 for return */ | ||
40 | #define NS_TST_RESERVED 340 /* N. entries reserved for UBR/ABR/VBR */ | ||
41 | |||
42 | #define NS_SMBUFSIZE 48 /* 48, 96, 240 or 2048 */ | ||
43 | #define NS_LGBUFSIZE 16384 /* 2048, 4096, 8192 or 16384 */ | ||
44 | #define NS_RSQSIZE 8192 /* 2048, 4096 or 8192 */ | ||
45 | #define NS_VPIBITS 2 /* 0, 1, 2, or 8 */ | ||
46 | |||
47 | #define NS_MAX_RCTSIZE 4096 /* Number of entries. 4096 or 16384. | ||
48 | Define 4096 only if (all) your card(s) | ||
49 | have 32K x 32bit SRAM, in which case | ||
50 | setting this to 16384 will just waste a | ||
51 | lot of memory. | ||
52 | Setting this to 4096 for a card with | ||
53 | 128K x 32bit SRAM will limit the maximum | ||
54 | VCI. */ | ||
55 | |||
56 | /*#define NS_PCI_LATENCY 64*/ /* Must be a multiple of 32 */ | ||
57 | |||
58 | /* Number of buffers initially allocated */ | ||
59 | #define NUM_SB 32 /* Must be even */ | ||
60 | #define NUM_LB 24 /* Must be even */ | ||
61 | #define NUM_HB 8 /* Pre-allocated huge buffers */ | ||
62 | #define NUM_IOVB 48 /* Iovec buffers */ | ||
63 | |||
64 | /* Lower level for count of buffers */ | ||
65 | #define MIN_SB 8 /* Must be even */ | ||
66 | #define MIN_LB 8 /* Must be even */ | ||
67 | #define MIN_HB 6 | ||
68 | #define MIN_IOVB 8 | ||
69 | |||
70 | /* Upper level for count of buffers */ | ||
71 | #define MAX_SB 64 /* Must be even, <= 508 */ | ||
72 | #define MAX_LB 48 /* Must be even, <= 508 */ | ||
73 | #define MAX_HB 10 | ||
74 | #define MAX_IOVB 80 | ||
75 | |||
76 | /* These are the absolute maximum allowed for the ioctl() */ | ||
77 | #define TOP_SB 256 /* Must be even, <= 508 */ | ||
78 | #define TOP_LB 128 /* Must be even, <= 508 */ | ||
79 | #define TOP_HB 64 | ||
80 | #define TOP_IOVB 256 | ||
81 | |||
82 | |||
83 | #define MAX_TBD_PER_VC 1 /* Number of TBDs before a TSR */ | ||
84 | #define MAX_TBD_PER_SCQ 10 /* Only meaningful for variable rate SCQs */ | ||
85 | |||
86 | #undef ENABLE_TSQFIE | ||
87 | |||
88 | #define SCQFULL_TIMEOUT (5 * HZ) | ||
89 | |||
90 | #define NS_POLL_PERIOD (HZ) | ||
91 | |||
92 | #define PCR_TOLERANCE (1.0001) | ||
93 | |||
94 | |||
95 | |||
96 | /* ESI stuff ******************************************************************/ | ||
97 | |||
98 | #define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C | ||
99 | #define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6 | ||
100 | |||
101 | |||
102 | /* #defines *******************************************************************/ | ||
103 | |||
104 | #define NS_IOREMAP_SIZE 4096 | ||
105 | |||
106 | #define BUF_SM 0x00000000 /* These two are used for push_rxbufs() */ | ||
107 | #define BUF_LG 0x00000001 /* CMD, Write_FreeBufQ, LBUF bit */ | ||
108 | |||
109 | #define NS_HBUFSIZE 65568 /* Size of max. AAL5 PDU */ | ||
110 | #define NS_MAX_IOVECS (2 + (65568 - NS_SMBUFSIZE) / \ | ||
111 | (NS_LGBUFSIZE - (NS_LGBUFSIZE % 48))) | ||
112 | #define NS_IOVBUFSIZE (NS_MAX_IOVECS * (sizeof(struct iovec))) | ||
113 | |||
114 | #define NS_SMBUFSIZE_USABLE (NS_SMBUFSIZE - NS_SMBUFSIZE % 48) | ||
115 | #define NS_LGBUFSIZE_USABLE (NS_LGBUFSIZE - NS_LGBUFSIZE % 48) | ||
116 | |||
117 | #define NS_AAL0_HEADER (ATM_AAL0_SDU - ATM_CELL_PAYLOAD) /* 4 bytes */ | ||
118 | |||
119 | #define NS_SMSKBSIZE (NS_SMBUFSIZE + NS_AAL0_HEADER) | ||
120 | #define NS_LGSKBSIZE (NS_SMBUFSIZE + NS_LGBUFSIZE) | ||
121 | |||
122 | |||
123 | /* NICStAR structures located in host memory **********************************/ | ||
124 | |||
125 | |||
126 | |||
127 | /* RSQ - Receive Status Queue | ||
128 | * | ||
129 | * Written by the NICStAR, read by the device driver. | ||
130 | */ | ||
131 | |||
132 | typedef struct ns_rsqe | ||
133 | { | ||
134 | u32 word_1; | ||
135 | u32 buffer_handle; | ||
136 | u32 final_aal5_crc32; | ||
137 | u32 word_4; | ||
138 | } ns_rsqe; | ||
139 | |||
140 | #define ns_rsqe_vpi(ns_rsqep) \ | ||
141 | ((le32_to_cpu((ns_rsqep)->word_1) & 0x00FF0000) >> 16) | ||
142 | #define ns_rsqe_vci(ns_rsqep) \ | ||
143 | (le32_to_cpu((ns_rsqep)->word_1) & 0x0000FFFF) | ||
144 | |||
145 | #define NS_RSQE_VALID 0x80000000 | ||
146 | #define NS_RSQE_NZGFC 0x00004000 | ||
147 | #define NS_RSQE_EOPDU 0x00002000 | ||
148 | #define NS_RSQE_BUFSIZE 0x00001000 | ||
149 | #define NS_RSQE_CONGESTION 0x00000800 | ||
150 | #define NS_RSQE_CLP 0x00000400 | ||
151 | #define NS_RSQE_CRCERR 0x00000200 | ||
152 | |||
153 | #define NS_RSQE_BUFSIZE_SM 0x00000000 | ||
154 | #define NS_RSQE_BUFSIZE_LG 0x00001000 | ||
155 | |||
156 | #define ns_rsqe_valid(ns_rsqep) \ | ||
157 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_VALID) | ||
158 | #define ns_rsqe_nzgfc(ns_rsqep) \ | ||
159 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_NZGFC) | ||
160 | #define ns_rsqe_eopdu(ns_rsqep) \ | ||
161 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_EOPDU) | ||
162 | #define ns_rsqe_bufsize(ns_rsqep) \ | ||
163 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_BUFSIZE) | ||
164 | #define ns_rsqe_congestion(ns_rsqep) \ | ||
165 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CONGESTION) | ||
166 | #define ns_rsqe_clp(ns_rsqep) \ | ||
167 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CLP) | ||
168 | #define ns_rsqe_crcerr(ns_rsqep) \ | ||
169 | (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CRCERR) | ||
170 | |||
171 | #define ns_rsqe_cellcount(ns_rsqep) \ | ||
172 | (le32_to_cpu((ns_rsqep)->word_4) & 0x000001FF) | ||
173 | #define ns_rsqe_init(ns_rsqep) \ | ||
174 | ((ns_rsqep)->word_4 = cpu_to_le32(0x00000000)) | ||
175 | |||
176 | #define NS_RSQ_NUM_ENTRIES (NS_RSQSIZE / 16) | ||
177 | #define NS_RSQ_ALIGNMENT NS_RSQSIZE | ||
178 | |||
179 | |||
180 | |||
181 | /* RCQ - Raw Cell Queue | ||
182 | * | ||
183 | * Written by the NICStAR, read by the device driver. | ||
184 | */ | ||
185 | |||
186 | typedef struct cell_payload | ||
187 | { | ||
188 | u32 word[12]; | ||
189 | } cell_payload; | ||
190 | |||
191 | typedef struct ns_rcqe | ||
192 | { | ||
193 | u32 word_1; | ||
194 | u32 word_2; | ||
195 | u32 word_3; | ||
196 | u32 word_4; | ||
197 | cell_payload payload; | ||
198 | } ns_rcqe; | ||
199 | |||
200 | #define NS_RCQE_SIZE 64 /* bytes */ | ||
201 | |||
202 | #define ns_rcqe_islast(ns_rcqep) \ | ||
203 | (le32_to_cpu((ns_rcqep)->word_2) != 0x00000000) | ||
204 | #define ns_rcqe_cellheader(ns_rcqep) \ | ||
205 | (le32_to_cpu((ns_rcqep)->word_1)) | ||
206 | #define ns_rcqe_nextbufhandle(ns_rcqep) \ | ||
207 | (le32_to_cpu((ns_rcqep)->word_2)) | ||
208 | |||
209 | |||
210 | |||
211 | /* SCQ - Segmentation Channel Queue | ||
212 | * | ||
213 | * Written by the device driver, read by the NICStAR. | ||
214 | */ | ||
215 | |||
216 | typedef struct ns_scqe | ||
217 | { | ||
218 | u32 word_1; | ||
219 | u32 word_2; | ||
220 | u32 word_3; | ||
221 | u32 word_4; | ||
222 | } ns_scqe; | ||
223 | |||
224 | /* NOTE: SCQ entries can be either a TBD (Transmit Buffer Descriptors) | ||
225 | or TSR (Transmit Status Requests) */ | ||
226 | |||
227 | #define NS_SCQE_TYPE_TBD 0x00000000 | ||
228 | #define NS_SCQE_TYPE_TSR 0x80000000 | ||
229 | |||
230 | |||
231 | #define NS_TBD_EOPDU 0x40000000 | ||
232 | #define NS_TBD_AAL0 0x00000000 | ||
233 | #define NS_TBD_AAL34 0x04000000 | ||
234 | #define NS_TBD_AAL5 0x08000000 | ||
235 | |||
236 | #define NS_TBD_VPI_MASK 0x0FF00000 | ||
237 | #define NS_TBD_VCI_MASK 0x000FFFF0 | ||
238 | #define NS_TBD_VC_MASK (NS_TBD_VPI_MASK | NS_TBD_VCI_MASK) | ||
239 | |||
240 | #define NS_TBD_VPI_SHIFT 20 | ||
241 | #define NS_TBD_VCI_SHIFT 4 | ||
242 | |||
243 | #define ns_tbd_mkword_1(flags, m, n, buflen) \ | ||
244 | (cpu_to_le32((flags) | (m) << 23 | (n) << 16 | (buflen))) | ||
245 | #define ns_tbd_mkword_1_novbr(flags, buflen) \ | ||
246 | (cpu_to_le32((flags) | (buflen) | 0x00810000)) | ||
247 | #define ns_tbd_mkword_3(control, pdulen) \ | ||
248 | (cpu_to_le32((control) << 16 | (pdulen))) | ||
249 | #define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) \ | ||
250 | (cpu_to_le32((gfc) << 28 | (vpi) << 20 | (vci) << 4 | (pt) << 1 | (clp))) | ||
251 | |||
252 | |||
253 | #define NS_TSR_INTENABLE 0x20000000 | ||
254 | |||
255 | #define NS_TSR_SCDISVBR 0xFFFF /* Use as scdi for VBR SCD */ | ||
256 | |||
257 | #define ns_tsr_mkword_1(flags) \ | ||
258 | (cpu_to_le32(NS_SCQE_TYPE_TSR | (flags))) | ||
259 | #define ns_tsr_mkword_2(scdi, scqi) \ | ||
260 | (cpu_to_le32((scdi) << 16 | 0x00008000 | (scqi))) | ||
261 | |||
262 | #define ns_scqe_is_tsr(ns_scqep) \ | ||
263 | (le32_to_cpu((ns_scqep)->word_1) & NS_SCQE_TYPE_TSR) | ||
264 | |||
265 | #define VBR_SCQ_NUM_ENTRIES 512 | ||
266 | #define VBR_SCQSIZE 8192 | ||
267 | #define CBR_SCQ_NUM_ENTRIES 64 | ||
268 | #define CBR_SCQSIZE 1024 | ||
269 | |||
270 | #define NS_SCQE_SIZE 16 | ||
271 | |||
272 | |||
273 | |||
274 | /* TSQ - Transmit Status Queue | ||
275 | * | ||
276 | * Written by the NICStAR, read by the device driver. | ||
277 | */ | ||
278 | |||
279 | typedef struct ns_tsi | ||
280 | { | ||
281 | u32 word_1; | ||
282 | u32 word_2; | ||
283 | } ns_tsi; | ||
284 | |||
285 | /* NOTE: The first word can be a status word copied from the TSR which | ||
286 | originated the TSI, or a timer overflow indicator. In this last | ||
287 | case, the value of the first word is all zeroes. */ | ||
288 | |||
289 | #define NS_TSI_EMPTY 0x80000000 | ||
290 | #define NS_TSI_TIMESTAMP_MASK 0x00FFFFFF | ||
291 | |||
292 | #define ns_tsi_isempty(ns_tsip) \ | ||
293 | (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_EMPTY) | ||
294 | #define ns_tsi_gettimestamp(ns_tsip) \ | ||
295 | (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_TIMESTAMP_MASK) | ||
296 | |||
297 | #define ns_tsi_init(ns_tsip) \ | ||
298 | ((ns_tsip)->word_2 = cpu_to_le32(NS_TSI_EMPTY)) | ||
299 | |||
300 | |||
301 | #define NS_TSQSIZE 8192 | ||
302 | #define NS_TSQ_NUM_ENTRIES 1024 | ||
303 | #define NS_TSQ_ALIGNMENT 8192 | ||
304 | |||
305 | |||
306 | #define NS_TSI_SCDISVBR NS_TSR_SCDISVBR | ||
307 | |||
308 | #define ns_tsi_tmrof(ns_tsip) \ | ||
309 | (le32_to_cpu((ns_tsip)->word_1) == 0x00000000) | ||
310 | #define ns_tsi_getscdindex(ns_tsip) \ | ||
311 | ((le32_to_cpu((ns_tsip)->word_1) & 0xFFFF0000) >> 16) | ||
312 | #define ns_tsi_getscqpos(ns_tsip) \ | ||
313 | (le32_to_cpu((ns_tsip)->word_1) & 0x00007FFF) | ||
314 | |||
315 | |||
316 | |||
317 | /* NICStAR structures located in local SRAM ***********************************/ | ||
318 | |||
319 | |||
320 | |||
321 | /* RCT - Receive Connection Table | ||
322 | * | ||
323 | * Written by both the NICStAR and the device driver. | ||
324 | */ | ||
325 | |||
326 | typedef struct ns_rcte | ||
327 | { | ||
328 | u32 word_1; | ||
329 | u32 buffer_handle; | ||
330 | u32 dma_address; | ||
331 | u32 aal5_crc32; | ||
332 | } ns_rcte; | ||
333 | |||
334 | #define NS_RCTE_BSFB 0x00200000 /* Rev. D only */ | ||
335 | #define NS_RCTE_NZGFC 0x00100000 | ||
336 | #define NS_RCTE_CONNECTOPEN 0x00080000 | ||
337 | #define NS_RCTE_AALMASK 0x00070000 | ||
338 | #define NS_RCTE_AAL0 0x00000000 | ||
339 | #define NS_RCTE_AAL34 0x00010000 | ||
340 | #define NS_RCTE_AAL5 0x00020000 | ||
341 | #define NS_RCTE_RCQ 0x00030000 | ||
342 | #define NS_RCTE_RAWCELLINTEN 0x00008000 | ||
343 | #define NS_RCTE_RXCONSTCELLADDR 0x00004000 | ||
344 | #define NS_RCTE_BUFFVALID 0x00002000 | ||
345 | #define NS_RCTE_FBDSIZE 0x00001000 | ||
346 | #define NS_RCTE_EFCI 0x00000800 | ||
347 | #define NS_RCTE_CLP 0x00000400 | ||
348 | #define NS_RCTE_CRCERROR 0x00000200 | ||
349 | #define NS_RCTE_CELLCOUNT_MASK 0x000001FF | ||
350 | |||
351 | #define NS_RCTE_FBDSIZE_SM 0x00000000 | ||
352 | #define NS_RCTE_FBDSIZE_LG 0x00001000 | ||
353 | |||
354 | #define NS_RCT_ENTRY_SIZE 4 /* Number of dwords */ | ||
355 | |||
356 | /* NOTE: We could make macros to contruct the first word of the RCTE, | ||
357 | but that doesn't seem to make much sense... */ | ||
358 | |||
359 | |||
360 | |||
361 | /* FBD - Free Buffer Descriptor | ||
362 | * | ||
363 | * Written by the device driver using via the command register. | ||
364 | */ | ||
365 | |||
366 | typedef struct ns_fbd | ||
367 | { | ||
368 | u32 buffer_handle; | ||
369 | u32 dma_address; | ||
370 | } ns_fbd; | ||
371 | |||
372 | |||
373 | |||
374 | |||
375 | /* TST - Transmit Schedule Table | ||
376 | * | ||
377 | * Written by the device driver. | ||
378 | */ | ||
379 | |||
380 | typedef u32 ns_tste; | ||
381 | |||
382 | #define NS_TST_OPCODE_MASK 0x60000000 | ||
383 | |||
384 | #define NS_TST_OPCODE_NULL 0x00000000 /* Insert null cell */ | ||
385 | #define NS_TST_OPCODE_FIXED 0x20000000 /* Cell from a fixed rate channel */ | ||
386 | #define NS_TST_OPCODE_VARIABLE 0x40000000 | ||
387 | #define NS_TST_OPCODE_END 0x60000000 /* Jump */ | ||
388 | |||
389 | #define ns_tste_make(opcode, sramad) (opcode | sramad) | ||
390 | |||
391 | /* NOTE: | ||
392 | |||
393 | - When the opcode is FIXED, sramad specifies the SRAM address of the | ||
394 | SCD for that fixed rate channel. | ||
395 | - When the opcode is END, sramad specifies the SRAM address of the | ||
396 | location of the next TST entry to read. | ||
397 | */ | ||
398 | |||
399 | |||
400 | |||
401 | /* SCD - Segmentation Channel Descriptor | ||
402 | * | ||
403 | * Written by both the device driver and the NICStAR | ||
404 | */ | ||
405 | |||
406 | typedef struct ns_scd | ||
407 | { | ||
408 | u32 word_1; | ||
409 | u32 word_2; | ||
410 | u32 partial_aal5_crc; | ||
411 | u32 reserved; | ||
412 | ns_scqe cache_a; | ||
413 | ns_scqe cache_b; | ||
414 | } ns_scd; | ||
415 | |||
416 | #define NS_SCD_BASE_MASK_VAR 0xFFFFE000 /* Variable rate */ | ||
417 | #define NS_SCD_BASE_MASK_FIX 0xFFFFFC00 /* Fixed rate */ | ||
418 | #define NS_SCD_TAIL_MASK_VAR 0x00001FF0 | ||
419 | #define NS_SCD_TAIL_MASK_FIX 0x000003F0 | ||
420 | #define NS_SCD_HEAD_MASK_VAR 0x00001FF0 | ||
421 | #define NS_SCD_HEAD_MASK_FIX 0x000003F0 | ||
422 | #define NS_SCD_XMITFOREVER 0x02000000 | ||
423 | |||
424 | /* NOTE: There are other fields in word 2 of the SCD, but as they should | ||
425 | not be needed in the device driver they are not defined here. */ | ||
426 | |||
427 | |||
428 | |||
429 | |||
430 | /* NICStAR local SRAM memory map **********************************************/ | ||
431 | |||
432 | |||
433 | #define NS_RCT 0x00000 | ||
434 | #define NS_RCT_32_END 0x03FFF | ||
435 | #define NS_RCT_128_END 0x0FFFF | ||
436 | #define NS_UNUSED_32 0x04000 | ||
437 | #define NS_UNUSED_128 0x10000 | ||
438 | #define NS_UNUSED_END 0x1BFFF | ||
439 | #define NS_TST_FRSCD 0x1C000 | ||
440 | #define NS_TST_FRSCD_END 0x1E7DB | ||
441 | #define NS_VRSCD2 0x1E7DC | ||
442 | #define NS_VRSCD2_END 0x1E7E7 | ||
443 | #define NS_VRSCD1 0x1E7E8 | ||
444 | #define NS_VRSCD1_END 0x1E7F3 | ||
445 | #define NS_VRSCD0 0x1E7F4 | ||
446 | #define NS_VRSCD0_END 0x1E7FF | ||
447 | #define NS_RXFIFO 0x1E800 | ||
448 | #define NS_RXFIFO_END 0x1F7FF | ||
449 | #define NS_SMFBQ 0x1F800 | ||
450 | #define NS_SMFBQ_END 0x1FBFF | ||
451 | #define NS_LGFBQ 0x1FC00 | ||
452 | #define NS_LGFBQ_END 0x1FFFF | ||
453 | |||
454 | |||
455 | |||
456 | /* NISCtAR operation registers ************************************************/ | ||
457 | |||
458 | |||
459 | /* See Section 3.4 of `IDT77211 NICStAR User Manual' from www.idt.com */ | ||
460 | |||
461 | enum ns_regs | ||
462 | { | ||
463 | DR0 = 0x00, /* Data Register 0 R/W*/ | ||
464 | DR1 = 0x04, /* Data Register 1 W */ | ||
465 | DR2 = 0x08, /* Data Register 2 W */ | ||
466 | DR3 = 0x0C, /* Data Register 3 W */ | ||
467 | CMD = 0x10, /* Command W */ | ||
468 | CFG = 0x14, /* Configuration R/W */ | ||
469 | STAT = 0x18, /* Status R/W */ | ||
470 | RSQB = 0x1C, /* Receive Status Queue Base W */ | ||
471 | RSQT = 0x20, /* Receive Status Queue Tail R */ | ||
472 | RSQH = 0x24, /* Receive Status Queue Head W */ | ||
473 | CDC = 0x28, /* Cell Drop Counter R/clear */ | ||
474 | VPEC = 0x2C, /* VPI/VCI Lookup Error Count R/clear */ | ||
475 | ICC = 0x30, /* Invalid Cell Count R/clear */ | ||
476 | RAWCT = 0x34, /* Raw Cell Tail R */ | ||
477 | TMR = 0x38, /* Timer R */ | ||
478 | TSTB = 0x3C, /* Transmit Schedule Table Base R/W */ | ||
479 | TSQB = 0x40, /* Transmit Status Queue Base W */ | ||
480 | TSQT = 0x44, /* Transmit Status Queue Tail R */ | ||
481 | TSQH = 0x48, /* Transmit Status Queue Head W */ | ||
482 | GP = 0x4C, /* General Purpose R/W */ | ||
483 | VPM = 0x50 /* VPI/VCI Mask W */ | ||
484 | }; | ||
485 | |||
486 | |||
487 | /* NICStAR commands issued to the CMD register ********************************/ | ||
488 | |||
489 | |||
490 | /* Top 4 bits are command opcode, lower 28 are parameters. */ | ||
491 | |||
492 | #define NS_CMD_NO_OPERATION 0x00000000 | ||
493 | /* params always 0 */ | ||
494 | |||
495 | #define NS_CMD_OPENCLOSE_CONNECTION 0x20000000 | ||
496 | /* b19{1=open,0=close} b18-2{SRAM addr} */ | ||
497 | |||
498 | #define NS_CMD_WRITE_SRAM 0x40000000 | ||
499 | /* b18-2{SRAM addr} b1-0{burst size} */ | ||
500 | |||
501 | #define NS_CMD_READ_SRAM 0x50000000 | ||
502 | /* b18-2{SRAM addr} */ | ||
503 | |||
504 | #define NS_CMD_WRITE_FREEBUFQ 0x60000000 | ||
505 | /* b0{large buf indicator} */ | ||
506 | |||
507 | #define NS_CMD_READ_UTILITY 0x80000000 | ||
508 | /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */ | ||
509 | |||
510 | #define NS_CMD_WRITE_UTILITY 0x90000000 | ||
511 | /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */ | ||
512 | |||
513 | #define NS_CMD_OPEN_CONNECTION (NS_CMD_OPENCLOSE_CONNECTION | 0x00080000) | ||
514 | #define NS_CMD_CLOSE_CONNECTION NS_CMD_OPENCLOSE_CONNECTION | ||
515 | |||
516 | |||
517 | /* NICStAR configuration bits *************************************************/ | ||
518 | |||
519 | #define NS_CFG_SWRST 0x80000000 /* Software Reset */ | ||
520 | #define NS_CFG_RXPATH 0x20000000 /* Receive Path Enable */ | ||
521 | #define NS_CFG_SMBUFSIZE_MASK 0x18000000 /* Small Receive Buffer Size */ | ||
522 | #define NS_CFG_LGBUFSIZE_MASK 0x06000000 /* Large Receive Buffer Size */ | ||
523 | #define NS_CFG_EFBIE 0x01000000 /* Empty Free Buffer Queue | ||
524 | Interrupt Enable */ | ||
525 | #define NS_CFG_RSQSIZE_MASK 0x00C00000 /* Receive Status Queue Size */ | ||
526 | #define NS_CFG_ICACCEPT 0x00200000 /* Invalid Cell Accept */ | ||
527 | #define NS_CFG_IGNOREGFC 0x00100000 /* Ignore General Flow Control */ | ||
528 | #define NS_CFG_VPIBITS_MASK 0x000C0000 /* VPI/VCI Bits Size Select */ | ||
529 | #define NS_CFG_RCTSIZE_MASK 0x00030000 /* Receive Connection Table Size */ | ||
530 | #define NS_CFG_VCERRACCEPT 0x00008000 /* VPI/VCI Error Cell Accept */ | ||
531 | #define NS_CFG_RXINT_MASK 0x00007000 /* End of Receive PDU Interrupt | ||
532 | Handling */ | ||
533 | #define NS_CFG_RAWIE 0x00000800 /* Raw Cell Qu' Interrupt Enable */ | ||
534 | #define NS_CFG_RSQAFIE 0x00000400 /* Receive Queue Almost Full | ||
535 | Interrupt Enable */ | ||
536 | #define NS_CFG_RXRM 0x00000200 /* Receive RM Cells */ | ||
537 | #define NS_CFG_TMRROIE 0x00000080 /* Timer Roll Over Interrupt | ||
538 | Enable */ | ||
539 | #define NS_CFG_TXEN 0x00000020 /* Transmit Operation Enable */ | ||
540 | #define NS_CFG_TXIE 0x00000010 /* Transmit Status Interrupt | ||
541 | Enable */ | ||
542 | #define NS_CFG_TXURIE 0x00000008 /* Transmit Under-run Interrupt | ||
543 | Enable */ | ||
544 | #define NS_CFG_UMODE 0x00000004 /* Utopia Mode (cell/byte) Select */ | ||
545 | #define NS_CFG_TSQFIE 0x00000002 /* Transmit Status Queue Full | ||
546 | Interrupt Enable */ | ||
547 | #define NS_CFG_PHYIE 0x00000001 /* PHY Interrupt Enable */ | ||
548 | |||
549 | #define NS_CFG_SMBUFSIZE_48 0x00000000 | ||
550 | #define NS_CFG_SMBUFSIZE_96 0x08000000 | ||
551 | #define NS_CFG_SMBUFSIZE_240 0x10000000 | ||
552 | #define NS_CFG_SMBUFSIZE_2048 0x18000000 | ||
553 | |||
554 | #define NS_CFG_LGBUFSIZE_2048 0x00000000 | ||
555 | #define NS_CFG_LGBUFSIZE_4096 0x02000000 | ||
556 | #define NS_CFG_LGBUFSIZE_8192 0x04000000 | ||
557 | #define NS_CFG_LGBUFSIZE_16384 0x06000000 | ||
558 | |||
559 | #define NS_CFG_RSQSIZE_2048 0x00000000 | ||
560 | #define NS_CFG_RSQSIZE_4096 0x00400000 | ||
561 | #define NS_CFG_RSQSIZE_8192 0x00800000 | ||
562 | |||
563 | #define NS_CFG_VPIBITS_0 0x00000000 | ||
564 | #define NS_CFG_VPIBITS_1 0x00040000 | ||
565 | #define NS_CFG_VPIBITS_2 0x00080000 | ||
566 | #define NS_CFG_VPIBITS_8 0x000C0000 | ||
567 | |||
568 | #define NS_CFG_RCTSIZE_4096_ENTRIES 0x00000000 | ||
569 | #define NS_CFG_RCTSIZE_8192_ENTRIES 0x00010000 | ||
570 | #define NS_CFG_RCTSIZE_16384_ENTRIES 0x00020000 | ||
571 | |||
572 | #define NS_CFG_RXINT_NOINT 0x00000000 | ||
573 | #define NS_CFG_RXINT_NODELAY 0x00001000 | ||
574 | #define NS_CFG_RXINT_314US 0x00002000 | ||
575 | #define NS_CFG_RXINT_624US 0x00003000 | ||
576 | #define NS_CFG_RXINT_899US 0x00004000 | ||
577 | |||
578 | |||
579 | /* NICStAR STATus bits ********************************************************/ | ||
580 | |||
581 | #define NS_STAT_SFBQC_MASK 0xFF000000 /* hi 8 bits Small Buffer Queue Count */ | ||
582 | #define NS_STAT_LFBQC_MASK 0x00FF0000 /* hi 8 bits Large Buffer Queue Count */ | ||
583 | #define NS_STAT_TSIF 0x00008000 /* Transmit Status Queue Indicator */ | ||
584 | #define NS_STAT_TXICP 0x00004000 /* Transmit Incomplete PDU */ | ||
585 | #define NS_STAT_TSQF 0x00001000 /* Transmit Status Queue Full */ | ||
586 | #define NS_STAT_TMROF 0x00000800 /* Timer Overflow */ | ||
587 | #define NS_STAT_PHYI 0x00000400 /* PHY Device Interrupt */ | ||
588 | #define NS_STAT_CMDBZ 0x00000200 /* Command Busy */ | ||
589 | #define NS_STAT_SFBQF 0x00000100 /* Small Buffer Queue Full */ | ||
590 | #define NS_STAT_LFBQF 0x00000080 /* Large Buffer Queue Full */ | ||
591 | #define NS_STAT_RSQF 0x00000040 /* Receive Status Queue Full */ | ||
592 | #define NS_STAT_EOPDU 0x00000020 /* End of PDU */ | ||
593 | #define NS_STAT_RAWCF 0x00000010 /* Raw Cell Flag */ | ||
594 | #define NS_STAT_SFBQE 0x00000008 /* Small Buffer Queue Empty */ | ||
595 | #define NS_STAT_LFBQE 0x00000004 /* Large Buffer Queue Empty */ | ||
596 | #define NS_STAT_RSQAF 0x00000002 /* Receive Status Queue Almost Full */ | ||
597 | |||
598 | #define ns_stat_sfbqc_get(stat) (((stat) & NS_STAT_SFBQC_MASK) >> 23) | ||
599 | #define ns_stat_lfbqc_get(stat) (((stat) & NS_STAT_LFBQC_MASK) >> 15) | ||
600 | |||
601 | |||
602 | |||
603 | /* #defines which depend on other #defines ************************************/ | ||
604 | |||
605 | |||
606 | #define NS_TST0 NS_TST_FRSCD | ||
607 | #define NS_TST1 (NS_TST_FRSCD + NS_TST_NUM_ENTRIES + 1) | ||
608 | |||
609 | #define NS_FRSCD (NS_TST1 + NS_TST_NUM_ENTRIES + 1) | ||
610 | #define NS_FRSCD_SIZE 12 /* 12 dwords */ | ||
611 | #define NS_FRSCD_NUM ((NS_TST_FRSCD_END + 1 - NS_FRSCD) / NS_FRSCD_SIZE) | ||
612 | |||
613 | #if (NS_SMBUFSIZE == 48) | ||
614 | #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_48 | ||
615 | #elif (NS_SMBUFSIZE == 96) | ||
616 | #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_96 | ||
617 | #elif (NS_SMBUFSIZE == 240) | ||
618 | #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_240 | ||
619 | #elif (NS_SMBUFSIZE == 2048) | ||
620 | #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_2048 | ||
621 | #else | ||
622 | #error NS_SMBUFSIZE is incorrect in nicstar.h | ||
623 | #endif /* NS_SMBUFSIZE */ | ||
624 | |||
625 | #if (NS_LGBUFSIZE == 2048) | ||
626 | #define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_2048 | ||
627 | #elif (NS_LGBUFSIZE == 4096) | ||
628 | #define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_4096 | ||
629 | #elif (NS_LGBUFSIZE == 8192) | ||
630 | #define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_8192 | ||
631 | #elif (NS_LGBUFSIZE == 16384) | ||
632 | #define NS_CFG_LGBUFSIZE NS_CFG_LGBUFSIZE_16384 | ||
633 | #else | ||
634 | #error NS_LGBUFSIZE is incorrect in nicstar.h | ||
635 | #endif /* NS_LGBUFSIZE */ | ||
636 | |||
637 | #if (NS_RSQSIZE == 2048) | ||
638 | #define NS_CFG_RSQSIZE NS_CFG_RSQSIZE_2048 | ||
639 | #elif (NS_RSQSIZE == 4096) | ||
640 | #define NS_CFG_RSQSIZE NS_CFG_RSQSIZE_4096 | ||
641 | #elif (NS_RSQSIZE == 8192) | ||
642 | #define NS_CFG_RSQSIZE NS_CFG_RSQSIZE_8192 | ||
643 | #else | ||
644 | #error NS_RSQSIZE is incorrect in nicstar.h | ||
645 | #endif /* NS_RSQSIZE */ | ||
646 | |||
647 | #if (NS_VPIBITS == 0) | ||
648 | #define NS_CFG_VPIBITS NS_CFG_VPIBITS_0 | ||
649 | #elif (NS_VPIBITS == 1) | ||
650 | #define NS_CFG_VPIBITS NS_CFG_VPIBITS_1 | ||
651 | #elif (NS_VPIBITS == 2) | ||
652 | #define NS_CFG_VPIBITS NS_CFG_VPIBITS_2 | ||
653 | #elif (NS_VPIBITS == 8) | ||
654 | #define NS_CFG_VPIBITS NS_CFG_VPIBITS_8 | ||
655 | #else | ||
656 | #error NS_VPIBITS is incorrect in nicstar.h | ||
657 | #endif /* NS_VPIBITS */ | ||
658 | |||
659 | #ifdef RCQ_SUPPORT | ||
660 | #define NS_CFG_RAWIE_OPT NS_CFG_RAWIE | ||
661 | #else | ||
662 | #define NS_CFG_RAWIE_OPT 0x00000000 | ||
663 | #endif /* RCQ_SUPPORT */ | ||
664 | |||
665 | #ifdef ENABLE_TSQFIE | ||
666 | #define NS_CFG_TSQFIE_OPT NS_CFG_TSQFIE | ||
667 | #else | ||
668 | #define NS_CFG_TSQFIE_OPT 0x00000000 | ||
669 | #endif /* ENABLE_TSQFIE */ | ||
670 | |||
671 | |||
672 | /* PCI stuff ******************************************************************/ | ||
673 | |||
674 | #ifndef PCI_VENDOR_ID_IDT | ||
675 | #define PCI_VENDOR_ID_IDT 0x111D | ||
676 | #endif /* PCI_VENDOR_ID_IDT */ | ||
677 | |||
678 | #ifndef PCI_DEVICE_ID_IDT_IDT77201 | ||
679 | #define PCI_DEVICE_ID_IDT_IDT77201 0x0001 | ||
680 | #endif /* PCI_DEVICE_ID_IDT_IDT77201 */ | ||
681 | |||
682 | |||
683 | |||
684 | /* Device driver structures ***************************************************/ | ||
685 | |||
686 | |||
687 | typedef struct tsq_info | ||
688 | { | ||
689 | void *org; | ||
690 | ns_tsi *base; | ||
691 | ns_tsi *next; | ||
692 | ns_tsi *last; | ||
693 | } tsq_info; | ||
694 | |||
695 | |||
696 | typedef struct scq_info | ||
697 | { | ||
698 | void *org; | ||
699 | ns_scqe *base; | ||
700 | ns_scqe *last; | ||
701 | ns_scqe *next; | ||
702 | volatile ns_scqe *tail; /* Not related to the nicstar register */ | ||
703 | unsigned num_entries; | ||
704 | struct sk_buff **skb; /* Pointer to an array of pointers | ||
705 | to the sk_buffs used for tx */ | ||
706 | u32 scd; /* SRAM address of the corresponding | ||
707 | SCD */ | ||
708 | int tbd_count; /* Only meaningful on variable rate */ | ||
709 | wait_queue_head_t scqfull_waitq; | ||
710 | volatile char full; /* SCQ full indicator */ | ||
711 | spinlock_t lock; /* SCQ spinlock */ | ||
712 | #ifdef NS_DEBUG_SPINLOCKS | ||
713 | volatile long has_lock; | ||
714 | volatile int cpu_lock; | ||
715 | #endif /* NS_DEBUG_SPINLOCKS */ | ||
716 | } scq_info; | ||
717 | |||
718 | |||
719 | |||
720 | typedef struct rsq_info | ||
721 | { | ||
722 | void *org; | ||
723 | ns_rsqe *base; | ||
724 | ns_rsqe *next; | ||
725 | ns_rsqe *last; | ||
726 | } rsq_info; | ||
727 | |||
728 | |||
729 | typedef struct skb_pool | ||
730 | { | ||
731 | volatile int count; /* number of buffers in the queue */ | ||
732 | struct sk_buff_head queue; | ||
733 | } skb_pool; | ||
734 | |||
735 | /* NOTE: for small and large buffer pools, the count is not used, as the | ||
736 | actual value used for buffer management is the one read from the | ||
737 | card. */ | ||
738 | |||
739 | |||
740 | typedef struct vc_map | ||
741 | { | ||
742 | volatile unsigned int tx:1; /* TX vc? */ | ||
743 | volatile unsigned int rx:1; /* RX vc? */ | ||
744 | struct atm_vcc *tx_vcc, *rx_vcc; | ||
745 | struct sk_buff *rx_iov; /* RX iovector skb */ | ||
746 | scq_info *scq; /* To keep track of the SCQ */ | ||
747 | u32 cbr_scd; /* SRAM address of the corresponding | ||
748 | SCD. 0x00000000 for UBR/VBR/ABR */ | ||
749 | int tbd_count; | ||
750 | } vc_map; | ||
751 | |||
752 | |||
753 | struct ns_skb_data | ||
754 | { | ||
755 | struct atm_vcc *vcc; | ||
756 | int iovcnt; | ||
757 | }; | ||
758 | |||
759 | #define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb)) | ||
760 | |||
761 | |||
762 | typedef struct ns_dev | ||
763 | { | ||
764 | int index; /* Card ID to the device driver */ | ||
765 | int sram_size; /* In k x 32bit words. 32 or 128 */ | ||
766 | void __iomem *membase; /* Card's memory base address */ | ||
767 | unsigned long max_pcr; | ||
768 | int rct_size; /* Number of entries */ | ||
769 | int vpibits; | ||
770 | int vcibits; | ||
771 | struct pci_dev *pcidev; | ||
772 | struct atm_dev *atmdev; | ||
773 | tsq_info tsq; | ||
774 | rsq_info rsq; | ||
775 | scq_info *scq0, *scq1, *scq2; /* VBR SCQs */ | ||
776 | skb_pool sbpool; /* Small buffers */ | ||
777 | skb_pool lbpool; /* Large buffers */ | ||
778 | skb_pool hbpool; /* Pre-allocated huge buffers */ | ||
779 | skb_pool iovpool; /* iovector buffers */ | ||
780 | volatile int efbie; /* Empty free buf. queue int. enabled */ | ||
781 | volatile u32 tst_addr; /* SRAM address of the TST in use */ | ||
782 | volatile int tst_free_entries; | ||
783 | vc_map vcmap[NS_MAX_RCTSIZE]; | ||
784 | vc_map *tste2vc[NS_TST_NUM_ENTRIES]; | ||
785 | vc_map *scd2vc[NS_FRSCD_NUM]; | ||
786 | buf_nr sbnr; | ||
787 | buf_nr lbnr; | ||
788 | buf_nr hbnr; | ||
789 | buf_nr iovnr; | ||
790 | int sbfqc; | ||
791 | int lbfqc; | ||
792 | u32 sm_handle; | ||
793 | u32 sm_addr; | ||
794 | u32 lg_handle; | ||
795 | u32 lg_addr; | ||
796 | struct sk_buff *rcbuf; /* Current raw cell buffer */ | ||
797 | u32 rawch; /* Raw cell queue head */ | ||
798 | unsigned intcnt; /* Interrupt counter */ | ||
799 | spinlock_t int_lock; /* Interrupt lock */ | ||
800 | spinlock_t res_lock; /* Card resource lock */ | ||
801 | #ifdef NS_DEBUG_SPINLOCKS | ||
802 | volatile long has_int_lock; | ||
803 | volatile int cpu_int; | ||
804 | volatile long has_res_lock; | ||
805 | volatile int cpu_res; | ||
806 | #endif /* NS_DEBUG_SPINLOCKS */ | ||
807 | } ns_dev; | ||
808 | |||
809 | |||
810 | /* NOTE: Each tste2vc entry relates a given TST entry to the corresponding | ||
811 | CBR vc. If the entry is not allocated, it must be NULL. | ||
812 | |||
813 | There are two TSTs so the driver can modify them on the fly | ||
814 | without stopping the transmission. | ||
815 | |||
816 | scd2vc allows us to find out unused fixed rate SCDs, because | ||
817 | they must have a NULL pointer here. */ | ||
818 | |||
819 | |||
820 | #endif /* _LINUX_NICSTAR_H_ */ | ||
diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c new file mode 100644 index 000000000000..2c5e3ae77503 --- /dev/null +++ b/drivers/atm/nicstarmac.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* | ||
2 | * this file included by nicstar.c | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * nicstarmac.c | ||
7 | * Read this ForeRunner's MAC address from eprom/eeprom | ||
8 | */ | ||
9 | |||
10 | typedef void __iomem *virt_addr_t; | ||
11 | |||
12 | #define CYCLE_DELAY 5 | ||
13 | |||
14 | /* This was the original definition | ||
15 | #define osp_MicroDelay(microsec) \ | ||
16 | do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) | ||
17 | */ | ||
18 | #define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \ | ||
19 | udelay((useconds));} | ||
20 | |||
21 | |||
22 | /* The following tables represent the timing diagrams found in | ||
23 | * the Data Sheet for the Xicor X25020 EEProm. The #defines below | ||
24 | * represent the bits in the NICStAR's General Purpose register | ||
25 | * that must be toggled for the corresponding actions on the EEProm | ||
26 | * to occur. | ||
27 | */ | ||
28 | |||
29 | /* Write Data To EEProm from SI line on rising edge of CLK */ | ||
30 | /* Read Data From EEProm on falling edge of CLK */ | ||
31 | |||
32 | #define CS_HIGH 0x0002 /* Chip select high */ | ||
33 | #define CS_LOW 0x0000 /* Chip select low (active low)*/ | ||
34 | #define CLK_HIGH 0x0004 /* Clock high */ | ||
35 | #define CLK_LOW 0x0000 /* Clock low */ | ||
36 | #define SI_HIGH 0x0001 /* Serial input data high */ | ||
37 | #define SI_LOW 0x0000 /* Serial input data low */ | ||
38 | |||
39 | /* Read Status Register = 0000 0101b */ | ||
40 | #if 0 | ||
41 | static u_int32_t rdsrtab[] = | ||
42 | { | ||
43 | CS_HIGH | CLK_HIGH, | ||
44 | CS_LOW | CLK_LOW, | ||
45 | CLK_HIGH, /* 0 */ | ||
46 | CLK_LOW, | ||
47 | CLK_HIGH, /* 0 */ | ||
48 | CLK_LOW, | ||
49 | CLK_HIGH, /* 0 */ | ||
50 | CLK_LOW, | ||
51 | CLK_HIGH, /* 0 */ | ||
52 | CLK_LOW, | ||
53 | CLK_HIGH, /* 0 */ | ||
54 | CLK_LOW | SI_HIGH, | ||
55 | CLK_HIGH | SI_HIGH, /* 1 */ | ||
56 | CLK_LOW | SI_LOW, | ||
57 | CLK_HIGH, /* 0 */ | ||
58 | CLK_LOW | SI_HIGH, | ||
59 | CLK_HIGH | SI_HIGH /* 1 */ | ||
60 | }; | ||
61 | #endif /* 0 */ | ||
62 | |||
63 | |||
64 | /* Read from EEPROM = 0000 0011b */ | ||
65 | static u_int32_t readtab[] = | ||
66 | { | ||
67 | /* | ||
68 | CS_HIGH | CLK_HIGH, | ||
69 | */ | ||
70 | CS_LOW | CLK_LOW, | ||
71 | CLK_HIGH, /* 0 */ | ||
72 | CLK_LOW, | ||
73 | CLK_HIGH, /* 0 */ | ||
74 | CLK_LOW, | ||
75 | CLK_HIGH, /* 0 */ | ||
76 | CLK_LOW, | ||
77 | CLK_HIGH, /* 0 */ | ||
78 | CLK_LOW, | ||
79 | CLK_HIGH, /* 0 */ | ||
80 | CLK_LOW, | ||
81 | CLK_HIGH, /* 0 */ | ||
82 | CLK_LOW | SI_HIGH, | ||
83 | CLK_HIGH | SI_HIGH, /* 1 */ | ||
84 | CLK_LOW | SI_HIGH, | ||
85 | CLK_HIGH | SI_HIGH /* 1 */ | ||
86 | }; | ||
87 | |||
88 | |||
89 | /* Clock to read from/write to the eeprom */ | ||
90 | static u_int32_t clocktab[] = | ||
91 | { | ||
92 | CLK_LOW, | ||
93 | CLK_HIGH, | ||
94 | CLK_LOW, | ||
95 | CLK_HIGH, | ||
96 | CLK_LOW, | ||
97 | CLK_HIGH, | ||
98 | CLK_LOW, | ||
99 | CLK_HIGH, | ||
100 | CLK_LOW, | ||
101 | CLK_HIGH, | ||
102 | CLK_LOW, | ||
103 | CLK_HIGH, | ||
104 | CLK_LOW, | ||
105 | CLK_HIGH, | ||
106 | CLK_LOW, | ||
107 | CLK_HIGH, | ||
108 | CLK_LOW | ||
109 | }; | ||
110 | |||
111 | |||
112 | #define NICSTAR_REG_WRITE(bs, reg, val) \ | ||
113 | while ( readl(bs + STAT) & 0x0200 ) ; \ | ||
114 | writel((val),(base)+(reg)) | ||
115 | #define NICSTAR_REG_READ(bs, reg) \ | ||
116 | readl((base)+(reg)) | ||
117 | #define NICSTAR_REG_GENERAL_PURPOSE GP | ||
118 | |||
119 | /* | ||
120 | * This routine will clock the Read_Status_reg function into the X2520 | ||
121 | * eeprom, then pull the result from bit 16 of the NicSTaR's General Purpose | ||
122 | * register. | ||
123 | */ | ||
124 | #if 0 | ||
125 | u_int32_t | ||
126 | nicstar_read_eprom_status( virt_addr_t base ) | ||
127 | { | ||
128 | u_int32_t val; | ||
129 | u_int32_t rbyte; | ||
130 | int32_t i, j; | ||
131 | |||
132 | /* Send read instruction */ | ||
133 | val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0; | ||
134 | |||
135 | for (i=0; i<sizeof rdsrtab/sizeof rdsrtab[0]; i++) | ||
136 | { | ||
137 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
138 | (val | rdsrtab[i]) ); | ||
139 | osp_MicroDelay( CYCLE_DELAY ); | ||
140 | } | ||
141 | |||
142 | /* Done sending instruction - now pull data off of bit 16, MSB first */ | ||
143 | /* Data clocked out of eeprom on falling edge of clock */ | ||
144 | |||
145 | rbyte = 0; | ||
146 | for (i=7, j=0; i>=0; i--) | ||
147 | { | ||
148 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
149 | (val | clocktab[j++]) ); | ||
150 | rbyte |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE) | ||
151 | & 0x00010000) >> 16) << i); | ||
152 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
153 | (val | clocktab[j++]) ); | ||
154 | osp_MicroDelay( CYCLE_DELAY ); | ||
155 | } | ||
156 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 ); | ||
157 | osp_MicroDelay( CYCLE_DELAY ); | ||
158 | return rbyte; | ||
159 | } | ||
160 | #endif /* 0 */ | ||
161 | |||
162 | |||
163 | /* | ||
164 | * This routine will clock the Read_data function into the X2520 | ||
165 | * eeprom, followed by the address to read from, through the NicSTaR's General | ||
166 | * Purpose register. | ||
167 | */ | ||
168 | |||
169 | static u_int8_t | ||
170 | read_eprom_byte(virt_addr_t base, u_int8_t offset) | ||
171 | { | ||
172 | u_int32_t val = 0; | ||
173 | int i,j=0; | ||
174 | u_int8_t tempread = 0; | ||
175 | |||
176 | val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0; | ||
177 | |||
178 | /* Send READ instruction */ | ||
179 | for (i=0; i<sizeof readtab/sizeof readtab[0]; i++) | ||
180 | { | ||
181 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
182 | (val | readtab[i]) ); | ||
183 | osp_MicroDelay( CYCLE_DELAY ); | ||
184 | } | ||
185 | |||
186 | /* Next, we need to send the byte address to read from */ | ||
187 | for (i=7; i>=0; i--) | ||
188 | { | ||
189 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
190 | (val | clocktab[j++] | ((offset >> i) & 1) ) ); | ||
191 | osp_MicroDelay(CYCLE_DELAY); | ||
192 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
193 | (val | clocktab[j++] | ((offset >> i) & 1) ) ); | ||
194 | osp_MicroDelay( CYCLE_DELAY ); | ||
195 | } | ||
196 | |||
197 | j = 0; | ||
198 | |||
199 | /* Now, we can read data from the eeprom by clocking it in */ | ||
200 | for (i=7; i>=0; i--) | ||
201 | { | ||
202 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
203 | (val | clocktab[j++]) ); | ||
204 | osp_MicroDelay( CYCLE_DELAY ); | ||
205 | tempread |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) | ||
206 | & 0x00010000) >> 16) << i); | ||
207 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, | ||
208 | (val | clocktab[j++]) ); | ||
209 | osp_MicroDelay( CYCLE_DELAY ); | ||
210 | } | ||
211 | |||
212 | NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 ); | ||
213 | osp_MicroDelay( CYCLE_DELAY ); | ||
214 | return tempread; | ||
215 | } | ||
216 | |||
217 | |||
218 | static void | ||
219 | nicstar_init_eprom( virt_addr_t base ) | ||
220 | { | ||
221 | u_int32_t val; | ||
222 | |||
223 | /* | ||
224 | * turn chip select off | ||
225 | */ | ||
226 | val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; | ||
227 | |||
228 | NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, | ||
229 | (val | CS_HIGH | CLK_HIGH)); | ||
230 | osp_MicroDelay( CYCLE_DELAY ); | ||
231 | |||
232 | NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, | ||
233 | (val | CS_HIGH | CLK_LOW)); | ||
234 | osp_MicroDelay( CYCLE_DELAY ); | ||
235 | |||
236 | NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, | ||
237 | (val | CS_HIGH | CLK_HIGH)); | ||
238 | osp_MicroDelay( CYCLE_DELAY ); | ||
239 | |||
240 | NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, | ||
241 | (val | CS_HIGH | CLK_LOW)); | ||
242 | osp_MicroDelay( CYCLE_DELAY ); | ||
243 | } | ||
244 | |||
245 | |||
246 | /* | ||
247 | * This routine will be the interface to the ReadPromByte function | ||
248 | * above. | ||
249 | */ | ||
250 | |||
251 | static void | ||
252 | nicstar_read_eprom( | ||
253 | virt_addr_t base, | ||
254 | u_int8_t prom_offset, | ||
255 | u_int8_t *buffer, | ||
256 | u_int32_t nbytes ) | ||
257 | { | ||
258 | u_int i; | ||
259 | |||
260 | for (i=0; i<nbytes; i++) | ||
261 | { | ||
262 | buffer[i] = read_eprom_byte( base, prom_offset ); | ||
263 | ++prom_offset; | ||
264 | osp_MicroDelay( CYCLE_DELAY ); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | |||
269 | /* | ||
270 | void osp_MicroDelay(int x) { | ||
271 | |||
272 | } | ||
273 | */ | ||
274 | |||
diff --git a/drivers/atm/nicstarmac.copyright b/drivers/atm/nicstarmac.copyright new file mode 100644 index 000000000000..2e15b39fac4f --- /dev/null +++ b/drivers/atm/nicstarmac.copyright | |||
@@ -0,0 +1,61 @@ | |||
1 | /* nicstar.c v0.22 Jawaid Bazyar (bazyar@hypermall.com) | ||
2 | * nicstar.c, M. Welsh (matt.welsh@cl.cam.ac.uk) | ||
3 | * | ||
4 | * Hacked October, 1997 by Jawaid Bazyar, Interlink Advertising Services Inc. | ||
5 | * http://www.hypermall.com/ | ||
6 | * 10/1/97 - commented out CFG_PHYIE bit - we don't care when the PHY | ||
7 | * interrupts us (except possibly for removal/insertion of the cable?) | ||
8 | * 10/4/97 - began heavy inline documentation of the code. Corrected typos | ||
9 | * and spelling mistakes. | ||
10 | * 10/5/97 - added code to handle PHY interrupts, disable PHY on | ||
11 | * loss of link, and correctly re-enable PHY when link is | ||
12 | * re-established. (put back CFG_PHYIE) | ||
13 | * | ||
14 | * Modified to work with the IDT7721 nicstar -- AAL5 (tested) only. | ||
15 | * | ||
16 | * R. D. Rechenmacher <ron@fnal.gov>, Aug. 6, 1997 $Revision: 1.1 $ $Date: 1999/08/20 11:00:11 $ | ||
17 | * | ||
18 | * Linux driver for the IDT77201 NICStAR PCI ATM controller. | ||
19 | * PHY component is expected to be 155 Mbps S/UNI-Lite or IDT 77155; | ||
20 | * see init_nicstar() for PHY initialization to change this. This driver | ||
21 | * expects the Linux ATM stack to support scatter-gather lists | ||
22 | * (skb->atm.iovcnt != 0) for Rx skb's passed to vcc->push. | ||
23 | * | ||
24 | * Implementing minimal-copy of received data: | ||
25 | * IDT always receives data into a small buffer, then large buffers | ||
26 | * as needed. This means that data must always be copied to create | ||
27 | * the linear buffer needed by most non-ATM protocol stacks (e.g. IP) | ||
28 | * Fix is simple: make large buffers large enough to hold entire | ||
29 | * SDU, and leave <small_buffer_data> bytes empty at the start. Then | ||
30 | * copy small buffer contents to head of large buffer. | ||
31 | * Trick is to avoid fragmenting Linux, due to need for a lot of large | ||
32 | * buffers. This is done by 2 things: | ||
33 | * 1) skb->destructor / skb->atm.recycle_buffer | ||
34 | * combined, allow nicstar_free_rx_skb to be called to | ||
35 | * recycle large data buffers | ||
36 | * 2) skb_clone of received buffers | ||
37 | * See nicstar_free_rx_skb and linearize_buffer for implementation | ||
38 | * details. | ||
39 | * | ||
40 | * | ||
41 | * | ||
42 | * Copyright (c) 1996 University of Cambridge Computer Laboratory | ||
43 | * | ||
44 | * This program is free software; you can redistribute it and/or modify | ||
45 | * it under the terms of the GNU General Public License as published by | ||
46 | * the Free Software Foundation; either version 2 of the License, or | ||
47 | * (at your option) any later version. | ||
48 | * | ||
49 | * This program is distributed in the hope that it will be useful, | ||
50 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
51 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
52 | * GNU General Public License for more details. | ||
53 | * | ||
54 | * You should have received a copy of the GNU General Public License | ||
55 | * along with this program; if not, write to the Free Software | ||
56 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
57 | * | ||
58 | * M. Welsh, 6 July 1996 | ||
59 | * | ||
60 | * | ||
61 | */ | ||
diff --git a/drivers/atm/pca200e.data b/drivers/atm/pca200e.data new file mode 100644 index 000000000000..e78e83becd95 --- /dev/null +++ b/drivers/atm/pca200e.data | |||
@@ -0,0 +1,850 @@ | |||
1 | :150000001F8B0808AB5A10380203706361323030652E62696E4D | ||
2 | :150015007D00E43A0D7014D7796FA5BDE84EC86211A7333020EE | ||
3 | :15002A00AD89C00A23EA83AA589C7E7C38D8152EB887477677D3 | ||
4 | :15003F0095C39C3DB2AB388CA324C4A509352BFBB085BBD0C73F | ||
5 | :150054007210B903C92991CCD1B1C242255BCCD81EA5C34C6826 | ||
6 | :1500690006271AC6D36A3A31B976D4A9A683DB4B07BB38265C56 | ||
7 | :15007E00BFEFBDB7777BA7030B2733994C35737AFBBEF7BDEFE7 | ||
8 | :15009300EF7DDFF7BEF7769FFEEAD79F221221E1ED844C3E4677 | ||
9 | :1500A8007EA3BFF036F827CF8597C3AF0C7E920B16595BCE5AA8 | ||
10 | :1500BD00296B6483D83E9F7DBE8FF50BE74A0B45FB1F274FAA79 | ||
11 | :1500D200D82E2867139DF637FD937EF1D55FB0769FE8678BDAFB | ||
12 | :1500E7007D9BD8885451515172FE27E4138E9FC9949CBFF026BC | ||
13 | :1500FC00741DF83ECE59823FF23BF89346493F6B4F17C1B3A7CE | ||
14 | :15011100B3B79C97D3275B5ABFEC3CF9579457703B3CBFEFD600 | ||
15 | :15012600FC38236CA91B5E347EDBFA67F7ED4397956EA4D3C5F4 | ||
16 | :15013B007CE6A567799EFFF5CFC4FF7BDF938BF83E83EDE59F02 | ||
17 | :15015000FEAC24BF8A3C3F2FF9FDFF933CF51EF2FFEC2FEBFA11 | ||
18 | :150165002341C38CBC5F4EAA265F5EAF04BC51F0059FD1419ED8 | ||
19 | :15017A00063493D465A2384E66A0171C30231F40AB5CB5646FC8 | ||
20 | :15018F005CBFB633DECCC614D2DAF622F15D3189EFEA3EE28B83 | ||
21 | :1501A4007D99F8DABE4D7C2418A438AF3129015D7507F1032EBA | ||
22 | :1501B900E174827F46C82229AE2BC63A9D50E9253960EC005FCA | ||
23 | :1501CE00F2EDFE0AF12A9D5EBD6A35F1B5AC441A49BAD94F22C6 | ||
24 | :1501E300DECB544F180D1A51FACD8C4A7C034B93DAFD6455A8F9 | ||
25 | :1501F8009AAC5AB74C9542EF11E23DB0946A0F1B0DA10BF0CC0C | ||
26 | :15020D00F9A4A8097BCA1D751474A02FEC02593C75C9E870D176 | ||
27 | :15022200B8CF352EC3783C379E1C2893C98017C6A57B3CDD0E4D | ||
28 | :15023700CE32426A9CB99F03FC2E81BF46AD0D06544FD0190B08 | ||
29 | :15024C00C0580B8E897EFDF490DE08FD652E9CFAE911DD5F24FE | ||
30 | :15026100CF832469DAB1116BE0F3C437B686F8D275C437AC9220 | ||
31 | :150276000542BFF6CC0320B22AB7237E1F5B97A4E927A397490C | ||
32 | :15028B0064C43AFF0CD8ACCE8886D37F632A7F4C16005E289CAF | ||
33 | :1502A0003E491DDAFB083513C6B0A6B8E4929626F531E0877479 | ||
34 | :1502B50082E58C9E2503DDD45DC4777E3BF1051F253E09684E42 | ||
35 | :1502CA00C3BAC26825AC39F5225F6598EE23B366227C52ABFC3A | ||
36 | :1502DF00BC2754E61BD1FFEBAE6DCDFE8D49AAEA38EE89A35A1B | ||
37 | :1502F4009DF0DCF4254234681BBB09E98536033F2F3C5F835F24 | ||
38 | :15030900107E147E1AE8AA0406A36989DB63C95ADE9F9272EBA7 | ||
39 | :15031E00C17C6131AC4519193457028723BE118D0433D6F063E5 | ||
40 | :150333005C6E1C77EC2981FD118663B2FA3A455F8D11A2D66BC0 | ||
41 | :15034800AFE9B096E6D4A38454D70D004ECA8235541117C7A5F2 | ||
42 | :15035D002D26F8E4B07D3848BA956402FC7BF8EC956CB6B6D35F | ||
43 | :1503720091EB21B280C218CAB04122B5957583D126189B7D88FF | ||
44 | :15038700FB2BDA46560F52056C867C6CE85FF1135F19E0C948D1 | ||
45 | :15039C0023873342916798F3A6E45FA58C9021887DB9A8DF9307 | ||
46 | :1503B1002EECF7421F693AB054DE6F73F4FDF414E83A6B66B2C0 | ||
47 | :1503C6000B11C3BA0E45D0D1074E3318C92C24FE074FF267E847 | ||
48 | :1503DB00E03AE67193D635C40D9FD66A65B471CABA5AC66D9C17 | ||
49 | :1503F00081B68DE4F5200AEA316B3E3EF5F8D4CAF0C902BFBC6E | ||
50 | :1504050003FD12ED00BE39F8E7C4E765F2A6F8BCC8083DA6B648 | ||
51 | :15041A00335DAAA0AFC4DEA66A6CDC8418EA26910FAD6A0821BE | ||
52 | :15042F0012B4A9C269D1DDAC9DB05A98BD06B91D807702D6021B | ||
53 | :15044400F02CA479BF88CD3D82BE3F92D49137C262E0EB5969BB | ||
54 | :15045900D6AC8DA4F4A3A0EB808FEB8570E6F34897F9F77CE4C2 | ||
55 | :15046E0071E4E07C73F2C0FC256AC3208B2D5C834D43BA3F060F | ||
56 | :15048300F39566B386103FC611E321E23D02F1168A79426C3DFD | ||
57 | :15049800E159DA32AAA34C083FBA62DC2474847A94BF031D86A2 | ||
58 | :1504AD00ACE5EAEB969CDC4FF3F3216F03DE5414FD8ED3DA3050 | ||
59 | :1504C2005F5AC953795A804F2146D05612811C0DB6A0BC0E67DE | ||
60 | :1504D7007C6E471FC3A5CFA04B06639EFA201E11FA182E7D3E53 | ||
61 | :1504EC009556913E89227D129F511FDBA5CF05970CF63CF54199 | ||
62 | :15050100BCE097B83EB64B9F4FA555A4CF60913E839F511F752A | ||
63 | :1505160026AF4FCB4C5E0684CF471FC48B75737DF079C37C69B3 | ||
64 | :15052B0015E973BC489FE32E7DC231AFD997FEF15925301975DC | ||
65 | :150540007CBC5E33F5D918F2E53E82FD69D1B745FF82E8237F22 | ||
66 | :15055500EC4FB07ED2A4626FD8C3F7363321FA29D11F14FD6938 | ||
67 | :15056A00D13F2EFA9D40678FFA1ACBD131181B507F88FBA8451E | ||
68 | :15057F00E179507D8362EC4FC2734A7D8786D5D526CF431356CC | ||
69 | :1505940010E6D51152BB2CE6690F243DED35694FBB17D6017487 | ||
70 | :1505A900B251C766F514A3D3037337AB67189D043C77A9E728AB | ||
71 | :1505BE00CE3FCFE5A0C8B347ED17F9CDB09A812EE4A09AFBC861 | ||
72 | :1505D30005F3ECCE1F76B0B8059C6AD51342D87777BEC16093F7 | ||
73 | :1505E8002ED82B3BDF613094C9813DB7F3A50E87FE6A95AF1F58 | ||
74 | :1505FD00D259C69E53B447F047991EAA1FDDE8D0747091968332 | ||
75 | :15061200EBC88AB2D5095CA4FB07AA87ED030961D37494DB348F | ||
76 | :15062700C27225D77D497EBF32958271CE6F8DA0D12CF612E37F | ||
77 | :15063C00718ED32568206F3FDF874C7B477EAC4DD8310AE35B40 | ||
78 | :15065100C17E683B139EA3EA6178A6D65B4CA65926E72EF555F4 | ||
79 | :150666007A82D977D06A9A610E58F3D80D4F6BFDF4DDFAC37506 | ||
80 | :15067B00E7D67D672AA93DD881720C301B55C6E4D0860EB97506 | ||
81 | :150690007D5DFF3A0A636BD898CDE4AD4C7A42CBDE915B037587 | ||
82 | :1506A50087D7593056DDC1E5477B55429CDCF8B5DCFAAB15AFBD | ||
83 | :1506BA00AE3B0263FFD3EE69AF8C5584FEF3FD0FDA90E6BFADE7 | ||
84 | :1506CF0030DB70FEBF9C186B43DC4BEFBFDE4682BD8C27C86F5A | ||
85 | :1506E400B3BC185CC264063DED086BF730DA2418B655D6F63110 | ||
86 | :1506F900394850B53126EEFCD1AC2EBD1B83F83B6D56056C5662 | ||
87 | :15070E0027F079B3565739DFC3A2AC8D591AB48B37FD4097B6BD | ||
88 | :150723007D4527CA41F38E00D6C48665887A30CEDA5E6BA09CE8 | ||
89 | :15073800EF7568CF8A7EC03FF80DC05F6B56078280AFB25C86D9 | ||
90 | :15074D00F863ACEDB32658DBC26CBEE04780FFEEB7017F9BB98C | ||
91 | :15076200301001FCB0C5E54E5A0DD0BEC8D6618FD53893DFDBC0 | ||
92 | :15077700489D0A781A5B9B27616DFAD4435409C08E179C365B01 | ||
93 | :15078C00B86D2C5EB34E5BCDD0CEC0B98106CBBA25A29A87AEC7 | ||
94 | :1507A100676BD0977601BC4A7DCDC2BA15ED575E1DD7B78610CF | ||
95 | :1507B6008FC715EE954F0A5CB4B78837139F9F079E8AEFA21E32 | ||
96 | :1507CB00DF9814679714AB9163E99F59FEBDE3263A704FFA4DF8 | ||
97 | :1507E0000BFAD400D9FCE1115DF1C541C7772D591DB7BA1C7929 | ||
98 | :1507F500D4BBCC1B9F701EC761BE22E4A1429EB736E6E5C1BDA9 | ||
99 | :15080A00EE92C09D74C933790B79222E79BA401EE8535A429E39 | ||
100 | :15081F00F3ABF2F23C2B785CC43812F24C0A799A5CF2E05E759D | ||
101 | :15083400BFC0457F73E4C1E79BC91376C9B319E4813E4D9690D5 | ||
102 | :15084900A7D925CFE55F711E6D33B8A771799007CA73BC252F86 | ||
103 | :15085E000FEE3567392EE35506B935DE3E625D87B3AC9363DDC5 | ||
104 | :15087300675D387B325FEEC53DCA370CF1D064D2707F1F9E1BAD | ||
105 | :15088800BCCC7732962CFCB60AF76B17AFD80C1694A4D6EBDAB7 | ||
106 | :15089D0047E58DFC1CEB75E1E10563311E21B6794C95704FA00C | ||
107 | :1508B20031EEBF8BC93DD0270326EC0F8A54674771FCCEF0B040 | ||
108 | :1508C7007E67F81CD864D8EA401CC819480FE1811DBC76E5FDFE | ||
109 | :1508DC00733A83FDD508D6AA24406D9DCF3FA75FCC66FD65D592 | ||
110 | :1508F100FDFAEE7BF332F5F0FDC225936D769033AD01550A3A24 | ||
111 | :15090600BCF12CBF86F184F305E007567C68E59EDB3FCCF1498D | ||
112 | :15091B00D79F692B73E8803CC25E4CAEDA152370463A4A2DE42F | ||
113 | :15093000AB34998BC0DE1BD01C0AA7C5715314ED0FC74F4B510E | ||
114 | :150945005ED2BDC9319893001F18B3A2AE734B17D4E2CFA89EB1 | ||
115 | :15095A00D6B7245E6394E2F350520E95A6DD6079943780F65B70 | ||
116 | :15096F00507B1C857AE36D0B6B12491D8133EA88E6D41A72B92A | ||
117 | :15098400A835607E52D421448C255D7548EE0F723FD656E84744 | ||
118 | :15099900CA3D28974DE33C4751AF90CFEB9603D61BE545BA8197 | ||
119 | :1509AE00906D2A44D446CA190BE550DE5F85B273DF637264CCC1 | ||
120 | :1509C300C15E487501388B928C8974B4ED9C4E8FD80F395D9B32 | ||
121 | :1509D800D9A7F6FDFD5482B3B6141B358F92514D3A30CEEA2EE8 | ||
122 | :1509ED003EC7B6108744E478BE6ECB98555F46FA54D0E77A23D8 | ||
123 | :150A0200FDE876AE1FE7932AE0C3EC226CC2EC98E676BC7347DE | ||
124 | :150A1700DC0A446C361675F3A48267306C72595A4C85D9A5D310 | ||
125 | :150A2C006467AB60D0E4761AA00C1E19A6CFDE057584F27DAC4C | ||
126 | :150A4100810A64F09F5845DD6B073896ACC05936324E1D3FC1D0 | ||
127 | :150A56001C843796C7485C2391FD168998CC2EAC0E807119F419 | ||
128 | :150A6B00A52D86899716E555719D1E5CABF77860FDA686D87D2E | ||
129 | :150A8000881FD74839ABCBEADB34C06AE6FC196F49F9DC3367A7 | ||
130 | :150A9500FF9653FCBCE83E774E9DC198FD9433E7203F734E0EF2 | ||
131 | :150AAA00E7CE9BECEC19F9BEE5F8961C30A2634DFCFEA0D0B70D | ||
132 | :150ABF00B82FA14CBDC23E6C6D4249E6574419B2081DA247F1E2 | ||
133 | :150AD400AE02FC0A7D81D9CC00FA74C84ADCC82E72F9336B3524 | ||
134 | :150AE90075186487D8A757CCC5B06FE37D56B5BAAAF912D674D6 | ||
135 | :150AFE0012F13EA3AE0D5D83985C9FF6B7B3DAEE31CEB713DA06 | ||
136 | :150B130045E420F33B90DB12700BE117C47D4058E0468A700568 | ||
137 | :150B2800DC42F87111EF0EFD1E316777D11C01B710DE2BE8F75C | ||
138 | :150B3D000A5CA30857C02D84B709FA2B05FD06818B78F8BCDCC9 | ||
139 | :150B5200956F1A5D63F88C67293C4379C18FCAAB46C037862CF0 | ||
140 | :150B6700B497ACBCA2E37A07D5613B00F6AA091FED901553AFF3 | ||
141 | :150B7C00EDBFA257A9A7AC65C6076D814DFFADCBB131EB44D2FC | ||
142 | :150B9100D3ED8D9966269B5D0C355EAB1CBB62393E5B09B92DA1 | ||
143 | :150BA6007D3DEB73C7C0B7A0CE95599D4AE7C4A388AF5C5E4121 | ||
144 | :150BBB001ACAA1213D513EACA16C353B1A2C279ED9DA634E30EB | ||
145 | :150BD0002027A4DFC63C22E273C22A8E67F405C61362C61D27AE | ||
146 | :150BE5002FDE11D7C365DC0F1591D33E2D4E5E82FD3B17230768 | ||
147 | :150BFA008634CC078AD84F31565642CAC2B3E0D3AC9E17310500 | ||
148 | :150C0F00F1F318F89BA8DF73B0FBC5B9E2E6B1D4226269A8F448 | ||
149 | :150C2400FD8D2B9E7ABEF0DBCFD57473E2296C3D2DEC7EBCF2E1 | ||
150 | :150C3900AE00DF13950DDEA802CFB7FA713CC25A35E0ECA52AC3 | ||
151 | :150C4E00D412F544A96ED2E3655F78CA23E0B4C678CA19C73BC6 | ||
152 | :150C63007A25DCF084ECD008279EA8719E37E5E1B9FD8ADDB182 | ||
153 | :150C78000DC0764CD423AADC4D73B519BFDF7C84EDF7B3589BA5 | ||
154 | :150C8D002978178F2324729206D4F666ACDF181C6C7FFDBEF62F | ||
155 | :150CA2003F04FFB4091D3E8BEDE2C8A08EF7A1481361354A427E | ||
156 | :150CB700BF0075C79CFD52F0EFBA09FFF58CFF80C9F2281DB6EB | ||
157 | :150CCC00918E943ECEE946809780E173BA047D6A637DC3E9E326 | ||
158 | :150CE100FD30D41426ABD5A0BF066353F5B7AD57AB426111E732 | ||
159 | :150CF6002175793BD0A435CA01DD9101E36E51513FF72CF85916 | ||
160 | :150D0B00533FD0D6AB0F846AD4079A03EAAAD056276FA94F71C2 | ||
161 | :150D2000DA82A6E43B3E87AEF48FB786AD4E2F6F75EEA36584E2 | ||
162 | :150D3500837D8F64208743DE10F7CD8B56A7E5565C0F7627CD82 | ||
163 | :150D4A0071E811C84132E2404C200ECA9A85BA8E1AFB35425244 | ||
164 | :150D5F00980BCDECDF9F97C1AF71CF55D02E2C2EA660BF823D2D | ||
165 | :150D74006135190E61FC6476BEDEE1BEA7FD9C787F107F84E908 | ||
166 | :150D89005860EF2C9930495D2A9AA76D08DAB6C1624F81FD644F | ||
167 | :150D9E0072445B638C94A45D2168373E42BCEE7D285F5F65CC2D | ||
168 | :150DB300E4D7B03E3172F5C9FCF381CDF301E856321F28AE3A51 | ||
169 | :150DC80028771E688C4A5BD641CD07B107B58A72379C210E6DFD | ||
170 | :150DDD00D477415EF648712D0AAD1C4846132A3F977C1772DDE5 | ||
171 | :150DF200B1E4C7CDE4EA10BDF6B5FC7B8D3D5FFFDDFEA623C476 | ||
172 | :150E070037F149D60767196DF37D72BB73D787F76764B77176CD | ||
173 | :150E1C0012DFEDED4E9E9D62ED24C612B4E9B319F6CE0FCEC553 | ||
174 | :150E310060A795E28EC5592B49ACD55EA03DFBA77C1F408D2F19 | ||
175 | :150E4600C19925111ED61AB1FD22D431CC768DCC76686BC46913 | ||
176 | :150E5B00025948755C5BFE89B05F4C62F603E3079A805E15C03F | ||
177 | :150E70007F7E9F7C2F5BCFEDA2BE82166B17AC59900EF6BB59E8 | ||
178 | :150E85003D95F781473ED50706C49DFE70491F5072FB7DC6422E | ||
179 | :150E9A009DC136B6B08D2D6C630BDBD8689B72C8E56E9F99AF8B | ||
180 | :150EAF003DF1DD13D451C14A757F10CEF8BE3C6C2DC00E06535C | ||
181 | :150EC40005B03F02D8D1E09803AB42582DC056042711C6EE3D4A | ||
182 | :150ED900B87DDFFB18EC09763DFFF15CBBBEF730F18D7D8C764C | ||
183 | :150EEE006DB877BE7ACD579F7809FF2813FE1105BE17B615CA1F | ||
184 | :150F0300D922135F23C8E20159979490B511E67899AC4DF7DEFF | ||
185 | :150F1800CE1ACC57DEDE12F2960B795F0759976C9BEBCF06FAC8 | ||
186 | :150F2D004B095F8E5DCBFACA408FC8B5B97AC4804EF81AEAE194 | ||
187 | :150F4200BFF7767DE976F4E929A18F2CF4F9F956E2EB84DF675D | ||
188 | :150F5700E1BFF97F4127B5812A6A1365EFE620074AB029B701EC | ||
189 | :150F6C001CFB32E934357C0E6AA60AD659AEEA96A26EFA5B76F9 | ||
190 | :150F8100970E79676B6C88BD2B8E7D53DCF73CC76A5433FD0D60 | ||
191 | :150F9600A89D643847E33B55DC9401EF62EC9455F5C419EBC295 | ||
192 | :150FAB00479C3601BAD9858639057D89F7BD631F15CA33267057 | ||
193 | :150FC000DF83B68B244DBFCAF9118DF3433EC8CFDE5DC86F3932 | ||
194 | :150FD500E0553D71CADA0AFC3441837EC4F9C5043FE87BDDF609 | ||
195 | :150FEA0054843DCD3FE1EFB8AF3E440AC61789F15D62FCBDA29D | ||
196 | :150FFF00F11A31BE558C8F158D2F16E34D623CC1C63366D79E29 | ||
197 | :15101400FC793F0B3A5202FB37ECD5DEE52452707687BF81A5FC | ||
198 | :15102900B646E14C41EA923BF0AC5963EC5F87EFF53591D70ED8 | ||
199 | :15103E002C9DD53AC22F873A5DF7E92F4C3CF113B4D573BB2F35 | ||
200 | :1510530075045DF0CBAFFEF57584B7EEF84987FBFE7DFA8D6F83 | ||
201 | :151068009D40F893FFF0E30EC2BE871834E3FFFC179BFC0163E8 | ||
202 | :15107D0047B297F8269F24BE3972BAEE17827F59B87FCB380E23 | ||
203 | :15109200F9167388548D39197231C24AECC74EAE81B351FBEE40 | ||
204 | :1510A7002DE2DE07700F6C19D52A638F065F811671F66EE7672C | ||
205 | :1510BC003C1C73CE320C5644AF8EDFF7F1EF332E0FE8F683F8F2 | ||
206 | :1510D1001D01FB1640C47E8ADD2918BE51B6571056CB2419BE69 | ||
207 | :1510E6005F39CDEE52768B7B1784A9EA283B4BED71C18202D67F | ||
208 | :1510FB00E7823509D8DE99FCB707866B1CED4B26086954472D8C | ||
209 | :15111000370CBF436C2882554932692E84518A67BFD838550E10 | ||
210 | :151125008DEA2D3826F4C6EF6508BD9BD99D8AF91FDC58F453B2 | ||
211 | :15113A002F9B9FF345D18A7E649C4A07F09C0338ECFD3DE713EE | ||
212 | :15114F005647E93EA827B19EC2F3EE65F0B7441FE9C6F74ED3D0 | ||
213 | :15116400397FE1B66DACE2760DA74FE6E40CA74FD3FE2DE3DA2C | ||
214 | :151179006675DC72D37C79E98086FB33D28C15ECEFA3ECEE6226 | ||
215 | :15118E00AB80ED1132EE113206605F6732E27B2576864DE1DED8 | ||
216 | :1511A300CF6A05B6F78BB51C106B298B6F2998CDA06605DE16C5 | ||
217 | :1511B8007EFF9280338317CFA17866127A7845AB14B5176F64D1 | ||
218 | :1511CD000BEA546EDF93EC5E0EF76903F4C3332E3E3B30F2F086 | ||
219 | :1511E2005C58991BC6EAE794D509272B493C6F56381C6C66A124 | ||
220 | :1511F700DD6A33CCCE0143C8C160013B1AD89812E727389FC223 | ||
221 | :15120C009C5A03D60DD688B591717321D2A3A356297C52029F42 | ||
222 | :15122100E4F0DFE4F605183C5B7B9DCFF944FCBD20F4E4B19C55 | ||
223 | :1512360062758BE4E804CF57A514F3F7A03F3FFEF296FCB8034D | ||
224 | :15124B007BA9044C7E782ECCE386B9623AE7DF22A69C7875C78E | ||
225 | :15126000727F512C633B25C66E36C72831C7196BC4F68BF9B97C | ||
226 | :151275009590BB8DBBC902278FA04D5E747C0E9EEBA7E37AAC39 | ||
227 | :15128A00687CC1E594CE69A4CC1648B68998A71B7CAC06F7016D | ||
228 | :15129F0073733E27A17F605C38637DEE31F6ED1BA7C35A178D76 | ||
229 | :1512B400CE221A8E0DB80F7298510C037A2F38307F1E66948027 | ||
230 | :1512C900555617C250A7FD2E9D1D58BC04ACBCDA0D334CBB4EC1 | ||
231 | :1512DE0026E1D5C23EB08F60CEC0B8F483CF634D85DFE4B17ECD | ||
232 | :1512F3002015AD75BD4B225584BD3342FFF533FF1D311D3FAFDB | ||
233 | :151308003C84DF1BD87400BFB50BF35C568A8672DB34600CF7B2 | ||
234 | :15131D00176514F12C2D1717498AF91CF3E12ECC25D0C77907C1 | ||
235 | :1513320097A634461F7DC54F6829B8E2829B6EFC25A5E10AC018 | ||
236 | :151347007B9DEFDEEA788E75DB6BAB74137BF94BEBBAE0B20DCC | ||
237 | :15135C0067E4D1BE83504BB03C301FBBFD1669A19EB75A03F3CC | ||
238 | :1513710076E4FACCB40AD7D51679DED9AB793E2EB475613E2E11 | ||
239 | :15138600210BCCE1B2A44CD602ED85480F6ABE927628814F729C | ||
240 | :15139B00F885F2ED75F91DC6AF543D37BE49F5DCF82EAB9E1BB7 | ||
241 | :1513B000CBA404EC15DFDCF8F654CF8D65B90886F847DC73F32E | ||
242 | :1513C500EF3C2B79FD8531CEF706B469BD6BEF83D6D825BEDF9F | ||
243 | :1513DA0020AEBD50291A935D63FEA231AF6B6C49D158956B6C58 | ||
244 | :1513EF00B922F611E52D4A1493CAEA307BCFC4BF63A4F41A6BD3 | ||
245 | :1514040007E9F532BEE765581B34A1A82072F5889E30C635FCEE | ||
246 | :151419005676B13CA21F2B1FD78E854735AC55BE639CD3BC1730 | ||
247 | :15142E003FD0192E201F360E68CA5653AF81BC5CE97AFF8BDFE1 | ||
248 | :151443008FCAE638833F17AB0ACDB8D613DFFBFFD37DFC7B9AE7 | ||
249 | :1514580058EEDB1B80CFF0335F65F2D7CDCB92DFC4EF4EC4B7BF | ||
250 | :15146D003313ECBB277E5F3EC1BF8D080E50FEBD0C1538830C25 | ||
251 | :15148200A7D7F57E03DF9F3F2BF84CCEE17347011FFE7DCD0460 | ||
252 | :15149700FB7ECAE1630B3E5D820FC719345551A725A13D119479 | ||
253 | :1514AC00BA2B0E8DE8FEF02AFD353C9FC4EE6E0BC42A425745A7 | ||
254 | :1514C1007C5D8ADD139A85672FD8BF5E8BEBD433DA5719F3B4AB | ||
255 | :1514D600E33A292ABE8B033BBE097935297577A9A72C388AD66C | ||
256 | :1514EB00C8CA5A88EB03B42E7CB0ED30665CA5DFC46F5D37FF53 | ||
257 | :151500003B9CEB22BFB41AD45F5ACEFBE836F58015560F5BFEA9 | ||
258 | :15151500F408FDBFF6BE3E3A8AEBCAF355AB5A6A498DA816ADA6 | ||
259 | :15152A0046C2209588708447715A422648964C43182F78306934 | ||
260 | :15153F00639CAD12C26EDB644C1C26A3DD61E7704E58BB255AC4 | ||
261 | :1515540020E10729D548462638B4B064E30938322B123C47248E | ||
262 | :1515690062E275F02C61B48CC390C4269D19C626332456BC4A65 | ||
263 | :15157E0086CD38F4DEDFABAAEE9210FE9839B367FF58D5D1A9A8 | ||
264 | :15159300EA57EFE3BE7BEFBBEFDEF7EEBB657887B6D5087BF17D | ||
265 | :1515A800081FA63A83A941B22B5F3491CE945E0EDF6E779BEBA1 | ||
266 | :1515BD00BF3ED0EC2E5FA1FD996EDA75A02C9E5157FCDBF00DF9 | ||
267 | :1515D200AF6E8D4C2B5F4CE523EA336693FA8A5DBE77C6F2D17B | ||
268 | :1515E700E31818D5AD80254CEF6AD47623AC7673ACFB9A2CD1D0 | ||
269 | :1515FC00A6A93F37BD12FC228E7293F5B5C9B184594CF2CC8307 | ||
270 | :151611007DE9E8A0E98BF59AFED8A869EDDBB8F9F8A4CDC7F152 | ||
271 | :15162600297C9CE1DFB1214D71F16F51CCDB98E151EC1B61AFE5 | ||
272 | :15163B008478348FE466095BA45B7DABB6FA16196876F3735093 | ||
273 | :15165000ED364231F94E6BBFC1E0F0E51DF97BAC8FC45BA1DF9D | ||
274 | :15166500AF6E60F987CA929AA22E16B459053AC0F5491D31629D | ||
275 | :15167A00EA5123A26EE04A68756B1FE9A75864EF1B7F41737C57 | ||
276 | :15168F00777BEDF1DB6FF95B14BBFD285AA9BF3945A7743575DF | ||
277 | :1516A4008C67CB1C31B9ED0FE7E415FB9AE349AD9878DC5D3E9C | ||
278 | :1516B900AAF61A1BA87D8DE0D0D483F47FD56853AB8CED6A8D70 | ||
279 | :1516CE001157EB8D2EB5C930D45544BB477493FD595B754AEC79 | ||
280 | :1516E3009FB6F553FEA43A6A1C51B9D1F7EC515EC28EE97336A4 | ||
281 | :1516F8003DCB17BC759527367D92772E58CC776DAAE5BB9F6D89 | ||
282 | :15170D00E05D6FADE04F2F38CEB166F2B91FC0892426ECBAFDF3 | ||
283 | :15172200CF9EE2FED387F59EB7F6F262B677A91B2E3205F38BA3 | ||
284 | :15173700D455CD99B46807AF92587EB13B4D74A083F39BA4BF13 | ||
285 | :15174C0071217D43BA16EB3032FB606FDDF89E191DFCFD821912 | ||
286 | :15176100EA235E1B79279D5F953C6C88B1053FE0CB37DAD7F014 | ||
287 | :151776008388129F788B3A85AE7290F2BC1FCCFA9DF8A6FB9DCA | ||
288 | :15178B0010AF1E14B65E3B7C7A4CE13F4D63DF4B32A32F49FA86 | ||
289 | :1517A0006CD3104F596B5EA6DF3A5F31A744D87D9326DEAB6A39 | ||
290 | :1517B500027BA94167BC63FD5E8B55124FE0EC483B8FBBDA56CD | ||
291 | :1517CA0066F0C3F1C5A85D3127C44DEC57F6A9528B323AC0AF33 | ||
292 | :1517DF00D96D627F734A9BF4DE37ADCDE9FB071B5CED3357FB1F | ||
293 | :1517F400EA0CEDCBAEF6E7CFD07ED5C76C1FFE3589863077601A | ||
294 | :15180900010C3BE65830CCA7B6A6B7AF8CBE28DA526303A46BCC | ||
295 | :15181E000CB732A5D384EF8F4CB67188DA9D1F1B309E5EF06B13 | ||
296 | :15183300E1D331E9F6F371EDCFAC7D2AEB3F22E52774A9ECA464 | ||
297 | :15184800BE7EACB3D1B78E0B5D46B92FA995EC18E1511F8B60C6 | ||
298 | :15185D007C96EC18E4317A866F01F21B296F0B337E6D62EF18A4 | ||
299 | :15187200699E6969D4D712C77F24188AB5865929DFD939B88DCC | ||
300 | :15188700190F70F08FFA790234A4B5FACEEDA1F64EF292D096AF | ||
301 | :15189C00D6B93B8EF208B5118C5B3A33F2083F10E3707FF1B807 | ||
302 | :1518B10021F67738C13277473D27B9DDD6B177ADF0F3098696FE | ||
303 | :1518C600B576DCFB29FD3CE1E9B598E74ECFA5FF20CE4084AD8B | ||
304 | :1518DB00730562BF0D739DBD9F2CF6434331A9B94059AFA36E52 | ||
305 | :1518F00094654A3397A5C37AA7381BF0B258170EC2C732BA3C2A | ||
306 | :15190500B35621C717E9589F484C785A426F35F0D08A7B74362A | ||
307 | :15191A003E6286562CB6FD5AC4BA96B557611C3597624F3D3A72 | ||
308 | :15192F0018BF4DDDB4043693D88735068633FFCA603C4875F9B3 | ||
309 | :15194400F32BF52BE974E08DE57AD3E34F7A9A1C5A5DA0BEB02D | ||
310 | :15195900F0761BEEB69BC2EDB954A1CBA79337C21E5E6686ED09 | ||
311 | :15196E00F593E9F04346032FE883D59719FA30FE0D731DFA6039 | ||
312 | :151983003C175F29FA10113028D1B80EF80D35A70577C08F3B83 | ||
313 | :15199800F15EC92CCC25E37BF8E0EFD285428F540EC7C7976FC2 | ||
314 | :1519AD00AA1FA5BEADA2BE39EF77FCCE75D410FE24048BAFE8E2 | ||
315 | :1519C200A8E085B93B4EF00999C598B16838A00CEA993335F4F6 | ||
316 | :1519D7005B8D25E8FD31FE3EDEC37710FB414A3B6C06E386DFF9 | ||
317 | :1519EC006E7FA97D597EF71525048FB3FA041F233316FB9D6202 | ||
318 | :151A0100BF69D883FD6A137BBB57D3E950D6FF89C6CBBFB17C5F | ||
319 | :151A1600625F767D5894CF961DB6FF8DCCFFB4F5E2B6988F27FD | ||
320 | :151A2B0053DF3715E2733535305C1CDA4EF56CE1C154A5312B41 | ||
321 | :151A400095D3B22AB5D80884DA88DE63A2CE10CDC92CFAFBFC5E | ||
322 | :151A55003519FBF21A87AF8EFCFA2384C752BE16FABD021FF809 | ||
323 | :151A6A00A8F0B5EA8DD7697F1EA96DBE47F5349FF75EE1A1C844 | ||
324 | :151A7F002797826E1BD2E9C249C9B193BA8D3CD02D2AEF32DA11 | ||
325 | :151A9400E013B89683D6C85743F9CEDAF9C2A91554EF6A739572 | ||
326 | :151AA900C573C38286F6BD26760FEF16FB8295246F5682A68619 | ||
327 | :151ABE0045C3A9F70E09EB8657787A391C7107881F3FAD4DE607 | ||
328 | :151AD30058F517F101FD41755663B13AABF6A5CA924673E18293 | ||
329 | :151AE800C657F18EE018BC9E2E5CA84A8D024E85F4B072A3D58F | ||
330 | :151AFD00C7FAF9E51FA7F333E7F1C60F5B7B8DE387CD4365D585 | ||
331 | :151B12001AF58C63BFABD7AE9FCA37A32E8DEA72F23AF9B6524A | ||
332 | :151B27009E7D6B06B45D34C6D0875B49E64D6F6BFB8FAD3D8A0C | ||
333 | :151B3C00522AFFAA64C185737B5D180BE37163BE7F500FFE6E98 | ||
334 | :151B5100BF8101BE3AF5A2619DD34A3333F282D647F5CEF3D710 | ||
335 | :151B6600E8A42B97C0D7BC865DE189C837DB70F62E89B1BB66B3 | ||
336 | :151B7B00B16E12AD72D990EE25FEC7DE506364A89129CF59B491 | ||
337 | :151B9000B1F5378C6159F0994A70455A05FCCA73E69B3F4AE70C | ||
338 | :151BA5001FF558FD5C49B46E9A81A6B751DBD3FB34F8A3B4D82E | ||
339 | :151BBA0013443D5BEDF2F36252A3779C6440740FF7F8137A2424 | ||
340 | :151BCF00B59F375D4AE73B6573699CE02CDDA88D779CE714B2F2 | ||
341 | :151BE40080F0E0E4E9A777E2D9788AC77F98B6CE3F529E37DF4D | ||
342 | :151BF9009F8A7BF0E04CB012FE4B4A53ED46FD050BE783D3CA28 | ||
343 | :151C0E008D02FFE07371566D0F77708D3371AB530326C73E7BDE | ||
344 | :151C2300785ABF5957A6DF472F5AFD06ED515F1BD55763D34CAD | ||
345 | :151C3800F0E6A0C59BF04B97D6FCBE1EA5F7B73AFC67D3C2C2FA | ||
346 | :151C4D0063B60EEDA2056B1BF1C4C8BF583C31CF5FAF8706A432 | ||
347 | :151C6200468737B662BC5BE73B6DDE209D3F32A42D64279AC1E8 | ||
348 | :151C770017C18661C10F667CA1E6EB7E519769AE5C68F381E5DB | ||
349 | :151C8C00F73A95EEA493FA42CA61E2F9765E447C116CAFD595EC | ||
350 | :151CA100376C7C3BE3C15506F6D44CF8BE1DE39DF203E737B4A5 | ||
351 | :151CB60043E3E928D5E9F8D3E4BA78631BF186FAA6C51B12E1DB | ||
352 | :151CCB0057B67963EDDF5AF8157B568493CBBFCDD20FF5CD8A7C | ||
353 | :151CE0006ED1B59F7CA99E649C599D5A6356A5569824E74C9214 | ||
354 | :151CF50083C60CFB4DE21C33F4143FD901C2276E063F6FD2937B | ||
355 | :151D0A00785E51B7DE06BF4CD2DFA09749F9033AF6B5BAEC73CC | ||
356 | :151D1F000BF02D7B50F8330D0B5B4AF877E34C34D94F87CA4E3B | ||
357 | :151D34006ACC1812BEDE4AB2D384BDBB2A794AE877F1E410782A | ||
358 | :151D4900728EA2769AABD453A641F712E388FEAA6ABD67954398 | ||
359 | :151D5E00FCF24DF43FD8438150B4750FE66FA58A17939CAF263F | ||
360 | :151D73003BE676F8E23B7633D96915DA55BD27B2BF0DF8F35FD4 | ||
361 | :151D8800C8DACDADEA7DE6DB3F93EE94957BF52A7505AF225DD7 | ||
362 | :151D9D00FE92EA6D0ED2FD5BF04514E36C0F2F3D9FCE7FAD5214 | ||
363 | :151DB2006E249BDC207BD698C78EDD15211B50B6694D76AC01A8 | ||
364 | :151DC70059D9E44A433E25146EA53ACD2ED5DFECF8589692BDD0 | ||
365 | :151DDC009BC72C3D0DBF8F52DDBB95A7DAA08F55CF618580CB48 | ||
366 | :151DF1006D67BA6DCCE80FAD71D029F257F36BC5AC9029EF99AF | ||
367 | :151E0600412A0399E186C9E2BF7A7E3BCD0B800F7004D5970D68 | ||
368 | :151E1B00F4218F781FEBE76C7C31749E6068C5A774F41D7A90B7 | ||
369 | :151E3000F774834E6085AAA82E21038C1E1E559FE1AFCE26DABE | ||
370 | :151E45002BC46754DE6907766090F41F4A33DD6DDE934E8B36D0 | ||
371 | :151E5A00855EA51C364748472B8FD9B22C6AC939D4D9361BEBFD | ||
372 | :151E6F00F6614A3B2CE0F2B2BD7A0FE08AEE3121A71CBA396BC1 | ||
373 | :151E84001ED13740BBF704ED707E5C55498F573A877DEA1DA687 | ||
374 | :151E99007705E940D1BDA26EE8F5D0E9FDEAB366CD75A929AB9C | ||
375 | :151EAE00CF583470F0EDA6C360C0F2BFBCD97B1E60856E7A0042 | ||
376 | :151EC3009EB1BFA139D2A117E495526526D6701D7AD4E49355C5 | ||
377 | :151ED800774DE7D7A87D9E2F9E7AC72C095D6CCD49922D7DFE54 | ||
378 | :151EED000A8D8D2FF00AED4FF425B16FF37D9D27DAC43E90ED91 | ||
379 | :151F0200971EA6BBB087B08608C28CC1C77DD80C8BB3DCDF30DF | ||
380 | :151F1700E684CE50BB3F249952DAEA8B3D493AED72CC2B66C792 | ||
381 | :151F2C00BD0F918E7BBFD171EFBD7A774A024E857E9B87392E76 | ||
382 | :151F41001CB5F5DB2ECB2F8FC66CCCF6B31F16F76ADB0638627B | ||
383 | :151F56008CDC073B2B4265B6087D3A2D7C44525C444EC819E394 | ||
384 | :151F6B00E1582D9F9DCC69093CBB9E074EB7E852F2040F40BFA2 | ||
385 | :151F8000879E7C1F7CD25F163EB87DEC9B1ACABD4FCA53DF677C | ||
386 | :151F9500BF69EDA7517DFBD97734B6ED1847F4903EF66D0DBA40 | ||
387 | :151FAA0018E4771F7B4D832F2DE089920E87FC80E55689059E76 | ||
388 | :151FBF00227915185BA9DF4DFDF12B8FE8B2FA9C81BE3A7E50F6 | ||
389 | :151FD4002C7A9FD931EB5EE1039C4F3031638DD9C70632FE501A | ||
390 | :151FE90028CFA2CF99AF125FFACE8DE86CA4D384FD04FA0FDB39 | ||
391 | :151FFE007BCC68ABE8524AEFCD7941E8F56BB1AE3C72CC1C63DA | ||
392 | :15201300225F1CFA3CFCE2B0B78867D80758AF213917C7BC7364 | ||
393 | :15202800ADE27073B9EA69F49D233DBCFE18A7726DED852B5BE4 | ||
394 | :15203D00A05F930D5A124DBD635468DFD3674BCF0B9DD8E33F85 | ||
395 | :15205200A1236F09FC1BEA87903F7270672FCD457DC236050FD3 | ||
396 | :15206700887764234E923CF49D3BA8CF3BF79CCE2607054C382D | ||
397 | :15207C00EF437C2564FC1FC6D6365978F986E13BFD72960F9219 | ||
398 | :15209100DE0C1F84C007842787F6BEC82ABDABCD63D111F4336D | ||
399 | :1520A600BA4D879E4FB31735879E2CFA0D73103ABACD2B53F1A0 | ||
400 | :1520BB0067E1EDABAFFF9186337253717644E0ACA44DF848DBB0 | ||
401 | :1520D000381B06CE026CFC581CBEDAD79EBC7789A80FB6CCA84C | ||
402 | :1520E5008533165D346CFD77F65B733B1B9E3B7A42E047AC7FA6 | ||
403 | :1520FA0019C7CC02E8C5935FE16F104B127F9414A53CCDC0ED45 | ||
404 | :15210F00E39E2796FE69CA736728E66976F30978C373E91DDDF8 | ||
405 | :1521240027BDA077AB599C04A78C0DCBF6035D2D7EB6C60AF085 | ||
406 | :1521390094E1F5E9769FBDEF6EAAEBEFF49DBBAAC367D9EAA701 | ||
407 | :15214E00C1710644E83FE1301778D9F669AB7FCA401C6BEB2D2E | ||
408 | :15216300EA034BB0FFE1659D7A70C75745FFD8E6E778EFD81756 | ||
409 | :15217800493E7CD174D93BFDC2D6C19E36E18245474CA78E203C | ||
410 | :15218D00D951852E5C8C117F2797AF6FBA7EDDC2C76FCA9FA8EE | ||
411 | :1521A200DD40FA96859FBFD7EBA4273F003FDF27FC3CFFEF82DF | ||
412 | :1521B7009F97809F7577E98E6D9E6661CE267F6EE1836CE6DE14 | ||
413 | :1521CC0038EC050B1F0BD8223DF8FE62818F9C68A95E1E2F6F3A | ||
414 | :1521E100BE45CC71FB782CF5AEB9ED97B0974B5BE9D9807CB1CE | ||
415 | :1521F600EC1FC21BFBE32C0F2A583310FF84BB0117EE5E369D99 | ||
416 | :15220B00F6A6E3AE9770B78D70F77736EE2E12EED07EC8D5FE2D | ||
417 | :15222000B55F586D4F6DF7056D5FFE505666DC5C56CC71C98A24 | ||
418 | :15223500A64C3EEBEC74667C2CC4BAEEBAE7333244D8E7E3545F | ||
419 | :15224A002E3EA44D2EF70AD8204B204722A4E3418E604D0A67B3 | ||
420 | :15225F002050EEE9944B9EE4BCA461FF0FE736F05EBCB3E449EC | ||
421 | :15227400896FDD4BFA016A5BC8946D4362CC627D0A7D2E76F53C | ||
422 | :1522890059A63EBB65CD74FFA551F8E6285C2FBA64E801D20F34 | ||
423 | :15229E00FA9232F547354EDE27F4CA906B8F8C063EE99034B72D | ||
424 | :1522B3000357276DFE4079DF42962F8FEFD495F33BB5A9FEFC1E | ||
425 | :1522C80086B0357697F56B42B7945917703526D65C86E20BB10B | ||
426 | :1522DD00A743632327752C2EA74EC47D7ED27308BF05F1A1C669 | ||
427 | :1522F200E2A841F301E73D29B94556137CAEF217382B182AC2CA | ||
428 | :1523070019BA0C4C5161776CC799BBF2D5ADD0B1587958D821CF | ||
429 | :15231C00D095271EB07C67AFE15EBE8CE6DDDF3F207CF7C2EA17 | ||
430 | :15233100F1D40333FB731B87B07ED12FD62F76931E5C34D629A3 | ||
431 | :15234600D609D8B89C301A8E58B04787E245F06FB4D33DB1A12D | ||
432 | :15235B00B8D2302CFAD7C3F66A384FE85B47F3883104BD08739A | ||
433 | :152370008C41735BA67FC591C146A7ACB58F9B79BE019E6B8741 | ||
434 | :15238500B2EB31BBCB86B5A2B80D8F711378285D215B1AB0B83F | ||
435 | :15239A00DB94ACFD988ECC5A8DBD3F8FBD68567ED2DAF7B4FD65 | ||
436 | :1523AF00110977167EACB5F4A978543A0F4CF12FA27110BF1F74 | ||
437 | :1523C4007D305A31164897E928B77CA2E21D94DE1B4D6ABE22CE | ||
438 | :1523D9004B2F4B114C5772E258F32AC4FBE87ACB96C1DAC1428D | ||
439 | :1523EE00DB8F6AB5E09123F1FBE89D03BB809BF26BEBC51EA3A5 | ||
440 | :15240300D8075C6BE7D35DF956A45EE8A0FF38D28DF558CFF983 | ||
441 | :15241800761CF31EFA82FD4FC0D1BB73480B8ED9F050BAD3EE10 | ||
442 | :15242D0016BBBE9E19DAED77B5BBD5CEF78C2BDF4A6A17F99220 | ||
443 | :15244200AE7C6D76BE8119E05B99FA661C67108E0818BF1BC70A | ||
444 | :152457001ED815824521F89E16BC734CF8CDF47E8F6065D6BA3B | ||
445 | :15246C00E01517ACDBECBA5F9C01D661170CDBED7C2FCF00EB9F | ||
446 | :152481004957BE1D76BE573E0056D0D881F5EA87C07AD5056B9E | ||
447 | :15249600CAAEBBFDFE1B61EDBA3F0BC3653B5FF7FD37A1E7FD24 | ||
448 | :1524AB00597A5EBE093D2FBBDABDE2D0738676FB5DED5E75E845 | ||
449 | :1524C000799376B76CC0F81A050E8C0977BBE8AFBD7E8F74875A | ||
450 | :1524D500E71FA7FCFBD95086E737782D9E7F5FB2783EB621DB46 | ||
451 | :1524EA0076D46BB5FDF0860F681BFBA576BB4E7B93AE7E6EB0F7 | ||
452 | :1524FF00EBF8E2CC751818B38E6FCEB5E9328FE4CBE5C1ACBCF8 | ||
453 | :1525140013E359ACCD22E69421FC099832624057F1F93BF5DD6E | ||
454 | :152529006586A6D0FCA0AC3DA597F213FA3E9A12DC32E809EAA9 | ||
455 | :15253E00D74CB2C729179286B4FDA437825F2CFFC7BD644B24A5 | ||
456 | :152553003BE0EFBD52D4959D1BEAA82E0FCD0B19B94A7A896F04 | ||
457 | :15256800DD9090A9429E3AF3451CF27448C853650DC14F725439 | ||
458 | :15257D00723D4F9D8FB0DFDBAF4965869EC61A18F6DAADB37498 | ||
459 | :15259200F6DC346CB56FD8F234DA678A35D5F121C3EACBA0069B | ||
460 | :1525A7007F17EC0B189897C85E99ABBCA2FB48E7C6DC34E37C24 | ||
461 | :1525BC0032945D0FC73A1CF6944270D7856FBEFD9BE6F339D379 | ||
462 | :1525D100D7C2AD75DCA3864CF348A0419C756301E917FA933497 | ||
463 | :1525E600B72D10BAC911331264D1D7688EF6150D0A9F0E2B1601 | ||
464 | :1525FB0058B5D807DA5DA66AAC7E2F6F13FB0B3D64EF579AE254 | ||
465 | :152610004CDCFFEDFFC3BD1C30B36DEFF238D159C0EE7ABF99F3 | ||
466 | :15262500F4B6E5F4FECBEC1F9722C609FAB0ABEC88735E5915B9 | ||
467 | :15263A007D237D48F44321BBE2E3FE0FF4F29215EFEAD9B4A1AD | ||
468 | :15264F00E175B1F412A7AD0ACDB2D53F4A5BF1E48D7535C6BE43 | ||
469 | :152664002BEA8A7E40F918952B5D33B5DCEDB18796587433CC8C | ||
470 | :15267900D5A09B5D2E4C79FDD3F2D6C52AECBC2A17FB43365DAB | ||
471 | :15268E006591AFC75C3061C77B237CE26C5D5D2CAF51ECBDC060 | ||
472 | :1526A3007F53E44F7092F13109F989A7113746B6E2C319880F2E | ||
473 | :1526B80027CE3F132F89B399E383A67B3FA9F5886B3F087BA603 | ||
474 | :1526CD00DB388F603F272A6C1B71BE5251E0FF613FAB3807990B | ||
475 | :1526E200DD0FEA75955F18931B9D3D21D421AFE17A8F589B1E44 | ||
476 | :1526F7001C9E74EDA33AECEF63A3F96FC977E57CD9F39EF47519 | ||
477 | :15270C00E951E9335250BAC6FE8EFD35FB2E7B990DB1AF319314 | ||
478 | :1527210075B30EB683FD2929DA5F628FB147D9436C23D3D8036A | ||
479 | :152736006C3DFB1CBB97FD015BCDEE66ABD84AB6822D67CDACF0 | ||
480 | :15274B008935B206B68C2D6577B07AB684D5B15A16669F66B73C | ||
481 | :15276000B34FB11ABA7E8FDDC616D355CD3E49D7AD6C115D55E8 | ||
482 | :15277500747D82AE857455D2A5D25521AE72BA16886BBEB86E5A | ||
483 | :15278A0011D73CFB2A1357A97DCDCD5C21FB2AC95C41D735C7EC | ||
484 | :15279F0075154FB902D32EE5866BF60D57D18CD7AC9B5EFE0F7A | ||
485 | :1527B400BC0A3FF42AF8C857FE875E3E26CE181FB7D6B754E111 | ||
486 | :1527C9008B4EBA3DE9F151A61E475A15A519F673353D8FDBCFB4 | ||
487 | :1527DE0035F4AC48F48C35BEF26ACA1FE1065BCDC7C95E5024A0 | ||
488 | :1527F3008D2BEAC2E34A8CFE93F49F5A785C8C2BB11E522DF667 | ||
489 | :15280800DB55D54ECBB7D3244A8BD96905769A87D292765AA167 | ||
490 | :15281D009D964369A88FDA14B02B2C1AB6EB825F60D8AE037E98 | ||
491 | :152832008061BB2CFCFEC254262AC16651F9F04B5828BD8D33C0 | ||
492 | :1528470075E1016F6899A8272AE2EED41AC549A9CE776631CD9E | ||
493 | :15285C006B95077C671A843C887FC0BBE10F78073F38BC2BA2B2 | ||
494 | :1528710077946E225D7EBD41176D8F2F361DDC3938473FC66D43 | ||
495 | :15288600189561411343153E7661037E200CFD1465C2ADC02FED | ||
496 | :15289B0070A878ACFCA96FDBEF99CA9BD485A661D7C35EB1D235 | ||
497 | :1528B000A3942F8A754A65A129FBC8A6BFC93D2A65F38CBB9EA0 | ||
498 | :1528C500154FF6D9B0D345FD63E9D988ED64F947AA7C42ACE7CD | ||
499 | :1528DA00A8563C48B12EAA8A5891B9F6B3F043F310AF617D2323 | ||
500 | :1528EF00BC8C477FE16109CF32332FA4B6CA91067DA2B241C487 | ||
501 | :15290400A998F8AEF70EE004BFE12B3046E5FC6C19CEE49A35C6 | ||
502 | :15291900840B529EB84FAD33F3D86D04FB6DA63714691D9F2168 | ||
503 | :15292E004D91AC34A6BE67C2BEAACE99AE9FA98648037FD3FD64 | ||
504 | :152943004155AA9389664ABCBD4E86FF8C5209F9ED634A2D354B | ||
505 | :15295800B9CCA81171196A4DA6002E55C012F594521B8B0DB4AE | ||
506 | :15296D002F9F29D595F8E27ADC7DF1C575B847D1D7F1B090F94B | ||
507 | :15298200C82BF818F29DF489B81813CB7844F8D946901E4BCFE8 | ||
508 | :152997005E4D79A2464CAC776BF659FC188F88B5932DD699FCEB | ||
509 | :1529AC00709B75469E6DB7E3F076D9677810F764360195205DD9 | ||
510 | :1529C1002461182CA141FFC1EFF796CB77B0F10EC3AFCA752C4C | ||
511 | :1529D600BAD39844BFC655C35A07B2CE2DD7A472EA449D549F2D | ||
512 | :1529EB00386783E768AFD15516D72431FFF59A9973E3D1FFDE24 | ||
513 | :152A00008FFECD579F3664F575D21913464495EF78E9A197A820 | ||
514 | :152A1500FED7FA918EB41A4A3B302DAD94D2764D4BDBB69CE0E0 | ||
515 | :152A2A0052DEEEFFF243EFD49262C6FDEA25633B3BC3E7AF7812 | ||
516 | :152A3F00476FA9F869EDD7965DB17DA5E362BD6D41FC027C739B | ||
517 | :152A5400845EB160C5395D4E0E1A9EF223ADAAFAAD7E664C9A2E | ||
518 | :152A6900BEAE5EA193637EF68DF52D0D618EA47698F10DF3161F | ||
519 | :152A7E00E91D1D7828603FAD1D7EE8974B0906A2E92582EB9C07 | ||
520 | :152A930021F17DFAD736BDCD6F89D05CACEC330967F1EBCB57B1 | ||
521 | :152AA800D5FABAA9BDE8CE617624176BE5C33E1F7483DD077C9B | ||
522 | :152ABD00ABDFA1F4FD07ACDF2FD8BFBF7DE00CCDB7C9EBD3C29B | ||
523 | :152AD20060477FD89FF09C3180B7ED6C8CC7BF935BF7C413B97E | ||
524 | :152AE70075581F3830FE356DDEF9FD5ACEB937F4BBD985DA799A | ||
525 | :152AFC0063A774C41685FE62AD2F8E8BBE96287FAE4F3E7CC918 | ||
526 | :152B11009C27BD46EF2F98BEF8B1A5D88342DD130F9F337CC974 | ||
527 | :152B2600DCBA912773EF10671887451C98E3090FD90CCA090325 | ||
528 | :152B3B007DF9EDA1CEFAD069AA5BF9078EFE28803BFABD611FD5 | ||
529 | :152B5000620529BB8F2B02FEEF1F7F9BC66081BAB70B6BB57987 | ||
530 | :152B65006A67BC27CE3589F49389CA1F1AD05192A4777CD58762 | ||
531 | :152B7A00F83ABC6BA2F2D726E5DDF34BB5E68E28E5DF115B5586 | ||
532 | :152B8F0007BB4A8C2DE59821279F2519E9AD8B8D1DAD63C60920 | ||
533 | :152BA4006302BC47EF317ED653BA9C3C46FCD3297C13ABEDD81E | ||
534 | :152BB9006D62AC197BC53E47B5186706F725F7D2388B73996858 | ||
535 | :152BCE00AB305E8FBB8FF13ADC113FCA97ECA33AC68C36EC2BC0 | ||
536 | :152BE300261386E4231C85C74CFC061F627C9CF92EDE0D923EE6 | ||
537 | :152BF800493A7F3261DE16E7227D8CD2F11BFBC81395DCF0C751 | ||
538 | :152C0D00E4BA00E96B1827139583E63CB22746AF7BEF205C9AE6 | ||
539 | :152C220067DE4FFB1482A789DAB8807115EEE71324839BA85E80 | ||
540 | :152C3700963C68BE91F1E7EE32FC8481300177A193D733E374C9 | ||
541 | :152C4C00BFF0632179D61D39A7FDE51772EBFA59A7D61FEFD3ED | ||
542 | :152C61007E5925DFD14FF6DADC44AFDEB3936B3D0D17C55EB4FD | ||
543 | :152C7600927ABAFFB645E59F11BA5B383E8C9824810509C4C806 | ||
544 | :152C8B0032E627459FAC182F3EE8A37111C3A55AC6DEFBDB8611 | ||
545 | :152CA000B41AF18A5F357BC6B806FF415FF22095DB0D3C8B58F6 | ||
546 | :152CB50057A5A9A7CDF9A9AF9BD5849BF9D4D7642EF634778BAF | ||
547 | :152CCA00F159ADEE16BEF1A20E85236E9FAF54FDAA217CF63673 | ||
548 | :152CDF00714EE50CC806393662D4A7BE437977D358E9A579EE05 | ||
549 | :152CF400A08E3A3D6787442CE5B6BF60AC0CF62FD980885722D7 | ||
550 | :152D0900AFDBA5539F0E78D6EDD3B7E4B1A9E3631CB16EBAF850 | ||
551 | :152D1E0057DE92BFFFB424E82262000553F033EA177E46C029AE | ||
552 | :152D3300E2FE045942AC5F8A78669FB77CBF906E8EF56AA5A9CF | ||
553 | :152D48005DFDE1D4F3496505D77DA403E7ACE5BAAC72D3EF4371 | ||
554 | :152D5D008CB783BC3AD2B714EBBE25EDC43FEA102F8DE3F709B1 | ||
555 | :152D72003364FF464C0D4BEE937D9AF2D7210DEBC2BE8CFF7CCB | ||
556 | :152D8700BF8881E3016EC67B8D2A4107EB8CA2447637CEE55AC6 | ||
557 | :152D9C006713AD3DBD37A92E896000ED413FA9EB981E5AD069C0 | ||
558 | :152DB100EE8F58E7DA104346FA032EF47445D0D1107E6A8AE003 | ||
559 | :152DC600EBE78E5F1636449788B723A748868D4F0A3C07C84604 | ||
560 | :152DDB00F60B1F837E116FC72362565BBE6BCC78CA443C46C088 | ||
561 | :152DF00029A5BEC2AB539FA875CB76C874D04FC8F58C4C27F975 | ||
562 | :152E0500BE25B72598FA8D29E22C1E07FFED32F7FC2E5D520F81 | ||
563 | :152E1A003F3B9B06C07130B5CFF0F05E3DD068C5BCF3906C4040 | ||
564 | :152E2F00DC763FEB5DE2271E99C77A6B41BFAD2EDEDC6AD1C9B0 | ||
565 | :152E4400D88E7BF99556C15B4437FC96C5B982B888E3047A8367 | ||
566 | :152E5900BE22361FC632D1733A2D6551D6A2C387E1F623D3083F | ||
567 | :152E6E003470E3DEA1C7C7A04181A041BF1DE7284B8B0FA58182 | ||
568 | :152E83006B6E75F03FF62DC4A72C0ABB69511CFB64ADB04BA3BE | ||
569 | :152E9800EDC3D79EFCE452259647F368BB01DB13B28A7F25B730 | ||
570 | :152EAD00EEE2BF38F2C79217A544ABE205DC94A84FA01DFA68E6 | ||
571 | :152EC200C53AB2DA407BA83B130F23A31F59F42873D1628780A9 | ||
572 | :152ED700A7CB3AB740EF11574B49ED33253521F808BF35D77979 | ||
573 | :152EEC00E0A0AB7CF0F399F8E022AE783F1B12FB163ED0BC7DCA | ||
574 | :152F010048F3AB5E218B15F007C99EB288257B32E38EFA2C6D48 | ||
575 | :152F1600C1FC4BF735E7040E689C06FB7F6BF53735EDB313D89E | ||
576 | :152F2B00A3290D75B596D1DCAFB2E4F1301B3B1E61A9E3D72E7F | ||
577 | :152F4000A4F3E93E4CBF87297D58B3CBDF2CFF9137A7E6AFB6EC | ||
578 | :152F5500F3631E1FFD8DDBFF14F32C8BBACB8AB8C362CF8D1B4F | ||
579 | :152F6A00D79F94EF6882BF8B3A1AFFEA99535A2E9917B2DADB5D | ||
580 | :152F7F0085B84805EAAB5D38FF68F9838F8933508A3A42764A45 | ||
581 | :152F9400C2F0A716D5C97F93CE071ECE5E4AE74FAFD30D9B3808 | ||
582 | :152FA9003B48659BD4678CC99F71D2890C1173C9E2C33F330520 | ||
583 | :152FBE00EF5AB19D267A483FAC233DE8E3F0E6C4CF7A8D84A7CE | ||
584 | :152FD300CB6047E496899F7133E1E9379BD41EF337D7313EE251 | ||
585 | :152FE800B62DD26E5E86EE13361CBDD48AEB6E1C34A0034B3494 | ||
586 | :152FFD006E003BFD3677FC17D2FBC25113FAAE83B39387B2F8C4 | ||
587 | :153012006EFD7516BFF3110B22544A7A79BB7196E0DECE629CE6 | ||
588 | :15302700A5C2FDD88FF2A7AA8DDCD3B5FAB7E28B6B3B972D9B72 | ||
589 | :15303C00A22BE631F8892E13FA539EF428C98F35869A8AF63372 | ||
590 | :15305100E557A6CF57A9C3D7D4D213172E2D205BC453AE8936F5 | ||
591 | :15306600105F167AB6B7BD562F8AD4D617509B472BEE5C3A3F3C | ||
592 | :15307B00A5D25C576D94A6C286E46FD43B9FADE5DE31B2FBC612 | ||
593 | :153090009799CE1E37621B0A5D5D6927FDB1AA56C65E6AF49146 | ||
594 | :1530A50061663C7CC0D785F301FF49DC53CB3D7764D7834AED9C | ||
595 | :1530BA00B882D5B69C0A939C5AA6414F9FA74A61118F54C869C1 | ||
596 | :1530CF00B241A83FB22B2695357F3E3F5C3676502FB3D7338382 | ||
597 | :1530E400340F63BE65E3AF9801E9B25E5759F419567EA695B16D | ||
598 | :1530F9002B5C61FFB03428BDABEF53BD75D005C32413E74B43AF | ||
599 | :15310E007A49E864AB2FF20F4BE6D3DD73AE4FF8AD601D6FEEF2 | ||
600 | :153123000AC4C23B69FBC7C4F9159AD78BE327F4C07CD24B94E8 | ||
601 | :153138008EE18FFA3F97746FDCFB97E7D517C7F2C82679C5604B | ||
602 | :15314D00A9E78FBF41E3687EEA6903B24AC411A0FE07683EBE55 | ||
603 | :153162005AD6BB2442BA0CE69B07BC86D05F7EFC0CAF75749694 | ||
604 | :15317700ABBF4BDF546719FEDFE99BEA2CCB6EA6B344DFE129A5 | ||
605 | :15318C00E7FC27640CE1CA57F985A505620F0F783BB53478FAFC | ||
606 | :1531A1001754FF29BE9E70B77F99E19CA917780AC54732780A6C | ||
607 | :1531B600A516D5FAAE604FB963587EFD14E473685E6A562DFD13 | ||
608 | :1531CB00368A5325E25E905A20EE06C9F199FA4FF369BD67F568 | ||
609 | :1531E000BBFAE56B691FF080BED6D87D9F78DFEAFBFC19FA8E7C | ||
610 | :1531F50032C3D73E7EFF1710DD4B2147A33DFD6DBF9966BF5070 | ||
611 | :15320A001FC55AAA8B9E6BDD79A27DC63DAC9F6F201D3DF78709 | ||
612 | :15321F00BD4B54F5345920295E2C91DEA55C3083365FCA381F10 | ||
613 | :15323400A4FCC4DCCE2EF280745587DCBB65C5BB7A78EC3BF5FD | ||
614 | :15324900B73458F8BC85BD63F975517BB7C05E095F143805CF3D | ||
615 | :15325E00C1BF133EA2E5296F9D9367EEE94B19BCCFA5B28ADA53 | ||
616 | :15327300DE1F2F4CB420EF56ECE54447FA117B31E7CC29BC3BCF | ||
617 | :15328800E0397B4A37D26427D1FB6AF50B4B71073C93CBF3EE4B | ||
618 | :15329D00D8F6D04F491FFC89E1535F3E50A3FEC85C3669F73195 | ||
619 | :1532B200BA6BD88FF8AAC9F5DC7A86ADB46BF8CA72ABFC49C28D | ||
620 | :1532C7005BD0AEEBDAF2C796DECE5EA813B68E2B2FCAA20E77B1 | ||
621 | :1532DC00B9B394A7E3A90B5A58FD8F4B908EF99154E5CFE1F98C | ||
622 | :1532F10019CC91D15D49E89F285B803D65C225BE1F33BFE7B062 | ||
623 | :15330600C0EB3C957402BBFEA229CF736B3DD6737F813ABB967E | ||
624 | :15331B00EE86A7C8D2CB51BFE7EB7B74A1037C876405E9576696 | ||
625 | :15333000E4794D8924F4529A3B443C16C53A83F361FF34A7745C | ||
626 | :15334500495DEB75F8193265A7987794129A3FEC7947CC41785F | ||
627 | :15335A00F731E61F67EEB1E7A119E71FCC3D9883EAC599FBCC51 | ||
628 | :15336F005CC3D5316BAEB1DA5159A9FA2B730E74099A977C6AF3 | ||
629 | :15338400B7B9E5BDB4AF20C9BB0A08EEFA48A2CEB1FF4A691EE8 | ||
630 | :15339900439ED5EF39F4EE349AEA2CBB716254BC37F03E4CF834 | ||
631 | :1533AE00417996BC6C486557881F39D98D5D3C37998817533BB2 | ||
632 | :1533C3004A72A41F632E27758AA34EF01A78AE5AFDD901F0D4A9 | ||
633 | :1533D800C5F71DFDCC8699607DA3E7591AC3EDC6D65F58F3BB94 | ||
634 | :1533ED005897A5B6467F951D5F8190E5EFE1B3CF1924432C9F18 | ||
635 | :1534020074CFFC2B01EB77DCCBF23748AC707B0ECBC77986F8A2 | ||
636 | :15341700D8D46F3B4DFC2D4D4C1711129DBA46FF6DF46FD0FFC6 | ||
637 | :15342C0030FD8FD3FF04FD2B3FA2F73FB2F28ABD83A0EAC46896 | ||
638 | :15344100E467C7F0E1884A1DB1F06F555B97B0FA5F755EA47C51 | ||
639 | :1534560015FDCF100EAE926CBE6AB2FA761EFB4B7B9DAD7E8045 | ||
640 | :15346B0027E9B947F5B62834AEC7DE465F470DC4BC14E73EEA46 | ||
641 | :15348000BB39DAA977F43BCA1FA7FCB7B2BDCDE299DA539A5FFA | ||
642 | :15349500340CF4433961C0BF36B4E298CE627B39DEA3EC7EF867 | ||
643 | :1534AA0063217634D5592CEA7C45B429621B7D601DC77851E412 | ||
644 | :1534BF005433F2A3CDB9A11BFDA9597082F7B2ECFEADF0DF0892 | ||
645 | :1534D40066CFECBF799A1AA43993D59FE216AEE1DB316CF5B34B | ||
646 | :1534E9007E888B36C73B0DAC81948C1DD3156AB7247E54878F79 | ||
647 | :1534FE009EAC4E4DC31A888FD202E35D7ACF84A7C5FDCE47EF92 | ||
648 | :1535130042CA7FD3FD64878E601FD4D97725F8FCCC155F697AF0 | ||
649 | :153528000CA57FE37B9C131A0922364775EB55BA7B953A1D3188 | ||
650 | :15353D0072FDB14A3397CA5C0BB142F9BFB61B56BC617917D2C3 | ||
651 | :153552000629CD1F1BA03967917E71B9749757E9D0C7290DF1AC | ||
652 | :153567004BBB903F5669E07C8D8A73A29426C706CC61A4D3B355 | ||
653 | :15357C00417C7B9164217CFC6BE63271C68307B23609CE1C5FF6 | ||
654 | :15359100F558F1B2B6219DE007C079471077F45DAE9C7F464330 | ||
655 | :1535A6003F4AE11BA48C709FFF98BE8E6CB339AADC92973A2800 | ||
656 | :1535BB00E2B610FCC5A114F2EFED90BA7B853F27CE18DE966C99 | ||
657 | :1535D0005AA2F82D5F0BC466982DEA1C3AE0A33C3E2B4FB034D1 | ||
658 | :1535E500292F918EDC589645F304DE0C9AF7AAE658DF8082FF11 | ||
659 | :1535FA00BDC3E7E373E0979EC8F887C9EAA4D95A427822B92460 | ||
660 | :15360F00137EA2F4CC66F0E72F25BC5BDF3CF96B737BEA6F0F36 | ||
661 | :15362400C897DAF5CBC553EBC7F744DAECFABDA1B156CA6B50E9 | ||
662 | :15363900DE7ED4B58764E75A196B3AED343E2254FF6AEE53F13D | ||
663 | :15364E001C6D853FB7447A2EE9C2A65FD5CDB504838C33722494 | ||
664 | :15366300A7F17D95F96A3B87DCDC537646C37AECAAD43F13CFF4 | ||
665 | :15367800FEC05C4DF724F1C25ABAAF4E7DA61FB410FEE76AEDB5 | ||
666 | :15368D00011FD5514FF59706587E581DE0169C5FE8079C388F73 | ||
667 | :1536A200BD92F475D8309EF258EB9EB2360DF23E42EDC4A82EF4 | ||
668 | :1536B700CA773C4AF7CDF41FA1FA733167184D7C436AB919A3B7 | ||
669 | :1536CC0076A2A9FDFD38F3B09ADA89AA3D070E521E8DDA3AAA9F | ||
670 | :1536E100D8676C4987403B84C0923D6549AD551D306304D7662A | ||
671 | :1536F600AA7F82F07335C00A7D54E632DD714E9EF8CFBC46CFF7 | ||
672 | :15370B00ABA88E8900CE1924F8167A7E35007E575BDFA4FB6AE1 | ||
673 | :153720004A93296D989EFD418B46D371ECA697F7525CDF4C7926 | ||
674 | :153735008B55B939C745CFB03A48B8867F31F68427699C0F9A63 | ||
675 | :15374A008A4A73DA349A875F9B2AAFE12FA284734806776564EA | ||
676 | :15375F00301C123057DF4DD38107E71CB78D7051CE386594ECF6 | ||
677 | :1537740018B4E4DCB663960C8AEE35E0D33217320A6B58888D3C | ||
678 | :1537890019957765DADD3669CBEF1E9249581B3C684A65713D24 | ||
679 | :15379E00E37F4678A0692F9FE62E23389BE5E3AC06D9408DFDF8 | ||
680 | :1537B30012CB273E32A89F8D7E1AC705EA82CFACCA63F9F3E96C | ||
681 | :1537C80019DF929195DDFA28F169BFC20ABFCCAA1A494008FC7C | ||
682 | :1537DD003E42CF09C5C26B39AB6A8EDA721FB240C04675602E4B | ||
683 | :1537F20088501E12E685CBE8AE282FEA997874341F5FA8686FF7 | ||
684 | :1538070084CFA788BD46F7ABCBBDCD0AE5DB5A7CE31872C60954 | ||
685 | :15381C00F6CC300E2798F50D3C278F9FF860A7FD9DBA72D5DBD0 | ||
686 | :153831005C4DF5E4975F213A1D9A820B85FA73167CA3DC26CE74 | ||
687 | :15384600D0EC8AE13B033DC613915ED1FFFC4FD3FC46F800FFDC | ||
688 | :15385B002D25B4416F7FB508E30EFD7AD1C01CD1C83A455EA932 | ||
689 | :153870002CAC77E663AD63C0AC72FAA5741B32E916D5E0BD40AC | ||
690 | :1538850017740503FE7E0AD581323EF5457AFF2B33BFC82AC7C6 | ||
691 | :15389A0094174DE0783BE5CF75CD5B6AD1D4F59B6B45AC3048CA | ||
692 | :1538AF0079268AC0F35546428C936A314EE0DF0499FBE6F5749D | ||
693 | :1538C4003EFC750AE289466FB45A57D54AE3CA72A97994CAD023 | ||
694 | :1538D900382EF4BAEA2FB6CFD665ED55D598781B01B576EAA8ED | ||
695 | :1538EE005B39FF7B22D6307CB5B09624931C95A9BE2292F7E8B6 | ||
696 | :15390300C7C44303F50FD2337CAD64711EC8D603E0E3F536F634 | ||
697 | :15391800F82CF8E5D810C9A4170D712EDDD255D3C53407E3FBCC | ||
698 | :15392D0055B2FA8C69CB9300BE0D09F926C33FC2FEFEC424D5C1 | ||
699 | :15394200F3E318F1606CC85E334EA7FF6A6CB0D14FBF713687E5 | ||
700 | :1539570045DBF9F642969F5B4934B4EBFE2DF5DDE90BD67050D7 | ||
701 | :15396C008785AB230257F0FB0DB1458D4E7F0AA80F93158B9A3D | ||
702 | :1539810071CE7372162BACB8981D3F326414D96517C986FC2802 | ||
703 | :15399600FDC4FE9B809FF409C0E21D233B3B3A4A750D4057248D | ||
704 | :1539AB003C7467FC45BC946FB480E5DFA30276AB6F778D250892 | ||
705 | :1539C000B735A60337F611FFC7B19F1CC5FA83A82F84B58C55BA | ||
706 | :1539D50007A03FE3BD903D36BEEAA7ED4F59E36515B7F15B828E | ||
707 | :1539EA00FD0F3FE5298EC9CD9B73B26347C9AFC1B7BB047ED1E3 | ||
708 | :1539FF00D6BCB141D2A306B1A79816E71AE9AF3CF242E3453F3E | ||
709 | :153A140070F373DD194F23F6F95EE80781F1A7F4C0F9255AB02E | ||
710 | :153A2900BD419F97929A049F19DD7C07CDEFBE50360E0960AEE7 | ||
711 | :153A3E00639F6A862E3096EFD0CDEAFB6FD177AA0BF97136C947 | ||
712 | :153A53001FB3E28A20CDDBB448C46C9745DC120BA6BF2298E058 | ||
713 | :153A6800DF081AECC7593A9A0333F44D791BA103CAA9534601AC | ||
714 | :153A7D007BA57132ED6D9E97F23607A7F58164880F78925343FB | ||
715 | :153A920037A72BE1183038FCE84F9D30FA52DE9650D3908009B9 | ||
716 | :153AA7007066F4D570B5A08B22F42AC0FD29EC41091CCD8B0F3C | ||
717 | :153ABC00D43B78D94C32D76BD3CD473A5451A5D468F5CDC2C5E5 | ||
718 | :153AD10075C1E30306C64D89DDCE3F52F98FD3DF85D4DFAA4288 | ||
719 | :153AE600F437ABCF839FB723662FF1815F75F529F6B2D117930E | ||
720 | :153AFB00B27D52AD3E59F850459F9CF3D2363D44BF0CD798284B | ||
721 | :153B100076E10E7A01F0E6F4674EE84A2BC9419A7F7F6EE6B539 | ||
722 | :153B2500D3F852F6F0373C969E087C6C60D9710F19B839730EAD | ||
723 | :153B3A00D7D28BC4B96ABBDC412A071E49A28C4B9E857F379504 | ||
724 | :153B4F00FFFDEA51923983FC4F2343B5CA8E11D12F5FB2D374B5 | ||
725 | :153B6400FA0C79017E2F16B1E59F35DDB20973899C7CD6EC230E | ||
726 | :153B79005D5321FB3E4032DF9F841CE3A6D5CFE12C9D934346AA | ||
727 | :153B8E00A8E984C04788FA60AF6F171440BE8AF1C5752BEEFC13 | ||
728 | :153BA30015D1DEC2152FB8C697859FA2D38322FE2F70F7C8C3D1 | ||
729 | :153BB80096BF2BEAFF0EDB4B7C3068049A3A6DFE1FCCF0FF61C9 | ||
730 | :153BCD00E27FC0073B05EB7C820F62E003C3E683D10CDFCFCFB8 | ||
731 | :153BE2009FCAF747057F0E66E9AF8E18A82BCBD3832EFA774D11 | ||
732 | :153BF700A33FE0D96BF537293763ECB8C70C7ECB49C4324A1863 | ||
733 | :153C0C004F936CB360B6FAB98BF8DAE1E110C1574C7CEBC07AA5 | ||
734 | :153C21008D602D2758DB7C37F2ECABBF01BFBAE08D11BC311723 | ||
735 | :153C3600BCAA1B5E4B36BAF502A5A953C0EBC8216B6EE8123030 | ||
736 | :153C4B00CB31CB87CF8824DA8A5C7362EADA541EC4B91256DF0C | ||
737 | :153C60006BE0FB53B01DB5FF952ECCF01FD92E6F2256C061F98F | ||
738 | :153C75004E2566D92FC591A33AA972C52595724BE07CBFE6913D | ||
739 | :153C8A0058600EDE8D8F18CAF9A426930D739CE055C8E6958910 | ||
740 | :153C9F00C7B0AEE5F321561CE721A2A74AB64FFCA9DE960EA415 | ||
741 | :153CB40077FD33E6910EDFD953629FF44AC5DE3BD8F8A8618648 | ||
742 | :153CC900A516D4539ED88B98C1C1B988EF41E9896EEC77ED3513 | ||
743 | :153CDE0065AA0F7B61E237B52B8BB5FABDA62887B68CBD387FDC | ||
744 | :153CF3003CA73C2937B65B653AE26413E16C936F2DD785BF237A | ||
745 | :153D08007C526C9B08B0A2FE9DABB996B36E528FD370E9FD2C8B | ||
746 | :153D1D00D7D06799CA94278E6D02FC98CF010B60036F2E2318BE | ||
747 | :153D32004ACE9FD4E662CE7FFD59BD98719A2F92DAB7302FD91C | ||
748 | :153D470075E2FB086DD4579473FABE8BEAEFDA7742F851827F75 | ||
749 | :153D5C0044DEE84887AFFB9FF51460A33EA12F6CF220CE5EA6C6 | ||
750 | :153D71008107D29D39F0B9142C4BEF1D5C5CCCE0C16A2B830789 | ||
751 | :153D8600ACDF8D5B78087D576EEC5A873DC921DE4EE9BD185FB6 | ||
752 | :153D9B008413A4C13644AC330BDE538483631AEACF59F76B7D0D | ||
753 | :153DB00087C0C3312D40FD030E149C3BC6DA3BF4326A0B310BAB | ||
754 | :153DC500C3D47E39C941271EA1751E24CED93B8CED29EBD2DED5 | ||
755 | :153DDA0023DD754198FD61952ADFE5C45B1FFEBC88472874DE64 | ||
756 | :153DEF00D5C2AE5A7420286268EE16DF804059E2EB7CFA3D8C92 | ||
757 | :153E04007DC0F17F72C5B3251B113184845E087F7AF8A685976F | ||
758 | :153E190071863C4ADD01D249C6E2D5DE16C957A3CB91C5FA20AF | ||
759 | :153E2E00C18AF80B48AFD0FA750573907A6FA34FFDA346457D70 | ||
760 | :153E4300A0598EAA3ADEA54847C77DB3388FF4E722966149836F | ||
761 | :153E58006A5AF51E860E34B68CDE5568861E8E0F36D6501DD54A | ||
762 | :153E6D00544795FA40A35347A9783FB58DCBCB1F10F5FA45BD41 | ||
763 | :153E8200BFEA70F25ABF0F1B89E57D778A33DA0D13565B510BB7 | ||
764 | :153E97007EE0EAACF0EFAF36A3948E39F62A6385D2EAC5BA120B | ||
765 | :153EAC00818E68F793F20D8A7C61BE01E58DC526F28ECD90178A | ||
766 | :153EC1006D6F07ED92569E8337C9B30163D3CEB3FD2679C294B6 | ||
767 | :153ED600C76FE7D9302D4FAE522FBE37847CE095ADCB7F762708 | ||
768 | :153EEB006425FA21533F719F43F2DCA79AE64CEB596166FBCB27 | ||
769 | :153F0000638C2A8363D86F147A0B3DE34CAD88371B8D0BDE2D37 | ||
770 | :153F1500B1CECE67D68424C9E2B74CBD549FEAAC1F093F34B224 | ||
771 | :153F2A004F7F90C3B07E029FEF94A06FB6BC150BEB8881746A9C | ||
772 | :153F3F00D3AA9FDE958C3FA707CF3FA7C1462DA1B1126C1A1181 | ||
773 | :153F54006397F836A0B013F598673FF7560E53E3234B133497BD | ||
774 | :153F6900FBC9362A461F146E5A3E6FC233A400318BFDF1634B40 | ||
775 | :153F7E00A04B237F10F53B700839DE65C11749D48BEFFDD9F533 | ||
776 | :153F9300CE8F0F2EAD99566FC60EA6B941949F617DE61FEDF10C | ||
777 | :153FA800877EC15626788B2F63DC2855D9F2EE785B347E71160F | ||
778 | :153FBD00EB9F662877745A391A9F379C27B4CA1FE23F9FA1FCAC | ||
779 | :153FD200D68F50FEDD19CAD57F28BC87F89519CABDCF3EBCBDF5 | ||
780 | :153FE700D434FD0AFC1274F31FD6D5FFC9F54DBA19DEC7AF7EC8 | ||
781 | :153FFC00F0FB890F7BFFEF5DFFB4F77EF778F8A0F5D6FFFFFE71 | ||
782 | :154011005FF55E71E1BF789A7CFA7F077E9B3FA69D399A78FFE4 | ||
783 | :15402600C6F1F061F5B9F94D2A3BA2F779129B3F2ABF61BCCE52 | ||
784 | :15403B009155FE79711EAABAB553896D5E49C3DA1FF8828EF8BF | ||
785 | :1540500077F80EB8FFEE6E1D631E3A823FB0459FB5AA5B57D5B8 | ||
786 | :154065002FF15977B7EBC1755CF34B957AB0A8524F90CE66CB4D | ||
787 | :15407A00874DD7482F5102D53AEAFBD7D675680DD786E173B5CB | ||
788 | :15408F00AE4A877F33BC776435A7E57192F925FE4ABD605D8D23 | ||
789 | :1540A400FEF5358BB58A758BB5907FB3DE99F37B1AF6A316C828 | ||
790 | :1540B90031C4C70922AF2C7D4217EB40ABDA850C822CAA284A4F | ||
791 | :1540CE0068F08372DE178BF78B756F202EF4DA8A07E3BAF0CFA1 | ||
792 | :1540E3002438CFCED0FE4ABBFD426AFF10B55FE26A1BED9653F3 | ||
793 | :1540F800FBC827EAA5FADD6D5FB3EB9D70D59B4EFF34ED474C7B | ||
794 | :15410D00C55AD6B29E4C18D41DCF8971E022CDACBA6EA7297B4C | ||
795 | :154122002EE1C54F6DE6AF5D4CF8A9D416F86BF4F99F965BBC93 | ||
796 | :15413700AC7D63C51FCB2D87662704FEB12E457378106BA2B712 | ||
797 | :15414C0009DD240BBB881D01FD90C59F147D2398CEDA308DA2A4 | ||
798 | :15416100EFFE0D7AC5BEF5BA54E4C096BEEEC0D648B095FA2B21 | ||
799 | :15417600457A9C14638756F94535BA5FC0D4AD2D284AE83D3BB9 | ||
800 | :15418B00F764F80078FE6D3A6DC3C0443F71F6CEDA779D78128F | ||
801 | :1541A000ED8EDB7048655DF8269C6F36B76008ECABD203D41E5E | ||
802 | :1541B500FAD662FBB8C3394CE0252F8B970AE29BC2B54D7AC9E4 | ||
803 | :1541CA00BA7A01CFEE9C6EAD80F052E84FE8B92CB1718FCD975C | ||
804 | :1541DF000B45DFB3ED5EA1B60C7A17207C11DD8B1D1840FB8A9B | ||
805 | :1541F400D51B34D8DC15EB3668D3E94F83275020CE13B2828A7C | ||
806 | :154209003307C57BE95C8D5EF2604C97D997F45994E780C44203 | ||
807 | :15421E005EFB791F3D17AE23F8884F0A8BEA75FEBD06EDD0EB49 | ||
808 | :154233000D5AE1B9B57A09A7B47DAB74FED97B88DFEFD140FB92 | ||
809 | :1542480012C265C55A0B07724C6A51D9165E4F38F34A0FEBFE75 | ||
810 | :15425D00580E62F807F3B15753BEBA7596F4A8EE9757EAFE153F | ||
811 | :15427200D4D6DD8FEBFE55F7E87B73566A5823975764F3E7852A | ||
812 | :15428700AC3324227FA2D6CAFFDA1775FFAB0DFADE9DB59A97C5 | ||
813 | :15429C00E6ECC0F7366B159FCE69C177627CF1DA8DF9630D1B06 | ||
814 | :1542B1009FC6B78679AD5E71EE615D3ADBA073CA2BF9B2F8DF16 | ||
815 | :1542C60086311D12674E362176B4AF9DCA9D6ED828ECDA65ACCF | ||
816 | :1542DB00253710DE981758B6B1A26BBDB69B6401E982C5BBE8C3 | ||
817 | :1542F000FE879031FFF331DDBFAB41870DA1AA8F72B16F98F838 | ||
818 | :15430500A22EADFD922EDEBDD640EF6BF5BD842FD01C7C0DFB89 | ||
819 | :15431A00ABE09B524BC539C21F6FD74BCE7D512F3CDB2DE8DE86 | ||
820 | :15432F0043749F45F42E88F08D6E39045A835EC25FD7A623F818 | ||
821 | :15434400F06E82A505F0138E11377A1D3D2772B66AB3A81DC03C | ||
822 | :15435900DFB9D37ABEFB7ABA0472C8F98DBC34AF6C3A4869289B | ||
823 | :15436E000B7E36C98C04FE20E7C8BE9CE3F0D276CA237CAB09C3 | ||
824 | :1543830086ADF41CF8DE7CADE26C29E1B3549F896F7EC9B27C78 | ||
825 | :15439800F377CCE21BE0BD80F826E4DF2A70F1759B77C03725B1 | ||
826 | :1543AD009CD2A6F14E77FCBEC70A425B8826B1D66EF6E863B372 | ||
827 | :1543C20042D156C9FFB8EEFC2E8C3CFA186833AB7DFD46F67A95 | ||
828 | :1543D700CB46E75EF1AE477C1FA220BE7E63E158CB46299FE89F | ||
829 | :1543EC00FC894AEE25DC5F277A0367B70BFC7B5A0A7907E1FE98 | ||
830 | :1544010071C2FD1E21B7DDF8CFB1F19FB0BE4B11947C9FA0B6CC | ||
831 | :15441600A39BCE085A8057A29B46A7D102DF6D7BD0A605C9D76D | ||
832 | :15442B00E2F52E5ADCEAA2C57BC287303B8677D2F8ED75D106C1 | ||
833 | :15444000EB55A03BD277D8F4394FB471E8B1659AFFE787D1E3D1 | ||
834 | :15445500828B1E7F65D30363B8C4A6C50D7420DAB86991177966 | ||
835 | :15446A00E4B1DCC8FAC7D876D6E21F7B64E32C65CBC63CF69F69 | ||
836 | :15447F001F2B88FFC946FFD8A3E277C51F8B315AEC67F43BF207 | ||
837 | :15449400258177794725F7908CBD9E17E5050EDE696C16FA775A | ||
838 | :1544A900929CBB5F2F5CFBD414BC17CC84F7AE85A0B90BEF3177 | ||
839 | :1544BE008177A7BF6EFC936C2FBEDBC63FD67C30361CFC17BBB3 | ||
840 | :1544D300F0EF116B37167E7B6DFC164136D13BEC33BBF9DE2957 | ||
841 | :1544E800FF4B21FF2D9AA19C887B69D3C1C279FD14589E408C43 | ||
842 | :1544FD00AAA4D48273D5099237B954C72304C3A17B37EB15EBF0 | ||
843 | :154512009A34256789969773A7061EF693BC61AF376C3CF4031B | ||
844 | :154527007A776EAD569CF3592D3FE70FAC77D2CA8D6CCD3D1BF6 | ||
845 | :15453C0077C73C2D806B2170522ED6B603B9AA47CC8548473C72 | ||
846 | :1545510037C7A641FBD89BCA71E6687B9E403EF80E03AEB7C9AB | ||
847 | :15456600ECA43C99F1FE1A8D77CC5117D26905EB41D003684EA5 | ||
848 | :15457B000BBE6AE7FF163D57BC2BE35E7CD2EA77C1FF01EF9849 | ||
849 | :06459000C0E6B892000035 | ||
850 | :00000001FF | ||
diff --git a/drivers/atm/pca200e_ecd.data b/drivers/atm/pca200e_ecd.data new file mode 100644 index 000000000000..eca84aa7e0c0 --- /dev/null +++ b/drivers/atm/pca200e_ecd.data | |||
@@ -0,0 +1,906 @@ | |||
1 | :150000001F8B0808AC5A10380203706361323030655F65636428 | ||
2 | :150015002E62696E327D00DC3A0D7054459AFD261333136278A4 | ||
3 | :15002A00192663E02479728060A10E9063213F64F0700F3DE05E | ||
4 | :15003F009E6CDC7B2F3514B35EF0A28B9A5A731E554B91474C5C | ||
5 | :1500540034E11AB6692618B7609D8404A2121CA8648D7551435D | ||
6 | :150069009DA578A56C8AF276A9AB829DF3AC92DD52CC5EB177A0 | ||
7 | :15007E00D4CA32F77DDD6F665E263FA25B775B7753D5E9F7BEA8 | ||
8 | :15009300FEFAFBEBEFFBFAEB7E79F4A91F6C270A21A1870849C1 | ||
9 | :1500A8007C974CFA8536C11F37B9A99FFEAD9C49302569258321 | ||
10 | :1500BD00D8EF4EEE6E14EF59E3B3EDFED3E3C735EC67E50822CC | ||
11 | :1500D200A9FE0FFD29BF7CEA97A26F4EC993D537AF13234A5E2D | ||
12 | :1500E7005EDE94F3BF245F4AFCF1F129E7CF9E866E0ADE2C3919 | ||
13 | :1500FC002BF0237F849F3240F688FEB5EC75792D39E3BCB43E9B | ||
14 | :15011100C9A9F54BDE24FFBC9C3C6987DDCD33F3938CB0674E4E | ||
15 | :1501260078D6F8D7D63FD9DC8CEEABDC4824B2F9DC949E391965 | ||
16 | :15013B00FED7BF11FF975E7267F17D1CFB4BE77E3625BFBC0C26 | ||
17 | :150150003F0FF9BFFF5372CB72671A1F3D3EF99DF51312ECCF0D | ||
18 | :15016500C070095C0E5FF8FFFE4B3A7E246851FDD31C5230FA46 | ||
19 | :15017A00FC0A35E009832F79ADB5E45140A3A4743C8CE3E39F62 | ||
20 | :15018F00C35BB09DEAFF05BD7A95BB3DADE6B56DADE538465425 | ||
21 | :1501A40052C90E11EF08B4773A8857FB013CB7112F090619CEAC | ||
22 | :1501B9005B125380AEB695F80197D874FE9A9022A5D554ADE572 | ||
23 | :1501CE002661CA73EE80B5F5F26AE22D7F9A78FC814838484AB5 | ||
24 | :1501E300E8B36DBD4D843D4C4930CE42B06FCC091861CFB9BDAD | ||
25 | :1501F8002621C3B438D010BE6DD7091AF29090DFEA334930C6AA | ||
26 | :15020D001187E86D9CB09E2EDF18033C8DD220A9BB6D57390DB4 | ||
27 | :1502220011D2D8B26F23C02CEA0FAC0EB76CBADB3C4F48F1BBF2 | ||
28 | :150237001157A5EBD25FC0FCCB804A3412ECA211D133EA167DD2 | ||
29 | :15024C003B8518510311A53A5FDD62226D9C4BD46AEA567ACCA9 | ||
30 | :15026100362DB78EE8A7683E21017F201E4E927EEAB6169944DB | ||
31 | :15027600AFE1ADE3AEBAC0C53534B0EE4194CF8AC2FE47C6065E | ||
32 | :15028B007960DD5253D1FA6834346000BC45C0D909BE0A681025 | ||
33 | :1502A000BDD7BA4BDBBA12ED8A7C09EB8EA79BDA6BF9816681AC | ||
34 | :1502B500F70EF3723259F4518D59F578B3AB0A66E7A3597F0E69 | ||
35 | :1502CA00BA90E04E5BEEC669E5765D2A33DD6762936427C1D5C0 | ||
36 | :1502DF005CDA40CA8A7AA03EA807AC0147BBA02E52A72974180E | ||
37 | :1502F4007B956F461DD851EB3EA14348C8A0EA9689F2332DA72B | ||
38 | :150309000E7B941FFB00D8FFD6801526637B69AB8FCC22A5F03C | ||
39 | :15031E00ACF65863355BCB4740B7F5A05B6A3CEC239954156CC1 | ||
40 | :15033300E7B09E9AA7F084F085DB760DD171378910B6285EA406 | ||
41 | :15034800F64A5F403DE05D8BB4C2F800BD8EE3418BAF06B8AA3D | ||
42 | :15035D00EE81F5E96393DE6D3B92E0385D564748698085091946 | ||
43 | :15037200A79EC256E0D34F49792B1D759310AC032BD6FBCDCEAF | ||
44 | :1503870038D845EFE5456A87F95932097ABB5B050D98BFE30F8A | ||
45 | :15039C009CDF2BE6B767E667E6C6EDC6D24DB7E7A56AA4888777 | ||
46 | :1503B1003626DE3B6D253EE5C5810BE19CD8095A7CFEB241D8BF | ||
47 | :1503C600765A663C6DAE8CBC4EF7B70D35420264F51833C16105 | ||
48 | :1503DB00A6438F32018C232C303A64E29A23DCADBDCAE604CE52 | ||
49 | :1503F000C2DAFC0BE48392B027D20C3E546386122FF0964DDB3D | ||
50 | :15040500C0A7BEC35A366D323B120AE8B357F8531ECA1ED46DF0 | ||
51 | :15041A007F6AE732A6800FFA49302E6321B8C48EB97E560BEFE0 | ||
52 | :15042F00458110CC6910FE9B84D825C10415992A67940623CBF7 | ||
53 | :15044400E9EC584E5DD1912DB4E84C9DA9C486689188ABB8F0F0 | ||
54 | :15045900BD43E494A124DEA49DE43503E75D87B4D6F9E7F81CCD | ||
55 | :15046E00E748EF05F296419A062866F84EF23AC04791363CBF24 | ||
56 | :150483000BCFC31CE5D213EF71C44759162BA4E81F2077148DF9 | ||
57 | :15049800DE677E1BF429501F117ABAB5A3E037FD527EFD21DE68 | ||
58 | :1504AD0072EB2653890C502FC844D803BC937403BD7E2113CE66 | ||
59 | :1504C20027FA51FE0EC4AAE7DCA04906DB38E62BF04FDB0E52E9 | ||
60 | :1504D700EFC24B09339A731CE3886F2C203A191CE0A344E0591A | ||
61 | :1504EC00183F514DC49F88258C471F213EC2FAAC68A8CFB85650 | ||
62 | :15050100D6535DAAB92A3CE7C0EFCB0728CC6BDC33EBBE3AF4E9 | ||
63 | :15051600E76BC964B19EF8949519FF64CE568E091F74150C995D | ||
64 | :15052B00885B1C83D82FEF43FCD0E167A306513B39C4E31CF4C7 | ||
65 | :150540000131A6FE965F4D26FD9E7387CD79E78E9AE46AAF90F1 | ||
66 | :1505550009FC2A0E7E2562E5D1C8C62AB40BFA87E7CCA98C1F9A | ||
67 | :15056A00E07CDB0F02E0079ED07A136DD5DEE892EB27D74DDAA8 | ||
68 | :15057F009075F0D47A1E222F1BA9F524FAABBC1763C2F6998923 | ||
69 | :15059400F69376FBD1FB4F007E4396CDFA85CD8A1BD166C3B678 | ||
70 | :1505A900CDE268B322323660755A03C6B5E64D2B053DCC1D2390 | ||
71 | :1505BE00D266445F1497ADAD0B68E03E15BF6D6448D8278AEB56 | ||
72 | :1505D300C80678BEF73EB0C30FE947E092E01FC585095735DAFE | ||
73 | :1505E800F671D7EE55CF245C958188AB5ADA037C046D01BEE121 | ||
74 | :1505FD00BAF4A9E9518E9B1D5AC626FE09B121732DAEABB48BBB | ||
75 | :150612008C15B459DAD7B3F32CC428FA34D7B6547ACE7D067369 | ||
76 | :15062700345B4F0631B39A266B102748855D9AEE95FAA9DD5677 | ||
77 | :15063C00D4EA35EAB4875792D2583897B499FE5D3F12FA91FA31 | ||
78 | :15065100A3343AFA18E487C7B823BF7489DC027E87B620FA20D5 | ||
79 | :150666004FD1F043DE9AE5B0C528F877AC664BD58D1BD21EFFFA | ||
80 | :15067B0059BA7B79AD423CD23EFF6EAE509A67B0CF7B609F6360 | ||
81 | :15069000FF23F63989F6D9BCD64CED8550E85072F557D21EB076 | ||
82 | :1506A5004745AD6EE339DB1EF3C922D37F7DA9B0478E5E629653 | ||
83 | :1506BA005AA5D57F827B8FBE9F46125FF04F66E1FE5412866761 | ||
84 | :1506CF0086F945D818ED469ECAF8A08A7BB46860BB6E87ED4EC3 | ||
85 | :1506E400F114BF6CDB45C1764D60BB8F6DDB5D00DB21FF8083E0 | ||
86 | :1506F9007F83CD7B22DFE3C67E6F5F26674C9F2BE638724555DF | ||
87 | :15070E001A0F7DDA111F0B20A778361F4BE710B11F8EC13CAB3F | ||
88 | :15072300CFB85A932B64C35C82792494788F611E51E60E9B4A3C | ||
89 | :1507380007E413987728E1C8273927219F0C603EF1E1B81893A8 | ||
90 | :15074D00F9A4D8B3F9A4F963E02D724A539F88D97980873AFBA5 | ||
91 | :150762001C3A37E59359CE5C33A1781D3BC1DC9B7BCDA235ED12 | ||
92 | :15077700A29E2C523E379B4988CE17BAF7F3909FE8EF821F7925 | ||
93 | :15078C000AB11608D25AE1474B445DF7FC5CCD20E5FB68A3A870 | ||
94 | :1507A100170E70A2DF010DFCFD7FBBF54429CA4C9ABEA016F86E | ||
95 | :1507B6008190DD315E0F7E5103E34F925FAF825A94A30ECFCD41 | ||
96 | :1507CB00EDC7BD45FA3FEA06F6167AA890B7BE6EEB8ED2E275F7 | ||
97 | :1507E0005F9819585F7C7324B932C5ABCC90B5C0CDF0B262939A | ||
98 | :1507F500695544DE16B4F419E647605EC90313E7DD13D9B652B6 | ||
99 | :15080A00AE1BE31B70DDEC7941C02DC8C25D1129B371352AEAA4 | ||
100 | :15081F003D7B5DDD02EF009F3F4EEA549887F684FAAA68452469 | ||
101 | :15083400AF42D45290DF570BFC56BA0BF015C4D73BF911F04B90 | ||
102 | :1508490037E243DE03FC62DCA7D1977CA206EDE5CEFA7063BDC6 | ||
103 | :15085E00A3BEDB4CC197290D617DA68BDC791A7B55055EA967AE | ||
104 | :150873000D7A477DD7EA98BF20E2AE48D57848C3FD00350F601C | ||
105 | :150888007C421EC69849CFB37FEA060FC6604F20B001CE496318 | ||
106 | :15089D00F45BB141FAE3B6A126DC2B99A8E7346641AFCCBD0C5D | ||
107 | :1508B200FC9F80B3D24E383761AD1C83FDE1320F41BEF0EFBA70 | ||
108 | :1508C7005F9C89FC501BE39EAAC2D98AE8F5D48775DE582DD4FD | ||
109 | :1508DC0079C130D653FB649EE04837404E899AD0B2CF592B7220 | ||
110 | :1508F10048F13F47DC707EFA7B13EB3699AF0DFBFCA4DB755C24 | ||
111 | :150906003B75477AA046AD605EF541B3E5D6BBCD36A0A978FFF8 | ||
112 | :15091B00C6DC8B750C9CBB3007DDB2E7553337827B40B7D80387 | ||
113 | :150930008A033190A792DF42FECCF4C379E3167106B1EBAEB1A5 | ||
114 | :150945001EEEC7F307D45D9DA1DE74BD05671CBE429CA18E43BC | ||
115 | :15095A00BE5B682CD0CC95E2ACA1F6C4DD381FFA828EE5E21D9F | ||
116 | :15096F00CF4F17DE36CBDB9B95EA476A72D279D11F53A6CF9FA5 | ||
117 | :150984002F7597077ACCF25BD6C49886A7633517D785EC80E7CC | ||
118 | :15099900C4DF12320AAD0BDA4E683AB425D008B40B301E87C6CB | ||
119 | :1509AE00A0E9625E4FDC6EB04FF43059BBFD16CF2CA13DDE56FB | ||
120 | :1509C30043BEDBB50EF83FC2317F3629F20C3409C7410F71268F | ||
121 | :1509D8008F2F88CBF60A4BF1D9381D5E9ADF82B8362D3FA475C3 | ||
122 | :1509ED00BA4BD293F8E3643ABE8067E39C2533D1CBD03A3C13A1 | ||
123 | :150A02009E8DD33425BF89326D9C964E46A68553D2C9D040BBF7 | ||
124 | :150A17007F55C31A995C3D2CF1C7A25CE40D8CB1E29881790360 | ||
125 | :150A2C00623586F12B629A58F412FA289C3F647C34424C9608E5 | ||
126 | :150A41007F9B2E4E5E8138715DFA8579CB9E939363247D66979D | ||
127 | :150A5600B181F1823501C620C60CC64E3A56ACA39958518FC96B | ||
128 | :150A6B00B3FA18D457D69F1A6B2156F09CCE223913E224153FF3 | ||
129 | :150A80001F431E9A8D7990EDA5175CF2ACFE817D7D38027114D6 | ||
130 | :150A950081380A7D8D38DA6CC751C3639938FA009E23DF07232E | ||
131 | :150AAA004223D0128F43850E8D416B8016825602ED1AE0753D49 | ||
132 | :150ABF0036318EC41D03C412CAEFD9DF938E27E09B965B03B992 | ||
133 | :150AD400F7BCFF8A21C70726C557AA05537E9F8DEBE047317E33 | ||
134 | :150AE900DEEF81F157441D23C75BE2B2C13A3649FEF5022F9BEF | ||
135 | :150AFE004E8B23CE5AE21F91E9F8B54C8AB35E320D3D874FEF6F | ||
136 | :150B13009A915E86969EC69B420F382B230E9D92DF4499668A69 | ||
137 | :150B28008D7A32959D60BE4D7FE194E3683F394E74A0F3154D74 | ||
138 | :150B3D00CE4DE17F988EBFD4BA8B38D4FBB846C8AC542C4EA83B | ||
139 | :150B520027713FDF91D98F156FABA86DB78CB65588BD1DFC5798 | ||
140 | :150B67007D286614EF1AA4BA479E078B77F5D28847D6AE88CF94 | ||
141 | :150B7C00B0C665526784B9B260E38E7DBC445B88674CB6E10A5C | ||
142 | :150B910021EE75DDA61F635A2DC718F12B780796AE33FA999E1D | ||
143 | :150BA60043484524B702756A8067E58101519721BC73FE108595 | ||
144 | :150BBB009862B92AE8AF77F3DBB513DC1D6B73DC635914F1AC84 | ||
145 | :150BD00087F12E56D25A75B3B4622F6768017E1CF67CBF1E338F | ||
146 | :150BE50015C85F985FE2F23B9EE0F375F4B11CFA743964B06EE9 | ||
147 | :150BFA00521FC48BD74A7D2C873E5F492B4B9FC12C7D06BFA10A | ||
148 | :150C0F003E71873E671D32C46F521FC44B7C47EA1377E8F3954C | ||
149 | :150C2400B4B2F419CED267F81BEAA35EC9E8B3E44A460684DF02 | ||
150 | :150C39008C3E88A7DAFAE0F3AA9BA595A5CF48963E230E7D4207 | ||
151 | :150C4E00F6FDA61A180DA77CBCCCA066BB897CA58FE0FB4EFBF0 | ||
152 | :150C63003D6EBF37D8EFC81FDF0DF11EA3C29781C7CE1CD1D360 | ||
153 | :150C780041FBBDDF7E1FB6DF2FD8EF23F6FB6AA0B3533BC6C47E | ||
154 | :150C8D007E0B63EDDA49BC1BE40C9EBBB49FE2F99F8FC273BFE6 | ||
155 | :150CA200F6160B698BA97DE6E61ACC2B857D695E24B73A10CB76 | ||
156 | :150CB700ADF62572AB3DB00E78DE451DCBB597059D7A98BB5EAC | ||
157 | :150CCC003B25E844E1B9567B83E1FC77A41C0C79D66B7B98A408 | ||
158 | :150CE1006BF18540B710724F0D394B4F6F3BB916715096422D36 | ||
159 | :150CF600B702613FD9F653011B75C0F66E7B4BC050A614EC99A4 | ||
160 | :150D0B006DCFAD4DD15FACC9F5433AF3C4733FABB7F9A34C0FC4 | ||
161 | :150D2000960DAC49D14CE122AD146E4A5694ADD4C645BAF768FE | ||
162 | :150D3500B9D5381EB56DAA3D216D1ABA22EF6F904789BD3FE19D | ||
163 | :150D4A00B8BEC3392EF9DD65D358286174F44989B3DEA681BC57 | ||
164 | :150D5F00FD4803C6C69FC88C55D9760CC3F846B01FDA8EC2739B | ||
165 | :150D7400583BC0F0DC392264BA2CE4DCA1BDC88E08FB76F1DBED | ||
166 | :150D8900AF0807F47DF7466E65D9853BCDCDA56F2C7F612C6631 | ||
167 | :150D9E007C7B2DCAD12E6C940F67B9556BDD952B4AF72C6730C3 | ||
168 | :150DB3007697188B0B79F363B915F3DE7257064A0F2CE7305641 | ||
169 | :150DC800B856CA8FF6CA8738B9F17B77E5EFE6BFB8FC208CFDBE | ||
170 | :150DDD0047756E753E9C577F7DF1F32AA4F9F17C5A85F3FFF557 | ||
171 | :150DF200C86015E29EBF78026AAD06C113E48F5BA22F113283A0 | ||
172 | :150E07009E715DF43B056D120CC555D1370A39E07C18C798B8BB | ||
173 | :150E1C00EDCC6553F93002F1F71A2D10DF7F625CCEBBCC6B45C5 | ||
174 | :150E31002F6D4482116E403F67DD5153D9F47DA8B3F6D15B712C | ||
175 | :150E4600AF04BB49BE31DE2AFA06DE2EFA2E61CFBC3D80BFEF5E | ||
176 | :150E5B0069C0BF9B16068280AF895C26F2ADE81BF9B0E8570B92 | ||
177 | :150E70009BCF3A03F81FFE10F037D1D9011DF0435CCA1DE37EDB | ||
178 | :150E8500E89F15EBB093975CC9EC6DA454033C43ACCD23B0367D | ||
179 | :150E9A008DDA7EA606C6007681AE96B6E141D15FE0E5D037AD30 | ||
180 | :150EAF00245E1674D52944A3FBAF277DE84B3B005EA01D83BA29 | ||
181 | :150EC400C112F6CB81B3F8ED77209E8C2BDC2B1FB171D1DE7613 | ||
182 | :150ED900BC517CDE0D3C55EF0766EB9A98FD6DB39F22BF48E2BF | ||
183 | :150EEE0067DCBF6B08EB5F529F789DC33BB340367FA8CF54BDFC | ||
184 | :150F0300782FF021776B43FC9315B63CDA1DF4C69792C76198CC | ||
185 | :150F1800AFDAF2305B1EAA65E4C1BDEEBC8D3BEA9067740679E9 | ||
186 | :150F2D0074873CB5200FBC3336853CB50E799EB4797C807164D6 | ||
187 | :150F4200CB336ACB73BD2C230FEE55F7D9B8E86F2979F0793A72 | ||
188 | :150F570079420E79D6833CF0CE6253C8F3CEF28C3C977E277943 | ||
189 | :150F6C002CBB827B9A940779A03C3B1CF2E05E735AE20A5E2E36 | ||
190 | :150F8100C8ADADD57DFC7A32994CE55867F917D10659443B01F6 | ||
191 | :150F960039BA96AA810DE1CE35FD14FF4FA873ECB821758973F1 | ||
192 | :150FAB00DDCE291BAFE0A505F1791CFB6658EB6539856F9A5A59 | ||
193 | :150FC00002CE58E939FD7C839D8F53B806E04521B67D901B9DD8 | ||
194 | :150FD500F3752DCA6A81BF017218DA61689FB1466D21DBA92DFB | ||
195 | :150FEA00039F2967ED5A15ACD57A56663C627272B07149A28F90 | ||
196 | :150FFF0046ADBEC62EC08F6923AC5FA3ACF3C8095A4C06CC398E | ||
197 | :151014005B8FD0F9173FA3AD5BEFA46DF397D2E7B62EA7CF1F57 | ||
198 | :151029005943DB2FAEA387E69FA6783FF357BFC8C198A6F8BFCB | ||
199 | :15103E00542F1C7993169CE9310F5CDC07F5C0BE554EB9CEDE5D | ||
200 | :1510530043BC85DAFAEA344C6FA1E5F712AFCF09130AB4D0C3DD | ||
201 | :15106800D3C06BAF2527C18D480BC37C89F6F12F9E621E6BA1D1 | ||
202 | :15107D00CBD64C01875AE093F9C4BB30D6C3704D312FD45EC9C3 | ||
203 | :15109200D405E99F3AC2884A995B13DF2FD855FCC78E2063D72D | ||
204 | :1510A70044DFC5AEBB64AD33EE92DF494812EAA2C23E336A0D67 | ||
205 | :1510BC0019F87D638EBBCF3C9433641C0A0D189DB0962F586F8B | ||
206 | :1510D100189E0F3E1777C9F825E280D561A81BA9897E90EF9079 | ||
207 | :1510E6000FCFF76E3A24E0CF440A2A3E49FD7B8D9D377E5E23CE | ||
208 | :1510FB00F7C7487A2F8D31947F01EC63F9B1DF97CF8BFD1DEE8E | ||
209 | :1511100023F65E382CEA18B97F0DCB5C073693FB1FB371BA04B5 | ||
210 | :151125004E43669F14F1F0A4CD6774129F5B27F091FBE5B0A8F2 | ||
211 | :15113A0087527CE2369FF5361F89D345651EEE67B171428E04DB | ||
212 | :15114F0095BABCFD7DA63FB4C83C06BAFA2277560560AFBA7A78 | ||
213 | :1511640043EA7B3E726FC56578F680FDCB0C3807E50E34C29EFD | ||
214 | :1511790055AD94F687550DBF8B04E9D8DB9027624A5DADF6326D | ||
215 | :15118E00DED9F9DCEADDB00F75B0D2D0BEAA0324DA48D43DD4DD | ||
216 | :1511A30055DA15762F851A4DFF0D5FA8FD86BB6C5B57691D3C31 | ||
217 | :1511B800A41DE0FE441F63B97D4DCBB46E8E79C51A053D12BD56 | ||
218 | :1511CD004C059A08276A94C281CBE3E4B9E527DDD5CEF965C6B7 | ||
219 | :1511E2004193DB34702E3E232D1D68B94B97844359F37D303FCA | ||
220 | :1511F700A4BDC8A186B0E747A79CAFFE23EE4D4BC2284B10C611 | ||
221 | :15120C0096419D11D43AC45D3427AD8D86F62B9EAB609E3B411A | ||
222 | :1512210039E96C74475AB90FF66017D6BB7A2FF744A2BC2032BB | ||
223 | :1512360022EE9C27FAF1B0EDC7D6043F4EFBEF689FA13AFCB79B | ||
224 | :15124B00106A85B48F821FE0FAA18FE6ED1F308BC92253EAB616 | ||
225 | :1512600044EA16EAAE76FAB35FEB608188BBD28DE768C2A807ED | ||
226 | :15127500D6A3E94EE2C5F7E7E7B61B259B89F7A5B93143D596FA | ||
227 | :15128A008AB5598FEB0073D9FAE876EC73578BFF21CABF23206C | ||
228 | :15129F0069AAAB3C61159E676A128F885E0BA4E4D620EECA880B | ||
229 | :1512B4005AB8CC6C752DDD9E6BC399CFDA9E1AC7FF6352430BCD | ||
230 | :1512C900BFE74ED10845BFE74B3DAFCBC0459C801EF81D11EF02 | ||
231 | :1512DE00CD0E6AEE3A96DE9BE4BDD916BCABB2EFA5314E08DEDD | ||
232 | :1512F300AFE9C75940AB2EC7B51570BD8F5DAFA95E29EEFB990A | ||
233 | :15130800BCE39FA37799F8BD016922CCA746CDB3C9A47F527EA9 | ||
234 | :15131D00B2F9D74EE2DF6EDF9D4B39EE127766BD71A4A3240E38 | ||
235 | :151332004BBA3A7E4790307C4E4C419FC571FF91F4D500F0620B | ||
236 | :1513470094E2BE68D3F4F9347FD50AADA02264E78D0AEDF66A05 | ||
237 | :15135C00A0C97C6A47FAEE1068B3A2ACF7F4B3CD8F8F1D355654 | ||
238 | :1513710068F757F8B4FBCB03DAA28AD47DEB0A6DBBA46DD35490 | ||
239 | :15138600BC8727D155DE9F19B638717B25D610F8EC4638D8F716 | ||
240 | :15139B00207ECF8950FC3E731ABFE72C4EB82B713D104791385F | ||
241 | :1513B000EC20E660C4D1FB38E2A0ACA501AC11A1B67B88903162 | ||
242 | :1513C5000236FE4BE255C5DD690CCF9BEA79D24FF15ED2F20E35 | ||
243 | :1513DA0088EF6B44AC7B4CE0FBD5D7E47730FBDC81304D1BA0C3 | ||
244 | :1513EF00E28CE280056D58A303B6CC8635E0D9B754F0E33B1C7E | ||
245 | :15140400E3E2FF0C865D648936C09D30DC971766C188CB4DCA55 | ||
246 | :1514190027C2583DF46A6488A910CBABB3C712CAF87016AC0146 | ||
247 | :15142E0060235930F7BF29E3A3593002B0771066AFF37F13F3E9 | ||
248 | :1514430084C1511569F6242F3203617CC0644C280C0F0C1AF656 | ||
249 | :15145800229960D0640871E2A297502C37025AEFB141264ADC60 | ||
250 | :15146D00E0A1CC4156D92DEE7CC144126CB07926122DDD9DB8D3 | ||
251 | :1514820099327844070F14B7425DEE8E73BD2D6A2B6559B7D497 | ||
252 | :151497009D52B355DE15578538BAE8B2559C73DFD7DD6FE6CDD5 | ||
253 | :1514AC006450F1F6EA7E4CBD37DDFDBEEFEBAFBFFEBEAFFBFBA7 | ||
254 | :1514C100BA31DE44D82DB80EE738919E4FBE9AF31B37FF6E8C0B | ||
255 | :1514D600D97D8E4A1BC19FE113CC3500EB7D15DAA8986B25E05C | ||
256 | :1514EB0087B471F62449D02133CEFDA473208FA0ED37A19F74B0 | ||
257 | :151500003663C7C458757D99E6E3144ABE9AA12F947C9BF50CD4 | ||
258 | :151515008CEBAB1D34234CD447180B4298111E57823AA4431D81 | ||
259 | :15152A006768C3D7CAB2AD92C6AD92463FE63CA91C16DF3FF7EC | ||
260 | :15153F00E1FF709CDAB90469291BFD5236446E9DE415D833C0CF | ||
261 | :151554000DBEEBAB6C10E61C105FC6F58DEC875B3ED5BCE799CF | ||
262 | :15156900AF3269B70EFEBE8AB2C2569792B0D97682E72DADE6FD | ||
263 | :15157E00717D5146D64D2F2B7296012DDCE704CDE492EFAB5527 | ||
264 | :15159300511E4ABE0134BEC1CA529CCF7E53D2C1CBC0E6F81BA9 | ||
265 | :1515A800C7A4FE495015BE293361DC608CF8337C825E8FF0D8F6 | ||
266 | :1515BD00B855A83D29D09E64DABF2DF80B65F06EEDC9F843208F | ||
267 | :1515D200770BC03B94FDC477DE271FD06EF709DE2FB9C6F8FCD9 | ||
268 | :1515E70009F8B2F5FBDAB2F576D9D305CA9475D3CB4A9C65796F | ||
269 | :1515FC00F1542EDF728EDAF3DFA91B7AF274033EA764DDD5BE7C | ||
270 | :15161100310B7C63D755E3F3FBD96FD1EE4ECD27B36CBD843CC7 | ||
271 | :1516260079CA9639785F78B6D748E4D5CF3A3766081863B4A142 | ||
272 | :15163B001CFCA948C92615F7A301D6853FCFEA38940F9C17769B | ||
273 | :15165000DD94B30E78E19670F8D301632C0F86CD032183A2CC22 | ||
274 | :15166500CC2F03787BED325FB6CC2C5036D39B5B867DEA73F4B0 | ||
275 | :15167A00D92EEB2D5056EC7596993451A9105621F9436214752A | ||
276 | :15168F0006CE4B1FC83CC6CA306EC2FFFBC7DACB1C6B51524A3A | ||
277 | :1516A400F89A13E5D7C7E5374E6D399F7910F72B13AC1DE6BA33 | ||
278 | :1516B9003F2474592118EA35C380BA700CDFB19DA53BD60968C7 | ||
279 | :1516CE001F501F6E475D02FFF1BB0315633A878FB2E223AC503C | ||
280 | :1516E300B9EA28A7CEF6E585CB5528EF92712E94FB7C7E617C84 | ||
281 | :1516F800B820BF7C85FB3AEB5CC21832C7A3072A123AD703DF1D | ||
282 | :15170D00866F7F4258D8CFAF1B037A2D747D6758B9E39A907AAE | ||
283 | :15172200DEB6FD421FE7F23A571F17A005BE11B48C51FE04D841 | ||
284 | :15173700D7233CF06F0AF2A1407B92699F4BDF1E87DCE1FC7519 | ||
285 | :15174C0079A7CF6FE29D3EBF8BBCD3E7322950B6DF337D7E97A8 | ||
286 | :1517610078A7CF6525AF0CDB3FE7FC36BB26E13ABB92CF716123 | ||
287 | :151776001B90A70B1DB60FE3E0DD72AF86386CA19A57A738EAD9 | ||
288 | :15178B007C79756E475D795E5DA9A36E812AED48204577F72309 | ||
289 | :1517A0005D268F1F667D8F380BDA7BE6DCDF88338C69E058640C | ||
290 | :1517B500FD8D98217C8BDCDC45A266737E547F75BBABAD8E9F57 | ||
291 | :1517CA0067C09C7AF516428A0E361AC9CFD31E5843EA53F054F3 | ||
292 | :1517DF00802798FB87FB643F03997A3EF6C77A726984BDD79F79 | ||
293 | :1517F4008DAFB70EFCFFFECEB7104F0DD0CA423DFAEA3B9555D3 | ||
294 | :1518090076EC09E339A4DB7C7312CFA274C7DE9CE2CF495CDB6C | ||
295 | :15181E00C033F9668A9F5101FFF25EB157E2F039A98B8C9F43E4 | ||
296 | :151833007E52807D39C4E339D2CEF6839D1D053B0BCFEF8FEA65 | ||
297 | :151848008277D59C77B6CD8D7D96F6106FAFCE3E93FC8BB8384D | ||
298 | :15185D00FF50FF35013C13CA3FBC53B903F1EDB957CC93DDF0B5 | ||
299 | :15187200447F12734E79CC08FEAFCFF137E36CCD771C7335E3A0 | ||
300 | :15188700FFA62CEC2BF024217992903C49489E249027C5B09E3B | ||
301 | :15189C00BE16FEE15CF26A4B0233B5BEC04BC58257A2EC562824 | ||
302 | :1518B1003B1018CB295B01654381E3765929969541D98D8149CF | ||
303 | :1518C6002CE3FBEE829F7A0AF8077C6C4D4DE7E3A53B89A721F4 | ||
304 | :1518DB00857CACBAE34FDD9FFE02F25024E5610FE03DDF9C4B45 | ||
305 | :1518F0006783423C473F853903B4BEF4E9745A5BE11BFA29D2CB | ||
306 | :151905005AF3AD69B5E391DF86DEED05E82D96F49E015A1B9ABF | ||
307 | :15191A00A7CBAF8939BE0564F7E38B694F11F4E3838BD3FB616C | ||
308 | :15192F00029CD317B11FBE6BEA47E63CEEB7EC4F5781FE28B23F | ||
309 | :151944003F5756114F17FCBE0BFEF73E813E69554CD56A18D73C | ||
310 | :15195900FDA0F35CCB09998472FCAF9056FA21BE0774AA017723 | ||
311 | :15196E00166886A56A2D2F22FE08E899B511DC0F8C51DC35426B | ||
312 | :151983009B98A262AD12DB0FB65831C11EF6F3FD2C0AEDCE4436 | ||
313 | :151998008E58A51DC7ACB512762F3CD3D79B74233C5DE2BFBBA6 | ||
314 | :1519AD00218F9E06D95687E746F0357D9AC04774810FF120BED8 | ||
315 | :1519C200E833B9F81640BBD28E23D65AC0F7E10501C327F17D8A | ||
316 | :1519D7007C41E083FF6E273F55C9CFA34D44D437919CFA39B6C6 | ||
317 | :1519EC00FE93F59756E6D6CF95F5DB65FD0779F5F364FD5A59A5 | ||
318 | :151A01007F9CD7A7A8EFD9ECF9A334F491913E1DF790DC68A32C | ||
319 | :151A1600F3CE1BF5833FC4F0CC47656C7333EE2F997D75959A13 | ||
320 | :151A2B0012D4A53E1BA838AF3787F6055B1DF1DCBD273B7E8D0B | ||
321 | :151A4000BC7ABCFBFDE680A3FCDC0BCF5CC1F2959B7FDDEC8CD9 | ||
322 | :151A5500FF9E7DEBA72F63F983FFF8AB665289B1C761DAFBDB56 | ||
323 | :151A6A00275A7C7E7373EC87C433761FF14CA3D391AF9B7A36C9 | ||
324 | :151A7F00D73E0B5F2365A10E7179C53A8C97A9B97DB3FD236C72 | ||
325 | :151A94003713647D3028721BB0ED40DBB83E33725F607F1BD7AA | ||
326 | :151AA900E5CCB47539D4719D0F3079591E3C5C6F52B02D5D5C15 | ||
327 | :151ABE0086ED35183306CD2A1DF7BDC16FF4F457C4F4BBC89216 | ||
328 | :151AD300A0972CA99BAFB98298233650C1F4756655F0BD0C5F2F | ||
329 | :151AE800C6F83EC46CCE0FB6177D9412F0F546F3EA3D8E7A059E | ||
330 | :151AFD00EA7BB37CED2F5248BF1BEA5DB5307EB2CD7C6ECFC40A | ||
331 | :151B1200B7D741FB8DB2FDF740FFFBB592805DE787BA0622E42F | ||
332 | :151B270009FF2F3C3B6254C3FFF98E360BCFC60D5F1E3DF7C0A8 | ||
333 | :151B3C0038252271CB0DBAB6FECBB4277625EDD9FA557A96EC0C | ||
334 | :151B5100DFAA49D0D3203F397AC527E574B491F079134A3E4B1F | ||
335 | :151B660093256416CA19FAC136EC27619E610C4775D0E5AA8842 | ||
336 | :151B7B0019C723DCFED2808C3FEF01B8D5C0FFDE45C493AA12E9 | ||
337 | :151B9000B27FB20160CB7D72226DF99364980E4E8EEA336F4273 | ||
338 | :151BA5009B1EA0C297D5E43E6D35C576459EB8F1AF8B7E50EF22 | ||
339 | :151BBA006B8CB1062BEB6F45E0BD669090283C1B9E23C484E70C | ||
340 | :151BCF0065F895C3FB65F885E0C79E13FB5D08A7F53FD29ED399 | ||
341 | :151BE400B82693FFDDE7D39EE3F89F8DB079303E181BA8E47B6F | ||
342 | :151BF9000929EBF4FD843C87B6818D58367FED75C669919FC22E | ||
343 | :151C0E0061281AC6285EC77C7A9ABA8F102FEA228C9B711FF33D | ||
344 | :151C230088E56AA306EE2763EC8AE7CAAB23B8B75AD6E4A0E3B9 | ||
345 | :151C3800AC9BCCC2D82AE2C7734FB857B100EAC73CD25E713CCB | ||
346 | :151C4D000798CA7535A326FC5FF05F609F501F89FC8B0C2D99AC | ||
347 | :151C6200B39958F63B570AF0F17D3CC5F18E7B97F63BEE59F2DD | ||
348 | :151C7700B80FFC1F73C4B96C783E76C4405D904A5FCFE71EC6BA | ||
349 | :151C8C004486FEF9282F23A9EB89EFDD51F10E7F701CB36D6341 | ||
350 | :151CA10016C65186268FEA650ADF43B1447C2566613CA5C94103 | ||
351 | :151CB600B7D8BF1CA60F4C3D30B5787234472E67A35C227D20D4 | ||
352 | :151CCB009BBB6F271E1EAF0C1F61E8F7EDD7560510861B73A2DD | ||
353 | :151CE00022A798163941FDFC9CD3179697E700279862EF075FF5 | ||
354 | :151CF50014F916FC5C82DAC3F74C791C397CCC7A5CCEC76BF51C | ||
355 | :151D0A00279B1CFCFA661A246E3CAB84F80BCC81F25560EBE5AC | ||
356 | :151D1F00FC60B8F7AC522E5764B288801D328662CA263C7B40E5 | ||
357 | :151D3400EFE5716FBFBD6E9B43460CD46BC85B2AE9C3EFCFDEF8 | ||
358 | :151D4900463CCAD45386FAFE53BA5347E2792466821EE76BBC5A | ||
359 | :151D5E007E9AFEBBD30AC626152EFBA6581F4D017FCCB87E3379 | ||
360 | :151D7300190DE299C5D496A3CDCE71B94EEA8BEE159C0779F150 | ||
361 | :151D8800175CBFD9704D0E374D4ED2CC99447594611CED7B66CF | ||
362 | :151D9D00BC20EC191276F90A92B38F9B858F79A4FD745FC5B0E0 | ||
363 | :151DB200CECFC7838E45FA63FCEC42DC5C8CEB03C0519C1C3729 | ||
364 | :151DC70095E409D35D1A37704F7026E09B1B66862B42E9A1A492 | ||
365 | :151DDC00B249D17AE90DEA2F8D33E9B4DF1B5382D9757098A279 | ||
366 | :151DF1005FBBDB85BAB015CAAAF9790D9EAE8B3EC3FD620D515C | ||
367 | :151E06008ECFCA06983B77BFC8D75A01ED4D727F017AC13E46AC | ||
368 | :151E1B000EA37D1CE6F6715FC549DD3BD9773BC737A5F4B2C6FC | ||
369 | :151E300031417B386E7AD1DF93E54591B8A9362678FF0E9103BC | ||
370 | :151E4500BA05F2EA5E07F38DC5AD9BC51955E68A8C67FA3737FD | ||
371 | :151E5A00341AB4BF15FA2AF33E8D9EF70E67F371F7817FE13540 | ||
372 | :151E6F00253DEC2AF440B90AFA176971E2748978EADE9C3334E2 | ||
373 | :151E8400A82741C648E549B18F20FD33E09DE08FC82DC8E5A33C | ||
374 | :151E9900DAF762CE7E3DCCBDC806EC036BC7791A4A1EDE5B29A3 | ||
375 | :151EAE00D681E683503E188EE96EAFD86B4B024DE78B4D3CA3AA | ||
376 | :151EC3003E0BEB03EB458E0CDAB0C572EDD8CA6564CCAC833ABB | ||
377 | :151ED8009B764E37B46F58CFFD6C1EC75F2BDB353ADAB5245FE1 | ||
378 | :151EED00DD0B3F13CBA3EB798CC4C43831F605D7AA48C7E05399 | ||
379 | :151F020071DD3729F704A1DCC6DB25E1FD5501BCBB1D78B7CB1C | ||
380 | :151F1700763F71B4BB0BF0623BD3D12E2ADBF514A0EFAEE41B6C | ||
381 | :151F2C0026CEB17E4EE3DF9B685FDC408B0AF43DCF65679CEF03 | ||
382 | :151F4100430FFE13D04AC4397EB783D66E097BA000ADCC41C374 | ||
383 | :151F56006ED9EE50015A871DEDF6C8762F7C0DAD38C636ADA5E6 | ||
384 | :151F6B00DF406BA983D6A484DDB1613AAD5D1BB2347C2CDB6D89 | ||
385 | :151F8000DB7095F1DC901D4FE52AE3A938F09EB7C7B300DEDD56 | ||
386 | :151F95000EBC17ECF1BC0ADED68D38BF2690074C75E2C5FECA8E | ||
387 | :151FAA00FB36B0DC96F935D0FE308967647E638990F92B2E21E2 | ||
388 | :151FBF00F3A18D59DCE11281BB65E3D7E006BC3E89D7C6E77309 | ||
389 | :151FD400F473A384D1561806C3396BEF7597E7EB3CD02FC75F90 | ||
390 | :151FE900CAEA3B3E9FF95D0A4719B767784F8E7A9CA11FE92EF7 | ||
391 | :151FFE00ED33F6815FAA826D53D79E32CAE909E32021739C3A1C | ||
392 | :15201300E86FA05F85748FFD9DDF15D70F9BE33ACA8B88271E8C | ||
393 | :15202800D0613DBC17D7BF77715859DBB01C6015815DC8E8D5B4 | ||
394 | :15203D00D0B8EE5E17E73A95EB53DB5E98A84FE35C9FAA6D40B2 | ||
395 | :152052003FE85197E33DA7BF9598AF31ACBB2A9881E7F178AE2F | ||
396 | :152067008CB0F9D23625047E26F5697848F8946063455F46F90A | ||
397 | :15207C00F9097E3E08ED52641CECD23B863B7682A26D2A684F28 | ||
398 | :152091005ECEAE1F193FC7D46BF8319C8E7B15F2FFA5747A5E1E | ||
399 | :1520A600FE5A52EC77F278BD359C02FDEA81B915AEA12CD41386 | ||
400 | :1520BB00455DEC2E163A59917E7C293CA37F486772FF588AE7B0 | ||
401 | :1520D000E79539F3C6944671EF4CABA31D5EF893DF0E6DC2F3A4 | ||
402 | :1520E5001A9E5B3AC910CE83987F510BFF8167E877BB2A13EDD1 | ||
403 | :1520FA00587F4368D4B821F40ECA8CD5CC7345C618C2C372FF1D | ||
404 | :15210F00E6B895FDFF8EC1CBFE3A8E3E0BF1B38421BE7F076D69 | ||
405 | :15212400BAAFC8DB631CFF324BD3608AFB4D0E9A12B4991C5B1C | ||
406 | :15213900E9D75C011B37DEBDC3F34230FF1ADAFB6FFCC2CABCBE | ||
407 | :15214E00AFFA228327B9F058535126EF07D6AB320F1BE92ABB9B | ||
408 | :15216300310E7EFE10B3F819D31A3A07F87D3BB24315B044DB21 | ||
409 | :152178003186FC07B368A9EAD330D6C7E19B414BD18E5BED0E8D | ||
410 | :15218D00BF12D6DDE411AD64E5844BAE8B0BE05983BE4B41D8DD | ||
411 | :1521A200555689FA16C09EA0840D594AEC94856704C4797E691E | ||
412 | :1521B700BB51BF15CBF98B396DF25C0091759305FD19915B88C8 | ||
413 | :1521CC0072746106D29560ED226798B9257D6E271D682B8B05AC | ||
414 | :1521E1005C7F30415522CF2AA8C72CA443FD6889C56D51868E26 | ||
415 | :1521F60014ED8A65E51BE11CBD4FC0194C09F8026E82F3A7EC3D | ||
416 | :15220B00A33EE68235223F8347C6753C138F3EB0F82661619B93 | ||
417 | :152220009C7900F03F8C65FD1FBBDF083F719FE89FC0339683D4 | ||
418 | :15223500C7DE73C0B69C8F49C1C71B36F75AFE7082D7259C38A8 | ||
419 | :15224A0033E7914354D0D24055CE975679875080BA653E202FCF | ||
420 | :15225F000F8FB28717A1EFFA0ACF4773D2E07B7909738E1DB4DE | ||
421 | :15227400B114F508C6FE992D27E80BE30D65CF935E9DDFD31477 | ||
422 | :15228900A69C2FFCAC05D42BD05FD660525C841797F61AECC022 | ||
423 | :15229E00ADC607FF96F690A911BEBEF7E118A96F1A8A768AF9BB | ||
424 | :1522B30023E24E017B0D535E3C7D1DD5D37624735E3EB39E9A77 | ||
425 | :1522C8003A66DD7EADEBA9F06B962D539847365C22D6BDB93243 | ||
426 | :1522DD002564086919967CE163128C7179E2EB5958C7A33D4393 | ||
427 | :1522F200794219E0BC32C51AFEA5AF44AE52A1F504CF1B0EC06E | ||
428 | :15230700DC6717E83C7FA01DF767BCDA92FAF7D19EC23AFC1118 | ||
429 | :15231C00EDD6E0659893CB93BE55DC36DE2FF37DEEC74B4F0E1C | ||
430 | :1523310070B9E3F960A2DCC2F2F7E4FA3622DB46F3DACA720B9E | ||
431 | :15234600CBEDF3B836FC5EF9CD60DE37B2DCC2F22E09BF5FB607 | ||
432 | :15235B008DE5B595E51696DBEBD4C512FE6AD916DBE1FB028718 | ||
433 | :15237000BE6975D4E13B9E6DC2334D6E90A362B0558A36622134 | ||
434 | :15238500BF1475BF81E31DD046F19EA9B9734343CD0AAC57CB16 | ||
435 | :15239A007A2E18A5DA116BBEF94993BFE55343891CB75E8E95C9 | ||
436 | :1523AF006C72C39A0BECF1BC9991192B95C805CB96D999A0DB1C | ||
437 | :1523C4009257709F2E3B077E0A3652E1E746D8B4F928E757464D | ||
438 | :1523D900AF200CF5E08831583CAA236D73375759F67CE632C014 | ||
439 | :1523EE00CFE58EF3BB8BF8592FA147ACFCF92CF2400127CC19EB | ||
440 | :15240300E73C796A76AF91F8ADD84754A54EFBA679F27480DF1E | ||
441 | :152418008D23E6C8C008CF89518BB3F98F8B31F7007C8D07F85F | ||
442 | :15242D00DE7E36AEB50EE4CD67CBCDFF36BEE9984FAD45FF072C | ||
443 | :152442003A3ACF9F086B23ACC4DBC7F9F912C06BFAD4E10B5CB6 | ||
444 | :15245700CCB3BB400BB611FB20A6C5F7472AC7DA4B0EC68D21C8 | ||
445 | :15246C009015B5294E93220662B9C57E29BF37096D33D66BB0B8 | ||
446 | :152481006E4FA17D97F0307EAB4716B1622FDE75D743272F66C3 | ||
447 | :1524960071AB05FC107704F0F23D0AD3C2F11A02BBAF4E8CD0AA | ||
448 | :1524AB00CB12278E6F0E4EA877E7E1CCED7F75FB4607FE900352 | ||
449 | :1524C000BF5600BFE2C0BFA000FEAA6BC48FFE456F6380DAB4A9 | ||
450 | :1524D500200D139F081A1600AE7CFCEAC4118E4B8B8CC0DA3C30 | ||
451 | :1524EA00D10E6B6F0B7D1F45E377CACC5B101961CF83DF833679 | ||
452 | :1524FF00ED92D3CFC1589F5A65F5B65103EF74BBF46455338FA4 | ||
453 | :152514002756DFB4B4AA6D6B50FB6143E366ED9EBF587FB7B6A6 | ||
454 | :15252900E127BBBA3B1FDDA5ADEFDCDED9B1AB33A8B56CB9679D | ||
455 | :15253E00C7CECE8D5D3B7EFCA3AEEE2DF5CB6E5B16D0AA1FD909 | ||
456 | :15255300D5B56DE7CE1D8F6DE978BC235457D75877DBD23F5BD6 | ||
457 | :15256800AE3DBC6D7BE72E2DD0585BD750DB7807BC04EB03C11A | ||
458 | :15257D00FADBB4AA4CFCCCC6575BBBB533BAA3BBF6A11D8F4646 | ||
459 | :152592006B3BB67644773D51FB68C7B6C76A77ED7CA8B6735700 | ||
460 | :1525A700B4F6E1276A3B3AB6F3B2ED3B764497EDBAA96E857601 | ||
461 | :1525BC00ABD6B9755BB7B6B5F3E18E1F6FEFD61EEAEA78EC478C | ||
462 | :1525D1009D5AF5EEEECEDDDD4B11CBB783BF75E7B6C73B77D624 | ||
463 | :1525E6003E0CDDDAD2D1FDE896AD3B1F5FF6D04D2B1AAE063F10 | ||
464 | :1525FB00039E9F6799E30FB7EFC77D42B58ACEF537B4576BF5C9 | ||
465 | :152610006C199EE5B1F3F423CACA85FA05E350E870B4880CD334 | ||
466 | :15262500F63FA63379FAEDDABDD67FFECEB552517F6054692D59 | ||
467 | :15263A00B40AE6DE39D0253E78BE85BA539ECBEEFA22ED797785 | ||
468 | :15264F009112DCA81D613550379F8C3787B401C6EBC3CAD30165 | ||
469 | :1526640028437DD3E428C3762AD8408069F56BA5AB6C9B500E21 | ||
470 | :15267900BA710611BE04FEBF02B0F7A9CF44D14F1CFE657A16F7 | ||
471 | :15268E00D2E5CC6B77E6B4C72E8B585C1F6F5F4DBBA03D513FA2 | ||
472 | :1526A300B77CF0CD04E68D39F0B328E1676797B9C85CA40FE9F8 | ||
473 | :1526B800F069C718F66106AC53317F8E4C2DC538ACCFDF72AB4E | ||
474 | :1526CD00817DC77B164BFEA1D1C02B54AA0096D8AF3A44C3DAC6 | ||
475 | :1526E2000BB4FE6DC00DFE940FBEB7F1E0391EBCB301CA2C2721 | ||
476 | :1526F700CE35E934C7C9EF6D04FFEA783A3DA732E2127B6AE153 | ||
477 | :15270C00017A1DD80584997C0BF3660350F60AA7AB04ECE521AB | ||
478 | :152721007E6FC47EDC972BB3C7CD3E6311FB038EDDE77CEC30F5 | ||
479 | :152736007EA36930EFD4BE845B5B6195B41C85F13EC061E33C5F | ||
480 | :15274B00C43958AABD6CD57CE56ACAFAAB620C6C7E3BC7C1F730 | ||
481 | :152760004EDAFD75F5574EA66739C703E951811E9F63BCA211D6 | ||
482 | :15277500378D257F65A920875A722431D7BF1BDA76515F7211DD | ||
483 | :15278A009B9D2CDEB43AB914E435DA8E776AE01D89782F0E0997 | ||
484 | :15279F00DF4DDF55709DA453F465947F79D0C07B36D662FC4621 | ||
485 | :1527B400C533BB61EE8B0E9ACBF5D74275ABD66845ABDE2F396E | ||
486 | :1527C9004FFDA15BF83E63EFEBE959975C765ED6009B9133FE04 | ||
487 | :1527DE006B29DE5D89EDDAA1DD19D92E906C01B8ADD66A11DF97 | ||
488 | :1527F30048F03B29E5B326B2860EF0BC9145D485F77F014FC4CC | ||
489 | :152808009D94B9CFBD2E71278EB8E76B047CE95AFD52B180EFB5 | ||
490 | :15281D00A523C603DAECE05C6D76DDEB8BCA82D6E21B83A7B1E3 | ||
491 | :152832000EE3BAE3E9598B355790D3A90E50DC8376C3BC3C0DA3 | ||
492 | :15284700F320137F9B7A45D8E7A957AC9F5754EB7CBF1874E630 | ||
493 | :15285C00A0840FDFF3BDD47E8065B7B5DB6D873607DBF0BEB4B9 | ||
494 | :1528710012DE07DCDFCDC7A57F21E6512B7CCFE358324E77F2F6 | ||
495 | :1528860028C233D982D251C3F7DF87190A4E6B12CF389FE7E720 | ||
496 | :15289B00A9ACD0ABFA10C09D5F5A632C07BEE2D9D81A729EF631 | ||
497 | :1528B00086DE88624C2D896B83B6A5860563751DC84EC99E710C | ||
498 | :1528C5008AB90441DCFF507F21C646CE65F4A915BE2ED380AECD | ||
499 | :1528DA00503BA75FFD85357129ED395A24FA79178C75538131D3 | ||
500 | :1528EF00857575597E9F7A2FA5790E09C2D92EBF9F0F73AE6456 | ||
501 | :15290400CA34F0BEBA2258A784928729FD4DDA637F8B730575F3 | ||
502 | :15291900E284E43BC66F911701E083DD6618EAF83B7B864652D2 | ||
503 | :15292E006911EF8436A54773798F325888569CC7E5C91EE6FB92 | ||
504 | :152943004CF0FC83BFCDFD6E02F98F72CE75C37E6AF37A1078EE | ||
505 | :15295800DD9A1CB1265E933E80B3DFB83724FB4D7F2FFA8D63CC | ||
506 | :15296D008FF0A200AF468E1997CD51219B788ED6D576B71186B2 | ||
507 | :15298200FA9B6DF9936321F89885D1F07B416B1464E2E3D78499 | ||
508 | :152997004CCC2FAD37FC23AEA02D1B78CC3B2AE2B952364EE849 | ||
509 | :1529AC00E8DF2D262756A15CF81A135C1E2C73B1EE1E386228C5 | ||
510 | :1529C100A073174B3910FB02B9E37E12F8EC575F0199EFA15EF8 | ||
511 | :1529D600900B5F4F9D91BA28F96DCF07C737181B2FC4EF6538A7 | ||
512 | :1529EB00DFA13DE7793E1E984F9837649F7FB9CE211BDD201B4B | ||
513 | :152A0000D13342365C781796940DCC8343DEF01C07CCEB782D44 | ||
514 | :152A15003B7E086F76B8CBD0FFFD2FEB41C759D5C936AB2AD9BA | ||
515 | :152A2A0062819EB3400FB202F909FC5E665CEF946A553CC61AE4 | ||
516 | :152A3F002BB00F06FA9BCEF00E1891728C1B8DB5A3DFE6F28C47 | ||
517 | :152A540018B89FA6CB73D6E8833FC0F79712FCAC18DFFF8275A5 | ||
518 | :152A69003B9E0FFB79C54958ABC6F95E981AEBB3300F7275EC6C | ||
519 | :152A7E0014F7FFCC581C65729EAAF559ABB553168367191B3372 | ||
520 | :152A93004E6BA29E2C8AD38FAFE21FBAC984E723A5B9F8B1A2B3 | ||
521 | :152AA800CF5D3F73FD4F7B4F1B1DC575DD9BD5AC342B0D627676 | ||
522 | :152ABD00D95D495848232C12C9519C5DB1C8922CC242A88FEC13 | ||
523 | :152AD20010654B9D744612F63AB603B19D84B634C7E784C42B00 | ||
524 | :152AE7005889058FF03015F65A266695480E6E209539909014D9 | ||
525 | :152AFC0092A5761C9152B2E1381C9AA4F638716C9AB8B6EC6293 | ||
526 | :152B110087A436DB7BEFCCAC56027F25ED39FDD13367CECCFB72 | ||
527 | :152B2600BEEFDEF7EEBBEFBDFBEEBB95BB86F37317D82FD98F5D | ||
528 | :152B3B00D9F7D9636C823DC40CB69D6D619BD917D84676275BBC | ||
529 | :152B5000CF6E6537B33EA6B04FB0B5ECE3EC63ECA3AC9B5DC784 | ||
530 | :152B650056B3556C255BC196C38CB29375B076D6C696B1085B45 | ||
531 | :152B7A00CA5A599885D887D8D5EC83AC059E0FB0AB58333C4D64 | ||
532 | :152B8F00ECFDF0BC8F2D81A7119E2BE1590C4F033C323CF5F4B3 | ||
533 | :152BA400D4C1B3889E5A7AAEA067A1FDD4D0536D3F558527687B | ||
534 | :152BB9003F81C2E32F7A16143DBE598F77CE235DF2CCBFE4A91D | ||
535 | :152BCE00BCEC33EF2D1FF16D9F8A777CCADFF5E379C747C0C3D7 | ||
536 | :152BE300535AF6BB963D6099CEB280EC52D7DE1F63F241F46BAC | ||
537 | :152BF800043FDDFE6F82FF9CFDDF02FF1207FFC863EA9A207EDC | ||
538 | :152C0D0054D359B7968349B2C4299A242F3E28C5E1CDC06B2E5B | ||
539 | :152C22003E487602C97E6C13D9BE9365DBCF63FB71E017B7FD26 | ||
540 | :152C3700CA6D3F17F8656CBF0ADBAF04FC303F2893CE264A2C4B | ||
541 | :152C4C0016B2F342BDE2909D07EA1187ECB4A8371C8234310E91 | ||
542 | :152C6100F768656DE3B751D0BA4A83D9F6A81BE41AF48BD1B952 | ||
543 | :152C7600FFB0EECB70ADC25433F081865161AA83EC1B26DE2674 | ||
544 | :152C8B006CF26DC2C81E0B84554218F81BE8CF9FE850A9EC5CF1 | ||
545 | :152CA000B3E1E0CEC139D62367C3983B4234D1659A8787749C89 | ||
546 | :152CB500F731AC27A509F5237E118792CB8A3F99B5C3813776CE | ||
547 | :152CCA00C98B0DDDC9E7B8E51F837831E49BD262831740067A12 | ||
548 | :152CDF008B6F8C9B89932BFA975C33FFBAED4FF8CFE6E7A36DBF | ||
549 | :152CF40009EB3CB7AC4D93FD5BD9D2E720DD4999743D4AED7F28 | ||
550 | :152D09003A37EB82B686F66043EDC03B5D2CE96A37CA609ECA75 | ||
551 | :152D1E00473BD4E9860E5A9F9BFEBE7B19E204DDB8469A857495 | ||
552 | :152D3300226B471D6CA30570018C5613E456A38C5D05B05F65E1 | ||
553 | :152D4800B883D1FEDC65FC24CEF263F2AB06F2DAA6B96B14217A | ||
554 | :152D5D0059273F6CDFF0BD49E65A79A099941868E571BE2C35E6 | ||
555 | :152D7200A03D4A18CFC35064BBDE42EB5061834908974CB0C425 | ||
556 | :152D87005CD55046B38EE5F353D5AA94688EE0574834B7E23778 | ||
557 | :152D9C008675CD8548A6C6B8D48ED15E6528A425A84FB46B511B | ||
558 | :152DB100D26D8AA27F3C3FBF1BE2C4C88E24CAD0D659D8B8163F | ||
559 | :152DC600A573001BAC33B1A18D961E14BBDBBE272065EB48E02C | ||
560 | :152DDB003AEF7C002A09F397A4AEB3A482FB3DE87E7505BF8CF3 | ||
561 | :152DF000E5B6E8A2CCB7B2D856FD3CD62B27EB96DD5C4B6FAAC7 | ||
562 | :152E0500C52C69A53C213F5A57C2FFD8889EAA49281CD9F31C8E | ||
563 | :152E1A00310A7A20B11FA4B17EB5F2FD3A2F9F30989E84791408 | ||
564 | :152E2F00BFEC9B377F13F27F328DFEE8D7027EA373FCAAC16F26 | ||
565 | :152E4400688EDFA6150097F47CFA7337BF1006815913E5A7F5FB | ||
566 | :152E5900BBD99456BBF205B5B7FE99F043EDE7ECB316093A3FF3 | ||
567 | :152E6E00BC287106EF0EA075B3452B4FA97C665C77C1B828CBA6 | ||
568 | :152E8300DF4A33FDBC21A44668AE836B6D4276775B10E7515087 | ||
569 | :152E98000ED3BF615CC1BDA0221ECAD933E1C99B5F6A031880EB | ||
570 | :152EAD00A64F035CA7744EDBA93EB4EE79ED8AA806ED68A70154 | ||
571 | :152EC200384B5C5CB13A2C6C87F2625B27D9BE52B42D3E2908A7 | ||
572 | :152ED70068EB74DBA8D0FD02F83F306AB9BF6EBBBF3D3A95CFC1 | ||
573 | :152EEC00073217E75CF311FB693AE99AD2116F77B3AC96F85E05 | ||
574 | :152F010069EB97BF5CDA8AFA10A3B9879485A71F504A4E3DA5BB | ||
575 | :152F16005EC7CE8417668FA964672DA4DB76067354D780F4F77E | ||
576 | :152F2B00EAF95B9E3616724F42F81943481C68C3392CE63D7D7E | ||
577 | :152F4000CB295DC894B61EBAA77419CA26C447A4B18349570694 | ||
578 | :152F5500E87C58C7BAFC61EF6024781CF2967EAD617D24843B52 | ||
579 | :152F6A00F6F8A4807B23D2B68312C1FFC383CF431F2C978753B1 | ||
580 | :152F7F0068DBBA4C1E4CEC4A680AD7A3411FFDA98E3657E38FD5 | ||
581 | :152F940031769F80FB095A6ABAE13503E2EE78496E591683F8DE | ||
582 | :152FA9009BE3AB5B518EA1BE251DD0F9CC578047BA5BE3D9FD8E | ||
583 | :152FBE00AD4C3FAC4F63DB8370EC3F6BC19FCF1C80F63348B612 | ||
584 | :152FD300299A6CDB31D4D7F461B20BDF44FD0C64DBCC30F4B3E3 | ||
585 | :152FE80084C6036D25A645F02B30AD15BFB85F266476431E596D | ||
586 | :152FFD00B2C55A9D49EA9C00380A65C9862AB643EC1FFBA6308D | ||
587 | :153012006CDC88A1CC9D491A572534F2CF803FBA512E9C6ED029 | ||
588 | :153027007431CEB77A4176C47E32DD306E2C0C66FA8F5E742F22 | ||
589 | :15303C00035C1A536FE40509E0E98232CE60BF0AA5B52CF0E088 | ||
590 | :153051002EC89765F6184F15CEF7A47411301002E09E1FD42243 | ||
591 | :153066004C3F9EA67929F0B3EDD153CAE9DB4B5BD36C504927FD | ||
592 | :15307B00762B171BF965E9E8B052951C51776DD5945D1D6749C3 | ||
593 | :15309000B694CCFBD39D4BEAAEA13DA3506212D762BD8B92B8B7 | ||
594 | :1530A50027A8D766A84ED69AB680F67513B466DDCEA32CFDBCA3 | ||
595 | :1530BA00CE75A38EE113C6AEACA6E07AA190D903E9B6219E69A5 | ||
596 | :1530CF006FAFDABCDFA8351F369A0037B550D75C298805108ECA | ||
597 | :1530E400FDB349DE46B63C280F49439B4E42B57C9F4E36F7D6B9 | ||
598 | :1530F900691AA4D39137F0F1437AC4FC1EC4DD66A00D4E616AB7 | ||
599 | :15310E008F8A79BA4E4E908E5AEC71C66A70BF3F74846C05F0F8 | ||
600 | :153123003D432AD469D4D5B3534D95B1D9FD23876BFB29ED8BE7 | ||
601 | :15313800FFC6FFF0618EE8427B1E7EF311D203A45B7670CD1FF4 | ||
602 | :15314D00FD5892F4B5B0CED6FE478AF63F8CEC88526D0EA543D0 | ||
603 | :15316200E6231969A5A60AD76B6AC91A4DE565CD1005DCD3DEE3 | ||
604 | :15317700A3354577B7E1B9B1C000B41F98B75627D07DD808DA47 | ||
605 | :15318C006E3CD36EF1FDDD86DF145BD18FEC8D16F643D2B4E610 | ||
606 | :1531A100EF42DCE446F446A28375C69963FB34D4CBB6CE365B69 | ||
607 | :1531B6007720FC02F2E2D6A0CE5E86E8C7A50EA8C14583C60317 | ||
608 | :1531CB0051EB5C2CAE9DBB7A2CDBCB3716D921E03EAA912D62AA | ||
609 | :1531E0000969AB7FED20D93284FAE33A346F022FCB9D277C7B31 | ||
610 | :1531F5004DBE57A4B9439AF6195CA46B6ADDB101F35C03ED4235 | ||
611 | :15320A0021BC9CF945ADC95C102EE6F1C8DB918EC4DF0BBC1DC8 | ||
612 | :15321F00F8FC86D25EBFF9BA4176DBFE11DBE190B1E5CD7CA012 | ||
613 | :15323400E54DECBB162D10D77E73A7EED246546FA7B5D7EF02FD | ||
614 | :153249001E81F7CB886C64A9086D65211B09231DB5A236AA591F | ||
615 | :15325E00F4D2D3A4F375AE9FDA18D00FDD3CB3F45F5336DD9182 | ||
616 | :15327300CE9806DD48D7B934251AD8F478271CBF5B5AFD4FD299 | ||
617 | :15328800A29C6891B6F7796668F28EB4281A6B1D3AE8DF477B45 | ||
618 | :15329D005995A1629AF8E2EF0F93DDEDD8C0E4857BDEDF26C538 | ||
619 | :1532B200CB605C1DD0D1B636F2AECD5F2C6D9DFA2F871F59FCB0 | ||
620 | :1532C700A31A68E65BA4191CF04DA421D6D5DAF3B1CAC0F230DC | ||
621 | :1532DC00EFC2B9A882BC64D1A5A688269B099E94657705C27175 | ||
622 | :1532F1005F5132771A9C9CA4F6846EA5C8BE40A4287DE4930561 | ||
623 | :153306007D5FD2134EB309D2DB6C42DA0F4C28A2EC26DE1C225F | ||
624 | :15331B003D404DAF895ABCA8D00FA1CEDC061C8FE17BFD29C2BE | ||
625 | :1533300001F45B7FEA0F567DCD39D76CA18DFBEA60AABF06645E | ||
626 | :153345000199650E8658F660949907AB7F9BF7C07712DC93E0AA | ||
627 | :15335A003FD96DA77FABF8CAB9D9F1ABEDF838AEEF7FBDA84C2E | ||
628 | :15336F00D4C780F947715AB2CF45771668FAC57BF8655DB87E3E | ||
629 | :153384002E1F4DDC37754C2985E9062F8FA4D04E49B9FC448ADD | ||
630 | :15339900EC86D37E5096CE544AF22198B72475D15CD27AE3FDB6 | ||
631 | :1533AE00790FE2417B30EF999B67316CA4770869BBE407F5F373 | ||
632 | :1533C300CF6A2023E96403C56A877F6750DBB56CAD4CEF0279DE | ||
633 | :1533D800B115E4A2F7D236A79F1DD193AE94CEF6F1BDD3CF6A0E | ||
634 | :1533ED0046D29536BAE45DC6EB17B17F24ECB9C980F11CCA42CA | ||
635 | :15340200407FDC5F95A18C629C5C787A363E717FD796672D5DEB | ||
636 | :15341700687D8F8EB23307FD0BEB086E63F5DF82BC188A914D54 | ||
637 | :15342C0074279FEC8F67F2697C2D2FD4E2D9A16035C8F103FAC1 | ||
638 | :153441004928F36E16D798194AE3BA986836E9A5C7C3EAB7121E | ||
639 | :15345600CDE1C1F6F659B26519C375E276EAF765DCADC067AE49 | ||
640 | :15346B00D765339666D22B862034A8B8D66CC9958BDBCA61EE8B | ||
641 | :15348000E2AA53A80CB4878769DC0361B5321A8E944399FBEB54 | ||
642 | :15349500AF6DAB3565181B9BF46A33A47362A73AF895B0E6CE17 | ||
643 | :1534AA00C23C31D76E387788A0EE07B374D041DE6C0CF3B8563E | ||
644 | :1534BF001DFBD424D36F191552B87FF857F43557B896CDACFF5A | ||
645 | :1534D40057DB7A174D363F0B013F6B5750AEF7C95C88E62A504F | ||
646 | :1534E9000FDEB11D937B64B226BB47ADB1EF6FF0C3388DE3317F | ||
647 | :1534FE00CB7DC7F072CFA9AD0D95D7B0BAA97EC6CE6912FB759A | ||
648 | :153513009B9F7B59DD29BB5B51560C01AFACE526D440F048BF54 | ||
649 | :1535280010FDF5D25AF8BA4EED26BBF4C827AB56A26EC011FBD2 | ||
650 | :15353D00BEA1843605E3BE2F7158F5D682DC52B0CFFCCE6F157A | ||
651 | :15355200C8E6F84DAF288BF8E2653067F98ECECC470E8E83CCE6 | ||
652 | :15356700556BDEAF23EFC276817BD85E18AF9FAA19591A05598C | ||
653 | :15357C0007C7A14FB875926FFEE9412DECC8346FBC997F4B99EA | ||
654 | :1535910026FDFBFC5BCA34ED6F25D3C45ED04CE77C39F21CC0B6 | ||
655 | :1535A60095D0707B5B39E93423DE8EB5F98FFF07E47F4C5B0B28 | ||
656 | :1535BB00B87BA05D776C76109E828943053C05CD2561E11CEEF2 | ||
657 | :1535D000296D99E44F1C437E1D5C68CE0B835BF79901FA969B53 | ||
658 | :1535E5008BE8AB035FBF5CFD619C8DB8BA5F564F5EC80B880779 | ||
659 | :1535FA00AC6B8B5D7766D7BDF63275C734E90BEFBDFE8B80EE1D | ||
660 | :15360F00D5C85763BBD2B1D7E7CC6FA08E747744113D5B8AE3A5 | ||
661 | :15362400C476EB37B0B47623C8F0CF3F35B254968F4F0297D654 | ||
662 | :153639007C1C8CB7D219C36FB74B1EF505A49F1B77B3B39A97FE | ||
663 | :15364E007B91EE4FB862E5CB6A28FBBDC8151D163EAF602F502E | ||
664 | :15366300DBC3FE7A05CE67426709A7D8E6703D17D784EB4C771E | ||
665 | :15367800AB13A7EAF8D305BC57415A491E48272A92BD18F72EE4 | ||
666 | :15368D005CB28D1D4AA32E4AC9D4310C1B759D3CA6EA799847E0 | ||
667 | :1536A2004178937C7B1B7E119EF32BCA966DBAF91990177FAEFD | ||
668 | :1536B7000BF263A32DF2BF1AD5E7ED3AC6862645D437CBACD512 | ||
669 | :1536CC00AC7F9C4B0D4D9E5B61A53F0278F3DB795D58B1BEED6D | ||
670 | :1536E1006AF6F5569A0B15C5C5B49847713AB4F7BEE5DE334AFE | ||
671 | :1536F60048FECBA5E88FE32588D21FC7FF0771CC8C0D65503E7B | ||
672 | :15370B00C5B4E5A8630FB8C4F361B5BBBE4A785D28838C60E796 | ||
673 | :153720005F39EBBF2AECB2FED3E5F2FC307C7557A525B763FE8C | ||
674 | :15373500AE8777A83437FA21F00A90BB8CE8238A144DAAD5302F | ||
675 | :15374A0096D079BD7761A31F5F1863525C6AAD8AFB984CDA4A08 | ||
676 | :15375F00E3901480F1C41E87684CC2B0F7301E3963913D2E5D94 | ||
677 | :15377400763CC2B108C7A408D9F4288C291A3B618D29563932C9 | ||
678 | :15378900AB965F3116A06C01E394206F37BA5FCD0BE5192D5589 | ||
679 | :15379E000E7047A2C956677E580DE31AC6697AD5A1F7A05EDB5A | ||
680 | :1537B3006ACD2B733FA0701DC343801F4CCF32CFE97417484EF5 | ||
681 | :1537C8008379654A2BCD24133E2847CA1C4A639F2B318F699847 | ||
682 | :1537DD0027B6356C734DF2B3A3D8A6CEBEE1C86B36CC00EBA1A5 | ||
683 | :1537F2005D5F813E3CA0D37959B439FA5D6B5CDDF3CA4CFFF2E4 | ||
684 | :1538070006ADF32F82BD5F3659C53C208B7AF62DB0DC719E794D | ||
685 | :15381C0036BB98670A5E4BCE6EB27993A523E2C6BB03FCCE58AA | ||
686 | :1538310098D136039EFCC73BD45520CFBA07C6D491DC98522753 | ||
687 | :15384600BB3B17CA1FFC30AE9D511AA9592D9C178D3540BBE016 | ||
688 | :15385B0086F87883EE96701D8E1B7A716F73849D1FD0CC1378F1 | ||
689 | :15387000B9D15C797276F9AB12CD4BFFA4722ED1BF09F53756D0 | ||
690 | :15388500B10A495AACA2BE2DEE75476A58855BFA06E9475E9528 | ||
691 | :15389A0079B30B75A7825F0AA3AC4B3A51645F00CFE5423CA71A | ||
692 | :1538AF003CF4EF02F78CCD6E9AEB94E3BEF81341B47DD3D4FF48 | ||
693 | :1538C4004610F36D253D9F5C35AB10E363C05797A8EF93B98E87 | ||
694 | :1538D90052482FC61B8C0BE0CF7F6940B7F412F921679DC02DFA | ||
695 | :1538EE006D517F0161685F6F04E340BD704F4F46DD29F0E3E3FC | ||
696 | :1539030063C651F487FF17618E7ED64E877B5BCF813F7EC78161 | ||
697 | :15391800C6783EF0A8CB3A53398234F74FA31D4656B60FEDE209 | ||
698 | :15392D00BDAC49A71F5450AFB51AE737D2214D100FA83D40DB6E | ||
699 | :153942000532DF5B66EE21BB48B5C00B8326C61FDEC26D1FA1AC | ||
700 | :15395700FBE170AE7355A66BA9245A672FD0F6C97CCA736254CD | ||
701 | :15396C0080388215C75F9DE19772FB2E4DCB6265A4EFAA03DE24 | ||
702 | :153981002201EB4C23EAB7A0DD41DCCF37C18F49C9C2FE1A2F08 | ||
703 | :153996009F37EE02BAF1801711FA66BCCABEA3720E7D437141CA | ||
704 | :1539AB008B9B3F3CC83F3DA0BEE177F2AD2DE49BB2F38DDBB65E | ||
705 | :1539C000677700AF385A86B695E47E964B18B4FE2E4534AEAEF2 | ||
706 | :1539D500BD9F379B0CC1443FA095D94EE5579BD306CA4392991B | ||
707 | :1539EA00813CE3FDB82EB9A3668342BCAA6E637FAD8967CCCFD0 | ||
708 | :1539FF00F6F3F2678DA341AB7D34429A263337DA02E923905F61 | ||
709 | :153A1400D702E609417A0BB63F4B236C68A77415CAA076FB725B | ||
710 | :153A2900D545FBA3E6EF8C1D3531254A792AFD317043FC83ABCF | ||
711 | :153A3E00E11B87BC4B614E70A3B9D7889A0FA4BB4D7D34065FA4 | ||
712 | :153A5300DCD38BC17F16C215282BE7B36DF1B20CE1009015D890 | ||
713 | :153A6800519351FACD8C711BE41B07D8FCD85E01572DF015E0BB | ||
714 | :153A7D008B362E6508AF85FFD590871FBE8D3077DB00FFE716D1 | ||
715 | :153A920060DB065C815F37F8F1C06F9E02BF50D0A2477C8E4D94 | ||
716 | :153AA7005FF7D30915DA5D854FE6979714D18B4378E47103D74A | ||
717 | :153ABC00A042F2B826E0FFE5F4E5E83C48448BB958C5D5995BCC | ||
718 | :153AD10022D86F4A3B642D4B3A81CD7A359E6991068C52DA2366 | ||
719 | :153AE600E6869C3C3250667D7A8CCE0570350975C67E4B14E2A1 | ||
720 | :153AFB00453406F90D215EFC4D05DEA69CC231AD5945BBE28BDE | ||
721 | :153B1000E5DEA56CD32B8353CF32E6E4C3360D68999FD8FB05AF | ||
722 | :153B25009BC63413FE51074328C0D3A12FC47105C39EB5F48CEF | ||
723 | :153B3A005B1CFE047ED99FA0AEDEB2E502C00A3207C1EDD09B26 | ||
724 | :153B4F00492097DBE9826CF972B6A983F277F46D310DE45551D0 | ||
725 | :153B6400C9BA280CF32A0B5E8A2FECDF7E6E461F5EC2BB96FCCD | ||
726 | :153B7900FB0A75ECFA31D6F1807A030C0DD29726F4F88F11604E | ||
727 | :153B8E00B44D64ADF7EBE0CEC03B096F16DE1CBC26BCD3787B99 | ||
728 | :153BA300758E0CAD3119DE50CE8ACB360D5A75B574E6C9CD7E81 | ||
729 | :153BB80039DB2DCF7147E7B8E373DC8939EECC1C77768EDB9CD5 | ||
730 | :153BCD00E366BF9A53FEAF8A74FA013FDDDC6CFB0393483BFFD1 | ||
731 | :153BE20064C16E531CEA161838AC56D2D9503B1F9873E3DCFA61 | ||
732 | :153BF70086F8BA48E0D8849ECE219D66F03605EEB3F09E83F799 | ||
733 | :153C0C0002BC02D0A71ADE2678DBE1ED86578177C34FACB8ECF6 | ||
734 | :153C2100D004E12DE3D01FDC8837BDC88D784B14B9116F1B8B77 | ||
735 | :153C3600DC88B778911BF1162B7223DEA2456EC45BA8C88D78AC | ||
736 | :153C4B00938BCBFFD58C5D442A1FDC818E8C816D1BF54BF97BFD | ||
737 | :153C6000D65DEB9C6B279C5DCE3E03E0576445F89D1BE74F0C29 | ||
738 | :153C750047DE7314E417908DF427E6310FEA1AC29CBA33CD31E8 | ||
739 | :153C8A008F00FFC0673A451823CBE545D73C05E3622DFC231DFB | ||
740 | :153C9F0079699B7A971778D67C5671076BEC8CCEB778DA4DF0DC | ||
741 | :153CB4001F996FF1B23AD6B8DCD11B91D1CE2F8CF93AE48138E6 | ||
742 | :153CC9009BAE84F11BD29FAB44D9E1D1193B0A20EF9DA91F80D0 | ||
743 | :153CDE0071793FCA08FAF40AF7F227208EECBDFCF8E48C73B8E8 | ||
744 | :153CF3009789E311A0D1531C4F8472B7DA67BC41DE597E16F2D1 | ||
745 | :153D0800F290FC3E9B8FD502BC9B251C0F51BED8AEEF88E3B99A | ||
746 | :153D1D009E47F52DD1FD547FCF87DCBD92DCAC23CF6F03B4794F | ||
747 | :153D320057EEC6B5306DE33C5CCF1FD399FEA81E80B97B271B90 | ||
748 | :153D4700A4F8839E0985AB6987B175CCC07B8078905BC9B66F83 | ||
749 | :153D5C006C587B6A3E8E637ABFE44D511E47459021218D203F57 | ||
750 | :153D7100AAF330167B2A715D6ECC401B0688E746C9923F10D617 | ||
751 | :153D86009C385BBEDB378F553C01F965E6E138D3A827696C6ACA | ||
752 | :153D9B00A2B109CF137235213A9F7EF662DE539E18E874C79ABA | ||
753 | :153DB00054596ED05F5CC12DBF0BD24CCDB76422070F3E5B5772 | ||
754 | :153DC5006B66FD43D6A7A7914F6D25BB6B98BF74FA030A9ED3D9 | ||
755 | :153DDA0040987DD1B1A53CC82A3CE4390D79F6824C85E7407863 | ||
756 | :153DEF00D265A57138407607A62D9BA17C7CC21065EBFED03C4A | ||
757 | :153E0400E9413FAA0580E7F3F26306C6AF043E4AF7A59780FC2C | ||
758 | :153E19008C770C16DDDF721EF2F8511CDA5E1C6D16587691BFD7 | ||
759 | :153E2E00CBC63A4570E33883B88C9633CFEBD0665F65039D0EF2 | ||
760 | :153E4300EC164EF6116FC23CE8CC045BD2E9C07D1EE046FD401A | ||
761 | :153E5800A04305DAF9C0B6C1A3DED985BCC7B1FB5D5CA7605144 | ||
762 | :153E6D009D9CF106EB45FBBCC0EF102E777618E039AA511DA462 | ||
763 | :153E8200319C7340BDB7CFD89D8D0F68231EE6B9016075D27CEB | ||
764 | :153E9700383AD8897BD4FF7CE0E7FB45B9C50890AEA70A7D760A | ||
765 | :153EAC00B5E1C0CECBFB691E86FF38C64B368ED6D8703A7A6FBD | ||
766 | :153EC100362E03B8BFD60261BE38BFDC5F32D337244FA36ADD4C | ||
767 | :153ED600E39AA6F28CE3E3CB5924827BD6796BEF219FFFF2F1E0 | ||
768 | :153EEB0008F82575BC5BC09BBB57F59EBE56918EAF54EB645735 | ||
769 | :153F000017E9B4E6B6A30E89C7533C6EDA70B6B225342E4F0ACC | ||
770 | :153F1500CCF334D4F167D0F6D8A6AF525E185F405E1F19A77B66 | ||
771 | :153F2A000BE8FC47570B9D7B00395CFF6662AC13CF44207E1FE7 | ||
772 | :153F3F00887374AF9C8D779FCF747756A1BC6E1ED3CFDFFC9DFD | ||
773 | :153F5400E53F0337D69937272EDFDE0047567BB3DA8F681ED6B2 | ||
774 | :153F6900779BEEDE60D7049587FDCCA2A74C3875F835DFB5043E | ||
775 | :153F7E00F729315CAFCB8E459CFAC6B8D9ED12F5122EC6B94E46 | ||
776 | :153F930084DBC1DB4BD971E201621C78825DCECF208F775BA70C | ||
777 | :153FA8003AD3BD3C543EBB2D76BF9EF7AC063A8AF1A2BAC88FA0 | ||
778 | :153FBD00E9A87F56A80BCC61ACFA3715EA8270F05D1FA4BA1001 | ||
779 | :153FD2009EE2636F8927B7D4A8DAEB1E79ACAF707C17E9FAE127 | ||
780 | :153FE700DC688FCBE6138003E0E99E82CDF1DC8076F2BF1C7DE8 | ||
781 | :153FFC00CB16AA13EACF3A696F837448EF34A429E63377BF6960 | ||
782 | :15401100B55751DEAFCBF171ED73D18930968D6D51DA7CD43A54 | ||
783 | :1540260057969B80F9C2A041F6E1A72D5EEEF415DE3C60489E81 | ||
784 | :15403B0009D50B3CF77E985B8926F215CDAEFF9199FA43BBA8E9 | ||
785 | :15405000EA3A46F5AF02BAD9F42D8C21E5C8EFA83F68AA6507E9 | ||
786 | :15406500DCEA0F17D1164AE4D0ACFEF09BEC21B28F82386BBD10 | ||
787 | :15407A00C53AEF8DE53CCC863BA12D5BFDA46BD06AC700EB5097 | ||
788 | :15408F0002CF30EBFDBBC9B6F9B139F4D62D7AD71F5D6E805B09 | ||
789 | :1540A4008C8F17D1F5908E6966E83A6ED72B45F5429EE3ED1A8C | ||
790 | :1540B900A63A2DCCF0CBB1ED3BB42CB45FF0E333686B3FA90FC2 | ||
791 | :1540CE0041FFB3ECEC5BF5F802B44FA72DFAD8D1CE4A281F618E | ||
792 | :1540E300B900B02C84B677A86C76DB3BF99FD0EEE422F8E200AC | ||
793 | :1540F8005FBC083ED981CFE24B84CFAE4182AF982F4C4F5B7B51 | ||
794 | :15410D00C8F8E5E3D69DB37A34B9B1B268CC49FCDE694B85B9DC | ||
795 | :15412200AB8F454608B768CB223D9DAF28B43D906D7E81BADD7A | ||
796 | :154137005FE5AF95E2D6FCDB17DDAF3E0969020D7CAFF7745A0A | ||
797 | :15414C007171CCBB00C3728774E97446E1610E7E10609570CC13 | ||
798 | :1541610081F683EB92828072A7A6058347FA65909112F78EF437 | ||
799 | :154176006E41FFD4EF90876F114E1EA37DF073F5C3CB58EEA8CC | ||
800 | :15418B006E84B85ECCA72E398C36C1FC5578BF10F827613ECE96 | ||
801 | :1541A000A4618387FC708F93DC502E4F7B2AC306A5C3B2F461E7 | ||
802 | :1541B500D4175D5097E13B07AC345B1230A7C77511618DA6D2CC | ||
803 | :1541CA00FDBCA87364CFE91156CC7F6BB7A694F49C5713F9BC33 | ||
804 | :1541DF006FE4239A8275E6214D5DF2C03A841FC74E840561C3C2 | ||
805 | :1541F4003D8476802170FA88521587BA9EF88AEA631AF0F08C51 | ||
806 | :15420900F22D1C17EC3CD1FE3CC8C03E4CE7D47D08F24FED3C5F | ||
807 | :15421E004CF7FE627BA1B8B1435B84EDBF534D840DEA8475C1C0 | ||
808 | :154233007B41912E8807A61FD3109F6DA83600E10E2ECE16F0E9 | ||
809 | :15424800609555C003AEBFE62C3C04BFCF77A67A70AF79421B7B | ||
810 | :15425D0000FF11EC2F8013F4C3B50D1C832D788F010E0E289865 | ||
811 | :154272007F49CF6BEA66C2C301C50BF5431C48782E05F74EF013 | ||
812 | :15428700CE0D280B6DDA86A0FCBAE0B97EC75EAD65DF04E6FFDB | ||
813 | :15429C00AF30B6A326A5BCCACE698B42ECD38D32FF61C79E62DB | ||
814 | :1542B100EE9364AF96ECCE74D31AC19251EB6C608AD245CD6D7D | ||
815 | :1542C6001AB46D0F7C711FCDC8BD36D3CEF13C18AE55611B6D33 | ||
816 | :1542DB00C1B934EA1E86DA35F61AE9B58DC2989B4D34B97B3965 | ||
817 | :1542F00021A2F289B0BA0760AD5726F19E385D977777D1FC14F6 | ||
818 | :15430500E248C03B44F9639D82FCD94E49FEC4723E26E3789DC3 | ||
819 | :15431A007D0EE461FCF6E35C2AF628D9BC0D74C886953FCA8CB7 | ||
820 | :15432F0063D91084B540FA2648DF08E9D1AF56FE44A79307B46F | ||
821 | :15434400A74E11C205087F6EC567293F91E666AF6C71E26CC493 | ||
822 | :154359007200267FC7B495B76EC18D388A60DF00385BE467BB1B | ||
823 | :15436E00F88E901183705C2FE882F934970AAB5202F7D2ACF8F1 | ||
824 | :15438300981FB481000FF9603CD2E77E0DCF015AF769601F6EDA | ||
825 | :1543980067F6FC1ADBBC346E97B3AF1F6D3254D3D97DCB0FE76F | ||
826 | :1543AD004CE8876D2260E9B05F325FE2388B9E057FC8BFD6990B | ||
827 | :1543C200FF901E1F944F7704650CF3B54BE75CD6D9C17D3A8668 | ||
828 | :1543D70021FF015E6B95057102B9AFA9FED35F53505EF5771D0F | ||
829 | :1543EC00B2EEE580303FCEFDD9611CDFB58FBF50C26AB387DBB4 | ||
830 | :1544010036C2B827DAF30C4B67D09273D066BC9038B0B40A64E3 | ||
831 | :154416004F3FE61BDA67C151E0932982CF1F4D46C83E04B8311D | ||
832 | :15442B00CFEAE8785B6D519E85B90BF05C4A6FF3CFDFD8ED19DF | ||
833 | :15444000EB81733B80CDF71CADE934CEA4293E8F48F76DDFA789 | ||
834 | :15445500FDF632E9F6CF4907ED5DBFDC7A52D4DCABFDFB65D2F4 | ||
835 | :15446A00DFF52ED2BF7C997491778477AF76EE32E9DE60EF5C67 | ||
836 | :15447F00DEF49B73F6D3707DA7B8FD01ADA65F9BBDBE31373CC9 | ||
837 | :15449400F1FADB874FBF53F8FF76FE73C2C5E2F6FF76EB03FFC6 | ||
838 | :1544A9001FFE47854B45F8F7CDE54BFF67E0B7DB47ECBDA5C765 | ||
839 | :1544BE00FEB580974916FB24D9B869EA1F94E2B7AD82AE287AF2 | ||
840 | :1544D3006F573508C7BB56C5EBB6AB74D607656EEF0675DEEA92 | ||
841 | :1544E800EDAA2CDFA9CDBB6E40F5F7688AC835A8FECA063509AF | ||
842 | :1544FD00728BDDA7D75D80B159F236A998DF1F9BD7DEEB35652F | ||
843 | :154512001275FF7A70EE12D7502389974B7A3F073C392036A83C | ||
844 | :15452700E53D2DEAC3D7372BF53DCD4A50BC4D1D2CF98082F66E | ||
845 | :15453C002017F17167AEE2C7F83C77A54A6B0FAB078877200F1F | ||
846 | :15455100A9AF4C2AA8DFE584FB28BC59757B1324DFD5DF9450C1 | ||
847 | :15456600697FC9BE2F7C2E0CAB6C182A0086BD0043A0A87C2C1D | ||
848 | :15457B00B70E60C078942FE45F5CF6053BDFE9A27CF3F967F20B | ||
849 | :15459000229E150FB3DEB578473AE49D28896B888F3CB3F2BAA4 | ||
850 | :1545A5009AB10555801B11CAF4AC69061C35288BC416B5F6430B | ||
851 | :1545BA007CAF9B0DF4D57F9EEFDD3B3F4934C0759110C0817BDE | ||
852 | :1545CF00705791DD9019D81126929358E21EAA1BC074D286E933 | ||
853 | :1545E40028D65DBC51ADDFB956E52A1DD8F2171DD83A01B66A62 | ||
854 | :1545F900B181FC1320203AF4F254B6A822C1B45D595499547755 | ||
855 | :15460E006DDD51680B88E73FE4F3360C8CEA893695ACFDE3E983 | ||
856 | :154623007BB0DC9C0D075793C2BBA784F99A05837767A3EA852E | ||
857 | :15463800F2B06EBDB62E3F2ABD115ECA66F0520F6DA7624D974C | ||
858 | :15464D001AE889103CDB4AB62BE580970A31A996B264DF0EBB47 | ||
859 | :154662006D2EA6BACF947B0ECAD221CC0BF802BAFB1C1890F65F | ||
860 | :15467700F5DD372A280BD5F7DCA8CCA53F74226F39ED1BCCF4C2 | ||
861 | :15468C00A7FAA93D148F3BD5A2066E8AAB3CBB539D07711FE630 | ||
862 | :1546A10058D06DFF1BF05FD10370427BA9A88CA8DAE31DCADEFE | ||
863 | :1546B600131D4AC5A9356A4003BF9DAB55ED233740DBBF41C1A6 | ||
864 | :1546CB003610009CD6AFB170C1C7B95E996DA0B60D729ADFCD92 | ||
865 | :1546E000DDA28AF112BCF7C4EFC1BD9ABAEEFE79DCADAAC8AF72 | ||
866 | :1546F50052C59550DE7577A8E2EA1BD4E192554A04D70156CE75 | ||
867 | :15470A00C42F0B5AE766287E326CC57FF233AAF844873ABC35B0 | ||
868 | :15471F00ACB861DCF53E7E9B52FFA1925EB48D2C24C27D9E6CDC | ||
869 | :1547340047DFFD684F4A0BABF5A76E51B9931DAA067139618691 | ||
870 | :15474900169BB08F07E99CCD3AB4A5220C40BAE31D7D34D76B64 | ||
871 | :15475E0067BDA5DE505F99B7BDAF3EB556D906BC4106FF21F8F1 | ||
872 | :154773007E1A79CE4FD6ABE250878A72B52CDF8AB29D20263FAF | ||
873 | :15478800A3726BEE5429ECC90E080FABC38033A43FB6719C93FD | ||
874 | :15479D0094FF03D75B7F0A70A80DA881539F512B4E6EA736B0B1 | ||
875 | :1547B2000BDAC03CA07D7954EB2BE64B4877A41DE928DB34C57B | ||
876 | :1547C70036791DC0D28BF0039EF16EBF1EF84F96DCA5CC837208 | ||
877 | :1547DC0010FEC1ADD6FFAA8BF900F225C78D71616C58B7278FDB | ||
878 | :1547F1006B3856DB36606A85F843BE0773AE054EBBBA1BE290E4 | ||
879 | :154806003E39C070D71CFD4AEFE3B54AFDC96AC06DB57AB97630 | ||
880 | :15481B00F4129B6947BF64563B421A94433B0A8A77115E1EB6C7 | ||
881 | :15483000DB12B6A380067E73DAD2F6C49FAF2F0F6E00FAC4FB9D | ||
882 | :15484500B7B35BD7CF0BC6FA39F10ED57157446F5D8F749A376F | ||
883 | :15485A00B0B68F9DE8ED73BEF52FBBE87E9DF2C4DABE8A6C6F1C | ||
884 | :15486F001FE7019A5FD9A0B9810E1781F688BFAB8916AEDE0ABE | ||
885 | :154884006D0BD0E10EA0C30EE2E9C5B428B16991B4EEF5F17365 | ||
886 | :15489900C29550766CDD14D105DB4D6CDDD13974019AF86EB218 | ||
887 | :1548AE00E9027CD7B7B6882EEF2BA2CBABA43339D3B7B742BF10 | ||
888 | :1548C3001E29A213D987863680FE9B6D5A9D063A39B4D9F01E37 | ||
889 | :1548D800E971A6881E3FB2E9817D3A60D3E2123A006D8A695101 | ||
890 | :1548ED0016FDD4FAD2E8DAF5EC6ED62B663FD5374FDAD057C62A | ||
891 | :15490200FE7A7D79E26FFAC4ECADE4AEFF3CF5579FC8C01DBD70 | ||
892 | :1549170093F0CE6F6ED05CC07B2F96C5B47207EFD04F2BC4AD95 | ||
893 | :15492C00C0FFFE42AD5873EF2CBC975F0EEFA9C548F322BCC7E7 | ||
894 | :1549410009EF4E7D8BF10F3CDF779D8D7F5C13C17EE2E0DF5732 | ||
895 | :15495600847F17AD6D58F81DB1F15B897C0AC2F0DEF0E23EE01F | ||
896 | :15496B00A47F89C6058B66988EECD3DB74B0701E9905CB97015C | ||
897 | :15498000CF6286EB7D12BE49E03DA59007DE9FBCF763B7A9F5A9 | ||
898 | :154995003D5D8A54B254292BB956C1362C02EF61273AFAF6FE68 | ||
899 | :1549AA000B849D5AA3F84A3EA2784A3E6A8571ABFAD8F537F4B0 | ||
900 | :1549BF006D8BBB7A11AEC5F69DF2D046BCA5B28BC648F4477B35 | ||
901 | :1549D40018CE1C05CB47BB9125CED86D8F1F180F75A511AEE79C | ||
902 | :1549E900F3793FC429F4FD27A1EFE3D87506A693B85E82F2017F | ||
903 | :1549FE008C75FE27ECF8DF82FFFA9779FCFA8E505E2975976B5E | ||
904 | :154A1300FC36D4D3629C7597298C2C795F74FC768369A4F38504 | ||
905 | :104A2800FEFE99F5D6F2FF06E2E5D1A4A89C0000A7 | ||
906 | :00000001FF | ||
diff --git a/drivers/atm/sba200e_ecd.data b/drivers/atm/sba200e_ecd.data new file mode 100644 index 000000000000..d097e743b846 --- /dev/null +++ b/drivers/atm/sba200e_ecd.data | |||
@@ -0,0 +1,928 @@ | |||
1 | :150000001F8B0808AC5A10380203736261323030655F65636426 | ||
2 | :150015002E62696E327D00DC3A0D6C14D7996FD7B3F5AE71CCD4 | ||
3 | :15002A0078592F3F8DD70F0AA949E8DD022E07F61A1644AA40C3 | ||
4 | :15003F00012D88A433EE52268844E8924B571792229D1B0F8EB1 | ||
5 | :15005400013B7DD0C7608813E1640D5E58529C6C909D101DE4AC | ||
6 | :1500690016357749A4E4BA8A7227541DC9AA17295C4A2F76455E | ||
7 | :15007E00259438EC7DDF9B19EF7831C4A1524F772B8DDF9BF742 | ||
8 | :15009300BEF7FDBFEFFBDE1B3FFCD3BF7F88B808896E2484FED3 | ||
9 | :1500A8008890844A880EFD1CB4BBA00DB710128396439B8076CC | ||
10 | :1500BD0018DA4E68B51FC3036D16DA1DB8364E88026DE92FBA6D | ||
11 | :1500D2001EFE486452BF7C63D90D63AE825E0863FB54E1A984C2 | ||
12 | :1500E700782F999F6AB59F9E3C49B19D522690D8ED9FFB737D9F | ||
13 | :1500FC00FCD38F45DB66F353D2B6AD1433AEF2F2F209D77F491D | ||
14 | :15011100BE34E18787275C3FF52678EDF13693B20B7EE47FE17D | ||
15 | :15012600E71A20BB45FB4AA95D5E29DC72DD983C8589E52B4C68 | ||
16 | :15013B00927E7959B9A987A7DA6E4DCF24842D778E97CC7F63BA | ||
17 | :15015000F90B6D6DE8BEAEEBF97C299D49C95956A43F7A5BF4D5 | ||
18 | :150165005F7C512AA1FBB7D87EF4AFBF99905E79919E97FCDF83 | ||
19 | :15017A00FFB93C759E5BCDF3F48DEFDA29E89C2A8EA109DC0E0B | ||
20 | :15018F005FF8FFFE2B387E24ACB3FC6765A432BB6F911CF4C674 | ||
21 | :1501A400C1977CFA72F2308031121A8EE3BC3E026FE14E96FF67 | ||
22 | :1501B900025AF9AA21793BD46B5B3B1A708EC8A429FF1CF1557A | ||
23 | :1501CE003E4F7C81FDC4977802FA5DC447C2618EEBEA932EC057 | ||
24 | :1501E3004BB79000C012130F873C52EDEA50657DA14AB86BAFA6 | ||
25 | :1501F80014D4B75C5C467C1D4F126F20B8231E269759EF9EFE32 | ||
26 | :15020D009D846F61249CE1FA03844C0B6A716FD52F20EB9C6518 | ||
27 | :1502220035C1447C7AEB6916F59268404FA9249C341086C4F6C2 | ||
28 | :15023700182477ACC79FE300570FFC87E3FBC3A4657AEB6A1692 | ||
29 | :15024C0085F4D4BE7FB34AE4F5AC7D7DB3FA3C213546D2DD045F | ||
30 | :150261007C32C81F7230EF6A9E22B7A8B81EE7116EDFCCCB8A9D | ||
31 | :1502760067E549751FF5B490DC6C5641483010844C26EF66BEA1 | ||
32 | :15028B006067FCC3B9C4E721F3D53DC3EE1669F72655BAB04CF6 | ||
33 | :1502A00095B6AC654B008EF03EFD6EBA6531EA08F113F958A63E | ||
34 | :1502B500F8F4EB015853B966BE7AB950A8FEB04D8DB4FF933BA0 | ||
35 | :1502CA00021254BC2478DA75DB3C456FC2D306E429775C5F2546 | ||
36 | :1502DF0078A202FFB7626115F9D9AB95B5608BFC601B04DD5402 | ||
37 | :1502F4000575C0F90BA1C39DD5640A91FBF4DC8A2D0DE780D715 | ||
38 | :150309001DC0AB3D1FAB26E3C3487898BD07DA0F053964FC6180 | ||
39 | :15031E00B09F6E2C85F4EFDDC054B2B33F93978886ED30B49447 | ||
40 | :15033300768879E085CA723BCEF75CC37918AB1763BB718C8F81 | ||
41 | :15034800E218973A503F887F41CB78FCF545FC0256ACB3E8DA10 | ||
42 | :15035D0034052D8BEE84341DF8D924F1874DFC62BDC065D1B458 | ||
43 | :1503720069396575E2BF52823F5CC47F03AE9BF17F2BFD283F5C | ||
44 | :15038700BE7DFE1BC41863C362AC4325B1FE8C3D3EF66ED31296 | ||
45 | :15039C00F6BE39FF0257281DAF69ED17F8883C2F83386A5A1923 | ||
46 | :1503B1001BB5E418C30B73E3E48AF573539E9BF37F2BFCD76E07 | ||
47 | :1503C600827FCCEEB1FE1E1B7F838D9FA45929AE521C387FCD8B | ||
48 | :1503DB00E143B62C02A73CD433A10CE3F647A7B91FAAFA55D204 | ||
49 | :1503F00030CFB4AD06B685FE0DBED990327DD38903EC5BB9A572 | ||
50 | :15040500685F6F5587E09B3474B0AC44A2105B784D2CAD1ECE76 | ||
51 | :15041A00B85B80BE512D77A9570A85A0D33FD6FD99EB3BC4FAF6 | ||
52 | :15042F00CE09D78FAD053C57715DCCE12B18A2352F4BE4DF3E26 | ||
53 | :15044400A3E73F3562F9670D7FEEAC3AFD034D21B14BAC4EB966 | ||
54 | :15045900475D4C7FC5F6DC3B9020F2BF81EF26793FC4F5605035 | ||
55 | :15046E0089631EE0D00FC49222DEE3788D3E00FDB481E324B744 | ||
56 | :15048300A8470EEE8A93DC7B10B366C4F7CDDCA178E9E3ACFDEA | ||
57 | :15049800FD956A27C4B7F6F7D7837DE688787987152FBF0532CD | ||
58 | :1504AD00C87598AB92BC1BCF26E134E7D056692EE07F3ED0CF67 | ||
59 | :1504C20033CC96D2CAB56AA12CCB24D72A55EADDC8BAC949C5A3 | ||
60 | :1504D700A50DB0EEB2E30AC28C421A3D4C5E56C05E0CAB886E6F | ||
61 | :1504EC00F23A8C67712DF4FF45113C02DE68FE6D03E4309096C9 | ||
62 | :15050100DB45AABB203749D1BBD5BB80A7629CBF17F86C6701DD | ||
63 | :15051600E06D6788F8BC40FB933677C4BBE135950CFEDCC09CF9 | ||
64 | :15052B0087FC728B5FC455F5515EED2E3BA9A05ED65592181934 | ||
65 | :150540001C30B244C0E918E7BB519E705AC4FC2A42FC2496D294 | ||
66 | :1505550047B7F635873457A377C309F0B30106F089DD3F9C0F86 | ||
67 | :15056A00364FF16B85424D9DF26B359AFF9457B94EA8B1FCDB9D | ||
68 | :15057F009C84327177E57915E18379C83D202BD2385A0672CBE6 | ||
69 | :1505940003461053742C63CEC97F32C0F601EF8697D559078ED5 | ||
70 | :1505A900C3BE4D097EC0EE19B0BBD8136BE99A8829F3A21ECFAA | ||
71 | :1505BE00CAE3AAB013E634CB4601878D1EADB5725A02721ADA1A | ||
72 | :1505D30000748276C8A27FA15F800E9016D959D40FEAE5975DB2 | ||
73 | :1505E800DF079D844D9D583CD83A09002E874EAA854E56AC5F7D | ||
74 | :1505FD002CF0900C0BB60AF9C00FF764AC07F676126B984CB013 | ||
75 | :1506120055E82BFA3CD80FD619159837071F671F423DF547CC48 | ||
76 | :150627009D9ABBB94EF94FD5EDFED9920D9ABB2948DDCDE3ED05 | ||
77 | :15063C007B3FE4F1ACE201DD96CA8CF2A1DC1EB2006AA3679877 | ||
78 | :150651000CB2CABD9BD88E3B896FAFB6B1C9BBE105F0796ED6EE | ||
79 | :1506660014E1A5ACB002FD803221E3D52B26CFBC5F7F80DEBF28 | ||
80 | :15067B00988492F15AB2470D8C32C12FE9EF63DDD98560AF85B3 | ||
81 | :1506900006ECCF8CF5F4E05E053D0AD9486CD0C0F501D8C35394 | ||
82 | :1506A5001C72BD05754ABA6D6364519B29DBDD753F5B485DC4FE | ||
83 | :1506BA006BCAFA6BF53A79F216B2E641D6939396B5F5DBC477B6 | ||
84 | :1506CF004CC8FA30C8BAC39435047BBBE1F7A67CB1E3FA532095 | ||
85 | :1506E4005F6DF63BEAD4489390AD2C36430DE9A1E66F635D12CB | ||
86 | :1506F9003B20628096FFDC38EB2553A0E5B81F85AE5007644910 | ||
87 | :15070E00D12FE4BE8CF5801EFA8A7AC8BD6A209D523DF4801E4A | ||
88 | :1507230074D043D0D24325E80169074B68831F4E194FF38472E3 | ||
89 | :15073800C0972AEED189F7E6346B6F46C6E6D1C78027EC8760F4 | ||
90 | :15074D00EF3AF72BEE55C253FAB5151EC10BC417D8AF2761BF9D | ||
91 | :150762007ECADD9543AA6BE659D5D53524F6EC11C79EED297B45 | ||
92 | :15077700C5DEB37E9C3F52DCB335E8FFE8D7CE7D3B0BE05046FB | ||
93 | :15078C00BF4346AD9C4C71EEE7B1FC943BCDFDC1CBF1EA46B191 | ||
94 | :1507A1005788F48AD452BDAC53F4AB5DEB45BC8E06486C8EF056 | ||
95 | :1507B6005F6EE65EC88572F20A93D6ACC59C974940CE2B4C4D3A | ||
96 | :1507CB00B05EFDB8C2662694C06E880F77A4541FFA4FCCB0FC60 | ||
97 | :1507E00087C7671D931ABD55AB61BFC6581BD118FA4ADA05352E | ||
98 | :1507F50041586188A322F20CD3A03568598B1F7CEB04ACF36627 | ||
99 | :15080A008FA9011DF3FFEF0D51CBE01EF84BB6DB3E6764B09B53 | ||
100 | :15081F00E9E04BC89773FE51F0AD1524C1B6E9879693F065A3B1 | ||
101 | :150834001E6581396FB61DCE4A585F7C435A0F9AB4B278CE7380 | ||
102 | :15084900CCAD4A8E3621FE34B9357E5D33D7E74BD637265BC568 | ||
103 | :15085E00FAA513ACA7DA492677758B1C6DCF47110FCCDD958C37 | ||
104 | :1508730034A1FEEDB501FD984A61CE8BF0B1B9803B950925C1C8 | ||
105 | :15088800A6164C8305238BF5A9CC647C22F0A6D48CF11F7DAC82 | ||
106 | :15089D00167D35D76F94D64FEB1E76D43FA2AE642C8AB58F2916 | ||
107 | :1508B200DF196CCD7ACFEA53689DF58F63FD1C0D7D1060A1FEDC | ||
108 | :1508C700411CD21AA61EC43D0BF2E27E1A572BE3F1F93E2FEEED | ||
109 | :1508DC0053C31FCCC6F17C5BA75C51FF86BE06E7DDA19D24F6BF | ||
110 | :1508F10004C39C9E7B40D4893C8BF50E9C875D33CD9A270A7153 | ||
111 | :1509060003EB2B92DB8E7006C2C9C119702E7E5A9C8BA747FA68 | ||
112 | :15091B00C59938181D54B1CEC0F544AE15676212AA8F4F8F3447 | ||
113 | :150930008873309E89CB8066FBFEFBADF3F0BDEAF32EFB3CBC70 | ||
114 | :15094500D43C7BDE10C78B67CF89F2349E3DDFAA29397B62AE9C | ||
115 | :15095A00B6CFC3B992F33087986B3F373B0F7F4D8C7C4CDB1875 | ||
116 | :15096F00F11C3CA3BA601DC6BA3D10C776BF9B56BC55C7314647 | ||
117 | :150984008A5A40C43898C739A0853569CD9CA4A7C98449A13EBA | ||
118 | :15099900A222060A9B891858EDADFA15F8C48098DB4EACF36D2F | ||
119 | :1509AE0091DF1EC423D60B9D9B7024F62763F7BB19657A24259F | ||
120 | :1509C3006C00670103C726F7FCB3217C16EC1BA8492A585360D5 | ||
121 | :1509D8002C47BF7906F9224BD94BA843FB5EE0366C531F98D827 | ||
122 | :1509ED003613DD0B94C796AA28EB3EBC178056DC0B403BFE5E71 | ||
123 | :150A020060693CEEBAF15EE0EB6CD6FE17B0D944FAE413D8D15A | ||
124 | :150A17005B750FD830CA2C7939CAEB6D9D6DE290470CBF43DE6A | ||
125 | :150A2C00042153049FAD7D967D070C8499DC73613C3F729F6190 | ||
126 | :150A4100E39D01786D5BDBF1E9CE478AF1C5E5EB107ADA94DD30 | ||
127 | :150A5600D3689F51E58D49A5A67590C5800FAC0FF04CAA79CD1A | ||
128 | :150A6B003C8DF05CE80DFC0A748363EE92B161475C9A41E7F61F | ||
129 | :150A800060CCB93802B97A659F1AD0D07F1A18C81E708580C77E | ||
130 | :150A950031BED23C564648A3E66944597640DFB5C63C7FE1F838 | ||
131 | :150AAA00E1DA2106B508F7C82F412CEF33EEA4A70D29B9C7210B | ||
132 | :150ABF0097CE104EFF119EB74C5C4B268B2B79AA880BE087AD61 | ||
133 | :150AD40073A08BE8784634F0DDA6F34DE4D11DF2F43878D02783 | ||
134 | :150AE900290FC2651E30E5D11DF27C2DAE1279AE96C873F536FA | ||
135 | :150AFE00E5C938E479C7C1436692F2205CFE7E539E8C439EAFE6 | ||
136 | :150B1300C55522CFB51279AEDDA63CC991A23C67478A3CE0F891 | ||
137 | :150B280064E44138D99207FB4B268BAB449ED11279461DF2440C | ||
138 | :150B3D00ADFB0C19F3B9E5E3750A53EFFB09D2357D04DF975A45 | ||
139 | :150B5200EF19EBBDDE7A47FAF83E43BC2799F065A0B1AB4CB4FF | ||
140 | :150B6700ECAAF59EB6DEAF59EF17ADF751EBFD1DC0B38B9EE038 | ||
141 | :150B7C00D8D760AE93BECCC5BD03F47BE86B5CD403D04FD337E7 | ||
142 | :150B91007994DEC5CC73C5592303EBE05C51334BF33407939EC7 | ||
143 | :150BA600667FDED3EC053B606D8F3236D05302CF7658BB9ABEDF | ||
144 | :150BBB002AF074437F337D83E3FAB74C3E38D2DC4E777313AFA4 | ||
145 | :150BD0006E0C025EBC6B5841DE6167B6BEBC5CDC59004C15F5B9 | ||
146 | :150BE50034E2D80B5B5F136359C7D8335BDF1463C8933DF6E484 | ||
147 | :150BFA00D6BDCB6DFC7751D37E886796E8A7F9768B3EF2B4B65E | ||
148 | :150C0F006E60998DD386455C36ACCD2BF216B26011EF5F514FEF | ||
149 | :150C2400B3B84BB1743AFC88A9D39CF8EE61CA3EC3CE1F304F8C | ||
150 | :150C3900C7CD9BF4EEB6700C9A638CFF9D09F3A1850369071099 | ||
151 | :150C4E0007CC651F2DCE452C3DC6617E1DE80F75C7A01FA7072F | ||
152 | :150C6300399E8FCE099E2E0B3E1FA5CFF15EA1DF1EE3F48870DB | ||
153 | :150C780040FF03D73D4D7B67526543E88D85CFE692CA0F962315 | ||
154 | :150C8D001F9D424715509B2E592E352D0AED5EC861EE6E319754 | ||
155 | :150CA20011FC56243D8DB3DE949A82A1830B0D98AB5A6EF28FE3 | ||
156 | :150CB700FAAA807D72FD2BA9E98BDAE7161E82B93F367B9A2BEB | ||
157 | :150CCC00B4F2C6CF2EFD2182387F57CB22B8FEB7BD831184FDD0 | ||
158 | :150CE100E0D269C8FB3B044DE03FA38B7686E019E4CCC444BBDF | ||
159 | :150CF6004BE026E1682629DA84E0036A8E0CEE89E9172EABAEBD | ||
160 | :150D0B00F735D87FAFB0CA60268EFA31D75D36368BD6D41109F9 | ||
161 | :150D20006B8602EDB495C755D7FA47A0F6D9CFEEC05C097A3363 | ||
162 | :150D3500E9268D0ED1EE303A45DB23F4590EE705D7FEC701FEB1 | ||
163 | :150D4A007BAC2A1806782A6219C20F8A36619C15ED52A1F32969 | ||
164 | :150D5F001700FEFD7F10B5D5D4600CE0A386C977D2E887F6692B | ||
165 | :150D740061875D467AA498DB4808EAADB0226CB30D6C93A007C3 | ||
166 | :150D8900B81CCCC1D845B6B4CCBA2B17ED45A301DA9DDF273E14 | ||
167 | :150D9E001E76B7C0318F1D182DF8D1971E85F14A7A02EA055D0D | ||
168 | :150DB300E8AF0CCE160BBE8370E6BEC25CB9CD82457D5BFB8D79 | ||
169 | :150DC80061FF29A029FBDE533B9625AD6F6D507FC1B896FF8DAF | ||
170 | :150DDD0011681D62E8C0DBF3AF1BF0CE75E02D104DA9B20FCFF3 | ||
171 | :150DF20039EF1B121D323E69B0F8A1B3D9F52F4D1A4761BD6C70 | ||
172 | :150E0700F1C32D7E8ECE29F283B9EE030B36EBE0277B0B7E623A | ||
173 | :150E1C000E7E36033FF0CEF904FC6C76F0F39845E33DDC47160B | ||
174 | :150E31003F598B9F4A073F98AB5659B0E86F363FD8BF193F51AC | ||
175 | :150E4600073FAB811F78E7C909F8796B71919F8FBE30699C1BBB | ||
176 | :150E5B00C19C66F28334909FD6D9457E30D79C3161052D37C413 | ||
177 | :150E7000D68EE694310A676A3BC63A3F0F6874906BF434C4E84F | ||
178 | :150E8500CD4C0EDE173FBC2CCDF0FF560EE74E2AD65D9091B78B | ||
179 | :150E9A0062CA7F8CE0652EF17B1D79334EFB7959D57995E60779 | ||
180 | :150EAF0058714DDAB868C5631B5601B86ED8DB7E888DCEF53124 | ||
181 | :150EC400DACD37037D05F850E85178AEF0049DCB77D105E03353 | ||
182 | :150ED9000DBC9346C056AB799DB24D35C8A1447D3EC5BAF55427 | ||
183 | :150EEE00A207E093F41C4F53C60FF79E663564409DB6A597D514 | ||
184 | :150F03005EBAC23AB67C97EDA99DCFF66E59C8F6F52E639D97C5 | ||
185 | :150F180056B223B56718DED37CFCDB32DCD30CFFB7E7D9DEF32D | ||
186 | :150F2D00ACF2C231F5E0A5FD500FEC5FE2E4EB9D30F155D1D593 | ||
187 | :150F4200CD6363B176D6B090F8FCCE3121403B3B7A93F1CDD75E | ||
188 | :150F57000A378C2B5A3BC77889FA09D44FB08EB7B33B9B26184E | ||
189 | :150F6C00875AE06A1DF179434911ABC046F2DCE4318EF6C5F74D | ||
190 | :150F81004F46AC1A413EC789CCB844C51D2BBF8AFF6810E6FCBA | ||
191 | :150F96009A687BF8A8DBAC7586451B66A4007551554AEDD6878E | ||
192 | :150FAB00946EBD5F9926A5D4236543CA91E88072186CF9ACFEB4 | ||
193 | :150FC00086E27DEF0FAA8005E0837A9722AF632AFA4185833FB6 | ||
194 | :150FD500BC8390D890187F52AB6CFCC4FE770F2B6EFCFB0A33BF | ||
195 | :150FEA003F6A63B934C991E73990C72A925F35CC4A3E8179C4C6 | ||
196 | :150FFF00CA8567451D63E6AFB366AC039D99F98F5B303D026617 | ||
197 | :1510140047314F8AFDF09845277B039D3BC6D131F3E559510FD6 | ||
198 | :15102900D97432169D0F2D3A264C0F33E3709A87AF12D21B76BE | ||
199 | :15103E00B5941F48A981E83CBCDFF3FBB5EF468290ABAE5E372C | ||
200 | :15105300E5FD40FBEBC6CBD0F782FEEB14380779061290B39AFC | ||
201 | :151068005DA1745CA678DF1B66C92CC489A4AB65333D652C022E | ||
202 | :15107D001C92FC3DC8435D3C14DD1F3948BA13788676877AE21E | ||
203 | :15109200D23D50A3C5468CB974C4705BBA8ED02E234A0F1A8197 | ||
204 | :1510A7007C8A734F6AE702DA67605C895D0039F2FD5C069C38D8 | ||
205 | :1510BC000E276206072EAF93E6A617FA9A9DEBEB9443AA61E19E | ||
206 | :1510D100C0B5D8475C147049A1FA78B464BD1FD647E97306D4F3 | ||
207 | :1510E60010D6FAEE09D7E7FE1173537D1C7909C3DC02A833C232 | ||
208 | :1510FB00B48BE1DD96413A120AFD2FC3E3C238779A19E470422A | ||
209 | :15111000D23A0C3FE46037D6BBB17EC3AB751B95DA39718F365C | ||
210 | :15112500DE8FCF5A7EAC8FF3E331FFCDA614D9E1BF55502B8C04 | ||
211 | :15113A00F928F801DA0F7DB4FCC0805A43E6A9A66CF5A66CD11A | ||
212 | :15114F00BE66A73F0768170F6A529384E766C29917ECB1733E0C | ||
213 | :15116400F1E1FBBE999DCAC54DC4F7E2CCA422D3F9C236ABD16A | ||
214 | :151179000EB096AFEE7E085BCF52F13F2D15B383264E79893719 | ||
215 | :15118E002E43FF568F0947444B8336DF14F65D1D91AB16A81DE5 | ||
216 | :1511A300EEF90F79AC71EED71FB2E7F1FF6AE4E8DC07251B479E | ||
217 | :1511B800B4FB41BFDD5F591C17FB04E498438E36617E801A931D | ||
218 | :1511CD004E8BF5604D631CA2520BD51883B37A0061360998CB74 | ||
219 | :1511E200D6779F4EBCA3A0247692076973837DCF82DF034657E0 | ||
220 | :1511F700342F36BFD19B7797884F4E7633C487637EB95B7D077F | ||
221 | :15120C00713AE82F17B829C33B5949FE0CE87719B80EE95BEBFC | ||
222 | :1512210032B80EE89D71F62F3AF158BF83B9E39073F0FBEF1552 | ||
223 | :15123600568DF74FFC285B8BFB92DE1B09D2798DCC8A0F3FA1C4 | ||
224 | :15124B000F35EA629F778AEFE5BBA75C413ADC2F3F67DE75C28B | ||
225 | :1512600018E4AB1A1BBFA4CD6558B309D81F7EDE4272FD7C9ADA | ||
226 | :1512750003B6C2829520374F16EE10F0BA0AE2DD0B5A5D13D6FA | ||
227 | :15128A0008E677FE432A9C9E184473435AF339F8E46CD63B4C08 | ||
228 | :15129F00104FA67AF42893454EE83FF3BB42A11AEF06B789B5BD | ||
229 | :1512B40069B17681B69FD5C84FAB776AE759448333656C9E811D | ||
230 | :1512C900F489DC6F081EB09F4B19923C5745DC52FEA88DDBE4E5 | ||
231 | :1512DE0011F6DA589FA78C2CD058A44D6FACD2A6477EA04D6DF9 | ||
232 | :1512F30044BE376975CDB67C923C5B2D956F3273820F7BACC455 | ||
233 | :151308007E7C18BF7D9F03DB65E24B08A9C63AC6E53BA7BEE98E | ||
234 | :15131D00C2FBC734D64D747A10725E6CC8C0DA424A0E31D7BBE7 | ||
235 | :15133200E7D5FF065E7B5CC48BF6C77BF9465AD358456B227E15 | ||
236 | :151347007A47E366D0D32A5ADBB8CEB237E2A8965F1577D4E057 | ||
237 | :15135C000C34289F51CB80C60298AF86BE1BFA088773F6B90BB5 | ||
238 | :15137100E15DD638AE0F26E78571BD8CB2027D19F8284CA5ECCB | ||
239 | :1513860008E953189C8702AE3EF17DE059F17F5203D67D685A64 | ||
240 | :15139B009CD1719F797D57D4368823337C4755D7CC4EF57052CB | ||
241 | :1513B0006AA9B9705E9D23EE5933868EDF5E760E88EF34384755 | ||
242 | :1513C5008E0DB1CBE2FB0C65B3C8A9E508432C18F17DA56F880C | ||
243 | :1513DA00CDD2BE6A126B89398EDF4DF4248EFFBC89C883064DB6 | ||
244 | :1513EF00A6F03B8821AF1950A330EED79AC5B817DEA980AB6D72 | ||
245 | :1514040092F05E22F6BA7118FC026582FD5F8D7715B3A2A71B27 | ||
246 | :15141900C59D456ED038AC4942EF788FF70CC43C5BC6A0252368 | ||
247 | :15142E00CA11B1F27D7D01CF75FF43CC13064755A4D993BC91CC | ||
248 | :151443001988C3038611280C0F1CD6E045326894648038C168C9 | ||
249 | :151458002556E40688EE7B5CD089266EB450729055768B5B5FCA | ||
250 | :15146D003081041F5CF34C206BE1DE84CD94932B2203071A3D8B | ||
251 | :15148200ACCBDE79BB68A5AE721677C7D5B9DEECD69E4779615E | ||
252 | :151497008D6CDC65AB38E7BEAFBBDFCC9BC9A0E0DED5FD987AC3 | ||
253 | :1514AC006FBEEEF77D5F7FFDF5F77DDDFD7547F5F31B315A88AC | ||
254 | :1514C1001BB88ED10BB618607BCEF31C0253B2E941318E59B05A | ||
255 | :1514D600E751CCF18671A03F4CDCB28FC53814642D3F01387A39 | ||
256 | :1514EB00433155770FB3BC0699D9A328ABEF954FB03595493179 | ||
257 | :151500002F4698A20CB3BD8A291B2C2060E47206562A6057702E | ||
258 | :151515006D46C454576DDF30DD1B292025CAB0698761DCE8CF5F | ||
259 | :15152A00819102899467C3E8203CE5C8192A83AFA9C032D15E21 | ||
260 | :15153F00DC8F21F4769E6B22BEBFF4E59C7F70B1EFE3D4E291CB | ||
261 | :151554003FC5FFF019EAE881BE606BC0316AD10929C3F44592AE | ||
262 | :1515690030FAF4188BBB3F01BB07D1C3168CBB93E9B888CB7601 | ||
263 | :15157E00C1548AC935947C3DCD6728F916EDE819566B6CBC2309 | ||
264 | :151593004EF46F7DA14186B319437E5C0345D9C8C3B42F1C65B4 | ||
265 | :1515A800F07A019F12B1117B029F3EDC2F92193EA6035EFC1FE0 | ||
266 | :1515BD008E1956FFA7447F768BFE64BA60C90D6224A00FF3A197 | ||
267 | :1515D200D7696F826C29B2D96359B4C7259E72CEF3BD2FD3E9DE | ||
268 | :1515E700C559F685CBFB75B6CF555344C27ADD1915C74C0DDB68 | ||
269 | :1515FC0013E730B2613AACC00E2BC6711C376BC1E339C47B8D20 | ||
270 | :15161100CCE1A1E409E0F7049D3FC9E4EED3053F0C0636CD57B4 | ||
271 | :15162600191773BF8421C3372C8708FA8C3DC3678CD9888F0E7C | ||
272 | :15163B009BF9EA933CF549BAFE5B5CD600837773773ADE8E53ED | ||
273 | :151650006931CC3E443BF19DB5C90BBC5B6D82F729479CE97FDA | ||
274 | :15166500C09B29DF579729B7607BF3C0A40DD3614E3B2C67FFB1 | ||
275 | :15167A0091E9BB1863D6F8B58FED8E9CB18D4FE7C7710DCBAE50 | ||
276 | :15168F00F58D9EE71BABEC255B19C674ED8BC82CCBA6A03CAC55 | ||
277 | :1516A400727C5F72A1536BC8299F85B4EF47DA71A3028C776FB2 | ||
278 | :1516B900C4B945C6BD0EC0157E28639F5037702C5865E5F6325F | ||
279 | :1516CE0090834BE0614F1B8EA21C1C56FBB9FE71989E0B037C5D | ||
280 | :1516E3007B2C983703D3F3C0667AB261D8A62E5B9B2D58671E54 | ||
281 | :1516F80058A1C70ED38D4431D8B685423E246AA0FDC0F1E915CD | ||
282 | :15170D00FA1E4FEB3BC0D017D8D63A4811616B1AA8BF5EA6BF42 | ||
283 | :1517220031C3D2F39907713D3C418FC2B8F785B86DCB8743BE31 | ||
284 | :15173700611C5086397BF230D6331B6CF350B4EF681FB7A15DC2 | ||
285 | :15174C00C1B526F8EEC0C2B8CAF0839EC14490E683CB36B861D9 | ||
286 | :15176100AFBF203F5C0678AB43D8DF626E732D99615C500F659D | ||
287 | :1517760079E5E5CDDFD6591F27B43E7DB8EDC0C284CA7310AFE4 | ||
288 | :15178B00436EFF8BB8B09D5FD507C68DF0F58D7165F76B42D8B7 | ||
289 | :1517A0007BCB77737B9C2DEB6C7B9C8717F886F302710A3E0187 | ||
290 | :1517B500F76CC4C7F6C3F3C8214F7D92AE9FCDDF6E9BDEE11865 | ||
291 | :1517CA007678A68F71E2993EC60B3CD3C733C903DBEF9E3EC6AB | ||
292 | :1517DF009D9EE9E359CA8161FD57ECDF66E6BC221EC371CE7D03 | ||
293 | :1517F40003CA7489CDF7C15397785C62129B2F9473CA245B99AC | ||
294 | :1518090037A7CC652B5B905356642B5B2C0B3F129834E23DC8D7 | ||
295 | :15181E00972EF2CBAD582446838A3390893D6294E5EA425F6464 | ||
296 | :15183300628FA8C6E38C9CD853CEE4C8C8BE924647DD2AE853AA | ||
297 | :1518480098670742867C3B2105072B357D32E5763A3AD5367878 | ||
298 | :15185D004A20935E85AFC3FE0874EA70F4F7E5646A805EE941AA | ||
299 | :15187200044EC44576EDFFFFFDD5D610F7D86729370D75A835F8 | ||
300 | :15188700F749EBACBD4DDC2F24EDFA293667688F9E1A67CFD1D9 | ||
301 | :15189C00532CC7AA3D796A929DC989D2C446BE16678B410D07AF | ||
302 | :1518B10019FE18E539713F71ABF7F3BC65EE67BBC1CF0E829F2F | ||
303 | :1518C600051FC9E456C2E466F9EA1AE083783AD5F2CF84EC22A0 | ||
304 | :1518DB000E263BB47D51C0E307F847F749AB91D6D98D7C8C8CD2 | ||
305 | :1518F000C013D71B1D0A8B154DFCBF212BF68CD107BF617F17F3 | ||
306 | :15190500B179E0A4896D045924842C12421609218B04CAA2F079 | ||
307 | :15191A005E57A33D7EB95EF9E158F228CB033395AEC0D1422EFD | ||
308 | :15192F002B0EBB13600702F12CD83D00EB0B9CB66045089B0F62 | ||
309 | :15194400B05B03A30863FB3A5CA6572E810C4196172F4D9765C3 | ||
310 | :15195900C37AE2BE700965E95F7DBDEDBADEF69CCBA30F054261 | ||
311 | :15196E001F3EAA26EEDAEA6C3E2B24E2AE075E9CC0EBDA3CBC7E | ||
312 | :15198300C6A17E29E3B574F58DF4C1F5F27B3C0FBF8582DF525A | ||
313 | :15199800A0DD1F9AAEBFFA35F4B77322E52E8076B44F4C6F471A | ||
314 | :1519AD0012F0344F603BBCAB6F54976EA43DF13CED91447B1A71 | ||
315 | :1519C200818773F7417BBE01FDD6FF8236297E2A2BA594D97E0D | ||
316 | :1519D700B0798EBB0889001CFF4BA4D6D88DEF01D550403A8B99 | ||
317 | :1519EC0015CD9495EA57D91E33D899FA08AE37478DF001EE1352 | ||
318 | :151A010095837CAE32FE32F86249077FD8CDD64B0DA837161922 | ||
319 | :151A1600328B9A4E9A139F72DC7EC09B9AAD1B53F0DFC1FFBBA4 | ||
320 | :151A2B002E7C9ACDCF0551F70A3C1B20DEF42A9C1E51393DA4D7 | ||
321 | :151A400083F4D02BDBE92D867A454D43663DD0DB2D709CFE9440 | ||
322 | :151A5500D3EB14F4E0BFCB2E4F59C8B3086489E5ED5524AB7C94 | ||
323 | :151A6A008E65FFAA7879434EF95C513E26CACB73CAE789F2E328 | ||
324 | :151A7F00A2DCCBCA278D1A9A39CF92823652D2A5E2DE9D0B7DD7 | ||
325 | :151A940074CEF9956E888768D4B905E28CAD55B8AEA977AD2A29 | ||
326 | :151AA90056A4A02AE29A9E8517D5AAD0BE60AD2D5F60CF48D3BE | ||
327 | :151ABE000728ABE7DB3FAC0AD8E01FFFF0E5AB085FB3F5832A70 | ||
328 | :151AD3007B7EC18537BFFF1AC29FF8DB9F559162DCDBEE373A7F | ||
329 | :151AE800FFE5856AAF4FDF4A1E236E974ADCD3F8B4E58F2987E0 | ||
330 | :151AFD00B2FD338F35264DB4210E0F9FC331989CDD362B3EC2C4 | ||
331 | :151B12007A3341D7A7D6F2DC19ACDB5337ACCE8C3C12D85FC732 | ||
332 | :151B2700EC391DB5EC39945967724637E69FEF1B9FA7DCF14B5D | ||
333 | :151B3C002977661E46B55EDDAFE2BE0AC48DEEEE8551753D59D3 | ||
334 | :151B51001EF490E5AB16298EE0799045CF42AA6ED0FDC17369BF | ||
335 | :151B6600B9C4D99AC4CD4C1E740FC6284E88F50673CADDB672FB | ||
336 | :151B7B0009CA3B3372ED2E9048B70BCA1D65D07FA2CE22E6D307 | ||
337 | :151B9000F8B73741FD0651FF0EB0FF3EE1DFB0CC07651584EB9F | ||
338 | :151BA50013FE5F7261402B81FF8B6C75965C8869DE1C7E1E8494 | ||
339 | :151BBA007E4A4462A60B7C6CF96F53EEE8D594BBF9CBD42CD1C5 | ||
340 | :151BCF00BE7511B0D3A03F5976C52BF45442F9839E86927F6EF3 | ||
341 | :151BE400E84E320BF50CE3600B37AE5FE21EA16CE30B73854FA4 | ||
342 | :151BF90047980F360222BFA108F02E00F97B9712B7EEE7BABFE7 | ||
343 | :151C0E00600DE016FB3054F8F31749BFD13B3AA8BEB90CF7E984 | ||
344 | :151C230002068F654B0C561EA830D07717B863DA0F963E5CEE8D | ||
345 | :151C3800AD8CD2D65732F1168577A90F2255788EC2EF1CFC9498 | ||
346 | :151C4D005EB0AFF01B17BFD65EBEFE85F82EFE12D7BF94C6F455 | ||
347 | :151C6200BC4CC0A3FFC1E161012F009F5683EF7480CE837E2B7B | ||
348 | :151C770000FF50CCD618264DE9DB84BC823E830E9896DCADF9D7 | ||
349 | :151C8C000796596D9394037406B3ADD4083C4A48D17FA6DC93CD | ||
350 | :151CA100249BAEEE22B370AD1BF1FF33CC476702DD31A81376E8 | ||
351 | :151CB600733F65E191051EF932E76DF493947B90E7F5883A101A | ||
352 | :151CCB0007D1210DC7EC646A361B23B837D6F7F7C7198C4CCED0 | ||
353 | :151CE00026DE9F0EF277F883F2CED48D9AB89FD6377A5C9D2F99 | ||
354 | :151CF500B1F50E93EFB3454DDC575B6BA3C3D71DFB8DC7C61FD8 | ||
355 | :151D0A001B5F363A98A53F37A3FE209FA043814ADCA386B8203C | ||
356 | :151D1F003C443146DBAFAC0BB01C45CC8D8BBC4B95C819C3C77B | ||
357 | :151D340072E8BF303D7CED9BF68A7557BE8E3BC2F70C020ADF8D | ||
358 | :151D49002F40BA387EC227CDE7593FDC40FC373E8438D2F3B0B3 | ||
359 | :151D5E00AFE741D0065A69FA79F475DB3AF0CB69FB17A5E3B899 | ||
360 | :151D7300D62B1BEC9C14192D20E037D8FA3EE0A0631B591E841D | ||
361 | :151D8800CF9A67CD2103EC0C12CA784CD834FCBEFB5EE296C690 | ||
362 | :151D9D005FD2E40F5F52ED362D6D77D99C6CC448FDD57B923824 | ||
363 | :151DB2003324A32D66F3191AA37790C120E6EA4FFDFB7095BD05 | ||
364 | :151DC7006F6E1263BBA482E45D1FE56B9BBAC03B22F026742EFA | ||
365 | :151DDC003FC0ABC738DE25C7B3F0CE1078C757E7E0457B08F1E8 | ||
366 | :151DF100D5BE85FD2A3BAF0F3610F126393E7D19EEC9CB83B482 | ||
367 | :151E06003039AC4BC933BAAB28C6D6F966029DB961AA3922869F | ||
368 | :151E1B007128296D91944EE316F91D6D2C95F279A25230334FC2 | ||
369 | :151E30000D1B1877EE72A0ADAA6DB4CEDD635E358B4B587EE23F | ||
370 | :151E4500A4A9E2B3B8A291C80FBCCAE64201E554E8D13CED0713 | ||
371 | :151E5A00FF15E847FFD5CFFCD7BE8523AA67B4EB5E466F5CEA4B | ||
372 | :151E6F00A49571CE7B38A67B301E13F082484C972B13AC7D8726 | ||
373 | :151E8400C801D584B1ECDA30C8F6D1BE85361EFAC411194EB76D | ||
374 | :151E99006F6E6830687DCBED46FA7D1A3FFDFD997CEC7DE0FFB5 | ||
375 | :151EAE003DBAE0875E831F80CB601F91173B4D07DF4FDF9375AB | ||
376 | :151EC3002604ED1501BE8B47F83C5FC44F203B2E1F9E4F922D53 | ||
377 | :151ED80047B9EBD5ACFD0B186FC88303FA1AD73F43C9237B8A4E | ||
378 | :151EED00F95C4DFF25C07BC351D5E5116B64C0D3C5421DCF3873 | ||
379 | :151F0200CFC2F2B64D3C470A7DCC3231BFAB653A12D7FF14CA3C | ||
380 | :151F17002CDE19DF507FD7261607B33C8E7A51EF7BB67AD5C94A | ||
381 | :151F2C00D7F7C04F47786213DBD3D0314F00DB82F349E4A3F77A | ||
382 | :151F4100A598EA1DE5FC20DCA2DB2AF09DCC4377C446779BA8EC | ||
383 | :151F5600F7B6ADDE7AA08BF5466DF5DA44BD9FE4E16F7DF2845B | ||
384 | :151F6B008EE3EA1CE3F16F74F403B5789E06F83BCC746798AD4C | ||
385 | :151F800015F7FE1DF04A0619AFB5365EDB05EEF7F3F03A6EE3A1 | ||
386 | :151F95006197A8F78F7978BD60ABB75BD4FBD7AFE035BA39C326 | ||
387 | :151FAA006BFDD7F05A6FE33529700F6C9ECE6B7C7386875F8943 | ||
388 | :151FBF007A439BAFD19F9B33FD59738DFEACB1D1BD68F5671EA7 | ||
389 | :151FD400BA2336BA13567F5E836E77038EAFB328031AB6D3C5F7 | ||
390 | :151FE900F68AFB3F106EE9FC7EA87F84C4D23ADFE0E43A7FD59C | ||
391 | :151FFE00C1755E6FC8D00E3B39ED8E86AFA00D741B045D8B5E7B | ||
392 | :1520130083AD9D0D02474F7E1C14C7ACB516ADE6DA3C3C4FF630 | ||
393 | :152028005AC6DEB1F18CE771E5E394F92FBCB7473E4D31CE73E4 | ||
394 | :15203D00157569FB206E94C197C9F5EF6A0B8C33DA41DCA3B7F4 | ||
395 | :15205200D9A01F40BBF2D91EEB3B9F23A61ED18755D417BEF704 | ||
396 | :15206700774085F9EA1E9C9FAE67B832BEE12EC055007E216DFF | ||
397 | :15207C005743C3AA6B438CD954664F2D7FA1A33D8D317B2AD7C5 | ||
398 | :1520910001FF60471DB6F7ACF61663BE4EBFEA5848B514E65951 | ||
399 | :1520A600E0BAEF659EFBC57D5382D3A7C29E86FB786C07BE8FF4 | ||
400 | :1520BB00B765909DE791C3BA46D12F4586C12FBDADB9A2670C99 | ||
401 | :1520D000F44D79FDC98F32F33B9ECFD0A9F970BB1AD712C4FFBC | ||
402 | :1520E500A9546A5EEE5C8FAF47B2FD70B3640AECAB1BC656B88C | ||
403 | :1520FA00D4A0A18E36B4C5AE426E93252BCEC6F32DBF4BA57368 | ||
404 | :15210F003F9529969F39DF9E372855F27B70545B3DBC8028B73B | ||
405 | :152124001EFA84C30A9EA11AA188E7093C4355E6C0DBD558FC4D | ||
406 | :15213900EB284E3462F92DA141ED96D0DBA8336615D6C19800DF | ||
407 | :15214E00F3A901EEDB1A3333FFDFD618ECCF6218A3101F4D680E | ||
408 | :15216300FCFBB7D1A77B0B3C1DDA7BBFCDF0E49F6271928DA775 | ||
409 | :152178008451454EAEF1298E80451BEF02BA83D18C52ACEFBB81 | ||
410 | :15218D00F50B33FDBEEE8B349DE492936B0BD2795F309F147980 | ||
411 | :1521A200F8C8D7FC5B3127A28F9AEC2C5729CB19BA17C5217371 | ||
412 | :1521B7005CBC6E9CA2FCC12D9AB2BC17FAFA347CD36B4ACA69E7 | ||
413 | :1521CC00B3D1164F5E7C84906714E79AB30E316FCD43E7218C26 | ||
414 | :1521E1005DF2E2F69B4EF94DC07DD620B4CF94A2EF9A986F8196 | ||
415 | :1521F600EB9F69DF8DF38A42317E11EFB7C57D14A20CFFE7B9AD | ||
416 | :15220B00EF83E596A21E4DCC40BE127482E78C5397E0CF65E79A | ||
417 | :1522200003FA1BF945BCBE6082E51BB1BC0FF9A4897CC83F5F73 | ||
418 | :152235008EBC73DD13EBF1150319FD463C138F703CFE298E9FB9 | ||
419 | :15224A00E34D30F9CCFF791775C01C0EEFAFE823C32A9EA3C3D2 | ||
420 | :15225F0098977F9330B14ED63800FCC707ECF7C9F07623FEC926 | ||
421 | :152274004778FB389D78161D6B4D00EB323926B91C6FD9DA6987 | ||
422 | :15228900E23D116C4E63A7993E5F1B32382F1586CCE4526BF06A | ||
423 | :15229E009C8480E112F9A00C1E1EA44F2DC5D8F518CB47B4F334 | ||
424 | :1522B300E07D6D39B5F71DD431257908F7E6A9A5272CC606DB7A | ||
425 | :1522C8007A9874AAECDEA8B0C1E4827C61B904EDA515BA819379 | ||
426 | :1522DD00E4C2A24E8D1EB8533B7F21E526E3036CFEEDC53E92E8 | ||
427 | :1522F2004F6992F22EF545F8F9796BEEB2A070FAFCA9A36E8876 | ||
428 | :15230700CDE7B2E650E327CD7B6F740E15FE4BD3D229CC23ECDB | ||
429 | :15231C0077F2F969B64E711D425E4A845C589F04A33C7F4D1EC1 | ||
430 | :1523310030713E8DFE0CF5097580C94AE773E9A35FA6E6D8F47E | ||
431 | :15234600384B9F59DE7800C63E9D30E6F9028DB87EE2519697DC | ||
432 | :15235B007F88FE14E6E9CF287706AFC098BC2BE965E7B07B1FA4 | ||
433 | :15237000E5F4E38FE2251B0798DE610E97809B083F27E6B551F3 | ||
434 | :152385005137915357C04D841F15E3DDC2FF9EF8E67CCE37023B | ||
435 | :15239A006E22BC55E03F27EA2673EA0AB889F0B502FF3281BF77 | ||
436 | :1523AF0053D4C57AF8BED8666FBA6D65F88E67DBF04C9B0BF426 | ||
437 | :1523C400A8107C95A40C98282F49DEAFA19F092883788676EE70 | ||
438 | :1523D900DC505F9504F3D3F91D135A9132642ED22FADF5557FB6 | ||
439 | :1523EE00A64991D3E66B51E71617CFFB9C373332638D14993002 | ||
440 | :152403002D9D9D09B62D7915D7D13263E0FBE02325766E884EE9 | ||
441 | :152418001B8F627CA5ED0AE2900F0E68BD85832AF23677ABDF7C | ||
442 | :15242D00B4C633D301B409101B3892EFB2FD46FEFD88993B9E8E | ||
443 | :1524420079FE24D08431631F272FDDDCA925FE89AFF3C9C2A6AC | ||
444 | :152457007DDD38D98BB9A2D618E91960392BB2F0A7385696619D | ||
445 | :15246C006E00C41A8FB1B5F7CCDED306C51910E7A9FEF0FD47F0 | ||
446 | :15248100DB78AA2DF83FB0D139F1445819A04E4F17936729E02E | ||
447 | :15249600ABFF2CE377E9E7397E1778C13A44EEC03326265B170D | ||
448 | :1524AB00298E373A0FC6B43ED015796D8CDFCF00B8703D05C6F8 | ||
449 | :1524C000E33C764700F8662CC77BC33087D8F2BFB8BFAA46965F | ||
450 | :1524D500D2420FDEBDD7618CFF3A435BCE1387B8224097AF4988 | ||
451 | :1524EA0098D85F7DE0F7E5B303C6154113FB378B2694BB7268E4 | ||
452 | :1524FF0066B7BFA4B1C1463F6CA3AFE4A12FD9E82FCE43DF7F80 | ||
453 | :1525140083F431BEE8AC0C18162FC8C3D825CEC362A0954B5FF5 | ||
454 | :152529003E3BC46829910103EF4082B9B789B18FA4F03B8F16DC | ||
455 | :15253E004706E861887BD0A74DD9E31C5C7393FD66679DA1E108 | ||
456 | :152553005D60532FFAABD87E5FC96D2BFC75CD41E54F2A2AB7BB | ||
457 | :152568002A0FFEF1A60794CDDFDBD9DEF2EC4E6553CBB696A616 | ||
458 | :15257D009D2D41A5FAF107B7EF686968DDFEDDEFB4B63F5EBE5C | ||
459 | :15259200F2EE9501A5E4999DAD4FEFD8B1FDB9C79B9E6F0AADAF | ||
460 | :1525A7005A55B9EAEE157F7497F2D4D3DB5A762A81CAB255156B | ||
461 | :1525BC006595ABE125581E0896DFADF8D3FB5B16BDB2B2E696EB | ||
462 | :1525D100B6EDED654F6E7FB6ADACA9B9A96DE70B65CF363DFDA7 | ||
463 | :1525E6005CD9CE1D4F96B5EC6C2B7BEA85B2A6A66D0CB66DFB24 | ||
464 | :1525FB00F6B6953B6F5B758F72A7D2D2FC74BBD2DCF254D3775B | ||
465 | :15261000B7B52B4FB6363DF79D16A564577BCBAEF61548E5FA76 | ||
466 | :15262500F037EF78FAF9961D654F41B31E6F6A7FF6F1E61DCF95 | ||
467 | :15263A00AF7CF2B67B2AAE853F8D9E9D679AE30B37EE67F71A4D | ||
468 | :15264F00F88DB9BE8AC612A59CAEC4B35CD6398D88B406EFD1B8 | ||
469 | :1526640038143AD25640FA8DC6DFA7D2E7341A958DE627BF703B | ||
470 | :15267900AC91E48735BF526DF861EC7D0CB6C40BCF37D176E26F | ||
471 | :15268E003E09DD6FB47E9172FF74A9146C50866829942D22C3C6 | ||
472 | :1526A3005521A587B2F2B0B4370030B4376B6D30AC27830F04B5 | ||
473 | :1526B8009C66B752B4CEF2090BC036CE203C96C0FF5701F73E78 | ||
474 | :1526CD00F9E5368C13CFFD756A16F2653FD7603FD310BDC2F71F | ||
475 | :1526E200CABA58FD12A31FEA13F9B2E9856FCE027D3B4FB48D99 | ||
476 | :1526F700B0B3D32B1D642EF2877C78959314DB3003E6A998E3FD | ||
477 | :15270C0046C657E03EA9D7577DA7866DEF02393A7F52A9E1B5D5 | ||
478 | :152721006A7EC0C5D7AB0E1961E58746CD08D08678CA0BDF5BC8 | ||
479 | :1527360074F01C97B77A850630D34EF3A1548AD1EC62FD72CC9E | ||
480 | :15274B003C9D4ACDC1FBC4F8BA738F7113F805C439F916AEE733 | ||
481 | :152760000700768CF1E5047F7908F90AEFC775B9F956BF5967CC | ||
482 | :152775006CA2BFC3BEBBCCFA0EF7571405C69DDC957029F7980F | ||
483 | :15278A00CEEAE3D0DF07186E1C8738068B94D7CCD22F1D6BED4A | ||
484 | :15279F00EBBF28734BDEF67EA87927E5FAAAF2D27752B3ECFD49 | ||
485 | :1527B40081FCC8C08FD7D65F6D1197114DFEEC556C93121D4848 | ||
486 | :1527C900CCC13BE7E8622314ED4890E2B6464F926CF14697828B | ||
487 | :1527DE003F3EC7EEC3F3F96AA1ED0F18787F29CE1DDF9470BE3A | ||
488 | :1527F300A41A18D348EF3FA3E11D51F5B8CF12C6B3DB611693D4 | ||
489 | :15280800F6EA41D50C55AEDBA414ACFBD079D1F0856E67EB8DA0 | ||
490 | :15281D00462235EB23B12F128AF6D09BB2F4A01EF3BFE763BD01 | ||
491 | :1528320066A8773ABDAF1231F07EEE40B49A12F915EA666D83D9 | ||
492 | :15284700793795F63ADCEB35DC4767F617BEDFE3C0F58C8BFC2C | ||
493 | :15285C00CEAAE601889DCB204E78925E29242ECFD880F69872A0 | ||
494 | :152871007370AE72F3AA3796CE0FBEBAECD6E018C091DED4894A | ||
495 | :15288600D4AC658A23C8F8917B0C5C7376C1383C0F7A9FDE0F44 | ||
496 | :15289B001B3FC6FDF1F831F32F1696A86C7D186CE4D142116F97 | ||
497 | :1528B000290EB6761A075C565DAB5E3BD4395837A0E29DA7C812 | ||
498 | :1528C5002FAEE7E6D2C2F18BDFB7C2F7EF39385FB8A679E10D71 | ||
499 | :1528DA001C3F7BE9E2A241CDFBDF47282A4A6D14CFB45F64E72D | ||
500 | :1528EF00E7CCD0EB6A1FE05D5454AADD8577C28E47D55272D174 | ||
501 | :15290400E80C9D68C33D2E05FBA96E8566429FA0AE38770F1B8D | ||
502 | :15291900B8B71FC4F58EF08F791F88B18B31B4C4E6610AF015FA | ||
503 | :15292E006A64FC877F6C8E4DA5DCA70B783BD7439FAECDD37719 | ||
504 | :15294300308F9E9FDBA6DEA914CBE9403CEDE2FB4530C69CE3B3 | ||
505 | :152958003A8C83FD4601CC4B42C923863196725BDFCE80B1811F | ||
506 | :15296D0036F0AC903BEEA7A22CC22007AB4E3F94B1F7F1970D63 | ||
507 | :15298200CCA762FB8F50A7F48D6CD95F0539E6E315C7ED82680B | ||
508 | :1529970007F57FCE653E359CFD1D933FEA33B305FB0D4BD6BDC7 | ||
509 | :1529AC0020EBDAE88079F5B8F0F9F676A34E8A761FFD0D6F378E | ||
510 | :1529C100F63DE2DB05F84A599F458C5D2C6E133AFA2BAEA378CF | ||
511 | :1529D6007EDA51F780867B86DFB2F450F40997670657E8379C5D | ||
512 | :1529EB00E736D00DE083E9C6A2A2B59AEF178EA0A523783CBFC9 | ||
513 | :152A00008DEFB30A1D39A3625CB78C9C5987FAE1AD4C30BD3021 | ||
514 | :152A1500F565AAEBFD214D025BBB4CE8035F0FC8EEFF1190B788 | ||
515 | :152A2A004F3EC6E29DD9A01F5EB0BF577E2DE46E8D0BDB37B8AA | ||
516 | :152A3F00679D4FEE2B717C437D94FD343A30AE7A218EAC17FDA3 | ||
517 | :152A54003EC3A623EDA023AD1F701D71809C25A123E597B99C53 | ||
518 | :152A690059EE01F6FFF14C3F223E4FB84D6BFDB7B672B0676627 | ||
519 | :152A7E0049B4CEF447FFA7BDEF8F8EE2B8F3AC1EF54833D22015 | ||
520 | :152A93005AC3CC20B0905A443892A33833625024598481B05E2D | ||
521 | :152AA8009910769673B2DD92B0C7B1BD109B64B93B6E1FEF85E7 | ||
522 | :152ABD00C42318890137B8E913589615337224AF7C0B398507C9 | ||
523 | :152AD200397C4F24E2C239B021DC2C211C9764F1388FD8BAACE3 | ||
524 | :152AE700CF283E62E3C466EEFBA9EE1E8D846CECDDBDF7EE8F21 | ||
525 | :152AFC009B7EF3BAEBF7B7BEDF6F557DABEA5BDF5A69AC4D3DC0 | ||
526 | :152B110064AC4ED519D4075AF65353DC2E34E6371EB9869F2B10 | ||
527 | :152B26000ACEB2EE45FDB55654BA5B0DDE817DA2914EC869824F | ||
528 | :152B3B007B50C5FAD98475AE1E32F7037C3D69949F0DE4EB5DA3 | ||
529 | :152B5000B09131CED8A10527686E3ACCD7BEA454B701BDC4D514 | ||
530 | :152B6500A9935CDE8BA786C193F324B9DB582D9F34747AFBF5F8 | ||
531 | :152B7A0011F5B46C86B3EA61EDEA07C8832E36E6FE07F17305BB | ||
532 | :152B8F005F77BC253C273C2C7C56F00937D8AFD97F633F64DFE9 | ||
533 | :152BA40063C3EC5966B0DD6C07DBCEFE9A6D618FB38DEC61F62A | ||
534 | :152BB90020EB600AFB125BCFFE8C7D917D81B5B17BD96AB68A61 | ||
535 | :152BCE00AD642BD8729A41B6B066D6C41AD93216664B59030BD8 | ||
536 | :152BE300B120FB0CBB9B7D9AD5D3F3297617ABA3A7967D929E0F | ||
537 | :152BF8003BD9127A6AE8F9043D8BE9A9A647A6A78A3F95F42CC7 | ||
538 | :152C0D00E24F057FEEE0CF42EB59C09F72EB999F7B02D6E3CFE1 | ||
539 | :152C22003DBEBC675EDEE39DF694CD78A45B9EB9B73CA5B33E15 | ||
540 | :152C3700733EF0F17CE85372DBA7F8233FEEDB3E2E6E3B338E52 | ||
541 | :152C4C00F3B1C15A4DE6674B4856A96CEA8C32F928FC6AC84FD6 | ||
542 | :152C6100B7BE6BE93B6D7DD7D3B724D037FA96CA5A8A1FD17442 | ||
543 | :152C7600D6A6A569522C098A26C98B8F4A31FAA7E89F597C1419 | ||
544 | :152C8B00E598B6496BB90D3659B6FCDC969F407E31CBAFD8F202 | ||
545 | :152CA00073905FCAF22BB1FC0AC80FF95199FC2CAAC4A2412BC1 | ||
546 | :152CB5002FE8F906AD3CA0D71BB4D2428F374869A202F66465D7 | ||
547 | :152CCA002D880E49BE4BA3D975BF93E469F845B99D8790EE4D6B | ||
548 | :152CDF00090DAE3375D4FEABFB5D679A558E9F0F091BFD90302C | ||
549 | :152CF4006E7F87C24A298CFC0DF88B679B555E76BACEB07167CF | ||
550 | :152D0900E31CF5485B30EA2F719AE8329F770775CCF318EAC994 | ||
551 | :152D1E00D3043B815FE0507298F1E3A7AC70EA135BE5C5866EE7 | ||
552 | :152D3300E593FA2FA67F94E245D15F4A8B0DD105BBA3B3BFA3AF | ||
553 | :152D4800C2549C74DEB7E498FAD62D7F8EFFF1EC5CE82698E770 | ||
554 | :152D5D00F7656DD2B4C76AEA6D705D4699EB74145ADFFC9CB4E6 | ||
555 | :152D720083788DD11C34D8447DA783251C4D4611ECA1469AD5B9 | ||
556 | :152D8700C9EA66BE1E37F943E732E0046EAC898E533A0F6B8218 | ||
557 | :152D9C004EB4514FB8A08E5673C90D4611BB8B60BFCB700622DC | ||
558 | :152DB1009DE959FC24C1F463F25B06FADADA996B124159E77EE0 | ||
559 | :152DC600E0EF029CCB151A44A29914EF6A10313F96AAF537A019 | ||
560 | :152DDB003B2F85A8C826BD9EAF3BC17E6C33D7C9803BEA28A727 | ||
561 | :152DF00032EA74942F9E2957A5785D186F57BCAE01EF28EA9AFF | ||
562 | :152E05000E72191A71391FC3DE6230A8C5799B68D2225CD728D1 | ||
563 | :152E1A0002FF58766E1BC58972FB879095CD33CF312DC2F5F20E | ||
564 | :152E2F0037F133A82CB8C53C03CDB659F714242D5D08ACEBCEA1 | ||
565 | :152E440025A012345F49E83A4B28D8DF81FBAD15E23296DEA113 | ||
566 | :152E59007B64B1814577C2AE9C8BA565DDB4FF6AEA31D5670A9B | ||
567 | :152E6E001A789E941F5F47C277B4574F2E882B42AA17DF464EDC | ||
568 | :152E8300CF23FA5FFB50BF0AF9A02ECA670DA62768DE242EFB76 | ||
569 | :152E9800EE83DFA5FC5FEE833FFCEAC9AF7F865F39F9F5CCF080 | ||
570 | :152EAD00DBBA82E0925EEBFBFA83AF874860D63CF2157D1B3BFC | ||
571 | :152EC200A355AC7C5D6DAF7A25F46CD3045FB75814BF44F57999 | ||
572 | :152ED7004A5BB4F2BCEABA4FE336CACB2DBBF3934F88CBC4D496 | ||
573 | :152EEC0090EEA0F15196BFDFC7F4EB862B69DAE3E476D4C70FBC | ||
574 | :152F01003406307FA2F298FEB7C61DC2EB2AF051CC5E098D3CFA | ||
575 | :152F1600F86623C142B4BD42F09DD7056D9FFAEC86D7B43B22A6 | ||
576 | :152F2B005486B4CF20DCC56FAE581D72ED46F93B47D94821CDB2 | ||
577 | :152F4000E3BE33EA725DA3F05DFDAEB6D7C9FFE97ED3FD3796FB | ||
578 | :152F5500FB3FF59FC966FD7DF679C0E8CFFB128E333AF0B68DCF | ||
579 | :152F6A008D6BF11F14367CEB5B850DD07FE84F3FAB2CBCF0B4B0 | ||
580 | :152F7F005270FEA2BA865D0A2D1C3FA9422748F8C900F4F5CCDC | ||
581 | :152F94003A120D70EED52FFD07F5FA43578C85C2CB14E792E1D4 | ||
582 | :152FA9008A1F69C4BC15F94F3E745E77A50A1B469F285CC6F5AF | ||
583 | :152FBE00645FE26BDE47138E14D1FAB88E7AFCE1507738708AB3 | ||
584 | :152FD300F2977EA3A12E12608EFE68D485FD1069D75189C3FEC9 | ||
585 | :152FE800E3A3AF513B2C96F726B3244F16C9DDF1FD714D11D6BF | ||
586 | :152FFD0069D44E7FAEC36E288D00EC2917F610B4E464F5EF0D02 | ||
587 | :153012008ABBE74DB97E5994E26F8FAD6EE0EBAF05E6594D31D5 | ||
588 | :15302700F56DEA279D0DB1F1C30D4C3FAE4F82FFB0BE47E1EB7B | ||
589 | :15303C00C95F4C1D211EEAE6F6486A2D7B41BCBDE97BB9DDF0EB | ||
590 | :153051005ADED648AE4DEDA5B616D744A2ABC4B430DE2EA635C4 | ||
591 | :15306600E08D3D3257EA00EC1D733BA2E5A9842EB85EC63C93F4 | ||
592 | :15307B00DB0B052FA28DB8CE216CC88842EE4E258CBBE21AF7B7 | ||
593 | :153090007FEF27541EB921134ED2D4D013131BCA486E445B997A | ||
594 | :1530A500AC1E321606529D63379DCB0897C6E9F7B22E89E06916 | ||
595 | :1530BA00A5322EA16D05FB349DFAE156CA97A5068C8BBC7E4946 | ||
596 | :1530CF009DDAA91424C0DEEED6C24C3F053BDAA3E82F7747CE85 | ||
597 | :1530E4002BBF7EB4B0A18F752B7DF1034AE91271595F64AF3217 | ||
598 | :1530F9003FD1ABEEDFA929FB9B2F73D952CA1CEC5BB3A4F2B3DC | ||
599 | :15310E007C8F28181FC5DA6BD9A204F600F58A14AF8FB986EDC6 | ||
600 | :1531230032EDF5E3BB4D24193AF39A2EB411EFEAA78DFDE39A1A | ||
601 | :1531380082F541576A80D2ED028EF95E5E79E6A0519179CEA8B5 | ||
602 | :15314D0025BC54503D338524165038DA67ADBC8BDB6EE1794811 | ||
603 | :153162009A7191E6A1E5F2533AB7B1B841D3289D8EBE418C1DA2 | ||
604 | :15317700D3C3991F50DC5DD4467A699C1B509167762EF4786000 | ||
605 | :15318C004B80BAFC7327D583F15EC5BBB257756843AA6B7CB87A | ||
606 | :1531A10011E7E87DA78E98F6BC4F33B6003A00D029A39FB8AE2A | ||
607 | :1531B60047A57AF73BD6ED53134579776CA4B1D69FD4BEF10F46 | ||
608 | :1531CB00E28F0F0A9C667C0FC4977981EB03F25B806033057EB2 | ||
609 | :1531E0002CC1F5B78013733F24C9F7438CF15EA53CD3D317CC90 | ||
610 | :1531F500BC9092566ABC0F2958ABA9A2AC191E17F6B807B4DAA8 | ||
611 | :15320A00C881469CF3F277116FD1BCB63C0EF7712360B985B33F | ||
612 | :15321F0003AA392E1C307C194F03FCB0B6EFCAED8FF4F13D009A | ||
613 | :15323400077097EED56B389DCCF3C9021BD1A0476D9E4B1EE5BE | ||
614 | :153249007DE9AF282F612DFAB214A7AF903CA20616751B4F47B0 | ||
615 | :15325E00CC73AC584B17BEA071BBBA12A7B3693B5AE23CFF9D4E | ||
616 | :15327300A35761D392EA8DF56831437D5BFA3AA7435946C4B92C | ||
617 | :15328800E57980A79CDB5F4A76DA773430FD4903F6C100A7902A | ||
618 | :15329D00F986569B9917CAEFFBD1E783BEBCDFCFF5F9D4FF6FB5 | ||
619 | :1532B2002A6CF765DEC638C06DAB48991EE3B1F7B37EDFFBE0EC | ||
620 | :1532C700779306C0B12FB34F7768BD6A598BB9E7EFA07E03F7AF | ||
621 | :1532DC00DE7858EF520FF1D042D61B02FDCE7D798A77CF59B649 | ||
622 | :1532F1007F2F73DDAF894ECE7B4437B845BEDF11E7FB58A037C4 | ||
623 | :15330600E8CB6D5EA19D133D67D292E3DEA2C3ED70FB9169045F | ||
624 | :15331B001AE4E3DEA6C7C7A04131A7419FB5CF33458BDBD220BD | ||
625 | :153330006FECB5F11F1B87BDB4D2603E2DBCB14F86605F8345EF | ||
626 | :15334500BB466F3CF1C946295644E36C972E901FFAB1CDDF28C2 | ||
627 | :15335A006C38F147FB3CA0D99F9413ADBC8B3443A03A8176A8A8 | ||
628 | :15336F00A3B9E7639681F290B77DBE7D4A7E32E9B1208F16DB67 | ||
629 | :15338400393C49D3EE0E85635F51CAEC3304EBBE1BB8953CFDD8 | ||
630 | :15339900E3AD79E9B77E39A7E7CBF583FBD830D7DBDC049A7748 | ||
631 | :1533AE000D2B1ED9C9FBE92D5C0F50D31744CCBE29D7EEA8CE2A | ||
632 | :1533C300C2268CCBF4BEEF3CC701B553DFB63F98F5CDCCB8F661 | ||
633 | :1533D8000BF6DCCB03C9CE052413C82C7534C8C68F4658E668BC | ||
634 | :1533ED00F93F66DDF41E25F728F98F3659E93F28BE32313DBE77 | ||
635 | :15340200CB8A8F717EE0EDBC32B1DF48F391FCB4A80F9F7B51F9 | ||
636 | :153417007D6E92FCD28AF573792CFED499934A2189F6A2DC9BBD | ||
637 | :15342C00849D9A62F97412679ECDFDA0717EE651928FD13C2606 | ||
638 | :15344100A17B324B1A4E1FC8BA81878167B3EE9979E6C3C6F7CB | ||
639 | :1534560031296DABFC8C7EFD558D64259C19485A7CF8EF0DCEEC | ||
640 | :15346B00BB416EB37E723FC98F0D241F7D1CDE9C7CB5574F3836 | ||
641 | :15348000481E1D11DB275FD58C84A3CF6895F71B6FDF44FB88C7 | ||
642 | :153495005B73952EE32A6422A23FF657652A231F2737AE4CC7E0 | ||
643 | :1534AA0027F6772DF9D6D47FD60774C8D202B52FD491DC46F8DA | ||
644 | :1534BF00DF91FC188C72BBDF763E727A2A1FDFEFB3AE0A9CED31 | ||
645 | :1534D4000994C32EB47E91CADC06BBF91968DC46344FA6562FE1 | ||
646 | :1534E9003C15527F10AF0B753735F13EAB88D1DC287D9F562434 | ||
647 | :1534FE003C4C7DCB9A19B2A6639928DFA7CB99681FEC1CBB5C2A | ||
648 | :15351300D514DE66C9998B1B8B694EE3A8547859B08B0879DDE3 | ||
649 | :15352800D915524B23A17031953D54754F634546A631B3562FB7 | ||
650 | :15353D00CF0475C1D3A2767F3BA439C769FE986E326C7BD4D0FD | ||
651 | :1535520001E132BFD445F2674D4874134CD1AF8C32FDA17E5706 | ||
652 | :1535670012FB88FF9ABF332B1CCB6ED5BF29B7F4306AAD7E2D55 | ||
653 | :15357C0048FD5A9302B9DF2B0B413E9709364DD94049BF30BA8B | ||
654 | :15359100607C405D60DD59E0A3711C63314BBF64940957D55FDC | ||
655 | :1535A60057977E96914CCED88426B1DF34FA846B6A69B5B301F8 | ||
656 | :1535BB0072648464F60A6158D593DD4A39E618D46FA29F14DD49 | ||
657 | :1535D000AF73FB344CDA31FA00FBEF212ECBC1760CB91792FC9F | ||
658 | :1535E5008DB7FD5F2817B5E7DC83669A8FF23F9CCD06642ABF7B | ||
659 | :1535FA00D1CA9FDBF69F257FFB1F4F4DE57DA7FCA73C0DEC3F98 | ||
660 | :15360F0049B566F92E8259B6E250BF1E58287F32945F1FF84BF5 | ||
661 | :15362400DC864D11CDA95ED259E685A33E6AE7C998735945E6DD | ||
662 | :15363900A08EFE14BC8A7DF5329219DA16F42E8D903C8631F194 | ||
663 | :15364E004B4E9DCB608DCF68215BEEDAF47EF603E52ECFBBD91D | ||
664 | :153663000F94BB9A6691BB1CE78EA890BD206FD9F2574EEE8AAB | ||
665 | :153678000C37E28CBB6F25CEBABFAE35DD9CDE1FF23E9368DB97 | ||
666 | :15368D0056FD686331D7C99ED03CEC64A3EFD4FF22584E6A8B1D | ||
667 | :1536A200334B7278704D38DB6D3CC006D104E1E9DECC1C93BEB6 | ||
668 | :1536B700382B6386EB62F2B87A37A1A1006E2B0C7E080B4085CD | ||
669 | :1536CC006486DF091AAF3E088F243B841D6DD7D41BEF645DC0D6 | ||
670 | :1536E1002770566FE1B0E63D138715B3E010694EBFF32F8B4708 | ||
671 | :1536F6003FE457C2E3A2C089CECBC063747F5FECF733AE95B49A | ||
672 | :15370B007065F3FFEDDCF2CCF4D103FA1AD6A7DD4FF39DEFFF58 | ||
673 | :15372000AC77A92C9F1AA5514CF30A24A74A970C9FD54E45E8FD | ||
674 | :153735005348BF34B6B1CB5A99F0867AC7CA6BEA216A87341F91 | ||
675 | :15374A006FC01AB85466A898FBB2F401CD357E90DE07B53B5395 | ||
676 | :15375F00628397E6805EF6BAEA3D754515F8BD15A3DCBE14B79D | ||
677 | :15377400AFF4438C1B716D60FC07E13B28DE1D142F30DE13B21D | ||
678 | :153789006D3F4994066D54A638B63F6C3FC11FEDAB32736F4889 | ||
679 | :15379E009A28E434E736A7CE5EE16D0AF76905327786A6EC5777 | ||
680 | :1537B3005DE1FD43F0D5D2507EF9F2AB81696EE9D5CA696EE8E9 | ||
681 | :1537C8005BCDA7B2E673B8BAF3E03A990757771E5C272DB8FEA1 | ||
682 | :1537DD0084E072E6C175320FAE25A19976B582164FE7E0CAF8FC | ||
683 | :1537F200A7C3955934CD0D9EA9A0B1B531833E90DF11C9F8DC00 | ||
684 | :153807004700EF8C111DC61AE711CFCC3F457C263F63283769B9 | ||
685 | :15381C009E9E7E5E0F73FB865D7DF192443BDCDBF85D55C7FA7E | ||
686 | :15383100A00F5570866091BBFA1DE7BECD797284AFDD3CAF0766 | ||
687 | :15384600E5471BCDB897B5EB2B8A96791E7885E629BFD45DF29A | ||
688 | :15385B00F7FAEBE5FF61C47F37939F7A463DD07F4CADD7CC6F34 | ||
689 | :15387000CCF37B46275698F98C52BE3E2BCF1B2B3636DECDFE86 | ||
690 | :15388500A681CFD3F3E2222DF2C84F778EE2EC78F2921294FFC4 | ||
691 | :15389A006229FC21BFD134EECFF0FD0C64B8684F0AF323A42D33 | ||
692 | :1538AF00C6990FE25D9C27ACD8FF3CE763F4AFA2957FE9B4EFA6 | ||
693 | :1538C400F92187F9DD572CCF0DD15B7770BD769DE7EF786E8FEB | ||
694 | :1538D900CA714CF3761FC9FF46E405458A24D472C23F3FDF2953 | ||
695 | :1538EE009936FF6FF72799272924D7ABD85767D24E2E1749FE99 | ||
696 | :15390300B862CB455C4642D8C7908F6CD9C8929366958F201BEC | ||
697 | :1539180041460A731B30391947D3CF99328E598ECCCAE5DF195D | ||
698 | :15392D00F320EB92DCE492771B23D7B2AEE294962C26B8C3914D | ||
699 | :153942004483BD76514E7216E224AF8166DD3AAB15DBB75F33B8 | ||
700 | :15395700E5AEF11FF3701DE141C20FD2B3D4555D583041E3BBD3 | ||
701 | :15396C00466D21A915A612712F9523A58EF5A19F04DF214FCC1D | ||
702 | :15398100DFC17FB5F2ABFDE6BC7E265FF7F2FE653EC9C5DE53D5 | ||
703 | :153996007B492619D3C08315046BEB1FF3E55FAB8E54B7792958 | ||
704 | :1539AB00677BE6CDACBF96E4DD6DBF356556BE1741F09D79D3A5 | ||
705 | :1539C0004C531630CF6FB9ACFDDFD1F9CC4D7329F7C83CD38DB4 | ||
706 | :1539D500F3A3DB1DCC7D86FEE6FCB0D6B28F62EA383953423B4C | ||
707 | :1539EA00F33569F6D962CF4F894F4E35ABAB683EE6EC1A547BD6 | ||
708 | :1539FF00D3834AA5EC6C59287FFA73580BE669A43A35771E3916 | ||
709 | :153A14005A4D7C24F488B16ADD29615D59E879E3505D985DEFCD | ||
710 | :153A2900D2B6FC149750CD9C0F4D2F7F55BC6EE93FAB9C5BF459 | ||
711 | :153A3E00C7829D35F35989242D56A12F0E5D0DD843724A7FCB73 | ||
712 | :153A5300F57BEF4ABDDF0ADDBFC03743E8C3B84E1FB761111D23 | ||
713 | :153A680036D6523CBB3CF8B7927BEACE013E472F96024D9DA766 | ||
714 | :153A7D0003B0AF54DBF95E00F936987A72E5ACC4131BA4B1734E | ||
715 | :153A9200897AA72C34632FD513AB366E90BFF8CD2EDDD4AB1599 | ||
716 | :153AA7007B2E5AF32BA7B443FD1585C13E682FE250BDB0372D1B | ||
717 | :153ABC0043F78FFCC4D8A031067FFA7EA390B92F5BE98AC87D98 | ||
718 | :153AD10095FCF11E221AC35ED698C33CB3DB0B9AFB26614796E4 | ||
719 | :153AE600158DC02EE7354DBAF08C02BDEC729C75938E692ECFE7 | ||
720 | :153AFB0011751DD1769E2CB6176506349CF3A8A07E349041FC40 | ||
721 | :153B1000BD3B30C60996EDC0BB52AD4B258F797608B675E6F2B3 | ||
722 | :153B25003C87FB711F93CB8CE32B4F894B85915BD3B26811D7DC | ||
723 | :153B3A00D7D6096F61BF797616FA59B09B0A3D948C1F77C324AA | ||
724 | :153B4F0072F73188F2756333D14D24BC78A82DC7E89BCDB21F0F | ||
725 | :153B64001B8CB9B458E6C747C52B5DEA7B3E3BDF8A5CBE492BCA | ||
726 | :153B7900DF98653B7B0FF52D63458C9F1966E9B8C1F793A4B0E2 | ||
727 | :153B8E00265436758A995AC395811FD12AD3C4CB2FCF4C92FB54 | ||
728 | :153BA3004CA79449519EB14EACB3EF59B049E17D5BE596CE8A23 | ||
729 | :153BB8000C6C185CEE14E5AF196301933F6A284D6D26DD5F4F2A | ||
730 | :153BCD00E9C3945FEB3CE60E527A13B63FE9036CB0B3BC0A7361 | ||
731 | :153BE20028669F5B8E744632EF187B16449508CF53E98C929B8F | ||
732 | :153BF700E21F5D4DEF18E55D4873DAFB33878C48E6E9BEB68CD8 | ||
733 | :153C0C00DE1FA537F6A8A3F43D4EE10A9595F65AB6C4598AE365 | ||
734 | :153C210000F64B61F3B13393321EA17C63049B0FFC4AB8AAA7B5 | ||
735 | :153C3600B78BDEB0D12B5378057DAFA63C7CF4AEA1F9DA26FA1D | ||
736 | :153C4B009E9807DE265C915F1BF989D4D75C24BF60C0A4476CD9 | ||
737 | :153C6000864D72E795B84A7C57E295C5E50579F412008F3C64E5 | ||
738 | :153C7500604D35280F515F3764CC464FF33C53588B3A58C9DDD8 | ||
739 | :153C8A00A987C2683785CDB216E53AAD757A39BF43A8CB30756C | ||
740 | :153C9F001D841E3B8F149559D537C8CFB5080BE2EA947DA00895 | ||
741 | :153CB400C50B6B8CF2EB015E7CB5B9BE6DE2EF3106D6A9B8178D | ||
742 | :153CC90061B1DCBE946DFD5DB7F21BC6EC7CD8D62E2DF8736B0E | ||
743 | :153CDE00FF6BEBA0B685BE7B6467BB2B074FB3BE10E310C27EAD | ||
744 | :153CF30063EAC9D7DBFD13F9457F0E5DD365CB5D046B8C997058 | ||
745 | :153D0800DBF4E6772A5AE9026CF972B6B599E76FEB8B230DE54F | ||
746 | :153D1D005552CA5A7918F22A0ADC8A2FB46F9F30759E439A7424 | ||
747 | :153D3200501D4772753C7701753CA2AE8149D46F0EEB9317007C | ||
748 | :153D4700306C5F99FB57F2CF281AFD23F48FD23F46FF2DF48FD5 | ||
749 | :153D5C00D35FA77F8AFEA3F41FFF9919976DED36EB6A9EF9E018 | ||
750 | :153D71006E7D867B74863B3DC33D39C32DBD36DD1D9CE18ECEF0 | ||
751 | :153D8600706F99E1D667B8475FCB3B9342F86913A6DBB78880A5 | ||
752 | :153D9B0076BED19C5DB049AA97BFEBB85ACACF365BF9548E74A6 | ||
753 | :153DB000626D684D6C43D87F7258AFBD083A4DE14D21F726FA49 | ||
754 | :153DC5006FA37F92FE7DF41FA1FF09FA9FA1FF65FA4FD0FFC613 | ||
755 | :153DDA0045332E3B36CCF196B2E94F6EE04DCF73036FF13C37CD | ||
756 | :153DEF00F0B625CF0DBCC5F2DCC05B34CF0DBC45F2DCC05B3084 | ||
757 | :153E0400CF0DBCC9F9E5BF36657F93974F6E7F73CA006F433FFD | ||
758 | :153E19005A7C62C33DB67D048EB3D9EC7F107E3D2C0FBF33E3C5 | ||
759 | :153E2E00FC33C3D1F78C91FC42B2947E7A0E734357B658165B92 | ||
760 | :153E4300FA04E676D137F5332D1E1A238BE5459FBD48E36205B5 | ||
761 | :153E58007D838EA2B44BDD5C467DD65C56F218AB6989CC35FBFF | ||
762 | :153E6D00B407E83B3CD7ECCB2A59CD725BFF49869D72DCFB4582 | ||
763 | :153E820079006793A5347E53FA8952C80E2F4ED9E92019F152A8 | ||
764 | :153E970055178DCB872123E8932B9CCB4F531CB96CF6F1C91EC9 | ||
765 | :153EAC00E7B0378FF1689299363AEC781E2A77A7659780E49DE9 | ||
766 | :153EC100E597292F3797F7A7F7631504EF7609E321E48BDDFA81 | ||
767 | :153ED6009E18CEA5BDA8EF881CE6F5777FC6D92EC9753AFA7C2A | ||
768 | :153EEB009C112A5B79006BB9DA9639D89F1AD499FEA2EE178621 | ||
769 | :153F0000D516D6CDE377BB87156141138DAD83460DD54D243929 | ||
770 | :153F150097DB268FEED52ECEC538A6774A65499EC7988764486F | ||
771 | :153F2A004AE3925FD4451A8BDDA558571EA4BEFC450378AE91FA | ||
772 | :153F3F004CF903B0A63DD3E5BB9139ACE434E5979A8371A6469B | ||
773 | :153F54004FF0B1A9968F4D380F2B2C08727B0A976F66DDC5F1B1 | ||
774 | :153F6900AE1667B45695E56AFD8D15C2F2CD94E6CC5C5326B23D | ||
775 | :153F7E00F1E0B5740FA7F477653D4EBC29A57772BB7EC85FBA96 | ||
776 | :153F9300F02905E78C00B33732B854245945A43C2729CF769297 | ||
777 | :153FA800A9708E49E4BAD87C1C862D490379A0BD8BB161C323AE | ||
778 | :153FBD009BF7BA66B91EFF8B9A9FFA7C51FE9E81F8B8FB976419 | ||
779 | :153FD200B00D1305243FE3CEC7BCFBA71294C7DFC588F762B02A | ||
780 | :153FE700B561DA75FFCF6CB0C5436E8C33C065A498B9DF269E84 | ||
781 | :153FFC007D8B75B5D8B09B3819E17D13F2E0677ED892161BEE59 | ||
782 | :15401100EB0437F45D890E25B02303DE100907176F64DDF6BD19 | ||
783 | :1540260005F9750AE4D5C91E6F502FAEB740FD1DE0728ED39C6C | ||
784 | :15403B00233AA6F13A4883FD34F7A07AEF9EB2731CEBD27ADD53 | ||
785 | :15405000CCBD8660B5D37C2ED2DD029D8B9F1CF9E5618F5C6F8D | ||
786 | :15406500F8B9AEB24A6D76B561C32ECA87F9BC0DDF18E3250BE4 | ||
787 | :15407A00476B2D386D3D4E0B977EEC15D7539837262EF7154C5C | ||
788 | :15408F00B50DC95DA39AF7EBF6F1F28C5343CB59380C1D8CAC5D | ||
789 | :1540A400B96796CD7EEB5498FC123AEE46294B3FA9965DB84765 | ||
790 | :1540B900914EAD542B65472BD7C94EEF864E94DB9D3F6E5A70DC | ||
791 | :1540CE0036B0257C5C1E7531F715AAE32F88F7D8D6E7795E88FB | ||
792 | :1540E300EF425F1F1EE2F7AEF0F34BADF5FCDC0EC9E1FA77E3C0 | ||
793 | :1540F800832D38D303FC3E8D7B0B49A6B5F0EEF5669C2DF321EE | ||
794 | :15410D00AF674EEAD71F7C69F92FC88D3A8B99E1D9F98D706485 | ||
795 | :15412200F29BC93F9ECC71FD40C6D91E681DE6E5A19D99F4946F | ||
796 | :15413700394EEDFE5A6C5D82B51884EB95E38361BBBE51613A5F | ||
797 | :15414C005F42CFE6664C6801DC36DEDE1C1FE27D8027467D8299 | ||
798 | :1541610055CE2F288F8F5AA7CA8C7379B0783A2FB6BD9D75AFA9 | ||
799 | :15417600263A7A62797591BFA7439F3257179AC398F5AFCDD556 | ||
800 | :15418B00057088AD9FE675E1788A0D7E209E9C528D6AAD9364C6 | ||
801 | :1541A000515FD7A9FD5C671573A30187D54F100EA84F77E7EEE2 | ||
802 | :1541B5004C487769E7FE68EB0FD7F33A411FDC4EFB08A503BD44 | ||
803 | :1541CA00FB284D7E3FB3ED7D935F3DF2615D8E0D695F8F0C8732 | ||
804 | :1541DF0050367851DA3E669E8B4C0FD37CA11BFB9D567D877409 | ||
805 | :1541F400BBAD88992386E41E56CBA8CF3D48732B4F06FD8A6685 | ||
806 | :15420900D5FFC454FD892FE6B79EE4F59F4F74B3E89B1B438A6B | ||
807 | :15421E00D1DFF1F6A0C1DE7FAE3DDC840D9FF0B169EDE1B7E3CD | ||
808 | :15423300C7B85D1FE0ACE121D35E01CA798EED6D215E36DB49B7 | ||
809 | :154248006BB7C9C7046B4F1C67F0F5CE03B8B3217A7206BD7508 | ||
810 | :15425D0093DE5563CB0D727B624379743DA623CD145D87AC7ADB | ||
811 | :154272002579BDD0E794B5EEE5755A98129783F76D5AE6F89743 | ||
812 | :15428700FCC414EE0A49E83DD4FECC7B42CC7AFC35F1A7CD8B26 | ||
813 | :15429C005E36D6524AE503961B04CB42E2BD6345D379EFDCFF00 | ||
814 | :1542B10026BE93F3E08B117CB13CF8641B3EB35FE2F86CEDE6C9 | ||
815 | :1542C600F0E5F70BF1EBA6CE03DE62CCBC07588F24B694E68D22 | ||
816 | :1542DB0039F1776D5ECACD5DBD2CDCCB710B5B2C7D93D9921C44 | ||
817 | :1542F000EF916CF32B9C55785EBC478A99F36F6FE4B0FA32A58C | ||
818 | :15430500F1578BED6517FA1487C0CAE6212C7D4C972EA414DCF3 | ||
819 | :15431A00F17094609530E610FF6C06AFBA20776A5A2070A253C4 | ||
820 | :15432F00261929FE646FFB0EF827DF411FBEC375EE24D7DB9887 | ||
821 | :15434400A8DABB8CA5C7742328B4239FCAC45ED89CF3CDC7FD16 | ||
822 | :1543590068E49FC07AB5B4D710293FECCD7337952BF23DC1BDA2 | ||
823 | :15436E00064F87B2F4BDD07F9E87BB95BBCC343BE234A7C7BA03 | ||
824 | :15438300886BAD063D0E3FD7A1B3E6F412BF4F604CDFD9A6299D | ||
825 | :1543980005EBAEABF16CD6DBFB794D419D454A539938B201F0C4 | ||
826 | :1543AD0063EC042C80CD4F75692218FC174E28F36354D7B3DF2C | ||
827 | :1543C20056BD4CA33E3CA57C1FE38295A77876402519D88B7446 | ||
828 | :1543D70076DD7B28FFE4BEE3FC1E66F00B8F1B3DB6C3B5FB1DAF | ||
829 | :1543EC003503D8A84EA80BBB3EA0812EC003D34F6AC06723D44E | ||
830 | :154401005C28DCC6C5E51C1ECCB27278C07A6DDAC443E08762E3 | ||
831 | :154416004B721D742486B52EF2EF457B219CC00F6B1B18834D1B | ||
832 | :15442B00784F120E8E28C8BF60DDEFD5ED1C0F479432AA1F70F9 | ||
833 | :1544400020E15C15D5DB853B83A82CD84C0E52F99581894EDBE9 | ||
834 | :154455001EB2699F27AEE9C4837B162495B7D884B628C8FEB2C2 | ||
835 | :15446A0046163F97B3D7F917DC1E32B79BD4C6D70896F49B67EE | ||
836 | :15447F005B933C5D24B30B7756B8E98D7D6023F6EE149FE33C0E | ||
837 | :1544940023D6AAC0A3F5984B439736D8A4E937B89E663F8DB948 | ||
838 | :1544A900E3F15A67BBE00AAB623CA40E10AC55CA28EEB9D475D6 | ||
839 | :1544BE00F9402B9F9F521C89FA0E8FFCC51697FCB51649FED26B | ||
840 | :1544D30072312A63BC1EBF4AF230DE9D984B455FE43695FDCD24 | ||
841 | :1544E800B261E60F9971703C4861F594BE96D2D7507AF855C8F3 | ||
842 | :1544FD005F6AB1F3207E6AF150B88BC2AFAEF81ACFCFC3E766D2 | ||
843 | :15451200BFDB61C7D9827208265FF3A499B76EC20D1C85D136AC | ||
844 | :1545270008CE7AF9D556B1396864281CEB05AD349F1692215583 | ||
845 | :15453C008A630FD88C8FFC8807FC22E58378FC7C020EA4C7CC33 | ||
846 | :15455100FB80D0869B9835BF06CF4B435639239DB02952CE6D45 | ||
847 | :154566004F987E9833C18FEB1B9A67316E992F098249CF9C3FD4 | ||
848 | :15457B00E55F61CF7FB85E2A95CFEF384B195BDEBD75CE659ECD | ||
849 | :154590007D1DD11186FE07772CF8ADFEC69FFE8EEABBF01D0521 | ||
850 | :1545A500F2AAAFF59879AF1085F930F767C731BE6BAFFCB680E3 | ||
851 | :1545BA00558C1F6FDC42E39EC79A67983AB0A69C833B095CF13E | ||
852 | :1545CF00234BE793ECE943BEC111138E5C3F99E4F0F9228930CA | ||
853 | :1545E400B76F426EE4591E196AACC8CB333777A13E97A7B7FA20 | ||
854 | :1545F900CFDF5AFC8C7A606E47B079AFF2359D9AA934F9E76932 | ||
855 | :15460E00F9FDE74F69FF384BBAC333D211BFEBB3AD27453287BE | ||
856 | :15462300B4FF394BFACD1F21FDB559D2856F0BEF216D6296747F | ||
857 | :15463800EFB1DB9737F9FE8CFD27ACEFE4F31FD6FCDF9DBEBE22 | ||
858 | :15464D0031335CFAC38787C76F17FE7F3BFF19E19E7CFEFFB008 | ||
859 | :15466200F581FF1FFE4F0A97F2F0EF9DD92FFD3F03BFC51FD198 | ||
860 | :154677008F971EED6B9E287359ECCBDC46536D67B7147B641541 | ||
861 | :15468C0035454FD9A3AA46E1B82BDA73EF6E15ED14E3A4A76CC6 | ||
862 | :1546A100933A67F56E55961FD7E6DCDBA5FAD6698A47A8567DC5 | ||
863 | :1546B600A5D56A82E416AB4D6FB84163B35456AB22BF7F6A5E9C | ||
864 | :1546CB0087EED314EC110BEB30778969D0A813E582F6AF539F69 | ||
865 | :1546E000ECF754ABC5EBEAD5E7EEAB53AAD6D52901CF236A774F | ||
866 | :1546F500C1A714DCC5B8488CD973151FE28BC22754BEF6B0BABF | ||
867 | :15470A008BF71DE843AA4A130AF413ED702F0FAF539D65712E7A | ||
868 | :15471F00DF553D1057F9FE1264E459605865C15042301C22180D | ||
869 | :15473400FC79E5A3DC4A8201F178BE947F7ED937AC7C27F3F2CE | ||
870 | :15474900CD665FC97A60EB20C4DAD7331640DEF18298067C644E | ||
871 | :15475E009999D7DD8CCD9B4FB8F15099EEB57584A36A6591A745 | ||
872 | :154773005EADF88CD8EE645D1D557F25B61F9A9BE034C0BA4825 | ||
873 | :1547880090E0C01EDC5DDC76DA14EC5EAE07833DB8F813BC6EA9 | ||
874 | :15479D0004D3390BA631D4DD73BF5AB56FBD2A94DAB0656FDA01 | ||
875 | :1547B200B0B5106CE59E6AEE1F2701D1A697BBB45EF5709876A1 | ||
876 | :1547C7002B8B4A13EAFE9D7B72BC003CFF219BB56060BC9EB026 | ||
877 | :1547DC000966EE374F3E8172D3161CB81FEC0C7DCFD54C18CA91 | ||
878 | :1547F100F6D5A865541EEAD66E9D4D81D226C74BD1145EAA8851 | ||
879 | :15480600774AD6B6AAFE75610ECFAE82DD4A31E1A5C493500B35 | ||
880 | :15481B0059A2638FC59B8B79DDA7CA9DA0B2740A2B237C11DDC4 | ||
881 | :15483000BD360CA07D55DBFD0A64A1AA75F72B33E94F8DA8AC8E | ||
882 | :1548450098EF1B4CB5A7AA33033C9E70BE5EF53F105345F6B844 | ||
883 | :15485A003A87E23E27B080D3FA36E8BB641DC149FC52521A56D0 | ||
884 | :15486F00B51F352B87CE362B25E7D7AA7E8DFCF6AD56B5CFAF8A | ||
885 | :1548840021DE5FA38007FC84D3AAB5262EC498D02EB34D9CB7E4 | ||
886 | :15489900494EF3398587544FAC0077EBF8DCD8ABA96CEB9C2374 | ||
887 | :1548AE003CAC7AC455AA67259577EF63AA67F51A756FC12A05F2 | ||
888 | :1548C300FA1EE2CAA9F84501F31C188F9F0899F15FFEAAEA3924 | ||
889 | :1548D800DDACEEDD19529C34EE96FDE811A5EA3305EDB0BDEDB4 | ||
890 | :1548ED008A873ADCE3CD1D07610F4D0BA955E71F528573CDAA2E | ||
891 | :15490200467105D7142DB6A28D07F8B9B10DB005E4EAA274A731 | ||
892 | :154917009A3BF85CAF89B51796053B8ACA9A3AAA92EB955DD473 | ||
893 | :15492C0037C8E4DF43EFBF449FF3F71B554F4FB30AB95A961F63 | ||
894 | :15494100866CE7F224BEAA0A6B1F5779D8CBCD141E52F712CEDB | ||
895 | :15495600407FF038E624C5FF5168AF3A4F38D4BA54FFF9AFAA3B | ||
896 | :15496B0025E776731ED84F3C3087685F1CD13AF2FB25D01DB469 | ||
897 | :15498000E33AF5164DC193F7122CED809FF08CBB49D7D177A2D7 | ||
898 | :1549950060B33287CA01FCDD3BCDEF5537B37EF44BB61B7169FF | ||
899 | :1549AA006CD83090C51A8EC9DB064DAD803FF47B34E79A67F3A6 | ||
900 | :1549BF00D5368AC3CF47100C9B67E80797FDA842A93A574EB8AA | ||
901 | :1549D4002D5767E3A337D9141FFD9A997C041A14131F053C9B2E | ||
902 | :1549E900395E9EB378097CE4D7C86F062FED8EFFF9C6E2C026AC | ||
903 | :1549FE00A24FAC73377B78E39C40B453F03CA6DAEE92C8C31BD2 | ||
904 | :154A130041A7395DEB3BD8D9F60EFB5D75CDC1EF702A8EAFEF25 | ||
905 | :154A280028196FEF10DC44F34F546B4EA2C34DA23DF07737A785 | ||
906 | :154A3D0085A3BD44DB4174788CE8B087F7E9F9B428B0689130FA | ||
907 | :154A5200EF8EF209AE4F50D9D10D67385DC037D10D6333E84242 | ||
908 | :154A670034F13E60D185FA5DEFFA3CBADC994797B7B8CEEF5418 | ||
909 | :154A7C00DBDE49EDBA378F4EDCFE38F100FCB75BB4BA803BFF2F | ||
910 | :154A91002CDA6CFA98F4B894478FBFB3E88136EDB768710B1D40 | ||
911 | :154AA6008836F9B4288A7C65636164FD46B68DB57BC6BFD23197 | ||
912 | :154ABB0047DAD451C4FECDC6E2F8BFEDF08C3FCCDD557FC5DBED | ||
913 | :154AD000ABD7C3C81D799CE35DDC5EAD39A8EFBD5914D58A6DA5 | ||
914 | :154AE500BC533B2DF1ECA4FEEF5FA9256B9F9C86F7E2D9F09E3E | ||
915 | :154AFA005C0C9AE7E13DC6F16ED7371FFFD4E77BEFB5F08F35C1 | ||
916 | :154B0F0011B4131BFFDE3CFC3BF8DA8689DF5E0BBFA5E8A7280A | ||
917 | :154B2400AC92E65AF96DC04EFF261F174C9A211DE8A658743081 | ||
918 | :154B3900711E9E06CBB708CF9E94D0FE32BD13D4F714521EB8D2 | ||
919 | :154B4E00FFFDD0171F51ABD6B52A52C152A5A8E01E053CECA121 | ||
920 | :154B6300BE879D6DEE38F4530A3BBF56F1167C5E71177CC10C75 | ||
921 | :154B7800135675B0FBD674EC8A39DA01D762E084CA261E292BCC | ||
922 | :154B8D00941D7C8C843FECB9D87314940FBBA705F6D86D8D1FA2 | ||
923 | :154BA20088075D7FC0F55A36EBA338B9B6FF32B57D8C5D9768CE | ||
924 | :154BB7003A89F512C80734D6F94E5BF1BF4FDF55D744BCBD27B6 | ||
925 | :154BCC00785E4975BF63E8117EC65230EF62A69125EB8D0C3DF1 | ||
926 | :154BE1006A308DEB88C1DF37B5DE5AFC7F00E871AED038A00037 | ||
927 | :014BF60000BE | ||
928 | :00000001FF | ||
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c new file mode 100644 index 000000000000..06817dec0c25 --- /dev/null +++ b/drivers/atm/suni.c | |||
@@ -0,0 +1,311 @@ | |||
1 | /* drivers/atm/suni.c - PMC PM5346 SUNI (PHY) driver */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/jiffies.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/atmdev.h> | ||
12 | #include <linux/sonet.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/timer.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/capability.h> | ||
17 | #include <linux/atm_suni.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/param.h> | ||
20 | #include <asm/uaccess.h> | ||
21 | #include <asm/atomic.h> | ||
22 | |||
23 | #include "suni.h" | ||
24 | |||
25 | |||
26 | #if 0 | ||
27 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
28 | #else | ||
29 | #define DPRINTK(format,args...) | ||
30 | #endif | ||
31 | |||
32 | |||
33 | struct suni_priv { | ||
34 | struct k_sonet_stats sonet_stats; /* link diagnostics */ | ||
35 | int loop_mode; /* loopback mode */ | ||
36 | struct atm_dev *dev; /* device back-pointer */ | ||
37 | struct suni_priv *next; /* next SUNI */ | ||
38 | }; | ||
39 | |||
40 | |||
41 | #define PRIV(dev) ((struct suni_priv *) dev->phy_data) | ||
42 | |||
43 | #define PUT(val,reg) dev->ops->phy_put(dev,val,SUNI_##reg) | ||
44 | #define GET(reg) dev->ops->phy_get(dev,SUNI_##reg) | ||
45 | #define REG_CHANGE(mask,shift,value,reg) \ | ||
46 | PUT((GET(reg) & ~(mask)) | ((value) << (shift)),reg) | ||
47 | |||
48 | |||
49 | static struct timer_list poll_timer; | ||
50 | static struct suni_priv *sunis = NULL; | ||
51 | static DEFINE_SPINLOCK(sunis_lock); | ||
52 | |||
53 | |||
54 | #define ADD_LIMITED(s,v) \ | ||
55 | atomic_add((v),&stats->s); \ | ||
56 | if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX); | ||
57 | |||
58 | |||
59 | static void suni_hz(unsigned long from_timer) | ||
60 | { | ||
61 | struct suni_priv *walk; | ||
62 | struct atm_dev *dev; | ||
63 | struct k_sonet_stats *stats; | ||
64 | |||
65 | for (walk = sunis; walk; walk = walk->next) { | ||
66 | dev = walk->dev; | ||
67 | stats = &walk->sonet_stats; | ||
68 | PUT(0,MRI); /* latch counters */ | ||
69 | udelay(1); | ||
70 | ADD_LIMITED(section_bip,(GET(RSOP_SBL) & 0xff) | | ||
71 | ((GET(RSOP_SBM) & 0xff) << 8)); | ||
72 | ADD_LIMITED(line_bip,(GET(RLOP_LBL) & 0xff) | | ||
73 | ((GET(RLOP_LB) & 0xff) << 8) | | ||
74 | ((GET(RLOP_LBM) & 0xf) << 16)); | ||
75 | ADD_LIMITED(path_bip,(GET(RPOP_PBL) & 0xff) | | ||
76 | ((GET(RPOP_PBM) & 0xff) << 8)); | ||
77 | ADD_LIMITED(line_febe,(GET(RLOP_LFL) & 0xff) | | ||
78 | ((GET(RLOP_LF) & 0xff) << 8) | | ||
79 | ((GET(RLOP_LFM) & 0xf) << 16)); | ||
80 | ADD_LIMITED(path_febe,(GET(RPOP_PFL) & 0xff) | | ||
81 | ((GET(RPOP_PFM) & 0xff) << 8)); | ||
82 | ADD_LIMITED(corr_hcs,GET(RACP_CHEC) & 0xff); | ||
83 | ADD_LIMITED(uncorr_hcs,GET(RACP_UHEC) & 0xff); | ||
84 | ADD_LIMITED(rx_cells,(GET(RACP_RCCL) & 0xff) | | ||
85 | ((GET(RACP_RCC) & 0xff) << 8) | | ||
86 | ((GET(RACP_RCCM) & 7) << 16)); | ||
87 | ADD_LIMITED(tx_cells,(GET(TACP_TCCL) & 0xff) | | ||
88 | ((GET(TACP_TCC) & 0xff) << 8) | | ||
89 | ((GET(TACP_TCCM) & 7) << 16)); | ||
90 | } | ||
91 | if (from_timer) mod_timer(&poll_timer,jiffies+HZ); | ||
92 | } | ||
93 | |||
94 | |||
95 | #undef ADD_LIMITED | ||
96 | |||
97 | |||
98 | static int fetch_stats(struct atm_dev *dev,struct sonet_stats __user *arg,int zero) | ||
99 | { | ||
100 | struct sonet_stats tmp; | ||
101 | int error = 0; | ||
102 | |||
103 | sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp); | ||
104 | if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); | ||
105 | if (zero && !error) sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp); | ||
106 | return error ? -EFAULT : 0; | ||
107 | } | ||
108 | |||
109 | |||
110 | #define HANDLE_FLAG(flag,reg,bit) \ | ||
111 | if (todo & flag) { \ | ||
112 | if (set) PUT(GET(reg) | bit,reg); \ | ||
113 | else PUT(GET(reg) & ~bit,reg); \ | ||
114 | todo &= ~flag; \ | ||
115 | } | ||
116 | |||
117 | |||
118 | static int change_diag(struct atm_dev *dev,void __user *arg,int set) | ||
119 | { | ||
120 | int todo; | ||
121 | |||
122 | if (get_user(todo,(int __user *)arg)) return -EFAULT; | ||
123 | HANDLE_FLAG(SONET_INS_SBIP,TSOP_DIAG,SUNI_TSOP_DIAG_DBIP8); | ||
124 | HANDLE_FLAG(SONET_INS_LBIP,TLOP_DIAG,SUNI_TLOP_DIAG_DBIP); | ||
125 | HANDLE_FLAG(SONET_INS_PBIP,TPOP_CD,SUNI_TPOP_DIAG_DB3); | ||
126 | HANDLE_FLAG(SONET_INS_FRAME,RSOP_CIE,SUNI_RSOP_CIE_FOOF); | ||
127 | HANDLE_FLAG(SONET_INS_LAIS,TSOP_CTRL,SUNI_TSOP_CTRL_LAIS); | ||
128 | HANDLE_FLAG(SONET_INS_PAIS,TPOP_CD,SUNI_TPOP_DIAG_PAIS); | ||
129 | HANDLE_FLAG(SONET_INS_LOS,TSOP_DIAG,SUNI_TSOP_DIAG_DLOS); | ||
130 | HANDLE_FLAG(SONET_INS_HCS,TACP_CS,SUNI_TACP_CS_DHCS); | ||
131 | return put_user(todo,(int __user *)arg) ? -EFAULT : 0; | ||
132 | } | ||
133 | |||
134 | |||
135 | #undef HANDLE_FLAG | ||
136 | |||
137 | |||
138 | static int get_diag(struct atm_dev *dev,void __user *arg) | ||
139 | { | ||
140 | int set; | ||
141 | |||
142 | set = 0; | ||
143 | if (GET(TSOP_DIAG) & SUNI_TSOP_DIAG_DBIP8) set |= SONET_INS_SBIP; | ||
144 | if (GET(TLOP_DIAG) & SUNI_TLOP_DIAG_DBIP) set |= SONET_INS_LBIP; | ||
145 | if (GET(TPOP_CD) & SUNI_TPOP_DIAG_DB3) set |= SONET_INS_PBIP; | ||
146 | /* SONET_INS_FRAME is one-shot only */ | ||
147 | if (GET(TSOP_CTRL) & SUNI_TSOP_CTRL_LAIS) set |= SONET_INS_LAIS; | ||
148 | if (GET(TPOP_CD) & SUNI_TPOP_DIAG_PAIS) set |= SONET_INS_PAIS; | ||
149 | if (GET(TSOP_DIAG) & SUNI_TSOP_DIAG_DLOS) set |= SONET_INS_LOS; | ||
150 | if (GET(TACP_CS) & SUNI_TACP_CS_DHCS) set |= SONET_INS_HCS; | ||
151 | return put_user(set,(int __user *)arg) ? -EFAULT : 0; | ||
152 | } | ||
153 | |||
154 | |||
155 | static int set_loopback(struct atm_dev *dev,int mode) | ||
156 | { | ||
157 | unsigned char control; | ||
158 | |||
159 | control = GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE); | ||
160 | switch (mode) { | ||
161 | case ATM_LM_NONE: | ||
162 | break; | ||
163 | case ATM_LM_LOC_PHY: | ||
164 | control |= SUNI_MCT_DLE; | ||
165 | break; | ||
166 | case ATM_LM_RMT_PHY: | ||
167 | control |= SUNI_MCT_LLE; | ||
168 | break; | ||
169 | default: | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | PUT(control,MCT); | ||
173 | PRIV(dev)->loop_mode = mode; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | |||
178 | static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
179 | { | ||
180 | switch (cmd) { | ||
181 | case SONET_GETSTATZ: | ||
182 | case SONET_GETSTAT: | ||
183 | return fetch_stats(dev, arg, cmd == SONET_GETSTATZ); | ||
184 | case SONET_SETDIAG: | ||
185 | return change_diag(dev,arg,1); | ||
186 | case SONET_CLRDIAG: | ||
187 | return change_diag(dev,arg,0); | ||
188 | case SONET_GETDIAG: | ||
189 | return get_diag(dev,arg); | ||
190 | case SONET_SETFRAMING: | ||
191 | if (arg != SONET_FRAME_SONET) return -EINVAL; | ||
192 | return 0; | ||
193 | case SONET_GETFRAMING: | ||
194 | return put_user(SONET_FRAME_SONET,(int __user *)arg) ? | ||
195 | -EFAULT : 0; | ||
196 | case SONET_GETFRSENSE: | ||
197 | return -EINVAL; | ||
198 | case ATM_SETLOOP: | ||
199 | return set_loopback(dev,(int)(unsigned long)arg); | ||
200 | case ATM_GETLOOP: | ||
201 | return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ? | ||
202 | -EFAULT : 0; | ||
203 | case ATM_QUERYLOOP: | ||
204 | return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, | ||
205 | (int __user *) arg) ? -EFAULT : 0; | ||
206 | default: | ||
207 | return -ENOIOCTLCMD; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | |||
212 | static void poll_los(struct atm_dev *dev) | ||
213 | { | ||
214 | dev->signal = GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? ATM_PHY_SIG_LOST : | ||
215 | ATM_PHY_SIG_FOUND; | ||
216 | } | ||
217 | |||
218 | |||
219 | static void suni_int(struct atm_dev *dev) | ||
220 | { | ||
221 | poll_los(dev); | ||
222 | printk(KERN_NOTICE "%s(itf %d): signal %s\n",dev->type,dev->number, | ||
223 | dev->signal == ATM_PHY_SIG_LOST ? "lost" : "detected again"); | ||
224 | } | ||
225 | |||
226 | |||
227 | static int suni_start(struct atm_dev *dev) | ||
228 | { | ||
229 | unsigned long flags; | ||
230 | int first; | ||
231 | |||
232 | if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL))) | ||
233 | return -ENOMEM; | ||
234 | |||
235 | PRIV(dev)->dev = dev; | ||
236 | spin_lock_irqsave(&sunis_lock,flags); | ||
237 | first = !sunis; | ||
238 | PRIV(dev)->next = sunis; | ||
239 | sunis = PRIV(dev); | ||
240 | spin_unlock_irqrestore(&sunis_lock,flags); | ||
241 | memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats)); | ||
242 | PUT(GET(RSOP_CIE) | SUNI_RSOP_CIE_LOSE,RSOP_CIE); | ||
243 | /* interrupt on loss of signal */ | ||
244 | poll_los(dev); /* ... and clear SUNI interrupts */ | ||
245 | if (dev->signal == ATM_PHY_SIG_LOST) | ||
246 | printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type, | ||
247 | dev->number); | ||
248 | PRIV(dev)->loop_mode = ATM_LM_NONE; | ||
249 | suni_hz(0); /* clear SUNI counters */ | ||
250 | (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ | ||
251 | if (first) { | ||
252 | init_timer(&poll_timer); | ||
253 | poll_timer.expires = jiffies+HZ; | ||
254 | poll_timer.function = suni_hz; | ||
255 | poll_timer.data = 1; | ||
256 | #if 0 | ||
257 | printk(KERN_DEBUG "[u] p=0x%lx,n=0x%lx\n",(unsigned long) poll_timer.list.prev, | ||
258 | (unsigned long) poll_timer.list.next); | ||
259 | #endif | ||
260 | add_timer(&poll_timer); | ||
261 | } | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | |||
266 | static int suni_stop(struct atm_dev *dev) | ||
267 | { | ||
268 | struct suni_priv **walk; | ||
269 | unsigned long flags; | ||
270 | |||
271 | /* let SAR driver worry about stopping interrupts */ | ||
272 | spin_lock_irqsave(&sunis_lock,flags); | ||
273 | for (walk = &sunis; *walk != PRIV(dev); | ||
274 | walk = &PRIV((*walk)->dev)->next); | ||
275 | *walk = PRIV((*walk)->dev)->next; | ||
276 | if (!sunis) del_timer_sync(&poll_timer); | ||
277 | spin_unlock_irqrestore(&sunis_lock,flags); | ||
278 | kfree(PRIV(dev)); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | static const struct atmphy_ops suni_ops = { | ||
285 | .start = suni_start, | ||
286 | .ioctl = suni_ioctl, | ||
287 | .interrupt = suni_int, | ||
288 | .stop = suni_stop, | ||
289 | }; | ||
290 | |||
291 | |||
292 | int suni_init(struct atm_dev *dev) | ||
293 | { | ||
294 | unsigned char mri; | ||
295 | |||
296 | mri = GET(MRI); /* reset SUNI */ | ||
297 | PUT(mri | SUNI_MRI_RESET,MRI); | ||
298 | PUT(mri,MRI); | ||
299 | PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */ | ||
300 | REG_CHANGE(SUNI_TPOP_APM_S,SUNI_TPOP_APM_S_SHIFT,SUNI_TPOP_S_SONET, | ||
301 | TPOP_APM); /* use SONET */ | ||
302 | REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP, | ||
303 | TACP_IUCHP); /* idle cells */ | ||
304 | PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP); | ||
305 | dev->phy = &suni_ops; | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | EXPORT_SYMBOL(suni_init); | ||
310 | |||
311 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/atm/suni.h b/drivers/atm/suni.h new file mode 100644 index 000000000000..d14c835abc97 --- /dev/null +++ b/drivers/atm/suni.h | |||
@@ -0,0 +1,211 @@ | |||
1 | /* drivers/atm/suni.h - PMC PM5346 SUNI (PHY) declarations */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVER_ATM_SUNI_H | ||
7 | #define DRIVER_ATM_SUNI_H | ||
8 | |||
9 | #include <linux/atmdev.h> | ||
10 | #include <linux/atmioc.h> | ||
11 | |||
12 | |||
13 | /* SUNI registers */ | ||
14 | |||
15 | #define SUNI_MRI 0x00 /* Master Reset and Identity / Load | ||
16 | Meter */ | ||
17 | #define SUNI_MC 0x01 /* Master Configuration */ | ||
18 | #define SUNI_MIS 0x02 /* Master Interrupt Status */ | ||
19 | /* no 0x03 */ | ||
20 | #define SUNI_MCM 0x04 /* Master Clock Monitor */ | ||
21 | #define SUNI_MCT 0x05 /* Master Control */ | ||
22 | #define SUNI_CSCS 0x06 /* Clock Synthesis Control and Status */ | ||
23 | #define SUNI_CRCS 0x07 /* Clock Recovery Control and Status */ | ||
24 | /* 0x08-0x0F reserved */ | ||
25 | #define SUNI_RSOP_CIE 0x10 /* RSOP Control/Interrupt Enable */ | ||
26 | #define SUNI_RSOP_SIS 0x11 /* RSOP Status/Interrupt Status */ | ||
27 | #define SUNI_RSOP_SBL 0x12 /* RSOP Section BIP-8 LSB */ | ||
28 | #define SUNI_RSOP_SBM 0x13 /* RSOP Section BIP-8 MSB */ | ||
29 | #define SUNI_TSOP_CTRL 0x14 /* TSOP Control */ | ||
30 | #define SUNI_TSOP_DIAG 0x15 /* TSOP Diagnostic */ | ||
31 | /* 0x16-0x17 reserved */ | ||
32 | #define SUNI_RLOP_CS 0x18 /* RLOP Control/Status */ | ||
33 | #define SUNI_RLOP_IES 0x19 /* RLOP Interrupt Enable/Status */ | ||
34 | #define SUNI_RLOP_LBL 0x1A /* RLOP Line BIP-8/24 LSB */ | ||
35 | #define SUNI_RLOP_LB 0x1B /* RLOP Line BIP-8/24 */ | ||
36 | #define SUNI_RLOP_LBM 0x1C /* RLOP Line BIP-8/24 MSB */ | ||
37 | #define SUNI_RLOP_LFL 0x1D /* RLOP Line FEBE LSB */ | ||
38 | #define SUNI_RLOP_LF 0x1E /* RLOP Line FEBE */ | ||
39 | #define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */ | ||
40 | #define SUNI_TLOP_CTRL 0x20 /* TLOP Control */ | ||
41 | #define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */ | ||
42 | /* 0x22-0x2F reserved */ | ||
43 | #define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */ | ||
44 | #define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */ | ||
45 | /* 0x32 reserved */ | ||
46 | #define SUNI_RPOP_IE 0x33 /* RPOP Interrupt Enable */ | ||
47 | /* 0x34-0x36 reserved */ | ||
48 | #define SUNI_RPOP_PSL 0x37 /* RPOP Path Signal Label */ | ||
49 | #define SUNI_RPOP_PBL 0x38 /* RPOP Path BIP-8 LSB */ | ||
50 | #define SUNI_RPOP_PBM 0x39 /* RPOP Path BIP-8 MSB */ | ||
51 | #define SUNI_RPOP_PFL 0x3A /* RPOP Path FEBE LSB */ | ||
52 | #define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */ | ||
53 | /* 0x3C reserved */ | ||
54 | #define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */ | ||
55 | /* 0x3E-0x3F reserved */ | ||
56 | #define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */ | ||
57 | #define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */ | ||
58 | /* 0x42-0x44 reserved */ | ||
59 | #define SUNI_TPOP_APL 0x45 /* TPOP Arbitrary Pointer LSB */ | ||
60 | #define SUNI_TPOP_APM 0x46 /* TPOP Arbitrary Pointer MSB */ | ||
61 | /* 0x47 reserved */ | ||
62 | #define SUNI_TPOP_PSL 0x48 /* TPOP Path Signal Label */ | ||
63 | #define SUNI_TPOP_PS 0x49 /* TPOP Path Status */ | ||
64 | /* 0x4A-0x4F reserved */ | ||
65 | #define SUNI_RACP_CS 0x50 /* RACP Control/Status */ | ||
66 | #define SUNI_RACP_IES 0x51 /* RACP Interrupt Enable/Status */ | ||
67 | #define SUNI_RACP_MHP 0x52 /* RACP Match Header Pattern */ | ||
68 | #define SUNI_RACP_MHM 0x53 /* RACP Match Header Mask */ | ||
69 | #define SUNI_RACP_CHEC 0x54 /* RACP Correctable HCS Error Count */ | ||
70 | #define SUNI_RACP_UHEC 0x55 /* RACP Uncorrectable HCS Err Count */ | ||
71 | #define SUNI_RACP_RCCL 0x56 /* RACP Receive Cell Counter LSB */ | ||
72 | #define SUNI_RACP_RCC 0x57 /* RACP Receive Cell Counter */ | ||
73 | #define SUNI_RACP_RCCM 0x58 /* RACP Receive Cell Counter MSB */ | ||
74 | #define SUNI_RACP_CFG 0x59 /* RACP Configuration */ | ||
75 | /* 0x5A-0x5F reserved */ | ||
76 | #define SUNI_TACP_CS 0x60 /* TACP Control/Status */ | ||
77 | #define SUNI_TACP_IUCHP 0x61 /* TACP Idle/Unassigned Cell Hdr Pat */ | ||
78 | #define SUNI_TACP_IUCPOP 0x62 /* TACP Idle/Unassigned Cell Payload | ||
79 | Octet Pattern */ | ||
80 | #define SUNI_TACP_FIFO 0x63 /* TACP FIFO Configuration */ | ||
81 | #define SUNI_TACP_TCCL 0x64 /* TACP Transmit Cell Counter LSB */ | ||
82 | #define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */ | ||
83 | #define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */ | ||
84 | #define SUNI_TACP_CFG 0x67 /* TACP Configuration */ | ||
85 | /* 0x68-0x7F reserved */ | ||
86 | #define SUNI_MT 0x80 /* Master Test */ | ||
87 | /* 0x81-0xFF reserved */ | ||
88 | |||
89 | /* SUNI register values */ | ||
90 | |||
91 | |||
92 | /* MRI is reg 0 */ | ||
93 | #define SUNI_MRI_ID 0x0f /* R, SUNI revision number */ | ||
94 | #define SUNI_MRI_ID_SHIFT 0 | ||
95 | #define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */ | ||
96 | #define SUNI_MRI_TYPE_SHIFT 4 | ||
97 | #define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip | ||
98 | 0: normal operation | ||
99 | 1: reset & low power */ | ||
100 | /* MCT is reg 5 */ | ||
101 | #define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from | ||
102 | TRCLK+/- */ | ||
103 | #define SUNI_MCT_DLE 0x02 /* RW, diagnostic loopback */ | ||
104 | #define SUNI_MCT_LLE 0x04 /* RW, line loopback */ | ||
105 | #define SUNI_MCT_FIXPTR 0x20 /* RW, disable transmit payload pointer | ||
106 | adjustments | ||
107 | 0: payload ptr controlled by TPOP | ||
108 | ptr control reg | ||
109 | 1: payload pointer fixed at 522 */ | ||
110 | #define SUNI_MCT_LCDV 0x40 /* R, loss of cell delineation */ | ||
111 | #define SUNI_MCT_LCDE 0x80 /* RW, loss of cell delineation | ||
112 | interrupt (1: on) */ | ||
113 | /* RSOP_CIE is reg 0x10 */ | ||
114 | #define SUNI_RSOP_CIE_OOFE 0x01 /* RW, enable interrupt on frame alarm | ||
115 | state change */ | ||
116 | #define SUNI_RSOP_CIE_LOFE 0x02 /* RW, enable interrupt on loss of | ||
117 | frame state change */ | ||
118 | #define SUNI_RSOP_CIE_LOSE 0x04 /* RW, enable interrupt on loss of | ||
119 | signal state change */ | ||
120 | #define SUNI_RSOP_CIE_BIPEE 0x08 /* RW, enable interrupt on section | ||
121 | BIP-8 error (B1) */ | ||
122 | #define SUNI_RSOP_CIE_FOOF 0x20 /* W, force RSOP out of frame at next | ||
123 | boundary */ | ||
124 | #define SUNI_RSOP_CIE_DDS 0x40 /* RW, disable scrambling */ | ||
125 | |||
126 | /* RSOP_SIS is reg 0x11 */ | ||
127 | #define SUNI_RSOP_SIS_OOFV 0x01 /* R, out of frame */ | ||
128 | #define SUNI_RSOP_SIS_LOFV 0x02 /* R, loss of frame */ | ||
129 | #define SUNI_RSOP_SIS_LOSV 0x04 /* R, loss of signal */ | ||
130 | #define SUNI_RSOP_SIS_OOFI 0x08 /* R, out of frame interrupt */ | ||
131 | #define SUNI_RSOP_SIS_LOFI 0x10 /* R, loss of frame interrupt */ | ||
132 | #define SUNI_RSOP_SIS_LOSI 0x20 /* R, loss of signal interrupt */ | ||
133 | #define SUNI_RSOP_SIS_BIPEI 0x40 /* R, section BIP-8 interrupt */ | ||
134 | |||
135 | /* TSOP_CTRL is reg 0x14 */ | ||
136 | #define SUNI_TSOP_CTRL_LAIS 0x01 /* insert alarm indication signal */ | ||
137 | #define SUNI_TSOP_CTRL_DS 0x40 /* disable scrambling */ | ||
138 | |||
139 | /* TSOP_DIAG is reg 0x15 */ | ||
140 | #define SUNI_TSOP_DIAG_DFP 0x01 /* insert single bit error cont. */ | ||
141 | #define SUNI_TSOP_DIAG_DBIP8 0x02 /* insert section BIP err (cont) */ | ||
142 | #define SUNI_TSOP_DIAG_DLOS 0x04 /* set line to zero (loss of signal) */ | ||
143 | |||
144 | /* TLOP_DIAG is reg 0x21 */ | ||
145 | #define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */ | ||
146 | |||
147 | /* TPOP_DIAG is reg 0x40 */ | ||
148 | #define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */ | ||
149 | #define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */ | ||
150 | |||
151 | /* TPOP_APM is reg 0x46 */ | ||
152 | #define SUNI_TPOP_APM_APTR 0x03 /* RW, arbitrary pointer, upper 2 | ||
153 | bits */ | ||
154 | #define SUNI_TPOP_APM_APTR_SHIFT 0 | ||
155 | #define SUNI_TPOP_APM_S 0x0c /* RW, "unused" bits of payload | ||
156 | pointer */ | ||
157 | #define SUNI_TPOP_APM_S_SHIFT 2 | ||
158 | #define SUNI_TPOP_APM_NDF 0xf0 /* RW, NDF bits */ | ||
159 | #define SUNI_TPOP_APM_NDF_SHIFT 4 | ||
160 | |||
161 | #define SUNI_TPOP_S_SONET 0 /* set S bits to 00 */ | ||
162 | #define SUNI_TPOP_S_SDH 2 /* set S bits to 10 */ | ||
163 | |||
164 | /* RACP_IES is reg 0x51 */ | ||
165 | #define SUNI_RACP_IES_FOVRI 0x02 /* R, FIFO overrun */ | ||
166 | #define SUNI_RACP_IES_UHCSI 0x04 /* R, uncorrectable HCS error */ | ||
167 | #define SUNI_RACP_IES_CHCSI 0x08 /* R, correctable HCS error */ | ||
168 | #define SUNI_RACP_IES_OOCDI 0x10 /* R, change of cell delineation | ||
169 | state */ | ||
170 | #define SUNI_RACP_IES_FIFOE 0x20 /* RW, enable FIFO overrun interrupt */ | ||
171 | #define SUNI_RACP_IES_HCSE 0x40 /* RW, enable HCS error interrupt */ | ||
172 | #define SUNI_RACP_IES_OOCDE 0x80 /* RW, enable cell delineation state | ||
173 | change interrupt */ | ||
174 | |||
175 | /* TACP_CS is reg 0x60 */ | ||
176 | #define SUNI_TACP_CS_FIFORST 0x01 /* RW, reset transmit FIFO (sticky) */ | ||
177 | #define SUNI_TACP_CS_DSCR 0x02 /* RW, disable payload scrambling */ | ||
178 | #define SUNI_TACP_CS_HCAADD 0x04 /* RW, add coset polynomial to HCS */ | ||
179 | #define SUNI_TACP_CS_DHCS 0x10 /* RW, insert HCS errors */ | ||
180 | #define SUNI_TACP_CS_FOVRI 0x20 /* R, FIFO overrun */ | ||
181 | #define SUNI_TACP_CS_TSOCI 0x40 /* R, TSOC input high */ | ||
182 | #define SUNI_TACP_CS_FIFOE 0x80 /* RW, enable FIFO overrun interrupt */ | ||
183 | |||
184 | /* TACP_IUCHP is reg 0x61 */ | ||
185 | #define SUNI_TACP_IUCHP_CLP 0x01 /* RW, 8th bit of 4th octet of i/u | ||
186 | pattern */ | ||
187 | #define SUNI_TACP_IUCHP_PTI 0x0e /* RW, 5th-7th bits of 4th octet of i/u | ||
188 | pattern */ | ||
189 | #define SUNI_TACP_IUCHP_PTI_SHIFT 1 | ||
190 | #define SUNI_TACP_IUCHP_GFC 0xf0 /* RW, 1st-4th bits of 1st octet of i/u | ||
191 | pattern */ | ||
192 | #define SUNI_TACP_IUCHP_GFC_SHIFT 4 | ||
193 | |||
194 | /* MT is reg 0x80 */ | ||
195 | #define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface | ||
196 | tri-state */ | ||
197 | #define SUNI_MT_HIZDATA 0x02 /* W, also tri-state data bus */ | ||
198 | #define SUNI_MT_IOTST 0x04 /* RW, enable test mode */ | ||
199 | #define SUNI_MT_DBCTRL 0x08 /* W, control data bus by CSB pin */ | ||
200 | #define SUNI_MT_PMCTST 0x10 /* W, PMC test mode */ | ||
201 | #define SUNI_MT_DS27_53 0x80 /* RW, select between 8- or 16- bit */ | ||
202 | |||
203 | |||
204 | #define SUNI_IDLE_PATTERN 0x6a /* idle pattern */ | ||
205 | |||
206 | |||
207 | #ifdef __KERNEL__ | ||
208 | int suni_init(struct atm_dev *dev); | ||
209 | #endif | ||
210 | |||
211 | #endif | ||
diff --git a/drivers/atm/tonga.h b/drivers/atm/tonga.h new file mode 100644 index 000000000000..672da96243ca --- /dev/null +++ b/drivers/atm/tonga.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* drivers/atm/tonga.h - Efficient Networks Tonga (PCI bridge) declarations */ | ||
2 | |||
3 | /* Written 1995 by Werner Almesberger, EPFL LRC */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVER_ATM_TONGA_H | ||
7 | #define DRIVER_ATM_TONGA_H | ||
8 | |||
9 | #define PCI_TONGA_CTRL 0x60 /* control register */ | ||
10 | |||
11 | #define END_SWAP_DMA 0x80 /* endian swap on DMA */ | ||
12 | #define END_SWAP_BYTE 0x40 /* endian swap on slave byte accesses */ | ||
13 | #define END_SWAP_WORD 0x20 /* endian swap on slave word accesses */ | ||
14 | #define SEPROM_MAGIC 0x0c /* obscure required pattern (ASIC only) */ | ||
15 | #define SEPROM_DATA 0x02 /* serial EEPROM data (ASIC only) */ | ||
16 | #define SEPROM_CLK 0x01 /* serial EEPROM clock (ASIC only) */ | ||
17 | |||
18 | #define SEPROM_ESI_BASE 64 /* start of ESI in serial EEPROM */ | ||
19 | |||
20 | #endif | ||
diff --git a/drivers/atm/uPD98401.h b/drivers/atm/uPD98401.h new file mode 100644 index 000000000000..0ab36503a4b7 --- /dev/null +++ b/drivers/atm/uPD98401.h | |||
@@ -0,0 +1,292 @@ | |||
1 | /* drivers/atm/uPD98401.h - NEC uPD98401 (SAR) declarations */ | ||
2 | |||
3 | /* Written 1995 by Werner Almesberger, EPFL LRC */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVERS_ATM_uPD98401_H | ||
7 | #define DRIVERS_ATM_uPD98401_H | ||
8 | |||
9 | |||
10 | #define MAX_CRAM_SIZE (1 << 18) /* 2^18 words */ | ||
11 | #define RAM_INCREMENT 1024 /* check in 4 kB increments */ | ||
12 | |||
13 | #define uPD98401_PORTS 0x24 /* probably more ? */ | ||
14 | |||
15 | |||
16 | /* | ||
17 | * Commands | ||
18 | */ | ||
19 | |||
20 | #define uPD98401_OPEN_CHAN 0x20000000 /* open channel */ | ||
21 | #define uPD98401_CHAN_ADDR 0x0003fff8 /* channel address */ | ||
22 | #define uPD98401_CHAN_ADDR_SHIFT 3 | ||
23 | #define uPD98401_CLOSE_CHAN 0x24000000 /* close channel */ | ||
24 | #define uPD98401_CHAN_RT 0x02000000 /* RX/TX (0 TX, 1 RX) */ | ||
25 | #define uPD98401_DEACT_CHAN 0x28000000 /* deactivate channel */ | ||
26 | #define uPD98401_TX_READY 0x30000000 /* TX ready */ | ||
27 | #define uPD98401_ADD_BAT 0x34000000 /* add batches */ | ||
28 | #define uPD98401_POOL 0x000f0000 /* pool number */ | ||
29 | #define uPD98401_POOL_SHIFT 16 | ||
30 | #define uPD98401_POOL_NUMBAT 0x0000ffff /* number of batches */ | ||
31 | #define uPD98401_NOP 0x3f000000 /* NOP */ | ||
32 | #define uPD98401_IND_ACC 0x00000000 /* Indirect Access */ | ||
33 | #define uPD98401_IA_RW 0x10000000 /* Read/Write (0 W, 1 R) */ | ||
34 | #define uPD98401_IA_B3 0x08000000 /* Byte select, 1 enable */ | ||
35 | #define uPD98401_IA_B2 0x04000000 | ||
36 | #define uPD98401_IA_B1 0x02000000 | ||
37 | #define uPD98401_IA_B0 0x01000000 | ||
38 | #define uPD98401_IA_BALL 0x0f000000 /* whole longword */ | ||
39 | #define uPD98401_IA_TGT 0x000c0000 /* Target */ | ||
40 | #define uPD98401_IA_TGT_SHIFT 18 | ||
41 | #define uPD98401_IA_TGT_CM 0 /* - Control Memory */ | ||
42 | #define uPD98401_IA_TGT_SAR 1 /* - uPD98401 registers */ | ||
43 | #define uPD98401_IA_TGT_PHY 3 /* - PHY device */ | ||
44 | #define uPD98401_IA_ADDR 0x0003ffff | ||
45 | |||
46 | /* | ||
47 | * Command Register Status | ||
48 | */ | ||
49 | |||
50 | #define uPD98401_BUSY 0x80000000 /* SAR is busy */ | ||
51 | #define uPD98401_LOCKED 0x40000000 /* SAR is locked by other CPU */ | ||
52 | |||
53 | /* | ||
54 | * Indications | ||
55 | */ | ||
56 | |||
57 | /* Normal (AAL5) Receive Indication */ | ||
58 | #define uPD98401_AAL5_UINFO 0xffff0000 /* user-supplied information */ | ||
59 | #define uPD98401_AAL5_UINFO_SHIFT 16 | ||
60 | #define uPD98401_AAL5_SIZE 0x0000ffff /* PDU size (in _CELLS_ !!) */ | ||
61 | #define uPD98401_AAL5_CHAN 0x7fff0000 /* Channel number */ | ||
62 | #define uPD98401_AAL5_CHAN_SHIFT 16 | ||
63 | #define uPD98401_AAL5_ERR 0x00008000 /* Error indication */ | ||
64 | #define uPD98401_AAL5_CI 0x00004000 /* Congestion Indication */ | ||
65 | #define uPD98401_AAL5_CLP 0x00002000 /* CLP (>= 1 cell had CLP=1) */ | ||
66 | #define uPD98401_AAL5_ES 0x00000f00 /* Error Status */ | ||
67 | #define uPD98401_AAL5_ES_SHIFT 8 | ||
68 | #define uPD98401_AAL5_ES_NONE 0 /* No error */ | ||
69 | #define uPD98401_AAL5_ES_FREE 1 /* Receiver free buf underflow */ | ||
70 | #define uPD98401_AAL5_ES_FIFO 2 /* Receiver FIFO overrun */ | ||
71 | #define uPD98401_AAL5_ES_TOOBIG 3 /* Maximum length violation */ | ||
72 | #define uPD98401_AAL5_ES_CRC 4 /* CRC error */ | ||
73 | #define uPD98401_AAL5_ES_ABORT 5 /* User abort */ | ||
74 | #define uPD98401_AAL5_ES_LENGTH 6 /* Length violation */ | ||
75 | #define uPD98401_AAL5_ES_T1 7 /* T1 error (timeout) */ | ||
76 | #define uPD98401_AAL5_ES_DEACT 8 /* Deactivated with DEACT_CHAN */ | ||
77 | #define uPD98401_AAL5_POOL 0x0000001f /* Free buffer pool number */ | ||
78 | |||
79 | /* Raw Cell Indication */ | ||
80 | #define uPD98401_RAW_UINFO uPD98401_AAL5_UINFO | ||
81 | #define uPD98401_RAW_UINFO_SHIFT uPD98401_AAL5_UINFO_SHIFT | ||
82 | #define uPD98401_RAW_HEC 0x000000ff /* HEC */ | ||
83 | #define uPD98401_RAW_CHAN uPD98401_AAL5_CHAN | ||
84 | #define uPD98401_RAW_CHAN_SHIFT uPD98401_AAL5_CHAN_SHIFT | ||
85 | |||
86 | /* Transmit Indication */ | ||
87 | #define uPD98401_TXI_CONN 0x7fff0000 /* Connection Number */ | ||
88 | #define uPD98401_TXI_CONN_SHIFT 16 | ||
89 | #define uPD98401_TXI_ACTIVE 0x00008000 /* Channel remains active */ | ||
90 | #define uPD98401_TXI_PQP 0x00007fff /* Packet Queue Pointer */ | ||
91 | |||
92 | /* | ||
93 | * Directly Addressable Registers | ||
94 | */ | ||
95 | |||
96 | #define uPD98401_GMR 0x00 /* General Mode Register */ | ||
97 | #define uPD98401_GSR 0x01 /* General Status Register */ | ||
98 | #define uPD98401_IMR 0x02 /* Interrupt Mask Register */ | ||
99 | #define uPD98401_RQU 0x03 /* Receive Queue Underrun */ | ||
100 | #define uPD98401_RQA 0x04 /* Receive Queue Alert */ | ||
101 | #define uPD98401_ADDR 0x05 /* Last Burst Address */ | ||
102 | #define uPD98401_VER 0x06 /* Version Number */ | ||
103 | #define uPD98401_SWR 0x07 /* Software Reset */ | ||
104 | #define uPD98401_CMR 0x08 /* Command Register */ | ||
105 | #define uPD98401_CMR_L 0x09 /* Command Register and Lock/Unlock */ | ||
106 | #define uPD98401_CER 0x0a /* Command Extension Register */ | ||
107 | #define uPD98401_CER_L 0x0b /* Command Ext Reg and Lock/Unlock */ | ||
108 | |||
109 | #define uPD98401_MSH(n) (0x10+(n)) /* Mailbox n Start Address High */ | ||
110 | #define uPD98401_MSL(n) (0x14+(n)) /* Mailbox n Start Address High */ | ||
111 | #define uPD98401_MBA(n) (0x18+(n)) /* Mailbox n Bottom Address */ | ||
112 | #define uPD98401_MTA(n) (0x1c+(n)) /* Mailbox n Tail Address */ | ||
113 | #define uPD98401_MWA(n) (0x20+(n)) /* Mailbox n Write Address */ | ||
114 | |||
115 | /* GMR is at 0x00 */ | ||
116 | #define uPD98401_GMR_ONE 0x80000000 /* Must be set to one */ | ||
117 | #define uPD98401_GMR_SLM 0x40000000 /* Address mode (0 word, 1 byte) */ | ||
118 | #define uPD98401_GMR_CPE 0x00008000 /* Control Memory Parity Enable */ | ||
119 | #define uPD98401_GMR_LP 0x00004000 /* Loopback */ | ||
120 | #define uPD98401_GMR_WA 0x00002000 /* Early Bus Write Abort/RDY */ | ||
121 | #define uPD98401_GMR_RA 0x00001000 /* Early Read Abort/RDY */ | ||
122 | #define uPD98401_GMR_SZ 0x00000f00 /* Burst Size Enable */ | ||
123 | #define uPD98401_BURST16 0x00000800 /* 16-word burst */ | ||
124 | #define uPD98401_BURST8 0x00000400 /* 8-word burst */ | ||
125 | #define uPD98401_BURST4 0x00000200 /* 4-word burst */ | ||
126 | #define uPD98401_BURST2 0x00000100 /* 2-word burst */ | ||
127 | #define uPD98401_GMR_AD 0x00000080 /* Address (burst resolution) Disable */ | ||
128 | #define uPD98401_GMR_BO 0x00000040 /* Byte Order (0 little, 1 big) */ | ||
129 | #define uPD98401_GMR_PM 0x00000020 /* Bus Parity Mode (0 byte, 1 word)*/ | ||
130 | #define uPD98401_GMR_PC 0x00000010 /* Bus Parity Control (0even,1odd) */ | ||
131 | #define uPD98401_GMR_BPE 0x00000008 /* Bus Parity Enable */ | ||
132 | #define uPD98401_GMR_DR 0x00000004 /* Receive Drop Mode (0drop,1don't)*/ | ||
133 | #define uPD98401_GMR_SE 0x00000002 /* Shapers Enable */ | ||
134 | #define uPD98401_GMR_RE 0x00000001 /* Receiver Enable */ | ||
135 | |||
136 | /* GSR is at 0x01, IMR is at 0x02 */ | ||
137 | #define uPD98401_INT_PI 0x80000000 /* PHY interrupt */ | ||
138 | #define uPD98401_INT_RQA 0x40000000 /* Receive Queue Alert */ | ||
139 | #define uPD98401_INT_RQU 0x20000000 /* Receive Queue Underrun */ | ||
140 | #define uPD98401_INT_RD 0x10000000 /* Receiver Deactivated */ | ||
141 | #define uPD98401_INT_SPE 0x08000000 /* System Parity Error */ | ||
142 | #define uPD98401_INT_CPE 0x04000000 /* Control Memory Parity Error */ | ||
143 | #define uPD98401_INT_SBE 0x02000000 /* System Bus Error */ | ||
144 | #define uPD98401_INT_IND 0x01000000 /* Initialization Done */ | ||
145 | #define uPD98401_INT_RCR 0x0000ff00 /* Raw Cell Received */ | ||
146 | #define uPD98401_INT_RCR_SHIFT 8 | ||
147 | #define uPD98401_INT_MF 0x000000f0 /* Mailbox Full */ | ||
148 | #define uPD98401_INT_MF_SHIFT 4 | ||
149 | #define uPD98401_INT_MM 0x0000000f /* Mailbox Modified */ | ||
150 | |||
151 | /* VER is at 0x06 */ | ||
152 | #define uPD98401_MAJOR 0x0000ff00 /* Major revision */ | ||
153 | #define uPD98401_MAJOR_SHIFT 8 | ||
154 | #define uPD98401_MINOR 0x000000ff /* Minor revision */ | ||
155 | |||
156 | /* | ||
157 | * Indirectly Addressable Registers | ||
158 | */ | ||
159 | |||
160 | #define uPD98401_IM(n) (0x40000+(n)) /* Scheduler n I and M */ | ||
161 | #define uPD98401_X(n) (0x40010+(n)) /* Scheduler n X */ | ||
162 | #define uPD98401_Y(n) (0x40020+(n)) /* Scheduler n Y */ | ||
163 | #define uPD98401_PC(n) (0x40030+(n)) /* Scheduler n P, C, p and c */ | ||
164 | #define uPD98401_PS(n) (0x40040+(n)) /* Scheduler n priority and status */ | ||
165 | |||
166 | /* IM contents */ | ||
167 | #define uPD98401_IM_I 0xff000000 /* I */ | ||
168 | #define uPD98401_IM_I_SHIFT 24 | ||
169 | #define uPD98401_IM_M 0x00ffffff /* M */ | ||
170 | |||
171 | /* PC contents */ | ||
172 | #define uPD98401_PC_P 0xff000000 /* P */ | ||
173 | #define uPD98401_PC_P_SHIFT 24 | ||
174 | #define uPD98401_PC_C 0x00ff0000 /* C */ | ||
175 | #define uPD98401_PC_C_SHIFT 16 | ||
176 | #define uPD98401_PC_p 0x0000ff00 /* p */ | ||
177 | #define uPD98401_PC_p_SHIFT 8 | ||
178 | #define uPD98401_PC_c 0x000000ff /* c */ | ||
179 | |||
180 | /* PS contents */ | ||
181 | #define uPD98401_PS_PRIO 0xf0 /* Priority level (0 high, 15 low) */ | ||
182 | #define uPD98401_PS_PRIO_SHIFT 4 | ||
183 | #define uPD98401_PS_S 0x08 /* Scan - must be 0 (internal) */ | ||
184 | #define uPD98401_PS_R 0x04 /* Round Robin (internal) */ | ||
185 | #define uPD98401_PS_A 0x02 /* Active (internal) */ | ||
186 | #define uPD98401_PS_E 0x01 /* Enabled */ | ||
187 | |||
188 | #define uPD98401_TOS 0x40100 /* Top of Stack Control Memory Address */ | ||
189 | #define uPD98401_SMA 0x40200 /* Shapers Control Memory Start Address */ | ||
190 | #define uPD98401_PMA 0x40201 /* Receive Pool Control Memory Start Address */ | ||
191 | #define uPD98401_T1R 0x40300 /* T1 Register */ | ||
192 | #define uPD98401_VRR 0x40301 /* VPI/VCI Reduction Register/Recv. Shutdown */ | ||
193 | #define uPD98401_TSR 0x40302 /* Time-Stamp Register */ | ||
194 | |||
195 | /* VRR is at 0x40301 */ | ||
196 | #define uPD98401_VRR_SDM 0x80000000 /* Shutdown Mode */ | ||
197 | #define uPD98401_VRR_SHIFT 0x000f0000 /* VPI/VCI Shift */ | ||
198 | #define uPD98401_VRR_SHIFT_SHIFT 16 | ||
199 | #define uPD98401_VRR_MASK 0x0000ffff /* VPI/VCI mask */ | ||
200 | |||
201 | /* | ||
202 | * TX packet descriptor | ||
203 | */ | ||
204 | |||
205 | #define uPD98401_TXPD_SIZE 16 /* descriptor size (in bytes) */ | ||
206 | |||
207 | #define uPD98401_TXPD_V 0x80000000 /* Valid bit */ | ||
208 | #define uPD98401_TXPD_DP 0x40000000 /* Descriptor (1) or Pointer (0) */ | ||
209 | #define uPD98401_TXPD_SM 0x20000000 /* Single (1) or Multiple (0) */ | ||
210 | #define uPD98401_TXPD_CLPM 0x18000000 /* CLP mode */ | ||
211 | #define uPD98401_CLPM_0 0 /* 00 CLP = 0 */ | ||
212 | #define uPD98401_CLPM_1 3 /* 11 CLP = 1 */ | ||
213 | #define uPD98401_CLPM_LAST 1 /* 01 CLP unless last cell */ | ||
214 | #define uPD98401_TXPD_CLPM_SHIFT 27 | ||
215 | #define uPD98401_TXPD_PTI 0x07000000 /* PTI pattern */ | ||
216 | #define uPD98401_TXPD_PTI_SHIFT 24 | ||
217 | #define uPD98401_TXPD_GFC 0x00f00000 /* GFC pattern */ | ||
218 | #define uPD98401_TXPD_GFC_SHIFT 20 | ||
219 | #define uPD98401_TXPD_C10 0x00040000 /* insert CRC-10 */ | ||
220 | #define uPD98401_TXPD_AAL5 0x00020000 /* AAL5 processing */ | ||
221 | #define uPD98401_TXPD_MB 0x00010000 /* TX mailbox number */ | ||
222 | #define uPD98401_TXPD_UU 0x0000ff00 /* CPCS-UU */ | ||
223 | #define uPD98401_TXPD_UU_SHIFT 8 | ||
224 | #define uPD98401_TXPD_CPI 0x000000ff /* CPI */ | ||
225 | |||
226 | /* | ||
227 | * TX buffer descriptor | ||
228 | */ | ||
229 | |||
230 | #define uPD98401_TXBD_SIZE 8 /* descriptor size (in bytes) */ | ||
231 | |||
232 | #define uPD98401_TXBD_LAST 0x80000000 /* last buffer in packet */ | ||
233 | |||
234 | /* | ||
235 | * TX VC table | ||
236 | */ | ||
237 | |||
238 | /* 1st word has the same structure as in a TX packet descriptor */ | ||
239 | #define uPD98401_TXVC_L 0x80000000 /* last buffer */ | ||
240 | #define uPD98401_TXVC_SHP 0x0f000000 /* shaper number */ | ||
241 | #define uPD98401_TXVC_SHP_SHIFT 24 | ||
242 | #define uPD98401_TXVC_VPI 0x00ff0000 /* VPI */ | ||
243 | #define uPD98401_TXVC_VPI_SHIFT 16 | ||
244 | #define uPD98401_TXVC_VCI 0x0000ffff /* VCI */ | ||
245 | #define uPD98401_TXVC_QRP 6 /* Queue Read Pointer is in word 6 */ | ||
246 | |||
247 | /* | ||
248 | * RX free buffer pools descriptor | ||
249 | */ | ||
250 | |||
251 | #define uPD98401_RXFP_ALERT 0x70000000 /* low water mark */ | ||
252 | #define uPD98401_RXFP_ALERT_SHIFT 28 | ||
253 | #define uPD98401_RXFP_BFSZ 0x0f000000 /* buffer size, 64*2^n */ | ||
254 | #define uPD98401_RXFP_BFSZ_SHIFT 24 | ||
255 | #define uPD98401_RXFP_BTSZ 0x00ff0000 /* batch size, n+1 */ | ||
256 | #define uPD98401_RXFP_BTSZ_SHIFT 16 | ||
257 | #define uPD98401_RXFP_REMAIN 0x0000ffff /* remaining batches in pool */ | ||
258 | |||
259 | /* | ||
260 | * RX VC table | ||
261 | */ | ||
262 | |||
263 | #define uPD98401_RXVC_BTSZ 0xff000000 /* remaining free buffers in batch */ | ||
264 | #define uPD98401_RXVC_BTSZ_SHIFT 24 | ||
265 | #define uPD98401_RXVC_MB 0x00200000 /* RX mailbox number */ | ||
266 | #define uPD98401_RXVC_POOL 0x001f0000 /* free buffer pool number */ | ||
267 | #define uPD98401_RXVC_POOL_SHIFT 16 | ||
268 | #define uPD98401_RXVC_UINFO 0x0000ffff /* user-supplied information */ | ||
269 | #define uPD98401_RXVC_T1 0xffff0000 /* T1 timestamp */ | ||
270 | #define uPD98401_RXVC_T1_SHIFT 16 | ||
271 | #define uPD98401_RXVC_PR 0x00008000 /* Packet Reception, 1 if busy */ | ||
272 | #define uPD98401_RXVC_DR 0x00004000 /* FIFO Drop */ | ||
273 | #define uPD98401_RXVC_OD 0x00001000 /* Drop OAM cells */ | ||
274 | #define uPD98401_RXVC_AR 0x00000800 /* AAL5 or raw cell; 1 if AAL5 */ | ||
275 | #define uPD98401_RXVC_MAXSEG 0x000007ff /* max number of segments per PDU */ | ||
276 | #define uPD98401_RXVC_REM 0xfffe0000 /* remaining words in curr buffer */ | ||
277 | #define uPD98401_RXVC_REM_SHIFT 17 | ||
278 | #define uPD98401_RXVC_CLP 0x00010000 /* CLP received */ | ||
279 | #define uPD98401_RXVC_BFA 0x00008000 /* Buffer Assigned */ | ||
280 | #define uPD98401_RXVC_BTA 0x00004000 /* Batch Assigned */ | ||
281 | #define uPD98401_RXVC_CI 0x00002000 /* Congestion Indication */ | ||
282 | #define uPD98401_RXVC_DD 0x00001000 /* Dropping incoming cells */ | ||
283 | #define uPD98401_RXVC_DP 0x00000800 /* like PR ? */ | ||
284 | #define uPD98401_RXVC_CURSEG 0x000007ff /* Current Segment count */ | ||
285 | |||
286 | /* | ||
287 | * RX lookup table | ||
288 | */ | ||
289 | |||
290 | #define uPD98401_RXLT_ENBL 0x8000 /* Enable */ | ||
291 | |||
292 | #endif | ||
diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c new file mode 100644 index 000000000000..9504cce51bfb --- /dev/null +++ b/drivers/atm/uPD98402.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/sched.h> /* for jiffies */ | ||
8 | #include <linux/mm.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/atmdev.h> | ||
11 | #include <linux/sonet.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/atomic.h> | ||
15 | |||
16 | #include "uPD98402.h" | ||
17 | |||
18 | |||
19 | #if 0 | ||
20 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
21 | #else | ||
22 | #define DPRINTK(format,args...) | ||
23 | #endif | ||
24 | |||
25 | |||
26 | struct uPD98402_priv { | ||
27 | struct k_sonet_stats sonet_stats;/* link diagnostics */ | ||
28 | unsigned char framing; /* SONET/SDH framing */ | ||
29 | int loop_mode; /* loopback mode */ | ||
30 | spinlock_t lock; | ||
31 | }; | ||
32 | |||
33 | |||
34 | #define PRIV(dev) ((struct uPD98402_priv *) dev->phy_data) | ||
35 | |||
36 | #define PUT(val,reg) dev->ops->phy_put(dev,val,uPD98402_##reg) | ||
37 | #define GET(reg) dev->ops->phy_get(dev,uPD98402_##reg) | ||
38 | |||
39 | |||
40 | static int fetch_stats(struct atm_dev *dev,struct sonet_stats __user *arg,int zero) | ||
41 | { | ||
42 | struct sonet_stats tmp; | ||
43 | int error = 0; | ||
44 | |||
45 | atomic_add(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs); | ||
46 | sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp); | ||
47 | if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); | ||
48 | if (zero && !error) { | ||
49 | /* unused fields are reported as -1, but we must not "adjust" | ||
50 | them */ | ||
51 | tmp.corr_hcs = tmp.tx_cells = tmp.rx_cells = 0; | ||
52 | sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp); | ||
53 | } | ||
54 | return error ? -EFAULT : 0; | ||
55 | } | ||
56 | |||
57 | |||
58 | static int set_framing(struct atm_dev *dev,unsigned char framing) | ||
59 | { | ||
60 | static const unsigned char sonet[] = { 1,2,3,0 }; | ||
61 | static const unsigned char sdh[] = { 1,0,0,2 }; | ||
62 | const char *set; | ||
63 | unsigned long flags; | ||
64 | |||
65 | switch (framing) { | ||
66 | case SONET_FRAME_SONET: | ||
67 | set = sonet; | ||
68 | break; | ||
69 | case SONET_FRAME_SDH: | ||
70 | set = sdh; | ||
71 | break; | ||
72 | default: | ||
73 | return -EINVAL; | ||
74 | } | ||
75 | spin_lock_irqsave(&PRIV(dev)->lock, flags); | ||
76 | PUT(set[0],C11T); | ||
77 | PUT(set[1],C12T); | ||
78 | PUT(set[2],C13T); | ||
79 | PUT((GET(MDR) & ~uPD98402_MDR_SS_MASK) | (set[3] << | ||
80 | uPD98402_MDR_SS_SHIFT),MDR); | ||
81 | spin_unlock_irqrestore(&PRIV(dev)->lock, flags); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | |||
86 | static int get_sense(struct atm_dev *dev,u8 __user *arg) | ||
87 | { | ||
88 | unsigned long flags; | ||
89 | unsigned char s[3]; | ||
90 | |||
91 | spin_lock_irqsave(&PRIV(dev)->lock, flags); | ||
92 | s[0] = GET(C11R); | ||
93 | s[1] = GET(C12R); | ||
94 | s[2] = GET(C13R); | ||
95 | spin_unlock_irqrestore(&PRIV(dev)->lock, flags); | ||
96 | return (put_user(s[0], arg) || put_user(s[1], arg+1) || | ||
97 | put_user(s[2], arg+2) || put_user(0xff, arg+3) || | ||
98 | put_user(0xff, arg+4) || put_user(0xff, arg+5)) ? -EFAULT : 0; | ||
99 | } | ||
100 | |||
101 | |||
102 | static int set_loopback(struct atm_dev *dev,int mode) | ||
103 | { | ||
104 | unsigned char mode_reg; | ||
105 | |||
106 | mode_reg = GET(MDR) & ~(uPD98402_MDR_TPLP | uPD98402_MDR_ALP | | ||
107 | uPD98402_MDR_RPLP); | ||
108 | switch (__ATM_LM_XTLOC(mode)) { | ||
109 | case __ATM_LM_NONE: | ||
110 | break; | ||
111 | case __ATM_LM_PHY: | ||
112 | mode_reg |= uPD98402_MDR_TPLP; | ||
113 | break; | ||
114 | case __ATM_LM_ATM: | ||
115 | mode_reg |= uPD98402_MDR_ALP; | ||
116 | break; | ||
117 | default: | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | switch (__ATM_LM_XTRMT(mode)) { | ||
121 | case __ATM_LM_NONE: | ||
122 | break; | ||
123 | case __ATM_LM_PHY: | ||
124 | mode_reg |= uPD98402_MDR_RPLP; | ||
125 | break; | ||
126 | default: | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | PUT(mode_reg,MDR); | ||
130 | PRIV(dev)->loop_mode = mode; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | |||
135 | static int uPD98402_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
136 | { | ||
137 | switch (cmd) { | ||
138 | |||
139 | case SONET_GETSTATZ: | ||
140 | case SONET_GETSTAT: | ||
141 | return fetch_stats(dev,arg, cmd == SONET_GETSTATZ); | ||
142 | case SONET_SETFRAMING: | ||
143 | return set_framing(dev, (int)(unsigned long)arg); | ||
144 | case SONET_GETFRAMING: | ||
145 | return put_user(PRIV(dev)->framing,(int __user *)arg) ? | ||
146 | -EFAULT : 0; | ||
147 | case SONET_GETFRSENSE: | ||
148 | return get_sense(dev,arg); | ||
149 | case ATM_SETLOOP: | ||
150 | return set_loopback(dev, (int)(unsigned long)arg); | ||
151 | case ATM_GETLOOP: | ||
152 | return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ? | ||
153 | -EFAULT : 0; | ||
154 | case ATM_QUERYLOOP: | ||
155 | return put_user(ATM_LM_LOC_PHY | ATM_LM_LOC_ATM | | ||
156 | ATM_LM_RMT_PHY,(int __user *)arg) ? -EFAULT : 0; | ||
157 | default: | ||
158 | return -ENOIOCTLCMD; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | |||
163 | #define ADD_LIMITED(s,v) \ | ||
164 | { atomic_add(GET(v),&PRIV(dev)->sonet_stats.s); \ | ||
165 | if (atomic_read(&PRIV(dev)->sonet_stats.s) < 0) \ | ||
166 | atomic_set(&PRIV(dev)->sonet_stats.s,INT_MAX); } | ||
167 | |||
168 | |||
169 | static void stat_event(struct atm_dev *dev) | ||
170 | { | ||
171 | unsigned char events; | ||
172 | |||
173 | events = GET(PCR); | ||
174 | if (events & uPD98402_PFM_PFEB) ADD_LIMITED(path_febe,PFECB); | ||
175 | if (events & uPD98402_PFM_LFEB) ADD_LIMITED(line_febe,LECCT); | ||
176 | if (events & uPD98402_PFM_B3E) ADD_LIMITED(path_bip,B3ECT); | ||
177 | if (events & uPD98402_PFM_B2E) ADD_LIMITED(line_bip,B2ECT); | ||
178 | if (events & uPD98402_PFM_B1E) ADD_LIMITED(section_bip,B1ECT); | ||
179 | } | ||
180 | |||
181 | |||
182 | #undef ADD_LIMITED | ||
183 | |||
184 | |||
185 | static void uPD98402_int(struct atm_dev *dev) | ||
186 | { | ||
187 | static unsigned long silence = 0; | ||
188 | unsigned char reason; | ||
189 | |||
190 | while ((reason = GET(PICR))) { | ||
191 | if (reason & uPD98402_INT_LOS) | ||
192 | printk(KERN_NOTICE "%s(itf %d): signal lost\n", | ||
193 | dev->type,dev->number); | ||
194 | if (reason & uPD98402_INT_PFM) stat_event(dev); | ||
195 | if (reason & uPD98402_INT_PCO) { | ||
196 | (void) GET(PCOCR); /* clear interrupt cause */ | ||
197 | atomic_add(GET(HECCT), | ||
198 | &PRIV(dev)->sonet_stats.uncorr_hcs); | ||
199 | } | ||
200 | if ((reason & uPD98402_INT_RFO) && | ||
201 | (time_after(jiffies, silence) || silence == 0)) { | ||
202 | printk(KERN_WARNING "%s(itf %d): uPD98402 receive " | ||
203 | "FIFO overflow\n",dev->type,dev->number); | ||
204 | silence = (jiffies+HZ/2)|1; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | |||
210 | static int uPD98402_start(struct atm_dev *dev) | ||
211 | { | ||
212 | DPRINTK("phy_start\n"); | ||
213 | if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL))) | ||
214 | return -ENOMEM; | ||
215 | spin_lock_init(&PRIV(dev)->lock); | ||
216 | memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats)); | ||
217 | (void) GET(PCR); /* clear performance events */ | ||
218 | PUT(uPD98402_PFM_FJ,PCMR); /* ignore frequency adj */ | ||
219 | (void) GET(PCOCR); /* clear overflows */ | ||
220 | PUT(~uPD98402_PCO_HECC,PCOMR); | ||
221 | (void) GET(PICR); /* clear interrupts */ | ||
222 | PUT(~(uPD98402_INT_PFM | uPD98402_INT_ALM | uPD98402_INT_RFO | | ||
223 | uPD98402_INT_LOS),PIMR); /* enable them */ | ||
224 | (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ | ||
225 | atomic_set(&PRIV(dev)->sonet_stats.corr_hcs,-1); | ||
226 | atomic_set(&PRIV(dev)->sonet_stats.tx_cells,-1); | ||
227 | atomic_set(&PRIV(dev)->sonet_stats.rx_cells,-1); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | |||
232 | static int uPD98402_stop(struct atm_dev *dev) | ||
233 | { | ||
234 | /* let SAR driver worry about stopping interrupts */ | ||
235 | kfree(PRIV(dev)); | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | |||
240 | static const struct atmphy_ops uPD98402_ops = { | ||
241 | .start = uPD98402_start, | ||
242 | .ioctl = uPD98402_ioctl, | ||
243 | .interrupt = uPD98402_int, | ||
244 | .stop = uPD98402_stop, | ||
245 | }; | ||
246 | |||
247 | |||
248 | int uPD98402_init(struct atm_dev *dev) | ||
249 | { | ||
250 | DPRINTK("phy_init\n"); | ||
251 | dev->phy = &uPD98402_ops; | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | |||
256 | MODULE_LICENSE("GPL"); | ||
257 | |||
258 | EXPORT_SYMBOL(uPD98402_init); | ||
259 | |||
260 | static __init int uPD98402_module_init(void) | ||
261 | { | ||
262 | return 0; | ||
263 | } | ||
264 | module_init(uPD98402_module_init); | ||
265 | /* module_exit not defined so not unloadable */ | ||
diff --git a/drivers/atm/uPD98402.h b/drivers/atm/uPD98402.h new file mode 100644 index 000000000000..c947214db7e3 --- /dev/null +++ b/drivers/atm/uPD98402.h | |||
@@ -0,0 +1,106 @@ | |||
1 | /* drivers/atm/uPD98402.h - NEC uPD98402 (PHY) declarations */ | ||
2 | |||
3 | /* Written 1995 by Werner Almesberger, EPFL LRC */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVERS_ATM_uPD98402_H | ||
7 | #define DRIVERS_ATM_uPD98402_H | ||
8 | |||
9 | /* | ||
10 | * Registers | ||
11 | */ | ||
12 | |||
13 | #define uPD98402_CMR 0x00 /* Command Register */ | ||
14 | #define uPD98402_MDR 0x01 /* Mode Register */ | ||
15 | #define uPD98402_PICR 0x02 /* PHY Interrupt Cause Register */ | ||
16 | #define uPD98402_PIMR 0x03 /* PHY Interrupt Mask Register */ | ||
17 | #define uPD98402_ACR 0x04 /* Alarm Cause Register */ | ||
18 | #define uPD98402_ACMR 0x05 /* Alarm Cause Mask Register */ | ||
19 | #define uPD98402_PCR 0x06 /* Performance Cause Register */ | ||
20 | #define uPD98402_PCMR 0x07 /* Performance Cause Mask Register */ | ||
21 | #define uPD98402_IACM 0x08 /* Internal Alarm Cause Mask Register */ | ||
22 | #define uPD98402_B1ECT 0x09 /* B1 Error Count Register */ | ||
23 | #define uPD98402_B2ECT 0x0a /* B2 Error Count Register */ | ||
24 | #define uPD98402_B3ECT 0x0b /* B3 Error Count Regster */ | ||
25 | #define uPD98402_PFECB 0x0c /* Path FEBE Count Register */ | ||
26 | #define uPD98402_LECCT 0x0d /* Line FEBE Count Register */ | ||
27 | #define uPD98402_HECCT 0x0e /* HEC Error Count Register */ | ||
28 | #define uPD98402_FJCT 0x0f /* Frequence Justification Count Reg */ | ||
29 | #define uPD98402_PCOCR 0x10 /* Perf. Counter Overflow Cause Reg */ | ||
30 | #define uPD98402_PCOMR 0x11 /* Perf. Counter Overflow Mask Reg */ | ||
31 | #define uPD98402_C11T 0x20 /* C11T Data Register */ | ||
32 | #define uPD98402_C12T 0x21 /* C12T Data Register */ | ||
33 | #define uPD98402_C13T 0x22 /* C13T Data Register */ | ||
34 | #define uPD98402_F1T 0x23 /* F1T Data Register */ | ||
35 | #define uPD98402_K2T 0x25 /* K2T Data Register */ | ||
36 | #define uPD98402_C2T 0x26 /* C2T Data Register */ | ||
37 | #define uPD98402_F2T 0x27 /* F2T Data Register */ | ||
38 | #define uPD98402_C11R 0x30 /* C11T Data Register */ | ||
39 | #define uPD98402_C12R 0x31 /* C12T Data Register */ | ||
40 | #define uPD98402_C13R 0x32 /* C13T Data Register */ | ||
41 | #define uPD98402_F1R 0x33 /* F1T Data Register */ | ||
42 | #define uPD98402_K2R 0x35 /* K2T Data Register */ | ||
43 | #define uPD98402_C2R 0x36 /* C2T Data Register */ | ||
44 | #define uPD98402_F2R 0x37 /* F2T Data Register */ | ||
45 | |||
46 | /* CMR is at 0x00 */ | ||
47 | #define uPD98402_CMR_PFRF 0x01 /* Send path FERF */ | ||
48 | #define uPD98402_CMR_LFRF 0x02 /* Send line FERF */ | ||
49 | #define uPD98402_CMR_PAIS 0x04 /* Send path AIS */ | ||
50 | #define uPD98402_CMR_LAIS 0x08 /* Send line AIS */ | ||
51 | |||
52 | /* MDR is at 0x01 */ | ||
53 | #define uPD98402_MDR_ALP 0x01 /* ATM layer loopback */ | ||
54 | #define uPD98402_MDR_TPLP 0x02 /* PMD loopback, to host */ | ||
55 | #define uPD98402_MDR_RPLP 0x04 /* PMD loopback, to network */ | ||
56 | #define uPD98402_MDR_SS0 0x08 /* SS0 */ | ||
57 | #define uPD98402_MDR_SS1 0x10 /* SS1 */ | ||
58 | #define uPD98402_MDR_SS_MASK 0x18 /* mask */ | ||
59 | #define uPD98402_MDR_SS_SHIFT 3 /* shift */ | ||
60 | #define uPD98402_MDR_HEC 0x20 /* disable HEC inbound processing */ | ||
61 | #define uPD98402_MDR_FSR 0x40 /* disable frame scrambler */ | ||
62 | #define uPD98402_MDR_CSR 0x80 /* disable cell scrambler */ | ||
63 | |||
64 | /* PICR is at 0x02, PIMR is at 0x03 */ | ||
65 | #define uPD98402_INT_PFM 0x01 /* performance counter has changed */ | ||
66 | #define uPD98402_INT_ALM 0x02 /* line fault */ | ||
67 | #define uPD98402_INT_RFO 0x04 /* receive FIFO overflow */ | ||
68 | #define uPD98402_INT_PCO 0x08 /* performance counter overflow */ | ||
69 | #define uPD98402_INT_OTD 0x20 /* OTD has occurred */ | ||
70 | #define uPD98402_INT_LOS 0x40 /* Loss Of Signal */ | ||
71 | #define uPD98402_INT_LOF 0x80 /* Loss Of Frame */ | ||
72 | |||
73 | /* ACR is as 0x04, ACMR is at 0x05 */ | ||
74 | #define uPD98402_ALM_PFRF 0x01 /* path FERF */ | ||
75 | #define uPD98402_ALM_LFRF 0x02 /* line FERF */ | ||
76 | #define uPD98402_ALM_PAIS 0x04 /* path AIS */ | ||
77 | #define uPD98402_ALM_LAIS 0x08 /* line AIS */ | ||
78 | #define uPD98402_ALM_LOD 0x10 /* loss of delineation */ | ||
79 | #define uPD98402_ALM_LOP 0x20 /* loss of pointer */ | ||
80 | #define uPD98402_ALM_OOF 0x40 /* out of frame */ | ||
81 | |||
82 | /* PCR is at 0x06, PCMR is at 0x07 */ | ||
83 | #define uPD98402_PFM_PFEB 0x01 /* path FEBE */ | ||
84 | #define uPD98402_PFM_LFEB 0x02 /* line FEBE */ | ||
85 | #define uPD98402_PFM_B3E 0x04 /* B3 error */ | ||
86 | #define uPD98402_PFM_B2E 0x08 /* B2 error */ | ||
87 | #define uPD98402_PFM_B1E 0x10 /* B1 error */ | ||
88 | #define uPD98402_PFM_FJ 0x20 /* frequency justification */ | ||
89 | |||
90 | /* IACM is at 0x08 */ | ||
91 | #define uPD98402_IACM_PFRF 0x01 /* don't generate path FERF */ | ||
92 | #define uPD98402_IACM_LFRF 0x02 /* don't generate line FERF */ | ||
93 | |||
94 | /* PCOCR is at 0x010, PCOMR is at 0x11 */ | ||
95 | #define uPD98402_PCO_B1EC 0x01 /* B1ECT overflow */ | ||
96 | #define uPD98402_PCO_B2EC 0x02 /* B2ECT overflow */ | ||
97 | #define uPD98402_PCO_B3EC 0x04 /* B3ECT overflow */ | ||
98 | #define uPD98402_PCO_PFBC 0x08 /* PFEBC overflow */ | ||
99 | #define uPD98402_PCO_LFBC 0x10 /* LFEVC overflow */ | ||
100 | #define uPD98402_PCO_HECC 0x20 /* HECCT overflow */ | ||
101 | #define uPD98402_PCO_FJC 0x40 /* FJCT overflow */ | ||
102 | |||
103 | |||
104 | int uPD98402_init(struct atm_dev *dev); | ||
105 | |||
106 | #endif | ||
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c new file mode 100644 index 000000000000..47a800519ad0 --- /dev/null +++ b/drivers/atm/zatm.c | |||
@@ -0,0 +1,1646 @@ | |||
1 | /* drivers/atm/zatm.c - ZeitNet ZN122x device driver */ | ||
2 | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #include <linux/config.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/mm.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/atm.h> | ||
14 | #include <linux/atmdev.h> | ||
15 | #include <linux/sonet.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/netdevice.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/ioport.h> /* for request_region */ | ||
20 | #include <linux/uio.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/atm_zatm.h> | ||
23 | #include <linux/capability.h> | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/wait.h> | ||
26 | #include <asm/byteorder.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/string.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/atomic.h> | ||
31 | #include <asm/uaccess.h> | ||
32 | |||
33 | #include "uPD98401.h" | ||
34 | #include "uPD98402.h" | ||
35 | #include "zeprom.h" | ||
36 | #include "zatm.h" | ||
37 | |||
38 | |||
39 | /* | ||
40 | * TODO: | ||
41 | * | ||
42 | * Minor features | ||
43 | * - support 64 kB SDUs (will have to use multibuffer batches then :-( ) | ||
44 | * - proper use of CDV, credit = max(1,CDVT*PCR) | ||
45 | * - AAL0 | ||
46 | * - better receive timestamps | ||
47 | * - OAM | ||
48 | */ | ||
49 | |||
50 | #define ZATM_COPPER 1 | ||
51 | |||
52 | #if 0 | ||
53 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | ||
54 | #else | ||
55 | #define DPRINTK(format,args...) | ||
56 | #endif | ||
57 | |||
58 | #ifndef CONFIG_ATM_ZATM_DEBUG | ||
59 | |||
60 | |||
61 | #define NULLCHECK(x) | ||
62 | |||
63 | #define EVENT(s,a,b) | ||
64 | |||
65 | |||
66 | static void event_dump(void) | ||
67 | { | ||
68 | } | ||
69 | |||
70 | |||
71 | #else | ||
72 | |||
73 | |||
74 | /* | ||
75 | * NULL pointer checking | ||
76 | */ | ||
77 | |||
78 | #define NULLCHECK(x) \ | ||
79 | if ((unsigned long) (x) < 0x30) printk(KERN_CRIT #x "==0x%x\n", (int) (x)) | ||
80 | |||
81 | /* | ||
82 | * Very extensive activity logging. Greatly improves bug detection speed but | ||
83 | * costs a few Mbps if enabled. | ||
84 | */ | ||
85 | |||
86 | #define EV 64 | ||
87 | |||
88 | static const char *ev[EV]; | ||
89 | static unsigned long ev_a[EV],ev_b[EV]; | ||
90 | static int ec = 0; | ||
91 | |||
92 | |||
93 | static void EVENT(const char *s,unsigned long a,unsigned long b) | ||
94 | { | ||
95 | ev[ec] = s; | ||
96 | ev_a[ec] = a; | ||
97 | ev_b[ec] = b; | ||
98 | ec = (ec+1) % EV; | ||
99 | } | ||
100 | |||
101 | |||
102 | static void event_dump(void) | ||
103 | { | ||
104 | int n,i; | ||
105 | |||
106 | printk(KERN_NOTICE "----- event dump follows -----\n"); | ||
107 | for (n = 0; n < EV; n++) { | ||
108 | i = (ec+n) % EV; | ||
109 | printk(KERN_NOTICE); | ||
110 | printk(ev[i] ? ev[i] : "(null)",ev_a[i],ev_b[i]); | ||
111 | } | ||
112 | printk(KERN_NOTICE "----- event dump ends here -----\n"); | ||
113 | } | ||
114 | |||
115 | |||
116 | #endif /* CONFIG_ATM_ZATM_DEBUG */ | ||
117 | |||
118 | |||
119 | #define RING_BUSY 1 /* indication from do_tx that PDU has to be | ||
120 | backlogged */ | ||
121 | |||
122 | static struct atm_dev *zatm_boards = NULL; | ||
123 | static unsigned long dummy[2] = {0,0}; | ||
124 | |||
125 | |||
126 | #define zin_n(r) inl(zatm_dev->base+r*4) | ||
127 | #define zin(r) inl(zatm_dev->base+uPD98401_##r*4) | ||
128 | #define zout(v,r) outl(v,zatm_dev->base+uPD98401_##r*4) | ||
129 | #define zwait while (zin(CMR) & uPD98401_BUSY) | ||
130 | |||
131 | /* RX0, RX1, TX0, TX1 */ | ||
132 | static const int mbx_entries[NR_MBX] = { 1024,1024,1024,1024 }; | ||
133 | static const int mbx_esize[NR_MBX] = { 16,16,4,4 }; /* entry size in bytes */ | ||
134 | |||
135 | #define MBX_SIZE(i) (mbx_entries[i]*mbx_esize[i]) | ||
136 | |||
137 | |||
138 | /*-------------------------------- utilities --------------------------------*/ | ||
139 | |||
140 | |||
141 | static void zpokel(struct zatm_dev *zatm_dev,u32 value,u32 addr) | ||
142 | { | ||
143 | zwait; | ||
144 | zout(value,CER); | ||
145 | zout(uPD98401_IND_ACC | uPD98401_IA_BALL | | ||
146 | (uPD98401_IA_TGT_CM << uPD98401_IA_TGT_SHIFT) | addr,CMR); | ||
147 | } | ||
148 | |||
149 | |||
150 | static u32 zpeekl(struct zatm_dev *zatm_dev,u32 addr) | ||
151 | { | ||
152 | zwait; | ||
153 | zout(uPD98401_IND_ACC | uPD98401_IA_BALL | uPD98401_IA_RW | | ||
154 | (uPD98401_IA_TGT_CM << uPD98401_IA_TGT_SHIFT) | addr,CMR); | ||
155 | zwait; | ||
156 | return zin(CER); | ||
157 | } | ||
158 | |||
159 | |||
160 | /*------------------------------- free lists --------------------------------*/ | ||
161 | |||
162 | |||
163 | /* | ||
164 | * Free buffer head structure: | ||
165 | * [0] pointer to buffer (for SAR) | ||
166 | * [1] buffer descr link pointer (for SAR) | ||
167 | * [2] back pointer to skb (for poll_rx) | ||
168 | * [3] data | ||
169 | * ... | ||
170 | */ | ||
171 | |||
172 | struct rx_buffer_head { | ||
173 | u32 buffer; /* pointer to buffer (for SAR) */ | ||
174 | u32 link; /* buffer descriptor link pointer (for SAR) */ | ||
175 | struct sk_buff *skb; /* back pointer to skb (for poll_rx) */ | ||
176 | }; | ||
177 | |||
178 | |||
179 | static void refill_pool(struct atm_dev *dev,int pool) | ||
180 | { | ||
181 | struct zatm_dev *zatm_dev; | ||
182 | struct sk_buff *skb; | ||
183 | struct rx_buffer_head *first; | ||
184 | unsigned long flags; | ||
185 | int align,offset,free,count,size; | ||
186 | |||
187 | EVENT("refill_pool\n",0,0); | ||
188 | zatm_dev = ZATM_DEV(dev); | ||
189 | size = (64 << (pool <= ZATM_AAL5_POOL_BASE ? 0 : | ||
190 | pool-ZATM_AAL5_POOL_BASE))+sizeof(struct rx_buffer_head); | ||
191 | if (size < PAGE_SIZE) { | ||
192 | align = 32; /* for 32 byte alignment */ | ||
193 | offset = sizeof(struct rx_buffer_head); | ||
194 | } | ||
195 | else { | ||
196 | align = 4096; | ||
197 | offset = zatm_dev->pool_info[pool].offset+ | ||
198 | sizeof(struct rx_buffer_head); | ||
199 | } | ||
200 | size += align; | ||
201 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
202 | free = zpeekl(zatm_dev,zatm_dev->pool_base+2*pool) & | ||
203 | uPD98401_RXFP_REMAIN; | ||
204 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
205 | if (free >= zatm_dev->pool_info[pool].low_water) return; | ||
206 | EVENT("starting ... POOL: 0x%x, 0x%x\n", | ||
207 | zpeekl(zatm_dev,zatm_dev->pool_base+2*pool), | ||
208 | zpeekl(zatm_dev,zatm_dev->pool_base+2*pool+1)); | ||
209 | EVENT("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); | ||
210 | count = 0; | ||
211 | first = NULL; | ||
212 | while (free < zatm_dev->pool_info[pool].high_water) { | ||
213 | struct rx_buffer_head *head; | ||
214 | |||
215 | skb = alloc_skb(size,GFP_ATOMIC); | ||
216 | if (!skb) { | ||
217 | printk(KERN_WARNING DEV_LABEL "(Itf %d): got no new " | ||
218 | "skb (%d) with %d free\n",dev->number,size,free); | ||
219 | break; | ||
220 | } | ||
221 | skb_reserve(skb,(unsigned char *) ((((unsigned long) skb->data+ | ||
222 | align+offset-1) & ~(unsigned long) (align-1))-offset)- | ||
223 | skb->data); | ||
224 | head = (struct rx_buffer_head *) skb->data; | ||
225 | skb_reserve(skb,sizeof(struct rx_buffer_head)); | ||
226 | if (!first) first = head; | ||
227 | count++; | ||
228 | head->buffer = virt_to_bus(skb->data); | ||
229 | head->link = 0; | ||
230 | head->skb = skb; | ||
231 | EVENT("enq skb 0x%08lx/0x%08lx\n",(unsigned long) skb, | ||
232 | (unsigned long) head); | ||
233 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
234 | if (zatm_dev->last_free[pool]) | ||
235 | ((struct rx_buffer_head *) (zatm_dev->last_free[pool]-> | ||
236 | data))[-1].link = virt_to_bus(head); | ||
237 | zatm_dev->last_free[pool] = skb; | ||
238 | skb_queue_tail(&zatm_dev->pool[pool],skb); | ||
239 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
240 | free++; | ||
241 | } | ||
242 | if (first) { | ||
243 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
244 | zwait; | ||
245 | zout(virt_to_bus(first),CER); | ||
246 | zout(uPD98401_ADD_BAT | (pool << uPD98401_POOL_SHIFT) | count, | ||
247 | CMR); | ||
248 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
249 | EVENT ("POOL: 0x%x, 0x%x\n", | ||
250 | zpeekl(zatm_dev,zatm_dev->pool_base+2*pool), | ||
251 | zpeekl(zatm_dev,zatm_dev->pool_base+2*pool+1)); | ||
252 | EVENT("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | |||
257 | static void drain_free(struct atm_dev *dev,int pool) | ||
258 | { | ||
259 | skb_queue_purge(&ZATM_DEV(dev)->pool[pool]); | ||
260 | } | ||
261 | |||
262 | |||
263 | static int pool_index(int max_pdu) | ||
264 | { | ||
265 | int i; | ||
266 | |||
267 | if (max_pdu % ATM_CELL_PAYLOAD) | ||
268 | printk(KERN_ERR DEV_LABEL ": driver error in pool_index: " | ||
269 | "max_pdu is %d\n",max_pdu); | ||
270 | if (max_pdu > 65536) return -1; | ||
271 | for (i = 0; (64 << i) < max_pdu; i++); | ||
272 | return i+ZATM_AAL5_POOL_BASE; | ||
273 | } | ||
274 | |||
275 | |||
276 | /* use_pool isn't reentrant */ | ||
277 | |||
278 | |||
279 | static void use_pool(struct atm_dev *dev,int pool) | ||
280 | { | ||
281 | struct zatm_dev *zatm_dev; | ||
282 | unsigned long flags; | ||
283 | int size; | ||
284 | |||
285 | zatm_dev = ZATM_DEV(dev); | ||
286 | if (!(zatm_dev->pool_info[pool].ref_count++)) { | ||
287 | skb_queue_head_init(&zatm_dev->pool[pool]); | ||
288 | size = pool-ZATM_AAL5_POOL_BASE; | ||
289 | if (size < 0) size = 0; /* 64B... */ | ||
290 | else if (size > 10) size = 10; /* ... 64kB */ | ||
291 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
292 | zpokel(zatm_dev,((zatm_dev->pool_info[pool].low_water/4) << | ||
293 | uPD98401_RXFP_ALERT_SHIFT) | | ||
294 | (1 << uPD98401_RXFP_BTSZ_SHIFT) | | ||
295 | (size << uPD98401_RXFP_BFSZ_SHIFT), | ||
296 | zatm_dev->pool_base+pool*2); | ||
297 | zpokel(zatm_dev,(unsigned long) dummy,zatm_dev->pool_base+ | ||
298 | pool*2+1); | ||
299 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
300 | zatm_dev->last_free[pool] = NULL; | ||
301 | refill_pool(dev,pool); | ||
302 | } | ||
303 | DPRINTK("pool %d: %d\n",pool,zatm_dev->pool_info[pool].ref_count); | ||
304 | } | ||
305 | |||
306 | |||
307 | static void unuse_pool(struct atm_dev *dev,int pool) | ||
308 | { | ||
309 | if (!(--ZATM_DEV(dev)->pool_info[pool].ref_count)) | ||
310 | drain_free(dev,pool); | ||
311 | } | ||
312 | |||
313 | /*----------------------------------- RX ------------------------------------*/ | ||
314 | |||
315 | |||
316 | #if 0 | ||
317 | static void exception(struct atm_vcc *vcc) | ||
318 | { | ||
319 | static int count = 0; | ||
320 | struct zatm_dev *zatm_dev = ZATM_DEV(vcc->dev); | ||
321 | struct zatm_vcc *zatm_vcc = ZATM_VCC(vcc); | ||
322 | unsigned long *qrp; | ||
323 | int i; | ||
324 | |||
325 | if (count++ > 2) return; | ||
326 | for (i = 0; i < 8; i++) | ||
327 | printk("TX%d: 0x%08lx\n",i, | ||
328 | zpeekl(zatm_dev,zatm_vcc->tx_chan*VC_SIZE/4+i)); | ||
329 | for (i = 0; i < 5; i++) | ||
330 | printk("SH%d: 0x%08lx\n",i, | ||
331 | zpeekl(zatm_dev,uPD98401_IM(zatm_vcc->shaper)+16*i)); | ||
332 | qrp = (unsigned long *) zpeekl(zatm_dev,zatm_vcc->tx_chan*VC_SIZE/4+ | ||
333 | uPD98401_TXVC_QRP); | ||
334 | printk("qrp=0x%08lx\n",(unsigned long) qrp); | ||
335 | for (i = 0; i < 4; i++) printk("QRP[%d]: 0x%08lx",i,qrp[i]); | ||
336 | } | ||
337 | #endif | ||
338 | |||
339 | |||
340 | static const char *err_txt[] = { | ||
341 | "No error", | ||
342 | "RX buf underflow", | ||
343 | "RX FIFO overrun", | ||
344 | "Maximum len violation", | ||
345 | "CRC error", | ||
346 | "User abort", | ||
347 | "Length violation", | ||
348 | "T1 error", | ||
349 | "Deactivated", | ||
350 | "???", | ||
351 | "???", | ||
352 | "???", | ||
353 | "???", | ||
354 | "???", | ||
355 | "???", | ||
356 | "???" | ||
357 | }; | ||
358 | |||
359 | |||
360 | static void poll_rx(struct atm_dev *dev,int mbx) | ||
361 | { | ||
362 | struct zatm_dev *zatm_dev; | ||
363 | unsigned long pos; | ||
364 | u32 x; | ||
365 | int error; | ||
366 | |||
367 | EVENT("poll_rx\n",0,0); | ||
368 | zatm_dev = ZATM_DEV(dev); | ||
369 | pos = (zatm_dev->mbx_start[mbx] & ~0xffffUL) | zin(MTA(mbx)); | ||
370 | while (x = zin(MWA(mbx)), (pos & 0xffff) != x) { | ||
371 | u32 *here; | ||
372 | struct sk_buff *skb; | ||
373 | struct atm_vcc *vcc; | ||
374 | int cells,size,chan; | ||
375 | |||
376 | EVENT("MBX: host 0x%lx, nic 0x%x\n",pos,x); | ||
377 | here = (u32 *) pos; | ||
378 | if (((pos += 16) & 0xffff) == zatm_dev->mbx_end[mbx]) | ||
379 | pos = zatm_dev->mbx_start[mbx]; | ||
380 | cells = here[0] & uPD98401_AAL5_SIZE; | ||
381 | #if 0 | ||
382 | printk("RX IND: 0x%x, 0x%x, 0x%x, 0x%x\n",here[0],here[1],here[2],here[3]); | ||
383 | { | ||
384 | unsigned long *x; | ||
385 | printk("POOL: 0x%08x, 0x%08x\n",zpeekl(zatm_dev, | ||
386 | zatm_dev->pool_base), | ||
387 | zpeekl(zatm_dev,zatm_dev->pool_base+1)); | ||
388 | x = (unsigned long *) here[2]; | ||
389 | printk("[0..3] = 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n", | ||
390 | x[0],x[1],x[2],x[3]); | ||
391 | } | ||
392 | #endif | ||
393 | error = 0; | ||
394 | if (here[3] & uPD98401_AAL5_ERR) { | ||
395 | error = (here[3] & uPD98401_AAL5_ES) >> | ||
396 | uPD98401_AAL5_ES_SHIFT; | ||
397 | if (error == uPD98401_AAL5_ES_DEACT || | ||
398 | error == uPD98401_AAL5_ES_FREE) continue; | ||
399 | } | ||
400 | EVENT("error code 0x%x/0x%x\n",(here[3] & uPD98401_AAL5_ES) >> | ||
401 | uPD98401_AAL5_ES_SHIFT,error); | ||
402 | skb = ((struct rx_buffer_head *) bus_to_virt(here[2]))->skb; | ||
403 | do_gettimeofday(&skb->stamp); | ||
404 | #if 0 | ||
405 | printk("[-3..0] 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",((unsigned *) skb->data)[-3], | ||
406 | ((unsigned *) skb->data)[-2],((unsigned *) skb->data)[-1], | ||
407 | ((unsigned *) skb->data)[0]); | ||
408 | #endif | ||
409 | EVENT("skb 0x%lx, here 0x%lx\n",(unsigned long) skb, | ||
410 | (unsigned long) here); | ||
411 | #if 0 | ||
412 | printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); | ||
413 | #endif | ||
414 | size = error ? 0 : ntohs(((__be16 *) skb->data)[cells* | ||
415 | ATM_CELL_PAYLOAD/sizeof(u16)-3]); | ||
416 | EVENT("got skb 0x%lx, size %d\n",(unsigned long) skb,size); | ||
417 | chan = (here[3] & uPD98401_AAL5_CHAN) >> | ||
418 | uPD98401_AAL5_CHAN_SHIFT; | ||
419 | if (chan < zatm_dev->chans && zatm_dev->rx_map[chan]) { | ||
420 | vcc = zatm_dev->rx_map[chan]; | ||
421 | if (skb == zatm_dev->last_free[ZATM_VCC(vcc)->pool]) | ||
422 | zatm_dev->last_free[ZATM_VCC(vcc)->pool] = NULL; | ||
423 | skb_unlink(skb); | ||
424 | } | ||
425 | else { | ||
426 | printk(KERN_ERR DEV_LABEL "(itf %d): RX indication " | ||
427 | "for non-existing channel\n",dev->number); | ||
428 | size = 0; | ||
429 | vcc = NULL; | ||
430 | event_dump(); | ||
431 | } | ||
432 | if (error) { | ||
433 | static unsigned long silence = 0; | ||
434 | static int last_error = 0; | ||
435 | |||
436 | if (error != last_error || | ||
437 | time_after(jiffies, silence) || silence == 0){ | ||
438 | printk(KERN_WARNING DEV_LABEL "(itf %d): " | ||
439 | "chan %d error %s\n",dev->number,chan, | ||
440 | err_txt[error]); | ||
441 | last_error = error; | ||
442 | silence = (jiffies+2*HZ)|1; | ||
443 | } | ||
444 | size = 0; | ||
445 | } | ||
446 | if (size && (size > cells*ATM_CELL_PAYLOAD-ATM_AAL5_TRAILER || | ||
447 | size <= (cells-1)*ATM_CELL_PAYLOAD-ATM_AAL5_TRAILER)) { | ||
448 | printk(KERN_ERR DEV_LABEL "(itf %d): size %d with %d " | ||
449 | "cells\n",dev->number,size,cells); | ||
450 | size = 0; | ||
451 | event_dump(); | ||
452 | } | ||
453 | if (size > ATM_MAX_AAL5_PDU) { | ||
454 | printk(KERN_ERR DEV_LABEL "(itf %d): size too big " | ||
455 | "(%d)\n",dev->number,size); | ||
456 | size = 0; | ||
457 | event_dump(); | ||
458 | } | ||
459 | if (!size) { | ||
460 | dev_kfree_skb_irq(skb); | ||
461 | if (vcc) atomic_inc(&vcc->stats->rx_err); | ||
462 | continue; | ||
463 | } | ||
464 | if (!atm_charge(vcc,skb->truesize)) { | ||
465 | dev_kfree_skb_irq(skb); | ||
466 | continue; | ||
467 | } | ||
468 | skb->len = size; | ||
469 | ATM_SKB(skb)->vcc = vcc; | ||
470 | vcc->push(vcc,skb); | ||
471 | atomic_inc(&vcc->stats->rx); | ||
472 | } | ||
473 | zout(pos & 0xffff,MTA(mbx)); | ||
474 | #if 0 /* probably a stupid idea */ | ||
475 | refill_pool(dev,zatm_vcc->pool); | ||
476 | /* maybe this saves us a few interrupts */ | ||
477 | #endif | ||
478 | } | ||
479 | |||
480 | |||
481 | static int open_rx_first(struct atm_vcc *vcc) | ||
482 | { | ||
483 | struct zatm_dev *zatm_dev; | ||
484 | struct zatm_vcc *zatm_vcc; | ||
485 | unsigned long flags; | ||
486 | unsigned short chan; | ||
487 | int cells; | ||
488 | |||
489 | DPRINTK("open_rx_first (0x%x)\n",inb_p(0xc053)); | ||
490 | zatm_dev = ZATM_DEV(vcc->dev); | ||
491 | zatm_vcc = ZATM_VCC(vcc); | ||
492 | zatm_vcc->rx_chan = 0; | ||
493 | if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0; | ||
494 | if (vcc->qos.aal == ATM_AAL5) { | ||
495 | if (vcc->qos.rxtp.max_sdu > 65464) | ||
496 | vcc->qos.rxtp.max_sdu = 65464; | ||
497 | /* fix this - we may want to receive 64kB SDUs | ||
498 | later */ | ||
499 | cells = (vcc->qos.rxtp.max_sdu+ATM_AAL5_TRAILER+ | ||
500 | ATM_CELL_PAYLOAD-1)/ATM_CELL_PAYLOAD; | ||
501 | zatm_vcc->pool = pool_index(cells*ATM_CELL_PAYLOAD); | ||
502 | } | ||
503 | else { | ||
504 | cells = 1; | ||
505 | zatm_vcc->pool = ZATM_AAL0_POOL; | ||
506 | } | ||
507 | if (zatm_vcc->pool < 0) return -EMSGSIZE; | ||
508 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
509 | zwait; | ||
510 | zout(uPD98401_OPEN_CHAN,CMR); | ||
511 | zwait; | ||
512 | DPRINTK("0x%x 0x%x\n",zin(CMR),zin(CER)); | ||
513 | chan = (zin(CMR) & uPD98401_CHAN_ADDR) >> uPD98401_CHAN_ADDR_SHIFT; | ||
514 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
515 | DPRINTK("chan is %d\n",chan); | ||
516 | if (!chan) return -EAGAIN; | ||
517 | use_pool(vcc->dev,zatm_vcc->pool); | ||
518 | DPRINTK("pool %d\n",zatm_vcc->pool); | ||
519 | /* set up VC descriptor */ | ||
520 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
521 | zpokel(zatm_dev,zatm_vcc->pool << uPD98401_RXVC_POOL_SHIFT, | ||
522 | chan*VC_SIZE/4); | ||
523 | zpokel(zatm_dev,uPD98401_RXVC_OD | (vcc->qos.aal == ATM_AAL5 ? | ||
524 | uPD98401_RXVC_AR : 0) | cells,chan*VC_SIZE/4+1); | ||
525 | zpokel(zatm_dev,0,chan*VC_SIZE/4+2); | ||
526 | zatm_vcc->rx_chan = chan; | ||
527 | zatm_dev->rx_map[chan] = vcc; | ||
528 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | |||
533 | static int open_rx_second(struct atm_vcc *vcc) | ||
534 | { | ||
535 | struct zatm_dev *zatm_dev; | ||
536 | struct zatm_vcc *zatm_vcc; | ||
537 | unsigned long flags; | ||
538 | int pos,shift; | ||
539 | |||
540 | DPRINTK("open_rx_second (0x%x)\n",inb_p(0xc053)); | ||
541 | zatm_dev = ZATM_DEV(vcc->dev); | ||
542 | zatm_vcc = ZATM_VCC(vcc); | ||
543 | if (!zatm_vcc->rx_chan) return 0; | ||
544 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
545 | /* should also handle VPI @@@ */ | ||
546 | pos = vcc->vci >> 1; | ||
547 | shift = (1-(vcc->vci & 1)) << 4; | ||
548 | zpokel(zatm_dev,(zpeekl(zatm_dev,pos) & ~(0xffff << shift)) | | ||
549 | ((zatm_vcc->rx_chan | uPD98401_RXLT_ENBL) << shift),pos); | ||
550 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | |||
555 | static void close_rx(struct atm_vcc *vcc) | ||
556 | { | ||
557 | struct zatm_dev *zatm_dev; | ||
558 | struct zatm_vcc *zatm_vcc; | ||
559 | unsigned long flags; | ||
560 | int pos,shift; | ||
561 | |||
562 | zatm_vcc = ZATM_VCC(vcc); | ||
563 | zatm_dev = ZATM_DEV(vcc->dev); | ||
564 | if (!zatm_vcc->rx_chan) return; | ||
565 | DPRINTK("close_rx\n"); | ||
566 | /* disable receiver */ | ||
567 | if (vcc->vpi != ATM_VPI_UNSPEC && vcc->vci != ATM_VCI_UNSPEC) { | ||
568 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
569 | pos = vcc->vci >> 1; | ||
570 | shift = (1-(vcc->vci & 1)) << 4; | ||
571 | zpokel(zatm_dev,zpeekl(zatm_dev,pos) & ~(0xffff << shift),pos); | ||
572 | zwait; | ||
573 | zout(uPD98401_NOP,CMR); | ||
574 | zwait; | ||
575 | zout(uPD98401_NOP,CMR); | ||
576 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
577 | } | ||
578 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
579 | zwait; | ||
580 | zout(uPD98401_DEACT_CHAN | uPD98401_CHAN_RT | (zatm_vcc->rx_chan << | ||
581 | uPD98401_CHAN_ADDR_SHIFT),CMR); | ||
582 | zwait; | ||
583 | udelay(10); /* why oh why ... ? */ | ||
584 | zout(uPD98401_CLOSE_CHAN | uPD98401_CHAN_RT | (zatm_vcc->rx_chan << | ||
585 | uPD98401_CHAN_ADDR_SHIFT),CMR); | ||
586 | zwait; | ||
587 | if (!(zin(CMR) & uPD98401_CHAN_ADDR)) | ||
588 | printk(KERN_CRIT DEV_LABEL "(itf %d): can't close RX channel " | ||
589 | "%d\n",vcc->dev->number,zatm_vcc->rx_chan); | ||
590 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
591 | zatm_dev->rx_map[zatm_vcc->rx_chan] = NULL; | ||
592 | zatm_vcc->rx_chan = 0; | ||
593 | unuse_pool(vcc->dev,zatm_vcc->pool); | ||
594 | } | ||
595 | |||
596 | |||
597 | static int start_rx(struct atm_dev *dev) | ||
598 | { | ||
599 | struct zatm_dev *zatm_dev; | ||
600 | int size,i; | ||
601 | |||
602 | DPRINTK("start_rx\n"); | ||
603 | zatm_dev = ZATM_DEV(dev); | ||
604 | size = sizeof(struct atm_vcc *)*zatm_dev->chans; | ||
605 | zatm_dev->rx_map = (struct atm_vcc **) kmalloc(size,GFP_KERNEL); | ||
606 | if (!zatm_dev->rx_map) return -ENOMEM; | ||
607 | memset(zatm_dev->rx_map,0,size); | ||
608 | /* set VPI/VCI split (use all VCIs and give what's left to VPIs) */ | ||
609 | zpokel(zatm_dev,(1 << dev->ci_range.vci_bits)-1,uPD98401_VRR); | ||
610 | /* prepare free buffer pools */ | ||
611 | for (i = 0; i <= ZATM_LAST_POOL; i++) { | ||
612 | zatm_dev->pool_info[i].ref_count = 0; | ||
613 | zatm_dev->pool_info[i].rqa_count = 0; | ||
614 | zatm_dev->pool_info[i].rqu_count = 0; | ||
615 | zatm_dev->pool_info[i].low_water = LOW_MARK; | ||
616 | zatm_dev->pool_info[i].high_water = HIGH_MARK; | ||
617 | zatm_dev->pool_info[i].offset = 0; | ||
618 | zatm_dev->pool_info[i].next_off = 0; | ||
619 | zatm_dev->pool_info[i].next_cnt = 0; | ||
620 | zatm_dev->pool_info[i].next_thres = OFF_CNG_THRES; | ||
621 | } | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | |||
626 | /*----------------------------------- TX ------------------------------------*/ | ||
627 | |||
628 | |||
629 | static int do_tx(struct sk_buff *skb) | ||
630 | { | ||
631 | struct atm_vcc *vcc; | ||
632 | struct zatm_dev *zatm_dev; | ||
633 | struct zatm_vcc *zatm_vcc; | ||
634 | u32 *dsc; | ||
635 | unsigned long flags; | ||
636 | |||
637 | EVENT("do_tx\n",0,0); | ||
638 | DPRINTK("sending skb %p\n",skb); | ||
639 | vcc = ATM_SKB(skb)->vcc; | ||
640 | zatm_dev = ZATM_DEV(vcc->dev); | ||
641 | zatm_vcc = ZATM_VCC(vcc); | ||
642 | EVENT("iovcnt=%d\n",skb_shinfo(skb)->nr_frags,0); | ||
643 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
644 | if (!skb_shinfo(skb)->nr_frags) { | ||
645 | if (zatm_vcc->txing == RING_ENTRIES-1) { | ||
646 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
647 | return RING_BUSY; | ||
648 | } | ||
649 | zatm_vcc->txing++; | ||
650 | dsc = zatm_vcc->ring+zatm_vcc->ring_curr; | ||
651 | zatm_vcc->ring_curr = (zatm_vcc->ring_curr+RING_WORDS) & | ||
652 | (RING_ENTRIES*RING_WORDS-1); | ||
653 | dsc[1] = 0; | ||
654 | dsc[2] = skb->len; | ||
655 | dsc[3] = virt_to_bus(skb->data); | ||
656 | mb(); | ||
657 | dsc[0] = uPD98401_TXPD_V | uPD98401_TXPD_DP | uPD98401_TXPD_SM | ||
658 | | (vcc->qos.aal == ATM_AAL5 ? uPD98401_TXPD_AAL5 : 0 | | ||
659 | (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? | ||
660 | uPD98401_CLPM_1 : uPD98401_CLPM_0)); | ||
661 | EVENT("dsc (0x%lx)\n",(unsigned long) dsc,0); | ||
662 | } | ||
663 | else { | ||
664 | printk("NONONONOO!!!!\n"); | ||
665 | dsc = NULL; | ||
666 | #if 0 | ||
667 | u32 *put; | ||
668 | int i; | ||
669 | |||
670 | dsc = (u32 *) kmalloc(uPD98401_TXPD_SIZE*2+ | ||
671 | uPD98401_TXBD_SIZE*ATM_SKB(skb)->iovcnt,GFP_ATOMIC); | ||
672 | if (!dsc) { | ||
673 | if (vcc->pop) vcc->pop(vcc,skb); | ||
674 | else dev_kfree_skb_irq(skb); | ||
675 | return -EAGAIN; | ||
676 | } | ||
677 | /* @@@ should check alignment */ | ||
678 | put = dsc+8; | ||
679 | dsc[0] = uPD98401_TXPD_V | uPD98401_TXPD_DP | | ||
680 | (vcc->aal == ATM_AAL5 ? uPD98401_TXPD_AAL5 : 0 | | ||
681 | (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? | ||
682 | uPD98401_CLPM_1 : uPD98401_CLPM_0)); | ||
683 | dsc[1] = 0; | ||
684 | dsc[2] = ATM_SKB(skb)->iovcnt*uPD98401_TXBD_SIZE; | ||
685 | dsc[3] = virt_to_bus(put); | ||
686 | for (i = 0; i < ATM_SKB(skb)->iovcnt; i++) { | ||
687 | *put++ = ((struct iovec *) skb->data)[i].iov_len; | ||
688 | *put++ = virt_to_bus(((struct iovec *) | ||
689 | skb->data)[i].iov_base); | ||
690 | } | ||
691 | put[-2] |= uPD98401_TXBD_LAST; | ||
692 | #endif | ||
693 | } | ||
694 | ZATM_PRV_DSC(skb) = dsc; | ||
695 | skb_queue_tail(&zatm_vcc->tx_queue,skb); | ||
696 | DPRINTK("QRP=0x%08lx\n",zpeekl(zatm_dev,zatm_vcc->tx_chan*VC_SIZE/4+ | ||
697 | uPD98401_TXVC_QRP)); | ||
698 | zwait; | ||
699 | zout(uPD98401_TX_READY | (zatm_vcc->tx_chan << | ||
700 | uPD98401_CHAN_ADDR_SHIFT),CMR); | ||
701 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
702 | EVENT("done\n",0,0); | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | |||
707 | static inline void dequeue_tx(struct atm_vcc *vcc) | ||
708 | { | ||
709 | struct zatm_vcc *zatm_vcc; | ||
710 | struct sk_buff *skb; | ||
711 | |||
712 | EVENT("dequeue_tx\n",0,0); | ||
713 | zatm_vcc = ZATM_VCC(vcc); | ||
714 | skb = skb_dequeue(&zatm_vcc->tx_queue); | ||
715 | if (!skb) { | ||
716 | printk(KERN_CRIT DEV_LABEL "(itf %d): dequeue_tx but not " | ||
717 | "txing\n",vcc->dev->number); | ||
718 | return; | ||
719 | } | ||
720 | #if 0 /* @@@ would fail on CLP */ | ||
721 | if (*ZATM_PRV_DSC(skb) != (uPD98401_TXPD_V | uPD98401_TXPD_DP | | ||
722 | uPD98401_TXPD_SM | uPD98401_TXPD_AAL5)) printk("@#*$!!!! (%08x)\n", | ||
723 | *ZATM_PRV_DSC(skb)); | ||
724 | #endif | ||
725 | *ZATM_PRV_DSC(skb) = 0; /* mark as invalid */ | ||
726 | zatm_vcc->txing--; | ||
727 | if (vcc->pop) vcc->pop(vcc,skb); | ||
728 | else dev_kfree_skb_irq(skb); | ||
729 | while ((skb = skb_dequeue(&zatm_vcc->backlog))) | ||
730 | if (do_tx(skb) == RING_BUSY) { | ||
731 | skb_queue_head(&zatm_vcc->backlog,skb); | ||
732 | break; | ||
733 | } | ||
734 | atomic_inc(&vcc->stats->tx); | ||
735 | wake_up(&zatm_vcc->tx_wait); | ||
736 | } | ||
737 | |||
738 | |||
739 | static void poll_tx(struct atm_dev *dev,int mbx) | ||
740 | { | ||
741 | struct zatm_dev *zatm_dev; | ||
742 | unsigned long pos; | ||
743 | u32 x; | ||
744 | |||
745 | EVENT("poll_tx\n",0,0); | ||
746 | zatm_dev = ZATM_DEV(dev); | ||
747 | pos = (zatm_dev->mbx_start[mbx] & ~0xffffUL) | zin(MTA(mbx)); | ||
748 | while (x = zin(MWA(mbx)), (pos & 0xffff) != x) { | ||
749 | int chan; | ||
750 | |||
751 | #if 1 | ||
752 | u32 data,*addr; | ||
753 | |||
754 | EVENT("MBX: host 0x%lx, nic 0x%x\n",pos,x); | ||
755 | addr = (u32 *) pos; | ||
756 | data = *addr; | ||
757 | chan = (data & uPD98401_TXI_CONN) >> uPD98401_TXI_CONN_SHIFT; | ||
758 | EVENT("addr = 0x%lx, data = 0x%08x,",(unsigned long) addr, | ||
759 | data); | ||
760 | EVENT("chan = %d\n",chan,0); | ||
761 | #else | ||
762 | NO ! | ||
763 | chan = (zatm_dev->mbx_start[mbx][pos >> 2] & uPD98401_TXI_CONN) | ||
764 | >> uPD98401_TXI_CONN_SHIFT; | ||
765 | #endif | ||
766 | if (chan < zatm_dev->chans && zatm_dev->tx_map[chan]) | ||
767 | dequeue_tx(zatm_dev->tx_map[chan]); | ||
768 | else { | ||
769 | printk(KERN_CRIT DEV_LABEL "(itf %d): TX indication " | ||
770 | "for non-existing channel %d\n",dev->number,chan); | ||
771 | event_dump(); | ||
772 | } | ||
773 | if (((pos += 4) & 0xffff) == zatm_dev->mbx_end[mbx]) | ||
774 | pos = zatm_dev->mbx_start[mbx]; | ||
775 | } | ||
776 | zout(pos & 0xffff,MTA(mbx)); | ||
777 | } | ||
778 | |||
779 | |||
780 | /* | ||
781 | * BUG BUG BUG: Doesn't handle "new-style" rate specification yet. | ||
782 | */ | ||
783 | |||
784 | static int alloc_shaper(struct atm_dev *dev,int *pcr,int min,int max,int ubr) | ||
785 | { | ||
786 | struct zatm_dev *zatm_dev; | ||
787 | unsigned long flags; | ||
788 | unsigned long i,m,c; | ||
789 | int shaper; | ||
790 | |||
791 | DPRINTK("alloc_shaper (min = %d, max = %d)\n",min,max); | ||
792 | zatm_dev = ZATM_DEV(dev); | ||
793 | if (!zatm_dev->free_shapers) return -EAGAIN; | ||
794 | for (shaper = 0; !((zatm_dev->free_shapers >> shaper) & 1); shaper++); | ||
795 | zatm_dev->free_shapers &= ~1 << shaper; | ||
796 | if (ubr) { | ||
797 | c = 5; | ||
798 | i = m = 1; | ||
799 | zatm_dev->ubr_ref_cnt++; | ||
800 | zatm_dev->ubr = shaper; | ||
801 | } | ||
802 | else { | ||
803 | if (min) { | ||
804 | if (min <= 255) { | ||
805 | i = min; | ||
806 | m = ATM_OC3_PCR; | ||
807 | } | ||
808 | else { | ||
809 | i = 255; | ||
810 | m = ATM_OC3_PCR*255/min; | ||
811 | } | ||
812 | } | ||
813 | else { | ||
814 | if (max > zatm_dev->tx_bw) max = zatm_dev->tx_bw; | ||
815 | if (max <= 255) { | ||
816 | i = max; | ||
817 | m = ATM_OC3_PCR; | ||
818 | } | ||
819 | else { | ||
820 | i = 255; | ||
821 | m = (ATM_OC3_PCR*255+max-1)/max; | ||
822 | } | ||
823 | } | ||
824 | if (i > m) { | ||
825 | printk(KERN_CRIT DEV_LABEL "shaper algorithm botched " | ||
826 | "[%d,%d] -> i=%ld,m=%ld\n",min,max,i,m); | ||
827 | m = i; | ||
828 | } | ||
829 | *pcr = i*ATM_OC3_PCR/m; | ||
830 | c = 20; /* @@@ should use max_cdv ! */ | ||
831 | if ((min && *pcr < min) || (max && *pcr > max)) return -EINVAL; | ||
832 | if (zatm_dev->tx_bw < *pcr) return -EAGAIN; | ||
833 | zatm_dev->tx_bw -= *pcr; | ||
834 | } | ||
835 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
836 | DPRINTK("i = %d, m = %d, PCR = %d\n",i,m,*pcr); | ||
837 | zpokel(zatm_dev,(i << uPD98401_IM_I_SHIFT) | m,uPD98401_IM(shaper)); | ||
838 | zpokel(zatm_dev,c << uPD98401_PC_C_SHIFT,uPD98401_PC(shaper)); | ||
839 | zpokel(zatm_dev,0,uPD98401_X(shaper)); | ||
840 | zpokel(zatm_dev,0,uPD98401_Y(shaper)); | ||
841 | zpokel(zatm_dev,uPD98401_PS_E,uPD98401_PS(shaper)); | ||
842 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
843 | return shaper; | ||
844 | } | ||
845 | |||
846 | |||
847 | static void dealloc_shaper(struct atm_dev *dev,int shaper) | ||
848 | { | ||
849 | struct zatm_dev *zatm_dev; | ||
850 | unsigned long flags; | ||
851 | |||
852 | zatm_dev = ZATM_DEV(dev); | ||
853 | if (shaper == zatm_dev->ubr) { | ||
854 | if (--zatm_dev->ubr_ref_cnt) return; | ||
855 | zatm_dev->ubr = -1; | ||
856 | } | ||
857 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
858 | zpokel(zatm_dev,zpeekl(zatm_dev,uPD98401_PS(shaper)) & ~uPD98401_PS_E, | ||
859 | uPD98401_PS(shaper)); | ||
860 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
861 | zatm_dev->free_shapers |= 1 << shaper; | ||
862 | } | ||
863 | |||
864 | |||
865 | static void close_tx(struct atm_vcc *vcc) | ||
866 | { | ||
867 | struct zatm_dev *zatm_dev; | ||
868 | struct zatm_vcc *zatm_vcc; | ||
869 | unsigned long flags; | ||
870 | int chan; | ||
871 | |||
872 | zatm_vcc = ZATM_VCC(vcc); | ||
873 | zatm_dev = ZATM_DEV(vcc->dev); | ||
874 | chan = zatm_vcc->tx_chan; | ||
875 | if (!chan) return; | ||
876 | DPRINTK("close_tx\n"); | ||
877 | if (skb_peek(&zatm_vcc->backlog)) { | ||
878 | printk("waiting for backlog to drain ...\n"); | ||
879 | event_dump(); | ||
880 | wait_event(zatm_vcc->tx_wait, !skb_peek(&zatm_vcc->backlog)); | ||
881 | } | ||
882 | if (skb_peek(&zatm_vcc->tx_queue)) { | ||
883 | printk("waiting for TX queue to drain ...\n"); | ||
884 | event_dump(); | ||
885 | wait_event(zatm_vcc->tx_wait, !skb_peek(&zatm_vcc->tx_queue)); | ||
886 | } | ||
887 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
888 | #if 0 | ||
889 | zwait; | ||
890 | zout(uPD98401_DEACT_CHAN | (chan << uPD98401_CHAN_ADDR_SHIFT),CMR); | ||
891 | #endif | ||
892 | zwait; | ||
893 | zout(uPD98401_CLOSE_CHAN | (chan << uPD98401_CHAN_ADDR_SHIFT),CMR); | ||
894 | zwait; | ||
895 | if (!(zin(CMR) & uPD98401_CHAN_ADDR)) | ||
896 | printk(KERN_CRIT DEV_LABEL "(itf %d): can't close TX channel " | ||
897 | "%d\n",vcc->dev->number,chan); | ||
898 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
899 | zatm_vcc->tx_chan = 0; | ||
900 | zatm_dev->tx_map[chan] = NULL; | ||
901 | if (zatm_vcc->shaper != zatm_dev->ubr) { | ||
902 | zatm_dev->tx_bw += vcc->qos.txtp.min_pcr; | ||
903 | dealloc_shaper(vcc->dev,zatm_vcc->shaper); | ||
904 | } | ||
905 | if (zatm_vcc->ring) kfree(zatm_vcc->ring); | ||
906 | } | ||
907 | |||
908 | |||
909 | static int open_tx_first(struct atm_vcc *vcc) | ||
910 | { | ||
911 | struct zatm_dev *zatm_dev; | ||
912 | struct zatm_vcc *zatm_vcc; | ||
913 | unsigned long flags; | ||
914 | u32 *loop; | ||
915 | unsigned short chan; | ||
916 | int pcr,unlimited; | ||
917 | |||
918 | DPRINTK("open_tx_first\n"); | ||
919 | zatm_dev = ZATM_DEV(vcc->dev); | ||
920 | zatm_vcc = ZATM_VCC(vcc); | ||
921 | zatm_vcc->tx_chan = 0; | ||
922 | if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; | ||
923 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
924 | zwait; | ||
925 | zout(uPD98401_OPEN_CHAN,CMR); | ||
926 | zwait; | ||
927 | DPRINTK("0x%x 0x%x\n",zin(CMR),zin(CER)); | ||
928 | chan = (zin(CMR) & uPD98401_CHAN_ADDR) >> uPD98401_CHAN_ADDR_SHIFT; | ||
929 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
930 | DPRINTK("chan is %d\n",chan); | ||
931 | if (!chan) return -EAGAIN; | ||
932 | unlimited = vcc->qos.txtp.traffic_class == ATM_UBR && | ||
933 | (!vcc->qos.txtp.max_pcr || vcc->qos.txtp.max_pcr == ATM_MAX_PCR || | ||
934 | vcc->qos.txtp.max_pcr >= ATM_OC3_PCR); | ||
935 | if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr; | ||
936 | else { | ||
937 | if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU; | ||
938 | if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr, | ||
939 | vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,unlimited)) | ||
940 | < 0) { | ||
941 | close_tx(vcc); | ||
942 | return zatm_vcc->shaper; | ||
943 | } | ||
944 | if (pcr > ATM_OC3_PCR) pcr = ATM_OC3_PCR; | ||
945 | vcc->qos.txtp.min_pcr = vcc->qos.txtp.max_pcr = pcr; | ||
946 | } | ||
947 | zatm_vcc->tx_chan = chan; | ||
948 | skb_queue_head_init(&zatm_vcc->tx_queue); | ||
949 | init_waitqueue_head(&zatm_vcc->tx_wait); | ||
950 | /* initialize ring */ | ||
951 | zatm_vcc->ring = kmalloc(RING_SIZE,GFP_KERNEL); | ||
952 | if (!zatm_vcc->ring) return -ENOMEM; | ||
953 | memset(zatm_vcc->ring,0,RING_SIZE); | ||
954 | loop = zatm_vcc->ring+RING_ENTRIES*RING_WORDS; | ||
955 | loop[0] = uPD98401_TXPD_V; | ||
956 | loop[1] = loop[2] = 0; | ||
957 | loop[3] = virt_to_bus(zatm_vcc->ring); | ||
958 | zatm_vcc->ring_curr = 0; | ||
959 | zatm_vcc->txing = 0; | ||
960 | skb_queue_head_init(&zatm_vcc->backlog); | ||
961 | zpokel(zatm_dev,virt_to_bus(zatm_vcc->ring), | ||
962 | chan*VC_SIZE/4+uPD98401_TXVC_QRP); | ||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | |||
967 | static int open_tx_second(struct atm_vcc *vcc) | ||
968 | { | ||
969 | struct zatm_dev *zatm_dev; | ||
970 | struct zatm_vcc *zatm_vcc; | ||
971 | unsigned long flags; | ||
972 | |||
973 | DPRINTK("open_tx_second\n"); | ||
974 | zatm_dev = ZATM_DEV(vcc->dev); | ||
975 | zatm_vcc = ZATM_VCC(vcc); | ||
976 | if (!zatm_vcc->tx_chan) return 0; | ||
977 | /* set up VC descriptor */ | ||
978 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
979 | zpokel(zatm_dev,0,zatm_vcc->tx_chan*VC_SIZE/4); | ||
980 | zpokel(zatm_dev,uPD98401_TXVC_L | (zatm_vcc->shaper << | ||
981 | uPD98401_TXVC_SHP_SHIFT) | (vcc->vpi << uPD98401_TXVC_VPI_SHIFT) | | ||
982 | vcc->vci,zatm_vcc->tx_chan*VC_SIZE/4+1); | ||
983 | zpokel(zatm_dev,0,zatm_vcc->tx_chan*VC_SIZE/4+2); | ||
984 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
985 | zatm_dev->tx_map[zatm_vcc->tx_chan] = vcc; | ||
986 | return 0; | ||
987 | } | ||
988 | |||
989 | |||
990 | static int start_tx(struct atm_dev *dev) | ||
991 | { | ||
992 | struct zatm_dev *zatm_dev; | ||
993 | int i; | ||
994 | |||
995 | DPRINTK("start_tx\n"); | ||
996 | zatm_dev = ZATM_DEV(dev); | ||
997 | zatm_dev->tx_map = (struct atm_vcc **) kmalloc(sizeof(struct atm_vcc *)* | ||
998 | zatm_dev->chans,GFP_KERNEL); | ||
999 | if (!zatm_dev->tx_map) return -ENOMEM; | ||
1000 | zatm_dev->tx_bw = ATM_OC3_PCR; | ||
1001 | zatm_dev->free_shapers = (1 << NR_SHAPERS)-1; | ||
1002 | zatm_dev->ubr = -1; | ||
1003 | zatm_dev->ubr_ref_cnt = 0; | ||
1004 | /* initialize shapers */ | ||
1005 | for (i = 0; i < NR_SHAPERS; i++) zpokel(zatm_dev,0,uPD98401_PS(i)); | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /*------------------------------- interrupts --------------------------------*/ | ||
1011 | |||
1012 | |||
1013 | static irqreturn_t zatm_int(int irq,void *dev_id,struct pt_regs *regs) | ||
1014 | { | ||
1015 | struct atm_dev *dev; | ||
1016 | struct zatm_dev *zatm_dev; | ||
1017 | u32 reason; | ||
1018 | int handled = 0; | ||
1019 | |||
1020 | dev = dev_id; | ||
1021 | zatm_dev = ZATM_DEV(dev); | ||
1022 | while ((reason = zin(GSR))) { | ||
1023 | handled = 1; | ||
1024 | EVENT("reason 0x%x\n",reason,0); | ||
1025 | if (reason & uPD98401_INT_PI) { | ||
1026 | EVENT("PHY int\n",0,0); | ||
1027 | dev->phy->interrupt(dev); | ||
1028 | } | ||
1029 | if (reason & uPD98401_INT_RQA) { | ||
1030 | unsigned long pools; | ||
1031 | int i; | ||
1032 | |||
1033 | pools = zin(RQA); | ||
1034 | EVENT("RQA (0x%08x)\n",pools,0); | ||
1035 | for (i = 0; pools; i++) { | ||
1036 | if (pools & 1) { | ||
1037 | refill_pool(dev,i); | ||
1038 | zatm_dev->pool_info[i].rqa_count++; | ||
1039 | } | ||
1040 | pools >>= 1; | ||
1041 | } | ||
1042 | } | ||
1043 | if (reason & uPD98401_INT_RQU) { | ||
1044 | unsigned long pools; | ||
1045 | int i; | ||
1046 | pools = zin(RQU); | ||
1047 | printk(KERN_WARNING DEV_LABEL "(itf %d): RQU 0x%08lx\n", | ||
1048 | dev->number,pools); | ||
1049 | event_dump(); | ||
1050 | for (i = 0; pools; i++) { | ||
1051 | if (pools & 1) { | ||
1052 | refill_pool(dev,i); | ||
1053 | zatm_dev->pool_info[i].rqu_count++; | ||
1054 | } | ||
1055 | pools >>= 1; | ||
1056 | } | ||
1057 | } | ||
1058 | /* don't handle RD */ | ||
1059 | if (reason & uPD98401_INT_SPE) | ||
1060 | printk(KERN_ALERT DEV_LABEL "(itf %d): system parity " | ||
1061 | "error at 0x%08x\n",dev->number,zin(ADDR)); | ||
1062 | if (reason & uPD98401_INT_CPE) | ||
1063 | printk(KERN_ALERT DEV_LABEL "(itf %d): control memory " | ||
1064 | "parity error at 0x%08x\n",dev->number,zin(ADDR)); | ||
1065 | if (reason & uPD98401_INT_SBE) { | ||
1066 | printk(KERN_ALERT DEV_LABEL "(itf %d): system bus " | ||
1067 | "error at 0x%08x\n",dev->number,zin(ADDR)); | ||
1068 | event_dump(); | ||
1069 | } | ||
1070 | /* don't handle IND */ | ||
1071 | if (reason & uPD98401_INT_MF) { | ||
1072 | printk(KERN_CRIT DEV_LABEL "(itf %d): mailbox full " | ||
1073 | "(0x%x)\n",dev->number,(reason & uPD98401_INT_MF) | ||
1074 | >> uPD98401_INT_MF_SHIFT); | ||
1075 | event_dump(); | ||
1076 | /* @@@ should try to recover */ | ||
1077 | } | ||
1078 | if (reason & uPD98401_INT_MM) { | ||
1079 | if (reason & 1) poll_rx(dev,0); | ||
1080 | if (reason & 2) poll_rx(dev,1); | ||
1081 | if (reason & 4) poll_tx(dev,2); | ||
1082 | if (reason & 8) poll_tx(dev,3); | ||
1083 | } | ||
1084 | /* @@@ handle RCRn */ | ||
1085 | } | ||
1086 | return IRQ_RETVAL(handled); | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | /*----------------------------- (E)EPROM access -----------------------------*/ | ||
1091 | |||
1092 | |||
1093 | static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value, | ||
1094 | unsigned short cmd) | ||
1095 | { | ||
1096 | int error; | ||
1097 | |||
1098 | if ((error = pci_write_config_dword(zatm_dev->pci_dev,cmd,value))) | ||
1099 | printk(KERN_ERR DEV_LABEL ": PCI write failed (0x%02x)\n", | ||
1100 | error); | ||
1101 | } | ||
1102 | |||
1103 | |||
1104 | static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev, | ||
1105 | unsigned short cmd) | ||
1106 | { | ||
1107 | unsigned int value; | ||
1108 | int error; | ||
1109 | |||
1110 | if ((error = pci_read_config_dword(zatm_dev->pci_dev,cmd,&value))) | ||
1111 | printk(KERN_ERR DEV_LABEL ": PCI read failed (0x%02x)\n", | ||
1112 | error); | ||
1113 | return value; | ||
1114 | } | ||
1115 | |||
1116 | |||
1117 | static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev, | ||
1118 | unsigned long data,int bits,unsigned short cmd) | ||
1119 | { | ||
1120 | unsigned long value; | ||
1121 | int i; | ||
1122 | |||
1123 | for (i = bits-1; i >= 0; i--) { | ||
1124 | value = ZEPROM_CS | (((data >> i) & 1) ? ZEPROM_DI : 0); | ||
1125 | eprom_set(zatm_dev,value,cmd); | ||
1126 | eprom_set(zatm_dev,value | ZEPROM_SK,cmd); | ||
1127 | eprom_set(zatm_dev,value,cmd); | ||
1128 | } | ||
1129 | } | ||
1130 | |||
1131 | |||
1132 | static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev, | ||
1133 | unsigned char *byte,unsigned short cmd) | ||
1134 | { | ||
1135 | int i; | ||
1136 | |||
1137 | *byte = 0; | ||
1138 | for (i = 8; i; i--) { | ||
1139 | eprom_set(zatm_dev,ZEPROM_CS,cmd); | ||
1140 | eprom_set(zatm_dev,ZEPROM_CS | ZEPROM_SK,cmd); | ||
1141 | *byte <<= 1; | ||
1142 | if (eprom_get(zatm_dev,cmd) & ZEPROM_DO) *byte |= 1; | ||
1143 | eprom_set(zatm_dev,ZEPROM_CS,cmd); | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | static unsigned char __devinit eprom_try_esi(struct atm_dev *dev, | ||
1149 | unsigned short cmd,int offset,int swap) | ||
1150 | { | ||
1151 | unsigned char buf[ZEPROM_SIZE]; | ||
1152 | struct zatm_dev *zatm_dev; | ||
1153 | int i; | ||
1154 | |||
1155 | zatm_dev = ZATM_DEV(dev); | ||
1156 | for (i = 0; i < ZEPROM_SIZE; i += 2) { | ||
1157 | eprom_set(zatm_dev,ZEPROM_CS,cmd); /* select EPROM */ | ||
1158 | eprom_put_bits(zatm_dev,ZEPROM_CMD_READ,ZEPROM_CMD_LEN,cmd); | ||
1159 | eprom_put_bits(zatm_dev,i >> 1,ZEPROM_ADDR_LEN,cmd); | ||
1160 | eprom_get_byte(zatm_dev,buf+i+swap,cmd); | ||
1161 | eprom_get_byte(zatm_dev,buf+i+1-swap,cmd); | ||
1162 | eprom_set(zatm_dev,0,cmd); /* deselect EPROM */ | ||
1163 | } | ||
1164 | memcpy(dev->esi,buf+offset,ESI_LEN); | ||
1165 | return memcmp(dev->esi,"\0\0\0\0\0",ESI_LEN); /* assumes ESI_LEN == 6 */ | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | static void __devinit eprom_get_esi(struct atm_dev *dev) | ||
1170 | { | ||
1171 | if (eprom_try_esi(dev,ZEPROM_V1_REG,ZEPROM_V1_ESI_OFF,1)) return; | ||
1172 | (void) eprom_try_esi(dev,ZEPROM_V2_REG,ZEPROM_V2_ESI_OFF,0); | ||
1173 | } | ||
1174 | |||
1175 | |||
1176 | /*--------------------------------- entries ---------------------------------*/ | ||
1177 | |||
1178 | |||
1179 | static int __init zatm_init(struct atm_dev *dev) | ||
1180 | { | ||
1181 | struct zatm_dev *zatm_dev; | ||
1182 | struct pci_dev *pci_dev; | ||
1183 | unsigned short command; | ||
1184 | unsigned char revision; | ||
1185 | int error,i,last; | ||
1186 | unsigned long t0,t1,t2; | ||
1187 | |||
1188 | DPRINTK(">zatm_init\n"); | ||
1189 | zatm_dev = ZATM_DEV(dev); | ||
1190 | spin_lock_init(&zatm_dev->lock); | ||
1191 | pci_dev = zatm_dev->pci_dev; | ||
1192 | zatm_dev->base = pci_resource_start(pci_dev, 0); | ||
1193 | zatm_dev->irq = pci_dev->irq; | ||
1194 | if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) || | ||
1195 | (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) { | ||
1196 | printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n", | ||
1197 | dev->number,error); | ||
1198 | return -EINVAL; | ||
1199 | } | ||
1200 | if ((error = pci_write_config_word(pci_dev,PCI_COMMAND, | ||
1201 | command | PCI_COMMAND_IO | PCI_COMMAND_MASTER))) { | ||
1202 | printk(KERN_ERR DEV_LABEL "(itf %d): can't enable IO (0x%02x)" | ||
1203 | "\n",dev->number,error); | ||
1204 | return -EIO; | ||
1205 | } | ||
1206 | eprom_get_esi(dev); | ||
1207 | printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,", | ||
1208 | dev->number,revision,zatm_dev->base,zatm_dev->irq); | ||
1209 | /* reset uPD98401 */ | ||
1210 | zout(0,SWR); | ||
1211 | while (!(zin(GSR) & uPD98401_INT_IND)); | ||
1212 | zout(uPD98401_GMR_ONE /*uPD98401_BURST4*/,GMR); | ||
1213 | last = MAX_CRAM_SIZE; | ||
1214 | for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) { | ||
1215 | zpokel(zatm_dev,0x55555555,i); | ||
1216 | if (zpeekl(zatm_dev,i) != 0x55555555) last = i; | ||
1217 | else { | ||
1218 | zpokel(zatm_dev,0xAAAAAAAA,i); | ||
1219 | if (zpeekl(zatm_dev,i) != 0xAAAAAAAA) last = i; | ||
1220 | else zpokel(zatm_dev,i,i); | ||
1221 | } | ||
1222 | } | ||
1223 | for (i = 0; i < last; i += RAM_INCREMENT) | ||
1224 | if (zpeekl(zatm_dev,i) != i) break; | ||
1225 | zatm_dev->mem = i << 2; | ||
1226 | while (i) zpokel(zatm_dev,0,--i); | ||
1227 | /* reset again to rebuild memory pointers */ | ||
1228 | zout(0,SWR); | ||
1229 | while (!(zin(GSR) & uPD98401_INT_IND)); | ||
1230 | zout(uPD98401_GMR_ONE | uPD98401_BURST8 | uPD98401_BURST4 | | ||
1231 | uPD98401_BURST2 | uPD98401_GMR_PM | uPD98401_GMR_DR,GMR); | ||
1232 | /* TODO: should shrink allocation now */ | ||
1233 | printk("mem=%dkB,%s (",zatm_dev->mem >> 10,zatm_dev->copper ? "UTP" : | ||
1234 | "MMF"); | ||
1235 | for (i = 0; i < ESI_LEN; i++) | ||
1236 | printk("%02X%s",dev->esi[i],i == ESI_LEN-1 ? ")\n" : "-"); | ||
1237 | do { | ||
1238 | unsigned long flags; | ||
1239 | |||
1240 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
1241 | t0 = zpeekl(zatm_dev,uPD98401_TSR); | ||
1242 | udelay(10); | ||
1243 | t1 = zpeekl(zatm_dev,uPD98401_TSR); | ||
1244 | udelay(1010); | ||
1245 | t2 = zpeekl(zatm_dev,uPD98401_TSR); | ||
1246 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
1247 | } | ||
1248 | while (t0 > t1 || t1 > t2); /* loop if wrapping ... */ | ||
1249 | zatm_dev->khz = t2-2*t1+t0; | ||
1250 | printk(KERN_NOTICE DEV_LABEL "(itf %d): uPD98401 %d.%d at %d.%03d " | ||
1251 | "MHz\n",dev->number, | ||
1252 | (zin(VER) & uPD98401_MAJOR) >> uPD98401_MAJOR_SHIFT, | ||
1253 | zin(VER) & uPD98401_MINOR,zatm_dev->khz/1000,zatm_dev->khz % 1000); | ||
1254 | return uPD98402_init(dev); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | static int __init zatm_start(struct atm_dev *dev) | ||
1259 | { | ||
1260 | struct zatm_dev *zatm_dev; | ||
1261 | unsigned long curr; | ||
1262 | int pools,vccs,rx; | ||
1263 | int error,i,ld; | ||
1264 | |||
1265 | DPRINTK("zatm_start\n"); | ||
1266 | zatm_dev = ZATM_DEV(dev); | ||
1267 | zatm_dev->rx_map = zatm_dev->tx_map = NULL; | ||
1268 | for (i = 0; i < NR_MBX; i++) | ||
1269 | zatm_dev->mbx_start[i] = 0; | ||
1270 | if (request_irq(zatm_dev->irq,&zatm_int,SA_SHIRQ,DEV_LABEL,dev)) { | ||
1271 | printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", | ||
1272 | dev->number,zatm_dev->irq); | ||
1273 | return -EAGAIN; | ||
1274 | } | ||
1275 | request_region(zatm_dev->base,uPD98401_PORTS,DEV_LABEL); | ||
1276 | /* define memory regions */ | ||
1277 | pools = NR_POOLS; | ||
1278 | if (NR_SHAPERS*SHAPER_SIZE > pools*POOL_SIZE) | ||
1279 | pools = NR_SHAPERS*SHAPER_SIZE/POOL_SIZE; | ||
1280 | vccs = (zatm_dev->mem-NR_SHAPERS*SHAPER_SIZE-pools*POOL_SIZE)/ | ||
1281 | (2*VC_SIZE+RX_SIZE); | ||
1282 | ld = -1; | ||
1283 | for (rx = 1; rx < vccs; rx <<= 1) ld++; | ||
1284 | dev->ci_range.vpi_bits = 0; /* @@@ no VPI for now */ | ||
1285 | dev->ci_range.vci_bits = ld; | ||
1286 | dev->link_rate = ATM_OC3_PCR; | ||
1287 | zatm_dev->chans = vccs; /* ??? */ | ||
1288 | curr = rx*RX_SIZE/4; | ||
1289 | DPRINTK("RX pool 0x%08lx\n",curr); | ||
1290 | zpokel(zatm_dev,curr,uPD98401_PMA); /* receive pool */ | ||
1291 | zatm_dev->pool_base = curr; | ||
1292 | curr += pools*POOL_SIZE/4; | ||
1293 | DPRINTK("Shapers 0x%08lx\n",curr); | ||
1294 | zpokel(zatm_dev,curr,uPD98401_SMA); /* shapers */ | ||
1295 | curr += NR_SHAPERS*SHAPER_SIZE/4; | ||
1296 | DPRINTK("Free 0x%08lx\n",curr); | ||
1297 | zpokel(zatm_dev,curr,uPD98401_TOS); /* free pool */ | ||
1298 | printk(KERN_INFO DEV_LABEL "(itf %d): %d shapers, %d pools, %d RX, " | ||
1299 | "%ld VCs\n",dev->number,NR_SHAPERS,pools,rx, | ||
1300 | (zatm_dev->mem-curr*4)/VC_SIZE); | ||
1301 | /* create mailboxes */ | ||
1302 | for (i = 0; i < NR_MBX; i++) | ||
1303 | if (mbx_entries[i]) { | ||
1304 | unsigned long here; | ||
1305 | |||
1306 | here = (unsigned long) kmalloc(2*MBX_SIZE(i), | ||
1307 | GFP_KERNEL); | ||
1308 | if (!here) { | ||
1309 | error = -ENOMEM; | ||
1310 | goto out; | ||
1311 | } | ||
1312 | if ((here^(here+MBX_SIZE(i))) & ~0xffffUL)/* paranoia */ | ||
1313 | here = (here & ~0xffffUL)+0x10000; | ||
1314 | zatm_dev->mbx_start[i] = here; | ||
1315 | if ((here^virt_to_bus((void *) here)) & 0xffff) { | ||
1316 | printk(KERN_ERR DEV_LABEL "(itf %d): system " | ||
1317 | "bus incompatible with driver\n", | ||
1318 | dev->number); | ||
1319 | error = -ENODEV; | ||
1320 | goto out; | ||
1321 | } | ||
1322 | DPRINTK("mbx@0x%08lx-0x%08lx\n",here,here+MBX_SIZE(i)); | ||
1323 | zatm_dev->mbx_end[i] = (here+MBX_SIZE(i)) & 0xffff; | ||
1324 | zout(virt_to_bus((void *) here) >> 16,MSH(i)); | ||
1325 | zout(virt_to_bus((void *) here),MSL(i)); | ||
1326 | zout((here+MBX_SIZE(i)) & 0xffff,MBA(i)); | ||
1327 | zout(here & 0xffff,MTA(i)); | ||
1328 | zout(here & 0xffff,MWA(i)); | ||
1329 | } | ||
1330 | error = start_tx(dev); | ||
1331 | if (error) goto out; | ||
1332 | error = start_rx(dev); | ||
1333 | if (error) goto out; | ||
1334 | error = dev->phy->start(dev); | ||
1335 | if (error) goto out; | ||
1336 | zout(0xffffffff,IMR); /* enable interrupts */ | ||
1337 | /* enable TX & RX */ | ||
1338 | zout(zin(GMR) | uPD98401_GMR_SE | uPD98401_GMR_RE,GMR); | ||
1339 | return 0; | ||
1340 | out: | ||
1341 | for (i = 0; i < NR_MBX; i++) | ||
1342 | if (zatm_dev->mbx_start[i] != 0) | ||
1343 | kfree((void *) zatm_dev->mbx_start[i]); | ||
1344 | if (zatm_dev->rx_map != NULL) | ||
1345 | kfree(zatm_dev->rx_map); | ||
1346 | if (zatm_dev->tx_map != NULL) | ||
1347 | kfree(zatm_dev->tx_map); | ||
1348 | free_irq(zatm_dev->irq, dev); | ||
1349 | return error; | ||
1350 | } | ||
1351 | |||
1352 | |||
1353 | static void zatm_close(struct atm_vcc *vcc) | ||
1354 | { | ||
1355 | DPRINTK(">zatm_close\n"); | ||
1356 | if (!ZATM_VCC(vcc)) return; | ||
1357 | clear_bit(ATM_VF_READY,&vcc->flags); | ||
1358 | close_rx(vcc); | ||
1359 | EVENT("close_tx\n",0,0); | ||
1360 | close_tx(vcc); | ||
1361 | DPRINTK("zatm_close: done waiting\n"); | ||
1362 | /* deallocate memory */ | ||
1363 | kfree(ZATM_VCC(vcc)); | ||
1364 | vcc->dev_data = NULL; | ||
1365 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1366 | } | ||
1367 | |||
1368 | |||
1369 | static int zatm_open(struct atm_vcc *vcc) | ||
1370 | { | ||
1371 | struct zatm_dev *zatm_dev; | ||
1372 | struct zatm_vcc *zatm_vcc; | ||
1373 | short vpi = vcc->vpi; | ||
1374 | int vci = vcc->vci; | ||
1375 | int error; | ||
1376 | |||
1377 | DPRINTK(">zatm_open\n"); | ||
1378 | zatm_dev = ZATM_DEV(vcc->dev); | ||
1379 | if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) | ||
1380 | vcc->dev_data = NULL; | ||
1381 | if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) | ||
1382 | set_bit(ATM_VF_ADDR,&vcc->flags); | ||
1383 | if (vcc->qos.aal != ATM_AAL5) return -EINVAL; /* @@@ AAL0 */ | ||
1384 | DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi, | ||
1385 | vcc->vci); | ||
1386 | if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { | ||
1387 | zatm_vcc = kmalloc(sizeof(struct zatm_vcc),GFP_KERNEL); | ||
1388 | if (!zatm_vcc) { | ||
1389 | clear_bit(ATM_VF_ADDR,&vcc->flags); | ||
1390 | return -ENOMEM; | ||
1391 | } | ||
1392 | vcc->dev_data = zatm_vcc; | ||
1393 | ZATM_VCC(vcc)->tx_chan = 0; /* for zatm_close after open_rx */ | ||
1394 | if ((error = open_rx_first(vcc))) { | ||
1395 | zatm_close(vcc); | ||
1396 | return error; | ||
1397 | } | ||
1398 | if ((error = open_tx_first(vcc))) { | ||
1399 | zatm_close(vcc); | ||
1400 | return error; | ||
1401 | } | ||
1402 | } | ||
1403 | if (vci == ATM_VPI_UNSPEC || vpi == ATM_VCI_UNSPEC) return 0; | ||
1404 | if ((error = open_rx_second(vcc))) { | ||
1405 | zatm_close(vcc); | ||
1406 | return error; | ||
1407 | } | ||
1408 | if ((error = open_tx_second(vcc))) { | ||
1409 | zatm_close(vcc); | ||
1410 | return error; | ||
1411 | } | ||
1412 | set_bit(ATM_VF_READY,&vcc->flags); | ||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1416 | |||
1417 | static int zatm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flags) | ||
1418 | { | ||
1419 | printk("Not yet implemented\n"); | ||
1420 | return -ENOSYS; | ||
1421 | /* @@@ */ | ||
1422 | } | ||
1423 | |||
1424 | |||
1425 | static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) | ||
1426 | { | ||
1427 | struct zatm_dev *zatm_dev; | ||
1428 | unsigned long flags; | ||
1429 | |||
1430 | zatm_dev = ZATM_DEV(dev); | ||
1431 | switch (cmd) { | ||
1432 | case ZATM_GETPOOLZ: | ||
1433 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
1434 | /* fall through */ | ||
1435 | case ZATM_GETPOOL: | ||
1436 | { | ||
1437 | struct zatm_pool_info info; | ||
1438 | int pool; | ||
1439 | |||
1440 | if (get_user(pool, | ||
1441 | &((struct zatm_pool_req __user *) arg)->pool_num)) | ||
1442 | return -EFAULT; | ||
1443 | if (pool < 0 || pool > ZATM_LAST_POOL) | ||
1444 | return -EINVAL; | ||
1445 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
1446 | info = zatm_dev->pool_info[pool]; | ||
1447 | if (cmd == ZATM_GETPOOLZ) { | ||
1448 | zatm_dev->pool_info[pool].rqa_count = 0; | ||
1449 | zatm_dev->pool_info[pool].rqu_count = 0; | ||
1450 | } | ||
1451 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
1452 | return copy_to_user( | ||
1453 | &((struct zatm_pool_req __user *) arg)->info, | ||
1454 | &info,sizeof(info)) ? -EFAULT : 0; | ||
1455 | } | ||
1456 | case ZATM_SETPOOL: | ||
1457 | { | ||
1458 | struct zatm_pool_info info; | ||
1459 | int pool; | ||
1460 | |||
1461 | if (!capable(CAP_NET_ADMIN)) return -EPERM; | ||
1462 | if (get_user(pool, | ||
1463 | &((struct zatm_pool_req __user *) arg)->pool_num)) | ||
1464 | return -EFAULT; | ||
1465 | if (pool < 0 || pool > ZATM_LAST_POOL) | ||
1466 | return -EINVAL; | ||
1467 | if (copy_from_user(&info, | ||
1468 | &((struct zatm_pool_req __user *) arg)->info, | ||
1469 | sizeof(info))) return -EFAULT; | ||
1470 | if (!info.low_water) | ||
1471 | info.low_water = zatm_dev-> | ||
1472 | pool_info[pool].low_water; | ||
1473 | if (!info.high_water) | ||
1474 | info.high_water = zatm_dev-> | ||
1475 | pool_info[pool].high_water; | ||
1476 | if (!info.next_thres) | ||
1477 | info.next_thres = zatm_dev-> | ||
1478 | pool_info[pool].next_thres; | ||
1479 | if (info.low_water >= info.high_water || | ||
1480 | info.low_water < 0) | ||
1481 | return -EINVAL; | ||
1482 | spin_lock_irqsave(&zatm_dev->lock, flags); | ||
1483 | zatm_dev->pool_info[pool].low_water = | ||
1484 | info.low_water; | ||
1485 | zatm_dev->pool_info[pool].high_water = | ||
1486 | info.high_water; | ||
1487 | zatm_dev->pool_info[pool].next_thres = | ||
1488 | info.next_thres; | ||
1489 | spin_unlock_irqrestore(&zatm_dev->lock, flags); | ||
1490 | return 0; | ||
1491 | } | ||
1492 | default: | ||
1493 | if (!dev->phy->ioctl) return -ENOIOCTLCMD; | ||
1494 | return dev->phy->ioctl(dev,cmd,arg); | ||
1495 | } | ||
1496 | } | ||
1497 | |||
1498 | |||
1499 | static int zatm_getsockopt(struct atm_vcc *vcc,int level,int optname, | ||
1500 | void __user *optval,int optlen) | ||
1501 | { | ||
1502 | return -EINVAL; | ||
1503 | } | ||
1504 | |||
1505 | |||
1506 | static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname, | ||
1507 | void __user *optval,int optlen) | ||
1508 | { | ||
1509 | return -EINVAL; | ||
1510 | } | ||
1511 | |||
1512 | static int zatm_send(struct atm_vcc *vcc,struct sk_buff *skb) | ||
1513 | { | ||
1514 | int error; | ||
1515 | |||
1516 | EVENT(">zatm_send 0x%lx\n",(unsigned long) skb,0); | ||
1517 | if (!ZATM_VCC(vcc)->tx_chan || !test_bit(ATM_VF_READY,&vcc->flags)) { | ||
1518 | if (vcc->pop) vcc->pop(vcc,skb); | ||
1519 | else dev_kfree_skb(skb); | ||
1520 | return -EINVAL; | ||
1521 | } | ||
1522 | if (!skb) { | ||
1523 | printk(KERN_CRIT "!skb in zatm_send ?\n"); | ||
1524 | if (vcc->pop) vcc->pop(vcc,skb); | ||
1525 | return -EINVAL; | ||
1526 | } | ||
1527 | ATM_SKB(skb)->vcc = vcc; | ||
1528 | error = do_tx(skb); | ||
1529 | if (error != RING_BUSY) return error; | ||
1530 | skb_queue_tail(&ZATM_VCC(vcc)->backlog,skb); | ||
1531 | return 0; | ||
1532 | } | ||
1533 | |||
1534 | |||
1535 | static void zatm_phy_put(struct atm_dev *dev,unsigned char value, | ||
1536 | unsigned long addr) | ||
1537 | { | ||
1538 | struct zatm_dev *zatm_dev; | ||
1539 | |||
1540 | zatm_dev = ZATM_DEV(dev); | ||
1541 | zwait; | ||
1542 | zout(value,CER); | ||
1543 | zout(uPD98401_IND_ACC | uPD98401_IA_B0 | | ||
1544 | (uPD98401_IA_TGT_PHY << uPD98401_IA_TGT_SHIFT) | addr,CMR); | ||
1545 | } | ||
1546 | |||
1547 | |||
1548 | static unsigned char zatm_phy_get(struct atm_dev *dev,unsigned long addr) | ||
1549 | { | ||
1550 | struct zatm_dev *zatm_dev; | ||
1551 | |||
1552 | zatm_dev = ZATM_DEV(dev); | ||
1553 | zwait; | ||
1554 | zout(uPD98401_IND_ACC | uPD98401_IA_B0 | uPD98401_IA_RW | | ||
1555 | (uPD98401_IA_TGT_PHY << uPD98401_IA_TGT_SHIFT) | addr,CMR); | ||
1556 | zwait; | ||
1557 | return zin(CER) & 0xff; | ||
1558 | } | ||
1559 | |||
1560 | |||
1561 | static const struct atmdev_ops ops = { | ||
1562 | .open = zatm_open, | ||
1563 | .close = zatm_close, | ||
1564 | .ioctl = zatm_ioctl, | ||
1565 | .getsockopt = zatm_getsockopt, | ||
1566 | .setsockopt = zatm_setsockopt, | ||
1567 | .send = zatm_send, | ||
1568 | .phy_put = zatm_phy_put, | ||
1569 | .phy_get = zatm_phy_get, | ||
1570 | .change_qos = zatm_change_qos, | ||
1571 | }; | ||
1572 | |||
1573 | static int __devinit zatm_init_one(struct pci_dev *pci_dev, | ||
1574 | const struct pci_device_id *ent) | ||
1575 | { | ||
1576 | struct atm_dev *dev; | ||
1577 | struct zatm_dev *zatm_dev; | ||
1578 | int ret = -ENOMEM; | ||
1579 | |||
1580 | zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL); | ||
1581 | if (!zatm_dev) { | ||
1582 | printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL); | ||
1583 | goto out; | ||
1584 | } | ||
1585 | |||
1586 | dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); | ||
1587 | if (!dev) | ||
1588 | goto out_free; | ||
1589 | |||
1590 | ret = pci_enable_device(pci_dev); | ||
1591 | if (ret < 0) | ||
1592 | goto out_deregister; | ||
1593 | |||
1594 | ret = pci_request_regions(pci_dev, DEV_LABEL); | ||
1595 | if (ret < 0) | ||
1596 | goto out_disable; | ||
1597 | |||
1598 | zatm_dev->pci_dev = pci_dev; | ||
1599 | dev->dev_data = zatm_dev; | ||
1600 | zatm_dev->copper = (int)ent->driver_data; | ||
1601 | if ((ret = zatm_init(dev)) || (ret = zatm_start(dev))) | ||
1602 | goto out_release; | ||
1603 | |||
1604 | pci_set_drvdata(pci_dev, dev); | ||
1605 | zatm_dev->more = zatm_boards; | ||
1606 | zatm_boards = dev; | ||
1607 | ret = 0; | ||
1608 | out: | ||
1609 | return ret; | ||
1610 | |||
1611 | out_release: | ||
1612 | pci_release_regions(pci_dev); | ||
1613 | out_disable: | ||
1614 | pci_disable_device(pci_dev); | ||
1615 | out_deregister: | ||
1616 | atm_dev_deregister(dev); | ||
1617 | out_free: | ||
1618 | kfree(zatm_dev); | ||
1619 | goto out; | ||
1620 | } | ||
1621 | |||
1622 | |||
1623 | MODULE_LICENSE("GPL"); | ||
1624 | |||
1625 | static struct pci_device_id zatm_pci_tbl[] __devinitdata = { | ||
1626 | { PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1221, | ||
1627 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, ZATM_COPPER }, | ||
1628 | { PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1225, | ||
1629 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
1630 | { 0, } | ||
1631 | }; | ||
1632 | MODULE_DEVICE_TABLE(pci, zatm_pci_tbl); | ||
1633 | |||
1634 | static struct pci_driver zatm_driver = { | ||
1635 | .name = DEV_LABEL, | ||
1636 | .id_table = zatm_pci_tbl, | ||
1637 | .probe = zatm_init_one, | ||
1638 | }; | ||
1639 | |||
1640 | static int __init zatm_init_module(void) | ||
1641 | { | ||
1642 | return pci_register_driver(&zatm_driver); | ||
1643 | } | ||
1644 | |||
1645 | module_init(zatm_init_module); | ||
1646 | /* module_exit not defined so not unloadable */ | ||
diff --git a/drivers/atm/zatm.h b/drivers/atm/zatm.h new file mode 100644 index 000000000000..34a0480f63d6 --- /dev/null +++ b/drivers/atm/zatm.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */ | ||
2 | |||
3 | /* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVER_ATM_ZATM_H | ||
7 | #define DRIVER_ATM_ZATM_H | ||
8 | |||
9 | #include <linux/config.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/atm.h> | ||
12 | #include <linux/atmdev.h> | ||
13 | #include <linux/sonet.h> | ||
14 | #include <linux/pci.h> | ||
15 | |||
16 | |||
17 | #define DEV_LABEL "zatm" | ||
18 | |||
19 | #define MAX_AAL5_PDU 10240 /* allocate for AAL5 PDUs of this size */ | ||
20 | #define MAX_RX_SIZE_LD 14 /* ceil(log2((MAX_AAL5_PDU+47)/48)) */ | ||
21 | |||
22 | #define LOW_MARK 12 /* start adding new buffers if less than 12 */ | ||
23 | #define HIGH_MARK 30 /* stop adding buffers after reaching 30 */ | ||
24 | #define OFF_CNG_THRES 5 /* threshold for offset changes */ | ||
25 | |||
26 | #define RX_SIZE 2 /* RX lookup entry size (in bytes) */ | ||
27 | #define NR_POOLS 32 /* number of free buffer pointers */ | ||
28 | #define POOL_SIZE 8 /* buffer entry size (in bytes) */ | ||
29 | #define NR_SHAPERS 16 /* number of shapers */ | ||
30 | #define SHAPER_SIZE 4 /* shaper entry size (in bytes) */ | ||
31 | #define VC_SIZE 32 /* VC dsc (TX or RX) size (in bytes) */ | ||
32 | |||
33 | #define RING_ENTRIES 32 /* ring entries (without back pointer) */ | ||
34 | #define RING_WORDS 4 /* ring element size */ | ||
35 | #define RING_SIZE (sizeof(unsigned long)*(RING_ENTRIES+1)*RING_WORDS) | ||
36 | |||
37 | #define NR_MBX 4 /* four mailboxes */ | ||
38 | #define MBX_RX_0 0 /* mailbox indices */ | ||
39 | #define MBX_RX_1 1 | ||
40 | #define MBX_TX_0 2 | ||
41 | #define MBX_TX_1 3 | ||
42 | |||
43 | struct zatm_vcc { | ||
44 | /*-------------------------------- RX part */ | ||
45 | int rx_chan; /* RX channel, 0 if none */ | ||
46 | int pool; /* free buffer pool */ | ||
47 | /*-------------------------------- TX part */ | ||
48 | int tx_chan; /* TX channel, 0 if none */ | ||
49 | int shaper; /* shaper, <0 if none */ | ||
50 | struct sk_buff_head tx_queue; /* list of buffers in transit */ | ||
51 | wait_queue_head_t tx_wait; /* for close */ | ||
52 | u32 *ring; /* transmit ring */ | ||
53 | int ring_curr; /* current write position */ | ||
54 | int txing; /* number of transmits in progress */ | ||
55 | struct sk_buff_head backlog; /* list of buffers waiting for ring */ | ||
56 | }; | ||
57 | |||
58 | struct zatm_dev { | ||
59 | /*-------------------------------- TX part */ | ||
60 | int tx_bw; /* remaining bandwidth */ | ||
61 | u32 free_shapers; /* bit set */ | ||
62 | int ubr; /* UBR shaper; -1 if none */ | ||
63 | int ubr_ref_cnt; /* number of VCs using UBR shaper */ | ||
64 | /*-------------------------------- RX part */ | ||
65 | int pool_ref[NR_POOLS]; /* free buffer pool usage counters */ | ||
66 | volatile struct sk_buff *last_free[NR_POOLS]; | ||
67 | /* last entry in respective pool */ | ||
68 | struct sk_buff_head pool[NR_POOLS];/* free buffer pools */ | ||
69 | struct zatm_pool_info pool_info[NR_POOLS]; /* pool information */ | ||
70 | /*-------------------------------- maps */ | ||
71 | struct atm_vcc **tx_map; /* TX VCCs */ | ||
72 | struct atm_vcc **rx_map; /* RX VCCs */ | ||
73 | int chans; /* map size, must be 2^n */ | ||
74 | /*-------------------------------- mailboxes */ | ||
75 | unsigned long mbx_start[NR_MBX];/* start addresses */ | ||
76 | u16 mbx_end[NR_MBX]; /* end offset (in bytes) */ | ||
77 | /*-------------------------------- other pointers */ | ||
78 | u32 pool_base; /* Free buffer pool dsc (word addr) */ | ||
79 | /*-------------------------------- ZATM links */ | ||
80 | struct atm_dev *more; /* other ZATM devices */ | ||
81 | /*-------------------------------- general information */ | ||
82 | int mem; /* RAM on board (in bytes) */ | ||
83 | int khz; /* timer clock */ | ||
84 | int copper; /* PHY type */ | ||
85 | unsigned char irq; /* IRQ */ | ||
86 | unsigned int base; /* IO base address */ | ||
87 | struct pci_dev *pci_dev; /* PCI stuff */ | ||
88 | spinlock_t lock; | ||
89 | }; | ||
90 | |||
91 | |||
92 | #define ZATM_DEV(d) ((struct zatm_dev *) (d)->dev_data) | ||
93 | #define ZATM_VCC(d) ((struct zatm_vcc *) (d)->dev_data) | ||
94 | |||
95 | |||
96 | struct zatm_skb_prv { | ||
97 | struct atm_skb_data _; /* reserved */ | ||
98 | u32 *dsc; /* pointer to skb's descriptor */ | ||
99 | }; | ||
100 | |||
101 | #define ZATM_PRV_DSC(skb) (((struct zatm_skb_prv *) (skb)->cb)->dsc) | ||
102 | |||
103 | #endif | ||
diff --git a/drivers/atm/zeprom.h b/drivers/atm/zeprom.h new file mode 100644 index 000000000000..019bb82490e9 --- /dev/null +++ b/drivers/atm/zeprom.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* drivers/atm/zeprom.h - ZeitNet ZN122x EEPROM (NM93C46) declarations */ | ||
2 | |||
3 | /* Written 1995,1996 by Werner Almesberger, EPFL LRC */ | ||
4 | |||
5 | |||
6 | #ifndef DRIVER_ATM_ZEPROM_H | ||
7 | #define DRIVER_ATM_ZEPROM_H | ||
8 | |||
9 | /* Different versions use different control registers */ | ||
10 | |||
11 | #define ZEPROM_V1_REG PCI_VENDOR_ID /* PCI register */ | ||
12 | #define ZEPROM_V2_REG 0x40 | ||
13 | |||
14 | /* Bits in contol register */ | ||
15 | |||
16 | #define ZEPROM_SK 0x80000000 /* strobe (probably on raising edge) */ | ||
17 | #define ZEPROM_CS 0x40000000 /* Chip Select */ | ||
18 | #define ZEPROM_DI 0x20000000 /* Data Input */ | ||
19 | #define ZEPROM_DO 0x10000000 /* Data Output */ | ||
20 | |||
21 | #define ZEPROM_SIZE 32 /* 32 bytes */ | ||
22 | #define ZEPROM_V1_ESI_OFF 24 /* ESI offset in EEPROM (V1) */ | ||
23 | #define ZEPROM_V2_ESI_OFF 4 /* ESI offset in EEPROM (V2) */ | ||
24 | |||
25 | #define ZEPROM_CMD_LEN 3 /* commands are three bits */ | ||
26 | #define ZEPROM_ADDR_LEN 6 /* addresses are six bits */ | ||
27 | |||
28 | /* Commands (3 bits) */ | ||
29 | |||
30 | #define ZEPROM_CMD_READ 6 | ||
31 | |||
32 | /* No other commands are needed. */ | ||
33 | |||
34 | #endif | ||