aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hisax
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/hisax')
-rw-r--r--drivers/isdn/hisax/Kconfig442
-rw-r--r--drivers/isdn/hisax/Makefile64
-rw-r--r--drivers/isdn/hisax/amd7930_fn.c796
-rw-r--r--drivers/isdn/hisax/amd7930_fn.h37
-rw-r--r--drivers/isdn/hisax/arcofi.c134
-rw-r--r--drivers/isdn/hisax/arcofi.h27
-rw-r--r--drivers/isdn/hisax/asuscom.c427
-rw-r--r--drivers/isdn/hisax/avm_a1.c317
-rw-r--r--drivers/isdn/hisax/avm_a1p.c268
-rw-r--r--drivers/isdn/hisax/avm_pci.c865
-rw-r--r--drivers/isdn/hisax/avma1_cs.c527
-rw-r--r--drivers/isdn/hisax/bkm_a4t.c344
-rw-r--r--drivers/isdn/hisax/bkm_a8.c451
-rw-r--r--drivers/isdn/hisax/bkm_ax.h119
-rw-r--r--drivers/isdn/hisax/callc.c1793
-rw-r--r--drivers/isdn/hisax/config.c1958
-rw-r--r--drivers/isdn/hisax/diva.c1183
-rw-r--r--drivers/isdn/hisax/elsa.c1190
-rw-r--r--drivers/isdn/hisax/elsa_cs.c532
-rw-r--r--drivers/isdn/hisax/elsa_ser.c657
-rw-r--r--drivers/isdn/hisax/enternow.h51
-rw-r--r--drivers/isdn/hisax/enternow_pci.c399
-rw-r--r--drivers/isdn/hisax/fsm.c163
-rw-r--r--drivers/isdn/hisax/fsm.h61
-rw-r--r--drivers/isdn/hisax/gazel.c684
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c1714
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.h88
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c1082
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.h128
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c593
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.h60
-rw-r--r--drivers/isdn/hisax/hfc_pci.c1747
-rw-r--r--drivers/isdn/hisax/hfc_pci.h236
-rw-r--r--drivers/isdn/hisax/hfc_sx.c1521
-rw-r--r--drivers/isdn/hisax/hfc_sx.h197
-rw-r--r--drivers/isdn/hisax/hfc_usb.c1828
-rw-r--r--drivers/isdn/hisax/hfc_usb.h228
-rw-r--r--drivers/isdn/hisax/hfcscard.c266
-rw-r--r--drivers/isdn/hisax/hisax.h1341
-rw-r--r--drivers/isdn/hisax/hisax_cfg.h64
-rw-r--r--drivers/isdn/hisax/hisax_debug.h81
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c1028
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.h58
-rw-r--r--drivers/isdn/hisax/hisax_if.h66
-rw-r--r--drivers/isdn/hisax/hisax_isac.c897
-rw-r--r--drivers/isdn/hisax/hisax_isac.h45
-rw-r--r--drivers/isdn/hisax/hscx.c280
-rw-r--r--drivers/isdn/hisax/hscx.h41
-rw-r--r--drivers/isdn/hisax/hscx_irq.c292
-rw-r--r--drivers/isdn/hisax/icc.c685
-rw-r--r--drivers/isdn/hisax/icc.h72
-rw-r--r--drivers/isdn/hisax/ipac.h29
-rw-r--r--drivers/isdn/hisax/ipacx.c1004
-rw-r--r--drivers/isdn/hisax/ipacx.h162
-rw-r--r--drivers/isdn/hisax/isac.c684
-rw-r--r--drivers/isdn/hisax/isac.h70
-rw-r--r--drivers/isdn/hisax/isar.c1909
-rw-r--r--drivers/isdn/hisax/isar.h222
-rw-r--r--drivers/isdn/hisax/isdnhdlc.c628
-rw-r--r--drivers/isdn/hisax/isdnhdlc.h72
-rw-r--r--drivers/isdn/hisax/isdnl1.c932
-rw-r--r--drivers/isdn/hisax/isdnl1.h32
-rw-r--r--drivers/isdn/hisax/isdnl2.c1860
-rw-r--r--drivers/isdn/hisax/isdnl2.h26
-rw-r--r--drivers/isdn/hisax/isdnl3.c610
-rw-r--r--drivers/isdn/hisax/isdnl3.h37
-rw-r--r--drivers/isdn/hisax/isurf.c306
-rw-r--r--drivers/isdn/hisax/ix1_micro.c318
-rw-r--r--drivers/isdn/hisax/jade.c318
-rw-r--r--drivers/isdn/hisax/jade.h135
-rw-r--r--drivers/isdn/hisax/jade_irq.c236
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c955
-rw-r--r--drivers/isdn/hisax/l3_1tr6.h164
-rw-r--r--drivers/isdn/hisax/l3dss1.c3238
-rw-r--r--drivers/isdn/hisax/l3dss1.h124
-rw-r--r--drivers/isdn/hisax/l3ni1.c3189
-rw-r--r--drivers/isdn/hisax/l3ni1.h136
-rw-r--r--drivers/isdn/hisax/lmgr.c50
-rw-r--r--drivers/isdn/hisax/mic.c239
-rw-r--r--drivers/isdn/hisax/netjet.c996
-rw-r--r--drivers/isdn/hisax/netjet.h72
-rw-r--r--drivers/isdn/hisax/niccy.c389
-rw-r--r--drivers/isdn/hisax/nj_s.c278
-rw-r--r--drivers/isdn/hisax/nj_u.c244
-rw-r--r--drivers/isdn/hisax/q931.c1522
-rw-r--r--drivers/isdn/hisax/s0box.c266
-rw-r--r--drivers/isdn/hisax/saphir.c300
-rw-r--r--drivers/isdn/hisax/sedlbauer.c833
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c640
-rw-r--r--drivers/isdn/hisax/sportster.c270
-rw-r--r--drivers/isdn/hisax/st5481.h535
-rw-r--r--drivers/isdn/hisax/st5481_b.c374
-rw-r--r--drivers/isdn/hisax/st5481_d.c776
-rw-r--r--drivers/isdn/hisax/st5481_hdlc.c580
-rw-r--r--drivers/isdn/hisax/st5481_hdlc.h62
-rw-r--r--drivers/isdn/hisax/st5481_init.c224
-rw-r--r--drivers/isdn/hisax/st5481_usb.c650
-rw-r--r--drivers/isdn/hisax/tei.c466
-rw-r--r--drivers/isdn/hisax/teleint.c339
-rw-r--r--drivers/isdn/hisax/teles0.c367
-rw-r--r--drivers/isdn/hisax/teles3.c499
-rw-r--r--drivers/isdn/hisax/teles_cs.c513
-rw-r--r--drivers/isdn/hisax/telespci.c359
-rw-r--r--drivers/isdn/hisax/w6692.c1096
-rw-r--r--drivers/isdn/hisax/w6692.h184
105 files changed, 58646 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
new file mode 100644
index 00000000000..6c7b8bffc6f
--- /dev/null
+++ b/drivers/isdn/hisax/Kconfig
@@ -0,0 +1,442 @@
1
2menu "Passive cards"
3 depends on ISDN_I4L
4
5config ISDN_DRV_HISAX
6 tristate "HiSax SiemensChipSet driver support"
7 select CRC_CCITT
8 ---help---
9 This is a driver supporting the Siemens chipset on various
10 ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, Teles
11 S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and many
12 compatibles).
13
14 HiSax is just the name of this driver, not the name of any hardware.
15
16 If you have a card with such a chipset, you should say Y here and
17 also to the configuration option of the driver for your particular
18 card, below.
19
20if ISDN_DRV_HISAX!=n
21
22comment "D-channel protocol features"
23
24config HISAX_EURO
25 bool "HiSax Support for EURO/DSS1"
26 help
27 Say Y or N according to the D-channel protocol which your local
28 telephone service company provides.
29
30 The call control protocol E-DSS1 is used in most European countries.
31 If unsure, say Y.
32
33config DE_AOC
34 bool "Support for german chargeinfo"
35 depends on HISAX_EURO
36 help
37 If you want that the HiSax hardware driver sends messages to the
38 upper level of the isdn code on each AOCD (Advice Of Charge, During
39 the call -- transmission of the fee information during a call) and
40 on each AOCE (Advice Of Charge, at the End of the call --
41 transmission of fee information at the end of the call), say Y here.
42 This works only in Germany.
43
44config HISAX_NO_SENDCOMPLETE
45 bool "Disable sending complete"
46 depends on HISAX_EURO
47 help
48 If you have trouble with some ugly exchanges or you live in
49 Australia select this option.
50
51config HISAX_NO_LLC
52 bool "Disable sending low layer compatibility"
53 depends on HISAX_EURO
54 help
55 If you have trouble with some ugly exchanges try to select this
56 option.
57
58config HISAX_NO_KEYPAD
59 bool "Disable keypad protocol option"
60 depends on HISAX_EURO
61 help
62 If you like to send special dial strings including * or # without
63 using the keypad protocol, select this option.
64
65config HISAX_1TR6
66 bool "HiSax Support for german 1TR6"
67 help
68 Say Y or N according to the D-channel protocol which your local
69 telephone service company provides.
70
71 1TR6 is an old call control protocol which was used in Germany
72 before E-DSS1 was established. Nowadays, all new lines in Germany
73 use E-DSS1.
74
75config HISAX_NI1
76 bool "HiSax Support for US NI1"
77 help
78 Enable this if you like to use ISDN in US on a NI1 basic rate
79 interface.
80
81config HISAX_MAX_CARDS
82 int "Maximum number of cards supported by HiSax"
83 default "8"
84 help
85 This option allows you to specify the maximum number of cards which
86 the HiSax driver will be able to handle.
87
88comment "HiSax supported cards"
89
90config HISAX_16_0
91 bool "Teles 16.0/8.0"
92 depends on ISA
93 help
94 This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
95 and many compatibles.
96
97 See <file:Documentation/isdn/README.HiSax> on how to configure it
98 using the different cards, a different D-channel protocol, or
99 non-standard IRQ/port/shmem settings.
100
101config HISAX_16_3
102 bool "Teles 16.3 or PNP or PCMCIA"
103 help
104 This enables HiSax support for the Teles ISDN-cards S0-16.3 the
105 Teles/Creatix PnP and the Teles PCMCIA.
106
107 See <file:Documentation/isdn/README.HiSax> on how to configure it
108 using the different cards, a different D-channel protocol, or
109 non-standard IRQ/port settings.
110
111config HISAX_TELESPCI
112 bool "Teles PCI"
113 depends on PCI && (BROKEN || !(SPARC64 || PPC))
114 help
115 This enables HiSax support for the Teles PCI.
116 See <file:Documentation/isdn/README.HiSax> on how to configure it.
117
118config HISAX_S0BOX
119 bool "Teles S0Box"
120 help
121 This enables HiSax support for the Teles/Creatix parallel port
122 S0BOX. See <file:Documentation/isdn/README.HiSax> on how to
123 configure it.
124
125config HISAX_AVM_A1
126 bool "AVM A1 (Fritz)"
127 depends on ISA
128 help
129 This enables HiSax support for the AVM A1 (aka "Fritz").
130
131 See <file:Documentation/isdn/README.HiSax> on how to configure it
132 using the different cards, a different D-channel protocol, or
133 non-standard IRQ/port settings.
134
135config HISAX_FRITZPCI
136 bool "AVM PnP/PCI (Fritz!PnP/PCI)"
137 help
138 This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
139 See <file:Documentation/isdn/README.HiSax> on how to configure it.
140
141config HISAX_AVM_A1_PCMCIA
142 bool "AVM A1 PCMCIA (Fritz)"
143 help
144 This enables HiSax support for the AVM A1 "Fritz!PCMCIA").
145 See <file:Documentation/isdn/README.HiSax> on how to configure it.
146
147config HISAX_ELSA
148 bool "Elsa cards"
149 help
150 This enables HiSax support for the Elsa Mircolink ISA cards, for the
151 Elsa Quickstep series cards and Elsa PCMCIA.
152
153 See <file:Documentation/isdn/README.HiSax> on how to configure it
154 using the different cards, a different D-channel protocol, or
155 non-standard IRQ/port settings.
156
157config HISAX_IX1MICROR2
158 bool "ITK ix1-micro Revision 2"
159 depends on ISA
160 help
161 This enables HiSax support for the ITK ix1-micro Revision 2 card.
162
163 See <file:Documentation/isdn/README.HiSax> on how to configure it
164 using the different cards, a different D-channel protocol, or
165 non-standard IRQ/port settings.
166
167config HISAX_DIEHLDIVA
168 bool "Eicon.Diehl Diva cards"
169 help
170 This enables HiSax support for the Eicon.Diehl Diva none PRO
171 versions passive ISDN cards.
172
173 See <file:Documentation/isdn/README.HiSax> on how to configure it
174 using the different cards, a different D-channel protocol, or
175 non-standard IRQ/port settings.
176
177config HISAX_ASUSCOM
178 bool "ASUSCOM ISA cards"
179 depends on ISA
180 help
181 This enables HiSax support for the AsusCom and their OEM versions
182 passive ISDN ISA cards.
183
184 See <file:Documentation/isdn/README.HiSax> on how to configure it
185 using the different cards, a different D-channel protocol, or
186 non-standard IRQ/port settings.
187
188config HISAX_TELEINT
189 bool "TELEINT cards"
190 depends on ISA
191 help
192 This enables HiSax support for the TELEINT SA1 semiactiv ISDN card.
193
194 See <file:Documentation/isdn/README.HiSax> on how to configure it
195 using the different cards, a different D-channel protocol, or
196 non-standard IRQ/port settings.
197
198config HISAX_HFCS
199 bool "HFC-S based cards"
200 depends on ISA
201 help
202 This enables HiSax support for the HFC-S 2BDS0 based cards, like
203 teles 16.3c.
204
205 See <file:Documentation/isdn/README.HiSax> on how to configure it
206 using the different cards, a different D-channel protocol, or
207 non-standard IRQ/port settings.
208
209config HISAX_SEDLBAUER
210 bool "Sedlbauer cards"
211 help
212 This enables HiSax support for the Sedlbauer passive ISDN cards.
213
214 See <file:Documentation/isdn/README.HiSax> on how to configure it
215 using the different cards, a different D-channel protocol, or
216 non-standard IRQ/port settings.
217
218config HISAX_SPORTSTER
219 bool "USR Sportster internal TA"
220 depends on ISA
221 help
222 This enables HiSax support for the USR Sportster internal TA card.
223
224 See <file:Documentation/isdn/README.HiSax> on how to configure it
225 using a different D-channel protocol, or non-standard IRQ/port
226 settings.
227
228config HISAX_MIC
229 bool "MIC card"
230 depends on ISA
231 help
232 This enables HiSax support for the ITH MIC card.
233
234 See <file:Documentation/isdn/README.HiSax> on how to configure it
235 using a different D-channel protocol, or non-standard IRQ/port
236 settings.
237
238config HISAX_NETJET
239 bool "NETjet card"
240 depends on PCI && (BROKEN || !(SPARC64 || PPC))
241 help
242 This enables HiSax support for the NetJet from Traverse
243 Technologies.
244
245 See <file:Documentation/isdn/README.HiSax> on how to configure it
246 using a different D-channel protocol, or non-standard IRQ/port
247 settings.
248
249config HISAX_NETJET_U
250 bool "NETspider U card"
251 depends on PCI && (BROKEN || !(SPARC64 || PPC))
252 help
253 This enables HiSax support for the Netspider U interface ISDN card
254 from Traverse Technologies.
255 See <file:Documentation/isdn/README.HiSax> on how to configure it
256 using a different D-channel protocol, or non-standard IRQ/port
257 settings.
258
259config HISAX_NICCY
260 bool "Niccy PnP/PCI card"
261 help
262 This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI.
263
264 See <file:Documentation/isdn/README.HiSax> on how to configure it
265 using a different D-channel protocol, or non-standard IRQ/port
266 settings.
267
268config HISAX_ISURF
269 bool "Siemens I-Surf card"
270 depends on ISA
271 help
272 This enables HiSax support for the Siemens I-Talk/I-Surf card with
273 ISAR chip.
274 See <file:Documentation/isdn/README.HiSax> on how to configure it
275 using a different D-channel protocol, or non-standard IRQ/port
276 settings.
277
278config HISAX_HSTSAPHIR
279 bool "HST Saphir card"
280 depends on ISA
281 help
282 This enables HiSax support for the HST Saphir card.
283
284 See <file:Documentation/isdn/README.HiSax> on how to configure it
285 using a different D-channel protocol, or non-standard IRQ/port
286 settings.
287
288config HISAX_BKM_A4T
289 bool "Telekom A4T card"
290 depends on PCI
291 help
292 This enables HiSax support for the Telekom A4T card.
293
294 See <file:Documentation/isdn/README.HiSax> on how to configure it
295 using a different D-channel protocol, or non-standard IRQ/port
296 settings.
297
298config HISAX_SCT_QUADRO
299 bool "Scitel Quadro card"
300 depends on PCI
301 help
302 This enables HiSax support for the Scitel Quadro card.
303
304 See <file:Documentation/isdn/README.HiSax> on how to configure it
305 using a different D-channel protocol, or non-standard IRQ/port
306 settings.
307
308config HISAX_GAZEL
309 bool "Gazel cards"
310 help
311 This enables HiSax support for the Gazel cards.
312
313 See <file:Documentation/isdn/README.HiSax> on how to configure it
314 using a different D-channel protocol, or non-standard IRQ/port
315 settings.
316
317config HISAX_HFC_PCI
318 bool "HFC PCI-Bus cards"
319 depends on PCI && (BROKEN || !(SPARC64 || PPC))
320 help
321 This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
322
323 For more informations see under
324 <file:Documentation/isdn/README.hfc-pci>.
325
326config HISAX_W6692
327 bool "Winbond W6692 based cards"
328 depends on PCI
329 help
330 This enables HiSax support for Winbond W6692 based PCI ISDN cards.
331
332 See <file:Documentation/isdn/README.HiSax> on how to configure it
333 using a different D-channel protocol, or non-standard IRQ/port
334 settings.
335
336config HISAX_HFC_SX
337 bool "HFC-S+, HFC-SP, HFC-PCMCIA cards"
338 help
339 This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA
340 cards. This code is not finished yet.
341
342# bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
343
344config HISAX_ENTERNOW_PCI
345 bool "Formula-n enter:now PCI card"
346 depends on PCI && (BROKEN || !(SPARC64 || PPC))
347 help
348 This enables HiSax support for the Formula-n enter:now PCI
349 ISDN card.
350
351config HISAX_AMD7930
352 bool "Am7930 (EXPERIMENTAL)"
353 depends on EXPERIMENTAL && (SPARC32 || SPARC64)
354 help
355 This enables HiSax support for the AMD7930 chips on some SPARCs.
356 This code is not finished yet.
357
358endif
359
360if ISDN_DRV_HISAX
361
362config HISAX_DEBUG
363 bool "HiSax debugging"
364 help
365 This enables debugging code in the new-style HiSax drivers, i.e.
366 the ST5481 USB driver currently.
367 If in doubt, say yes.
368
369comment "HiSax PCMCIA card service modules"
370
371config HISAX_SEDLBAUER_CS
372 tristate "Sedlbauer PCMCIA cards"
373 depends on PCMCIA && HISAX_SEDLBAUER
374 help
375 This enables the PCMCIA client driver for the Sedlbauer Speed Star
376 and Speed Star II cards.
377
378config HISAX_ELSA_CS
379 tristate "ELSA PCMCIA MicroLink cards"
380 depends on PCMCIA && HISAX_ELSA
381 help
382 This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink
383 card.
384
385config HISAX_AVM_A1_CS
386 tristate "AVM A1 PCMCIA cards"
387 depends on PCMCIA && ISDN_DRV_HISAX
388 help
389 This enables the PCMCIA client driver for the AVM A1 / Fritz!Card
390 PCMCIA cards.
391
392config HISAX_TELES_CS
393 tristate "TELES PCMCIA cards"
394 depends on PCMCIA && HISAX_16_3
395 help
396 This enables the PCMCIA client driver for the Teles PCMCIA cards.
397
398comment "HiSax sub driver modules"
399
400config HISAX_ST5481
401 tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
402 depends on USB && EXPERIMENTAL
403 select CRC_CCITT
404 help
405 This enables the driver for ST5481 based USB ISDN adapters,
406 e.g. the BeWan Gazel 128 USB
407
408config HISAX_HFCUSB
409 tristate "HFC USB based ISDN modems (EXPERIMENTAL)"
410 depends on USB && EXPERIMENTAL
411 help
412 This enables the driver for HFC USB based ISDN modems.
413
414config HISAX_HFC4S8S
415 tristate "HFC-4S/8S based ISDN cards (EXPERIMENTAL)"
416 depends on EXPERIMENTAL
417 help
418 This enables the driver for HFC-4S/8S based ISDN cards.
419
420config HISAX_FRITZ_PCIPNP
421 tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
422 depends on PCI && EXPERIMENTAL
423 help
424 This enables the driver for the AVM Fritz!Card PCI,
425 Fritz!Card PCI v2 and Fritz!Card PnP.
426 (the latter also needs you to select "ISA Plug and Play support"
427 from the menu "Plug and Play configuration")
428
429config HISAX_HDLC
430 bool
431 depends on HISAX_ST5481
432 default y
433
434config HISAX_AVM_A1_PCMCIA
435 bool
436 depends on HISAX_AVM_A1_CS
437 default y
438
439endif
440
441endmenu
442
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
new file mode 100644
index 00000000000..8d6bb56754b
--- /dev/null
+++ b/drivers/isdn/hisax/Makefile
@@ -0,0 +1,64 @@
1# Makefile for the hisax ISDN device driver
2
3# The target object and module list name.
4
5# Define maximum number of cards
6
7EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
8
9obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o
10obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o
11obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o
12obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o
13obj-$(CONFIG_HISAX_TELES_CS) += teles_cs.o
14obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
15obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o
16obj-$(CONFIG_HISAX_HFC4S8S) += hfc4s8s_l1.o
17obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
18
19ifdef CONFIG_HISAX_HDLC
20obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o
21endif
22
23# Multipart objects.
24
25hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \
26 st5481_b.o st5481_hdlc.o
27
28hisax-y := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
29 lmgr.o q931.o callc.o fsm.o
30hisax-$(CONFIG_HISAX_EURO) += l3dss1.o
31hisax-$(CONFIG_HISAX_NI1) += l3ni1.o
32hisax-$(CONFIG_HISAX_1TR6) += l3_1tr6.o
33
34hisax-$(CONFIG_HISAX_16_0) += teles0.o isac.o arcofi.o hscx.o
35hisax-$(CONFIG_HISAX_16_3) += teles3.o isac.o arcofi.o hscx.o
36hisax-$(CONFIG_HISAX_TELESPCI) += telespci.o isac.o arcofi.o hscx.o
37hisax-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o
38hisax-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o
39hisax-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o
40hisax-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
41hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
42hisax-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
43hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o
44hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
45hisax-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
46hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o \
47 isar.o
48hisax-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
49hisax-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
50hisax-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o
51hisax-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o
52hisax-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
53hisax-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o
54hisax-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o
55hisax-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o
56hisax-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
57hisax-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
58hisax-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o
59hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
60hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
61hisax-$(CONFIG_HISAX_W6692) += w6692.o
62hisax-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o
63#hisax-$(CONFIG_HISAX_TESTEMU) += testemu.o
64
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
new file mode 100644
index 00000000000..c4f861a5db2
--- /dev/null
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -0,0 +1,796 @@
1/* gerdes_amd7930.c,v 0.99 2001/10/02
2 *
3 * gerdes_amd7930.c Amd 79C30A and 79C32A specific routines
4 * (based on HiSax driver by Karsten Keil)
5 *
6 * Author Christoph Ersfeld <info@formula-n.de>
7 * Formula-n Europe AG (www.formula-n.com)
8 * previously Gerdes AG
9 *
10 *
11 * This file is (c) under GNU PUBLIC LICENSE
12 *
13 *
14 * Notes:
15 * Version 0.99 is the first release of this driver and there are
16 * certainly a few bugs.
17 *
18 * Please don't report any malfunction to me without sending
19 * (compressed) debug-logs.
20 * It would be nearly impossible to retrace it.
21 *
22 * Log D-channel-processing as follows:
23 *
24 * 1. Load hisax with card-specific parameters, this example ist for
25 * Formula-n enter:now ISDN PCI and compatible
26 * (f.e. Gerdes Power ISDN PCI)
27 *
28 * modprobe hisax type=41 protocol=2 id=gerdes
29 *
30 * if you chose an other value for id, you need to modify the
31 * code below, too.
32 *
33 * 2. set debug-level
34 *
35 * hisaxctrl gerdes 1 0x3ff
36 * hisaxctrl gerdes 11 0x4f
37 * cat /dev/isdnctrl >> ~/log &
38 *
39 * Please take also a look into /var/log/messages if there is
40 * anything importand concerning HISAX.
41 *
42 *
43 * Credits:
44 * Programming the driver for Formula-n enter:now ISDN PCI and
45 * necessary this driver for the used Amd 7930 D-channel-controller
46 * was spnsored by Formula-n Europe AG.
47 * Thanks to Karsten Keil and Petr Novak, who gave me support in
48 * Hisax-specific questions.
49 * I want so say special thanks to Carl-Friedrich Braun, who had to
50 * answer a lot of questions about generally ISDN and about handling
51 * of the Amd-Chip.
52 *
53 */
54
55
56#include "hisax.h"
57#include "isdnl1.h"
58#include "isac.h"
59#include "amd7930_fn.h"
60#include <linux/interrupt.h>
61#include <linux/init.h>
62
63static void Amd7930_new_ph(struct IsdnCardState *cs);
64
65static WORD initAMD[] = {
66 0x0100,
67
68 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2
69 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on)
70 0x0087, 1, 0xFF, // DMR2
71 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on)
72 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition )
73 0x0084, 2, 0x80, 0x00, // DRLR
74 0x00C0, 1, 0x47, // PPCR1
75 0x00C8, 1, 0x01, // PPCR2
76
77 0x0102,
78 0x0107,
79 0x01A1, 1,
80 0x0121, 1,
81 0x0189, 2,
82
83 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4
84 0x0063, 2, 0x08, 0x08, // GX
85 0x0064, 2, 0x08, 0x08, // GR
86 0x0065, 2, 0x99, 0x00, // GER
87 0x0066, 2, 0x7C, 0x8B, // STG
88 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2
89 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2
90 0x0069, 1, 0x4F, // MMR1
91 0x006A, 1, 0x00, // MMR2
92 0x006C, 1, 0x40, // MMR3
93 0x0021, 1, 0x02, // INIT
94 0x00A3, 1, 0x40, // LMR1
95
96 0xFFFF
97};
98
99
100void /* macro wWordAMD */
101WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
102{
103 wByteAMD(cs, 0x00, reg);
104 wByteAMD(cs, 0x01, LOBYTE(val));
105 wByteAMD(cs, 0x01, HIBYTE(val));
106}
107
108WORD /* macro rWordAMD */
109ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg)
110{
111 WORD res;
112 /* direct access register */
113 if(reg < 8) {
114 res = rByteAMD(cs, reg);
115 res += 256*rByteAMD(cs, reg);
116 }
117 /* indirect access register */
118 else {
119 wByteAMD(cs, 0x00, reg);
120 res = rByteAMD(cs, 0x01);
121 res += 256*rByteAMD(cs, 0x01);
122 }
123 return (res);
124}
125
126
127static void
128Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s)
129{
130 if (cs->debug & L1_DEB_ISAC)
131 debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command);
132
133 cs->dc.amd7930.lmr1 = command;
134 wByteAMD(cs, 0xA3, command);
135}
136
137
138
139static BYTE i430States[] = {
140// to reset F3 F4 F5 F6 F7 F8 AR from
141 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // init
142 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // reset
143 0x01, 0x02, 0x00, 0x00, 0x00, 0x09, 0x05, 0x04, // F3
144 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F4
145 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F5
146 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, // F6
147 0x11, 0x13, 0x00, 0x00, 0x1B, 0x00, 0x15, 0x00, // F7
148 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, // F8
149 0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0A}; // AR
150
151
152/* Row init - reset F3 F4 F5 F6 F7 F8 AR */
153static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
154
155
156
157
158static void
159Amd7930_get_state(struct IsdnCardState *cs) {
160 BYTE lsr = rByteAMD(cs, 0xA1);
161 cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
162 Amd7930_new_ph(cs);
163}
164
165
166
167static void
168Amd7930_new_ph(struct IsdnCardState *cs)
169{
170 u_char index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1;
171 u_char message = i430States[index];
172
173 if (cs->debug & L1_DEB_ISAC)
174 debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d",
175 cs->dc.amd7930.ph_state, cs->dc.amd7930.old_state, message & 0x0f, index);
176
177 cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state;
178
179 /* abort transmit if nessesary */
180 if ((message & 0xf0) && (cs->tx_skb)) {
181 wByteAMD(cs, 0x21, 0xC2);
182 wByteAMD(cs, 0x21, 0x02);
183 }
184
185 switch (message & 0x0f) {
186
187 case (1):
188 l1_msg(cs, HW_RESET | INDICATION, NULL);
189 Amd7930_get_state(cs);
190 break;
191 case (2): /* init, Card starts in F3 */
192 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
193 break;
194 case (3):
195 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
196 break;
197 case (4):
198 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
199 Amd7930_ph_command(cs, 0x50, "HW_ENABLE REQUEST");
200 break;
201 case (5):
202 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
203 break;
204 case (6):
205 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
206 break;
207 case (7): /* init, Card starts in F7 */
208 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
209 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
210 break;
211 case (8):
212 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
213 /* fall through */
214 case (9):
215 Amd7930_ph_command(cs, 0x40, "HW_ENABLE REQ cleared if set");
216 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
217 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
218 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
219 break;
220 case (10):
221 Amd7930_ph_command(cs, 0x40, "T3 expired, HW_ENABLE REQ cleared");
222 cs->dc.amd7930.old_state = 3;
223 break;
224 case (11):
225 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
226 break;
227 default:
228 break;
229 }
230}
231
232
233
234static void
235Amd7930_bh(struct IsdnCardState *cs)
236{
237
238 struct PStack *stptr;
239
240 if (!cs)
241 return;
242 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
243 if (cs->debug)
244 debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
245 stptr = cs->stlist;
246 while (stptr != NULL) {
247 stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
248 stptr = stptr->next;
249 }
250 }
251 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
252 if (cs->debug & L1_DEB_ISAC)
253 debugl1(cs, "AMD7930: bh, D_L1STATECHANGE");
254 Amd7930_new_ph(cs);
255 }
256
257 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
258 if (cs->debug & L1_DEB_ISAC)
259 debugl1(cs, "AMD7930: bh, D_RCVBUFREADY");
260 DChannel_proc_rcv(cs);
261 }
262
263 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
264 if (cs->debug & L1_DEB_ISAC)
265 debugl1(cs, "AMD7930: bh, D_XMTBUFREADY");
266 DChannel_proc_xmt(cs);
267 }
268}
269
270static void
271Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
272{
273
274 BYTE stat, der;
275 BYTE *ptr;
276 struct sk_buff *skb;
277
278
279 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
280 debugl1(cs, "Amd7930: empty_Dfifo");
281
282
283 ptr = cs->rcvbuf + cs->rcvidx;
284
285 /* AMD interrupts off */
286 AmdIrqOff(cs);
287
288 /* read D-Channel-Fifo*/
289 stat = rByteAMD(cs, 0x07); // DSR2
290
291 /* while Data in Fifo ... */
292 while ( (stat & 2) && ((ptr-cs->rcvbuf) < MAX_DFRAME_LEN_L1) ) {
293 *ptr = rByteAMD(cs, 0x04); // DCRB
294 ptr++;
295 stat = rByteAMD(cs, 0x07); // DSR2
296 cs->rcvidx = ptr - cs->rcvbuf;
297
298 /* Paket ready? */
299 if (stat & 1) {
300
301 der = rWordAMD(cs, 0x03);
302
303 /* no errors, packet ok */
304 if(!der && !flag) {
305 rWordAMD(cs, 0x89); // clear DRCR
306
307 if ((cs->rcvidx) > 0) {
308 if (!(skb = alloc_skb(cs->rcvidx, GFP_ATOMIC)))
309 printk(KERN_WARNING "HiSax: Amd7930: empty_Dfifo, D receive out of memory!\n");
310 else {
311 /* Debugging */
312 if (cs->debug & L1_DEB_ISAC_FIFO) {
313 char *t = cs->dlog;
314
315 t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx);
316 QuickHex(t, cs->rcvbuf, cs->rcvidx);
317 debugl1(cs, cs->dlog);
318 }
319 /* moves received data in sk-buffer */
320 memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx);
321 skb_queue_tail(&cs->rq, skb);
322 }
323 }
324
325 }
326 /* throw damaged packets away, reset receive-buffer, indicate RX */
327 ptr = cs->rcvbuf;
328 cs->rcvidx = 0;
329 schedule_event(cs, D_RCVBUFREADY);
330 }
331 }
332 /* Packet to long, overflow */
333 if(cs->rcvidx >= MAX_DFRAME_LEN_L1) {
334 if (cs->debug & L1_DEB_WARN)
335 debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun");
336 cs->rcvidx = 0;
337 return;
338 }
339 /* AMD interrupts on */
340 AmdIrqOn(cs);
341}
342
343
344static void
345Amd7930_fill_Dfifo(struct IsdnCardState *cs)
346{
347
348 WORD dtcrr, dtcrw, len, count;
349 BYTE txstat, dmr3;
350 BYTE *ptr, *deb_ptr;
351
352 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
353 debugl1(cs, "Amd7930: fill_Dfifo");
354
355 if ((!cs->tx_skb) || (cs->tx_skb->len <= 0))
356 return;
357
358 dtcrw = 0;
359 if(!cs->dc.amd7930.tx_xmtlen)
360 /* new Frame */
361 len = dtcrw = cs->tx_skb->len;
362 /* continue frame */
363 else len = cs->dc.amd7930.tx_xmtlen;
364
365
366 /* AMD interrupts off */
367 AmdIrqOff(cs);
368
369 deb_ptr = ptr = cs->tx_skb->data;
370
371 /* while free place in tx-fifo available and data in sk-buffer */
372 txstat = 0x10;
373 while((txstat & 0x10) && (cs->tx_cnt < len)) {
374 wByteAMD(cs, 0x04, *ptr);
375 ptr++;
376 cs->tx_cnt++;
377 txstat= rByteAMD(cs, 0x07);
378 }
379 count = ptr - cs->tx_skb->data;
380 skb_pull(cs->tx_skb, count);
381
382
383 dtcrr = rWordAMD(cs, 0x85); // DTCR
384 dmr3 = rByteAMD(cs, 0x8E);
385
386 if (cs->debug & L1_DEB_ISAC) {
387 debugl1(cs, "Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X", dmr3, dtcrr, LOBYTE(dtcrw), HIBYTE(dtcrw));
388 }
389
390 /* writeing of dtcrw starts transmit */
391 if(!cs->dc.amd7930.tx_xmtlen) {
392 wWordAMD(cs, 0x85, dtcrw);
393 cs->dc.amd7930.tx_xmtlen = dtcrw;
394 }
395
396 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
397 debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running");
398 del_timer(&cs->dbusytimer);
399 }
400 init_timer(&cs->dbusytimer);
401 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
402 add_timer(&cs->dbusytimer);
403
404 if (cs->debug & L1_DEB_ISAC_FIFO) {
405 char *t = cs->dlog;
406
407 t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);
408 QuickHex(t, deb_ptr, count);
409 debugl1(cs, cs->dlog);
410 }
411 /* AMD interrupts on */
412 AmdIrqOn(cs);
413}
414
415
416void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags)
417{
418 BYTE dsr1, dsr2, lsr;
419 WORD der;
420
421 while (irflags)
422 {
423
424 dsr1 = rByteAMD(cs, 0x02);
425 der = rWordAMD(cs, 0x03);
426 dsr2 = rByteAMD(cs, 0x07);
427 lsr = rByteAMD(cs, 0xA1);
428
429 if (cs->debug & L1_DEB_ISAC)
430 debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der);
431
432 /* D error -> read DER and DSR2 bit 2 */
433 if (der || (dsr2 & 4)) {
434
435 if (cs->debug & L1_DEB_WARN)
436 debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der);
437
438 /* RX, TX abort if collision detected */
439 if (der & 2) {
440 wByteAMD(cs, 0x21, 0xC2);
441 wByteAMD(cs, 0x21, 0x02);
442 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
443 del_timer(&cs->dbusytimer);
444 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
445 schedule_event(cs, D_CLEARBUSY);
446 /* restart frame */
447 if (cs->tx_skb) {
448 skb_push(cs->tx_skb, cs->tx_cnt);
449 cs->tx_cnt = 0;
450 cs->dc.amd7930.tx_xmtlen = 0;
451 Amd7930_fill_Dfifo(cs);
452 } else {
453 printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n");
454 debugl1(cs, "Amd7930: interrupt: D-Collision, no skb");
455 }
456 }
457 /* remove damaged data from fifo */
458 Amd7930_empty_Dfifo(cs, 1);
459
460 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
461 del_timer(&cs->dbusytimer);
462 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
463 schedule_event(cs, D_CLEARBUSY);
464 /* restart TX-Frame */
465 if (cs->tx_skb) {
466 skb_push(cs->tx_skb, cs->tx_cnt);
467 cs->tx_cnt = 0;
468 cs->dc.amd7930.tx_xmtlen = 0;
469 Amd7930_fill_Dfifo(cs);
470 }
471 }
472
473 /* D TX FIFO empty -> fill */
474 if (irflags & 1) {
475 if (cs->debug & L1_DEB_ISAC)
476 debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data");
477
478 /* AMD interrupts off */
479 AmdIrqOff(cs);
480
481 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
482 del_timer(&cs->dbusytimer);
483 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
484 schedule_event(cs, D_CLEARBUSY);
485 if (cs->tx_skb) {
486 if (cs->tx_skb->len)
487 Amd7930_fill_Dfifo(cs);
488 }
489 /* AMD interrupts on */
490 AmdIrqOn(cs);
491 }
492
493
494 /* D RX FIFO full or tiny packet in Fifo -> empty */
495 if ((irflags & 2) || (dsr1 & 2)) {
496 if (cs->debug & L1_DEB_ISAC)
497 debugl1(cs, "Amd7930: interrupt: empty D-FIFO");
498 Amd7930_empty_Dfifo(cs, 0);
499 }
500
501
502 /* D-Frame transmit complete */
503 if (dsr1 & 64) {
504 if (cs->debug & L1_DEB_ISAC) {
505 debugl1(cs, "Amd7930: interrupt: transmit packet ready");
506 }
507 /* AMD interrupts off */
508 AmdIrqOff(cs);
509
510 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
511 del_timer(&cs->dbusytimer);
512 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
513 schedule_event(cs, D_CLEARBUSY);
514
515 if (cs->tx_skb) {
516 if (cs->debug & L1_DEB_ISAC)
517 debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb");
518 dev_kfree_skb_irq(cs->tx_skb);
519 cs->tx_cnt = 0;
520 cs->dc.amd7930.tx_xmtlen=0;
521 cs->tx_skb = NULL;
522 }
523 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
524 if (cs->debug & L1_DEB_ISAC)
525 debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued");
526 cs->tx_cnt = 0;
527 cs->dc.amd7930.tx_xmtlen=0;
528 Amd7930_fill_Dfifo(cs);
529 }
530 else
531 schedule_event(cs, D_XMTBUFREADY);
532 /* AMD interrupts on */
533 AmdIrqOn(cs);
534 }
535
536 /* LIU status interrupt -> read LSR, check statechanges */
537 if (lsr & 0x38) {
538 /* AMD interrupts off */
539 AmdIrqOff(cs);
540
541 if (cs->debug & L1_DEB_ISAC)
542 debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) +2));
543
544 cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
545
546 schedule_event(cs, D_L1STATECHANGE);
547 /* AMD interrupts on */
548 AmdIrqOn(cs);
549 }
550
551 /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */
552 irflags = rByteAMD(cs, 0x00);
553 }
554
555}
556
557static void
558Amd7930_l1hw(struct PStack *st, int pr, void *arg)
559{
560 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
561 struct sk_buff *skb = arg;
562 u_long flags;
563
564 if (cs->debug & L1_DEB_ISAC)
565 debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr);
566
567 switch (pr) {
568 case (PH_DATA | REQUEST):
569 if (cs->debug & DEB_DLOG_HEX)
570 LogFrame(cs, skb->data, skb->len);
571 if (cs->debug & DEB_DLOG_VERBOSE)
572 dlogframe(cs, skb, 0);
573 spin_lock_irqsave(&cs->lock, flags);
574 if (cs->tx_skb) {
575 skb_queue_tail(&cs->sq, skb);
576#ifdef L2FRAME_DEBUG /* psa */
577 if (cs->debug & L1_DEB_LAPD)
578 Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA Queued", 0);
579#endif
580 } else {
581 cs->tx_skb = skb;
582 cs->tx_cnt = 0;
583 cs->dc.amd7930.tx_xmtlen=0;
584#ifdef L2FRAME_DEBUG /* psa */
585 if (cs->debug & L1_DEB_LAPD)
586 Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0);
587#endif
588 Amd7930_fill_Dfifo(cs);
589 }
590 spin_unlock_irqrestore(&cs->lock, flags);
591 break;
592 case (PH_PULL | INDICATION):
593 spin_lock_irqsave(&cs->lock, flags);
594 if (cs->tx_skb) {
595 if (cs->debug & L1_DEB_WARN)
596 debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen");
597 skb_queue_tail(&cs->sq, skb);
598 break;
599 }
600 if (cs->debug & DEB_DLOG_HEX)
601 LogFrame(cs, skb->data, skb->len);
602 if (cs->debug & DEB_DLOG_VERBOSE)
603 dlogframe(cs, skb, 0);
604 cs->tx_skb = skb;
605 cs->tx_cnt = 0;
606 cs->dc.amd7930.tx_xmtlen=0;
607#ifdef L2FRAME_DEBUG /* psa */
608 if (cs->debug & L1_DEB_LAPD)
609 Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0);
610#endif
611 Amd7930_fill_Dfifo(cs);
612 spin_unlock_irqrestore(&cs->lock, flags);
613 break;
614 case (PH_PULL | REQUEST):
615#ifdef L2FRAME_DEBUG /* psa */
616 if (cs->debug & L1_DEB_LAPD)
617 debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb)? "yes":"no");
618#endif
619 if (!cs->tx_skb) {
620 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
621 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
622 } else
623 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
624 break;
625 case (HW_RESET | REQUEST):
626 spin_lock_irqsave(&cs->lock, flags);
627 if ((cs->dc.amd7930.ph_state == 8)) {
628 /* b-channels off, PH-AR cleared
629 * change to F3 */
630 Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
631 spin_unlock_irqrestore(&cs->lock, flags);
632 } else {
633 Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
634 cs->dc.amd7930.ph_state = 2;
635 spin_unlock_irqrestore(&cs->lock, flags);
636 Amd7930_new_ph(cs);
637 }
638 break;
639 case (HW_ENABLE | REQUEST):
640 cs->dc.amd7930.ph_state = 9;
641 Amd7930_new_ph(cs);
642 break;
643 case (HW_INFO3 | REQUEST):
644 // automatic
645 break;
646 case (HW_TESTLOOP | REQUEST):
647 /* not implemented yet */
648 break;
649 case (HW_DEACTIVATE | RESPONSE):
650 skb_queue_purge(&cs->rq);
651 skb_queue_purge(&cs->sq);
652 if (cs->tx_skb) {
653 dev_kfree_skb(cs->tx_skb);
654 cs->tx_skb = NULL;
655 }
656 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
657 del_timer(&cs->dbusytimer);
658 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
659 schedule_event(cs, D_CLEARBUSY);
660 break;
661 default:
662 if (cs->debug & L1_DEB_WARN)
663 debugl1(cs, "Amd7930: l1hw: unknown %04x", pr);
664 break;
665 }
666}
667
668void
669setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
670{
671
672 if (cs->debug & L1_DEB_ISAC)
673 debugl1(cs, "Amd7930: setstack called");
674
675 st->l1.l1hw = Amd7930_l1hw;
676}
677
678
679void
680DC_Close_Amd7930(struct IsdnCardState *cs) {
681 if (cs->debug & L1_DEB_ISAC)
682 debugl1(cs, "Amd7930: DC_Close called");
683}
684
685
686static void
687dbusy_timer_handler(struct IsdnCardState *cs)
688{
689 u_long flags;
690 struct PStack *stptr;
691 WORD dtcr, der;
692 BYTE dsr1, dsr2;
693
694
695 if (cs->debug & L1_DEB_ISAC)
696 debugl1(cs, "Amd7930: dbusy_timer expired!");
697
698 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
699 spin_lock_irqsave(&cs->lock, flags);
700 /* D Transmit Byte Count Register:
701 * Counts down packet's number of Bytes, 0 if packet ready */
702 dtcr = rWordAMD(cs, 0x85);
703 dsr1 = rByteAMD(cs, 0x02);
704 dsr2 = rByteAMD(cs, 0x07);
705 der = rWordAMD(cs, 0x03);
706
707 if (cs->debug & L1_DEB_ISAC)
708 debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt);
709
710 if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */
711 test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
712 stptr = cs->stlist;
713 spin_unlock_irqrestore(&cs->lock, flags);
714 while (stptr != NULL) {
715 stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
716 stptr = stptr->next;
717 }
718
719 } else {
720 /* discard frame; reset transceiver */
721 test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
722 if (cs->tx_skb) {
723 dev_kfree_skb_any(cs->tx_skb);
724 cs->tx_cnt = 0;
725 cs->tx_skb = NULL;
726 cs->dc.amd7930.tx_xmtlen = 0;
727 } else {
728 printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n");
729 debugl1(cs, "Amd7930: D-Channel Busy no skb");
730
731 }
732 /* Transmitter reset, abort transmit */
733 wByteAMD(cs, 0x21, 0x82);
734 wByteAMD(cs, 0x21, 0x02);
735 spin_unlock_irqrestore(&cs->lock, flags);
736 cs->irq_func(cs->irq, cs, NULL);
737
738 if (cs->debug & L1_DEB_ISAC)
739 debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
740 }
741 }
742}
743
744
745
746void __devinit
747Amd7930_init(struct IsdnCardState *cs)
748{
749 WORD *ptr;
750 BYTE cmd, cnt;
751
752 if (cs->debug & L1_DEB_ISAC)
753 debugl1(cs, "Amd7930: initamd called");
754
755 cs->dc.amd7930.tx_xmtlen = 0;
756 cs->dc.amd7930.old_state = 0;
757 cs->dc.amd7930.lmr1 = 0x40;
758 cs->dc.amd7930.ph_command = Amd7930_ph_command;
759 cs->setstack_d = setstack_Amd7930;
760 cs->DC_Close = DC_Close_Amd7930;
761
762 /* AMD Initialisation */
763 for (ptr = initAMD; *ptr != 0xFFFF; ) {
764 cmd = LOBYTE(*ptr);
765
766 /* read */
767 if (*ptr++ >= 0x100) {
768 if (cmd < 8)
769 /* setzt Register zurück */
770 rByteAMD(cs, cmd);
771 else {
772 wByteAMD(cs, 0x00, cmd);
773 for (cnt = *ptr++; cnt > 0; cnt--)
774 rByteAMD(cs, 0x01);
775 }
776 }
777 /* write */
778 else if (cmd < 8)
779 wByteAMD(cs, cmd, LOBYTE(*ptr++));
780
781 else {
782 wByteAMD(cs, 0x00, cmd);
783 for (cnt = *ptr++; cnt > 0; cnt--)
784 wByteAMD(cs, 0x01, LOBYTE(*ptr++));
785 }
786 }
787}
788
789void __devinit
790setup_Amd7930(struct IsdnCardState *cs)
791{
792 INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs);
793 cs->dbusytimer.function = (void *) dbusy_timer_handler;
794 cs->dbusytimer.data = (long) cs;
795 init_timer(&cs->dbusytimer);
796}
diff --git a/drivers/isdn/hisax/amd7930_fn.h b/drivers/isdn/hisax/amd7930_fn.h
new file mode 100644
index 00000000000..e039c3a0f2a
--- /dev/null
+++ b/drivers/isdn/hisax/amd7930_fn.h
@@ -0,0 +1,37 @@
1/* 2001/10/02
2 *
3 * gerdes_amd7930.h Header-file included by
4 * gerdes_amd7930.c
5 *
6 * Author Christoph Ersfeld <info@formula-n.de>
7 * Formula-n Europe AG (www.formula-n.com)
8 * previously Gerdes AG
9 *
10 *
11 * This file is (c) under GNU PUBLIC LICENSE
12 */
13
14
15
16
17#define BYTE unsigned char
18#define WORD unsigned int
19#define rByteAMD(cs, reg) cs->readisac(cs, reg)
20#define wByteAMD(cs, reg, val) cs->writeisac(cs, reg, val)
21#define rWordAMD(cs, reg) ReadWordAmd7930(cs, reg)
22#define wWordAMD(cs, reg, val) WriteWordAmd7930(cs, reg, val)
23#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256))
24#define LOBYTE(w) ((unsigned char)(w & 0x00ff))
25
26#define AmdIrqOff(cs) cs->dc.amd7930.setIrqMask(cs, 0)
27#define AmdIrqOn(cs) cs->dc.amd7930.setIrqMask(cs, 1)
28
29#define AMD_CR 0x00
30#define AMD_DR 0x01
31
32
33#define DBUSY_TIMER_VALUE 80
34
35extern void Amd7930_interrupt(struct IsdnCardState *, unsigned char);
36extern void Amd7930_init(struct IsdnCardState *);
37extern void setup_Amd7930(struct IsdnCardState *);
diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c
new file mode 100644
index 00000000000..d30ce5b978c
--- /dev/null
+++ b/drivers/isdn/hisax/arcofi.c
@@ -0,0 +1,134 @@
1/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $
2 *
3 * Ansteuerung ARCOFI 2165
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include "hisax.h"
14#include "isdnl1.h"
15#include "isac.h"
16#include "arcofi.h"
17
18#define ARCOFI_TIMER_VALUE 20
19
20static void
21add_arcofi_timer(struct IsdnCardState *cs) {
22 if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
23 del_timer(&cs->dc.isac.arcofitimer);
24 }
25 init_timer(&cs->dc.isac.arcofitimer);
26 cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
27 add_timer(&cs->dc.isac.arcofitimer);
28}
29
30static void
31send_arcofi(struct IsdnCardState *cs) {
32 u_char val;
33
34 add_arcofi_timer(cs);
35 cs->dc.isac.mon_txp = 0;
36 cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
37 memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc);
38 switch(cs->dc.isac.arcofi_bc) {
39 case 0: break;
40 case 1: cs->dc.isac.mon_tx[1] |= 0x40;
41 break;
42 default: break;
43 }
44 cs->dc.isac.mocr &= 0x0f;
45 cs->dc.isac.mocr |= 0xa0;
46 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
47 val = cs->readisac(cs, ISAC_MOSR);
48 cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
49 cs->dc.isac.mocr |= 0x10;
50 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
51}
52
53int
54arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
55 if (cs->debug & L1_DEB_MONITOR) {
56 debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event);
57 }
58 if (event == ARCOFI_TIMEOUT) {
59 cs->dc.isac.arcofi_state = ARCOFI_NOP;
60 test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags);
61 wake_up(&cs->dc.isac.arcofi_wait);
62 return(1);
63 }
64 switch (cs->dc.isac.arcofi_state) {
65 case ARCOFI_NOP:
66 if (event == ARCOFI_START) {
67 cs->dc.isac.arcofi_list = data;
68 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
69 send_arcofi(cs);
70 }
71 break;
72 case ARCOFI_TRANSMIT:
73 if (event == ARCOFI_TX_END) {
74 if (cs->dc.isac.arcofi_list->receive) {
75 add_arcofi_timer(cs);
76 cs->dc.isac.arcofi_state = ARCOFI_RECEIVE;
77 } else {
78 if (cs->dc.isac.arcofi_list->next) {
79 cs->dc.isac.arcofi_list =
80 cs->dc.isac.arcofi_list->next;
81 send_arcofi(cs);
82 } else {
83 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
84 del_timer(&cs->dc.isac.arcofitimer);
85 }
86 cs->dc.isac.arcofi_state = ARCOFI_NOP;
87 wake_up(&cs->dc.isac.arcofi_wait);
88 }
89 }
90 }
91 break;
92 case ARCOFI_RECEIVE:
93 if (event == ARCOFI_RX_END) {
94 if (cs->dc.isac.arcofi_list->next) {
95 cs->dc.isac.arcofi_list =
96 cs->dc.isac.arcofi_list->next;
97 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
98 send_arcofi(cs);
99 } else {
100 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
101 del_timer(&cs->dc.isac.arcofitimer);
102 }
103 cs->dc.isac.arcofi_state = ARCOFI_NOP;
104 wake_up(&cs->dc.isac.arcofi_wait);
105 }
106 }
107 break;
108 default:
109 debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state);
110 return(2);
111 }
112 return(0);
113}
114
115static void
116arcofi_timer(struct IsdnCardState *cs) {
117 arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
118}
119
120void
121clear_arcofi(struct IsdnCardState *cs) {
122 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
123 del_timer(&cs->dc.isac.arcofitimer);
124 }
125}
126
127void
128init_arcofi(struct IsdnCardState *cs) {
129 cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
130 cs->dc.isac.arcofitimer.data = (long) cs;
131 init_timer(&cs->dc.isac.arcofitimer);
132 init_waitqueue_head(&cs->dc.isac.arcofi_wait);
133 test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
134}
diff --git a/drivers/isdn/hisax/arcofi.h b/drivers/isdn/hisax/arcofi.h
new file mode 100644
index 00000000000..00c44d3ce97
--- /dev/null
+++ b/drivers/isdn/hisax/arcofi.h
@@ -0,0 +1,27 @@
1/* $Id: arcofi.h,v 1.6.6.2 2001/09/23 22:24:46 kai Exp $
2 *
3 * Ansteuerung ARCOFI 2165
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#define ARCOFI_USE 1
14
15/* states */
16#define ARCOFI_NOP 0
17#define ARCOFI_TRANSMIT 1
18#define ARCOFI_RECEIVE 2
19/* events */
20#define ARCOFI_START 1
21#define ARCOFI_TX_END 2
22#define ARCOFI_RX_END 3
23#define ARCOFI_TIMEOUT 4
24
25extern int arcofi_fsm(struct IsdnCardState *cs, int event, void *data);
26extern void init_arcofi(struct IsdnCardState *cs);
27extern void clear_arcofi(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
new file mode 100644
index 00000000000..7546e2e4a94
--- /dev/null
+++ b/drivers/isdn/hisax/asuscom.c
@@ -0,0 +1,427 @@
1/* $Id: asuscom.c,v 1.14.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for information
12 *
13 */
14
15#include <linux/init.h>
16#include <linux/isapnp.h>
17#include "hisax.h"
18#include "isac.h"
19#include "ipac.h"
20#include "hscx.h"
21#include "isdnl1.h"
22
23extern const char *CardType[];
24
25const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
26
27#define byteout(addr,val) outb(val,addr)
28#define bytein(addr) inb(addr)
29
30#define ASUS_ISAC 0
31#define ASUS_HSCX 1
32#define ASUS_ADR 2
33#define ASUS_CTRL_U7 3
34#define ASUS_CTRL_POTS 5
35
36#define ASUS_IPAC_ALE 0
37#define ASUS_IPAC_DATA 1
38
39#define ASUS_ISACHSCX 1
40#define ASUS_IPAC 2
41
42/* CARD_ADR (Write) */
43#define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
44
45static inline u_char
46readreg(unsigned int ale, unsigned int adr, u_char off)
47{
48 register u_char ret;
49
50 byteout(ale, off);
51 ret = bytein(adr);
52 return (ret);
53}
54
55static inline void
56readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
57{
58 byteout(ale, off);
59 insb(adr, data, size);
60}
61
62
63static inline void
64writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
65{
66 byteout(ale, off);
67 byteout(adr, data);
68}
69
70static inline void
71writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
72{
73 byteout(ale, off);
74 outsb(adr, data, size);
75}
76
77/* Interface functions */
78
79static u_char
80ReadISAC(struct IsdnCardState *cs, u_char offset)
81{
82 return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset));
83}
84
85static void
86WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
87{
88 writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset, value);
89}
90
91static void
92ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
93{
94 readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
95}
96
97static void
98WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
99{
100 writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size);
101}
102
103static u_char
104ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
105{
106 return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
107}
108
109static void
110WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
111{
112 writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value);
113}
114
115static void
116ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
117{
118 readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
119}
120
121static void
122WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
123{
124 writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
125}
126
127static u_char
128ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
129{
130 return (readreg(cs->hw.asus.adr,
131 cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0)));
132}
133
134static void
135WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
136{
137 writereg(cs->hw.asus.adr,
138 cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value);
139}
140
141/*
142 * fast interrupt HSCX stuff goes here
143 */
144
145#define READHSCX(cs, nr, reg) readreg(cs->hw.asus.adr, \
146 cs->hw.asus.hscx, reg + (nr ? 0x40 : 0))
147#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.asus.adr, \
148 cs->hw.asus.hscx, reg + (nr ? 0x40 : 0), data)
149
150#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.asus.adr, \
151 cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
152
153#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.asus.adr, \
154 cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt)
155
156#include "hscx_irq.c"
157
158static irqreturn_t
159asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
160{
161 struct IsdnCardState *cs = dev_id;
162 u_char val;
163 u_long flags;
164
165 spin_lock_irqsave(&cs->lock, flags);
166 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
167 Start_HSCX:
168 if (val)
169 hscx_int_main(cs, val);
170 val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
171 Start_ISAC:
172 if (val)
173 isac_interrupt(cs, val);
174 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
175 if (val) {
176 if (cs->debug & L1_DEB_HSCX)
177 debugl1(cs, "HSCX IntStat after IntRoutine");
178 goto Start_HSCX;
179 }
180 val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
181 if (val) {
182 if (cs->debug & L1_DEB_ISAC)
183 debugl1(cs, "ISAC IntStat after IntRoutine");
184 goto Start_ISAC;
185 }
186 writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF);
187 writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF);
188 writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF);
189 writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
190 writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
191 writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
192 spin_unlock_irqrestore(&cs->lock, flags);
193 return IRQ_HANDLED;
194}
195
196static irqreturn_t
197asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
198{
199 struct IsdnCardState *cs = dev_id;
200 u_char ista, val, icnt = 5;
201 u_long flags;
202
203 spin_lock_irqsave(&cs->lock, flags);
204 ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
205Start_IPAC:
206 if (cs->debug & L1_DEB_IPAC)
207 debugl1(cs, "IPAC ISTA %02X", ista);
208 if (ista & 0x0f) {
209 val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
210 if (ista & 0x01)
211 val |= 0x01;
212 if (ista & 0x04)
213 val |= 0x02;
214 if (ista & 0x08)
215 val |= 0x04;
216 if (val)
217 hscx_int_main(cs, val);
218 }
219 if (ista & 0x20) {
220 val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
221 if (val) {
222 isac_interrupt(cs, val);
223 }
224 }
225 if (ista & 0x10) {
226 val = 0x01;
227 isac_interrupt(cs, val);
228 }
229 ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
230 if ((ista & 0x3f) && icnt) {
231 icnt--;
232 goto Start_IPAC;
233 }
234 if (!icnt)
235 printk(KERN_WARNING "ASUS IRQ LOOP\n");
236 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF);
237 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0);
238 spin_unlock_irqrestore(&cs->lock, flags);
239 return IRQ_HANDLED;
240}
241
242void
243release_io_asuscom(struct IsdnCardState *cs)
244{
245 int bytecnt = 8;
246
247 if (cs->hw.asus.cfg_reg)
248 release_region(cs->hw.asus.cfg_reg, bytecnt);
249}
250
251static void
252reset_asuscom(struct IsdnCardState *cs)
253{
254 if (cs->subtyp == ASUS_IPAC)
255 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
256 else
257 byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */
258 mdelay(10);
259 if (cs->subtyp == ASUS_IPAC)
260 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
261 else
262 byteout(cs->hw.asus.adr, 0); /* Reset Off */
263 mdelay(10);
264 if (cs->subtyp == ASUS_IPAC) {
265 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
266 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff);
267 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0);
268 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0);
269 writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12);
270 }
271}
272
273static int
274Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
275{
276 u_long flags;
277
278 switch (mt) {
279 case CARD_RESET:
280 spin_lock_irqsave(&cs->lock, flags);
281 reset_asuscom(cs);
282 spin_unlock_irqrestore(&cs->lock, flags);
283 return(0);
284 case CARD_RELEASE:
285 release_io_asuscom(cs);
286 return(0);
287 case CARD_INIT:
288 spin_lock_irqsave(&cs->lock, flags);
289 cs->debug |= L1_DEB_IPAC;
290 inithscxisac(cs, 3);
291 spin_unlock_irqrestore(&cs->lock, flags);
292 return(0);
293 case CARD_TEST:
294 return(0);
295 }
296 return(0);
297}
298
299#ifdef __ISAPNP__
300static struct isapnp_device_id asus_ids[] __initdata = {
301 { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
302 ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
303 (unsigned long) "Asus1688 PnP" },
304 { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
305 ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
306 (unsigned long) "Asus1690 PnP" },
307 { ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
308 ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
309 (unsigned long) "Isurf2 PnP" },
310 { ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
311 ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
312 (unsigned long) "Iscas TE320" },
313 { 0, }
314};
315
316static struct isapnp_device_id *ipid __initdata = &asus_ids[0];
317static struct pnp_card *pnp_c __devinitdata = NULL;
318#endif
319
320int __init
321setup_asuscom(struct IsdnCard *card)
322{
323 int bytecnt;
324 struct IsdnCardState *cs = card->cs;
325 u_char val;
326 char tmp[64];
327
328 strcpy(tmp, Asuscom_revision);
329 printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
330 if (cs->typ != ISDN_CTYPE_ASUSCOM)
331 return (0);
332#ifdef __ISAPNP__
333 if (!card->para[1] && isapnp_present()) {
334 struct pnp_dev *pnp_d;
335 while(ipid->card_vendor) {
336 if ((pnp_c = pnp_find_card(ipid->card_vendor,
337 ipid->card_device, pnp_c))) {
338 pnp_d = NULL;
339 if ((pnp_d = pnp_find_dev(pnp_c,
340 ipid->vendor, ipid->function, pnp_d))) {
341 int err;
342
343 printk(KERN_INFO "HiSax: %s detected\n",
344 (char *)ipid->driver_data);
345 pnp_disable_dev(pnp_d);
346 err = pnp_activate_dev(pnp_d);
347 if (err<0) {
348 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
349 __FUNCTION__, err);
350 return(0);
351 }
352 card->para[1] = pnp_port_start(pnp_d, 0);
353 card->para[0] = pnp_irq(pnp_d, 0);
354 if (!card->para[0] || !card->para[1]) {
355 printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
356 card->para[0], card->para[1]);
357 pnp_disable_dev(pnp_d);
358 return(0);
359 }
360 break;
361 } else {
362 printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
363 }
364 }
365 ipid++;
366 pnp_c = NULL;
367 }
368 if (!ipid->card_vendor) {
369 printk(KERN_INFO "AsusPnP: no ISAPnP card found\n");
370 return(0);
371 }
372 }
373#endif
374 bytecnt = 8;
375 cs->hw.asus.cfg_reg = card->para[1];
376 cs->irq = card->para[0];
377 if (!request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) {
378 printk(KERN_WARNING
379 "HiSax: %s config port %x-%x already in use\n",
380 CardType[card->typ],
381 cs->hw.asus.cfg_reg,
382 cs->hw.asus.cfg_reg + bytecnt);
383 return (0);
384 }
385 printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
386 cs->hw.asus.cfg_reg, cs->irq);
387 setup_isac(cs);
388 cs->BC_Read_Reg = &ReadHSCX;
389 cs->BC_Write_Reg = &WriteHSCX;
390 cs->BC_Send_Data = &hscx_fill_fifo;
391 cs->cardmsg = &Asus_card_msg;
392 val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE,
393 cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
394 if ((val == 1) || (val == 2)) {
395 cs->subtyp = ASUS_IPAC;
396 cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
397 cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
398 cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
399 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
400 cs->readisac = &ReadISAC_IPAC;
401 cs->writeisac = &WriteISAC_IPAC;
402 cs->readisacfifo = &ReadISACfifo_IPAC;
403 cs->writeisacfifo = &WriteISACfifo_IPAC;
404 cs->irq_func = &asuscom_interrupt_ipac;
405 printk(KERN_INFO "Asus: IPAC version %x\n", val);
406 } else {
407 cs->subtyp = ASUS_ISACHSCX;
408 cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
409 cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
410 cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
411 cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
412 cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
413 cs->readisac = &ReadISAC;
414 cs->writeisac = &WriteISAC;
415 cs->readisacfifo = &ReadISACfifo;
416 cs->writeisacfifo = &WriteISACfifo;
417 cs->irq_func = &asuscom_interrupt;
418 ISACVersion(cs, "ISDNLink:");
419 if (HscxVersion(cs, "ISDNLink:")) {
420 printk(KERN_WARNING
421 "ISDNLink: wrong HSCX versions check IO address\n");
422 release_io_asuscom(cs);
423 return (0);
424 }
425 }
426 return (1);
427}
diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
new file mode 100644
index 00000000000..8f028d42fd2
--- /dev/null
+++ b/drivers/isdn/hisax/avm_a1.c
@@ -0,0 +1,317 @@
1/* $Id: avm_a1.c,v 2.15.2.4 2004/01/13 21:46:03 keil Exp $
2 *
3 * low level stuff for AVM A1 (Fritz) isdn cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "isac.h"
16#include "hscx.h"
17#include "isdnl1.h"
18
19extern const char *CardType[];
20static const char *avm_revision = "$Revision: 2.15.2.4 $";
21
22#define AVM_A1_STAT_ISAC 0x01
23#define AVM_A1_STAT_HSCX 0x02
24#define AVM_A1_STAT_TIMER 0x04
25
26#define byteout(addr,val) outb(val,addr)
27#define bytein(addr) inb(addr)
28
29static inline u_char
30readreg(unsigned int adr, u_char off)
31{
32 return (bytein(adr + off));
33}
34
35static inline void
36writereg(unsigned int adr, u_char off, u_char data)
37{
38 byteout(adr + off, data);
39}
40
41
42static inline void
43read_fifo(unsigned int adr, u_char * data, int size)
44{
45 insb(adr, data, size);
46}
47
48static void
49write_fifo(unsigned int adr, u_char * data, int size)
50{
51 outsb(adr, data, size);
52}
53
54/* Interface functions */
55
56static u_char
57ReadISAC(struct IsdnCardState *cs, u_char offset)
58{
59 return (readreg(cs->hw.avm.isac, offset));
60}
61
62static void
63WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
64{
65 writereg(cs->hw.avm.isac, offset, value);
66}
67
68static void
69ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
70{
71 read_fifo(cs->hw.avm.isacfifo, data, size);
72}
73
74static void
75WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
76{
77 write_fifo(cs->hw.avm.isacfifo, data, size);
78}
79
80static u_char
81ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
82{
83 return (readreg(cs->hw.avm.hscx[hscx], offset));
84}
85
86static void
87WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
88{
89 writereg(cs->hw.avm.hscx[hscx], offset, value);
90}
91
92/*
93 * fast interrupt HSCX stuff goes here
94 */
95
96#define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg)
97#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data)
98#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
99#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt)
100
101#include "hscx_irq.c"
102
103static irqreturn_t
104avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
105{
106 struct IsdnCardState *cs = dev_id;
107 u_char val, sval;
108 u_long flags;
109
110 spin_lock_irqsave(&cs->lock, flags);
111 while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) {
112 if (!(sval & AVM_A1_STAT_TIMER)) {
113 byteout(cs->hw.avm.cfg_reg, 0x1E);
114 sval = bytein(cs->hw.avm.cfg_reg);
115 } else if (cs->debug & L1_DEB_INTSTAT)
116 debugl1(cs, "avm IntStatus %x", sval);
117 if (!(sval & AVM_A1_STAT_HSCX)) {
118 val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
119 if (val)
120 hscx_int_main(cs, val);
121 }
122 if (!(sval & AVM_A1_STAT_ISAC)) {
123 val = readreg(cs->hw.avm.isac, ISAC_ISTA);
124 if (val)
125 isac_interrupt(cs, val);
126 }
127 }
128 writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
129 writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
130 writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
131 writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
132 writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
133 writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
134 spin_unlock_irqrestore(&cs->lock, flags);
135 return IRQ_HANDLED;
136}
137
138inline static void
139release_ioregs(struct IsdnCardState *cs, int mask)
140{
141 release_region(cs->hw.avm.cfg_reg, 8);
142 if (mask & 1)
143 release_region(cs->hw.avm.isac + 32, 32);
144 if (mask & 2)
145 release_region(cs->hw.avm.isacfifo, 1);
146 if (mask & 4)
147 release_region(cs->hw.avm.hscx[0] + 32, 32);
148 if (mask & 8)
149 release_region(cs->hw.avm.hscxfifo[0], 1);
150 if (mask & 0x10)
151 release_region(cs->hw.avm.hscx[1] + 32, 32);
152 if (mask & 0x20)
153 release_region(cs->hw.avm.hscxfifo[1], 1);
154}
155
156static int
157AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
158{
159 u_long flags;
160
161 switch (mt) {
162 case CARD_RESET:
163 return(0);
164 case CARD_RELEASE:
165 release_ioregs(cs, 0x3f);
166 return(0);
167 case CARD_INIT:
168 spin_lock_irqsave(&cs->lock, flags);
169 inithscxisac(cs, 1);
170 byteout(cs->hw.avm.cfg_reg, 0x16);
171 byteout(cs->hw.avm.cfg_reg, 0x1E);
172 inithscxisac(cs, 2);
173 spin_unlock_irqrestore(&cs->lock, flags);
174 return(0);
175 case CARD_TEST:
176 return(0);
177 }
178 return(0);
179}
180
181int __init
182setup_avm_a1(struct IsdnCard *card)
183{
184 u_char val;
185 struct IsdnCardState *cs = card->cs;
186 char tmp[64];
187
188 strcpy(tmp, avm_revision);
189 printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
190 if (cs->typ != ISDN_CTYPE_A1)
191 return (0);
192
193 cs->hw.avm.cfg_reg = card->para[1] + 0x1800;
194 cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20;
195 cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20;
196 cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20;
197 cs->hw.avm.isacfifo = card->para[1] + 0x1000;
198 cs->hw.avm.hscxfifo[0] = card->para[1];
199 cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800;
200 cs->irq = card->para[0];
201 if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) {
202 printk(KERN_WARNING
203 "HiSax: %s config port %x-%x already in use\n",
204 CardType[card->typ],
205 cs->hw.avm.cfg_reg,
206 cs->hw.avm.cfg_reg + 8);
207 return (0);
208 }
209 if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) {
210 printk(KERN_WARNING
211 "HiSax: %s isac ports %x-%x already in use\n",
212 CardType[cs->typ],
213 cs->hw.avm.isac + 32,
214 cs->hw.avm.isac + 64);
215 release_ioregs(cs, 0);
216 return (0);
217 }
218 if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) {
219 printk(KERN_WARNING
220 "HiSax: %s isac fifo port %x already in use\n",
221 CardType[cs->typ],
222 cs->hw.avm.isacfifo);
223 release_ioregs(cs, 1);
224 return (0);
225 }
226 if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) {
227 printk(KERN_WARNING
228 "HiSax: %s hscx A ports %x-%x already in use\n",
229 CardType[cs->typ],
230 cs->hw.avm.hscx[0] + 32,
231 cs->hw.avm.hscx[0] + 64);
232 release_ioregs(cs, 3);
233 return (0);
234 }
235 if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) {
236 printk(KERN_WARNING
237 "HiSax: %s hscx A fifo port %x already in use\n",
238 CardType[cs->typ],
239 cs->hw.avm.hscxfifo[0]);
240 release_ioregs(cs, 7);
241 return (0);
242 }
243 if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) {
244 printk(KERN_WARNING
245 "HiSax: %s hscx B ports %x-%x already in use\n",
246 CardType[cs->typ],
247 cs->hw.avm.hscx[1] + 32,
248 cs->hw.avm.hscx[1] + 64);
249 release_ioregs(cs, 0xf);
250 return (0);
251 }
252 if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) {
253 printk(KERN_WARNING
254 "HiSax: %s hscx B fifo port %x already in use\n",
255 CardType[cs->typ],
256 cs->hw.avm.hscxfifo[1]);
257 release_ioregs(cs, 0x1f);
258 return (0);
259 }
260 byteout(cs->hw.avm.cfg_reg, 0x0);
261 HZDELAY(HZ / 5 + 1);
262 byteout(cs->hw.avm.cfg_reg, 0x1);
263 HZDELAY(HZ / 5 + 1);
264 byteout(cs->hw.avm.cfg_reg, 0x0);
265 HZDELAY(HZ / 5 + 1);
266 val = cs->irq;
267 if (val == 9)
268 val = 2;
269 byteout(cs->hw.avm.cfg_reg + 1, val);
270 HZDELAY(HZ / 5 + 1);
271 byteout(cs->hw.avm.cfg_reg, 0x0);
272 HZDELAY(HZ / 5 + 1);
273
274 val = bytein(cs->hw.avm.cfg_reg);
275 printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
276 cs->hw.avm.cfg_reg, val);
277 val = bytein(cs->hw.avm.cfg_reg + 3);
278 printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
279 cs->hw.avm.cfg_reg + 3, val);
280 val = bytein(cs->hw.avm.cfg_reg + 2);
281 printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
282 cs->hw.avm.cfg_reg + 2, val);
283 val = bytein(cs->hw.avm.cfg_reg);
284 printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
285 cs->hw.avm.cfg_reg, val);
286
287 printk(KERN_INFO
288 "HiSax: %s config irq:%d cfg:0x%X\n",
289 CardType[cs->typ], cs->irq,
290 cs->hw.avm.cfg_reg);
291 printk(KERN_INFO
292 "HiSax: isac:0x%X/0x%X\n",
293 cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
294 printk(KERN_INFO
295 "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n",
296 cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
297 cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
298
299 cs->readisac = &ReadISAC;
300 cs->writeisac = &WriteISAC;
301 cs->readisacfifo = &ReadISACfifo;
302 cs->writeisacfifo = &WriteISACfifo;
303 cs->BC_Read_Reg = &ReadHSCX;
304 cs->BC_Write_Reg = &WriteHSCX;
305 cs->BC_Send_Data = &hscx_fill_fifo;
306 setup_isac(cs);
307 cs->cardmsg = &AVM_card_msg;
308 cs->irq_func = &avm_a1_interrupt;
309 ISACVersion(cs, "AVM A1:");
310 if (HscxVersion(cs, "AVM A1:")) {
311 printk(KERN_WARNING
312 "AVM A1: wrong HSCX versions check IO address\n");
313 release_ioregs(cs, 0x3f);
314 return (0);
315 }
316 return (1);
317}
diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
new file mode 100644
index 00000000000..d643bb32ad0
--- /dev/null
+++ b/drivers/isdn/hisax/avm_a1p.c
@@ -0,0 +1,268 @@
1/* $Id: avm_a1p.c,v 2.9.2.5 2004/01/24 20:47:19 keil Exp $
2 *
3 * low level stuff for the following AVM cards:
4 * A1 PCMCIA
5 * FRITZ!Card PCMCIA
6 * FRITZ!Card PCMCIA 2.0
7 *
8 * Author Carsten Paeth
9 * Copyright by Carsten Paeth <calle@calle.de>
10 *
11 * This software may be used and distributed according to the terms
12 * of the GNU General Public License, incorporated herein by reference.
13 *
14 */
15
16#include <linux/init.h>
17#include "hisax.h"
18#include "isac.h"
19#include "hscx.h"
20#include "isdnl1.h"
21
22/* register offsets */
23#define ADDRREG_OFFSET 0x02
24#define DATAREG_OFFSET 0x03
25#define ASL0_OFFSET 0x04
26#define ASL1_OFFSET 0x05
27#define MODREG_OFFSET 0x06
28#define VERREG_OFFSET 0x07
29
30/* address offsets */
31#define ISAC_FIFO_OFFSET 0x00
32#define ISAC_REG_OFFSET 0x20
33#define HSCX_CH_DIFF 0x40
34#define HSCX_FIFO_OFFSET 0x80
35#define HSCX_REG_OFFSET 0xa0
36
37/* read bits ASL0 */
38#define ASL0_R_TIMER 0x10 /* active low */
39#define ASL0_R_ISAC 0x20 /* active low */
40#define ASL0_R_HSCX 0x40 /* active low */
41#define ASL0_R_TESTBIT 0x80
42#define ASL0_R_IRQPENDING (ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
43
44/* write bits ASL0 */
45#define ASL0_W_RESET 0x01
46#define ASL0_W_TDISABLE 0x02
47#define ASL0_W_TRESET 0x04
48#define ASL0_W_IRQENABLE 0x08
49#define ASL0_W_TESTBIT 0x80
50
51/* write bits ASL1 */
52#define ASL1_W_LED0 0x10
53#define ASL1_W_LED1 0x20
54#define ASL1_W_ENABLE_S0 0xC0
55
56#define byteout(addr,val) outb(val,addr)
57#define bytein(addr) inb(addr)
58
59static const char *avm_revision = "$Revision: 2.9.2.5 $";
60
61static inline u_char
62ReadISAC(struct IsdnCardState *cs, u_char offset)
63{
64 u_char ret;
65
66 offset -= 0x20;
67 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
68 ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
69 return ret;
70}
71
72static inline void
73WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
74{
75 offset -= 0x20;
76 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
77 byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
78}
79
80static inline void
81ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
82{
83 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
84 insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
85}
86
87static inline void
88WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
89{
90 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
91 outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
92}
93
94static inline u_char
95ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
96{
97 u_char ret;
98
99 offset -= 0x20;
100 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
101 HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
102 ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
103 return ret;
104}
105
106static inline void
107WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
108{
109 offset -= 0x20;
110 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
111 HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
112 byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
113}
114
115static inline void
116ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
117{
118 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
119 HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
120 insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
121}
122
123static inline void
124WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
125{
126 byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
127 HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
128 outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
129}
130
131/*
132 * fast interrupt HSCX stuff goes here
133 */
134
135#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
136#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
137#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
138#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
139
140#include "hscx_irq.c"
141
142static irqreturn_t
143avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
144{
145 struct IsdnCardState *cs = dev_id;
146 u_char val, sval;
147 u_long flags;
148
149 spin_lock_irqsave(&cs->lock, flags);
150 while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
151 if (cs->debug & L1_DEB_INTSTAT)
152 debugl1(cs, "avm IntStatus %x", sval);
153 if (sval & ASL0_R_HSCX) {
154 val = ReadHSCX(cs, 1, HSCX_ISTA);
155 if (val)
156 hscx_int_main(cs, val);
157 }
158 if (sval & ASL0_R_ISAC) {
159 val = ReadISAC(cs, ISAC_ISTA);
160 if (val)
161 isac_interrupt(cs, val);
162 }
163 }
164 WriteHSCX(cs, 0, HSCX_MASK, 0xff);
165 WriteHSCX(cs, 1, HSCX_MASK, 0xff);
166 WriteISAC(cs, ISAC_MASK, 0xff);
167 WriteISAC(cs, ISAC_MASK, 0x00);
168 WriteHSCX(cs, 0, HSCX_MASK, 0x00);
169 WriteHSCX(cs, 1, HSCX_MASK, 0x00);
170 spin_unlock_irqrestore(&cs->lock, flags);
171 return IRQ_HANDLED;
172}
173
174static int
175AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
176{
177 u_long flags;
178
179 switch (mt) {
180 case CARD_RESET:
181 spin_lock_irqsave(&cs->lock, flags);
182 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
183 HZDELAY(HZ / 5 + 1);
184 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
185 HZDELAY(HZ / 5 + 1);
186 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
187 spin_unlock_irqrestore(&cs->lock, flags);
188 return 0;
189
190 case CARD_RELEASE:
191 /* free_irq is done in HiSax_closecard(). */
192 /* free_irq(cs->irq, cs); */
193 return 0;
194
195 case CARD_INIT:
196 spin_lock_irqsave(&cs->lock, flags);
197 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
198 clear_pending_isac_ints(cs);
199 clear_pending_hscx_ints(cs);
200 inithscxisac(cs, 1);
201 inithscxisac(cs, 2);
202 spin_unlock_irqrestore(&cs->lock, flags);
203 return 0;
204
205 case CARD_TEST:
206 /* we really don't need it for the PCMCIA Version */
207 return 0;
208
209 default:
210 /* all card drivers ignore others, so we do the same */
211 return 0;
212 }
213 return 0;
214}
215
216int
217setup_avm_a1_pcmcia(struct IsdnCard *card)
218{
219 u_char model, vers;
220 struct IsdnCardState *cs = card->cs;
221 char tmp[64];
222
223
224 strcpy(tmp, avm_revision);
225 printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
226 HiSax_getrev(tmp));
227 if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
228 return (0);
229
230 cs->hw.avm.cfg_reg = card->para[1];
231 cs->irq = card->para[0];
232
233
234 byteout(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
235 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
236 HZDELAY(HZ / 5 + 1);
237 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
238 HZDELAY(HZ / 5 + 1);
239 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
240
241 byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET);
242
243 model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET);
244 vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
245
246 printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
247 cs->hw.avm.cfg_reg, cs->irq, model, vers);
248
249 setup_isac(cs);
250 cs->readisac = &ReadISAC;
251 cs->writeisac = &WriteISAC;
252 cs->readisacfifo = &ReadISACfifo;
253 cs->writeisacfifo = &WriteISACfifo;
254 cs->BC_Read_Reg = &ReadHSCX;
255 cs->BC_Write_Reg = &WriteHSCX;
256 cs->BC_Send_Data = &hscx_fill_fifo;
257 cs->cardmsg = &AVM_card_msg;
258 cs->irq_flags = SA_SHIRQ;
259 cs->irq_func = &avm_a1p_interrupt;
260
261 ISACVersion(cs, "AVM A1 PCMCIA:");
262 if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
263 printk(KERN_WARNING
264 "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
265 return (0);
266 }
267 return (1);
268}
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
new file mode 100644
index 00000000000..6fcb2cf7b0b
--- /dev/null
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -0,0 +1,865 @@
1/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $
2 *
3 * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * Thanks to AVM, Berlin for information
12 *
13 */
14
15#include <linux/config.h>
16#include <linux/init.h>
17#include "hisax.h"
18#include "isac.h"
19#include "isdnl1.h"
20#include <linux/pci.h>
21#include <linux/isapnp.h>
22#include <linux/interrupt.h>
23
24extern const char *CardType[];
25static const char *avm_pci_rev = "$Revision: 1.29.2.4 $";
26
27#define AVM_FRITZ_PCI 1
28#define AVM_FRITZ_PNP 2
29
30#define HDLC_FIFO 0x0
31#define HDLC_STATUS 0x4
32
33#define AVM_HDLC_1 0x00
34#define AVM_HDLC_2 0x01
35#define AVM_ISAC_FIFO 0x02
36#define AVM_ISAC_REG_LOW 0x04
37#define AVM_ISAC_REG_HIGH 0x06
38
39#define AVM_STATUS0_IRQ_ISAC 0x01
40#define AVM_STATUS0_IRQ_HDLC 0x02
41#define AVM_STATUS0_IRQ_TIMER 0x04
42#define AVM_STATUS0_IRQ_MASK 0x07
43
44#define AVM_STATUS0_RESET 0x01
45#define AVM_STATUS0_DIS_TIMER 0x02
46#define AVM_STATUS0_RES_TIMER 0x04
47#define AVM_STATUS0_ENA_IRQ 0x08
48#define AVM_STATUS0_TESTBIT 0x10
49
50#define AVM_STATUS1_INT_SEL 0x0f
51#define AVM_STATUS1_ENA_IOM 0x80
52
53#define HDLC_MODE_ITF_FLG 0x01
54#define HDLC_MODE_TRANS 0x02
55#define HDLC_MODE_CCR_7 0x04
56#define HDLC_MODE_CCR_16 0x08
57#define HDLC_MODE_TESTLOOP 0x80
58
59#define HDLC_INT_XPR 0x80
60#define HDLC_INT_XDU 0x40
61#define HDLC_INT_RPR 0x20
62#define HDLC_INT_MASK 0xE0
63
64#define HDLC_STAT_RME 0x01
65#define HDLC_STAT_RDO 0x10
66#define HDLC_STAT_CRCVFRRAB 0x0E
67#define HDLC_STAT_CRCVFR 0x06
68#define HDLC_STAT_RML_MASK 0x3f00
69
70#define HDLC_CMD_XRS 0x80
71#define HDLC_CMD_XME 0x01
72#define HDLC_CMD_RRS 0x20
73#define HDLC_CMD_XML_MASK 0x3f00
74
75
76/* Interface functions */
77
78static u_char
79ReadISAC(struct IsdnCardState *cs, u_char offset)
80{
81 register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
82 register u_char val;
83
84 outb(idx, cs->hw.avm.cfg_reg + 4);
85 val = inb(cs->hw.avm.isac + (offset & 0xf));
86 return (val);
87}
88
89static void
90WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
91{
92 register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
93
94 outb(idx, cs->hw.avm.cfg_reg + 4);
95 outb(value, cs->hw.avm.isac + (offset & 0xf));
96}
97
98static void
99ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
100{
101 outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
102 insb(cs->hw.avm.isac, data, size);
103}
104
105static void
106WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
107{
108 outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
109 outsb(cs->hw.avm.isac, data, size);
110}
111
112static inline u_int
113ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset)
114{
115 register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
116 register u_int val;
117
118 outl(idx, cs->hw.avm.cfg_reg + 4);
119 val = inl(cs->hw.avm.isac + offset);
120 return (val);
121}
122
123static inline void
124WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value)
125{
126 register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
127
128 outl(idx, cs->hw.avm.cfg_reg + 4);
129 outl(value, cs->hw.avm.isac + offset);
130}
131
132static inline u_char
133ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset)
134{
135 register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
136 register u_char val;
137
138 outb(idx, cs->hw.avm.cfg_reg + 4);
139 val = inb(cs->hw.avm.isac + offset);
140 return (val);
141}
142
143static inline void
144WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
145{
146 register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
147
148 outb(idx, cs->hw.avm.cfg_reg + 4);
149 outb(value, cs->hw.avm.isac + offset);
150}
151
152static u_char
153ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset)
154{
155 return(0xff & ReadHDLCPCI(cs, chan, offset));
156}
157
158static void
159WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
160{
161 WriteHDLCPCI(cs, chan, offset, value);
162}
163
164static inline
165struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
166{
167 if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
168 return(&cs->bcs[0]);
169 else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
170 return(&cs->bcs[1]);
171 else
172 return(NULL);
173}
174
175void
176write_ctrl(struct BCState *bcs, int which) {
177
178 if (bcs->cs->debug & L1_DEB_HSCX)
179 debugl1(bcs->cs, "hdlc %c wr%x ctrl %x",
180 'A' + bcs->channel, which, bcs->hw.hdlc.ctrl.ctrl);
181 if (bcs->cs->subtyp == AVM_FRITZ_PCI) {
182 WriteHDLCPCI(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl.ctrl);
183 } else {
184 if (which & 4)
185 WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 2,
186 bcs->hw.hdlc.ctrl.sr.mode);
187 if (which & 2)
188 WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 1,
189 bcs->hw.hdlc.ctrl.sr.xml);
190 if (which & 1)
191 WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS,
192 bcs->hw.hdlc.ctrl.sr.cmd);
193 }
194}
195
196void
197modehdlc(struct BCState *bcs, int mode, int bc)
198{
199 struct IsdnCardState *cs = bcs->cs;
200 int hdlc = bcs->channel;
201
202 if (cs->debug & L1_DEB_HSCX)
203 debugl1(cs, "hdlc %c mode %d --> %d ichan %d --> %d",
204 'A' + hdlc, bcs->mode, mode, hdlc, bc);
205 bcs->hw.hdlc.ctrl.ctrl = 0;
206 switch (mode) {
207 case (-1): /* used for init */
208 bcs->mode = 1;
209 bcs->channel = bc;
210 bc = 0;
211 case (L1_MODE_NULL):
212 if (bcs->mode == L1_MODE_NULL)
213 return;
214 bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
215 bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
216 write_ctrl(bcs, 5);
217 bcs->mode = L1_MODE_NULL;
218 bcs->channel = bc;
219 break;
220 case (L1_MODE_TRANS):
221 bcs->mode = mode;
222 bcs->channel = bc;
223 bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
224 bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
225 write_ctrl(bcs, 5);
226 bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
227 write_ctrl(bcs, 1);
228 bcs->hw.hdlc.ctrl.sr.cmd = 0;
229 schedule_event(bcs, B_XMTBUFREADY);
230 break;
231 case (L1_MODE_HDLC):
232 bcs->mode = mode;
233 bcs->channel = bc;
234 bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
235 bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_ITF_FLG;
236 write_ctrl(bcs, 5);
237 bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
238 write_ctrl(bcs, 1);
239 bcs->hw.hdlc.ctrl.sr.cmd = 0;
240 schedule_event(bcs, B_XMTBUFREADY);
241 break;
242 }
243}
244
245static inline void
246hdlc_empty_fifo(struct BCState *bcs, int count)
247{
248 register u_int *ptr;
249 u_char *p;
250 u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
251 int cnt=0;
252 struct IsdnCardState *cs = bcs->cs;
253
254 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
255 debugl1(cs, "hdlc_empty_fifo %d", count);
256 if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
257 if (cs->debug & L1_DEB_WARN)
258 debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
259 return;
260 }
261 p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
262 ptr = (u_int *)p;
263 bcs->hw.hdlc.rcvidx += count;
264 if (cs->subtyp == AVM_FRITZ_PCI) {
265 outl(idx, cs->hw.avm.cfg_reg + 4);
266 while (cnt < count) {
267#ifdef __powerpc__
268#ifdef CONFIG_APUS
269 *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
270#else
271 *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
272#endif /* CONFIG_APUS */
273#else
274 *ptr++ = inl(cs->hw.avm.isac);
275#endif /* __powerpc__ */
276 cnt += 4;
277 }
278 } else {
279 outb(idx, cs->hw.avm.cfg_reg + 4);
280 while (cnt < count) {
281 *p++ = inb(cs->hw.avm.isac);
282 cnt++;
283 }
284 }
285 if (cs->debug & L1_DEB_HSCX_FIFO) {
286 char *t = bcs->blog;
287
288 if (cs->subtyp == AVM_FRITZ_PNP)
289 p = (u_char *) ptr;
290 t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
291 bcs->channel ? 'B' : 'A', count);
292 QuickHex(t, p, count);
293 debugl1(cs, bcs->blog);
294 }
295}
296
297static inline void
298hdlc_fill_fifo(struct BCState *bcs)
299{
300 struct IsdnCardState *cs = bcs->cs;
301 int count, cnt =0;
302 int fifo_size = 32;
303 u_char *p;
304 u_int *ptr;
305
306 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
307 debugl1(cs, "hdlc_fill_fifo");
308 if (!bcs->tx_skb)
309 return;
310 if (bcs->tx_skb->len <= 0)
311 return;
312
313 bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
314 if (bcs->tx_skb->len > fifo_size) {
315 count = fifo_size;
316 } else {
317 count = bcs->tx_skb->len;
318 if (bcs->mode != L1_MODE_TRANS)
319 bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
320 }
321 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
322 debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
323 p = bcs->tx_skb->data;
324 ptr = (u_int *)p;
325 skb_pull(bcs->tx_skb, count);
326 bcs->tx_cnt -= count;
327 bcs->hw.hdlc.count += count;
328 bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
329 write_ctrl(bcs, 3); /* sets the correct index too */
330 if (cs->subtyp == AVM_FRITZ_PCI) {
331 while (cnt<count) {
332#ifdef __powerpc__
333#ifdef CONFIG_APUS
334 out_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
335#else
336 out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
337#endif /* CONFIG_APUS */
338#else
339 outl(*ptr++, cs->hw.avm.isac);
340#endif /* __powerpc__ */
341 cnt += 4;
342 }
343 } else {
344 while (cnt<count) {
345 outb(*p++, cs->hw.avm.isac);
346 cnt++;
347 }
348 }
349 if (cs->debug & L1_DEB_HSCX_FIFO) {
350 char *t = bcs->blog;
351
352 if (cs->subtyp == AVM_FRITZ_PNP)
353 p = (u_char *) ptr;
354 t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
355 bcs->channel ? 'B' : 'A', count);
356 QuickHex(t, p, count);
357 debugl1(cs, bcs->blog);
358 }
359}
360
361static inline void
362HDLC_irq(struct BCState *bcs, u_int stat) {
363 int len;
364 struct sk_buff *skb;
365
366 if (bcs->cs->debug & L1_DEB_HSCX)
367 debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
368 if (stat & HDLC_INT_RPR) {
369 if (stat & HDLC_STAT_RDO) {
370 if (bcs->cs->debug & L1_DEB_HSCX)
371 debugl1(bcs->cs, "RDO");
372 else
373 debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
374 bcs->hw.hdlc.ctrl.sr.xml = 0;
375 bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_RRS;
376 write_ctrl(bcs, 1);
377 bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
378 write_ctrl(bcs, 1);
379 bcs->hw.hdlc.rcvidx = 0;
380 } else {
381 if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
382 len = 32;
383 hdlc_empty_fifo(bcs, len);
384 if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
385 if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
386 (bcs->mode == L1_MODE_TRANS)) {
387 if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
388 printk(KERN_WARNING "HDLC: receive out of memory\n");
389 else {
390 memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
391 bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
392 skb_queue_tail(&bcs->rqueue, skb);
393 }
394 bcs->hw.hdlc.rcvidx = 0;
395 schedule_event(bcs, B_RCVBUFREADY);
396 } else {
397 if (bcs->cs->debug & L1_DEB_HSCX)
398 debugl1(bcs->cs, "invalid frame");
399 else
400 debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
401 bcs->hw.hdlc.rcvidx = 0;
402 }
403 }
404 }
405 }
406 if (stat & HDLC_INT_XDU) {
407 /* Here we lost an TX interrupt, so
408 * restart transmitting the whole frame.
409 */
410 if (bcs->tx_skb) {
411 skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
412 bcs->tx_cnt += bcs->hw.hdlc.count;
413 bcs->hw.hdlc.count = 0;
414 if (bcs->cs->debug & L1_DEB_WARN)
415 debugl1(bcs->cs, "ch%d XDU", bcs->channel);
416 } else if (bcs->cs->debug & L1_DEB_WARN)
417 debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);
418 bcs->hw.hdlc.ctrl.sr.xml = 0;
419 bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
420 write_ctrl(bcs, 1);
421 bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
422 write_ctrl(bcs, 1);
423 hdlc_fill_fifo(bcs);
424 } else if (stat & HDLC_INT_XPR) {
425 if (bcs->tx_skb) {
426 if (bcs->tx_skb->len) {
427 hdlc_fill_fifo(bcs);
428 return;
429 } else {
430 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
431 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
432 u_long flags;
433 spin_lock_irqsave(&bcs->aclock, flags);
434 bcs->ackcnt += bcs->hw.hdlc.count;
435 spin_unlock_irqrestore(&bcs->aclock, flags);
436 schedule_event(bcs, B_ACKPENDING);
437 }
438 dev_kfree_skb_irq(bcs->tx_skb);
439 bcs->hw.hdlc.count = 0;
440 bcs->tx_skb = NULL;
441 }
442 }
443 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
444 bcs->hw.hdlc.count = 0;
445 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
446 hdlc_fill_fifo(bcs);
447 } else {
448 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
449 schedule_event(bcs, B_XMTBUFREADY);
450 }
451 }
452}
453
454inline void
455HDLC_irq_main(struct IsdnCardState *cs)
456{
457 u_int stat;
458 struct BCState *bcs;
459
460 if (cs->subtyp == AVM_FRITZ_PCI) {
461 stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);
462 } else {
463 stat = ReadHDLCPnP(cs, 0, HDLC_STATUS);
464 if (stat & HDLC_INT_RPR)
465 stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS+1))<<8;
466 }
467 if (stat & HDLC_INT_MASK) {
468 if (!(bcs = Sel_BCS(cs, 0))) {
469 if (cs->debug)
470 debugl1(cs, "hdlc spurious channel 0 IRQ");
471 } else
472 HDLC_irq(bcs, stat);
473 }
474 if (cs->subtyp == AVM_FRITZ_PCI) {
475 stat = ReadHDLCPCI(cs, 1, HDLC_STATUS);
476 } else {
477 stat = ReadHDLCPnP(cs, 1, HDLC_STATUS);
478 if (stat & HDLC_INT_RPR)
479 stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS+1))<<8;
480 }
481 if (stat & HDLC_INT_MASK) {
482 if (!(bcs = Sel_BCS(cs, 1))) {
483 if (cs->debug)
484 debugl1(cs, "hdlc spurious channel 1 IRQ");
485 } else
486 HDLC_irq(bcs, stat);
487 }
488}
489
490void
491hdlc_l2l1(struct PStack *st, int pr, void *arg)
492{
493 struct BCState *bcs = st->l1.bcs;
494 struct sk_buff *skb = arg;
495 u_long flags;
496
497 switch (pr) {
498 case (PH_DATA | REQUEST):
499 spin_lock_irqsave(&bcs->cs->lock, flags);
500 if (bcs->tx_skb) {
501 skb_queue_tail(&bcs->squeue, skb);
502 } else {
503 bcs->tx_skb = skb;
504 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
505 bcs->hw.hdlc.count = 0;
506 bcs->cs->BC_Send_Data(bcs);
507 }
508 spin_unlock_irqrestore(&bcs->cs->lock, flags);
509 break;
510 case (PH_PULL | INDICATION):
511 spin_lock_irqsave(&bcs->cs->lock, flags);
512 if (bcs->tx_skb) {
513 printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
514 } else {
515 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
516 bcs->tx_skb = skb;
517 bcs->hw.hdlc.count = 0;
518 bcs->cs->BC_Send_Data(bcs);
519 }
520 spin_unlock_irqrestore(&bcs->cs->lock, flags);
521 break;
522 case (PH_PULL | REQUEST):
523 if (!bcs->tx_skb) {
524 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
525 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
526 } else
527 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
528 break;
529 case (PH_ACTIVATE | REQUEST):
530 spin_lock_irqsave(&bcs->cs->lock, flags);
531 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
532 modehdlc(bcs, st->l1.mode, st->l1.bc);
533 spin_unlock_irqrestore(&bcs->cs->lock, flags);
534 l1_msg_b(st, pr, arg);
535 break;
536 case (PH_DEACTIVATE | REQUEST):
537 l1_msg_b(st, pr, arg);
538 break;
539 case (PH_DEACTIVATE | CONFIRM):
540 spin_lock_irqsave(&bcs->cs->lock, flags);
541 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
542 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
543 modehdlc(bcs, 0, st->l1.bc);
544 spin_unlock_irqrestore(&bcs->cs->lock, flags);
545 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
546 break;
547 }
548}
549
550void
551close_hdlcstate(struct BCState *bcs)
552{
553 modehdlc(bcs, 0, 0);
554 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
555 if (bcs->hw.hdlc.rcvbuf) {
556 kfree(bcs->hw.hdlc.rcvbuf);
557 bcs->hw.hdlc.rcvbuf = NULL;
558 }
559 if (bcs->blog) {
560 kfree(bcs->blog);
561 bcs->blog = NULL;
562 }
563 skb_queue_purge(&bcs->rqueue);
564 skb_queue_purge(&bcs->squeue);
565 if (bcs->tx_skb) {
566 dev_kfree_skb_any(bcs->tx_skb);
567 bcs->tx_skb = NULL;
568 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
569 }
570 }
571}
572
573int
574open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
575{
576 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
577 if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
578 printk(KERN_WARNING
579 "HiSax: No memory for hdlc.rcvbuf\n");
580 return (1);
581 }
582 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
583 printk(KERN_WARNING
584 "HiSax: No memory for bcs->blog\n");
585 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
586 kfree(bcs->hw.hdlc.rcvbuf);
587 bcs->hw.hdlc.rcvbuf = NULL;
588 return (2);
589 }
590 skb_queue_head_init(&bcs->rqueue);
591 skb_queue_head_init(&bcs->squeue);
592 }
593 bcs->tx_skb = NULL;
594 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
595 bcs->event = 0;
596 bcs->hw.hdlc.rcvidx = 0;
597 bcs->tx_cnt = 0;
598 return (0);
599}
600
601int
602setstack_hdlc(struct PStack *st, struct BCState *bcs)
603{
604 bcs->channel = st->l1.bc;
605 if (open_hdlcstate(st->l1.hardware, bcs))
606 return (-1);
607 st->l1.bcs = bcs;
608 st->l2.l2l1 = hdlc_l2l1;
609 setstack_manager(st);
610 bcs->st = st;
611 setstack_l1_B(st);
612 return (0);
613}
614
615void __init
616clear_pending_hdlc_ints(struct IsdnCardState *cs)
617{
618 u_int val;
619
620 if (cs->subtyp == AVM_FRITZ_PCI) {
621 val = ReadHDLCPCI(cs, 0, HDLC_STATUS);
622 debugl1(cs, "HDLC 1 STA %x", val);
623 val = ReadHDLCPCI(cs, 1, HDLC_STATUS);
624 debugl1(cs, "HDLC 2 STA %x", val);
625 } else {
626 val = ReadHDLCPnP(cs, 0, HDLC_STATUS);
627 debugl1(cs, "HDLC 1 STA %x", val);
628 val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1);
629 debugl1(cs, "HDLC 1 RML %x", val);
630 val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2);
631 debugl1(cs, "HDLC 1 MODE %x", val);
632 val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3);
633 debugl1(cs, "HDLC 1 VIN %x", val);
634 val = ReadHDLCPnP(cs, 1, HDLC_STATUS);
635 debugl1(cs, "HDLC 2 STA %x", val);
636 val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1);
637 debugl1(cs, "HDLC 2 RML %x", val);
638 val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2);
639 debugl1(cs, "HDLC 2 MODE %x", val);
640 val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);
641 debugl1(cs, "HDLC 2 VIN %x", val);
642 }
643}
644
645void __init
646inithdlc(struct IsdnCardState *cs)
647{
648 cs->bcs[0].BC_SetStack = setstack_hdlc;
649 cs->bcs[1].BC_SetStack = setstack_hdlc;
650 cs->bcs[0].BC_Close = close_hdlcstate;
651 cs->bcs[1].BC_Close = close_hdlcstate;
652 modehdlc(cs->bcs, -1, 0);
653 modehdlc(cs->bcs + 1, -1, 1);
654}
655
656static irqreturn_t
657avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
658{
659 struct IsdnCardState *cs = dev_id;
660 u_long flags;
661 u_char val;
662 u_char sval;
663
664 spin_lock_irqsave(&cs->lock, flags);
665 sval = inb(cs->hw.avm.cfg_reg + 2);
666 if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
667 /* possible a shared IRQ reqest */
668 spin_unlock_irqrestore(&cs->lock, flags);
669 return IRQ_NONE;
670 }
671 if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
672 val = ReadISAC(cs, ISAC_ISTA);
673 isac_interrupt(cs, val);
674 }
675 if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
676 HDLC_irq_main(cs);
677 }
678 WriteISAC(cs, ISAC_MASK, 0xFF);
679 WriteISAC(cs, ISAC_MASK, 0x0);
680 spin_unlock_irqrestore(&cs->lock, flags);
681 return IRQ_HANDLED;
682}
683
684static void
685reset_avmpcipnp(struct IsdnCardState *cs)
686{
687 printk(KERN_INFO "AVM PCI/PnP: reset\n");
688 outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
689 mdelay(10);
690 outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
691 outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);
692 mdelay(10);
693 printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
694}
695
696static int
697AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
698{
699 u_long flags;
700
701 switch (mt) {
702 case CARD_RESET:
703 spin_lock_irqsave(&cs->lock, flags);
704 reset_avmpcipnp(cs);
705 spin_unlock_irqrestore(&cs->lock, flags);
706 return(0);
707 case CARD_RELEASE:
708 outb(0, cs->hw.avm.cfg_reg + 2);
709 release_region(cs->hw.avm.cfg_reg, 32);
710 return(0);
711 case CARD_INIT:
712 spin_lock_irqsave(&cs->lock, flags);
713 reset_avmpcipnp(cs);
714 clear_pending_isac_ints(cs);
715 initisac(cs);
716 inithdlc(cs);
717 outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
718 cs->hw.avm.cfg_reg + 2);
719 WriteISAC(cs, ISAC_MASK, 0);
720 outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
721 AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
722 /* RESET Receiver and Transmitter */
723 WriteISAC(cs, ISAC_CMDR, 0x41);
724 spin_unlock_irqrestore(&cs->lock, flags);
725 return(0);
726 case CARD_TEST:
727 return(0);
728 }
729 return(0);
730}
731
732#ifdef CONFIG_PCI
733static struct pci_dev *dev_avm __initdata = NULL;
734#endif
735#ifdef __ISAPNP__
736static struct pnp_card *pnp_avm_c __initdata = NULL;
737#endif
738
739int __init
740setup_avm_pcipnp(struct IsdnCard *card)
741{
742 u_int val, ver;
743 struct IsdnCardState *cs = card->cs;
744 char tmp[64];
745
746 strcpy(tmp, avm_pci_rev);
747 printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
748 if (cs->typ != ISDN_CTYPE_FRITZPCI)
749 return (0);
750 if (card->para[1]) {
751 /* old manual method */
752 cs->hw.avm.cfg_reg = card->para[1];
753 cs->irq = card->para[0];
754 cs->subtyp = AVM_FRITZ_PNP;
755 goto ready;
756 }
757#ifdef __ISAPNP__
758 if (isapnp_present()) {
759 struct pnp_dev *pnp_avm_d = NULL;
760 if ((pnp_avm_c = pnp_find_card(
761 ISAPNP_VENDOR('A', 'V', 'M'),
762 ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
763 if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
764 ISAPNP_VENDOR('A', 'V', 'M'),
765 ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
766 int err;
767
768 pnp_disable_dev(pnp_avm_d);
769 err = pnp_activate_dev(pnp_avm_d);
770 if (err<0) {
771 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
772 __FUNCTION__, err);
773 return(0);
774 }
775 cs->hw.avm.cfg_reg =
776 pnp_port_start(pnp_avm_d, 0);
777 cs->irq = pnp_irq(pnp_avm_d, 0);
778 if (!cs->irq) {
779 printk(KERN_ERR "FritzPnP:No IRQ\n");
780 return(0);
781 }
782 if (!cs->hw.avm.cfg_reg) {
783 printk(KERN_ERR "FritzPnP:No IO address\n");
784 return(0);
785 }
786 cs->subtyp = AVM_FRITZ_PNP;
787 goto ready;
788 }
789 }
790 } else {
791 printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
792 }
793#endif
794#ifdef CONFIG_PCI
795 if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
796 PCI_DEVICE_ID_AVM_A1, dev_avm))) {
797 if (pci_enable_device(dev_avm))
798 return(0);
799 cs->irq = dev_avm->irq;
800 if (!cs->irq) {
801 printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
802 return(0);
803 }
804 cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
805 if (!cs->hw.avm.cfg_reg) {
806 printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
807 return(0);
808 }
809 cs->subtyp = AVM_FRITZ_PCI;
810 } else {
811 printk(KERN_WARNING "FritzPCI: No PCI card found\n");
812 return(0);
813 }
814 cs->irq_flags |= SA_SHIRQ;
815#else
816 printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
817 return (0);
818#endif /* CONFIG_PCI */
819ready:
820 cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
821 if (!request_region(cs->hw.avm.cfg_reg, 32,
822 (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {
823 printk(KERN_WARNING
824 "HiSax: %s config port %x-%x already in use\n",
825 CardType[card->typ],
826 cs->hw.avm.cfg_reg,
827 cs->hw.avm.cfg_reg + 31);
828 return (0);
829 }
830 switch (cs->subtyp) {
831 case AVM_FRITZ_PCI:
832 val = inl(cs->hw.avm.cfg_reg);
833 printk(KERN_INFO "AVM PCI: stat %#x\n", val);
834 printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
835 val & 0xff, (val>>8) & 0xff);
836 cs->BC_Read_Reg = &ReadHDLC_s;
837 cs->BC_Write_Reg = &WriteHDLC_s;
838 break;
839 case AVM_FRITZ_PNP:
840 val = inb(cs->hw.avm.cfg_reg);
841 ver = inb(cs->hw.avm.cfg_reg + 1);
842 printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
843 cs->BC_Read_Reg = &ReadHDLCPnP;
844 cs->BC_Write_Reg = &WriteHDLCPnP;
845 break;
846 default:
847 printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);
848 return(0);
849 }
850 printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
851 (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
852 cs->irq, cs->hw.avm.cfg_reg);
853
854 setup_isac(cs);
855 cs->readisac = &ReadISAC;
856 cs->writeisac = &WriteISAC;
857 cs->readisacfifo = &ReadISACfifo;
858 cs->writeisacfifo = &WriteISACfifo;
859 cs->BC_Send_Data = &hdlc_fill_fifo;
860 cs->cardmsg = &AVM_card_msg;
861 cs->irq_func = &avm_pcipnp_interrupt;
862 cs->writeisac(cs, ISAC_MASK, 0xFF);
863 ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
864 return (1);
865}
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
new file mode 100644
index 00000000000..663a0bf703b
--- /dev/null
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -0,0 +1,527 @@
1/*
2 * PCMCIA client driver for AVM A1 / Fritz!PCMCIA
3 *
4 * Author Carsten Paeth
5 * Copyright 1998-2001 by Carsten Paeth <calle@calle.in-berlin.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/sched.h>
18#include <linux/ptrace.h>
19#include <linux/slab.h>
20#include <linux/string.h>
21#include <asm/io.h>
22#include <asm/system.h>
23
24#include <pcmcia/version.h>
25#include <pcmcia/cs_types.h>
26#include <pcmcia/cs.h>
27#include <pcmcia/cistpl.h>
28#include <pcmcia/ds.h>
29#include "hisax_cfg.h"
30
31MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards");
32MODULE_AUTHOR("Carsten Paeth");
33MODULE_LICENSE("GPL");
34
35/*
36 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
37 you do not define PCMCIA_DEBUG at all, all the debug code will be
38 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
39 be present but disabled -- but it can then be enabled for specific
40 modules at load time with a 'pc_debug=#' option to insmod.
41*/
42#ifdef PCMCIA_DEBUG
43static int pc_debug = PCMCIA_DEBUG;
44module_param(pc_debug, int, 0);
45#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
46static char *version =
47"avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)";
48#else
49#define DEBUG(n, args...)
50#endif
51
52/*====================================================================*/
53
54/* Parameters that can be set with 'insmod' */
55
56static int isdnprot = 2;
57
58module_param(isdnprot, int, 0);
59
60/*====================================================================*/
61
62/*
63 The event() function is this driver's Card Services event handler.
64 It will be called by Card Services when an appropriate card status
65 event is received. The config() and release() entry points are
66 used to configure or release a socket, in response to card insertion
67 and ejection events. They are invoked from the skeleton event
68 handler.
69*/
70
71static void avma1cs_config(dev_link_t *link);
72static void avma1cs_release(dev_link_t *link);
73static int avma1cs_event(event_t event, int priority,
74 event_callback_args_t *args);
75
76/*
77 The attach() and detach() entry points are used to create and destroy
78 "instances" of the driver, where each instance represents everything
79 needed to manage one actual PCMCIA card.
80*/
81
82static dev_link_t *avma1cs_attach(void);
83static void avma1cs_detach(dev_link_t *);
84
85/*
86 The dev_info variable is the "key" that is used to match up this
87 device driver with appropriate cards, through the card configuration
88 database.
89*/
90
91static dev_info_t dev_info = "avma1_cs";
92
93/*
94 A linked list of "instances" of the skeleton device. Each actual
95 PCMCIA card corresponds to one device instance, and is described
96 by one dev_link_t structure (defined in ds.h).
97
98 You may not want to use a linked list for this -- for example, the
99 memory card driver uses an array of dev_link_t pointers, where minor
100 device numbers are used to derive the corresponding array index.
101*/
102
103static dev_link_t *dev_list = NULL;
104
105/*
106 A dev_link_t structure has fields for most things that are needed
107 to keep track of a socket, but there will usually be some device
108 specific information that also needs to be kept track of. The
109 'priv' pointer in a dev_link_t structure can be used to point to
110 a device-specific private data structure, like this.
111
112 A driver needs to provide a dev_node_t structure for each device
113 on a card. In some cases, there is only one device per card (for
114 example, ethernet cards, modems). In other cases, there may be
115 many actual or logical devices (SCSI adapters, memory cards with
116 multiple partitions). The dev_node_t structures need to be kept
117 in a linked list starting at the 'dev' field of a dev_link_t
118 structure. We allocate them in the card's private data structure,
119 because they generally can't be allocated dynamically.
120*/
121
122typedef struct local_info_t {
123 dev_node_t node;
124} local_info_t;
125
126/*======================================================================
127
128 avma1cs_attach() creates an "instance" of the driver, allocating
129 local data structures for one device. The device is registered
130 with Card Services.
131
132 The dev_link structure is initialized, but we don't actually
133 configure the card at this point -- we wait until we receive a
134 card insertion event.
135
136======================================================================*/
137
138static dev_link_t *avma1cs_attach(void)
139{
140 client_reg_t client_reg;
141 dev_link_t *link;
142 local_info_t *local;
143 int ret;
144
145 DEBUG(0, "avma1cs_attach()\n");
146
147 /* Initialize the dev_link_t structure */
148 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
149 if (!link)
150 return NULL;
151 memset(link, 0, sizeof(struct dev_link_t));
152
153 /* Allocate space for private device-specific data */
154 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
155 if (!local) {
156 kfree(link);
157 return NULL;
158 }
159 memset(local, 0, sizeof(local_info_t));
160 link->priv = local;
161
162 /* The io structure describes IO port mapping */
163 link->io.NumPorts1 = 16;
164 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
165 link->io.NumPorts2 = 16;
166 link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
167 link->io.IOAddrLines = 5;
168
169 /* Interrupt setup */
170 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
171 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
172
173 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
174
175 /* General socket configuration */
176 link->conf.Attributes = CONF_ENABLE_IRQ;
177 link->conf.Vcc = 50;
178 link->conf.IntType = INT_MEMORY_AND_IO;
179 link->conf.ConfigIndex = 1;
180 link->conf.Present = PRESENT_OPTION;
181
182 /* Register with Card Services */
183 link->next = dev_list;
184 dev_list = link;
185 client_reg.dev_info = &dev_info;
186 client_reg.EventMask =
187 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
188 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
189 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
190 client_reg.event_handler = &avma1cs_event;
191 client_reg.Version = 0x0210;
192 client_reg.event_callback_args.client_data = link;
193 ret = pcmcia_register_client(&link->handle, &client_reg);
194 if (ret != 0) {
195 cs_error(link->handle, RegisterClient, ret);
196 avma1cs_detach(link);
197 return NULL;
198 }
199
200 return link;
201} /* avma1cs_attach */
202
203/*======================================================================
204
205 This deletes a driver "instance". The device is de-registered
206 with Card Services. If it has been released, all local data
207 structures are freed. Otherwise, the structures will be freed
208 when the device is released.
209
210======================================================================*/
211
212static void avma1cs_detach(dev_link_t *link)
213{
214 dev_link_t **linkp;
215
216 DEBUG(0, "avma1cs_detach(0x%p)\n", link);
217
218 /* Locate device structure */
219 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
220 if (*linkp == link) break;
221 if (*linkp == NULL)
222 return;
223
224 /*
225 If the device is currently configured and active, we won't
226 actually delete it yet. Instead, it is marked so that when
227 the release() function is called, that will trigger a proper
228 detach().
229 */
230 if (link->state & DEV_CONFIG) {
231#ifdef PCMCIA_DEBUG
232 printk(KERN_DEBUG "avma1_cs: detach postponed, '%s' "
233 "still locked\n", link->dev->dev_name);
234#endif
235 link->state |= DEV_STALE_LINK;
236 return;
237 }
238
239 /* Break the link with Card Services */
240 if (link->handle)
241 pcmcia_deregister_client(link->handle);
242
243 /* Unlink device structure, free pieces */
244 *linkp = link->next;
245 if (link->priv) {
246 kfree(link->priv);
247 }
248 kfree(link);
249
250} /* avma1cs_detach */
251
252/*======================================================================
253
254 avma1cs_config() is scheduled to run after a CARD_INSERTION event
255 is received, to configure the PCMCIA socket, and to make the
256 ethernet device available to the system.
257
258======================================================================*/
259
260static int get_tuple(client_handle_t handle, tuple_t *tuple,
261 cisparse_t *parse)
262{
263 int i = pcmcia_get_tuple_data(handle, tuple);
264 if (i != CS_SUCCESS) return i;
265 return pcmcia_parse_tuple(handle, tuple, parse);
266}
267
268static int first_tuple(client_handle_t handle, tuple_t *tuple,
269 cisparse_t *parse)
270{
271 int i = pcmcia_get_first_tuple(handle, tuple);
272 if (i != CS_SUCCESS) return i;
273 return get_tuple(handle, tuple, parse);
274}
275
276static int next_tuple(client_handle_t handle, tuple_t *tuple,
277 cisparse_t *parse)
278{
279 int i = pcmcia_get_next_tuple(handle, tuple);
280 if (i != CS_SUCCESS) return i;
281 return get_tuple(handle, tuple, parse);
282}
283
284static void avma1cs_config(dev_link_t *link)
285{
286 client_handle_t handle;
287 tuple_t tuple;
288 cisparse_t parse;
289 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
290 local_info_t *dev;
291 int i;
292 u_char buf[64];
293 char devname[128];
294 IsdnCard_t icard;
295 int busy = 0;
296
297 handle = link->handle;
298 dev = link->priv;
299
300 DEBUG(0, "avma1cs_config(0x%p)\n", link);
301
302 /*
303 This reads the card's CONFIG tuple to find its configuration
304 registers.
305 */
306 do {
307 tuple.DesiredTuple = CISTPL_CONFIG;
308 i = pcmcia_get_first_tuple(handle, &tuple);
309 if (i != CS_SUCCESS) break;
310 tuple.TupleData = buf;
311 tuple.TupleDataMax = 64;
312 tuple.TupleOffset = 0;
313 i = pcmcia_get_tuple_data(handle, &tuple);
314 if (i != CS_SUCCESS) break;
315 i = pcmcia_parse_tuple(handle, &tuple, &parse);
316 if (i != CS_SUCCESS) break;
317 link->conf.ConfigBase = parse.config.base;
318 } while (0);
319 if (i != CS_SUCCESS) {
320 cs_error(link->handle, ParseTuple, i);
321 link->state &= ~DEV_CONFIG_PENDING;
322 return;
323 }
324
325 /* Configure card */
326 link->state |= DEV_CONFIG;
327
328 do {
329
330 tuple.Attributes = 0;
331 tuple.TupleData = buf;
332 tuple.TupleDataMax = 254;
333 tuple.TupleOffset = 0;
334 tuple.DesiredTuple = CISTPL_VERS_1;
335
336 devname[0] = 0;
337 if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
338 strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
339 sizeof(devname));
340 }
341 /*
342 * find IO port
343 */
344 tuple.TupleData = (cisdata_t *)buf;
345 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
346 tuple.Attributes = 0;
347 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
348 i = first_tuple(handle, &tuple, &parse);
349 while (i == CS_SUCCESS) {
350 if (cf->io.nwin > 0) {
351 link->conf.ConfigIndex = cf->index;
352 link->io.BasePort1 = cf->io.win[0].base;
353 link->io.NumPorts1 = cf->io.win[0].len;
354 link->io.NumPorts2 = 0;
355 printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
356 link->io.BasePort1,
357 link->io.BasePort1+link->io.NumPorts1 - 1);
358 i = pcmcia_request_io(link->handle, &link->io);
359 if (i == CS_SUCCESS) goto found_port;
360 }
361 i = next_tuple(handle, &tuple, &parse);
362 }
363
364found_port:
365 if (i != CS_SUCCESS) {
366 cs_error(link->handle, RequestIO, i);
367 break;
368 }
369
370 /*
371 * allocate an interrupt line
372 */
373 i = pcmcia_request_irq(link->handle, &link->irq);
374 if (i != CS_SUCCESS) {
375 cs_error(link->handle, RequestIRQ, i);
376 pcmcia_release_io(link->handle, &link->io);
377 break;
378 }
379
380 /*
381 * configure the PCMCIA socket
382 */
383 i = pcmcia_request_configuration(link->handle, &link->conf);
384 if (i != CS_SUCCESS) {
385 cs_error(link->handle, RequestConfiguration, i);
386 pcmcia_release_io(link->handle, &link->io);
387 pcmcia_release_irq(link->handle, &link->irq);
388 break;
389 }
390
391 } while (0);
392
393 /* At this point, the dev_node_t structure(s) should be
394 initialized and arranged in a linked list at link->dev. */
395
396 strcpy(dev->node.dev_name, "A1");
397 dev->node.major = 45;
398 dev->node.minor = 0;
399 link->dev = &dev->node;
400
401 link->state &= ~DEV_CONFIG_PENDING;
402 /* If any step failed, release any partially configured state */
403 if (i != 0) {
404 avma1cs_release(link);
405 return;
406 }
407
408 printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
409 link->io.BasePort1, link->irq.AssignedIRQ);
410
411 icard.para[0] = link->irq.AssignedIRQ;
412 icard.para[1] = link->io.BasePort1;
413 icard.protocol = isdnprot;
414 icard.typ = ISDN_CTYPE_A1_PCMCIA;
415
416 i = hisax_init_pcmcia(link, &busy, &icard);
417 if (i < 0) {
418 printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
419 avma1cs_release(link);
420 return;
421 }
422 dev->node.minor = i;
423
424} /* avma1cs_config */
425
426/*======================================================================
427
428 After a card is removed, avma1cs_release() will unregister the net
429 device, and release the PCMCIA configuration. If the device is
430 still open, this will be postponed until it is closed.
431
432======================================================================*/
433
434static void avma1cs_release(dev_link_t *link)
435{
436 local_info_t *local = link->priv;
437
438 DEBUG(0, "avma1cs_release(0x%p)\n", link);
439
440 /* no unregister function with hisax */
441 HiSax_closecard(local->node.minor);
442
443 /* Unlink the device chain */
444 link->dev = NULL;
445
446 /* Don't bother checking to see if these succeed or not */
447 pcmcia_release_configuration(link->handle);
448 pcmcia_release_io(link->handle, &link->io);
449 pcmcia_release_irq(link->handle, &link->irq);
450 link->state &= ~DEV_CONFIG;
451
452 if (link->state & DEV_STALE_LINK)
453 avma1cs_detach(link);
454} /* avma1cs_release */
455
456/*======================================================================
457
458 The card status event handler. Mostly, this schedules other
459 stuff to run after an event is received. A CARD_REMOVAL event
460 also sets some flags to discourage the net drivers from trying
461 to talk to the card any more.
462
463 When a CARD_REMOVAL event is received, we immediately set a flag
464 to block future accesses to this device. All the functions that
465 actually access the device should check this flag to make sure
466 the card is still present.
467
468======================================================================*/
469
470static int avma1cs_event(event_t event, int priority,
471 event_callback_args_t *args)
472{
473 dev_link_t *link = args->client_data;
474
475 DEBUG(1, "avma1cs_event(0x%06x)\n", event);
476
477 switch (event) {
478 case CS_EVENT_CARD_REMOVAL:
479 if (link->state & DEV_CONFIG)
480 avma1cs_release(link);
481 break;
482 case CS_EVENT_CARD_INSERTION:
483 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
484 avma1cs_config(link);
485 break;
486 case CS_EVENT_PM_SUSPEND:
487 link->state |= DEV_SUSPEND;
488 /* Fall through... */
489 case CS_EVENT_RESET_PHYSICAL:
490 if (link->state & DEV_CONFIG)
491 pcmcia_release_configuration(link->handle);
492 break;
493 case CS_EVENT_PM_RESUME:
494 link->state &= ~DEV_SUSPEND;
495 /* Fall through... */
496 case CS_EVENT_CARD_RESET:
497 if (link->state & DEV_CONFIG)
498 pcmcia_request_configuration(link->handle, &link->conf);
499 break;
500 }
501 return 0;
502} /* avma1cs_event */
503
504static struct pcmcia_driver avma1cs_driver = {
505 .owner = THIS_MODULE,
506 .drv = {
507 .name = "avma1_cs",
508 },
509 .attach = avma1cs_attach,
510 .detach = avma1cs_detach,
511};
512
513/*====================================================================*/
514
515static int __init init_avma1_cs(void)
516{
517 return(pcmcia_register_driver(&avma1cs_driver));
518}
519
520static void __exit exit_avma1_cs(void)
521{
522 pcmcia_unregister_driver(&avma1cs_driver);
523 BUG_ON(dev_list != NULL);
524}
525
526module_init(init_avma1_cs);
527module_exit(exit_avma1_cs);
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
new file mode 100644
index 00000000000..f410f628a3e
--- /dev/null
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -0,0 +1,344 @@
1/* $Id: bkm_a4t.c,v 1.22.2.4 2004/01/14 16:04:48 keil Exp $
2 *
3 * low level stuff for T-Berkom A4T
4 *
5 * Author Roland Klabunde
6 * Copyright by Roland Klabunde <R.Klabunde@Berkom.de>
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
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include "hisax.h"
17#include "isac.h"
18#include "hscx.h"
19#include "jade.h"
20#include "isdnl1.h"
21#include <linux/pci.h>
22#include "bkm_ax.h"
23
24extern const char *CardType[];
25
26const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
27
28
29static inline u_char
30readreg(unsigned int ale, unsigned long adr, u_char off)
31{
32 register u_int ret;
33 unsigned int *po = (unsigned int *) adr; /* Postoffice */
34
35 *po = (GCS_2 | PO_WRITE | off);
36 __WAITI20__(po);
37 *po = (ale | PO_READ);
38 __WAITI20__(po);
39 ret = *po;
40 return ((unsigned char) ret);
41}
42
43
44static inline void
45readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
46{
47 int i;
48 for (i = 0; i < size; i++)
49 *data++ = readreg(ale, adr, off);
50}
51
52
53static inline void
54writereg(unsigned int ale, unsigned long adr, u_char off, u_char data)
55{
56 unsigned int *po = (unsigned int *) adr; /* Postoffice */
57 *po = (GCS_2 | PO_WRITE | off);
58 __WAITI20__(po);
59 *po = (ale | PO_WRITE | data);
60 __WAITI20__(po);
61}
62
63
64static inline void
65writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
66{
67 int i;
68
69 for (i = 0; i < size; i++)
70 writereg(ale, adr, off, *data++);
71}
72
73
74/* Interface functions */
75
76static u_char
77ReadISAC(struct IsdnCardState *cs, u_char offset)
78{
79 return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
80}
81
82static void
83WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
84{
85 writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
86}
87
88static void
89ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
90{
91 readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
92}
93
94static void
95WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
96{
97 writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
98}
99
100static u_char
101ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
102{
103 return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
104}
105
106static void
107WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
108{
109 writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
110}
111
112/*
113 * fast interrupt JADE stuff goes here
114 */
115
116#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\
117 cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
118#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\
119 cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
120
121#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\
122 cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
123#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\
124 cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
125
126#include "jade_irq.c"
127
128static irqreturn_t
129bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
130{
131 struct IsdnCardState *cs = dev_id;
132 u_char val = 0;
133 u_long flags;
134 I20_REGISTER_FILE *pI20_Regs;
135
136 spin_lock_irqsave(&cs->lock, flags);
137 pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
138
139 /* ISDN interrupt pending? */
140 if (pI20_Regs->i20IntStatus & intISDN) {
141 /* Reset the ISDN interrupt */
142 pI20_Regs->i20IntStatus = intISDN;
143 /* Disable ISDN interrupt */
144 pI20_Regs->i20IntCtrl &= ~intISDN;
145 /* Channel A first */
146 val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80);
147 if (val) {
148 jade_int_main(cs, val, 0);
149 }
150 /* Channel B */
151 val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0);
152 if (val) {
153 jade_int_main(cs, val, 1);
154 }
155 /* D-Channel */
156 val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA);
157 if (val) {
158 isac_interrupt(cs, val);
159 }
160 /* Reenable ISDN interrupt */
161 pI20_Regs->i20IntCtrl |= intISDN;
162 spin_unlock_irqrestore(&cs->lock, flags);
163 return IRQ_HANDLED;
164 } else {
165 spin_unlock_irqrestore(&cs->lock, flags);
166 return IRQ_NONE;
167 }
168}
169
170void
171release_io_bkm(struct IsdnCardState *cs)
172{
173 if (cs->hw.ax.base) {
174 iounmap((void *) cs->hw.ax.base);
175 cs->hw.ax.base = 0;
176 }
177}
178
179static void
180enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
181{
182 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
183 I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
184 if (bEnable)
185 pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
186 else
187 /* CAUTION: This disables the video capture driver too */
188 pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
189 }
190}
191
192static void
193reset_bkm(struct IsdnCardState *cs)
194{
195 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
196 I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
197 /* Issue the I20 soft reset */
198 pI20_Regs->i20SysControl = 0xFF; /* all in */
199 mdelay(10);
200 /* Remove the soft reset */
201 pI20_Regs->i20SysControl = sysRESET | 0xFF;
202 mdelay(10);
203 /* Set our configuration */
204 pI20_Regs->i20SysControl = sysRESET | sysCFG;
205 /* Issue ISDN reset */
206 pI20_Regs->i20GuestControl = guestWAIT_CFG |
207 g_A4T_JADE_RES |
208 g_A4T_ISAR_RES |
209 g_A4T_ISAC_RES |
210 g_A4T_JADE_BOOTR |
211 g_A4T_ISAR_BOOTR;
212 mdelay(10);
213
214 /* Remove RESET state from ISDN */
215 pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
216 g_A4T_JADE_RES |
217 g_A4T_ISAR_RES);
218 mdelay(10);
219 }
220}
221
222static int
223BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
224{
225 u_long flags;
226
227 switch (mt) {
228 case CARD_RESET:
229 /* Disable ints */
230 spin_lock_irqsave(&cs->lock, flags);
231 enable_bkm_int(cs, 0);
232 reset_bkm(cs);
233 spin_unlock_irqrestore(&cs->lock, flags);
234 return (0);
235 case CARD_RELEASE:
236 /* Sanity */
237 spin_lock_irqsave(&cs->lock, flags);
238 enable_bkm_int(cs, 0);
239 reset_bkm(cs);
240 spin_unlock_irqrestore(&cs->lock, flags);
241 release_io_bkm(cs);
242 return (0);
243 case CARD_INIT:
244 spin_lock_irqsave(&cs->lock, flags);
245 clear_pending_isac_ints(cs);
246 clear_pending_jade_ints(cs);
247 initisac(cs);
248 initjade(cs);
249 /* Enable ints */
250 enable_bkm_int(cs, 1);
251 spin_unlock_irqrestore(&cs->lock, flags);
252 return (0);
253 case CARD_TEST:
254 return (0);
255 }
256 return (0);
257}
258
259static struct pci_dev *dev_a4t __initdata = NULL;
260
261int __init
262setup_bkm_a4t(struct IsdnCard *card)
263{
264 struct IsdnCardState *cs = card->cs;
265 char tmp[64];
266 u_int pci_memaddr = 0, found = 0;
267 I20_REGISTER_FILE *pI20_Regs;
268#ifdef CONFIG_PCI
269#endif
270
271 strcpy(tmp, bkm_a4t_revision);
272 printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
273 if (cs->typ == ISDN_CTYPE_BKM_A4T) {
274 cs->subtyp = BKM_A4T;
275 } else
276 return (0);
277
278#ifdef CONFIG_PCI
279 while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
280 PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
281 u16 sub_sys;
282 u16 sub_vendor;
283
284 sub_vendor = dev_a4t->subsystem_vendor;
285 sub_sys = dev_a4t->subsystem_device;
286 if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
287 if (pci_enable_device(dev_a4t))
288 return(0);
289 found = 1;
290 pci_memaddr = pci_resource_start(dev_a4t, 0);
291 cs->irq = dev_a4t->irq;
292 break;
293 }
294 }
295 if (!found) {
296 printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
297 return (0);
298 }
299 if (!cs->irq) { /* IRQ range check ?? */
300 printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
301 return (0);
302 }
303 if (!pci_memaddr) {
304 printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
305 return (0);
306 }
307 cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
308 /* Check suspecious address */
309 pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
310 if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
311 printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
312 CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
313 iounmap((void *) cs->hw.ax.base);
314 cs->hw.ax.base = 0;
315 return (0);
316 }
317 cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
318 cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
319 cs->hw.ax.isac_ale = GCS_1;
320 cs->hw.ax.jade_ale = GCS_3;
321#else
322 printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
323 printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
324 return (0);
325#endif /* CONFIG_PCI */
326 printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
327 CardType[card->typ], cs->hw.ax.base, cs->irq);
328
329 setup_isac(cs);
330 cs->readisac = &ReadISAC;
331 cs->writeisac = &WriteISAC;
332 cs->readisacfifo = &ReadISACfifo;
333 cs->writeisacfifo = &WriteISACfifo;
334 cs->BC_Read_Reg = &ReadJADE;
335 cs->BC_Write_Reg = &WriteJADE;
336 cs->BC_Send_Data = &jade_fill_fifo;
337 cs->cardmsg = &BKM_card_msg;
338 cs->irq_func = &bkm_interrupt;
339 cs->irq_flags |= SA_SHIRQ;
340 ISACVersion(cs, "Telekom A4T:");
341 /* Jade version */
342 JadeVersion(cs, "Telekom A4T:");
343 return (1);
344}
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
new file mode 100644
index 00000000000..94bb83ce7fd
--- /dev/null
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -0,0 +1,451 @@
1/* $Id: bkm_a8.c,v 1.22.2.4 2004/01/15 14:02:34 keil Exp $
2 *
3 * low level stuff for Scitel Quadro (4*S0, passive)
4 *
5 * Author Roland Klabunde
6 * Copyright by Roland Klabunde <R.Klabunde@Berkom.de>
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
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include "hisax.h"
17#include "isac.h"
18#include "ipac.h"
19#include "hscx.h"
20#include "isdnl1.h"
21#include <linux/pci.h>
22#include "bkm_ax.h"
23
24#ifdef CONFIG_PCI
25
26#define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */
27
28extern const char *CardType[];
29
30const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
31
32static const char *sct_quadro_subtypes[] =
33{
34 "",
35 "#1",
36 "#2",
37 "#3",
38 "#4"
39};
40
41
42#define wordout(addr,val) outw(val,addr)
43#define wordin(addr) inw(addr)
44
45static inline u_char
46readreg(unsigned int ale, unsigned int adr, u_char off)
47{
48 register u_char ret;
49 wordout(ale, off);
50 ret = wordin(adr) & 0xFF;
51 return (ret);
52}
53
54static inline void
55readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
56{
57 int i;
58 wordout(ale, off);
59 for (i = 0; i < size; i++)
60 data[i] = wordin(adr) & 0xFF;
61}
62
63
64static inline void
65writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
66{
67 wordout(ale, off);
68 wordout(adr, data);
69}
70
71static inline void
72writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
73{
74 int i;
75 wordout(ale, off);
76 for (i = 0; i < size; i++)
77 wordout(adr, data[i]);
78}
79
80/* Interface functions */
81
82static u_char
83ReadISAC(struct IsdnCardState *cs, u_char offset)
84{
85 return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80));
86}
87
88static void
89WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
90{
91 writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value);
92}
93
94static void
95ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
96{
97 readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
98}
99
100static void
101WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
102{
103 writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
104}
105
106
107static u_char
108ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
109{
110 return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0)));
111}
112
113static void
114WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
115{
116 writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value);
117}
118
119/* Set the specific ipac to active */
120static void
121set_ipac_active(struct IsdnCardState *cs, u_int active)
122{
123 /* set irq mask */
124 writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK,
125 active ? 0xc0 : 0xff);
126}
127
128/*
129 * fast interrupt HSCX stuff goes here
130 */
131
132#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \
133 cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0))
134#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \
135 cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data)
136#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \
137 cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
138#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \
139 cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
140
141#include "hscx_irq.c"
142
143static irqreturn_t
144bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
145{
146 struct IsdnCardState *cs = dev_id;
147 u_char ista, val, icnt = 5;
148 u_long flags;
149
150 spin_lock_irqsave(&cs->lock, flags);
151 ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
152 if (!(ista & 0x3f)) { /* not this IPAC */
153 spin_unlock_irqrestore(&cs->lock, flags);
154 return IRQ_NONE;
155 }
156 Start_IPAC:
157 if (cs->debug & L1_DEB_IPAC)
158 debugl1(cs, "IPAC ISTA %02X", ista);
159 if (ista & 0x0f) {
160 val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40);
161 if (ista & 0x01)
162 val |= 0x01;
163 if (ista & 0x04)
164 val |= 0x02;
165 if (ista & 0x08)
166 val |= 0x04;
167 if (val) {
168 hscx_int_main(cs, val);
169 }
170 }
171 if (ista & 0x20) {
172 val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80);
173 if (val) {
174 isac_interrupt(cs, val);
175 }
176 }
177 if (ista & 0x10) {
178 val = 0x01;
179 isac_interrupt(cs, val);
180 }
181 ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
182 if ((ista & 0x3f) && icnt) {
183 icnt--;
184 goto Start_IPAC;
185 }
186 if (!icnt)
187 printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
188 CardType[cs->typ],
189 sct_quadro_subtypes[cs->subtyp]);
190 writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
191 writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
192 spin_unlock_irqrestore(&cs->lock, flags);
193 return IRQ_HANDLED;
194}
195
196void
197release_io_sct_quadro(struct IsdnCardState *cs)
198{
199 release_region(cs->hw.ax.base & 0xffffffc0, 128);
200 if (cs->subtyp == SCT_1)
201 release_region(cs->hw.ax.plx_adr, 64);
202}
203
204static void
205enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
206{
207 if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
208 if (bEnable)
209 wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
210 else
211 wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
212 }
213}
214
215static void
216reset_bkm(struct IsdnCardState *cs)
217{
218 if (cs->subtyp == SCT_1) {
219 wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4));
220 mdelay(10);
221 /* Remove the soft reset */
222 wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4));
223 mdelay(10);
224 }
225}
226
227static int
228BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
229{
230 u_long flags;
231
232 switch (mt) {
233 case CARD_RESET:
234 spin_lock_irqsave(&cs->lock, flags);
235 /* Disable ints */
236 set_ipac_active(cs, 0);
237 enable_bkm_int(cs, 0);
238 reset_bkm(cs);
239 spin_unlock_irqrestore(&cs->lock, flags);
240 return (0);
241 case CARD_RELEASE:
242 /* Sanity */
243 spin_lock_irqsave(&cs->lock, flags);
244 set_ipac_active(cs, 0);
245 enable_bkm_int(cs, 0);
246 spin_unlock_irqrestore(&cs->lock, flags);
247 release_io_sct_quadro(cs);
248 return (0);
249 case CARD_INIT:
250 spin_lock_irqsave(&cs->lock, flags);
251 cs->debug |= L1_DEB_IPAC;
252 set_ipac_active(cs, 1);
253 inithscxisac(cs, 3);
254 /* Enable ints */
255 enable_bkm_int(cs, 1);
256 spin_unlock_irqrestore(&cs->lock, flags);
257 return (0);
258 case CARD_TEST:
259 return (0);
260 }
261 return (0);
262}
263
264int __init
265sct_alloc_io(u_int adr, u_int len)
266{
267 if (!request_region(adr, len, "scitel")) {
268 printk(KERN_WARNING
269 "HiSax: Scitel port %#x-%#x already in use\n",
270 adr, adr + len);
271 return (1);
272 }
273 return(0);
274}
275
276static struct pci_dev *dev_a8 __initdata = NULL;
277static u16 sub_vendor_id __initdata = 0;
278static u16 sub_sys_id __initdata = 0;
279static u_char pci_bus __initdata = 0;
280static u_char pci_device_fn __initdata = 0;
281static u_char pci_irq __initdata = 0;
282
283#endif /* CONFIG_PCI */
284
285int __init
286setup_sct_quadro(struct IsdnCard *card)
287{
288#ifdef CONFIG_PCI
289 struct IsdnCardState *cs = card->cs;
290 char tmp[64];
291 u_char pci_rev_id;
292 u_int found = 0;
293 u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
294
295 strcpy(tmp, sct_quadro_revision);
296 printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
297 if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
298 cs->subtyp = SCT_1; /* Preset */
299 } else
300 return (0);
301
302 /* Identify subtype by para[0] */
303 if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
304 cs->subtyp = card->para[0];
305 else {
306 printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n",
307 CardType[card->typ]);
308 return (0);
309 }
310 if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) ||
311 (sub_vendor_id != PCI_VENDOR_ID_BERKOM)))
312 return (0);
313 if (cs->subtyp == SCT_1) {
314 while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX,
315 PCI_DEVICE_ID_PLX_9050, dev_a8))) {
316
317 sub_vendor_id = dev_a8->subsystem_vendor;
318 sub_sys_id = dev_a8->subsystem_device;
319 if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) &&
320 (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) {
321 if (pci_enable_device(dev_a8))
322 return(0);
323 pci_ioaddr1 = pci_resource_start(dev_a8, 1);
324 pci_irq = dev_a8->irq;
325 pci_bus = dev_a8->bus->number;
326 pci_device_fn = dev_a8->devfn;
327 found = 1;
328 break;
329 }
330 }
331 if (!found) {
332 printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
333 CardType[card->typ],
334 sct_quadro_subtypes[cs->subtyp]);
335 return (0);
336 }
337#ifdef ATTEMPT_PCI_REMAPPING
338/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
339 pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id);
340 if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
341 printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
342 CardType[card->typ],
343 sct_quadro_subtypes[cs->subtyp]);
344 /* Restart PCI negotiation */
345 pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int) - 1);
346 /* Move up by 0x80 byte */
347 pci_ioaddr1 += 0x80;
348 pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
349 pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, pci_ioaddr1);
350 dev_a8->resource[ 1].start = pci_ioaddr1;
351 }
352#endif /* End HACK */
353 }
354 if (!pci_irq) { /* IRQ range check ?? */
355 printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n",
356 CardType[card->typ],
357 sct_quadro_subtypes[cs->subtyp]);
358 return (0);
359 }
360 pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_1, &pci_ioaddr1);
361 pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_2, &pci_ioaddr2);
362 pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_3, &pci_ioaddr3);
363 pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4);
364 pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5);
365 if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) {
366 printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n",
367 CardType[card->typ],
368 sct_quadro_subtypes[cs->subtyp]);
369 return (0);
370 }
371 pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
372 pci_ioaddr2 &= PCI_BASE_ADDRESS_IO_MASK;
373 pci_ioaddr3 &= PCI_BASE_ADDRESS_IO_MASK;
374 pci_ioaddr4 &= PCI_BASE_ADDRESS_IO_MASK;
375 pci_ioaddr5 &= PCI_BASE_ADDRESS_IO_MASK;
376 /* Take over */
377 cs->irq = pci_irq;
378 cs->irq_flags |= SA_SHIRQ;
379 /* pci_ioaddr1 is unique to all subdevices */
380 /* pci_ioaddr2 is for the fourth subdevice only */
381 /* pci_ioaddr3 is for the third subdevice only */
382 /* pci_ioaddr4 is for the second subdevice only */
383 /* pci_ioaddr5 is for the first subdevice only */
384 cs->hw.ax.plx_adr = pci_ioaddr1;
385 /* Enter all ipac_base addresses */
386 switch(cs->subtyp) {
387 case 1:
388 cs->hw.ax.base = pci_ioaddr5 + 0x00;
389 if (sct_alloc_io(pci_ioaddr1, 128))
390 return(0);
391 if (sct_alloc_io(pci_ioaddr5, 64))
392 return(0);
393 /* disable all IPAC */
394 writereg(pci_ioaddr5, pci_ioaddr5 + 4,
395 IPAC_MASK, 0xFF);
396 writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c,
397 IPAC_MASK, 0xFF);
398 writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14,
399 IPAC_MASK, 0xFF);
400 writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24,
401 IPAC_MASK, 0xFF);
402 break;
403 case 2:
404 cs->hw.ax.base = pci_ioaddr4 + 0x08;
405 if (sct_alloc_io(pci_ioaddr4, 64))
406 return(0);
407 break;
408 case 3:
409 cs->hw.ax.base = pci_ioaddr3 + 0x10;
410 if (sct_alloc_io(pci_ioaddr3, 64))
411 return(0);
412 break;
413 case 4:
414 cs->hw.ax.base = pci_ioaddr2 + 0x20;
415 if (sct_alloc_io(pci_ioaddr2, 64))
416 return(0);
417 break;
418 }
419 /* For isac and hscx data path */
420 cs->hw.ax.data_adr = cs->hw.ax.base + 4;
421
422 printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
423 CardType[card->typ],
424 sct_quadro_subtypes[cs->subtyp],
425 cs->hw.ax.plx_adr,
426 cs->hw.ax.base,
427 cs->hw.ax.data_adr,
428 cs->irq);
429
430 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
431
432 cs->readisac = &ReadISAC;
433 cs->writeisac = &WriteISAC;
434 cs->readisacfifo = &ReadISACfifo;
435 cs->writeisacfifo = &WriteISACfifo;
436
437 cs->BC_Read_Reg = &ReadHSCX;
438 cs->BC_Write_Reg = &WriteHSCX;
439 cs->BC_Send_Data = &hscx_fill_fifo;
440 cs->cardmsg = &BKM_card_msg;
441 cs->irq_func = &bkm_interrupt_ipac;
442
443 printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
444 CardType[card->typ],
445 sct_quadro_subtypes[cs->subtyp],
446 readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
447 return (1);
448#else
449 printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
450#endif /* CONFIG_PCI */
451}
diff --git a/drivers/isdn/hisax/bkm_ax.h b/drivers/isdn/hisax/bkm_ax.h
new file mode 100644
index 00000000000..029e0a27766
--- /dev/null
+++ b/drivers/isdn/hisax/bkm_ax.h
@@ -0,0 +1,119 @@
1/* $Id: bkm_ax.h,v 1.5.6.3 2001/09/23 22:24:46 kai Exp $
2 *
3 * low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive)
4 *
5 * Author Roland Klabunde
6 * Copyright by Roland Klabunde <R.Klabunde@Berkom.de>
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
13#ifndef __BKM_AX_H__
14#define __BKM_AX_H__
15
16/* Supported boards (subtypes) */
17#define SCT_1 1
18#define SCT_2 2
19#define SCT_3 3
20#define SCT_4 4
21#define BKM_A4T 5
22
23#define PLX_ADDR_PLX 0x14 /* Addr PLX configuration */
24#define PLX_ADDR_ISAC 0x18 /* Addr ISAC */
25#define PLX_ADDR_HSCX 0x1C /* Addr HSCX */
26#define PLX_ADDR_ALE 0x20 /* Addr ALE */
27#define PLX_ADDR_ALEPLUS 0x24 /* Next Addr behind ALE */
28
29#define PLX_SUBVEN 0x2C /* Offset SubVendor */
30#define PLX_SUBSYS 0x2E /* Offset SubSystem */
31
32
33/* Application specific registers I20 (Siemens SZB6120H) */
34typedef struct {
35 /* Video front end horizontal configuration register */
36 volatile u_int i20VFEHorzCfg; /* Offset 00 */
37 /* Video front end vertical configuration register */
38 volatile u_int i20VFEVertCfg; /* Offset 04 */
39 /* Video front end scaler and pixel format register */
40 volatile u_int i20VFEScaler; /* Offset 08 */
41 /* Video display top register */
42 volatile u_int i20VDispTop; /* Offset 0C */
43 /* Video display bottom register */
44 volatile u_int i20VDispBottom; /* Offset 10 */
45 /* Video stride, status and frame grab register */
46 volatile u_int i20VidFrameGrab;/* Offset 14 */
47 /* Video display configuration register */
48 volatile u_int i20VDispCfg; /* Offset 18 */
49 /* Video masking map top */
50 volatile u_int i20VMaskTop; /* Offset 1C */
51 /* Video masking map bottom */
52 volatile u_int i20VMaskBottom; /* Offset 20 */
53 /* Overlay control register */
54 volatile u_int i20OvlyControl; /* Offset 24 */
55 /* System, PCI and general purpose pins control register */
56 volatile u_int i20SysControl; /* Offset 28 */
57#define sysRESET 0x01000000 /* bit 24:Softreset (Low) */
58 /* GPIO 4...0: Output fixed for our cfg! */
59#define sysCFG 0x000000E0 /* GPIO 7,6,5: Input */
60 /* General purpose pins and guest bus control register */
61 volatile u_int i20GuestControl;/* Offset 2C */
62#define guestWAIT_CFG 0x00005555 /* 4 PCI waits for all */
63#define guestISDN_INT_E 0x01000000 /* ISDN Int en (low) */
64#define guestVID_INT_E 0x02000000 /* Video interrupt en (low) */
65#define guestADI1_INT_R 0x04000000 /* ADI #1 int req (low) */
66#define guestADI2_INT_R 0x08000000 /* ADI #2 int req (low) */
67#define guestISDN_RES 0x10000000 /* ISDN reset bit (high) */
68#define guestADI1_INT_S 0x20000000 /* ADI #1 int pending (low) */
69#define guestADI2_INT_S 0x40000000 /* ADI #2 int pending (low) */
70#define guestISDN_INT_S 0x80000000 /* ISAC int pending (low) */
71
72#define g_A4T_JADE_RES 0x01000000 /* JADE Reset (High) */
73#define g_A4T_ISAR_RES 0x02000000 /* ISAR Reset (High) */
74#define g_A4T_ISAC_RES 0x04000000 /* ISAC Reset (High) */
75#define g_A4T_JADE_BOOTR 0x08000000 /* JADE enable boot SRAM (Low) NOT USED */
76#define g_A4T_ISAR_BOOTR 0x10000000 /* ISAR enable boot SRAM (Low) NOT USED */
77#define g_A4T_JADE_INT_S 0x20000000 /* JADE interrupt pnd (Low) */
78#define g_A4T_ISAR_INT_S 0x40000000 /* ISAR interrupt pnd (Low) */
79#define g_A4T_ISAC_INT_S 0x80000000 /* ISAC interrupt pnd (Low) */
80
81 volatile u_int i20CodeSource; /* Offset 30 */
82 volatile u_int i20CodeXferCtrl;/* Offset 34 */
83 volatile u_int i20CodeMemPtr; /* Offset 38 */
84
85 volatile u_int i20IntStatus; /* Offset 3C */
86 volatile u_int i20IntCtrl; /* Offset 40 */
87#define intISDN 0x40000000 /* GIRQ1En (ISAC/ADI) (High) */
88#define intVID 0x20000000 /* GIRQ0En (VSYNC) (High) */
89#define intCOD 0x10000000 /* CodRepIrqEn (High) */
90#define intPCI 0x01000000 /* PCI IntA enable (High) */
91
92 volatile u_int i20I2CCtrl; /* Offset 44 */
93} I20_REGISTER_FILE, *PI20_REGISTER_FILE;
94
95/*
96 * Postoffice structure for A4T
97 *
98 */
99#define PO_OFFSET 0x00000200 /* Postoffice offset from base */
100
101#define GCS_0 0x00000000 /* Guest bus chip selects */
102#define GCS_1 0x00100000
103#define GCS_2 0x00200000
104#define GCS_3 0x00300000
105
106#define PO_READ 0x00000000 /* R/W from/to guest bus */
107#define PO_WRITE 0x00800000
108
109#define PO_PEND 0x02000000
110
111#define POSTOFFICE(postoffice) *(volatile unsigned int*)(postoffice)
112
113/* Wait unlimited (don't worry) */
114#define __WAITI20__(postoffice) \
115do { \
116 while ((POSTOFFICE(postoffice) & PO_PEND)) ; \
117} while (0)
118
119#endif /* __BKM_AX_H__ */
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
new file mode 100644
index 00000000000..04065ab2610
--- /dev/null
+++ b/drivers/isdn/hisax/callc.c
@@ -0,0 +1,1793 @@
1/* $Id: callc.c,v 2.59.2.4 2004/02/11 13:21:32 keil Exp $
2 *
3 * Author Karsten Keil
4 * Copyright by Karsten Keil <keil@isdn4linux.de>
5 *
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License, incorporated herein by reference.
8 *
9 * For changes and modifications please read
10 * Documentation/isdn/HiSax.cert
11 *
12 * based on the teles driver from Jan den Ouden
13 *
14 * Thanks to Jan den Ouden
15 * Fritz Elfert
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include "hisax.h"
22#include <linux/isdn/capicmd.h>
23
24const char *lli_revision = "$Revision: 2.59.2.4 $";
25
26extern struct IsdnCard cards[];
27extern int nrcards;
28
29static int init_b_st(struct Channel *chanp, int incoming);
30static void release_b_st(struct Channel *chanp);
31
32static struct Fsm callcfsm;
33static int chancount;
34
35/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
36#define ALERT_REJECT 0
37
38/* Value to delay the sending of the first B-channel paket after CONNECT
39 * here is no value given by ITU, but experience shows that 300 ms will
40 * work on many networks, if you or your other side is behind local exchanges
41 * a greater value may be recommented. If the delay is to short the first paket
42 * will be lost and autodetect on many comercial routers goes wrong !
43 * You can adjust this value on runtime with
44 * hisaxctrl <id> 2 <value>
45 * value is in milliseconds
46 */
47#define DEFAULT_B_DELAY 300
48
49/* Flags for remembering action done in lli */
50
51#define FLG_START_B 0
52
53/*
54 * Find card with given driverId
55 */
56static inline struct IsdnCardState *
57hisax_findcard(int driverid)
58{
59 int i;
60
61 for (i = 0; i < nrcards; i++)
62 if (cards[i].cs)
63 if (cards[i].cs->myid == driverid)
64 return (cards[i].cs);
65 return (struct IsdnCardState *) 0;
66}
67
68static void
69link_debug(struct Channel *chanp, int direction, char *fmt, ...)
70{
71 va_list args;
72 char tmp[16];
73
74 va_start(args, fmt);
75 sprintf(tmp, "Ch%d %s ", chanp->chan,
76 direction ? "LL->HL" : "HL->LL");
77 VHiSax_putstatus(chanp->cs, tmp, fmt, args);
78 va_end(args);
79}
80
81enum {
82 ST_NULL, /* 0 inactive */
83 ST_OUT_DIAL, /* 1 outgoing, SETUP send; awaiting confirm */
84 ST_IN_WAIT_LL, /* 2 incoming call received; wait for LL confirm */
85 ST_IN_ALERT_SENT, /* 3 incoming call received; ALERT send */
86 ST_IN_WAIT_CONN_ACK, /* 4 incoming CONNECT send; awaiting CONN_ACK */
87 ST_WAIT_BCONN, /* 5 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */
88 ST_ACTIVE, /* 6 active, b channel prot. established */
89 ST_WAIT_BRELEASE, /* 7 call clear. (initiator), awaiting b channel prot. rel. */
90 ST_WAIT_BREL_DISC, /* 8 call clear. (receiver), DISCONNECT req. received */
91 ST_WAIT_DCOMMAND, /* 9 call clear. (receiver), awaiting DCHANNEL message */
92 ST_WAIT_DRELEASE, /* 10 DISCONNECT sent, awaiting RELEASE */
93 ST_WAIT_D_REL_CNF, /* 11 RELEASE sent, awaiting RELEASE confirm */
94 ST_IN_PROCEED_SEND, /* 12 incoming call, proceeding send */
95};
96
97
98#define STATE_COUNT (ST_IN_PROCEED_SEND + 1)
99
100static char *strState[] =
101{
102 "ST_NULL",
103 "ST_OUT_DIAL",
104 "ST_IN_WAIT_LL",
105 "ST_IN_ALERT_SENT",
106 "ST_IN_WAIT_CONN_ACK",
107 "ST_WAIT_BCONN",
108 "ST_ACTIVE",
109 "ST_WAIT_BRELEASE",
110 "ST_WAIT_BREL_DISC",
111 "ST_WAIT_DCOMMAND",
112 "ST_WAIT_DRELEASE",
113 "ST_WAIT_D_REL_CNF",
114 "ST_IN_PROCEED_SEND",
115};
116
117enum {
118 EV_DIAL, /* 0 */
119 EV_SETUP_CNF, /* 1 */
120 EV_ACCEPTB, /* 2 */
121 EV_DISCONNECT_IND, /* 3 */
122 EV_RELEASE, /* 4 */
123 EV_LEASED, /* 5 */
124 EV_LEASED_REL, /* 6 */
125 EV_SETUP_IND, /* 7 */
126 EV_ACCEPTD, /* 8 */
127 EV_SETUP_CMPL_IND, /* 9 */
128 EV_BC_EST, /* 10 */
129 EV_WRITEBUF, /* 11 */
130 EV_HANGUP, /* 12 */
131 EV_BC_REL, /* 13 */
132 EV_CINF, /* 14 */
133 EV_SUSPEND, /* 15 */
134 EV_RESUME, /* 16 */
135 EV_NOSETUP_RSP, /* 17 */
136 EV_SETUP_ERR, /* 18 */
137 EV_CONNECT_ERR, /* 19 */
138 EV_PROCEED, /* 20 */
139 EV_ALERT, /* 21 */
140 EV_REDIR, /* 22 */
141};
142
143#define EVENT_COUNT (EV_REDIR + 1)
144
145static char *strEvent[] =
146{
147 "EV_DIAL",
148 "EV_SETUP_CNF",
149 "EV_ACCEPTB",
150 "EV_DISCONNECT_IND",
151 "EV_RELEASE",
152 "EV_LEASED",
153 "EV_LEASED_REL",
154 "EV_SETUP_IND",
155 "EV_ACCEPTD",
156 "EV_SETUP_CMPL_IND",
157 "EV_BC_EST",
158 "EV_WRITEBUF",
159 "EV_HANGUP",
160 "EV_BC_REL",
161 "EV_CINF",
162 "EV_SUSPEND",
163 "EV_RESUME",
164 "EV_NOSETUP_RSP",
165 "EV_SETUP_ERR",
166 "EV_CONNECT_ERR",
167 "EV_PROCEED",
168 "EV_ALERT",
169 "EV_REDIR",
170};
171
172
173static inline void
174HL_LL(struct Channel *chanp, int command)
175{
176 isdn_ctrl ic;
177
178 ic.driver = chanp->cs->myid;
179 ic.command = command;
180 ic.arg = chanp->chan;
181 chanp->cs->iif.statcallb(&ic);
182}
183
184static inline void
185lli_deliver_cause(struct Channel *chanp)
186{
187 isdn_ctrl ic;
188
189 if (!chanp->proc)
190 return;
191 if (chanp->proc->para.cause == NO_CAUSE)
192 return;
193 ic.driver = chanp->cs->myid;
194 ic.command = ISDN_STAT_CAUSE;
195 ic.arg = chanp->chan;
196 if (chanp->cs->protocol == ISDN_PTYPE_EURO)
197 sprintf(ic.parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f,
198 chanp->proc->para.cause & 0x7f);
199 else
200 sprintf(ic.parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f,
201 chanp->proc->para.cause & 0x7f);
202 chanp->cs->iif.statcallb(&ic);
203}
204
205static inline void
206lli_close(struct FsmInst *fi)
207{
208 struct Channel *chanp = fi->userdata;
209
210 FsmChangeState(fi, ST_NULL);
211 chanp->Flags = 0;
212 chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
213}
214
215static void
216lli_leased_in(struct FsmInst *fi, int event, void *arg)
217{
218 struct Channel *chanp = fi->userdata;
219 isdn_ctrl ic;
220 int ret;
221
222 if (!chanp->leased)
223 return;
224 chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
225 FsmChangeState(fi, ST_IN_WAIT_LL);
226 if (chanp->debug & 1)
227 link_debug(chanp, 0, "STAT_ICALL_LEASED");
228 ic.driver = chanp->cs->myid;
229 ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW);
230 ic.arg = chanp->chan;
231 ic.parm.setup.si1 = 7;
232 ic.parm.setup.si2 = 0;
233 ic.parm.setup.plan = 0;
234 ic.parm.setup.screen = 0;
235 sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1);
236 sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid);
237 ret = chanp->cs->iif.statcallb(&ic);
238 if (chanp->debug & 1)
239 link_debug(chanp, 1, "statcallb ret=%d", ret);
240 if (!ret) {
241 chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
242 FsmChangeState(fi, ST_NULL);
243 }
244}
245
246
247/*
248 * Dial out
249 */
250static void
251lli_init_bchan_out(struct FsmInst *fi, int event, void *arg)
252{
253 struct Channel *chanp = fi->userdata;
254
255 FsmChangeState(fi, ST_WAIT_BCONN);
256 if (chanp->debug & 1)
257 link_debug(chanp, 0, "STAT_DCONN");
258 HL_LL(chanp, ISDN_STAT_DCONN);
259 init_b_st(chanp, 0);
260 chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
261}
262
263static void
264lli_prep_dialout(struct FsmInst *fi, int event, void *arg)
265{
266 struct Channel *chanp = fi->userdata;
267
268 FsmDelTimer(&chanp->drel_timer, 60);
269 FsmDelTimer(&chanp->dial_timer, 73);
270 chanp->l2_active_protocol = chanp->l2_protocol;
271 chanp->incoming = 0;
272 chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
273 if (chanp->leased) {
274 lli_init_bchan_out(fi, event, arg);
275 } else {
276 FsmChangeState(fi, ST_OUT_DIAL);
277 chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp);
278 }
279}
280
281static void
282lli_resume(struct FsmInst *fi, int event, void *arg)
283{
284 struct Channel *chanp = fi->userdata;
285
286 FsmDelTimer(&chanp->drel_timer, 60);
287 FsmDelTimer(&chanp->dial_timer, 73);
288 chanp->l2_active_protocol = chanp->l2_protocol;
289 chanp->incoming = 0;
290 chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
291 if (chanp->leased) {
292 lli_init_bchan_out(fi, event, arg);
293 } else {
294 FsmChangeState(fi, ST_OUT_DIAL);
295 chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp);
296 }
297}
298
299static void
300lli_go_active(struct FsmInst *fi, int event, void *arg)
301{
302 struct Channel *chanp = fi->userdata;
303 isdn_ctrl ic;
304
305
306 FsmChangeState(fi, ST_ACTIVE);
307 chanp->data_open = !0;
308 if (chanp->bcs->conmsg)
309 strcpy(ic.parm.num, chanp->bcs->conmsg);
310 else
311 ic.parm.num[0] = 0;
312 if (chanp->debug & 1)
313 link_debug(chanp, 0, "STAT_BCONN %s", ic.parm.num);
314 ic.driver = chanp->cs->myid;
315 ic.command = ISDN_STAT_BCONN;
316 ic.arg = chanp->chan;
317 chanp->cs->iif.statcallb(&ic);
318 chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);
319}
320
321
322/*
323 * RESUME
324 */
325
326/* incoming call */
327
328static void
329lli_deliver_call(struct FsmInst *fi, int event, void *arg)
330{
331 struct Channel *chanp = fi->userdata;
332 isdn_ctrl ic;
333 int ret;
334
335 chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
336 /*
337 * Report incoming calls only once to linklevel, use CallFlags
338 * which is set to 3 with each broadcast message in isdnl1.c
339 * and resetted if a interface answered the STAT_ICALL.
340 */
341 if (1) { /* for only one TEI */
342 FsmChangeState(fi, ST_IN_WAIT_LL);
343 if (chanp->debug & 1)
344 link_debug(chanp, 0, (chanp->chan < 2) ? "STAT_ICALL" : "STAT_ICALLW");
345 ic.driver = chanp->cs->myid;
346 ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW);
347
348 ic.arg = chanp->chan;
349 /*
350 * No need to return "unknown" for calls without OAD,
351 * cause that's handled in linklevel now (replaced by '0')
352 */
353 memcpy(&ic.parm.setup, &chanp->proc->para.setup, sizeof(setup_parm));
354 ret = chanp->cs->iif.statcallb(&ic);
355 if (chanp->debug & 1)
356 link_debug(chanp, 1, "statcallb ret=%d", ret);
357
358 switch (ret) {
359 case 1: /* OK, someone likes this call */
360 FsmDelTimer(&chanp->drel_timer, 61);
361 FsmChangeState(fi, ST_IN_ALERT_SENT);
362 chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
363 break;
364 case 5: /* direct redirect */
365 case 4: /* Proceeding desired */
366 FsmDelTimer(&chanp->drel_timer, 61);
367 FsmChangeState(fi, ST_IN_PROCEED_SEND);
368 chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
369 if (ret == 5) {
370 memcpy(&chanp->setup, &ic.parm.setup, sizeof(setup_parm));
371 chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
372 }
373 break;
374 case 2: /* Rejecting Call */
375 break;
376 case 3: /* incomplete number */
377 FsmDelTimer(&chanp->drel_timer, 61);
378 chanp->d_st->lli.l4l3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc);
379 break;
380 case 0: /* OK, nobody likes this call */
381 default: /* statcallb problems */
382 chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
383 chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
384 FsmChangeState(fi, ST_NULL);
385 break;
386 }
387 } else {
388 chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
389 chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
390 }
391}
392
393static void
394lli_send_dconnect(struct FsmInst *fi, int event, void *arg)
395{
396 struct Channel *chanp = fi->userdata;
397
398 FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
399 chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
400}
401
402static void
403lli_send_alert(struct FsmInst *fi, int event, void *arg)
404{
405 struct Channel *chanp = fi->userdata;
406
407 FsmChangeState(fi, ST_IN_ALERT_SENT);
408 chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
409}
410
411static void
412lli_send_redir(struct FsmInst *fi, int event, void *arg)
413{
414 struct Channel *chanp = fi->userdata;
415
416 chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
417}
418
419static void
420lli_init_bchan_in(struct FsmInst *fi, int event, void *arg)
421{
422 struct Channel *chanp = fi->userdata;
423
424 FsmChangeState(fi, ST_WAIT_BCONN);
425 if (chanp->debug & 1)
426 link_debug(chanp, 0, "STAT_DCONN");
427 HL_LL(chanp, ISDN_STAT_DCONN);
428 chanp->l2_active_protocol = chanp->l2_protocol;
429 chanp->incoming = !0;
430 init_b_st(chanp, !0);
431 chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
432}
433
434static void
435lli_setup_rsp(struct FsmInst *fi, int event, void *arg)
436{
437 struct Channel *chanp = fi->userdata;
438
439 if (chanp->leased) {
440 lli_init_bchan_in(fi, event, arg);
441 } else {
442 FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
443#ifdef WANT_ALERT
444 chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
445#endif
446 chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
447 }
448}
449
450/* Call suspend */
451
452static void
453lli_suspend(struct FsmInst *fi, int event, void *arg)
454{
455 struct Channel *chanp = fi->userdata;
456
457 chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc);
458}
459
460/* Call clearing */
461
462static void
463lli_leased_hup(struct FsmInst *fi, struct Channel *chanp)
464{
465 isdn_ctrl ic;
466
467 ic.driver = chanp->cs->myid;
468 ic.command = ISDN_STAT_CAUSE;
469 ic.arg = chanp->chan;
470 sprintf(ic.parm.num, "L0010");
471 chanp->cs->iif.statcallb(&ic);
472 if (chanp->debug & 1)
473 link_debug(chanp, 0, "STAT_DHUP");
474 HL_LL(chanp, ISDN_STAT_DHUP);
475 lli_close(fi);
476}
477
478static void
479lli_disconnect_req(struct FsmInst *fi, int event, void *arg)
480{
481 struct Channel *chanp = fi->userdata;
482
483 if (chanp->leased) {
484 lli_leased_hup(fi, chanp);
485 } else {
486 FsmChangeState(fi, ST_WAIT_DRELEASE);
487 if (chanp->proc)
488 chanp->proc->para.cause = 0x10; /* Normal Call Clearing */
489 chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST,
490 chanp->proc);
491 }
492}
493
494static void
495lli_disconnect_reject(struct FsmInst *fi, int event, void *arg)
496{
497 struct Channel *chanp = fi->userdata;
498
499 if (chanp->leased) {
500 lli_leased_hup(fi, chanp);
501 } else {
502 FsmChangeState(fi, ST_WAIT_DRELEASE);
503 if (chanp->proc)
504 chanp->proc->para.cause = 0x15; /* Call Rejected */
505 chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST,
506 chanp->proc);
507 }
508}
509
510static void
511lli_dhup_close(struct FsmInst *fi, int event, void *arg)
512{
513 struct Channel *chanp = fi->userdata;
514
515 if (chanp->leased) {
516 lli_leased_hup(fi, chanp);
517 } else {
518 if (chanp->debug & 1)
519 link_debug(chanp, 0, "STAT_DHUP");
520 lli_deliver_cause(chanp);
521 HL_LL(chanp, ISDN_STAT_DHUP);
522 lli_close(fi);
523 }
524}
525
526static void
527lli_reject_req(struct FsmInst *fi, int event, void *arg)
528{
529 struct Channel *chanp = fi->userdata;
530
531 if (chanp->leased) {
532 lli_leased_hup(fi, chanp);
533 return;
534 }
535#ifndef ALERT_REJECT
536 if (chanp->proc)
537 chanp->proc->para.cause = 0x15; /* Call Rejected */
538 chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
539 lli_dhup_close(fi, event, arg);
540#else
541 FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
542 FsmChangeState(fi, ST_IN_ALERT_SENT);
543 chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
544#endif
545}
546
547static void
548lli_disconn_bchan(struct FsmInst *fi, int event, void *arg)
549{
550 struct Channel *chanp = fi->userdata;
551
552 chanp->data_open = 0;
553 FsmChangeState(fi, ST_WAIT_BRELEASE);
554 chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
555}
556
557static void
558lli_start_disc(struct FsmInst *fi, int event, void *arg)
559{
560 struct Channel *chanp = fi->userdata;
561
562 if (chanp->leased) {
563 lli_leased_hup(fi, chanp);
564 } else {
565 lli_disconnect_req(fi, event, arg);
566 }
567}
568
569static void
570lli_rel_b_disc(struct FsmInst *fi, int event, void *arg)
571{
572 struct Channel *chanp = fi->userdata;
573
574 release_b_st(chanp);
575 lli_start_disc(fi, event, arg);
576}
577
578static void
579lli_bhup_disc(struct FsmInst *fi, int event, void *arg)
580{
581 struct Channel *chanp = fi->userdata;
582
583 if (chanp->debug & 1)
584 link_debug(chanp, 0, "STAT_BHUP");
585 HL_LL(chanp, ISDN_STAT_BHUP);
586 lli_rel_b_disc(fi, event, arg);
587}
588
589static void
590lli_bhup_rel_b(struct FsmInst *fi, int event, void *arg)
591{
592 struct Channel *chanp = fi->userdata;
593
594 FsmChangeState(fi, ST_WAIT_DCOMMAND);
595 chanp->data_open = 0;
596 if (chanp->debug & 1)
597 link_debug(chanp, 0, "STAT_BHUP");
598 HL_LL(chanp, ISDN_STAT_BHUP);
599 release_b_st(chanp);
600}
601
602static void
603lli_release_bchan(struct FsmInst *fi, int event, void *arg)
604{
605 struct Channel *chanp = fi->userdata;
606
607 chanp->data_open = 0;
608 FsmChangeState(fi, ST_WAIT_BREL_DISC);
609 chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
610}
611
612
613static void
614lli_rel_b_dhup(struct FsmInst *fi, int event, void *arg)
615{
616 struct Channel *chanp = fi->userdata;
617
618 release_b_st(chanp);
619 lli_dhup_close(fi, event, arg);
620}
621
622static void
623lli_bhup_dhup(struct FsmInst *fi, int event, void *arg)
624{
625 struct Channel *chanp = fi->userdata;
626
627 if (chanp->debug & 1)
628 link_debug(chanp, 0, "STAT_BHUP");
629 HL_LL(chanp, ISDN_STAT_BHUP);
630 lli_rel_b_dhup(fi, event, arg);
631}
632
633static void
634lli_abort(struct FsmInst *fi, int event, void *arg)
635{
636 struct Channel *chanp = fi->userdata;
637
638 chanp->data_open = 0;
639 chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
640 lli_bhup_dhup(fi, event, arg);
641}
642
643static void
644lli_release_req(struct FsmInst *fi, int event, void *arg)
645{
646 struct Channel *chanp = fi->userdata;
647
648 if (chanp->leased) {
649 lli_leased_hup(fi, chanp);
650 } else {
651 FsmChangeState(fi, ST_WAIT_D_REL_CNF);
652 chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST,
653 chanp->proc);
654 }
655}
656
657static void
658lli_rel_b_release_req(struct FsmInst *fi, int event, void *arg)
659{
660 struct Channel *chanp = fi->userdata;
661
662 release_b_st(chanp);
663 lli_release_req(fi, event, arg);
664}
665
666static void
667lli_bhup_release_req(struct FsmInst *fi, int event, void *arg)
668{
669 struct Channel *chanp = fi->userdata;
670
671 if (chanp->debug & 1)
672 link_debug(chanp, 0, "STAT_BHUP");
673 HL_LL(chanp, ISDN_STAT_BHUP);
674 lli_rel_b_release_req(fi, event, arg);
675}
676
677
678/* processing charge info */
679static void
680lli_charge_info(struct FsmInst *fi, int event, void *arg)
681{
682 struct Channel *chanp = fi->userdata;
683 isdn_ctrl ic;
684
685 ic.driver = chanp->cs->myid;
686 ic.command = ISDN_STAT_CINF;
687 ic.arg = chanp->chan;
688 sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo);
689 chanp->cs->iif.statcallb(&ic);
690}
691
692/* error procedures */
693
694static void
695lli_dchan_not_ready(struct FsmInst *fi, int event, void *arg)
696{
697 struct Channel *chanp = fi->userdata;
698
699 if (chanp->debug & 1)
700 link_debug(chanp, 0, "STAT_DHUP");
701 HL_LL(chanp, ISDN_STAT_DHUP);
702}
703
704static void
705lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg)
706{
707 struct Channel *chanp = fi->userdata;
708
709 if (chanp->debug & 1)
710 link_debug(chanp, 0, "STAT_DHUP");
711 HL_LL(chanp, ISDN_STAT_DHUP);
712 lli_close(fi);
713}
714
715static void
716lli_error(struct FsmInst *fi, int event, void *arg)
717{
718 FsmChangeState(fi, ST_WAIT_DRELEASE);
719}
720
721static void
722lli_failure_l(struct FsmInst *fi, int event, void *arg)
723{
724 struct Channel *chanp = fi->userdata;
725 isdn_ctrl ic;
726
727 FsmChangeState(fi, ST_NULL);
728 ic.driver = chanp->cs->myid;
729 ic.command = ISDN_STAT_CAUSE;
730 ic.arg = chanp->chan;
731 sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f);
732 chanp->cs->iif.statcallb(&ic);
733 HL_LL(chanp, ISDN_STAT_DHUP);
734 chanp->Flags = 0;
735 chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
736}
737
738static void
739lli_rel_b_fail(struct FsmInst *fi, int event, void *arg)
740{
741 struct Channel *chanp = fi->userdata;
742
743 release_b_st(chanp);
744 lli_failure_l(fi, event, arg);
745}
746
747static void
748lli_bhup_fail(struct FsmInst *fi, int event, void *arg)
749{
750 struct Channel *chanp = fi->userdata;
751
752 if (chanp->debug & 1)
753 link_debug(chanp, 0, "STAT_BHUP");
754 HL_LL(chanp, ISDN_STAT_BHUP);
755 lli_rel_b_fail(fi, event, arg);
756}
757
758static void
759lli_failure_a(struct FsmInst *fi, int event, void *arg)
760{
761 struct Channel *chanp = fi->userdata;
762
763 chanp->data_open = 0;
764 chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
765 lli_bhup_fail(fi, event, arg);
766}
767
768/* *INDENT-OFF* */
769static struct FsmNode fnlist[] __initdata =
770{
771 {ST_NULL, EV_DIAL, lli_prep_dialout},
772 {ST_NULL, EV_RESUME, lli_resume},
773 {ST_NULL, EV_SETUP_IND, lli_deliver_call},
774 {ST_NULL, EV_LEASED, lli_leased_in},
775 {ST_OUT_DIAL, EV_SETUP_CNF, lli_init_bchan_out},
776 {ST_OUT_DIAL, EV_HANGUP, lli_disconnect_req},
777 {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_release_req},
778 {ST_OUT_DIAL, EV_RELEASE, lli_dhup_close},
779 {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp},
780 {ST_OUT_DIAL, EV_SETUP_ERR, lli_error},
781 {ST_IN_WAIT_LL, EV_LEASED_REL, lli_failure_l},
782 {ST_IN_WAIT_LL, EV_ACCEPTD, lli_setup_rsp},
783 {ST_IN_WAIT_LL, EV_HANGUP, lli_reject_req},
784 {ST_IN_WAIT_LL, EV_DISCONNECT_IND, lli_release_req},
785 {ST_IN_WAIT_LL, EV_RELEASE, lli_dhup_close},
786 {ST_IN_WAIT_LL, EV_SETUP_IND, lli_deliver_call},
787 {ST_IN_WAIT_LL, EV_SETUP_ERR, lli_error},
788 {ST_IN_ALERT_SENT, EV_SETUP_CMPL_IND, lli_init_bchan_in},
789 {ST_IN_ALERT_SENT, EV_ACCEPTD, lli_send_dconnect},
790 {ST_IN_ALERT_SENT, EV_HANGUP, lli_disconnect_reject},
791 {ST_IN_ALERT_SENT, EV_DISCONNECT_IND, lli_release_req},
792 {ST_IN_ALERT_SENT, EV_RELEASE, lli_dhup_close},
793 {ST_IN_ALERT_SENT, EV_REDIR, lli_send_redir},
794 {ST_IN_PROCEED_SEND, EV_REDIR, lli_send_redir},
795 {ST_IN_PROCEED_SEND, EV_ALERT, lli_send_alert},
796 {ST_IN_PROCEED_SEND, EV_ACCEPTD, lli_send_dconnect},
797 {ST_IN_PROCEED_SEND, EV_HANGUP, lli_disconnect_reject},
798 {ST_IN_PROCEED_SEND, EV_DISCONNECT_IND, lli_dhup_close},
799 {ST_IN_ALERT_SENT, EV_RELEASE, lli_dhup_close},
800 {ST_IN_WAIT_CONN_ACK, EV_SETUP_CMPL_IND, lli_init_bchan_in},
801 {ST_IN_WAIT_CONN_ACK, EV_HANGUP, lli_disconnect_req},
802 {ST_IN_WAIT_CONN_ACK, EV_DISCONNECT_IND, lli_release_req},
803 {ST_IN_WAIT_CONN_ACK, EV_RELEASE, lli_dhup_close},
804 {ST_IN_WAIT_CONN_ACK, EV_CONNECT_ERR, lli_error},
805 {ST_WAIT_BCONN, EV_BC_EST, lli_go_active},
806 {ST_WAIT_BCONN, EV_BC_REL, lli_rel_b_disc},
807 {ST_WAIT_BCONN, EV_HANGUP, lli_rel_b_disc},
808 {ST_WAIT_BCONN, EV_DISCONNECT_IND, lli_rel_b_release_req},
809 {ST_WAIT_BCONN, EV_RELEASE, lli_rel_b_dhup},
810 {ST_WAIT_BCONN, EV_LEASED_REL, lli_rel_b_fail},
811 {ST_WAIT_BCONN, EV_CINF, lli_charge_info},
812 {ST_ACTIVE, EV_CINF, lli_charge_info},
813 {ST_ACTIVE, EV_BC_REL, lli_bhup_rel_b},
814 {ST_ACTIVE, EV_SUSPEND, lli_suspend},
815 {ST_ACTIVE, EV_HANGUP, lli_disconn_bchan},
816 {ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan},
817 {ST_ACTIVE, EV_RELEASE, lli_abort},
818 {ST_ACTIVE, EV_LEASED_REL, lli_failure_a},
819 {ST_WAIT_BRELEASE, EV_BC_REL, lli_bhup_disc},
820 {ST_WAIT_BRELEASE, EV_DISCONNECT_IND, lli_bhup_release_req},
821 {ST_WAIT_BRELEASE, EV_RELEASE, lli_bhup_dhup},
822 {ST_WAIT_BRELEASE, EV_LEASED_REL, lli_bhup_fail},
823 {ST_WAIT_BREL_DISC, EV_BC_REL, lli_bhup_release_req},
824 {ST_WAIT_BREL_DISC, EV_RELEASE, lli_bhup_dhup},
825 {ST_WAIT_DCOMMAND, EV_HANGUP, lli_start_disc},
826 {ST_WAIT_DCOMMAND, EV_DISCONNECT_IND, lli_release_req},
827 {ST_WAIT_DCOMMAND, EV_RELEASE, lli_dhup_close},
828 {ST_WAIT_DCOMMAND, EV_LEASED_REL, lli_failure_l},
829 {ST_WAIT_DRELEASE, EV_RELEASE, lli_dhup_close},
830 {ST_WAIT_DRELEASE, EV_DIAL, lli_dchan_not_ready},
831 /* ETS 300-104 16.1 */
832 {ST_WAIT_D_REL_CNF, EV_RELEASE, lli_dhup_close},
833 {ST_WAIT_D_REL_CNF, EV_DIAL, lli_dchan_not_ready},
834};
835/* *INDENT-ON* */
836
837#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
838
839int __init
840CallcNew(void)
841{
842 callcfsm.state_count = STATE_COUNT;
843 callcfsm.event_count = EVENT_COUNT;
844 callcfsm.strEvent = strEvent;
845 callcfsm.strState = strState;
846 return FsmNew(&callcfsm, fnlist, FNCOUNT);
847}
848
849void
850CallcFree(void)
851{
852 FsmFree(&callcfsm);
853}
854
855static void
856release_b_st(struct Channel *chanp)
857{
858 struct PStack *st = chanp->b_st;
859
860 if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) {
861 chanp->bcs->BC_Close(chanp->bcs);
862 switch (chanp->l2_active_protocol) {
863 case (ISDN_PROTO_L2_X75I):
864 releasestack_isdnl2(st);
865 break;
866 case (ISDN_PROTO_L2_HDLC):
867 case (ISDN_PROTO_L2_HDLC_56K):
868 case (ISDN_PROTO_L2_TRANS):
869 case (ISDN_PROTO_L2_MODEM):
870 case (ISDN_PROTO_L2_FAX):
871 releasestack_transl2(st);
872 break;
873 }
874 }
875}
876
877struct Channel
878*selectfreechannel(struct PStack *st, int bch)
879{
880 struct IsdnCardState *cs = st->l1.hardware;
881 struct Channel *chanp = st->lli.userdata;
882 int i;
883
884 if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
885 i=1;
886 else
887 i=0;
888
889 if (!bch) {
890 i = 2; /* virtual channel */
891 chanp += 2;
892 }
893
894 while (i < ((bch) ? cs->chanlimit : (2 + MAX_WAITING_CALLS))) {
895 if (chanp->fi.state == ST_NULL)
896 return (chanp);
897 chanp++;
898 i++;
899 }
900
901 if (bch) /* number of channels is limited */ {
902 i = 2; /* virtual channel */
903 chanp = st->lli.userdata;
904 chanp += i;
905 while (i < (2 + MAX_WAITING_CALLS)) {
906 if (chanp->fi.state == ST_NULL)
907 return (chanp);
908 chanp++;
909 i++;
910 }
911 }
912 return (NULL);
913}
914
915static void stat_redir_result(struct IsdnCardState *cs, int chan, ulong result)
916{ isdn_ctrl ic;
917
918 ic.driver = cs->myid;
919 ic.command = ISDN_STAT_REDIR;
920 ic.arg = chan;
921 ic.parm.num[0] = result;
922 cs->iif.statcallb(&ic);
923} /* stat_redir_result */
924
925static void
926dchan_l3l4(struct PStack *st, int pr, void *arg)
927{
928 struct l3_process *pc = arg;
929 struct IsdnCardState *cs = st->l1.hardware;
930 struct Channel *chanp;
931
932 if(!pc)
933 return;
934
935 if (pr == (CC_SETUP | INDICATION)) {
936 if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) {
937 pc->para.cause = 0x11; /* User busy */
938 pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc);
939 } else {
940 chanp->proc = pc;
941 pc->chan = chanp;
942 FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
943 }
944 return;
945 }
946 if (!(chanp = pc->chan))
947 return;
948
949 switch (pr) {
950 case (CC_MORE_INFO | INDICATION):
951 FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
952 break;
953 case (CC_DISCONNECT | INDICATION):
954 FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL);
955 break;
956 case (CC_RELEASE | CONFIRM):
957 FsmEvent(&chanp->fi, EV_RELEASE, NULL);
958 break;
959 case (CC_SUSPEND | CONFIRM):
960 FsmEvent(&chanp->fi, EV_RELEASE, NULL);
961 break;
962 case (CC_RESUME | CONFIRM):
963 FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
964 break;
965 case (CC_RESUME_ERR):
966 FsmEvent(&chanp->fi, EV_RELEASE, NULL);
967 break;
968 case (CC_RELEASE | INDICATION):
969 FsmEvent(&chanp->fi, EV_RELEASE, NULL);
970 break;
971 case (CC_SETUP_COMPL | INDICATION):
972 FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
973 break;
974 case (CC_SETUP | CONFIRM):
975 FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
976 break;
977 case (CC_CHARGE | INDICATION):
978 FsmEvent(&chanp->fi, EV_CINF, NULL);
979 break;
980 case (CC_NOSETUP_RSP):
981 FsmEvent(&chanp->fi, EV_NOSETUP_RSP, NULL);
982 break;
983 case (CC_SETUP_ERR):
984 FsmEvent(&chanp->fi, EV_SETUP_ERR, NULL);
985 break;
986 case (CC_CONNECT_ERR):
987 FsmEvent(&chanp->fi, EV_CONNECT_ERR, NULL);
988 break;
989 case (CC_RELEASE_ERR):
990 FsmEvent(&chanp->fi, EV_RELEASE, NULL);
991 break;
992 case (CC_PROCEED_SEND | INDICATION):
993 case (CC_PROCEEDING | INDICATION):
994 case (CC_ALERTING | INDICATION):
995 case (CC_PROGRESS | INDICATION):
996 case (CC_NOTIFY | INDICATION):
997 break;
998 case (CC_REDIR | INDICATION):
999 stat_redir_result(cs, chanp->chan, pc->redir_result);
1000 break;
1001 default:
1002 if (chanp->debug & 0x800) {
1003 HiSax_putstatus(chanp->cs, "Ch",
1004 "%d L3->L4 unknown primitiv %#x",
1005 chanp->chan, pr);
1006 }
1007 }
1008}
1009
1010static void
1011dummy_pstack(struct PStack *st, int pr, void *arg) {
1012 printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);
1013}
1014
1015static int
1016init_PStack(struct PStack **stp) {
1017 *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
1018 if (!*stp)
1019 return -ENOMEM;
1020 (*stp)->next = NULL;
1021 (*stp)->l1.l1l2 = dummy_pstack;
1022 (*stp)->l1.l1hw = dummy_pstack;
1023 (*stp)->l1.l1tei = dummy_pstack;
1024 (*stp)->l2.l2tei = dummy_pstack;
1025 (*stp)->l2.l2l1 = dummy_pstack;
1026 (*stp)->l2.l2l3 = dummy_pstack;
1027 (*stp)->l3.l3l2 = dummy_pstack;
1028 (*stp)->l3.l3ml3 = dummy_pstack;
1029 (*stp)->l3.l3l4 = dummy_pstack;
1030 (*stp)->lli.l4l3 = dummy_pstack;
1031 (*stp)->ma.layer = dummy_pstack;
1032 return 0;
1033}
1034
1035static int
1036init_d_st(struct Channel *chanp)
1037{
1038 struct PStack *st;
1039 struct IsdnCardState *cs = chanp->cs;
1040 char tmp[16];
1041 int err;
1042
1043 err = init_PStack(&chanp->d_st);
1044 if (err)
1045 return err;
1046 st = chanp->d_st;
1047 st->next = NULL;
1048 HiSax_addlist(cs, st);
1049 setstack_HiSax(st, cs);
1050 st->l2.sap = 0;
1051 st->l2.tei = -1;
1052 st->l2.flag = 0;
1053 test_and_set_bit(FLG_MOD128, &st->l2.flag);
1054 test_and_set_bit(FLG_LAPD, &st->l2.flag);
1055 test_and_set_bit(FLG_ORIG, &st->l2.flag);
1056 st->l2.maxlen = MAX_DFRAME_LEN;
1057 st->l2.window = 1;
1058 st->l2.T200 = 1000; /* 1000 milliseconds */
1059 st->l2.N200 = 3; /* try 3 times */
1060 st->l2.T203 = 10000; /* 10000 milliseconds */
1061 if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
1062 sprintf(tmp, "DCh%d Q.921 ", chanp->chan);
1063 else
1064 sprintf(tmp, "DCh Q.921 ");
1065 setstack_isdnl2(st, tmp);
1066 setstack_l3dc(st, chanp);
1067 st->lli.userdata = chanp;
1068 st->l3.l3l4 = dchan_l3l4;
1069
1070 return 0;
1071}
1072
1073static void
1074callc_debug(struct FsmInst *fi, char *fmt, ...)
1075{
1076 va_list args;
1077 struct Channel *chanp = fi->userdata;
1078 char tmp[16];
1079
1080 va_start(args, fmt);
1081 sprintf(tmp, "Ch%d callc ", chanp->chan);
1082 VHiSax_putstatus(chanp->cs, tmp, fmt, args);
1083 va_end(args);
1084}
1085
1086static int
1087init_chan(int chan, struct IsdnCardState *csta)
1088{
1089 struct Channel *chanp = csta->channel + chan;
1090 int err;
1091
1092 chanp->cs = csta;
1093 chanp->bcs = csta->bcs + chan;
1094 chanp->chan = chan;
1095 chanp->incoming = 0;
1096 chanp->debug = 0;
1097 chanp->Flags = 0;
1098 chanp->leased = 0;
1099 err = init_PStack(&chanp->b_st);
1100 if (err)
1101 return err;
1102 chanp->b_st->l1.delay = DEFAULT_B_DELAY;
1103 chanp->fi.fsm = &callcfsm;
1104 chanp->fi.state = ST_NULL;
1105 chanp->fi.debug = 0;
1106 chanp->fi.userdata = chanp;
1107 chanp->fi.printdebug = callc_debug;
1108 FsmInitTimer(&chanp->fi, &chanp->dial_timer);
1109 FsmInitTimer(&chanp->fi, &chanp->drel_timer);
1110 if (!chan || (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags) && chan < 2)) {
1111 err = init_d_st(chanp);
1112 if (err)
1113 return err;
1114 } else {
1115 chanp->d_st = csta->channel->d_st;
1116 }
1117 chanp->data_open = 0;
1118 return 0;
1119}
1120
1121int
1122CallcNewChan(struct IsdnCardState *csta) {
1123 int i, err;
1124
1125 chancount += 2;
1126 err = init_chan(0, csta);
1127 if (err)
1128 return err;
1129 err = init_chan(1, csta);
1130 if (err)
1131 return err;
1132 printk(KERN_INFO "HiSax: 2 channels added\n");
1133
1134 for (i = 0; i < MAX_WAITING_CALLS; i++) {
1135 err = init_chan(i+2,csta);
1136 if (err)
1137 return err;
1138 }
1139 printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n");
1140 if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) {
1141 printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
1142 csta->channel->d_st->lli.l4l3(csta->channel->d_st,
1143 DL_ESTABLISH | REQUEST, NULL);
1144 }
1145 return (0);
1146}
1147
1148static void
1149release_d_st(struct Channel *chanp)
1150{
1151 struct PStack *st = chanp->d_st;
1152
1153 if (!st)
1154 return;
1155 releasestack_isdnl2(st);
1156 releasestack_isdnl3(st);
1157 HiSax_rmlist(st->l1.hardware, st);
1158 kfree(st);
1159 chanp->d_st = NULL;
1160}
1161
1162void
1163CallcFreeChan(struct IsdnCardState *csta)
1164{
1165 int i;
1166
1167 for (i = 0; i < 2; i++) {
1168 FsmDelTimer(&csta->channel[i].drel_timer, 74);
1169 FsmDelTimer(&csta->channel[i].dial_timer, 75);
1170 if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
1171 release_d_st(csta->channel + i);
1172 if (csta->channel[i].b_st) {
1173 release_b_st(csta->channel + i);
1174 kfree(csta->channel[i].b_st);
1175 csta->channel[i].b_st = NULL;
1176 } else
1177 printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i);
1178 if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
1179 release_d_st(csta->channel + i);
1180 } else
1181 csta->channel[i].d_st = NULL;
1182 }
1183}
1184
1185static void
1186lldata_handler(struct PStack *st, int pr, void *arg)
1187{
1188 struct Channel *chanp = (struct Channel *) st->lli.userdata;
1189 struct sk_buff *skb = arg;
1190
1191 switch (pr) {
1192 case (DL_DATA | INDICATION):
1193 if (chanp->data_open) {
1194 if (chanp->debug & 0x800)
1195 link_debug(chanp, 0, "lldata: %d", skb->len);
1196 chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
1197 } else {
1198 link_debug(chanp, 0, "lldata: channel not open");
1199 dev_kfree_skb(skb);
1200 }
1201 break;
1202 case (DL_ESTABLISH | INDICATION):
1203 case (DL_ESTABLISH | CONFIRM):
1204 FsmEvent(&chanp->fi, EV_BC_EST, NULL);
1205 break;
1206 case (DL_RELEASE | INDICATION):
1207 case (DL_RELEASE | CONFIRM):
1208 FsmEvent(&chanp->fi, EV_BC_REL, NULL);
1209 break;
1210 default:
1211 printk(KERN_WARNING "lldata_handler unknown primitive %#x\n",
1212 pr);
1213 break;
1214 }
1215}
1216
1217static void
1218lltrans_handler(struct PStack *st, int pr, void *arg)
1219{
1220 struct Channel *chanp = (struct Channel *) st->lli.userdata;
1221 struct sk_buff *skb = arg;
1222
1223 switch (pr) {
1224 case (PH_DATA | INDICATION):
1225 if (chanp->data_open) {
1226 if (chanp->debug & 0x800)
1227 link_debug(chanp, 0, "lltrans: %d", skb->len);
1228 chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
1229 } else {
1230 link_debug(chanp, 0, "lltrans: channel not open");
1231 dev_kfree_skb(skb);
1232 }
1233 break;
1234 case (PH_ACTIVATE | INDICATION):
1235 case (PH_ACTIVATE | CONFIRM):
1236 FsmEvent(&chanp->fi, EV_BC_EST, NULL);
1237 break;
1238 case (PH_DEACTIVATE | INDICATION):
1239 case (PH_DEACTIVATE | CONFIRM):
1240 FsmEvent(&chanp->fi, EV_BC_REL, NULL);
1241 break;
1242 default:
1243 printk(KERN_WARNING "lltrans_handler unknown primitive %#x\n",
1244 pr);
1245 break;
1246 }
1247}
1248
1249void
1250lli_writewakeup(struct PStack *st, int len)
1251{
1252 struct Channel *chanp = st->lli.userdata;
1253 isdn_ctrl ic;
1254
1255 if (chanp->debug & 0x800)
1256 link_debug(chanp, 0, "llwakeup: %d", len);
1257 ic.driver = chanp->cs->myid;
1258 ic.command = ISDN_STAT_BSENT;
1259 ic.arg = chanp->chan;
1260 ic.parm.length = len;
1261 chanp->cs->iif.statcallb(&ic);
1262}
1263
1264static int
1265init_b_st(struct Channel *chanp, int incoming)
1266{
1267 struct PStack *st = chanp->b_st;
1268 struct IsdnCardState *cs = chanp->cs;
1269 char tmp[16];
1270
1271 st->l1.hardware = cs;
1272 if (chanp->leased)
1273 st->l1.bc = chanp->chan & 1;
1274 else
1275 st->l1.bc = chanp->proc->para.bchannel - 1;
1276 switch (chanp->l2_active_protocol) {
1277 case (ISDN_PROTO_L2_X75I):
1278 case (ISDN_PROTO_L2_HDLC):
1279 st->l1.mode = L1_MODE_HDLC;
1280 break;
1281 case (ISDN_PROTO_L2_HDLC_56K):
1282 st->l1.mode = L1_MODE_HDLC_56K;
1283 break;
1284 case (ISDN_PROTO_L2_TRANS):
1285 st->l1.mode = L1_MODE_TRANS;
1286 break;
1287 case (ISDN_PROTO_L2_MODEM):
1288 st->l1.mode = L1_MODE_V32;
1289 break;
1290 case (ISDN_PROTO_L2_FAX):
1291 st->l1.mode = L1_MODE_FAX;
1292 break;
1293 }
1294 chanp->bcs->conmsg = NULL;
1295 if (chanp->bcs->BC_SetStack(st, chanp->bcs))
1296 return (-1);
1297 st->l2.flag = 0;
1298 test_and_set_bit(FLG_LAPB, &st->l2.flag);
1299 st->l2.maxlen = MAX_DATA_SIZE;
1300 if (!incoming)
1301 test_and_set_bit(FLG_ORIG, &st->l2.flag);
1302 st->l2.T200 = 1000; /* 1000 milliseconds */
1303 st->l2.window = 7;
1304 st->l2.N200 = 4; /* try 4 times */
1305 st->l2.T203 = 5000; /* 5000 milliseconds */
1306 st->l3.debug = 0;
1307 switch (chanp->l2_active_protocol) {
1308 case (ISDN_PROTO_L2_X75I):
1309 sprintf(tmp, "Ch%d X.75", chanp->chan);
1310 setstack_isdnl2(st, tmp);
1311 setstack_l3bc(st, chanp);
1312 st->l2.l2l3 = lldata_handler;
1313 st->lli.userdata = chanp;
1314 test_and_clear_bit(FLG_LLI_L1WAKEUP, &st->lli.flag);
1315 test_and_set_bit(FLG_LLI_L2WAKEUP, &st->lli.flag);
1316 st->l2.l2m.debug = chanp->debug & 16;
1317 st->l2.debug = chanp->debug & 64;
1318 break;
1319 case (ISDN_PROTO_L2_HDLC):
1320 case (ISDN_PROTO_L2_HDLC_56K):
1321 case (ISDN_PROTO_L2_TRANS):
1322 case (ISDN_PROTO_L2_MODEM):
1323 case (ISDN_PROTO_L2_FAX):
1324 st->l1.l1l2 = lltrans_handler;
1325 st->lli.userdata = chanp;
1326 test_and_set_bit(FLG_LLI_L1WAKEUP, &st->lli.flag);
1327 test_and_clear_bit(FLG_LLI_L2WAKEUP, &st->lli.flag);
1328 setstack_transl2(st);
1329 setstack_l3bc(st, chanp);
1330 break;
1331 }
1332 test_and_set_bit(FLG_START_B, &chanp->Flags);
1333 return (0);
1334}
1335
1336static void
1337leased_l4l3(struct PStack *st, int pr, void *arg)
1338{
1339 struct Channel *chanp = (struct Channel *) st->lli.userdata;
1340 struct sk_buff *skb = arg;
1341
1342 switch (pr) {
1343 case (DL_DATA | REQUEST):
1344 link_debug(chanp, 0, "leased line d-channel DATA");
1345 dev_kfree_skb(skb);
1346 break;
1347 case (DL_ESTABLISH | REQUEST):
1348 st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
1349 break;
1350 case (DL_RELEASE | REQUEST):
1351 break;
1352 default:
1353 printk(KERN_WARNING "transd_l4l3 unknown primitive %#x\n",
1354 pr);
1355 break;
1356 }
1357}
1358
1359static void
1360leased_l1l2(struct PStack *st, int pr, void *arg)
1361{
1362 struct Channel *chanp = (struct Channel *) st->lli.userdata;
1363 struct sk_buff *skb = arg;
1364 int i,event = EV_LEASED_REL;
1365
1366 switch (pr) {
1367 case (PH_DATA | INDICATION):
1368 link_debug(chanp, 0, "leased line d-channel DATA");
1369 dev_kfree_skb(skb);
1370 break;
1371 case (PH_ACTIVATE | INDICATION):
1372 case (PH_ACTIVATE | CONFIRM):
1373 event = EV_LEASED;
1374 case (PH_DEACTIVATE | INDICATION):
1375 case (PH_DEACTIVATE | CONFIRM):
1376 if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags))
1377 i = 1;
1378 else
1379 i = 0;
1380 while (i < 2) {
1381 FsmEvent(&chanp->fi, event, NULL);
1382 chanp++;
1383 i++;
1384 }
1385 break;
1386 default:
1387 printk(KERN_WARNING
1388 "transd_l1l2 unknown primitive %#x\n", pr);
1389 break;
1390 }
1391}
1392
1393static void
1394distr_debug(struct IsdnCardState *csta, int debugflags)
1395{
1396 int i;
1397 struct Channel *chanp = csta->channel;
1398
1399 for (i = 0; i < (2 + MAX_WAITING_CALLS) ; i++) {
1400 chanp[i].debug = debugflags;
1401 chanp[i].fi.debug = debugflags & 2;
1402 chanp[i].d_st->l2.l2m.debug = debugflags & 8;
1403 chanp[i].b_st->l2.l2m.debug = debugflags & 0x10;
1404 chanp[i].d_st->l2.debug = debugflags & 0x20;
1405 chanp[i].b_st->l2.debug = debugflags & 0x40;
1406 chanp[i].d_st->l3.l3m.debug = debugflags & 0x80;
1407 chanp[i].b_st->l3.l3m.debug = debugflags & 0x100;
1408 chanp[i].b_st->ma.tei_m.debug = debugflags & 0x200;
1409 chanp[i].b_st->ma.debug = debugflags & 0x200;
1410 chanp[i].d_st->l1.l1m.debug = debugflags & 0x1000;
1411 chanp[i].b_st->l1.l1m.debug = debugflags & 0x2000;
1412 }
1413 if (debugflags & 4)
1414 csta->debug |= DEB_DLOG_HEX;
1415 else
1416 csta->debug &= ~DEB_DLOG_HEX;
1417}
1418
1419static char tmpbuf[256];
1420
1421static void
1422capi_debug(struct Channel *chanp, capi_msg *cm)
1423{
1424 char *t = tmpbuf;
1425
1426 t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length);
1427 t--;
1428 *t= 0;
1429 HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
1430}
1431
1432void
1433lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
1434 if ((cm->para[0] != 3) || (cm->para[1] != 0))
1435 return;
1436 if (cm->para[2]<3)
1437 return;
1438 if (cm->para[4] != 0)
1439 return;
1440 switch(cm->para[3]) {
1441 case 4: /* Suspend */
1442 strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
1443 FsmEvent(&chanp->fi, EV_SUSPEND, cm);
1444 break;
1445 case 5: /* Resume */
1446 strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
1447 if (chanp->fi.state == ST_NULL) {
1448 FsmEvent(&chanp->fi, EV_RESUME, cm);
1449 } else {
1450 FsmDelTimer(&chanp->dial_timer, 72);
1451 FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73);
1452 }
1453 break;
1454 }
1455}
1456
1457void
1458lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
1459 if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
1460 (cs->typ == ISDN_CTYPE_ELSA_PCI)) {
1461 if (cs->hw.elsa.MFlag) {
1462 cs->cardmsg(cs, CARD_AUX_IND, cm->para);
1463 }
1464 }
1465}
1466
1467
1468/***************************************************************/
1469/* Limit the available number of channels for the current card */
1470/***************************************************************/
1471static int
1472set_channel_limit(struct IsdnCardState *cs, int chanmax)
1473{
1474 isdn_ctrl ic;
1475 int i, ii;
1476
1477 if ((chanmax < 0) || (chanmax > 2))
1478 return(-EINVAL);
1479 cs->chanlimit = 0;
1480 for (ii = 0; ii < 2; ii++) {
1481 ic.driver = cs->myid;
1482 ic.command = ISDN_STAT_DISCH;
1483 ic.arg = ii;
1484 if (ii >= chanmax)
1485 ic.parm.num[0] = 0; /* disabled */
1486 else
1487 ic.parm.num[0] = 1; /* enabled */
1488 i = cs->iif.statcallb(&ic);
1489 if (i) return(-EINVAL);
1490 if (ii < chanmax)
1491 cs->chanlimit++;
1492 }
1493 return(0);
1494} /* set_channel_limit */
1495
1496int
1497HiSax_command(isdn_ctrl * ic)
1498{
1499 struct IsdnCardState *csta = hisax_findcard(ic->driver);
1500 struct PStack *st;
1501 struct Channel *chanp;
1502 int i;
1503 u_int num;
1504
1505 if (!csta) {
1506 printk(KERN_ERR
1507 "HiSax: if_command %d called with invalid driverId %d!\n",
1508 ic->command, ic->driver);
1509 return -ENODEV;
1510 }
1511 switch (ic->command) {
1512 case (ISDN_CMD_SETEAZ):
1513 chanp = csta->channel + ic->arg;
1514 break;
1515 case (ISDN_CMD_SETL2):
1516 chanp = csta->channel + (ic->arg & 0xff);
1517 if (chanp->debug & 1)
1518 link_debug(chanp, 1, "SETL2 card %d %ld",
1519 csta->cardnr + 1, ic->arg >> 8);
1520 chanp->l2_protocol = ic->arg >> 8;
1521 break;
1522 case (ISDN_CMD_SETL3):
1523 chanp = csta->channel + (ic->arg & 0xff);
1524 if (chanp->debug & 1)
1525 link_debug(chanp, 1, "SETL3 card %d %ld",
1526 csta->cardnr + 1, ic->arg >> 8);
1527 chanp->l3_protocol = ic->arg >> 8;
1528 break;
1529 case (ISDN_CMD_DIAL):
1530 chanp = csta->channel + (ic->arg & 0xff);
1531 if (chanp->debug & 1)
1532 link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
1533 ic->parm.setup.eazmsn, ic->parm.setup.phone,
1534 ic->parm.setup.si1, ic->parm.setup.si2);
1535 memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
1536 if (!strcmp(chanp->setup.eazmsn, "0"))
1537 chanp->setup.eazmsn[0] = '\0';
1538 /* this solution is dirty and may be change, if
1539 * we make a callreference based callmanager */
1540 if (chanp->fi.state == ST_NULL) {
1541 FsmEvent(&chanp->fi, EV_DIAL, NULL);
1542 } else {
1543 FsmDelTimer(&chanp->dial_timer, 70);
1544 FsmAddTimer(&chanp->dial_timer, 50, EV_DIAL, NULL, 71);
1545 }
1546 break;
1547 case (ISDN_CMD_ACCEPTB):
1548 chanp = csta->channel + ic->arg;
1549 if (chanp->debug & 1)
1550 link_debug(chanp, 1, "ACCEPTB");
1551 FsmEvent(&chanp->fi, EV_ACCEPTB, NULL);
1552 break;
1553 case (ISDN_CMD_ACCEPTD):
1554 chanp = csta->channel + ic->arg;
1555 memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
1556 if (chanp->debug & 1)
1557 link_debug(chanp, 1, "ACCEPTD");
1558 FsmEvent(&chanp->fi, EV_ACCEPTD, NULL);
1559 break;
1560 case (ISDN_CMD_HANGUP):
1561 chanp = csta->channel + ic->arg;
1562 if (chanp->debug & 1)
1563 link_debug(chanp, 1, "HANGUP");
1564 FsmEvent(&chanp->fi, EV_HANGUP, NULL);
1565 break;
1566 case (CAPI_PUT_MESSAGE):
1567 chanp = csta->channel + ic->arg;
1568 if (chanp->debug & 1)
1569 capi_debug(chanp, &ic->parm.cmsg);
1570 if (ic->parm.cmsg.Length < 8)
1571 break;
1572 switch(ic->parm.cmsg.Command) {
1573 case CAPI_FACILITY:
1574 if (ic->parm.cmsg.Subcommand == CAPI_REQ)
1575 lli_got_fac_req(chanp, &ic->parm.cmsg);
1576 break;
1577 case CAPI_MANUFACTURER:
1578 if (ic->parm.cmsg.Subcommand == CAPI_REQ)
1579 lli_got_manufacturer(chanp, csta, &ic->parm.cmsg);
1580 break;
1581 default:
1582 break;
1583 }
1584 break;
1585 case (ISDN_CMD_IOCTL):
1586 switch (ic->arg) {
1587 case (0):
1588 num = *(unsigned int *) ic->parm.num;
1589 HiSax_reportcard(csta->cardnr, num);
1590 break;
1591 case (1):
1592 num = *(unsigned int *) ic->parm.num;
1593 distr_debug(csta, num);
1594 printk(KERN_DEBUG "HiSax: debugging flags card %d set to %x\n",
1595 csta->cardnr + 1, num);
1596 HiSax_putstatus(csta, "debugging flags ",
1597 "card %d set to %x", csta->cardnr + 1, num);
1598 break;
1599 case (2):
1600 num = *(unsigned int *) ic->parm.num;
1601 csta->channel[0].b_st->l1.delay = num;
1602 csta->channel[1].b_st->l1.delay = num;
1603 HiSax_putstatus(csta, "delay ", "card %d set to %d ms",
1604 csta->cardnr + 1, num);
1605 printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n",
1606 csta->cardnr + 1, num);
1607 break;
1608 case (5): /* set card in leased mode */
1609 num = *(unsigned int *) ic->parm.num;
1610 if ((num <1) || (num > 2)) {
1611 HiSax_putstatus(csta, "Set LEASED ",
1612 "wrong channel %d", num);
1613 printk(KERN_WARNING "HiSax: Set LEASED wrong channel %d\n",
1614 num);
1615 } else {
1616 num--;
1617 chanp = csta->channel +num;
1618 chanp->leased = 1;
1619 HiSax_putstatus(csta, "Card",
1620 "%d channel %d set leased mode\n",
1621 csta->cardnr + 1, num + 1);
1622 chanp->d_st->l1.l1l2 = leased_l1l2;
1623 chanp->d_st->lli.l4l3 = leased_l4l3;
1624 chanp->d_st->lli.l4l3(chanp->d_st,
1625 DL_ESTABLISH | REQUEST, NULL);
1626 }
1627 break;
1628 case (6): /* set B-channel test loop */
1629 num = *(unsigned int *) ic->parm.num;
1630 if (csta->stlist)
1631 csta->stlist->l2.l2l1(csta->stlist,
1632 PH_TESTLOOP | REQUEST, (void *) (long)num);
1633 break;
1634 case (7): /* set card in PTP mode */
1635 num = *(unsigned int *) ic->parm.num;
1636 if (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
1637 printk(KERN_ERR "HiSax PTP mode only with one TEI possible\n");
1638 } else if (num) {
1639 test_and_set_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
1640 test_and_set_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
1641 csta->channel[0].d_st->l2.tei = 0;
1642 HiSax_putstatus(csta, "set card ", "in PTP mode");
1643 printk(KERN_DEBUG "HiSax: set card in PTP mode\n");
1644 printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
1645 csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st,
1646 DL_ESTABLISH | REQUEST, NULL);
1647 } else {
1648 test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
1649 test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
1650 HiSax_putstatus(csta, "set card ", "in PTMP mode");
1651 printk(KERN_DEBUG "HiSax: set card in PTMP mode\n");
1652 }
1653 break;
1654 case (8): /* set card in FIXED TEI mode */
1655 num = *(unsigned int *) ic->parm.num;
1656 chanp = csta->channel + (num & 1);
1657 num = num >>1;
1658 if (num == 127) {
1659 test_and_clear_bit(FLG_FIXED_TEI, &chanp->d_st->l2.flag);
1660 chanp->d_st->l2.tei = -1;
1661 HiSax_putstatus(csta, "set card ", "in VAR TEI mode");
1662 printk(KERN_DEBUG "HiSax: set card in VAR TEI mode\n");
1663 } else {
1664 test_and_set_bit(FLG_FIXED_TEI, &chanp->d_st->l2.flag);
1665 chanp->d_st->l2.tei = num;
1666 HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num);
1667 printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n",
1668 num);
1669 }
1670 chanp->d_st->lli.l4l3(chanp->d_st,
1671 DL_ESTABLISH | REQUEST, NULL);
1672 break;
1673 case (11):
1674 num = csta->debug & DEB_DLOG_HEX;
1675 csta->debug = *(unsigned int *) ic->parm.num;
1676 csta->debug |= num;
1677 HiSax_putstatus(cards[0].cs, "l1 debugging ",
1678 "flags card %d set to %x",
1679 csta->cardnr + 1, csta->debug);
1680 printk(KERN_DEBUG "HiSax: l1 debugging flags card %d set to %x\n",
1681 csta->cardnr + 1, csta->debug);
1682 break;
1683 case (13):
1684 csta->channel[0].d_st->l3.debug = *(unsigned int *) ic->parm.num;
1685 csta->channel[1].d_st->l3.debug = *(unsigned int *) ic->parm.num;
1686 HiSax_putstatus(cards[0].cs, "l3 debugging ",
1687 "flags card %d set to %x\n", csta->cardnr + 1,
1688 *(unsigned int *) ic->parm.num);
1689 printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n",
1690 csta->cardnr + 1, *(unsigned int *) ic->parm.num);
1691 break;
1692 case (10):
1693 i = *(unsigned int *) ic->parm.num;
1694 return(set_channel_limit(csta, i));
1695 default:
1696 if (csta->auxcmd)
1697 return(csta->auxcmd(csta, ic));
1698 printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
1699 (int) ic->arg);
1700 return (-EINVAL);
1701 }
1702 break;
1703
1704 case (ISDN_CMD_PROCEED):
1705 chanp = csta->channel + ic->arg;
1706 if (chanp->debug & 1)
1707 link_debug(chanp, 1, "PROCEED");
1708 FsmEvent(&chanp->fi, EV_PROCEED, NULL);
1709 break;
1710
1711 case (ISDN_CMD_ALERT):
1712 chanp = csta->channel + ic->arg;
1713 if (chanp->debug & 1)
1714 link_debug(chanp, 1, "ALERT");
1715 FsmEvent(&chanp->fi, EV_ALERT, NULL);
1716 break;
1717
1718 case (ISDN_CMD_REDIR):
1719 chanp = csta->channel + ic->arg;
1720 if (chanp->debug & 1)
1721 link_debug(chanp, 1, "REDIR");
1722 memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
1723 FsmEvent(&chanp->fi, EV_REDIR, NULL);
1724 break;
1725
1726 /* protocol specific io commands */
1727 case (ISDN_CMD_PROT_IO):
1728 for (st = csta->stlist; st; st = st->next)
1729 if (st->protocol == (ic->arg & 0xFF))
1730 return(st->lli.l4l3_proto(st, ic));
1731 return(-EINVAL);
1732 break;
1733 default:
1734 if (csta->auxcmd)
1735 return(csta->auxcmd(csta, ic));
1736 return(-EINVAL);
1737 }
1738 return (0);
1739}
1740
1741int
1742HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb)
1743{
1744 struct IsdnCardState *csta = hisax_findcard(id);
1745 struct Channel *chanp;
1746 struct PStack *st;
1747 int len = skb->len;
1748 struct sk_buff *nskb;
1749
1750 if (!csta) {
1751 printk(KERN_ERR
1752 "HiSax: if_sendbuf called with invalid driverId!\n");
1753 return -ENODEV;
1754 }
1755 chanp = csta->channel + chan;
1756 st = chanp->b_st;
1757 if (!chanp->data_open) {
1758 link_debug(chanp, 1, "writebuf: channel not open");
1759 return -EIO;
1760 }
1761 if (len > MAX_DATA_SIZE) {
1762 link_debug(chanp, 1, "writebuf: packet too large (%d bytes)", len);
1763 printk(KERN_WARNING "HiSax_writebuf: packet too large (%d bytes) !\n",
1764 len);
1765 return -EINVAL;
1766 }
1767 if (len) {
1768 if ((len + chanp->bcs->tx_cnt) > MAX_DATA_MEM) {
1769 /* Must return 0 here, since this is not an error
1770 * but a temporary lack of resources.
1771 */
1772 if (chanp->debug & 0x800)
1773 link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len);
1774 return 0;
1775 } else if (chanp->debug & 0x800)
1776 link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM);
1777 nskb = skb_clone(skb, GFP_ATOMIC);
1778 if (nskb) {
1779 nskb->truesize = nskb->len;
1780 if (!ack)
1781 nskb->pkt_type = PACKET_NOACK;
1782 if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I)
1783 st->l3.l3l2(st, DL_DATA | REQUEST, nskb);
1784 else {
1785 chanp->bcs->tx_cnt += len;
1786 st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
1787 }
1788 dev_kfree_skb(skb);
1789 } else
1790 len = 0;
1791 }
1792 return (len);
1793}
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
new file mode 100644
index 00000000000..1663ee69d41
--- /dev/null
+++ b/drivers/isdn/hisax/config.c
@@ -0,0 +1,1958 @@
1/* $Id: config.c,v 2.84.2.5 2004/02/11 13:21:33 keil Exp $
2 *
3 * Author Karsten Keil
4 * Copyright by Karsten Keil <keil@isdn4linux.de>
5 * by Kai Germaschewski <kai.germaschewski@gmx.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
12 *
13 * based on the teles driver from Jan den Ouden
14 *
15 */
16
17#include <linux/types.h>
18#include <linux/stddef.h>
19#include <linux/timer.h>
20#include <linux/config.h>
21#include <linux/init.h>
22#include "hisax.h"
23#include <linux/module.h>
24#include <linux/kernel_stat.h>
25#include <linux/workqueue.h>
26#include <linux/interrupt.h>
27#define HISAX_STATUS_BUFSIZE 4096
28#define INCLUDE_INLINE_FUNCS
29
30/*
31 * This structure array contains one entry per card. An entry looks
32 * like this:
33 *
34 * { type, protocol, p0, p1, p2, NULL }
35 *
36 * type
37 * 1 Teles 16.0 p0=irq p1=membase p2=iobase
38 * 2 Teles 8.0 p0=irq p1=membase
39 * 3 Teles 16.3 p0=irq p1=iobase
40 * 4 Creatix PNP p0=irq p1=IO0 (ISAC) p2=IO1 (HSCX)
41 * 5 AVM A1 (Fritz) p0=irq p1=iobase
42 * 6 ELSA PC [p0=iobase] or nothing (autodetect)
43 * 7 ELSA Quickstep p0=irq p1=iobase
44 * 8 Teles PCMCIA p0=irq p1=iobase
45 * 9 ITK ix1-micro p0=irq p1=iobase
46 * 10 ELSA PCMCIA p0=irq p1=iobase
47 * 11 Eicon.Diehl Diva p0=irq p1=iobase
48 * 12 Asuscom ISDNLink p0=irq p1=iobase
49 * 13 Teleint p0=irq p1=iobase
50 * 14 Teles 16.3c p0=irq p1=iobase
51 * 15 Sedlbauer speed p0=irq p1=iobase
52 * 15 Sedlbauer PC/104 p0=irq p1=iobase
53 * 15 Sedlbauer speed pci no parameter
54 * 16 USR Sportster internal p0=irq p1=iobase
55 * 17 MIC card p0=irq p1=iobase
56 * 18 ELSA Quickstep 1000PCI no parameter
57 * 19 Compaq ISDN S0 ISA card p0=irq p1=IO0 (HSCX) p2=IO1 (ISAC) p3=IO2
58 * 20 Travers Technologies NETjet-S PCI card
59 * 21 TELES PCI no parameter
60 * 22 Sedlbauer Speed Star p0=irq p1=iobase
61 * 23 reserved
62 * 24 Dr Neuhaus Niccy PnP/PCI card p0=irq p1=IO0 p2=IO1 (PnP only)
63 * 25 Teles S0Box p0=irq p1=iobase (from isapnp setup)
64 * 26 AVM A1 PCMCIA (Fritz) p0=irq p1=iobase
65 * 27 AVM PnP/PCI p0=irq p1=iobase (PCI no parameter)
66 * 28 Sedlbauer Speed Fax+ p0=irq p1=iobase (from isapnp setup)
67 * 29 Siemens I-Surf p0=irq p1=iobase p2=memory (from isapnp setup)
68 * 30 ACER P10 p0=irq p1=iobase (from isapnp setup)
69 * 31 HST Saphir p0=irq p1=iobase
70 * 32 Telekom A4T none
71 * 33 Scitel Quadro p0=subcontroller (4*S0, subctrl 1...4)
72 * 34 Gazel ISDN cards
73 * 35 HFC 2BDS0 PCI none
74 * 36 Winbond 6692 PCI none
75 * 37 HFC 2BDS0 S+/SP p0=irq p1=iobase
76 * 38 Travers Technologies NETspider-U PCI card
77 * 39 HFC 2BDS0-SP PCMCIA p0=irq p1=iobase
78 * 40 hotplug interface
79 * 41 Formula-n enter:now ISDN PCI a/b none
80 *
81 * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
82 *
83 *
84 */
85
86const char *CardType[] = {
87 "No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3",
88 "Creatix/Teles PnP", "AVM A1", "Elsa ML", "Elsa Quickstep",
89 "Teles PCMCIA", "ITK ix1-micro Rev.2", "Elsa PCMCIA",
90 "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c",
91 "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux",
92 "Elsa PCI", "Compaq ISA", "NETjet-S", "Teles PCI",
93 "Sedlbauer Speed Star (PCMCIA)", "AMD 7930", "NICCY", "S0Box",
94 "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", "Sedlbauer Speed Fax +",
95 "Siemens I-Surf", "Acer P10", "HST Saphir", "Telekom A4T",
96 "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
97 "HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
98 "Hotplug", "Formula-n enter:now PCI a/b",
99};
100
101#ifdef CONFIG_HISAX_ELSA
102#define DEFAULT_CARD ISDN_CTYPE_ELSA
103#define DEFAULT_CFG {0,0,0,0}
104#endif
105
106#ifdef CONFIG_HISAX_AVM_A1
107#undef DEFAULT_CARD
108#undef DEFAULT_CFG
109#define DEFAULT_CARD ISDN_CTYPE_A1
110#define DEFAULT_CFG {10,0x340,0,0}
111#endif
112
113#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
114#undef DEFAULT_CARD
115#undef DEFAULT_CFG
116#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
117#define DEFAULT_CFG {11,0x170,0,0}
118#endif
119
120#ifdef CONFIG_HISAX_FRITZPCI
121#undef DEFAULT_CARD
122#undef DEFAULT_CFG
123#define DEFAULT_CARD ISDN_CTYPE_FRITZPCI
124#define DEFAULT_CFG {0,0,0,0}
125#endif
126
127#ifdef CONFIG_HISAX_16_3
128#undef DEFAULT_CARD
129#undef DEFAULT_CFG
130#define DEFAULT_CARD ISDN_CTYPE_16_3
131#define DEFAULT_CFG {15,0x180,0,0}
132#endif
133
134#ifdef CONFIG_HISAX_S0BOX
135#undef DEFAULT_CARD
136#undef DEFAULT_CFG
137#define DEFAULT_CARD ISDN_CTYPE_S0BOX
138#define DEFAULT_CFG {7,0x378,0,0}
139#endif
140
141#ifdef CONFIG_HISAX_16_0
142#undef DEFAULT_CARD
143#undef DEFAULT_CFG
144#define DEFAULT_CARD ISDN_CTYPE_16_0
145#define DEFAULT_CFG {15,0xd0000,0xd80,0}
146#endif
147
148#ifdef CONFIG_HISAX_TELESPCI
149#undef DEFAULT_CARD
150#undef DEFAULT_CFG
151#define DEFAULT_CARD ISDN_CTYPE_TELESPCI
152#define DEFAULT_CFG {0,0,0,0}
153#endif
154
155#ifdef CONFIG_HISAX_IX1MICROR2
156#undef DEFAULT_CARD
157#undef DEFAULT_CFG
158#define DEFAULT_CARD ISDN_CTYPE_IX1MICROR2
159#define DEFAULT_CFG {5,0x390,0,0}
160#endif
161
162#ifdef CONFIG_HISAX_DIEHLDIVA
163#undef DEFAULT_CARD
164#undef DEFAULT_CFG
165#define DEFAULT_CARD ISDN_CTYPE_DIEHLDIVA
166#define DEFAULT_CFG {0,0x0,0,0}
167#endif
168
169#ifdef CONFIG_HISAX_ASUSCOM
170#undef DEFAULT_CARD
171#undef DEFAULT_CFG
172#define DEFAULT_CARD ISDN_CTYPE_ASUSCOM
173#define DEFAULT_CFG {5,0x200,0,0}
174#endif
175
176#ifdef CONFIG_HISAX_TELEINT
177#undef DEFAULT_CARD
178#undef DEFAULT_CFG
179#define DEFAULT_CARD ISDN_CTYPE_TELEINT
180#define DEFAULT_CFG {5,0x300,0,0}
181#endif
182
183#ifdef CONFIG_HISAX_SEDLBAUER
184#undef DEFAULT_CARD
185#undef DEFAULT_CFG
186#define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
187#define DEFAULT_CFG {11,0x270,0,0}
188#endif
189
190#ifdef CONFIG_HISAX_SPORTSTER
191#undef DEFAULT_CARD
192#undef DEFAULT_CFG
193#define DEFAULT_CARD ISDN_CTYPE_SPORTSTER
194#define DEFAULT_CFG {7,0x268,0,0}
195#endif
196
197#ifdef CONFIG_HISAX_MIC
198#undef DEFAULT_CARD
199#undef DEFAULT_CFG
200#define DEFAULT_CARD ISDN_CTYPE_MIC
201#define DEFAULT_CFG {12,0x3e0,0,0}
202#endif
203
204#ifdef CONFIG_HISAX_NETJET
205#undef DEFAULT_CARD
206#undef DEFAULT_CFG
207#define DEFAULT_CARD ISDN_CTYPE_NETJET_S
208#define DEFAULT_CFG {0,0,0,0}
209#endif
210
211#ifdef CONFIG_HISAX_HFCS
212#undef DEFAULT_CARD
213#undef DEFAULT_CFG
214#define DEFAULT_CARD ISDN_CTYPE_TELES3C
215#define DEFAULT_CFG {5,0x500,0,0}
216#endif
217
218#ifdef CONFIG_HISAX_HFC_PCI
219#undef DEFAULT_CARD
220#undef DEFAULT_CFG
221#define DEFAULT_CARD ISDN_CTYPE_HFC_PCI
222#define DEFAULT_CFG {0,0,0,0}
223#endif
224
225#ifdef CONFIG_HISAX_HFC_SX
226#undef DEFAULT_CARD
227#undef DEFAULT_CFG
228#define DEFAULT_CARD ISDN_CTYPE_HFC_SX
229#define DEFAULT_CFG {5,0x2E0,0,0}
230#endif
231
232
233#ifdef CONFIG_HISAX_AMD7930
234#undef DEFAULT_CARD
235#undef DEFAULT_CFG
236#define DEFAULT_CARD ISDN_CTYPE_AMD7930
237#define DEFAULT_CFG {12,0x3e0,0,0}
238#endif
239
240#ifdef CONFIG_HISAX_NICCY
241#undef DEFAULT_CARD
242#undef DEFAULT_CFG
243#define DEFAULT_CARD ISDN_CTYPE_NICCY
244#define DEFAULT_CFG {0,0x0,0,0}
245#endif
246
247#ifdef CONFIG_HISAX_ISURF
248#undef DEFAULT_CARD
249#undef DEFAULT_CFG
250#define DEFAULT_CARD ISDN_CTYPE_ISURF
251#define DEFAULT_CFG {5,0x100,0xc8000,0}
252#endif
253
254#ifdef CONFIG_HISAX_HSTSAPHIR
255#undef DEFAULT_CARD
256#undef DEFAULT_CFG
257#define DEFAULT_CARD ISDN_CTYPE_HSTSAPHIR
258#define DEFAULT_CFG {5,0x250,0,0}
259#endif
260
261#ifdef CONFIG_HISAX_BKM_A4T
262#undef DEFAULT_CARD
263#undef DEFAULT_CFG
264#define DEFAULT_CARD ISDN_CTYPE_BKM_A4T
265#define DEFAULT_CFG {0,0x0,0,0}
266#endif
267
268#ifdef CONFIG_HISAX_SCT_QUADRO
269#undef DEFAULT_CARD
270#undef DEFAULT_CFG
271#define DEFAULT_CARD ISDN_CTYPE_SCT_QUADRO
272#define DEFAULT_CFG {1,0x0,0,0}
273#endif
274
275#ifdef CONFIG_HISAX_GAZEL
276#undef DEFAULT_CARD
277#undef DEFAULT_CFG
278#define DEFAULT_CARD ISDN_CTYPE_GAZEL
279#define DEFAULT_CFG {15,0x180,0,0}
280#endif
281
282#ifdef CONFIG_HISAX_W6692
283#undef DEFAULT_CARD
284#undef DEFAULT_CFG
285#define DEFAULT_CARD ISDN_CTYPE_W6692
286#define DEFAULT_CFG {0,0,0,0}
287#endif
288
289#ifdef CONFIG_HISAX_NETJET_U
290#undef DEFAULT_CARD
291#undef DEFAULT_CFG
292#define DEFAULT_CARD ISDN_CTYPE_NETJET_U
293#define DEFAULT_CFG {0,0,0,0}
294#endif
295
296#ifdef CONFIG_HISAX_1TR6
297#define DEFAULT_PROTO ISDN_PTYPE_1TR6
298#define DEFAULT_PROTO_NAME "1TR6"
299#endif
300#ifdef CONFIG_HISAX_NI1
301#undef DEFAULT_PROTO
302#define DEFAULT_PROTO ISDN_PTYPE_NI1
303#undef DEFAULT_PROTO_NAME
304#define DEFAULT_PROTO_NAME "NI1"
305#endif
306#ifdef CONFIG_HISAX_EURO
307#undef DEFAULT_PROTO
308#define DEFAULT_PROTO ISDN_PTYPE_EURO
309#undef DEFAULT_PROTO_NAME
310#define DEFAULT_PROTO_NAME "EURO"
311#endif
312#ifndef DEFAULT_PROTO
313#define DEFAULT_PROTO ISDN_PTYPE_UNKNOWN
314#define DEFAULT_PROTO_NAME "UNKNOWN"
315#endif
316#ifndef DEFAULT_CARD
317#define DEFAULT_CARD 0
318#define DEFAULT_CFG {0,0,0,0}
319#endif
320
321#define FIRST_CARD { \
322 DEFAULT_CARD, \
323 DEFAULT_PROTO, \
324 DEFAULT_CFG, \
325 NULL, \
326}
327
328struct IsdnCard cards[HISAX_MAX_CARDS] = {
329 FIRST_CARD,
330};
331
332#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
333static char HiSaxID[HISAX_IDSIZE] = { 0, };
334
335char *HiSax_id = HiSaxID;
336#ifdef MODULE
337/* Variables for insmod */
338static int type[HISAX_MAX_CARDS] = { 0, };
339static int protocol[HISAX_MAX_CARDS] = { 0, };
340static int io[HISAX_MAX_CARDS] = { 0, };
341#undef IO0_IO1
342#ifdef CONFIG_HISAX_16_3
343#define IO0_IO1
344#endif
345#ifdef CONFIG_HISAX_NICCY
346#undef IO0_IO1
347#define IO0_IO1
348#endif
349#ifdef IO0_IO1
350static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
351static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
352#endif
353static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
354static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
355static char *id = HiSaxID;
356
357MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
358MODULE_AUTHOR("Karsten Keil");
359MODULE_LICENSE("GPL");
360module_param_array(type, int, NULL, 0);
361module_param_array(protocol, int, NULL, 0);
362module_param_array(io, int, NULL, 0);
363module_param_array(irq, int, NULL, 0);
364module_param_array(mem, int, NULL, 0);
365module_param(id, charp, 0);
366#ifdef IO0_IO1
367module_param_array(io0, int, NULL, 0);
368module_param_array(io1, int, NULL, 0);
369#endif
370#endif /* MODULE */
371
372int nrcards;
373
374extern char *l1_revision;
375extern char *l2_revision;
376extern char *l3_revision;
377extern char *lli_revision;
378extern char *tei_revision;
379
380char *HiSax_getrev(const char *revision)
381{
382 char *rev;
383 char *p;
384
385 if ((p = strchr(revision, ':'))) {
386 rev = p + 2;
387 p = strchr(rev, '$');
388 *--p = 0;
389 } else
390 rev = "???";
391 return rev;
392}
393
394void __init HiSaxVersion(void)
395{
396 char tmp[64];
397
398 printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
399#ifdef MODULE
400 printk(KERN_INFO "HiSax: Version 3.5 (module)\n");
401#else
402 printk(KERN_INFO "HiSax: Version 3.5 (kernel)\n");
403#endif
404 strcpy(tmp, l1_revision);
405 printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
406 strcpy(tmp, l2_revision);
407 printk(KERN_INFO "HiSax: Layer2 Revision %s\n", HiSax_getrev(tmp));
408 strcpy(tmp, tei_revision);
409 printk(KERN_INFO "HiSax: TeiMgr Revision %s\n", HiSax_getrev(tmp));
410 strcpy(tmp, l3_revision);
411 printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp));
412 strcpy(tmp, lli_revision);
413 printk(KERN_INFO "HiSax: LinkLayer Revision %s\n",
414 HiSax_getrev(tmp));
415}
416
417#ifndef MODULE
418#define MAX_ARG (HISAX_MAX_CARDS*5)
419static int __init HiSax_setup(char *line)
420{
421 int i, j, argc;
422 int ints[MAX_ARG + 1];
423 char *str;
424
425 str = get_options(line, MAX_ARG, ints);
426 argc = ints[0];
427 printk(KERN_DEBUG "HiSax_setup: argc(%d) str(%s)\n", argc, str);
428 i = 0;
429 j = 1;
430 while (argc && (i < HISAX_MAX_CARDS)) {
431 cards[i].protocol = DEFAULT_PROTO;
432 if (argc) {
433 cards[i].typ = ints[j];
434 j++;
435 argc--;
436 }
437 if (argc) {
438 cards[i].protocol = ints[j];
439 j++;
440 argc--;
441 }
442 if (argc) {
443 cards[i].para[0] = ints[j];
444 j++;
445 argc--;
446 }
447 if (argc) {
448 cards[i].para[1] = ints[j];
449 j++;
450 argc--;
451 }
452 if (argc) {
453 cards[i].para[2] = ints[j];
454 j++;
455 argc--;
456 }
457 i++;
458 }
459 if (str && *str) {
460 if (strlen(str) < HISAX_IDSIZE)
461 strcpy(HiSaxID, str);
462 else
463 printk(KERN_WARNING "HiSax: ID too long!");
464 } else
465 strcpy(HiSaxID, "HiSax");
466
467 HiSax_id = HiSaxID;
468 return 1;
469}
470
471__setup("hisax=", HiSax_setup);
472#endif /* MODULES */
473
474#if CARD_TELES0
475extern int setup_teles0(struct IsdnCard *card);
476#endif
477
478#if CARD_TELES3
479extern int setup_teles3(struct IsdnCard *card);
480#endif
481
482#if CARD_S0BOX
483extern int setup_s0box(struct IsdnCard *card);
484#endif
485
486#if CARD_TELESPCI
487extern int setup_telespci(struct IsdnCard *card);
488#endif
489
490#if CARD_AVM_A1
491extern int setup_avm_a1(struct IsdnCard *card);
492#endif
493
494#if CARD_AVM_A1_PCMCIA
495extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
496#endif
497
498#if CARD_FRITZPCI
499extern int setup_avm_pcipnp(struct IsdnCard *card);
500#endif
501
502#if CARD_ELSA
503extern int setup_elsa(struct IsdnCard *card);
504#endif
505
506#if CARD_IX1MICROR2
507extern int setup_ix1micro(struct IsdnCard *card);
508#endif
509
510#if CARD_DIEHLDIVA
511extern int setup_diva(struct IsdnCard *card);
512#endif
513
514#if CARD_ASUSCOM
515extern int setup_asuscom(struct IsdnCard *card);
516#endif
517
518#if CARD_TELEINT
519extern int setup_TeleInt(struct IsdnCard *card);
520#endif
521
522#if CARD_SEDLBAUER
523extern int setup_sedlbauer(struct IsdnCard *card);
524#endif
525
526#if CARD_SPORTSTER
527extern int setup_sportster(struct IsdnCard *card);
528#endif
529
530#if CARD_MIC
531extern int setup_mic(struct IsdnCard *card);
532#endif
533
534#if CARD_NETJET_S
535extern int setup_netjet_s(struct IsdnCard *card);
536#endif
537
538#if CARD_HFCS
539extern int setup_hfcs(struct IsdnCard *card);
540#endif
541
542#if CARD_HFC_PCI
543extern int setup_hfcpci(struct IsdnCard *card);
544#endif
545
546#if CARD_HFC_SX
547extern int setup_hfcsx(struct IsdnCard *card);
548#endif
549
550#if CARD_AMD7930
551extern int setup_amd7930(struct IsdnCard *card);
552#endif
553
554#if CARD_NICCY
555extern int setup_niccy(struct IsdnCard *card);
556#endif
557
558#if CARD_ISURF
559extern int setup_isurf(struct IsdnCard *card);
560#endif
561
562#if CARD_HSTSAPHIR
563extern int setup_saphir(struct IsdnCard *card);
564#endif
565
566#if CARD_TESTEMU
567extern int setup_testemu(struct IsdnCard *card);
568#endif
569
570#if CARD_BKM_A4T
571extern int setup_bkm_a4t(struct IsdnCard *card);
572#endif
573
574#if CARD_SCT_QUADRO
575extern int setup_sct_quadro(struct IsdnCard *card);
576#endif
577
578#if CARD_GAZEL
579extern int setup_gazel(struct IsdnCard *card);
580#endif
581
582#if CARD_W6692
583extern int setup_w6692(struct IsdnCard *card);
584#endif
585
586#if CARD_NETJET_U
587extern int setup_netjet_u(struct IsdnCard *card);
588#endif
589
590#if CARD_FN_ENTERNOW_PCI
591extern int setup_enternow_pci(struct IsdnCard *card);
592#endif
593
594/*
595 * Find card with given driverId
596 */
597static inline struct IsdnCardState *hisax_findcard(int driverid)
598{
599 int i;
600
601 for (i = 0; i < nrcards; i++)
602 if (cards[i].cs)
603 if (cards[i].cs->myid == driverid)
604 return cards[i].cs;
605 return NULL;
606}
607
608/*
609 * Find card with given card number
610 */
611struct IsdnCardState *hisax_get_card(int cardnr)
612{
613 if ((cardnr <= nrcards) && (cardnr > 0))
614 if (cards[cardnr - 1].cs)
615 return cards[cardnr - 1].cs;
616 return NULL;
617}
618
619int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
620{
621 int count, cnt;
622 u_char __user *p = buf;
623 struct IsdnCardState *cs = hisax_findcard(id);
624
625 if (cs) {
626 if (len > HISAX_STATUS_BUFSIZE) {
627 printk(KERN_WARNING
628 "HiSax: status overflow readstat %d/%d\n",
629 len, HISAX_STATUS_BUFSIZE);
630 }
631 count = cs->status_end - cs->status_read + 1;
632 if (count >= len)
633 count = len;
634 copy_to_user(p, cs->status_read, count);
635 cs->status_read += count;
636 if (cs->status_read > cs->status_end)
637 cs->status_read = cs->status_buf;
638 p += count;
639 count = len - count;
640 while (count) {
641 if (count > HISAX_STATUS_BUFSIZE)
642 cnt = HISAX_STATUS_BUFSIZE;
643 else
644 cnt = count;
645 copy_to_user(p, cs->status_read, cnt);
646 p += cnt;
647 cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
648 count -= cnt;
649 }
650 return len;
651 } else {
652 printk(KERN_ERR
653 "HiSax: if_readstatus called with invalid driverId!\n");
654 return -ENODEV;
655 }
656}
657
658int jiftime(char *s, long mark)
659{
660 s += 8;
661
662 *s-- = '\0';
663 *s-- = mark % 10 + '0';
664 mark /= 10;
665 *s-- = mark % 10 + '0';
666 mark /= 10;
667 *s-- = '.';
668 *s-- = mark % 10 + '0';
669 mark /= 10;
670 *s-- = mark % 6 + '0';
671 mark /= 6;
672 *s-- = ':';
673 *s-- = mark % 10 + '0';
674 mark /= 10;
675 *s-- = mark % 10 + '0';
676 return 8;
677}
678
679static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
680
681void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
682 va_list args)
683{
684 /* if head == NULL the fmt contains the full info */
685
686 u_long flags;
687 int count, i;
688 u_char *p;
689 isdn_ctrl ic;
690 int len;
691
692 if (!cs) {
693 printk(KERN_WARNING "HiSax: No CardStatus for message");
694 return;
695 }
696 spin_lock_irqsave(&cs->statlock, flags);
697 p = tmpbuf;
698 if (head) {
699 p += jiftime(p, jiffies);
700 p += sprintf(p, " %s", head);
701 p += vsprintf(p, fmt, args);
702 *p++ = '\n';
703 *p = 0;
704 len = p - tmpbuf;
705 p = tmpbuf;
706 } else {
707 p = fmt;
708 len = strlen(fmt);
709 }
710 if (len > HISAX_STATUS_BUFSIZE) {
711 spin_unlock_irqrestore(&cs->statlock, flags);
712 printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
713 len, HISAX_STATUS_BUFSIZE);
714 return;
715 }
716 count = len;
717 i = cs->status_end - cs->status_write + 1;
718 if (i >= len)
719 i = len;
720 len -= i;
721 memcpy(cs->status_write, p, i);
722 cs->status_write += i;
723 if (cs->status_write > cs->status_end)
724 cs->status_write = cs->status_buf;
725 p += i;
726 if (len) {
727 memcpy(cs->status_write, p, len);
728 cs->status_write += len;
729 }
730#ifdef KERNELSTACK_DEBUG
731 i = (ulong) & len - current->kernel_stack_page;
732 sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm,
733 current->kernel_stack_page, i);
734 len = strlen(tmpbuf);
735 for (p = tmpbuf, i = len; i > 0; i--, p++) {
736 *cs->status_write++ = *p;
737 if (cs->status_write > cs->status_end)
738 cs->status_write = cs->status_buf;
739 count++;
740 }
741#endif
742 spin_unlock_irqrestore(&cs->statlock, flags);
743 if (count) {
744 ic.command = ISDN_STAT_STAVAIL;
745 ic.driver = cs->myid;
746 ic.arg = count;
747 cs->iif.statcallb(&ic);
748 }
749}
750
751void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
752{
753 va_list args;
754
755 va_start(args, fmt);
756 VHiSax_putstatus(cs, head, fmt, args);
757 va_end(args);
758}
759
760int ll_run(struct IsdnCardState *cs, int addfeatures)
761{
762 isdn_ctrl ic;
763
764 ic.driver = cs->myid;
765 ic.command = ISDN_STAT_RUN;
766 cs->iif.features |= addfeatures;
767 cs->iif.statcallb(&ic);
768 return 0;
769}
770
771void ll_stop(struct IsdnCardState *cs)
772{
773 isdn_ctrl ic;
774
775 ic.command = ISDN_STAT_STOP;
776 ic.driver = cs->myid;
777 cs->iif.statcallb(&ic);
778 // CallcFreeChan(cs);
779}
780
781static void ll_unload(struct IsdnCardState *cs)
782{
783 isdn_ctrl ic;
784
785 ic.command = ISDN_STAT_UNLOAD;
786 ic.driver = cs->myid;
787 cs->iif.statcallb(&ic);
788 if (cs->status_buf)
789 kfree(cs->status_buf);
790 cs->status_read = NULL;
791 cs->status_write = NULL;
792 cs->status_end = NULL;
793 kfree(cs->dlog);
794 cs->dlog = NULL;
795}
796
797static void closecard(int cardnr)
798{
799 struct IsdnCardState *csta = cards[cardnr].cs;
800
801 if (csta->bcs->BC_Close != NULL) {
802 csta->bcs->BC_Close(csta->bcs + 1);
803 csta->bcs->BC_Close(csta->bcs);
804 }
805
806 skb_queue_purge(&csta->rq);
807 skb_queue_purge(&csta->sq);
808 if (csta->rcvbuf) {
809 kfree(csta->rcvbuf);
810 csta->rcvbuf = NULL;
811 }
812 if (csta->tx_skb) {
813 dev_kfree_skb(csta->tx_skb);
814 csta->tx_skb = NULL;
815 }
816 if (csta->DC_Close != NULL) {
817 csta->DC_Close(csta);
818 }
819 if (csta->cardmsg)
820 csta->cardmsg(csta, CARD_RELEASE, NULL);
821 if (csta->dbusytimer.function != NULL) // FIXME?
822 del_timer(&csta->dbusytimer);
823 ll_unload(csta);
824}
825
826static int init_card(struct IsdnCardState *cs)
827{
828 int irq_cnt, cnt = 3, ret;
829
830 if (!cs->irq) {
831 ret = cs->cardmsg(cs, CARD_INIT, NULL);
832 return(ret);
833 }
834 irq_cnt = kstat_irqs(cs->irq);
835 printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
836 cs->irq, irq_cnt);
837 if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
838 printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
839 cs->irq);
840 return 1;
841 }
842 while (cnt) {
843 cs->cardmsg(cs, CARD_INIT, NULL);
844 /* Timeout 10ms */
845 msleep(10);
846 printk(KERN_INFO "%s: IRQ %d count %d\n",
847 CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
848 if (kstat_irqs(cs->irq) == irq_cnt) {
849 printk(KERN_WARNING
850 "%s: IRQ(%d) getting no interrupts during init %d\n",
851 CardType[cs->typ], cs->irq, 4 - cnt);
852 if (cnt == 1) {
853 free_irq(cs->irq, cs);
854 return 2;
855 } else {
856 cs->cardmsg(cs, CARD_RESET, NULL);
857 cnt--;
858 }
859 } else {
860 cs->cardmsg(cs, CARD_TEST, NULL);
861 return 0;
862 }
863 }
864 return 3;
865}
866
867static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
868{
869 int ret = 0;
870 struct IsdnCard *card = cards + cardnr;
871 struct IsdnCardState *cs;
872
873 cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
874 if (!cs) {
875 printk(KERN_WARNING
876 "HiSax: No memory for IsdnCardState(card %d)\n",
877 cardnr + 1);
878 goto out;
879 }
880 memset(cs, 0, sizeof(struct IsdnCardState));
881 card->cs = cs;
882 spin_lock_init(&cs->statlock);
883 spin_lock_init(&cs->lock);
884 cs->chanlimit = 2; /* maximum B-channel number */
885 cs->logecho = 0; /* No echo logging */
886 cs->cardnr = cardnr;
887 cs->debug = L1_DEB_WARN;
888 cs->HW_Flags = 0;
889 cs->busy_flag = busy_flag;
890 cs->irq_flags = I4L_IRQ_FLAG;
891#if TEI_PER_CARD
892 if (card->protocol == ISDN_PTYPE_NI1)
893 test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
894#else
895 test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
896#endif
897 cs->protocol = card->protocol;
898
899 if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
900 printk(KERN_WARNING
901 "HiSax: Card Type %d out of range\n", card->typ);
902 goto outf_cs;
903 }
904 if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
905 printk(KERN_WARNING
906 "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
907 goto outf_cs;
908 }
909 if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
910 printk(KERN_WARNING
911 "HiSax: No memory for status_buf(card %d)\n",
912 cardnr + 1);
913 goto outf_dlog;
914 }
915 cs->stlist = NULL;
916 cs->status_read = cs->status_buf;
917 cs->status_write = cs->status_buf;
918 cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
919 cs->typ = card->typ;
920#ifdef MODULE
921 cs->iif.owner = lockowner;
922#endif
923 strcpy(cs->iif.id, id);
924 cs->iif.channels = 2;
925 cs->iif.maxbufsize = MAX_DATA_SIZE;
926 cs->iif.hl_hdrlen = MAX_HEADER_LEN;
927 cs->iif.features =
928 ISDN_FEATURE_L2_X75I |
929 ISDN_FEATURE_L2_HDLC |
930 ISDN_FEATURE_L2_HDLC_56K |
931 ISDN_FEATURE_L2_TRANS |
932 ISDN_FEATURE_L3_TRANS |
933#ifdef CONFIG_HISAX_1TR6
934 ISDN_FEATURE_P_1TR6 |
935#endif
936#ifdef CONFIG_HISAX_EURO
937 ISDN_FEATURE_P_EURO |
938#endif
939#ifdef CONFIG_HISAX_NI1
940 ISDN_FEATURE_P_NI1 |
941#endif
942 0;
943
944 cs->iif.command = HiSax_command;
945 cs->iif.writecmd = NULL;
946 cs->iif.writebuf_skb = HiSax_writebuf_skb;
947 cs->iif.readstat = HiSax_readstatus;
948 register_isdn(&cs->iif);
949 cs->myid = cs->iif.channels;
950 printk(KERN_INFO
951 "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
952 (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
953 (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
954 (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
955 (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
956 "NONE", cs->iif.id, cs->myid);
957 switch (card->typ) {
958#if CARD_TELES0
959 case ISDN_CTYPE_16_0:
960 case ISDN_CTYPE_8_0:
961 ret = setup_teles0(card);
962 break;
963#endif
964#if CARD_TELES3
965 case ISDN_CTYPE_16_3:
966 case ISDN_CTYPE_PNP:
967 case ISDN_CTYPE_TELESPCMCIA:
968 case ISDN_CTYPE_COMPAQ_ISA:
969 ret = setup_teles3(card);
970 break;
971#endif
972#if CARD_S0BOX
973 case ISDN_CTYPE_S0BOX:
974 ret = setup_s0box(card);
975 break;
976#endif
977#if CARD_TELESPCI
978 case ISDN_CTYPE_TELESPCI:
979 ret = setup_telespci(card);
980 break;
981#endif
982#if CARD_AVM_A1
983 case ISDN_CTYPE_A1:
984 ret = setup_avm_a1(card);
985 break;
986#endif
987#if CARD_AVM_A1_PCMCIA
988 case ISDN_CTYPE_A1_PCMCIA:
989 ret = setup_avm_a1_pcmcia(card);
990 break;
991#endif
992#if CARD_FRITZPCI
993 case ISDN_CTYPE_FRITZPCI:
994 ret = setup_avm_pcipnp(card);
995 break;
996#endif
997#if CARD_ELSA
998 case ISDN_CTYPE_ELSA:
999 case ISDN_CTYPE_ELSA_PNP:
1000 case ISDN_CTYPE_ELSA_PCMCIA:
1001 case ISDN_CTYPE_ELSA_PCI:
1002 ret = setup_elsa(card);
1003 break;
1004#endif
1005#if CARD_IX1MICROR2
1006 case ISDN_CTYPE_IX1MICROR2:
1007 ret = setup_ix1micro(card);
1008 break;
1009#endif
1010#if CARD_DIEHLDIVA
1011 case ISDN_CTYPE_DIEHLDIVA:
1012 ret = setup_diva(card);
1013 break;
1014#endif
1015#if CARD_ASUSCOM
1016 case ISDN_CTYPE_ASUSCOM:
1017 ret = setup_asuscom(card);
1018 break;
1019#endif
1020#if CARD_TELEINT
1021 case ISDN_CTYPE_TELEINT:
1022 ret = setup_TeleInt(card);
1023 break;
1024#endif
1025#if CARD_SEDLBAUER
1026 case ISDN_CTYPE_SEDLBAUER:
1027 case ISDN_CTYPE_SEDLBAUER_PCMCIA:
1028 case ISDN_CTYPE_SEDLBAUER_FAX:
1029 ret = setup_sedlbauer(card);
1030 break;
1031#endif
1032#if CARD_SPORTSTER
1033 case ISDN_CTYPE_SPORTSTER:
1034 ret = setup_sportster(card);
1035 break;
1036#endif
1037#if CARD_MIC
1038 case ISDN_CTYPE_MIC:
1039 ret = setup_mic(card);
1040 break;
1041#endif
1042#if CARD_NETJET_S
1043 case ISDN_CTYPE_NETJET_S:
1044 ret = setup_netjet_s(card);
1045 break;
1046#endif
1047#if CARD_HFCS
1048 case ISDN_CTYPE_TELES3C:
1049 case ISDN_CTYPE_ACERP10:
1050 ret = setup_hfcs(card);
1051 break;
1052#endif
1053#if CARD_HFC_PCI
1054 case ISDN_CTYPE_HFC_PCI:
1055 ret = setup_hfcpci(card);
1056 break;
1057#endif
1058#if CARD_HFC_SX
1059 case ISDN_CTYPE_HFC_SX:
1060 ret = setup_hfcsx(card);
1061 break;
1062#endif
1063#if CARD_NICCY
1064 case ISDN_CTYPE_NICCY:
1065 ret = setup_niccy(card);
1066 break;
1067#endif
1068#if CARD_AMD7930
1069 case ISDN_CTYPE_AMD7930:
1070 ret = setup_amd7930(card);
1071 break;
1072#endif
1073#if CARD_ISURF
1074 case ISDN_CTYPE_ISURF:
1075 ret = setup_isurf(card);
1076 break;
1077#endif
1078#if CARD_HSTSAPHIR
1079 case ISDN_CTYPE_HSTSAPHIR:
1080 ret = setup_saphir(card);
1081 break;
1082#endif
1083#if CARD_TESTEMU
1084 case ISDN_CTYPE_TESTEMU:
1085 ret = setup_testemu(card);
1086 break;
1087#endif
1088#if CARD_BKM_A4T
1089 case ISDN_CTYPE_BKM_A4T:
1090 ret = setup_bkm_a4t(card);
1091 break;
1092#endif
1093#if CARD_SCT_QUADRO
1094 case ISDN_CTYPE_SCT_QUADRO:
1095 ret = setup_sct_quadro(card);
1096 break;
1097#endif
1098#if CARD_GAZEL
1099 case ISDN_CTYPE_GAZEL:
1100 ret = setup_gazel(card);
1101 break;
1102#endif
1103#if CARD_W6692
1104 case ISDN_CTYPE_W6692:
1105 ret = setup_w6692(card);
1106 break;
1107#endif
1108#if CARD_NETJET_U
1109 case ISDN_CTYPE_NETJET_U:
1110 ret = setup_netjet_u(card);
1111 break;
1112#endif
1113#if CARD_FN_ENTERNOW_PCI
1114 case ISDN_CTYPE_ENTERNOW:
1115 ret = setup_enternow_pci(card);
1116 break;
1117#endif
1118 case ISDN_CTYPE_DYNAMIC:
1119 ret = 2;
1120 break;
1121 default:
1122 printk(KERN_WARNING
1123 "HiSax: Support for %s Card not selected\n",
1124 CardType[card->typ]);
1125 ll_unload(cs);
1126 goto outf_cs;
1127 }
1128 if (!ret) {
1129 ll_unload(cs);
1130 goto outf_cs;
1131 }
1132 if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
1133 printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
1134 ll_unload(cs);
1135 goto outf_cs;
1136 }
1137 cs->rcvidx = 0;
1138 cs->tx_skb = NULL;
1139 cs->tx_cnt = 0;
1140 cs->event = 0;
1141 cs->tqueue.data = cs;
1142
1143 skb_queue_head_init(&cs->rq);
1144 skb_queue_head_init(&cs->sq);
1145
1146 init_bcstate(cs, 0);
1147 init_bcstate(cs, 1);
1148
1149 /* init_card only handles interrupts which are not */
1150 /* used here for the loadable driver */
1151 switch (card->typ) {
1152 case ISDN_CTYPE_DYNAMIC:
1153 ret = 0;
1154 break;
1155 default:
1156 ret = init_card(cs);
1157 break;
1158 }
1159 if (ret) {
1160 closecard(cardnr);
1161 ret = 0;
1162 goto outf_cs;
1163 }
1164 init_tei(cs, cs->protocol);
1165 ret = CallcNewChan(cs);
1166 if (ret) {
1167 closecard(cardnr);
1168 ret = 0;
1169 goto outf_cs;
1170 }
1171 /* ISAR needs firmware download first */
1172 if (!test_bit(HW_ISAR, &cs->HW_Flags))
1173 ll_run(cs, 0);
1174
1175 ret = 1;
1176 goto out;
1177
1178 outf_dlog:
1179 kfree(cs->dlog);
1180 outf_cs:
1181 kfree(cs);
1182 card->cs = NULL;
1183 out:
1184 return ret;
1185}
1186
1187void HiSax_shiftcards(int idx)
1188{
1189 int i;
1190
1191 for (i = idx; i < (HISAX_MAX_CARDS - 1); i++)
1192 memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
1193}
1194
1195int HiSax_inithardware(int *busy_flag)
1196{
1197 int foundcards = 0;
1198 int i = 0;
1199 int t = ',';
1200 int flg = 0;
1201 char *id;
1202 char *next_id = HiSax_id;
1203 char ids[20];
1204
1205 if (strchr(HiSax_id, ','))
1206 t = ',';
1207 else if (strchr(HiSax_id, '%'))
1208 t = '%';
1209
1210 while (i < nrcards) {
1211 if (cards[i].typ < 1)
1212 break;
1213 id = next_id;
1214 if ((next_id = strchr(id, t))) {
1215 *next_id++ = 0;
1216 strcpy(ids, id);
1217 flg = i + 1;
1218 } else {
1219 next_id = id;
1220 if (flg >= i)
1221 strcpy(ids, id);
1222 else
1223 sprintf(ids, "%s%d", id, i);
1224 }
1225 if (checkcard(i, ids, busy_flag, THIS_MODULE)) {
1226 foundcards++;
1227 i++;
1228 } else {
1229 /* make sure we don't oops the module */
1230 if (cards[i].typ > 0 && cards[i].typ <= ISDN_CTYPE_COUNT) {
1231 printk(KERN_WARNING
1232 "HiSax: Card %s not installed !\n",
1233 CardType[cards[i].typ]);
1234 }
1235 HiSax_shiftcards(i);
1236 nrcards--;
1237 }
1238 }
1239 return foundcards;
1240}
1241
1242void HiSax_closecard(int cardnr)
1243{
1244 int i, last = nrcards - 1;
1245
1246 if (cardnr > last || cardnr < 0)
1247 return;
1248 if (cards[cardnr].cs) {
1249 ll_stop(cards[cardnr].cs);
1250 release_tei(cards[cardnr].cs);
1251 CallcFreeChan(cards[cardnr].cs);
1252
1253 closecard(cardnr);
1254 if (cards[cardnr].cs->irq)
1255 free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
1256 kfree((void *) cards[cardnr].cs);
1257 cards[cardnr].cs = NULL;
1258 }
1259 i = cardnr;
1260 while (i <= last) {
1261 cards[i] = cards[i + 1];
1262 i++;
1263 }
1264 nrcards--;
1265}
1266
1267void HiSax_reportcard(int cardnr, int sel)
1268{
1269 struct IsdnCardState *cs = cards[cardnr].cs;
1270
1271 printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
1272 printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
1273 printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
1274 printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
1275 (ulong) & HiSax_reportcard);
1276 printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
1277 printk(KERN_DEBUG "HiSax: HW_Flags %lx bc0 flg %lx bc1 flg %lx\n",
1278 cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
1279 printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
1280 cs->bcs[0].mode, cs->bcs[0].channel);
1281 printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n",
1282 cs->bcs[1].mode, cs->bcs[1].channel);
1283#ifdef ERROR_STATISTIC
1284 printk(KERN_DEBUG "HiSax: dc errors(rx,crc,tx) %d,%d,%d\n",
1285 cs->err_rx, cs->err_crc, cs->err_tx);
1286 printk(KERN_DEBUG
1287 "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
1288 cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc,
1289 cs->bcs[0].err_tx);
1290 printk(KERN_DEBUG
1291 "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
1292 cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc,
1293 cs->bcs[1].err_tx);
1294 if (sel == 99) {
1295 cs->err_rx = 0;
1296 cs->err_crc = 0;
1297 cs->err_tx = 0;
1298 cs->bcs[0].err_inv = 0;
1299 cs->bcs[0].err_rdo = 0;
1300 cs->bcs[0].err_crc = 0;
1301 cs->bcs[0].err_tx = 0;
1302 cs->bcs[1].err_inv = 0;
1303 cs->bcs[1].err_rdo = 0;
1304 cs->bcs[1].err_crc = 0;
1305 cs->bcs[1].err_tx = 0;
1306 }
1307#endif
1308}
1309
1310static int __init HiSax_init(void)
1311{
1312 int i, retval;
1313#ifdef MODULE
1314 int j;
1315 int nzproto = 0;
1316#endif
1317
1318 HiSaxVersion();
1319 retval = CallcNew();
1320 if (retval)
1321 goto out;
1322 retval = Isdnl3New();
1323 if (retval)
1324 goto out_callc;
1325 retval = Isdnl2New();
1326 if (retval)
1327 goto out_isdnl3;
1328 retval = TeiNew();
1329 if (retval)
1330 goto out_isdnl2;
1331 retval = Isdnl1New();
1332 if (retval)
1333 goto out_tei;
1334
1335#ifdef MODULE
1336 if (!type[0]) {
1337 /* We 'll register drivers later, but init basic functions */
1338 for (i = 0; i < HISAX_MAX_CARDS; i++)
1339 cards[i].typ = 0;
1340 return 0;
1341 }
1342#ifdef CONFIG_HISAX_ELSA
1343 if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) {
1344 /* we have exported and return in this case */
1345 return 0;
1346 }
1347#endif
1348#ifdef CONFIG_HISAX_SEDLBAUER
1349 if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
1350 /* we have to export and return in this case */
1351 return 0;
1352 }
1353#endif
1354#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
1355 if (type[0] == ISDN_CTYPE_A1_PCMCIA) {
1356 /* we have to export and return in this case */
1357 return 0;
1358 }
1359#endif
1360#ifdef CONFIG_HISAX_HFC_SX
1361 if (type[0] == ISDN_CTYPE_HFC_SP_PCMCIA) {
1362 /* we have to export and return in this case */
1363 return 0;
1364 }
1365#endif
1366#endif
1367 nrcards = 0;
1368#ifdef MODULE
1369 if (id) /* If id= string used */
1370 HiSax_id = id;
1371 for (i = j = 0; j < HISAX_MAX_CARDS; i++) {
1372 cards[j].typ = type[i];
1373 if (protocol[i]) {
1374 cards[j].protocol = protocol[i];
1375 nzproto++;
1376 } else {
1377 cards[j].protocol = DEFAULT_PROTO;
1378 }
1379 switch (type[i]) {
1380 case ISDN_CTYPE_16_0:
1381 cards[j].para[0] = irq[i];
1382 cards[j].para[1] = mem[i];
1383 cards[j].para[2] = io[i];
1384 break;
1385
1386 case ISDN_CTYPE_8_0:
1387 cards[j].para[0] = irq[i];
1388 cards[j].para[1] = mem[i];
1389 break;
1390
1391#ifdef IO0_IO1
1392 case ISDN_CTYPE_PNP:
1393 case ISDN_CTYPE_NICCY:
1394 cards[j].para[0] = irq[i];
1395 cards[j].para[1] = io0[i];
1396 cards[j].para[2] = io1[i];
1397 break;
1398 case ISDN_CTYPE_COMPAQ_ISA:
1399 cards[j].para[0] = irq[i];
1400 cards[j].para[1] = io0[i];
1401 cards[j].para[2] = io1[i];
1402 cards[j].para[3] = io[i];
1403 break;
1404#endif
1405 case ISDN_CTYPE_ELSA:
1406 case ISDN_CTYPE_HFC_PCI:
1407 cards[j].para[0] = io[i];
1408 break;
1409 case ISDN_CTYPE_16_3:
1410 case ISDN_CTYPE_TELESPCMCIA:
1411 case ISDN_CTYPE_A1:
1412 case ISDN_CTYPE_A1_PCMCIA:
1413 case ISDN_CTYPE_ELSA_PNP:
1414 case ISDN_CTYPE_ELSA_PCMCIA:
1415 case ISDN_CTYPE_IX1MICROR2:
1416 case ISDN_CTYPE_DIEHLDIVA:
1417 case ISDN_CTYPE_ASUSCOM:
1418 case ISDN_CTYPE_TELEINT:
1419 case ISDN_CTYPE_SEDLBAUER:
1420 case ISDN_CTYPE_SEDLBAUER_PCMCIA:
1421 case ISDN_CTYPE_SEDLBAUER_FAX:
1422 case ISDN_CTYPE_SPORTSTER:
1423 case ISDN_CTYPE_MIC:
1424 case ISDN_CTYPE_TELES3C:
1425 case ISDN_CTYPE_ACERP10:
1426 case ISDN_CTYPE_S0BOX:
1427 case ISDN_CTYPE_FRITZPCI:
1428 case ISDN_CTYPE_HSTSAPHIR:
1429 case ISDN_CTYPE_GAZEL:
1430 case ISDN_CTYPE_HFC_SX:
1431 case ISDN_CTYPE_HFC_SP_PCMCIA:
1432 cards[j].para[0] = irq[i];
1433 cards[j].para[1] = io[i];
1434 break;
1435 case ISDN_CTYPE_ISURF:
1436 cards[j].para[0] = irq[i];
1437 cards[j].para[1] = io[i];
1438 cards[j].para[2] = mem[i];
1439 break;
1440 case ISDN_CTYPE_ELSA_PCI:
1441 case ISDN_CTYPE_NETJET_S:
1442 case ISDN_CTYPE_AMD7930:
1443 case ISDN_CTYPE_TELESPCI:
1444 case ISDN_CTYPE_W6692:
1445 case ISDN_CTYPE_NETJET_U:
1446 break;
1447 case ISDN_CTYPE_BKM_A4T:
1448 break;
1449 case ISDN_CTYPE_SCT_QUADRO:
1450 if (irq[i]) {
1451 cards[j].para[0] = irq[i];
1452 } else {
1453 /* QUADRO is a 4 BRI card */
1454 cards[j++].para[0] = 1;
1455 /* we need to check if further cards can be added */
1456 if (j < HISAX_MAX_CARDS) {
1457 cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
1458 cards[j].protocol = protocol[i];
1459 cards[j++].para[0] = 2;
1460 }
1461 if (j < HISAX_MAX_CARDS) {
1462 cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
1463 cards[j].protocol = protocol[i];
1464 cards[j++].para[0] = 3;
1465 }
1466 if (j < HISAX_MAX_CARDS) {
1467 cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
1468 cards[j].protocol = protocol[i];
1469 cards[j].para[0] = 4;
1470 }
1471 }
1472 break;
1473 }
1474 j++;
1475 }
1476 if (!nzproto) {
1477 printk(KERN_WARNING
1478 "HiSax: Warning - no protocol specified\n");
1479 printk(KERN_WARNING "HiSax: using protocol %s\n",
1480 DEFAULT_PROTO_NAME);
1481 }
1482#endif
1483 if (!HiSax_id)
1484 HiSax_id = HiSaxID;
1485 if (!HiSaxID[0])
1486 strcpy(HiSaxID, "HiSax");
1487 for (i = 0; i < HISAX_MAX_CARDS; i++)
1488 if (cards[i].typ > 0)
1489 nrcards++;
1490 printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
1491 nrcards, (nrcards > 1) ? "s" : "");
1492
1493 /* Install only, if at least one card found */
1494 if (!HiSax_inithardware(NULL))
1495 return -ENODEV;
1496 return 0;
1497
1498 out_tei:
1499 TeiFree();
1500 out_isdnl2:
1501 Isdnl2Free();
1502 out_isdnl3:
1503 Isdnl3Free();
1504 out_callc:
1505 CallcFree();
1506 out:
1507 return retval;
1508}
1509
1510static void __exit HiSax_exit(void)
1511{
1512 int cardnr = nrcards - 1;
1513
1514 while (cardnr >= 0)
1515 HiSax_closecard(cardnr--);
1516 Isdnl1Free();
1517 TeiFree();
1518 Isdnl2Free();
1519 Isdnl3Free();
1520 CallcFree();
1521 printk(KERN_INFO "HiSax module removed\n");
1522}
1523
1524int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
1525{
1526 u_char ids[16];
1527 int ret = -1;
1528
1529 cards[nrcards] = *card;
1530 if (nrcards)
1531 sprintf(ids, "HiSax%d", nrcards);
1532 else
1533 sprintf(ids, "HiSax");
1534 if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE))
1535 goto error;
1536
1537 ret = nrcards;
1538 nrcards++;
1539error:
1540 return ret;
1541}
1542
1543EXPORT_SYMBOL(hisax_init_pcmcia);
1544EXPORT_SYMBOL(HiSax_closecard);
1545
1546#include "hisax_if.h"
1547
1548EXPORT_SYMBOL(hisax_register);
1549EXPORT_SYMBOL(hisax_unregister);
1550
1551static void hisax_d_l1l2(struct hisax_if *ifc, int pr, void *arg);
1552static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg);
1553static void hisax_d_l2l1(struct PStack *st, int pr, void *arg);
1554static void hisax_b_l2l1(struct PStack *st, int pr, void *arg);
1555static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg);
1556static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs);
1557static void hisax_bc_close(struct BCState *bcs);
1558static void hisax_bh(struct IsdnCardState *cs);
1559static void EChannel_proc_rcv(struct hisax_d_if *d_if);
1560
1561int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
1562 char *name, int protocol)
1563{
1564 int i, retval;
1565 char id[20];
1566 struct IsdnCardState *cs;
1567
1568 for (i = 0; i < HISAX_MAX_CARDS; i++) {
1569 if (!cards[i].typ)
1570 break;
1571 }
1572
1573 if (i >= HISAX_MAX_CARDS)
1574 return -EBUSY;
1575
1576 cards[i].typ = ISDN_CTYPE_DYNAMIC;
1577 cards[i].protocol = protocol;
1578 sprintf(id, "%s%d", name, i);
1579 nrcards++;
1580 retval = checkcard(i, id, NULL, hisax_d_if->owner);
1581 if (retval == 0) { // yuck
1582 cards[i].typ = 0;
1583 nrcards--;
1584 return retval;
1585 }
1586 cs = cards[i].cs;
1587 hisax_d_if->cs = cs;
1588 cs->hw.hisax_d_if = hisax_d_if;
1589 cs->cardmsg = hisax_cardmsg;
1590 INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs);
1591 cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1;
1592 for (i = 0; i < 2; i++) {
1593 cs->bcs[i].BC_SetStack = hisax_bc_setstack;
1594 cs->bcs[i].BC_Close = hisax_bc_close;
1595
1596 b_if[i]->ifc.l1l2 = hisax_b_l1l2;
1597
1598 hisax_d_if->b_if[i] = b_if[i];
1599 }
1600 hisax_d_if->ifc.l1l2 = hisax_d_l1l2;
1601 skb_queue_head_init(&hisax_d_if->erq);
1602 clear_bit(0, &hisax_d_if->ph_state);
1603
1604 return 0;
1605}
1606
1607void hisax_unregister(struct hisax_d_if *hisax_d_if)
1608{
1609 cards[hisax_d_if->cs->cardnr].typ = 0;
1610 HiSax_closecard(hisax_d_if->cs->cardnr);
1611 skb_queue_purge(&hisax_d_if->erq);
1612}
1613
1614#include "isdnl1.h"
1615
1616static void hisax_sched_event(struct IsdnCardState *cs, int event)
1617{
1618 test_and_set_bit(event, &cs->event);
1619 schedule_work(&cs->tqueue);
1620}
1621
1622static void hisax_bh(struct IsdnCardState *cs)
1623{
1624 struct PStack *st;
1625 int pr;
1626
1627 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
1628 DChannel_proc_rcv(cs);
1629 if (test_and_clear_bit(E_RCVBUFREADY, &cs->event))
1630 EChannel_proc_rcv(cs->hw.hisax_d_if);
1631 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
1632 if (test_bit(0, &cs->hw.hisax_d_if->ph_state))
1633 pr = PH_ACTIVATE | INDICATION;
1634 else
1635 pr = PH_DEACTIVATE | INDICATION;
1636 for (st = cs->stlist; st; st = st->next)
1637 st->l1.l1l2(st, pr, NULL);
1638
1639 }
1640}
1641
1642static void hisax_b_sched_event(struct BCState *bcs, int event)
1643{
1644 test_and_set_bit(event, &bcs->event);
1645 schedule_work(&bcs->tqueue);
1646}
1647
1648static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg)
1649{
1650 struct hisax_if *ifc = (struct hisax_if *) d_if;
1651 ifc->l2l1(ifc, pr, arg);
1652}
1653
1654static inline void B_L2L1(struct hisax_b_if *b_if, int pr, void *arg)
1655{
1656 struct hisax_if *ifc = (struct hisax_if *) b_if;
1657 ifc->l2l1(ifc, pr, arg);
1658}
1659
1660static void hisax_d_l1l2(struct hisax_if *ifc, int pr, void *arg)
1661{
1662 struct hisax_d_if *d_if = (struct hisax_d_if *) ifc;
1663 struct IsdnCardState *cs = d_if->cs;
1664 struct PStack *st;
1665 struct sk_buff *skb;
1666
1667 switch (pr) {
1668 case PH_ACTIVATE | INDICATION:
1669 set_bit(0, &d_if->ph_state);
1670 hisax_sched_event(cs, D_L1STATECHANGE);
1671 break;
1672 case PH_DEACTIVATE | INDICATION:
1673 clear_bit(0, &d_if->ph_state);
1674 hisax_sched_event(cs, D_L1STATECHANGE);
1675 break;
1676 case PH_DATA | INDICATION:
1677 skb_queue_tail(&cs->rq, arg);
1678 hisax_sched_event(cs, D_RCVBUFREADY);
1679 break;
1680 case PH_DATA | CONFIRM:
1681 skb = skb_dequeue(&cs->sq);
1682 if (skb) {
1683 D_L2L1(d_if, PH_DATA | REQUEST, skb);
1684 break;
1685 }
1686 clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
1687 for (st = cs->stlist; st; st = st->next) {
1688 if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) {
1689 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1690 break;
1691 }
1692 }
1693 break;
1694 case PH_DATA_E | INDICATION:
1695 skb_queue_tail(&d_if->erq, arg);
1696 hisax_sched_event(cs, E_RCVBUFREADY);
1697 break;
1698 default:
1699 printk("pr %#x\n", pr);
1700 break;
1701 }
1702}
1703
1704static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg)
1705{
1706 struct hisax_b_if *b_if = (struct hisax_b_if *) ifc;
1707 struct BCState *bcs = b_if->bcs;
1708 struct PStack *st = bcs->st;
1709 struct sk_buff *skb;
1710
1711 // FIXME use isdnl1?
1712 switch (pr) {
1713 case PH_ACTIVATE | INDICATION:
1714 st->l1.l1l2(st, pr, NULL);
1715 break;
1716 case PH_DEACTIVATE | INDICATION:
1717 st->l1.l1l2(st, pr, NULL);
1718 clear_bit(BC_FLG_BUSY, &bcs->Flag);
1719 skb_queue_purge(&bcs->squeue);
1720 bcs->hw.b_if = NULL;
1721 break;
1722 case PH_DATA | INDICATION:
1723 skb_queue_tail(&bcs->rqueue, arg);
1724 hisax_b_sched_event(bcs, B_RCVBUFREADY);
1725 break;
1726 case PH_DATA | CONFIRM:
1727 bcs->tx_cnt -= (int) arg;
1728 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag)) {
1729 u_long flags;
1730 spin_lock_irqsave(&bcs->aclock, flags);
1731 bcs->ackcnt += (int) arg;
1732 spin_unlock_irqrestore(&bcs->aclock, flags);
1733 schedule_event(bcs, B_ACKPENDING);
1734 }
1735 skb = skb_dequeue(&bcs->squeue);
1736 if (skb) {
1737 B_L2L1(b_if, PH_DATA | REQUEST, skb);
1738 break;
1739 }
1740 clear_bit(BC_FLG_BUSY, &bcs->Flag);
1741 if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) {
1742 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1743 }
1744 break;
1745 default:
1746 printk("hisax_b_l1l2 pr %#x\n", pr);
1747 break;
1748 }
1749}
1750
1751static void hisax_d_l2l1(struct PStack *st, int pr, void *arg)
1752{
1753 struct IsdnCardState *cs = st->l1.hardware;
1754 struct hisax_d_if *hisax_d_if = cs->hw.hisax_d_if;
1755 struct sk_buff *skb = arg;
1756
1757 switch (pr) {
1758 case PH_DATA | REQUEST:
1759 case PH_PULL | INDICATION:
1760 if (cs->debug & DEB_DLOG_HEX)
1761 LogFrame(cs, skb->data, skb->len);
1762 if (cs->debug & DEB_DLOG_VERBOSE)
1763 dlogframe(cs, skb, 0);
1764 Logl2Frame(cs, skb, "PH_DATA_REQ", 0);
1765 // FIXME lock?
1766 if (!test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags))
1767 D_L2L1(hisax_d_if, PH_DATA | REQUEST, skb);
1768 else
1769 skb_queue_tail(&cs->sq, skb);
1770 break;
1771 case PH_PULL | REQUEST:
1772 if (!test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
1773 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1774 else
1775 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1776 break;
1777 default:
1778 D_L2L1(hisax_d_if, pr, arg);
1779 break;
1780 }
1781}
1782
1783static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg)
1784{
1785 return 0;
1786}
1787
1788static void hisax_b_l2l1(struct PStack *st, int pr, void *arg)
1789{
1790 struct BCState *bcs = st->l1.bcs;
1791 struct hisax_b_if *b_if = bcs->hw.b_if;
1792
1793 switch (pr) {
1794 case PH_ACTIVATE | REQUEST:
1795 B_L2L1(b_if, pr, (void *) st->l1.mode);
1796 break;
1797 case PH_DATA | REQUEST:
1798 case PH_PULL | INDICATION:
1799 // FIXME lock?
1800 if (!test_and_set_bit(BC_FLG_BUSY, &bcs->Flag)) {
1801 B_L2L1(b_if, PH_DATA | REQUEST, arg);
1802 } else {
1803 skb_queue_tail(&bcs->squeue, arg);
1804 }
1805 break;
1806 case PH_PULL | REQUEST:
1807 if (!test_bit(BC_FLG_BUSY, &bcs->Flag))
1808 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1809 else
1810 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1811 break;
1812 case PH_DEACTIVATE | REQUEST:
1813 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1814 skb_queue_purge(&bcs->squeue);
1815 default:
1816 B_L2L1(b_if, pr, arg);
1817 break;
1818 }
1819}
1820
1821static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs)
1822{
1823 struct IsdnCardState *cs = st->l1.hardware;
1824 struct hisax_d_if *hisax_d_if = cs->hw.hisax_d_if;
1825
1826 bcs->channel = st->l1.bc;
1827
1828 bcs->hw.b_if = hisax_d_if->b_if[st->l1.bc];
1829 hisax_d_if->b_if[st->l1.bc]->bcs = bcs;
1830
1831 st->l1.bcs = bcs;
1832 st->l2.l2l1 = hisax_b_l2l1;
1833 setstack_manager(st);
1834 bcs->st = st;
1835 setstack_l1_B(st);
1836 skb_queue_head_init(&bcs->rqueue);
1837 skb_queue_head_init(&bcs->squeue);
1838 return 0;
1839}
1840
1841static void hisax_bc_close(struct BCState *bcs)
1842{
1843 struct hisax_b_if *b_if = bcs->hw.b_if;
1844
1845 if (b_if)
1846 B_L2L1(b_if, PH_DEACTIVATE | REQUEST, NULL);
1847}
1848
1849static void EChannel_proc_rcv(struct hisax_d_if *d_if)
1850{
1851 struct IsdnCardState *cs = d_if->cs;
1852 u_char *ptr;
1853 struct sk_buff *skb;
1854
1855 while ((skb = skb_dequeue(&d_if->erq)) != NULL) {
1856 if (cs->debug & DEB_DLOG_HEX) {
1857 ptr = cs->dlog;
1858 if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
1859 *ptr++ = 'E';
1860 *ptr++ = 'C';
1861 *ptr++ = 'H';
1862 *ptr++ = 'O';
1863 *ptr++ = ':';
1864 ptr += QuickHex(ptr, skb->data, skb->len);
1865 ptr--;
1866 *ptr++ = '\n';
1867 *ptr = 0;
1868 HiSax_putstatus(cs, NULL, cs->dlog);
1869 } else
1870 HiSax_putstatus(cs, "LogEcho: ",
1871 "warning Frame too big (%d)",
1872 skb->len);
1873 }
1874 dev_kfree_skb_any(skb);
1875 }
1876}
1877
1878#ifdef CONFIG_PCI
1879#include <linux/pci.h>
1880
1881static struct pci_device_id hisax_pci_tbl[] __initdata = {
1882#ifdef CONFIG_HISAX_FRITZPCI
1883 {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID},
1884#endif
1885#ifdef CONFIG_HISAX_DIEHLDIVA
1886 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID},
1887 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID},
1888 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID},
1889//#########################################################################################
1890 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, PCI_ANY_ID, PCI_ANY_ID},
1891//#########################################################################################
1892#endif
1893#ifdef CONFIG_HISAX_ELSA
1894 {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID},
1895 {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, PCI_ANY_ID, PCI_ANY_ID},
1896#endif
1897#ifdef CONFIG_HISAX_GAZEL
1898 {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R685, PCI_ANY_ID, PCI_ANY_ID},
1899 {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R753, PCI_ANY_ID, PCI_ANY_ID},
1900 {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO, PCI_ANY_ID, PCI_ANY_ID},
1901#endif
1902#ifdef CONFIG_HISAX_QUADRO
1903 {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_ANY_ID, PCI_ANY_ID},
1904#endif
1905#ifdef CONFIG_HISAX_NICCY
1906 {PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, PCI_ANY_ID,PCI_ANY_ID},
1907#endif
1908#ifdef CONFIG_HISAX_SEDLBAUER
1909 {PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_ANY_ID,PCI_ANY_ID},
1910#endif
1911#if defined(CONFIG_HISAX_NETJET) || defined(CONFIG_HISAX_NETJET_U)
1912 {PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, PCI_ANY_ID,PCI_ANY_ID},
1913#endif
1914#if defined(CONFIG_HISAX_TELESPCI) || defined(CONFIG_HISAX_SCT_QUADRO)
1915 {PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, PCI_ANY_ID,PCI_ANY_ID},
1916#endif
1917#ifdef CONFIG_HISAX_W6692
1918 {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, PCI_ANY_ID,PCI_ANY_ID},
1919 {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_ANY_ID,PCI_ANY_ID},
1920#endif
1921#ifdef CONFIG_HISAX_HFC_PCI
1922 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, PCI_ANY_ID, PCI_ANY_ID},
1923 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, PCI_ANY_ID, PCI_ANY_ID},
1924 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, PCI_ANY_ID, PCI_ANY_ID},
1925 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, PCI_ANY_ID, PCI_ANY_ID},
1926 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, PCI_ANY_ID, PCI_ANY_ID},
1927 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, PCI_ANY_ID, PCI_ANY_ID},
1928 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, PCI_ANY_ID, PCI_ANY_ID},
1929 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, PCI_ANY_ID, PCI_ANY_ID},
1930 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, PCI_ANY_ID, PCI_ANY_ID},
1931 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, PCI_ANY_ID, PCI_ANY_ID},
1932 {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, PCI_ANY_ID, PCI_ANY_ID},
1933 {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, PCI_ANY_ID, PCI_ANY_ID},
1934 {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, PCI_ANY_ID, PCI_ANY_ID},
1935 {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, PCI_ANY_ID, PCI_ANY_ID},
1936 {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, PCI_ANY_ID, PCI_ANY_ID},
1937 {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, PCI_ANY_ID, PCI_ANY_ID},
1938 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E, PCI_ANY_ID, PCI_ANY_ID},
1939 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E, PCI_ANY_ID, PCI_ANY_ID},
1940 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A, PCI_ANY_ID, PCI_ANY_ID},
1941 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A, PCI_ANY_ID, PCI_ANY_ID},
1942#endif
1943 { } /* Terminating entry */
1944};
1945
1946MODULE_DEVICE_TABLE(pci, hisax_pci_tbl);
1947#endif /* CONFIG_PCI */
1948
1949module_init(HiSax_init);
1950module_exit(HiSax_exit);
1951
1952EXPORT_SYMBOL(FsmNew);
1953EXPORT_SYMBOL(FsmFree);
1954EXPORT_SYMBOL(FsmEvent);
1955EXPORT_SYMBOL(FsmChangeState);
1956EXPORT_SYMBOL(FsmInitTimer);
1957EXPORT_SYMBOL(FsmDelTimer);
1958EXPORT_SYMBOL(FsmRestartTimer);
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
new file mode 100644
index 00000000000..394d481e093
--- /dev/null
+++ b/drivers/isdn/hisax/diva.c
@@ -0,0 +1,1183 @@
1/* $Id: diva.c,v 1.33.2.6 2004/02/11 13:21:33 keil Exp $
2 *
3 * low level stuff for Eicon.Diehl Diva Family ISDN cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * For changes and modifications please read
12 * Documentation/isdn/HiSax.cert
13 *
14 * Thanks to Eicon Technology for documents and information
15 *
16 */
17
18#include <linux/init.h>
19#include <linux/config.h>
20#include "hisax.h"
21#include "isac.h"
22#include "hscx.h"
23#include "ipac.h"
24#include "ipacx.h"
25#include "isdnl1.h"
26#include <linux/pci.h>
27#include <linux/isapnp.h>
28
29extern const char *CardType[];
30
31const char *Diva_revision = "$Revision: 1.33.2.6 $";
32
33#define byteout(addr,val) outb(val,addr)
34#define bytein(addr) inb(addr)
35
36#define DIVA_HSCX_DATA 0
37#define DIVA_HSCX_ADR 4
38#define DIVA_ISA_ISAC_DATA 2
39#define DIVA_ISA_ISAC_ADR 6
40#define DIVA_ISA_CTRL 7
41#define DIVA_IPAC_ADR 0
42#define DIVA_IPAC_DATA 1
43
44#define DIVA_PCI_ISAC_DATA 8
45#define DIVA_PCI_ISAC_ADR 0xc
46#define DIVA_PCI_CTRL 0x10
47
48/* SUB Types */
49#define DIVA_ISA 1
50#define DIVA_PCI 2
51#define DIVA_IPAC_ISA 3
52#define DIVA_IPAC_PCI 4
53#define DIVA_IPACX_PCI 5
54
55/* CTRL (Read) */
56#define DIVA_IRQ_STAT 0x01
57#define DIVA_EEPROM_SDA 0x02
58
59/* CTRL (Write) */
60#define DIVA_IRQ_REQ 0x01
61#define DIVA_RESET 0x08
62#define DIVA_EEPROM_CLK 0x40
63#define DIVA_PCI_LED_A 0x10
64#define DIVA_PCI_LED_B 0x20
65#define DIVA_ISA_LED_A 0x20
66#define DIVA_ISA_LED_B 0x40
67#define DIVA_IRQ_CLR 0x80
68
69/* Siemens PITA */
70#define PITA_MISC_REG 0x1c
71#ifdef __BIG_ENDIAN
72#define PITA_PARA_SOFTRESET 0x00000001
73#define PITA_SER_SOFTRESET 0x00000002
74#define PITA_PARA_MPX_MODE 0x00000004
75#define PITA_INT0_ENABLE 0x00000200
76#else
77#define PITA_PARA_SOFTRESET 0x01000000
78#define PITA_SER_SOFTRESET 0x02000000
79#define PITA_PARA_MPX_MODE 0x04000000
80#define PITA_INT0_ENABLE 0x00020000
81#endif
82#define PITA_INT0_STATUS 0x02
83
84static inline u_char
85readreg(unsigned int ale, unsigned int adr, u_char off)
86{
87 register u_char ret;
88
89 byteout(ale, off);
90 ret = bytein(adr);
91 return (ret);
92}
93
94static inline void
95readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
96{
97 byteout(ale, off);
98 insb(adr, data, size);
99}
100
101
102static inline void
103writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
104{
105 byteout(ale, off);
106 byteout(adr, data);
107}
108
109static inline void
110writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
111{
112 byteout(ale, off);
113 outsb(adr, data, size);
114}
115
116static inline u_char
117memreadreg(unsigned long adr, u_char off)
118{
119 return(*((unsigned char *)
120 (((unsigned int *)adr) + off)));
121}
122
123static inline void
124memwritereg(unsigned long adr, u_char off, u_char data)
125{
126 register u_char *p;
127
128 p = (unsigned char *)(((unsigned int *)adr) + off);
129 *p = data;
130}
131
132/* Interface functions */
133
134static u_char
135ReadISAC(struct IsdnCardState *cs, u_char offset)
136{
137 return(readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset));
138}
139
140static void
141WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
142{
143 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value);
144}
145
146static void
147ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
148{
149 readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
150}
151
152static void
153WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
154{
155 writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
156}
157
158static u_char
159ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
160{
161 return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80));
162}
163
164static void
165WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
166{
167 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value);
168}
169
170static void
171ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
172{
173 readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
174}
175
176static void
177WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
178{
179 writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
180}
181
182static u_char
183ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
184{
185 return(readreg(cs->hw.diva.hscx_adr,
186 cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0)));
187}
188
189static void
190WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
191{
192 writereg(cs->hw.diva.hscx_adr,
193 cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value);
194}
195
196static u_char
197MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
198{
199 return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80));
200}
201
202static void
203MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
204{
205 memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value);
206}
207
208static void
209MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
210{
211 while(size--)
212 *data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80);
213}
214
215static void
216MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
217{
218 while(size--)
219 memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++);
220}
221
222static u_char
223MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
224{
225 return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0)));
226}
227
228static void
229MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
230{
231 memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
232}
233
234/* IO-Functions for IPACX type cards */
235static u_char
236MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset)
237{
238 return (memreadreg(cs->hw.diva.cfg_reg, offset));
239}
240
241static void
242MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value)
243{
244 memwritereg(cs->hw.diva.cfg_reg, offset, value);
245}
246
247static void
248MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
249{
250 while(size--)
251 *data++ = memreadreg(cs->hw.diva.cfg_reg, 0);
252}
253
254static void
255MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
256{
257 while(size--)
258 memwritereg(cs->hw.diva.cfg_reg, 0, *data++);
259}
260
261static u_char
262MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset)
263{
264 return(memreadreg(cs->hw.diva.cfg_reg, offset +
265 (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1)));
266}
267
268static void
269MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
270{
271 memwritereg(cs->hw.diva.cfg_reg, offset +
272 (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value);
273}
274
275/*
276 * fast interrupt HSCX stuff goes here
277 */
278
279#define READHSCX(cs, nr, reg) readreg(cs->hw.diva.hscx_adr, \
280 cs->hw.diva.hscx, reg + (nr ? 0x40 : 0))
281#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \
282 cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data)
283
284#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \
285 cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
286
287#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \
288 cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
289
290#include "hscx_irq.c"
291
292static irqreturn_t
293diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
294{
295 struct IsdnCardState *cs = dev_id;
296 u_char val, sval;
297 u_long flags;
298 int cnt=5;
299
300 spin_lock_irqsave(&cs->lock, flags);
301 while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
302 val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
303 if (val)
304 hscx_int_main(cs, val);
305 val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA);
306 if (val)
307 isac_interrupt(cs, val);
308 cnt--;
309 }
310 if (!cnt)
311 printk(KERN_WARNING "Diva: IRQ LOOP\n");
312 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
313 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
314 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
315 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
316 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
317 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
318 spin_unlock_irqrestore(&cs->lock, flags);
319 return IRQ_HANDLED;
320}
321
322static irqreturn_t
323diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
324{
325 struct IsdnCardState *cs = dev_id;
326 u_char ista,val;
327 u_long flags;
328 int icnt=5;
329
330 spin_lock_irqsave(&cs->lock, flags);
331 ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
332Start_IPACISA:
333 if (cs->debug & L1_DEB_IPAC)
334 debugl1(cs, "IPAC ISTA %02X", ista);
335 if (ista & 0x0f) {
336 val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40);
337 if (ista & 0x01)
338 val |= 0x01;
339 if (ista & 0x04)
340 val |= 0x02;
341 if (ista & 0x08)
342 val |= 0x04;
343 if (val)
344 hscx_int_main(cs, val);
345 }
346 if (ista & 0x20) {
347 val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80);
348 if (val) {
349 isac_interrupt(cs, val);
350 }
351 }
352 if (ista & 0x10) {
353 val = 0x01;
354 isac_interrupt(cs, val);
355 }
356 ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
357 if ((ista & 0x3f) && icnt) {
358 icnt--;
359 goto Start_IPACISA;
360 }
361 if (!icnt)
362 printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
363 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF);
364 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
365 spin_unlock_irqrestore(&cs->lock, flags);
366 return IRQ_HANDLED;
367}
368
369static inline void
370MemwaitforCEC(struct IsdnCardState *cs, int hscx)
371{
372 int to = 50;
373
374 while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
375 udelay(1);
376 to--;
377 }
378 if (!to)
379 printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
380}
381
382
383static inline void
384MemwaitforXFW(struct IsdnCardState *cs, int hscx)
385{
386 int to = 50;
387
388 while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
389 udelay(1);
390 to--;
391 }
392 if (!to)
393 printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
394}
395
396static inline void
397MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
398{
399 MemwaitforCEC(cs, hscx);
400 MemWriteHSCX(cs, hscx, HSCX_CMDR, data);
401}
402
403static void
404Memhscx_empty_fifo(struct BCState *bcs, int count)
405{
406 u_char *ptr;
407 struct IsdnCardState *cs = bcs->cs;
408 int cnt;
409
410 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
411 debugl1(cs, "hscx_empty_fifo");
412
413 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
414 if (cs->debug & L1_DEB_WARN)
415 debugl1(cs, "hscx_empty_fifo: incoming packet too large");
416 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
417 bcs->hw.hscx.rcvidx = 0;
418 return;
419 }
420 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
421 cnt = count;
422 while (cnt--)
423 *ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
424 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
425 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
426 bcs->hw.hscx.rcvidx += count;
427 if (cs->debug & L1_DEB_HSCX_FIFO) {
428 char *t = bcs->blog;
429
430 t += sprintf(t, "hscx_empty_fifo %c cnt %d",
431 bcs->hw.hscx.hscx ? 'B' : 'A', count);
432 QuickHex(t, ptr, count);
433 debugl1(cs, bcs->blog);
434 }
435}
436
437static void
438Memhscx_fill_fifo(struct BCState *bcs)
439{
440 struct IsdnCardState *cs = bcs->cs;
441 int more, count, cnt;
442 int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
443 u_char *ptr,*p;
444
445 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
446 debugl1(cs, "hscx_fill_fifo");
447
448 if (!bcs->tx_skb)
449 return;
450 if (bcs->tx_skb->len <= 0)
451 return;
452
453 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
454 if (bcs->tx_skb->len > fifo_size) {
455 more = !0;
456 count = fifo_size;
457 } else
458 count = bcs->tx_skb->len;
459 cnt = count;
460 MemwaitforXFW(cs, bcs->hw.hscx.hscx);
461 p = ptr = bcs->tx_skb->data;
462 skb_pull(bcs->tx_skb, count);
463 bcs->tx_cnt -= count;
464 bcs->hw.hscx.count += count;
465 while(cnt--)
466 memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
467 *p++);
468 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
469 if (cs->debug & L1_DEB_HSCX_FIFO) {
470 char *t = bcs->blog;
471
472 t += sprintf(t, "hscx_fill_fifo %c cnt %d",
473 bcs->hw.hscx.hscx ? 'B' : 'A', count);
474 QuickHex(t, ptr, count);
475 debugl1(cs, bcs->blog);
476 }
477}
478
479static inline void
480Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
481{
482 u_char r;
483 struct BCState *bcs = cs->bcs + hscx;
484 struct sk_buff *skb;
485 int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
486 int count;
487
488 if (!test_bit(BC_FLG_INIT, &bcs->Flag))
489 return;
490
491 if (val & 0x80) { /* RME */
492 r = MemReadHSCX(cs, hscx, HSCX_RSTA);
493 if ((r & 0xf0) != 0xa0) {
494 if (!(r & 0x80))
495 if (cs->debug & L1_DEB_WARN)
496 debugl1(cs, "HSCX invalid frame");
497 if ((r & 0x40) && bcs->mode)
498 if (cs->debug & L1_DEB_WARN)
499 debugl1(cs, "HSCX RDO mode=%d",
500 bcs->mode);
501 if (!(r & 0x20))
502 if (cs->debug & L1_DEB_WARN)
503 debugl1(cs, "HSCX CRC error");
504 MemWriteHSCXCMDR(cs, hscx, 0x80);
505 } else {
506 count = MemReadHSCX(cs, hscx, HSCX_RBCL) & (
507 test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
508 if (count == 0)
509 count = fifo_size;
510 Memhscx_empty_fifo(bcs, count);
511 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
512 if (cs->debug & L1_DEB_HSCX_FIFO)
513 debugl1(cs, "HX Frame %d", count);
514 if (!(skb = dev_alloc_skb(count)))
515 printk(KERN_WARNING "HSCX: receive out of memory\n");
516 else {
517 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
518 skb_queue_tail(&bcs->rqueue, skb);
519 }
520 }
521 }
522 bcs->hw.hscx.rcvidx = 0;
523 schedule_event(bcs, B_RCVBUFREADY);
524 }
525 if (val & 0x40) { /* RPF */
526 Memhscx_empty_fifo(bcs, fifo_size);
527 if (bcs->mode == L1_MODE_TRANS) {
528 /* receive audio data */
529 if (!(skb = dev_alloc_skb(fifo_size)))
530 printk(KERN_WARNING "HiSax: receive out of memory\n");
531 else {
532 memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
533 skb_queue_tail(&bcs->rqueue, skb);
534 }
535 bcs->hw.hscx.rcvidx = 0;
536 schedule_event(bcs, B_RCVBUFREADY);
537 }
538 }
539 if (val & 0x10) { /* XPR */
540 if (bcs->tx_skb) {
541 if (bcs->tx_skb->len) {
542 Memhscx_fill_fifo(bcs);
543 return;
544 } else {
545 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
546 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
547 u_long flags;
548 spin_lock_irqsave(&bcs->aclock, flags);
549 bcs->ackcnt += bcs->hw.hscx.count;
550 spin_unlock_irqrestore(&bcs->aclock, flags);
551 schedule_event(bcs, B_ACKPENDING);
552 }
553 dev_kfree_skb_irq(bcs->tx_skb);
554 bcs->hw.hscx.count = 0;
555 bcs->tx_skb = NULL;
556 }
557 }
558 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
559 bcs->hw.hscx.count = 0;
560 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
561 Memhscx_fill_fifo(bcs);
562 } else {
563 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
564 schedule_event(bcs, B_XMTBUFREADY);
565 }
566 }
567}
568
569static inline void
570Memhscx_int_main(struct IsdnCardState *cs, u_char val)
571{
572
573 u_char exval;
574 struct BCState *bcs;
575
576 if (val & 0x01) { // EXB
577 bcs = cs->bcs + 1;
578 exval = MemReadHSCX(cs, 1, HSCX_EXIR);
579 if (exval & 0x40) {
580 if (bcs->mode == 1)
581 Memhscx_fill_fifo(bcs);
582 else {
583 /* Here we lost an TX interrupt, so
584 * restart transmitting the whole frame.
585 */
586 if (bcs->tx_skb) {
587 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
588 bcs->tx_cnt += bcs->hw.hscx.count;
589 bcs->hw.hscx.count = 0;
590 }
591 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
592 if (cs->debug & L1_DEB_WARN)
593 debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
594 }
595 } else if (cs->debug & L1_DEB_HSCX)
596 debugl1(cs, "HSCX B EXIR %x", exval);
597 }
598 if (val & 0xf8) {
599 if (cs->debug & L1_DEB_HSCX)
600 debugl1(cs, "HSCX B interrupt %x", val);
601 Memhscx_interrupt(cs, val, 1);
602 }
603 if (val & 0x02) { // EXA
604 bcs = cs->bcs;
605 exval = MemReadHSCX(cs, 0, HSCX_EXIR);
606 if (exval & 0x40) {
607 if (bcs->mode == L1_MODE_TRANS)
608 Memhscx_fill_fifo(bcs);
609 else {
610 /* Here we lost an TX interrupt, so
611 * restart transmitting the whole frame.
612 */
613 if (bcs->tx_skb) {
614 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
615 bcs->tx_cnt += bcs->hw.hscx.count;
616 bcs->hw.hscx.count = 0;
617 }
618 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
619 if (cs->debug & L1_DEB_WARN)
620 debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
621 }
622 } else if (cs->debug & L1_DEB_HSCX)
623 debugl1(cs, "HSCX A EXIR %x", exval);
624 }
625 if (val & 0x04) { // ICA
626 exval = MemReadHSCX(cs, 0, HSCX_ISTA);
627 if (cs->debug & L1_DEB_HSCX)
628 debugl1(cs, "HSCX A interrupt %x", exval);
629 Memhscx_interrupt(cs, exval, 0);
630 }
631}
632
633static irqreturn_t
634diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
635{
636 struct IsdnCardState *cs = dev_id;
637 u_char ista,val;
638 int icnt=5;
639 u_char *cfg;
640 u_long flags;
641
642 spin_lock_irqsave(&cs->lock, flags);
643 cfg = (u_char *) cs->hw.diva.pci_cfg;
644 val = *cfg;
645 if (!(val & PITA_INT0_STATUS)) {
646 spin_unlock_irqrestore(&cs->lock, flags);
647 return IRQ_NONE; /* other shared IRQ */
648 }
649 *cfg = PITA_INT0_STATUS; /* Reset pending INT0 */
650 ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
651Start_IPACPCI:
652 if (cs->debug & L1_DEB_IPAC)
653 debugl1(cs, "IPAC ISTA %02X", ista);
654 if (ista & 0x0f) {
655 val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40);
656 if (ista & 0x01)
657 val |= 0x01;
658 if (ista & 0x04)
659 val |= 0x02;
660 if (ista & 0x08)
661 val |= 0x04;
662 if (val)
663 Memhscx_int_main(cs, val);
664 }
665 if (ista & 0x20) {
666 val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
667 if (val) {
668 isac_interrupt(cs, val);
669 }
670 }
671 if (ista & 0x10) {
672 val = 0x01;
673 isac_interrupt(cs, val);
674 }
675 ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
676 if ((ista & 0x3f) && icnt) {
677 icnt--;
678 goto Start_IPACPCI;
679 }
680 if (!icnt)
681 printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n");
682 memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF);
683 memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
684 spin_unlock_irqrestore(&cs->lock, flags);
685 return IRQ_HANDLED;
686}
687
688static irqreturn_t
689diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
690{
691 struct IsdnCardState *cs = dev_id;
692 u_char val;
693 u_char *cfg;
694 u_long flags;
695
696 spin_lock_irqsave(&cs->lock, flags);
697 cfg = (u_char *) cs->hw.diva.pci_cfg;
698 val = *cfg;
699 if (!(val &PITA_INT0_STATUS)) {
700 spin_unlock_irqrestore(&cs->lock, flags);
701 return IRQ_NONE; // other shared IRQ
702 }
703 interrupt_ipacx(cs); // handler for chip
704 *cfg = PITA_INT0_STATUS; // Reset PLX interrupt
705 spin_unlock_irqrestore(&cs->lock, flags);
706 return IRQ_HANDLED;
707}
708
709void
710release_io_diva(struct IsdnCardState *cs)
711{
712 int bytecnt;
713
714 if ((cs->subtyp == DIVA_IPAC_PCI) ||
715 (cs->subtyp == DIVA_IPACX_PCI) ) {
716 u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
717
718 *cfg = 0; /* disable INT0/1 */
719 *cfg = 2; /* reset pending INT0 */
720 iounmap((void *)cs->hw.diva.cfg_reg);
721 iounmap((void *)cs->hw.diva.pci_cfg);
722 return;
723 } else if (cs->subtyp != DIVA_IPAC_ISA) {
724 del_timer(&cs->hw.diva.tl);
725 if (cs->hw.diva.cfg_reg)
726 byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
727 }
728 if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
729 bytecnt = 8;
730 else
731 bytecnt = 32;
732 if (cs->hw.diva.cfg_reg) {
733 release_region(cs->hw.diva.cfg_reg, bytecnt);
734 }
735}
736
737static void
738reset_diva(struct IsdnCardState *cs)
739{
740 if (cs->subtyp == DIVA_IPAC_ISA) {
741 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
742 mdelay(10);
743 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
744 mdelay(10);
745 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
746 } else if (cs->subtyp == DIVA_IPAC_PCI) {
747 unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
748 PITA_MISC_REG);
749 *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
750 mdelay(10);
751 *ireg = PITA_PARA_MPX_MODE;
752 mdelay(10);
753 memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
754 } else if (cs->subtyp == DIVA_IPACX_PCI) {
755 unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
756 PITA_MISC_REG);
757 *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
758 mdelay(10);
759 *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET;
760 mdelay(10);
761 MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off
762 } else { /* DIVA 2.0 */
763 cs->hw.diva.ctrl_reg = 0; /* Reset On */
764 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
765 mdelay(10);
766 cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */
767 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
768 mdelay(10);
769 if (cs->subtyp == DIVA_ISA)
770 cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
771 else {
772 /* Workaround PCI9060 */
773 byteout(cs->hw.diva.pci_cfg + 0x69, 9);
774 cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
775 }
776 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
777 }
778}
779
780#define DIVA_ASSIGN 1
781
782static void
783diva_led_handler(struct IsdnCardState *cs)
784{
785 int blink = 0;
786
787 if ((cs->subtyp == DIVA_IPAC_ISA) ||
788 (cs->subtyp == DIVA_IPAC_PCI) ||
789 (cs->subtyp == DIVA_IPACX_PCI) )
790 return;
791 del_timer(&cs->hw.diva.tl);
792 if (cs->hw.diva.status & DIVA_ASSIGN)
793 cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
794 DIVA_ISA_LED_A : DIVA_PCI_LED_A;
795 else {
796 cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
797 DIVA_ISA_LED_A : DIVA_PCI_LED_A;
798 blink = 250;
799 }
800 if (cs->hw.diva.status & 0xf000)
801 cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
802 DIVA_ISA_LED_B : DIVA_PCI_LED_B;
803 else if (cs->hw.diva.status & 0x0f00) {
804 cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
805 DIVA_ISA_LED_B : DIVA_PCI_LED_B;
806 blink = 500;
807 } else
808 cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ?
809 DIVA_ISA_LED_B : DIVA_PCI_LED_B);
810
811 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
812 if (blink) {
813 init_timer(&cs->hw.diva.tl);
814 cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000);
815 add_timer(&cs->hw.diva.tl);
816 }
817}
818
819static int
820Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
821{
822 u_int *ireg;
823 u_long flags;
824
825 switch (mt) {
826 case CARD_RESET:
827 spin_lock_irqsave(&cs->lock, flags);
828 reset_diva(cs);
829 spin_unlock_irqrestore(&cs->lock, flags);
830 return(0);
831 case CARD_RELEASE:
832 release_io_diva(cs);
833 return(0);
834 case CARD_INIT:
835 spin_lock_irqsave(&cs->lock, flags);
836 reset_diva(cs);
837 if (cs->subtyp == DIVA_IPACX_PCI) {
838 ireg = (unsigned int *)cs->hw.diva.pci_cfg;
839 *ireg = PITA_INT0_ENABLE;
840 init_ipacx(cs, 3); // init chip and enable interrupts
841 spin_unlock_irqrestore(&cs->lock, flags);
842 return (0);
843 }
844 if (cs->subtyp == DIVA_IPAC_PCI) {
845 ireg = (unsigned int *)cs->hw.diva.pci_cfg;
846 *ireg = PITA_INT0_ENABLE;
847 }
848 inithscxisac(cs, 3);
849 spin_unlock_irqrestore(&cs->lock, flags);
850 return(0);
851 case CARD_TEST:
852 return(0);
853 case (MDL_REMOVE | REQUEST):
854 cs->hw.diva.status = 0;
855 break;
856 case (MDL_ASSIGN | REQUEST):
857 cs->hw.diva.status |= DIVA_ASSIGN;
858 break;
859 case MDL_INFO_SETUP:
860 if ((long)arg)
861 cs->hw.diva.status |= 0x0200;
862 else
863 cs->hw.diva.status |= 0x0100;
864 break;
865 case MDL_INFO_CONN:
866 if ((long)arg)
867 cs->hw.diva.status |= 0x2000;
868 else
869 cs->hw.diva.status |= 0x1000;
870 break;
871 case MDL_INFO_REL:
872 if ((long)arg) {
873 cs->hw.diva.status &= ~0x2000;
874 cs->hw.diva.status &= ~0x0200;
875 } else {
876 cs->hw.diva.status &= ~0x1000;
877 cs->hw.diva.status &= ~0x0100;
878 }
879 break;
880 }
881 if ((cs->subtyp != DIVA_IPAC_ISA) &&
882 (cs->subtyp != DIVA_IPAC_PCI) &&
883 (cs->subtyp != DIVA_IPACX_PCI)) {
884 spin_lock_irqsave(&cs->lock, flags);
885 diva_led_handler(cs);
886 spin_unlock_irqrestore(&cs->lock, flags);
887 }
888 return(0);
889}
890
891static struct pci_dev *dev_diva __initdata = NULL;
892static struct pci_dev *dev_diva_u __initdata = NULL;
893static struct pci_dev *dev_diva201 __initdata = NULL;
894static struct pci_dev *dev_diva202 __initdata = NULL;
895
896#ifdef __ISAPNP__
897static struct isapnp_device_id diva_ids[] __initdata = {
898 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
899 ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
900 (unsigned long) "Diva picola" },
901 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
902 ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51),
903 (unsigned long) "Diva picola" },
904 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
905 ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
906 (unsigned long) "Diva 2.0" },
907 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
908 ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71),
909 (unsigned long) "Diva 2.0" },
910 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
911 ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
912 (unsigned long) "Diva 2.01" },
913 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
914 ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1),
915 (unsigned long) "Diva 2.01" },
916 { 0, }
917};
918
919static struct isapnp_device_id *ipid __initdata = &diva_ids[0];
920static struct pnp_card *pnp_c __devinitdata = NULL;
921#endif
922
923
924int __init
925setup_diva(struct IsdnCard *card)
926{
927 int bytecnt = 8;
928 u_char val;
929 struct IsdnCardState *cs = card->cs;
930 char tmp[64];
931
932 strcpy(tmp, Diva_revision);
933 printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
934 if (cs->typ != ISDN_CTYPE_DIEHLDIVA)
935 return(0);
936 cs->hw.diva.status = 0;
937 if (card->para[1]) {
938 cs->hw.diva.ctrl_reg = 0;
939 cs->hw.diva.cfg_reg = card->para[1];
940 val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
941 cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
942 printk(KERN_INFO "Diva: IPAC version %x\n", val);
943 if ((val == 1) || (val==2)) {
944 cs->subtyp = DIVA_IPAC_ISA;
945 cs->hw.diva.ctrl = 0;
946 cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
947 cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
948 cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
949 cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
950 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
951 } else {
952 cs->subtyp = DIVA_ISA;
953 cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
954 cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
955 cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
956 cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
957 cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
958 }
959 cs->irq = card->para[0];
960 } else {
961#ifdef __ISAPNP__
962 if (isapnp_present()) {
963 struct pnp_dev *pnp_d;
964 while(ipid->card_vendor) {
965 if ((pnp_c = pnp_find_card(ipid->card_vendor,
966 ipid->card_device, pnp_c))) {
967 pnp_d = NULL;
968 if ((pnp_d = pnp_find_dev(pnp_c,
969 ipid->vendor, ipid->function, pnp_d))) {
970 int err;
971
972 printk(KERN_INFO "HiSax: %s detected\n",
973 (char *)ipid->driver_data);
974 pnp_disable_dev(pnp_d);
975 err = pnp_activate_dev(pnp_d);
976 if (err<0) {
977 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
978 __FUNCTION__, err);
979 return(0);
980 }
981 card->para[1] = pnp_port_start(pnp_d, 0);
982 card->para[0] = pnp_irq(pnp_d, 0);
983 if (!card->para[0] || !card->para[1]) {
984 printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
985 card->para[0], card->para[1]);
986 pnp_disable_dev(pnp_d);
987 return(0);
988 }
989 cs->hw.diva.cfg_reg = card->para[1];
990 cs->irq = card->para[0];
991 if (ipid->function == ISAPNP_FUNCTION(0xA1)) {
992 cs->subtyp = DIVA_IPAC_ISA;
993 cs->hw.diva.ctrl = 0;
994 cs->hw.diva.isac =
995 card->para[1] + DIVA_IPAC_DATA;
996 cs->hw.diva.hscx =
997 card->para[1] + DIVA_IPAC_DATA;
998 cs->hw.diva.isac_adr =
999 card->para[1] + DIVA_IPAC_ADR;
1000 cs->hw.diva.hscx_adr =
1001 card->para[1] + DIVA_IPAC_ADR;
1002 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
1003 } else {
1004 cs->subtyp = DIVA_ISA;
1005 cs->hw.diva.ctrl =
1006 card->para[1] + DIVA_ISA_CTRL;
1007 cs->hw.diva.isac =
1008 card->para[1] + DIVA_ISA_ISAC_DATA;
1009 cs->hw.diva.hscx =
1010 card->para[1] + DIVA_HSCX_DATA;
1011 cs->hw.diva.isac_adr =
1012 card->para[1] + DIVA_ISA_ISAC_ADR;
1013 cs->hw.diva.hscx_adr =
1014 card->para[1] + DIVA_HSCX_ADR;
1015 }
1016 goto ready;
1017 } else {
1018 printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
1019 return(0);
1020 }
1021 }
1022 ipid++;
1023 pnp_c=NULL;
1024 }
1025 if (!ipid->card_vendor) {
1026 printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
1027 }
1028 }
1029#endif
1030#ifdef CONFIG_PCI
1031 cs->subtyp = 0;
1032 if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
1033 PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
1034 if (pci_enable_device(dev_diva))
1035 return(0);
1036 cs->subtyp = DIVA_PCI;
1037 cs->irq = dev_diva->irq;
1038 cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
1039 } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
1040 PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
1041 if (pci_enable_device(dev_diva_u))
1042 return(0);
1043 cs->subtyp = DIVA_PCI;
1044 cs->irq = dev_diva_u->irq;
1045 cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
1046 } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
1047 PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
1048 if (pci_enable_device(dev_diva201))
1049 return(0);
1050 cs->subtyp = DIVA_IPAC_PCI;
1051 cs->irq = dev_diva201->irq;
1052 cs->hw.diva.pci_cfg =
1053 (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
1054 cs->hw.diva.cfg_reg =
1055 (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
1056 } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,
1057 PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {
1058 if (pci_enable_device(dev_diva202))
1059 return(0);
1060 cs->subtyp = DIVA_IPACX_PCI;
1061 cs->irq = dev_diva202->irq;
1062 cs->hw.diva.pci_cfg =
1063 (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);
1064 cs->hw.diva.cfg_reg =
1065 (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);
1066 } else {
1067 printk(KERN_WARNING "Diva: No PCI card found\n");
1068 return(0);
1069 }
1070
1071 if (!cs->irq) {
1072 printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
1073 return(0);
1074 }
1075
1076 if (!cs->hw.diva.cfg_reg) {
1077 printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
1078 return(0);
1079 }
1080 cs->irq_flags |= SA_SHIRQ;
1081#else
1082 printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
1083 printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
1084 return (0);
1085#endif /* CONFIG_PCI */
1086 if ((cs->subtyp == DIVA_IPAC_PCI) ||
1087 (cs->subtyp == DIVA_IPACX_PCI) ) {
1088 cs->hw.diva.ctrl = 0;
1089 cs->hw.diva.isac = 0;
1090 cs->hw.diva.hscx = 0;
1091 cs->hw.diva.isac_adr = 0;
1092 cs->hw.diva.hscx_adr = 0;
1093 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
1094 bytecnt = 0;
1095 } else {
1096 cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
1097 cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
1098 cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
1099 cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
1100 cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
1101 bytecnt = 32;
1102 }
1103 }
1104ready:
1105 printk(KERN_INFO
1106 "Diva: %s card configured at %#lx IRQ %d\n",
1107 (cs->subtyp == DIVA_PCI) ? "PCI" :
1108 (cs->subtyp == DIVA_ISA) ? "ISA" :
1109 (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
1110 (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
1111 cs->hw.diva.cfg_reg, cs->irq);
1112 if ((cs->subtyp == DIVA_IPAC_PCI) ||
1113 (cs->subtyp == DIVA_IPACX_PCI) ||
1114 (cs->subtyp == DIVA_PCI) )
1115 printk(KERN_INFO "Diva: %s space at %#lx\n",
1116 (cs->subtyp == DIVA_PCI) ? "PCI" :
1117 (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
1118 cs->hw.diva.pci_cfg);
1119 if ((cs->subtyp != DIVA_IPAC_PCI) &&
1120 (cs->subtyp != DIVA_IPACX_PCI) ) {
1121 if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) {
1122 printk(KERN_WARNING
1123 "HiSax: %s config port %lx-%lx already in use\n",
1124 CardType[card->typ],
1125 cs->hw.diva.cfg_reg,
1126 cs->hw.diva.cfg_reg + bytecnt);
1127 return (0);
1128 }
1129 }
1130 cs->BC_Read_Reg = &ReadHSCX;
1131 cs->BC_Write_Reg = &WriteHSCX;
1132 cs->BC_Send_Data = &hscx_fill_fifo;
1133 cs->cardmsg = &Diva_card_msg;
1134 setup_isac(cs);
1135 if (cs->subtyp == DIVA_IPAC_ISA) {
1136 cs->readisac = &ReadISAC_IPAC;
1137 cs->writeisac = &WriteISAC_IPAC;
1138 cs->readisacfifo = &ReadISACfifo_IPAC;
1139 cs->writeisacfifo = &WriteISACfifo_IPAC;
1140 cs->irq_func = &diva_irq_ipac_isa;
1141 val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
1142 printk(KERN_INFO "Diva: IPAC version %x\n", val);
1143 } else if (cs->subtyp == DIVA_IPAC_PCI) {
1144 cs->readisac = &MemReadISAC_IPAC;
1145 cs->writeisac = &MemWriteISAC_IPAC;
1146 cs->readisacfifo = &MemReadISACfifo_IPAC;
1147 cs->writeisacfifo = &MemWriteISACfifo_IPAC;
1148 cs->BC_Read_Reg = &MemReadHSCX;
1149 cs->BC_Write_Reg = &MemWriteHSCX;
1150 cs->BC_Send_Data = &Memhscx_fill_fifo;
1151 cs->irq_func = &diva_irq_ipac_pci;
1152 val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
1153 printk(KERN_INFO "Diva: IPAC version %x\n", val);
1154 } else if (cs->subtyp == DIVA_IPACX_PCI) {
1155 cs->readisac = &MemReadISAC_IPACX;
1156 cs->writeisac = &MemWriteISAC_IPACX;
1157 cs->readisacfifo = &MemReadISACfifo_IPACX;
1158 cs->writeisacfifo = &MemWriteISACfifo_IPACX;
1159 cs->BC_Read_Reg = &MemReadHSCX_IPACX;
1160 cs->BC_Write_Reg = &MemWriteHSCX_IPACX;
1161 cs->BC_Send_Data = NULL; // function located in ipacx module
1162 cs->irq_func = &diva_irq_ipacx_pci;
1163 printk(KERN_INFO "Diva: IPACX Design Id: %x\n",
1164 MemReadISAC_IPACX(cs, IPACX_ID) &0x3F);
1165 } else { /* DIVA 2.0 */
1166 cs->hw.diva.tl.function = (void *) diva_led_handler;
1167 cs->hw.diva.tl.data = (long) cs;
1168 init_timer(&cs->hw.diva.tl);
1169 cs->readisac = &ReadISAC;
1170 cs->writeisac = &WriteISAC;
1171 cs->readisacfifo = &ReadISACfifo;
1172 cs->writeisacfifo = &WriteISACfifo;
1173 cs->irq_func = &diva_interrupt;
1174 ISACVersion(cs, "Diva:");
1175 if (HscxVersion(cs, "Diva:")) {
1176 printk(KERN_WARNING
1177 "Diva: wrong HSCX versions check IO address\n");
1178 release_io_diva(cs);
1179 return (0);
1180 }
1181 }
1182 return (1);
1183}
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
new file mode 100644
index 00000000000..4d7a0250d7e
--- /dev/null
+++ b/drivers/isdn/hisax/elsa.c
@@ -0,0 +1,1190 @@
1/* $Id: elsa.c,v 2.32.2.4 2004/01/24 20:47:21 keil Exp $
2 *
3 * low level stuff for Elsa isdn cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * For changes and modifications please read
12 * Documentation/isdn/HiSax.cert
13 *
14 * Thanks to Elsa GmbH for documents and information
15 *
16 * Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE)
17 * for ELSA PCMCIA support
18 *
19 */
20
21#include <linux/init.h>
22#include <linux/config.h>
23#include "hisax.h"
24#include "arcofi.h"
25#include "isac.h"
26#include "ipac.h"
27#include "hscx.h"
28#include "isdnl1.h"
29#include <linux/pci.h>
30#include <linux/isapnp.h>
31#include <linux/serial.h>
32#include <linux/serial_reg.h>
33
34extern const char *CardType[];
35
36const char *Elsa_revision = "$Revision: 2.32.2.4 $";
37const char *Elsa_Types[] =
38{"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
39 "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI",
40 "PCMCIA-IPAC" };
41
42const char *ITACVer[] =
43{"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2",
44 "B1", "A1"};
45
46#define byteout(addr,val) outb(val,addr)
47#define bytein(addr) inb(addr)
48
49#define ELSA_ISAC 0
50#define ELSA_ISAC_PCM 1
51#define ELSA_ITAC 1
52#define ELSA_HSCX 2
53#define ELSA_ALE 3
54#define ELSA_ALE_PCM 4
55#define ELSA_CONTROL 4
56#define ELSA_CONFIG 5
57#define ELSA_START_TIMER 6
58#define ELSA_TRIG_IRQ 7
59
60#define ELSA_PC 1
61#define ELSA_PCC8 2
62#define ELSA_PCC16 3
63#define ELSA_PCF 4
64#define ELSA_PCFPRO 5
65#define ELSA_PCMCIA 6
66#define ELSA_QS1000 7
67#define ELSA_QS3000 8
68#define ELSA_QS1000PCI 9
69#define ELSA_QS3000PCI 10
70#define ELSA_PCMCIA_IPAC 11
71
72/* PCI stuff */
73#define ELSA_PCI_IRQ_MASK 0x04
74
75/* ITAC Registeradressen (only Microlink PC) */
76#define ITAC_SYS 0x34
77#define ITAC_ISEN 0x48
78#define ITAC_RFIE 0x4A
79#define ITAC_XFIE 0x4C
80#define ITAC_SCIE 0x4E
81#define ITAC_STIE 0x46
82
83/*** ***
84 *** Makros als Befehle fuer die Kartenregister ***
85 *** (mehrere Befehle werden durch Bit-Oderung kombiniert) ***
86 *** ***/
87
88/* Config-Register (Read) */
89#define ELSA_TIMER_RUN 0x02 /* Bit 1 des Config-Reg */
90#define ELSA_TIMER_RUN_PCC8 0x01 /* Bit 0 des Config-Reg bei PCC */
91#define ELSA_IRQ_IDX 0x38 /* Bit 3,4,5 des Config-Reg */
92#define ELSA_IRQ_IDX_PCC8 0x30 /* Bit 4,5 des Config-Reg */
93#define ELSA_IRQ_IDX_PC 0x0c /* Bit 2,3 des Config-Reg */
94
95/* Control-Register (Write) */
96#define ELSA_LINE_LED 0x02 /* Bit 1 Gelbe LED */
97#define ELSA_STAT_LED 0x08 /* Bit 3 Gruene LED */
98#define ELSA_ISDN_RESET 0x20 /* Bit 5 Reset-Leitung */
99#define ELSA_ENA_TIMER_INT 0x80 /* Bit 7 Freigabe Timer Interrupt */
100
101/* ALE-Register (Read) */
102#define ELSA_HW_RELEASE 0x07 /* Bit 0-2 Hardwarerkennung */
103#define ELSA_S0_POWER_BAD 0x08 /* Bit 3 S0-Bus Spannung fehlt */
104
105/* Status Flags */
106#define ELSA_TIMER_AKTIV 1
107#define ELSA_BAD_PWR 2
108#define ELSA_ASSIGN 4
109
110#define RS_ISR_PASS_LIMIT 256
111#define _INLINE_ inline
112#define FLG_MODEM_ACTIVE 1
113/* IPAC AUX */
114#define ELSA_IPAC_LINE_LED 0x40 /* Bit 6 Gelbe LED */
115#define ELSA_IPAC_STAT_LED 0x80 /* Bit 7 Gruene LED */
116
117#if ARCOFI_USE
118static struct arcofi_msg ARCOFI_XOP_F =
119 {NULL,0,2,{0xa1,0x3f,0,0,0,0,0,0,0,0}}; /* Normal OP */
120static struct arcofi_msg ARCOFI_XOP_1 =
121 {&ARCOFI_XOP_F,0,2,{0xa1,0x31,0,0,0,0,0,0,0,0}}; /* PWR UP */
122static struct arcofi_msg ARCOFI_SOP_F =
123 {&ARCOFI_XOP_1,0,10,{0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12}};
124static struct arcofi_msg ARCOFI_COP_9 =
125 {&ARCOFI_SOP_F,0,10,{0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}}; /* RX */
126static struct arcofi_msg ARCOFI_COP_8 =
127 {&ARCOFI_COP_9,0,10,{0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}}; /* TX */
128static struct arcofi_msg ARCOFI_COP_7 =
129 {&ARCOFI_COP_8,0,4,{0xa1,0x27,0x80,0x80,0,0,0,0,0,0}}; /* GZ */
130static struct arcofi_msg ARCOFI_COP_6 =
131 {&ARCOFI_COP_7,0,6,{0xa1,0x26,0,0,0x82,0x7c,0,0,0,0}}; /* GRL GRH */
132static struct arcofi_msg ARCOFI_COP_5 =
133 {&ARCOFI_COP_6,0,4,{0xa1,0x25,0xbb,0x4a,0,0,0,0,0,0}}; /* GTX */
134static struct arcofi_msg ARCOFI_VERSION =
135 {NULL,1,2,{0xa0,0,0,0,0,0,0,0,0,0}};
136static struct arcofi_msg ARCOFI_XOP_0 =
137 {NULL,0,2,{0xa1,0x30,0,0,0,0,0,0,0,0}}; /* PWR Down */
138
139static void set_arcofi(struct IsdnCardState *cs, int bc);
140
141#include "elsa_ser.c"
142#endif /* ARCOFI_USE */
143
144static inline u_char
145readreg(unsigned int ale, unsigned int adr, u_char off)
146{
147 register u_char ret;
148
149 byteout(ale, off);
150 ret = bytein(adr);
151 return (ret);
152}
153
154static inline void
155readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
156{
157 byteout(ale, off);
158 insb(adr, data, size);
159}
160
161
162static inline void
163writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
164{
165 byteout(ale, off);
166 byteout(adr, data);
167}
168
169static inline void
170writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
171{
172 byteout(ale, off);
173 outsb(adr, data, size);
174}
175
176/* Interface functions */
177
178static u_char
179ReadISAC(struct IsdnCardState *cs, u_char offset)
180{
181 return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset));
182}
183
184static void
185WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
186{
187 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset, value);
188}
189
190static void
191ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
192{
193 readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size);
194}
195
196static void
197WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
198{
199 writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size);
200}
201
202static u_char
203ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
204{
205 return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset+0x80));
206}
207
208static void
209WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
210{
211 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset|0x80, value);
212}
213
214static void
215ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
216{
217 readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size);
218}
219
220static void
221WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
222{
223 writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size);
224}
225
226static u_char
227ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
228{
229 return (readreg(cs->hw.elsa.ale,
230 cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0)));
231}
232
233static void
234WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
235{
236 writereg(cs->hw.elsa.ale,
237 cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value);
238}
239
240static inline u_char
241readitac(struct IsdnCardState *cs, u_char off)
242{
243 register u_char ret;
244
245 byteout(cs->hw.elsa.ale, off);
246 ret = bytein(cs->hw.elsa.itac);
247 return (ret);
248}
249
250static inline void
251writeitac(struct IsdnCardState *cs, u_char off, u_char data)
252{
253 byteout(cs->hw.elsa.ale, off);
254 byteout(cs->hw.elsa.itac, data);
255}
256
257static inline int
258TimerRun(struct IsdnCardState *cs)
259{
260 register u_char v;
261
262 v = bytein(cs->hw.elsa.cfg);
263 if ((cs->subtyp == ELSA_QS1000) || (cs->subtyp == ELSA_QS3000))
264 return (0 == (v & ELSA_TIMER_RUN));
265 else if (cs->subtyp == ELSA_PCC8)
266 return (v & ELSA_TIMER_RUN_PCC8);
267 return (v & ELSA_TIMER_RUN);
268}
269/*
270 * fast interrupt HSCX stuff goes here
271 */
272
273#define READHSCX(cs, nr, reg) readreg(cs->hw.elsa.ale, \
274 cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0))
275#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.elsa.ale, \
276 cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0), data)
277
278#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.elsa.ale, \
279 cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt)
280
281#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.elsa.ale, \
282 cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt)
283
284#include "hscx_irq.c"
285
286static irqreturn_t
287elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
288{
289 struct IsdnCardState *cs = dev_id;
290 u_long flags;
291 u_char val;
292 int icnt=5;
293
294 if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
295 /* The card tends to generate interrupts while being removed
296 causing us to just crash the kernel. bad. */
297 printk(KERN_WARNING "Elsa: card not available!\n");
298 return IRQ_NONE;
299 }
300 spin_lock_irqsave(&cs->lock, flags);
301#if ARCOFI_USE
302 if (cs->hw.elsa.MFlag) {
303 val = serial_inp(cs, UART_IIR);
304 if (!(val & UART_IIR_NO_INT)) {
305 debugl1(cs,"IIR %02x", val);
306 rs_interrupt_elsa(intno, cs);
307 }
308 }
309#endif
310 val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
311 Start_HSCX:
312 if (val) {
313 hscx_int_main(cs, val);
314 }
315 val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA);
316 Start_ISAC:
317 if (val) {
318 isac_interrupt(cs, val);
319 }
320 val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
321 if (val && icnt) {
322 if (cs->debug & L1_DEB_HSCX)
323 debugl1(cs, "HSCX IntStat after IntRoutine");
324 icnt--;
325 goto Start_HSCX;
326 }
327 val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA);
328 if (val && icnt) {
329 if (cs->debug & L1_DEB_ISAC)
330 debugl1(cs, "ISAC IntStat after IntRoutine");
331 icnt--;
332 goto Start_ISAC;
333 }
334 if (!icnt)
335 printk(KERN_WARNING"ELSA IRQ LOOP\n");
336 writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF);
337 writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF);
338 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF);
339 if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) {
340 if (!TimerRun(cs)) {
341 /* Timer Restart */
342 byteout(cs->hw.elsa.timer, 0);
343 cs->hw.elsa.counter++;
344 }
345 }
346#if ARCOFI_USE
347 if (cs->hw.elsa.MFlag) {
348 val = serial_inp(cs, UART_MCR);
349 val ^= 0x8;
350 serial_outp(cs, UART_MCR, val);
351 val = serial_inp(cs, UART_MCR);
352 val ^= 0x8;
353 serial_outp(cs, UART_MCR, val);
354 }
355#endif
356 if (cs->hw.elsa.trig)
357 byteout(cs->hw.elsa.trig, 0x00);
358 writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
359 writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0);
360 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0);
361 spin_unlock_irqrestore(&cs->lock, flags);
362 return IRQ_HANDLED;
363}
364
365static irqreturn_t
366elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
367{
368 struct IsdnCardState *cs = dev_id;
369 u_long flags;
370 u_char ista,val;
371 int icnt=5;
372
373 spin_lock_irqsave(&cs->lock, flags);
374 if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {
375 val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
376 if (!(val & ELSA_PCI_IRQ_MASK)) {
377 spin_unlock_irqrestore(&cs->lock, flags);
378 return IRQ_NONE;
379 }
380 }
381#if ARCOFI_USE
382 if (cs->hw.elsa.MFlag) {
383 val = serial_inp(cs, UART_IIR);
384 if (!(val & UART_IIR_NO_INT)) {
385 debugl1(cs,"IIR %02x", val);
386 rs_interrupt_elsa(intno, cs);
387 }
388 }
389#endif
390 ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
391Start_IPAC:
392 if (cs->debug & L1_DEB_IPAC)
393 debugl1(cs, "IPAC ISTA %02X", ista);
394 if (ista & 0x0f) {
395 val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
396 if (ista & 0x01)
397 val |= 0x01;
398 if (ista & 0x04)
399 val |= 0x02;
400 if (ista & 0x08)
401 val |= 0x04;
402 if (val)
403 hscx_int_main(cs, val);
404 }
405 if (ista & 0x20) {
406 val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80);
407 if (val) {
408 isac_interrupt(cs, val);
409 }
410 }
411 if (ista & 0x10) {
412 val = 0x01;
413 isac_interrupt(cs, val);
414 }
415 ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
416 if ((ista & 0x3f) && icnt) {
417 icnt--;
418 goto Start_IPAC;
419 }
420 if (!icnt)
421 printk(KERN_WARNING "ELSA IRQ LOOP\n");
422 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF);
423 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0);
424 spin_unlock_irqrestore(&cs->lock, flags);
425 return IRQ_HANDLED;
426}
427
428void
429release_io_elsa(struct IsdnCardState *cs)
430{
431 int bytecnt = 8;
432
433 del_timer(&cs->hw.elsa.tl);
434#if ARCOFI_USE
435 clear_arcofi(cs);
436#endif
437 if (cs->hw.elsa.ctrl)
438 byteout(cs->hw.elsa.ctrl, 0); /* LEDs Out */
439 if (cs->subtyp == ELSA_QS1000PCI) {
440 byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */
441 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
442 bytecnt = 2;
443 release_region(cs->hw.elsa.cfg, 0x80);
444 }
445 if (cs->subtyp == ELSA_QS3000PCI) {
446 byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */
447 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
448 release_region(cs->hw.elsa.cfg, 0x80);
449 }
450 if (cs->subtyp == ELSA_PCMCIA_IPAC) {
451 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
452 }
453 if ((cs->subtyp == ELSA_PCFPRO) ||
454 (cs->subtyp == ELSA_QS3000) ||
455 (cs->subtyp == ELSA_PCF) ||
456 (cs->subtyp == ELSA_QS3000PCI)) {
457 bytecnt = 16;
458#if ARCOFI_USE
459 release_modem(cs);
460#endif
461 }
462 if (cs->hw.elsa.base)
463 release_region(cs->hw.elsa.base, bytecnt);
464}
465
466static void
467reset_elsa(struct IsdnCardState *cs)
468{
469 if (cs->hw.elsa.timer) {
470 /* Wait 1 Timer */
471 byteout(cs->hw.elsa.timer, 0);
472 while (TimerRun(cs));
473 cs->hw.elsa.ctrl_reg |= 0x50;
474 cs->hw.elsa.ctrl_reg &= ~ELSA_ISDN_RESET; /* Reset On */
475 byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
476 /* Wait 1 Timer */
477 byteout(cs->hw.elsa.timer, 0);
478 while (TimerRun(cs));
479 cs->hw.elsa.ctrl_reg |= ELSA_ISDN_RESET; /* Reset Off */
480 byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
481 /* Wait 1 Timer */
482 byteout(cs->hw.elsa.timer, 0);
483 while (TimerRun(cs));
484 if (cs->hw.elsa.trig)
485 byteout(cs->hw.elsa.trig, 0xff);
486 }
487 if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
488 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
489 mdelay(10);
490 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00);
491 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
492 mdelay(10);
493 if (cs->subtyp != ELSA_PCMCIA_IPAC) {
494 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
495 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
496 } else {
497 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10);
498 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4);
499 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8);
500 }
501 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
502 if (cs->subtyp == ELSA_QS1000PCI)
503 byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
504 else if (cs->subtyp == ELSA_QS3000PCI)
505 byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */
506 }
507}
508
509#if ARCOFI_USE
510
511static void
512set_arcofi(struct IsdnCardState *cs, int bc) {
513 cs->dc.isac.arcofi_bc = bc;
514 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);
515 interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
516}
517
518static int
519check_arcofi(struct IsdnCardState *cs)
520{
521 int arcofi_present = 0;
522 char tmp[40];
523 char *t;
524 u_char *p;
525
526 if (!cs->dc.isac.mon_tx)
527 if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
528 if (cs->debug & L1_DEB_WARN)
529 debugl1(cs, "ISAC MON TX out of buffers!");
530 return(0);
531 }
532 cs->dc.isac.arcofi_bc = 0;
533 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
534 interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
535 if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
536 debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
537 p = cs->dc.isac.mon_rx;
538 t = tmp;
539 t += sprintf(tmp, "Arcofi data");
540 QuickHex(t, p, cs->dc.isac.mon_rxp);
541 debugl1(cs, tmp);
542 if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) {
543 switch(cs->dc.isac.mon_rx[1]) {
544 case 0x80:
545 debugl1(cs, "Arcofi 2160 detected");
546 arcofi_present = 1;
547 break;
548 case 0x82:
549 debugl1(cs, "Arcofi 2165 detected");
550 arcofi_present = 2;
551 break;
552 case 0x84:
553 debugl1(cs, "Arcofi 2163 detected");
554 arcofi_present = 3;
555 break;
556 default:
557 debugl1(cs, "unknown Arcofi response");
558 break;
559 }
560 } else
561 debugl1(cs, "undefined Monitor response");
562 cs->dc.isac.mon_rxp = 0;
563 } else if (cs->dc.isac.mon_tx) {
564 debugl1(cs, "Arcofi not detected");
565 }
566 if (arcofi_present) {
567 if (cs->subtyp==ELSA_QS1000) {
568 cs->subtyp = ELSA_QS3000;
569 printk(KERN_INFO
570 "Elsa: %s detected modem at 0x%lx\n",
571 Elsa_Types[cs->subtyp],
572 cs->hw.elsa.base+8);
573 release_region(cs->hw.elsa.base, 8);
574 if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) {
575 printk(KERN_WARNING
576 "HiSax: %s config port %lx-%lx already in use\n",
577 Elsa_Types[cs->subtyp],
578 cs->hw.elsa.base + 8,
579 cs->hw.elsa.base + 16);
580 }
581 } else if (cs->subtyp==ELSA_PCC16) {
582 cs->subtyp = ELSA_PCF;
583 printk(KERN_INFO
584 "Elsa: %s detected modem at 0x%lx\n",
585 Elsa_Types[cs->subtyp],
586 cs->hw.elsa.base+8);
587 release_region(cs->hw.elsa.base, 8);
588 if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) {
589 printk(KERN_WARNING
590 "HiSax: %s config port %lx-%lx already in use\n",
591 Elsa_Types[cs->subtyp],
592 cs->hw.elsa.base + 8,
593 cs->hw.elsa.base + 16);
594 }
595 } else
596 printk(KERN_INFO
597 "Elsa: %s detected modem at 0x%lx\n",
598 Elsa_Types[cs->subtyp],
599 cs->hw.elsa.base+8);
600 arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
601 interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
602 return(1);
603 }
604 return(0);
605}
606#endif /* ARCOFI_USE */
607
608static void
609elsa_led_handler(struct IsdnCardState *cs)
610{
611 int blink = 0;
612
613 if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC)
614 return;
615 del_timer(&cs->hw.elsa.tl);
616 if (cs->hw.elsa.status & ELSA_ASSIGN)
617 cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED;
618 else if (cs->hw.elsa.status & ELSA_BAD_PWR)
619 cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED;
620 else {
621 cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED;
622 blink = 250;
623 }
624 if (cs->hw.elsa.status & 0xf000)
625 cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED;
626 else if (cs->hw.elsa.status & 0x0f00) {
627 cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED;
628 blink = 500;
629 } else
630 cs->hw.elsa.ctrl_reg &= ~ELSA_LINE_LED;
631
632 if ((cs->subtyp == ELSA_QS1000PCI) ||
633 (cs->subtyp == ELSA_QS3000PCI)) {
634 u_char led = 0xff;
635 if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED)
636 led ^= ELSA_IPAC_LINE_LED;
637 if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED)
638 led ^= ELSA_IPAC_STAT_LED;
639 writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led);
640 } else
641 byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
642 if (blink) {
643 init_timer(&cs->hw.elsa.tl);
644 cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);
645 add_timer(&cs->hw.elsa.tl);
646 }
647}
648
649static int
650Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
651{
652 int ret = 0;
653 u_long flags;
654
655 switch (mt) {
656 case CARD_RESET:
657 spin_lock_irqsave(&cs->lock, flags);
658 reset_elsa(cs);
659 spin_unlock_irqrestore(&cs->lock, flags);
660 return(0);
661 case CARD_RELEASE:
662 release_io_elsa(cs);
663 return(0);
664 case CARD_INIT:
665 spin_lock_irqsave(&cs->lock, flags);
666 cs->debug |= L1_DEB_IPAC;
667 reset_elsa(cs);
668 inithscxisac(cs, 1);
669 if ((cs->subtyp == ELSA_QS1000) ||
670 (cs->subtyp == ELSA_QS3000))
671 {
672 byteout(cs->hw.elsa.timer, 0);
673 }
674 if (cs->hw.elsa.trig)
675 byteout(cs->hw.elsa.trig, 0xff);
676 inithscxisac(cs, 2);
677 spin_unlock_irqrestore(&cs->lock, flags);
678 return(0);
679 case CARD_TEST:
680 if ((cs->subtyp == ELSA_PCMCIA) ||
681 (cs->subtyp == ELSA_PCMCIA_IPAC) ||
682 (cs->subtyp == ELSA_QS1000PCI)) {
683 return(0);
684 } else if (cs->subtyp == ELSA_QS3000PCI) {
685 ret = 0;
686 } else {
687 spin_lock_irqsave(&cs->lock, flags);
688 cs->hw.elsa.counter = 0;
689 cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT;
690 cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
691 byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
692 byteout(cs->hw.elsa.timer, 0);
693 spin_unlock_irqrestore(&cs->lock, flags);
694 msleep(110);
695 spin_lock_irqsave(&cs->lock, flags);
696 cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
697 byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
698 cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
699 spin_unlock_irqrestore(&cs->lock, flags);
700 printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
701 cs->hw.elsa.counter);
702 if ((cs->hw.elsa.counter > 10) &&
703 (cs->hw.elsa.counter < 16)) {
704 printk(KERN_INFO "Elsa: timer and irq OK\n");
705 ret = 0;
706 } else {
707 printk(KERN_WARNING
708 "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
709 cs->hw.elsa.counter, cs->irq);
710 ret = 1;
711 }
712 }
713#if ARCOFI_USE
714 if (check_arcofi(cs)) {
715 init_modem(cs);
716 }
717#endif
718 elsa_led_handler(cs);
719 return(ret);
720 case (MDL_REMOVE | REQUEST):
721 cs->hw.elsa.status &= 0;
722 break;
723 case (MDL_ASSIGN | REQUEST):
724 cs->hw.elsa.status |= ELSA_ASSIGN;
725 break;
726 case MDL_INFO_SETUP:
727 if ((long) arg)
728 cs->hw.elsa.status |= 0x0200;
729 else
730 cs->hw.elsa.status |= 0x0100;
731 break;
732 case MDL_INFO_CONN:
733 if ((long) arg)
734 cs->hw.elsa.status |= 0x2000;
735 else
736 cs->hw.elsa.status |= 0x1000;
737 break;
738 case MDL_INFO_REL:
739 if ((long) arg) {
740 cs->hw.elsa.status &= ~0x2000;
741 cs->hw.elsa.status &= ~0x0200;
742 } else {
743 cs->hw.elsa.status &= ~0x1000;
744 cs->hw.elsa.status &= ~0x0100;
745 }
746 break;
747#if ARCOFI_USE
748 case CARD_AUX_IND:
749 if (cs->hw.elsa.MFlag) {
750 int len;
751 u_char *msg;
752
753 if (!arg)
754 return(0);
755 msg = arg;
756 len = *msg;
757 msg++;
758 modem_write_cmd(cs, msg, len);
759 }
760 break;
761#endif
762 }
763 if (cs->typ == ISDN_CTYPE_ELSA) {
764 int pwr = bytein(cs->hw.elsa.ale);
765 if (pwr & 0x08)
766 cs->hw.elsa.status |= ELSA_BAD_PWR;
767 else
768 cs->hw.elsa.status &= ~ELSA_BAD_PWR;
769 }
770 elsa_led_handler(cs);
771 return(ret);
772}
773
774static unsigned char
775probe_elsa_adr(unsigned int adr, int typ)
776{
777 int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0,
778 pc_2 = 0, pfp_1 = 0, pfp_2 = 0;
779
780 /* In case of the elsa pcmcia card, this region is in use,
781 reserved for us by the card manager. So we do not check it
782 here, it would fail. */
783 if (typ != ISDN_CTYPE_ELSA_PCMCIA) {
784 if (request_region(adr, 8, "elsa card")) {
785 release_region(adr, 8);
786 } else {
787 printk(KERN_WARNING
788 "Elsa: Probing Port 0x%x: already in use\n", adr);
789 return (0);
790 }
791 }
792 for (i = 0; i < 16; i++) {
793 in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */
794 in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */
795 p16_1 += 0x04 & in1;
796 p16_2 += 0x04 & in2;
797 p8_1 += 0x02 & in1;
798 p8_2 += 0x02 & in2;
799 pc_1 += 0x01 & in1;
800 pc_2 += 0x01 & in2;
801 pfp_1 += 0x40 & in1;
802 pfp_2 += 0x40 & in2;
803 }
804 printk(KERN_INFO "Elsa: Probing IO 0x%x", adr);
805 if (65 == ++p16_1 * ++p16_2) {
806 printk(" PCC-16/PCF found\n");
807 return (ELSA_PCC16);
808 } else if (1025 == ++pfp_1 * ++pfp_2) {
809 printk(" PCF-Pro found\n");
810 return (ELSA_PCFPRO);
811 } else if (33 == ++p8_1 * ++p8_2) {
812 printk(" PCC8 found\n");
813 return (ELSA_PCC8);
814 } else if (17 == ++pc_1 * ++pc_2) {
815 printk(" PC found\n");
816 return (ELSA_PC);
817 } else {
818 printk(" failed\n");
819 return (0);
820 }
821}
822
823static unsigned int
824probe_elsa(struct IsdnCardState *cs)
825{
826 int i;
827 unsigned int CARD_portlist[] =
828 {0x160, 0x170, 0x260, 0x360, 0};
829
830 for (i = 0; CARD_portlist[i]; i++) {
831 if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ)))
832 break;
833 }
834 return (CARD_portlist[i]);
835}
836
837static struct pci_dev *dev_qs1000 __devinitdata = NULL;
838static struct pci_dev *dev_qs3000 __devinitdata = NULL;
839
840#ifdef __ISAPNP__
841static struct isapnp_device_id elsa_ids[] __devinitdata = {
842 { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
843 ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
844 (unsigned long) "Elsa QS1000" },
845 { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
846 ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
847 (unsigned long) "Elsa QS3000" },
848 { 0, }
849};
850
851static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0];
852static struct pnp_card *pnp_c __devinitdata = NULL;
853#endif
854
855int __devinit
856setup_elsa(struct IsdnCard *card)
857{
858 int bytecnt;
859 u_char val;
860 struct IsdnCardState *cs = card->cs;
861 char tmp[64];
862
863 strcpy(tmp, Elsa_revision);
864 printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
865 cs->hw.elsa.ctrl_reg = 0;
866 cs->hw.elsa.status = 0;
867 cs->hw.elsa.MFlag = 0;
868 cs->subtyp = 0;
869 if (cs->typ == ISDN_CTYPE_ELSA) {
870 cs->hw.elsa.base = card->para[0];
871 printk(KERN_INFO "Elsa: Microlink IO probing\n");
872 if (cs->hw.elsa.base) {
873 if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
874 cs->typ))) {
875 printk(KERN_WARNING
876 "Elsa: no Elsa Microlink at %#lx\n",
877 cs->hw.elsa.base);
878 return (0);
879 }
880 } else
881 cs->hw.elsa.base = probe_elsa(cs);
882 if (cs->hw.elsa.base) {
883 cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
884 cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
885 cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
886 cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
887 cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
888 cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
889 cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
890 cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
891 val = bytein(cs->hw.elsa.cfg);
892 if (cs->subtyp == ELSA_PC) {
893 const u_char CARD_IrqTab[8] =
894 {7, 3, 5, 9, 0, 0, 0, 0};
895 cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
896 } else if (cs->subtyp == ELSA_PCC8) {
897 const u_char CARD_IrqTab[8] =
898 {7, 3, 5, 9, 0, 0, 0, 0};
899 cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
900 } else {
901 const u_char CARD_IrqTab[8] =
902 {15, 10, 15, 3, 11, 5, 11, 9};
903 cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
904 }
905 val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
906 if (val < 3)
907 val |= 8;
908 val += 'A' - 3;
909 if (val == 'B' || val == 'C')
910 val ^= 1;
911 if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
912 val = 'C';
913 printk(KERN_INFO
914 "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
915 Elsa_Types[cs->subtyp],
916 cs->hw.elsa.base,
917 val, cs->irq);
918 val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
919 if (val) {
920 printk(KERN_WARNING
921 "Elsa: Microlink S0 bus power bad\n");
922 cs->hw.elsa.status |= ELSA_BAD_PWR;
923 }
924 } else {
925 printk(KERN_WARNING
926 "No Elsa Microlink found\n");
927 return (0);
928 }
929 } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
930#ifdef __ISAPNP__
931 if (!card->para[1] && isapnp_present()) {
932 struct pnp_dev *pnp_d;
933 while(ipid->card_vendor) {
934 if ((pnp_c = pnp_find_card(ipid->card_vendor,
935 ipid->card_device, pnp_c))) {
936 pnp_d = NULL;
937 if ((pnp_d = pnp_find_dev(pnp_c,
938 ipid->vendor, ipid->function, pnp_d))) {
939 int err;
940
941 printk(KERN_INFO "HiSax: %s detected\n",
942 (char *)ipid->driver_data);
943 pnp_disable_dev(pnp_d);
944 err = pnp_activate_dev(pnp_d);
945 if (err<0) {
946 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
947 __FUNCTION__, err);
948 return(0);
949 }
950 card->para[1] = pnp_port_start(pnp_d, 0);
951 card->para[0] = pnp_irq(pnp_d, 0);
952
953 if (!card->para[0] || !card->para[1]) {
954 printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
955 card->para[0], card->para[1]);
956 pnp_disable_dev(pnp_d);
957 return(0);
958 }
959 if (ipid->function == ISAPNP_FUNCTION(0x133))
960 cs->subtyp = ELSA_QS1000;
961 else
962 cs->subtyp = ELSA_QS3000;
963 break;
964 } else {
965 printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
966 return(0);
967 }
968 }
969 ipid++;
970 pnp_c=NULL;
971 }
972 if (!ipid->card_vendor) {
973 printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
974 return(0);
975 }
976 }
977#endif
978 if (card->para[1] && card->para[0]) {
979 cs->hw.elsa.base = card->para[1];
980 cs->irq = card->para[0];
981 if (!cs->subtyp)
982 cs->subtyp = ELSA_QS1000;
983 } else {
984 printk(KERN_ERR "Elsa PnP: no parameter\n");
985 }
986 cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
987 cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
988 cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
989 cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
990 cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
991 cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
992 cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
993 printk(KERN_INFO
994 "Elsa: %s defined at %#lx IRQ %d\n",
995 Elsa_Types[cs->subtyp],
996 cs->hw.elsa.base,
997 cs->irq);
998 } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
999 cs->hw.elsa.base = card->para[1];
1000 cs->irq = card->para[0];
1001 val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID);
1002 if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
1003 cs->subtyp = ELSA_PCMCIA_IPAC;
1004 cs->hw.elsa.ale = cs->hw.elsa.base + 0;
1005 cs->hw.elsa.isac = cs->hw.elsa.base + 2;
1006 cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
1007 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
1008 } else {
1009 cs->subtyp = ELSA_PCMCIA;
1010 cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
1011 cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
1012 cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
1013 }
1014 cs->hw.elsa.timer = 0;
1015 cs->hw.elsa.trig = 0;
1016 cs->hw.elsa.ctrl = 0;
1017 cs->irq_flags |= SA_SHIRQ;
1018 printk(KERN_INFO
1019 "Elsa: %s defined at %#lx IRQ %d\n",
1020 Elsa_Types[cs->subtyp],
1021 cs->hw.elsa.base,
1022 cs->irq);
1023 } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
1024#ifdef CONFIG_PCI
1025 cs->subtyp = 0;
1026 if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
1027 PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
1028 if (pci_enable_device(dev_qs1000))
1029 return(0);
1030 cs->subtyp = ELSA_QS1000PCI;
1031 cs->irq = dev_qs1000->irq;
1032 cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
1033 cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
1034 } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
1035 PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
1036 if (pci_enable_device(dev_qs3000))
1037 return(0);
1038 cs->subtyp = ELSA_QS3000PCI;
1039 cs->irq = dev_qs3000->irq;
1040 cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
1041 cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
1042 } else {
1043 printk(KERN_WARNING "Elsa: No PCI card found\n");
1044 return(0);
1045 }
1046 if (!cs->irq) {
1047 printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
1048 return(0);
1049 }
1050
1051 if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
1052 printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
1053 return(0);
1054 }
1055 if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
1056 printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
1057 printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
1058 printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
1059 }
1060 cs->hw.elsa.ale = cs->hw.elsa.base;
1061 cs->hw.elsa.isac = cs->hw.elsa.base +1;
1062 cs->hw.elsa.hscx = cs->hw.elsa.base +1;
1063 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
1064 cs->hw.elsa.timer = 0;
1065 cs->hw.elsa.trig = 0;
1066 cs->irq_flags |= SA_SHIRQ;
1067 printk(KERN_INFO
1068 "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
1069 Elsa_Types[cs->subtyp],
1070 cs->hw.elsa.base,
1071 cs->hw.elsa.cfg,
1072 cs->irq);
1073#else
1074 printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n");
1075 printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n");
1076 return (0);
1077#endif /* CONFIG_PCI */
1078 } else
1079 return (0);
1080
1081 switch (cs->subtyp) {
1082 case ELSA_PC:
1083 case ELSA_PCC8:
1084 case ELSA_PCC16:
1085 case ELSA_QS1000:
1086 case ELSA_PCMCIA:
1087 case ELSA_PCMCIA_IPAC:
1088 bytecnt = 8;
1089 break;
1090 case ELSA_PCFPRO:
1091 case ELSA_PCF:
1092 case ELSA_QS3000:
1093 case ELSA_QS3000PCI:
1094 bytecnt = 16;
1095 break;
1096 case ELSA_QS1000PCI:
1097 bytecnt = 2;
1098 break;
1099 default:
1100 printk(KERN_WARNING
1101 "Unknown ELSA subtype %d\n", cs->subtyp);
1102 return (0);
1103 }
1104 /* In case of the elsa pcmcia card, this region is in use,
1105 reserved for us by the card manager. So we do not check it
1106 here, it would fail. */
1107 if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) {
1108 printk(KERN_WARNING
1109 "HiSax: %s config port %#lx-%#lx already in use\n",
1110 CardType[card->typ],
1111 cs->hw.elsa.base,
1112 cs->hw.elsa.base + bytecnt);
1113 return (0);
1114 }
1115 if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
1116 if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) {
1117 printk(KERN_WARNING
1118 "HiSax: %s pci port %x-%x already in use\n",
1119 CardType[card->typ],
1120 cs->hw.elsa.cfg,
1121 cs->hw.elsa.cfg + 0x80);
1122 release_region(cs->hw.elsa.base, bytecnt);
1123 return (0);
1124 }
1125 }
1126#if ARCOFI_USE
1127 init_arcofi(cs);
1128#endif
1129 setup_isac(cs);
1130 cs->hw.elsa.tl.function = (void *) elsa_led_handler;
1131 cs->hw.elsa.tl.data = (long) cs;
1132 init_timer(&cs->hw.elsa.tl);
1133 /* Teste Timer */
1134 if (cs->hw.elsa.timer) {
1135 byteout(cs->hw.elsa.trig, 0xff);
1136 byteout(cs->hw.elsa.timer, 0);
1137 if (!TimerRun(cs)) {
1138 byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */
1139 if (!TimerRun(cs)) {
1140 printk(KERN_WARNING
1141 "Elsa: timer do not start\n");
1142 release_io_elsa(cs);
1143 return (0);
1144 }
1145 }
1146 HZDELAY((HZ/100) + 1); /* wait >=10 ms */
1147 if (TimerRun(cs)) {
1148 printk(KERN_WARNING "Elsa: timer do not run down\n");
1149 release_io_elsa(cs);
1150 return (0);
1151 }
1152 printk(KERN_INFO "Elsa: timer OK; resetting card\n");
1153 }
1154 cs->BC_Read_Reg = &ReadHSCX;
1155 cs->BC_Write_Reg = &WriteHSCX;
1156 cs->BC_Send_Data = &hscx_fill_fifo;
1157 cs->cardmsg = &Elsa_card_msg;
1158 if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
1159 cs->readisac = &ReadISAC_IPAC;
1160 cs->writeisac = &WriteISAC_IPAC;
1161 cs->readisacfifo = &ReadISACfifo_IPAC;
1162 cs->writeisacfifo = &WriteISACfifo_IPAC;
1163 cs->irq_func = &elsa_interrupt_ipac;
1164 val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID);
1165 printk(KERN_INFO "Elsa: IPAC version %x\n", val);
1166 } else {
1167 cs->readisac = &ReadISAC;
1168 cs->writeisac = &WriteISAC;
1169 cs->readisacfifo = &ReadISACfifo;
1170 cs->writeisacfifo = &WriteISACfifo;
1171 cs->irq_func = &elsa_interrupt;
1172 ISACVersion(cs, "Elsa:");
1173 if (HscxVersion(cs, "Elsa:")) {
1174 printk(KERN_WARNING
1175 "Elsa: wrong HSCX versions check IO address\n");
1176 release_io_elsa(cs);
1177 return (0);
1178 }
1179 }
1180 if (cs->subtyp == ELSA_PC) {
1181 val = readitac(cs, ITAC_SYS);
1182 printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
1183 writeitac(cs, ITAC_ISEN, 0);
1184 writeitac(cs, ITAC_RFIE, 0);
1185 writeitac(cs, ITAC_XFIE, 0);
1186 writeitac(cs, ITAC_SCIE, 0);
1187 writeitac(cs, ITAC_STIE, 0);
1188 }
1189 return (1);
1190}
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
new file mode 100644
index 00000000000..bfc013225f4
--- /dev/null
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -0,0 +1,532 @@
1/*======================================================================
2
3 An elsa_cs PCMCIA client driver
4
5 This driver is for the Elsa PCM ISDN Cards, i.e. the MicroLink
6
7
8 The contents of this file are subject to the Mozilla Public
9 License Version 1.1 (the "License"); you may not use this file
10 except in compliance with the License. You may obtain a copy of
11 the License at http://www.mozilla.org/MPL/
12
13 Software distributed under the License is distributed on an "AS
14 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 rights and limitations under the License.
17
18 The initial developer of the original code is David A. Hinds
19 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
20 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21
22 Modifications from dummy_cs.c are Copyright (C) 1999-2001 Klaus
23 Lichtenwalder <Lichtenwalder@ACM.org>. All Rights Reserved.
24
25 Alternatively, the contents of this file may be used under the
26 terms of the GNU General Public License version 2 (the "GPL"), in
27 which case the provisions of the GPL are applicable instead of the
28 above. If you wish to allow the use of your version of this file
29 only under the terms of the GPL and not to allow others to use
30 your version of this file under the MPL, indicate your decision
31 by deleting the provisions above and replace them with the notice
32 and other provisions required by the GPL. If you do not delete
33 the provisions above, a recipient may use your version of this
34 file under either the MPL or the GPL.
35
36======================================================================*/
37
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/init.h>
41#include <linux/sched.h>
42#include <linux/ptrace.h>
43#include <linux/slab.h>
44#include <linux/string.h>
45#include <linux/timer.h>
46#include <linux/ioport.h>
47#include <asm/io.h>
48#include <asm/system.h>
49
50#include <pcmcia/version.h>
51#include <pcmcia/cs_types.h>
52#include <pcmcia/cs.h>
53#include <pcmcia/cistpl.h>
54#include <pcmcia/cisreg.h>
55#include <pcmcia/ds.h>
56#include "hisax_cfg.h"
57
58MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards");
59MODULE_AUTHOR("Klaus Lichtenwalder");
60MODULE_LICENSE("Dual MPL/GPL");
61
62/*
63 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
64 you do not define PCMCIA_DEBUG at all, all the debug code will be
65 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
66 be present but disabled -- but it can then be enabled for specific
67 modules at load time with a 'pc_debug=#' option to insmod.
68*/
69
70#ifdef PCMCIA_DEBUG
71static int pc_debug = PCMCIA_DEBUG;
72module_param(pc_debug, int, 0);
73#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
74static char *version =
75"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)";
76#else
77#define DEBUG(n, args...)
78#endif
79
80/*====================================================================*/
81
82/* Parameters that can be set with 'insmod' */
83
84static int protocol = 2; /* EURO-ISDN Default */
85module_param(protocol, int, 0);
86
87/*====================================================================*/
88
89/*
90 The event() function is this driver's Card Services event handler.
91 It will be called by Card Services when an appropriate card status
92 event is received. The config() and release() entry points are
93 used to configure or release a socket, in response to card insertion
94 and ejection events. They are invoked from the elsa_cs event
95 handler.
96*/
97
98static void elsa_cs_config(dev_link_t *link);
99static void elsa_cs_release(dev_link_t *link);
100static int elsa_cs_event(event_t event, int priority,
101 event_callback_args_t *args);
102
103/*
104 The attach() and detach() entry points are used to create and destroy
105 "instances" of the driver, where each instance represents everything
106 needed to manage one actual PCMCIA card.
107*/
108
109static dev_link_t *elsa_cs_attach(void);
110static void elsa_cs_detach(dev_link_t *);
111
112/*
113 The dev_info variable is the "key" that is used to match up this
114 device driver with appropriate cards, through the card configuration
115 database.
116*/
117
118static dev_info_t dev_info = "elsa_cs";
119
120/*
121 A linked list of "instances" of the elsa_cs device. Each actual
122 PCMCIA card corresponds to one device instance, and is described
123 by one dev_link_t structure (defined in ds.h).
124
125 You may not want to use a linked list for this -- for example, the
126 memory card driver uses an array of dev_link_t pointers, where minor
127 device numbers are used to derive the corresponding array index.
128*/
129
130static dev_link_t *dev_list = NULL;
131
132/*
133 A dev_link_t structure has fields for most things that are needed
134 to keep track of a socket, but there will usually be some device
135 specific information that also needs to be kept track of. The
136 'priv' pointer in a dev_link_t structure can be used to point to
137 a device-specific private data structure, like this.
138
139 To simplify the data structure handling, we actually include the
140 dev_link_t structure in the device's private data structure.
141
142 A driver needs to provide a dev_node_t structure for each device
143 on a card. In some cases, there is only one device per card (for
144 example, ethernet cards, modems). In other cases, there may be
145 many actual or logical devices (SCSI adapters, memory cards with
146 multiple partitions). The dev_node_t structures need to be kept
147 in a linked list starting at the 'dev' field of a dev_link_t
148 structure. We allocate them in the card's private data structure,
149 because they generally shouldn't be allocated dynamically.
150 In this case, we also provide a flag to indicate if a device is
151 "stopped" due to a power management event, or card ejection. The
152 device IO routines can use a flag like this to throttle IO to a
153 card that is not ready to accept it.
154*/
155
156typedef struct local_info_t {
157 dev_link_t link;
158 dev_node_t node;
159 int busy;
160 int cardnr;
161} local_info_t;
162
163/*======================================================================
164
165 elsa_cs_attach() creates an "instance" of the driver, allocatingx
166 local data structures for one device. The device is registered
167 with Card Services.
168
169 The dev_link structure is initialized, but we don't actually
170 configure the card at this point -- we wait until we receive a
171 card insertion event.
172
173======================================================================*/
174
175static dev_link_t *elsa_cs_attach(void)
176{
177 client_reg_t client_reg;
178 dev_link_t *link;
179 local_info_t *local;
180 int ret;
181
182 DEBUG(0, "elsa_cs_attach()\n");
183
184 /* Allocate space for private device-specific data */
185 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
186 if (!local) return NULL;
187 memset(local, 0, sizeof(local_info_t));
188 local->cardnr = -1;
189 link = &local->link; link->priv = local;
190
191 /* Interrupt setup */
192 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
193 link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID;
194 link->irq.Handler = NULL;
195
196 /*
197 General socket configuration defaults can go here. In this
198 client, we assume very little, and rely on the CIS for almost
199 everything. In most clients, many details (i.e., number, sizes,
200 and attributes of IO windows) are fixed by the nature of the
201 device, and can be hard-wired here.
202 */
203 link->io.NumPorts1 = 8;
204 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
205 link->io.IOAddrLines = 3;
206
207 link->conf.Attributes = CONF_ENABLE_IRQ;
208 link->conf.Vcc = 50;
209 link->conf.IntType = INT_MEMORY_AND_IO;
210
211 /* Register with Card Services */
212 link->next = dev_list;
213 dev_list = link;
214 client_reg.dev_info = &dev_info;
215 client_reg.EventMask =
216 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
217 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
218 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
219 client_reg.event_handler = &elsa_cs_event;
220 client_reg.Version = 0x0210;
221 client_reg.event_callback_args.client_data = link;
222 ret = pcmcia_register_client(&link->handle, &client_reg);
223 if (ret != CS_SUCCESS) {
224 cs_error(link->handle, RegisterClient, ret);
225 elsa_cs_detach(link);
226 return NULL;
227 }
228
229 return link;
230} /* elsa_cs_attach */
231
232/*======================================================================
233
234 This deletes a driver "instance". The device is de-registered
235 with Card Services. If it has been released, all local data
236 structures are freed. Otherwise, the structures will be freed
237 when the device is released.
238
239======================================================================*/
240
241static void elsa_cs_detach(dev_link_t *link)
242{
243 dev_link_t **linkp;
244 local_info_t *info = link->priv;
245 int ret;
246
247 DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
248
249 /* Locate device structure */
250 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
251 if (*linkp == link) break;
252 if (*linkp == NULL)
253 return;
254
255 if (link->state & DEV_CONFIG)
256 elsa_cs_release(link);
257
258 /* Break the link with Card Services */
259 if (link->handle) {
260 ret = pcmcia_deregister_client(link->handle);
261 if (ret != CS_SUCCESS)
262 cs_error(link->handle, DeregisterClient, ret);
263 }
264
265 /* Unlink device structure and free it */
266 *linkp = link->next;
267 kfree(info);
268
269} /* elsa_cs_detach */
270
271/*======================================================================
272
273 elsa_cs_config() is scheduled to run after a CARD_INSERTION event
274 is received, to configure the PCMCIA socket, and to make the
275 device available to the system.
276
277======================================================================*/
278static int get_tuple(client_handle_t handle, tuple_t *tuple,
279 cisparse_t *parse)
280{
281 int i = pcmcia_get_tuple_data(handle, tuple);
282 if (i != CS_SUCCESS) return i;
283 return pcmcia_parse_tuple(handle, tuple, parse);
284}
285
286static int first_tuple(client_handle_t handle, tuple_t *tuple,
287 cisparse_t *parse)
288{
289 int i = pcmcia_get_first_tuple(handle, tuple);
290 if (i != CS_SUCCESS) return i;
291 return get_tuple(handle, tuple, parse);
292}
293
294static int next_tuple(client_handle_t handle, tuple_t *tuple,
295 cisparse_t *parse)
296{
297 int i = pcmcia_get_next_tuple(handle, tuple);
298 if (i != CS_SUCCESS) return i;
299 return get_tuple(handle, tuple, parse);
300}
301
302static void elsa_cs_config(dev_link_t *link)
303{
304 client_handle_t handle;
305 tuple_t tuple;
306 cisparse_t parse;
307 local_info_t *dev;
308 int i, j, last_fn;
309 u_short buf[128];
310 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
311 IsdnCard_t icard;
312
313 DEBUG(0, "elsa_config(0x%p)\n", link);
314 handle = link->handle;
315 dev = link->priv;
316
317 /*
318 This reads the card's CONFIG tuple to find its configuration
319 registers.
320 */
321 tuple.DesiredTuple = CISTPL_CONFIG;
322 tuple.TupleData = (cisdata_t *)buf;
323 tuple.TupleDataMax = 255;
324 tuple.TupleOffset = 0;
325 tuple.Attributes = 0;
326 i = first_tuple(handle, &tuple, &parse);
327 if (i != CS_SUCCESS) {
328 last_fn = ParseTuple;
329 goto cs_failed;
330 }
331 link->conf.ConfigBase = parse.config.base;
332 link->conf.Present = parse.config.rmask[0];
333
334 /* Configure card */
335 link->state |= DEV_CONFIG;
336
337 tuple.TupleData = (cisdata_t *)buf;
338 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
339 tuple.Attributes = 0;
340 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
341 i = first_tuple(handle, &tuple, &parse);
342 while (i == CS_SUCCESS) {
343 if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
344 printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
345 link->conf.ConfigIndex = cf->index;
346 link->io.BasePort1 = cf->io.win[0].base;
347 i = pcmcia_request_io(link->handle, &link->io);
348 if (i == CS_SUCCESS) break;
349 } else {
350 printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
351 link->conf.ConfigIndex = cf->index;
352 for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
353 link->io.BasePort1 = j;
354 i = pcmcia_request_io(link->handle, &link->io);
355 if (i == CS_SUCCESS) break;
356 }
357 break;
358 }
359 i = next_tuple(handle, &tuple, &parse);
360 }
361
362 if (i != CS_SUCCESS) {
363 last_fn = RequestIO;
364 goto cs_failed;
365 }
366
367 i = pcmcia_request_irq(link->handle, &link->irq);
368 if (i != CS_SUCCESS) {
369 link->irq.AssignedIRQ = 0;
370 last_fn = RequestIRQ;
371 goto cs_failed;
372 }
373
374 i = pcmcia_request_configuration(link->handle, &link->conf);
375 if (i != CS_SUCCESS) {
376 last_fn = RequestConfiguration;
377 goto cs_failed;
378 }
379
380 /* At this point, the dev_node_t structure(s) should be
381 initialized and arranged in a linked list at link->dev. *//* */
382 sprintf(dev->node.dev_name, "elsa");
383 dev->node.major = dev->node.minor = 0x0;
384
385 link->dev = &dev->node;
386
387 /* Finally, report what we've done */
388 printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
389 dev->node.dev_name, link->conf.ConfigIndex,
390 link->conf.Vcc/10, link->conf.Vcc%10);
391 if (link->conf.Vpp1)
392 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
393 if (link->conf.Attributes & CONF_ENABLE_IRQ)
394 printk(", irq %d", link->irq.AssignedIRQ);
395 if (link->io.NumPorts1)
396 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
397 link->io.BasePort1+link->io.NumPorts1-1);
398 if (link->io.NumPorts2)
399 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
400 link->io.BasePort2+link->io.NumPorts2-1);
401 printk("\n");
402
403 link->state &= ~DEV_CONFIG_PENDING;
404
405 icard.para[0] = link->irq.AssignedIRQ;
406 icard.para[1] = link->io.BasePort1;
407 icard.protocol = protocol;
408 icard.typ = ISDN_CTYPE_ELSA_PCMCIA;
409
410 i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
411 if (i < 0) {
412 printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n",
413 i, link->io.BasePort1);
414 elsa_cs_release(link);
415 } else
416 ((local_info_t*)link->priv)->cardnr = i;
417
418 return;
419cs_failed:
420 cs_error(link->handle, last_fn, i);
421 elsa_cs_release(link);
422} /* elsa_cs_config */
423
424/*======================================================================
425
426 After a card is removed, elsa_cs_release() will unregister the net
427 device, and release the PCMCIA configuration. If the device is
428 still open, this will be postponed until it is closed.
429
430======================================================================*/
431
432static void elsa_cs_release(dev_link_t *link)
433{
434 local_info_t *local = link->priv;
435
436 DEBUG(0, "elsa_cs_release(0x%p)\n", link);
437
438 if (local) {
439 if (local->cardnr >= 0) {
440 /* no unregister function with hisax */
441 HiSax_closecard(local->cardnr);
442 }
443 }
444 /* Unlink the device chain */
445 link->dev = NULL;
446
447 /* Don't bother checking to see if these succeed or not */
448 if (link->win)
449 pcmcia_release_window(link->win);
450 pcmcia_release_configuration(link->handle);
451 pcmcia_release_io(link->handle, &link->io);
452 pcmcia_release_irq(link->handle, &link->irq);
453 link->state &= ~DEV_CONFIG;
454} /* elsa_cs_release */
455
456/*======================================================================
457
458 The card status event handler. Mostly, this schedules other
459 stuff to run after an event is received. A CARD_REMOVAL event
460 also sets some flags to discourage the net drivers from trying
461 to talk to the card any more.
462
463 When a CARD_REMOVAL event is received, we immediately set a flag
464 to block future accesses to this device. All the functions that
465 actually access the device should check this flag to make sure
466 the card is still present.
467
468======================================================================*/
469
470static int elsa_cs_event(event_t event, int priority,
471 event_callback_args_t *args)
472{
473 dev_link_t *link = args->client_data;
474 local_info_t *dev = link->priv;
475
476 DEBUG(1, "elsa_cs_event(%d)\n", event);
477
478 switch (event) {
479 case CS_EVENT_CARD_REMOVAL:
480 link->state &= ~DEV_PRESENT;
481 if (link->state & DEV_CONFIG) {
482 ((local_info_t*)link->priv)->busy = 1;
483 elsa_cs_release(link);
484 }
485 break;
486 case CS_EVENT_CARD_INSERTION:
487 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
488 elsa_cs_config(link);
489 break;
490 case CS_EVENT_PM_SUSPEND:
491 link->state |= DEV_SUSPEND;
492 /* Fall through... */
493 case CS_EVENT_RESET_PHYSICAL:
494 /* Mark the device as stopped, to block IO until later */
495 dev->busy = 1;
496 if (link->state & DEV_CONFIG)
497 pcmcia_release_configuration(link->handle);
498 break;
499 case CS_EVENT_PM_RESUME:
500 link->state &= ~DEV_SUSPEND;
501 /* Fall through... */
502 case CS_EVENT_CARD_RESET:
503 if (link->state & DEV_CONFIG)
504 pcmcia_request_configuration(link->handle, &link->conf);
505 dev->busy = 0;
506 break;
507 }
508 return 0;
509} /* elsa_cs_event */
510
511static struct pcmcia_driver elsa_cs_driver = {
512 .owner = THIS_MODULE,
513 .drv = {
514 .name = "elsa_cs",
515 },
516 .attach = elsa_cs_attach,
517 .detach = elsa_cs_detach,
518};
519
520static int __init init_elsa_cs(void)
521{
522 return pcmcia_register_driver(&elsa_cs_driver);
523}
524
525static void __exit exit_elsa_cs(void)
526{
527 pcmcia_unregister_driver(&elsa_cs_driver);
528 BUG_ON(dev_list != NULL);
529}
530
531module_init(init_elsa_cs);
532module_exit(exit_elsa_cs);
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
new file mode 100644
index 00000000000..689c8339569
--- /dev/null
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -0,0 +1,657 @@
1/* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $
2 *
3 * stuff for the serial modem on ELSA cards
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/serial.h>
12#include <linux/serial_reg.h>
13
14#define MAX_MODEM_BUF 256
15#define WAKEUP_CHARS (MAX_MODEM_BUF/2)
16#define RS_ISR_PASS_LIMIT 256
17#define BASE_BAUD ( 1843200 / 16 )
18
19//#define SERIAL_DEBUG_OPEN 1
20//#define SERIAL_DEBUG_INTR 1
21//#define SERIAL_DEBUG_FLOW 1
22#undef SERIAL_DEBUG_OPEN
23#undef SERIAL_DEBUG_INTR
24#undef SERIAL_DEBUG_FLOW
25#undef SERIAL_DEBUG_REG
26//#define SERIAL_DEBUG_REG 1
27
28#ifdef SERIAL_DEBUG_REG
29static u_char deb[32];
30const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"};
31const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"};
32#endif
33
34static char *MInit_1 = "AT&F&C1E0&D2\r\0";
35static char *MInit_2 = "ATL2M1S64=13\r\0";
36static char *MInit_3 = "AT+FCLASS=0\r\0";
37static char *MInit_4 = "ATV1S2=128X1\r\0";
38static char *MInit_5 = "AT\\V8\\N3\r\0";
39static char *MInit_6 = "ATL0M0&G0%E1\r\0";
40static char *MInit_7 = "AT%L1%M0%C3\r\0";
41
42static char *MInit_speed28800 = "AT%G0%B28800\r\0";
43
44static char *MInit_dialout = "ATs7=60 x1 d\r\0";
45static char *MInit_dialin = "ATs7=60 x1 a\r\0";
46
47
48static inline unsigned int serial_in(struct IsdnCardState *cs, int offset)
49{
50#ifdef SERIAL_DEBUG_REG
51 u_int val = inb(cs->hw.elsa.base + 8 + offset);
52 debugl1(cs,"in %s %02x",ModemIn[offset], val);
53 return(val);
54#else
55 return inb(cs->hw.elsa.base + 8 + offset);
56#endif
57}
58
59static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset)
60{
61#ifdef SERIAL_DEBUG_REG
62#ifdef CONFIG_SERIAL_NOPAUSE_IO
63 u_int val = inb(cs->hw.elsa.base + 8 + offset);
64 debugl1(cs,"inp %s %02x",ModemIn[offset], val);
65#else
66 u_int val = inb_p(cs->hw.elsa.base + 8 + offset);
67 debugl1(cs,"inP %s %02x",ModemIn[offset], val);
68#endif
69 return(val);
70#else
71#ifdef CONFIG_SERIAL_NOPAUSE_IO
72 return inb(cs->hw.elsa.base + 8 + offset);
73#else
74 return inb_p(cs->hw.elsa.base + 8 + offset);
75#endif
76#endif
77}
78
79static inline void serial_out(struct IsdnCardState *cs, int offset, int value)
80{
81#ifdef SERIAL_DEBUG_REG
82 debugl1(cs,"out %s %02x",ModemOut[offset], value);
83#endif
84 outb(value, cs->hw.elsa.base + 8 + offset);
85}
86
87static inline void serial_outp(struct IsdnCardState *cs, int offset,
88 int value)
89{
90#ifdef SERIAL_DEBUG_REG
91#ifdef CONFIG_SERIAL_NOPAUSE_IO
92 debugl1(cs,"outp %s %02x",ModemOut[offset], value);
93#else
94 debugl1(cs,"outP %s %02x",ModemOut[offset], value);
95#endif
96#endif
97#ifdef CONFIG_SERIAL_NOPAUSE_IO
98 outb(value, cs->hw.elsa.base + 8 + offset);
99#else
100 outb_p(value, cs->hw.elsa.base + 8 + offset);
101#endif
102}
103
104/*
105 * This routine is called to set the UART divisor registers to match
106 * the specified baud rate for a serial port.
107 */
108static void change_speed(struct IsdnCardState *cs, int baud)
109{
110 int quot = 0, baud_base;
111 unsigned cval, fcr = 0;
112 int bits;
113
114
115 /* byte size and parity */
116 cval = 0x03; bits = 10;
117 /* Determine divisor based on baud rate */
118 baud_base = BASE_BAUD;
119 quot = baud_base / baud;
120 /* If the quotient is ever zero, default to 9600 bps */
121 if (!quot)
122 quot = baud_base / 9600;
123
124 /* Set up FIFO's */
125 if ((baud_base / quot) < 2400)
126 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
127 else
128 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
129 serial_outp(cs, UART_FCR, fcr);
130 /* CTS flow control flag and modem status interrupts */
131 cs->hw.elsa.IER &= ~UART_IER_MSI;
132 cs->hw.elsa.IER |= UART_IER_MSI;
133 serial_outp(cs, UART_IER, cs->hw.elsa.IER);
134
135 debugl1(cs,"modem quot=0x%x", quot);
136 serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
137 serial_outp(cs, UART_DLL, quot & 0xff); /* LS of divisor */
138 serial_outp(cs, UART_DLM, quot >> 8); /* MS of divisor */
139 serial_outp(cs, UART_LCR, cval); /* reset DLAB */
140 serial_inp(cs, UART_RX);
141}
142
143static int mstartup(struct IsdnCardState *cs)
144{
145 int retval=0;
146
147 /*
148 * Clear the FIFO buffers and disable them
149 * (they will be reenabled in change_speed())
150 */
151 serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
152
153 /*
154 * At this point there's no way the LSR could still be 0xFF;
155 * if it is, then bail out, because there's likely no UART
156 * here.
157 */
158 if (serial_inp(cs, UART_LSR) == 0xff) {
159 retval = -ENODEV;
160 goto errout;
161 }
162
163 /*
164 * Clear the interrupt registers.
165 */
166 (void) serial_inp(cs, UART_RX);
167 (void) serial_inp(cs, UART_IIR);
168 (void) serial_inp(cs, UART_MSR);
169
170 /*
171 * Now, initialize the UART
172 */
173 serial_outp(cs, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
174
175 cs->hw.elsa.MCR = 0;
176 cs->hw.elsa.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
177 serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
178
179 /*
180 * Finally, enable interrupts
181 */
182 cs->hw.elsa.IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
183 serial_outp(cs, UART_IER, cs->hw.elsa.IER); /* enable interrupts */
184
185 /*
186 * And clear the interrupt registers again for luck.
187 */
188 (void)serial_inp(cs, UART_LSR);
189 (void)serial_inp(cs, UART_RX);
190 (void)serial_inp(cs, UART_IIR);
191 (void)serial_inp(cs, UART_MSR);
192
193 cs->hw.elsa.transcnt = cs->hw.elsa.transp = 0;
194 cs->hw.elsa.rcvcnt = cs->hw.elsa.rcvp =0;
195
196 /*
197 * and set the speed of the serial port
198 */
199 change_speed(cs, BASE_BAUD);
200 cs->hw.elsa.MFlag = 1;
201errout:
202 return retval;
203}
204
205/*
206 * This routine will shutdown a serial port; interrupts are disabled, and
207 * DTR is dropped if the hangup on close termio flag is on.
208 */
209static void mshutdown(struct IsdnCardState *cs)
210{
211
212#ifdef SERIAL_DEBUG_OPEN
213 printk(KERN_DEBUG"Shutting down serial ....");
214#endif
215
216 /*
217 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
218 * here so the queue might never be waken up
219 */
220
221 cs->hw.elsa.IER = 0;
222 serial_outp(cs, UART_IER, 0x00); /* disable all intrs */
223 cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
224
225 /* disable break condition */
226 serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
227
228 cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
229 serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
230
231 /* disable FIFO's */
232 serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
233 serial_inp(cs, UART_RX); /* read data port to reset things */
234
235#ifdef SERIAL_DEBUG_OPEN
236 printk(" done\n");
237#endif
238}
239
240inline int
241write_modem(struct BCState *bcs) {
242 int ret=0;
243 struct IsdnCardState *cs = bcs->cs;
244 int count, len, fp;
245
246 if (!bcs->tx_skb)
247 return 0;
248 if (bcs->tx_skb->len <= 0)
249 return 0;
250 len = bcs->tx_skb->len;
251 if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt)
252 len = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
253 fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
254 fp &= (MAX_MODEM_BUF -1);
255 count = len;
256 if (count > MAX_MODEM_BUF - fp) {
257 count = MAX_MODEM_BUF - fp;
258 memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count);
259 skb_pull(bcs->tx_skb, count);
260 cs->hw.elsa.transcnt += count;
261 ret = count;
262 count = len - count;
263 fp = 0;
264 }
265 memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count);
266 skb_pull(bcs->tx_skb, count);
267 cs->hw.elsa.transcnt += count;
268 ret += count;
269
270 if (cs->hw.elsa.transcnt &&
271 !(cs->hw.elsa.IER & UART_IER_THRI)) {
272 cs->hw.elsa.IER |= UART_IER_THRI;
273 serial_outp(cs, UART_IER, cs->hw.elsa.IER);
274 }
275 return(ret);
276}
277
278inline void
279modem_fill(struct BCState *bcs) {
280
281 if (bcs->tx_skb) {
282 if (bcs->tx_skb->len) {
283 write_modem(bcs);
284 return;
285 } else {
286 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
287 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
288 u_long flags;
289 spin_lock_irqsave(&bcs->aclock, flags);
290 bcs->ackcnt += bcs->hw.hscx.count;
291 spin_unlock_irqrestore(&bcs->aclock, flags);
292 schedule_event(bcs, B_ACKPENDING);
293 }
294 dev_kfree_skb_any(bcs->tx_skb);
295 bcs->tx_skb = NULL;
296 }
297 }
298 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
299 bcs->hw.hscx.count = 0;
300 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
301 write_modem(bcs);
302 } else {
303 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
304 schedule_event(bcs, B_XMTBUFREADY);
305 }
306}
307
308static inline void receive_chars(struct IsdnCardState *cs,
309 int *status)
310{
311 unsigned char ch;
312 struct sk_buff *skb;
313
314 do {
315 ch = serial_in(cs, UART_RX);
316 if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF)
317 break;
318 cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch;
319#ifdef SERIAL_DEBUG_INTR
320 printk("DR%02x:%02x...", ch, *status);
321#endif
322 if (*status & (UART_LSR_BI | UART_LSR_PE |
323 UART_LSR_FE | UART_LSR_OE)) {
324
325#ifdef SERIAL_DEBUG_INTR
326 printk("handling exept....");
327#endif
328 }
329 *status = serial_inp(cs, UART_LSR);
330 } while (*status & UART_LSR_DR);
331 if (cs->hw.elsa.MFlag == 2) {
332 if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt)))
333 printk(KERN_WARNING "ElsaSER: receive out of memory\n");
334 else {
335 memcpy(skb_put(skb, cs->hw.elsa.rcvcnt), cs->hw.elsa.rcvbuf,
336 cs->hw.elsa.rcvcnt);
337 skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
338 }
339 schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
340 } else {
341 char tmp[128];
342 char *t = tmp;
343
344 t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
345 QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
346 debugl1(cs, tmp);
347 }
348 cs->hw.elsa.rcvcnt = 0;
349}
350
351static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
352{
353 int count;
354
355 debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp,
356 cs->hw.elsa.transcnt);
357
358 if (cs->hw.elsa.transcnt <= 0) {
359 cs->hw.elsa.IER &= ~UART_IER_THRI;
360 serial_out(cs, UART_IER, cs->hw.elsa.IER);
361 return;
362 }
363 count = 16;
364 do {
365 serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
366 if (cs->hw.elsa.transp >= MAX_MODEM_BUF)
367 cs->hw.elsa.transp=0;
368 if (--cs->hw.elsa.transcnt <= 0)
369 break;
370 } while (--count > 0);
371 if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag==2))
372 modem_fill(cs->hw.elsa.bcs);
373
374#ifdef SERIAL_DEBUG_INTR
375 printk("THRE...");
376#endif
377 if (intr_done)
378 *intr_done = 0;
379 if (cs->hw.elsa.transcnt <= 0) {
380 cs->hw.elsa.IER &= ~UART_IER_THRI;
381 serial_outp(cs, UART_IER, cs->hw.elsa.IER);
382 }
383}
384
385
386static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
387{
388 int status, iir, msr;
389 int pass_counter = 0;
390
391#ifdef SERIAL_DEBUG_INTR
392 printk("rs_interrupt_single(%d)...", irq);
393#endif
394
395 do {
396 status = serial_inp(cs, UART_LSR);
397 debugl1(cs,"rs LSR %02x", status);
398#ifdef SERIAL_DEBUG_INTR
399 printk("status = %x...", status);
400#endif
401 if (status & UART_LSR_DR)
402 receive_chars(cs, &status);
403 if (status & UART_LSR_THRE)
404 transmit_chars(cs, NULL);
405 if (pass_counter++ > RS_ISR_PASS_LIMIT) {
406 printk("rs_single loop break.\n");
407 break;
408 }
409 iir = serial_inp(cs, UART_IIR);
410 debugl1(cs,"rs IIR %02x", iir);
411 if ((iir & 0xf) == 0) {
412 msr = serial_inp(cs, UART_MSR);
413 debugl1(cs,"rs MSR %02x", msr);
414 }
415 } while (!(iir & UART_IIR_NO_INT));
416#ifdef SERIAL_DEBUG_INTR
417 printk("end.\n");
418#endif
419}
420
421extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
422extern void modehscx(struct BCState *bcs, int mode, int bc);
423extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
424
425void
426close_elsastate(struct BCState *bcs)
427{
428 modehscx(bcs, 0, bcs->channel);
429 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
430 if (bcs->hw.hscx.rcvbuf) {
431 if (bcs->mode != L1_MODE_MODEM)
432 kfree(bcs->hw.hscx.rcvbuf);
433 bcs->hw.hscx.rcvbuf = NULL;
434 }
435 skb_queue_purge(&bcs->rqueue);
436 skb_queue_purge(&bcs->squeue);
437 if (bcs->tx_skb) {
438 dev_kfree_skb_any(bcs->tx_skb);
439 bcs->tx_skb = NULL;
440 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
441 }
442 }
443}
444
445void
446modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
447 int count, fp;
448 u_char *msg = buf;
449
450 if (!len)
451 return;
452 if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
453 return;
454 }
455 fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
456 fp &= (MAX_MODEM_BUF -1);
457 count = len;
458 if (count > MAX_MODEM_BUF - fp) {
459 count = MAX_MODEM_BUF - fp;
460 memcpy(cs->hw.elsa.transbuf + fp, msg, count);
461 cs->hw.elsa.transcnt += count;
462 msg += count;
463 count = len - count;
464 fp = 0;
465 }
466 memcpy(cs->hw.elsa.transbuf + fp, msg, count);
467 cs->hw.elsa.transcnt += count;
468 if (cs->hw.elsa.transcnt &&
469 !(cs->hw.elsa.IER & UART_IER_THRI)) {
470 cs->hw.elsa.IER |= UART_IER_THRI;
471 serial_outp(cs, UART_IER, cs->hw.elsa.IER);
472 }
473}
474
475void
476modem_set_init(struct IsdnCardState *cs) {
477 int timeout;
478
479#define RCV_DELAY 20000
480 modem_write_cmd(cs, MInit_1, strlen(MInit_1));
481 timeout = 1000;
482 while(timeout-- && cs->hw.elsa.transcnt)
483 udelay(1000);
484 debugl1(cs, "msi tout=%d", timeout);
485 udelay(RCV_DELAY);
486 modem_write_cmd(cs, MInit_2, strlen(MInit_2));
487 timeout = 1000;
488 while(timeout-- && cs->hw.elsa.transcnt)
489 udelay(1000);
490 debugl1(cs, "msi tout=%d", timeout);
491 udelay(RCV_DELAY);
492 modem_write_cmd(cs, MInit_3, strlen(MInit_3));
493 timeout = 1000;
494 while(timeout-- && cs->hw.elsa.transcnt)
495 udelay(1000);
496 debugl1(cs, "msi tout=%d", timeout);
497 udelay(RCV_DELAY);
498 modem_write_cmd(cs, MInit_4, strlen(MInit_4));
499 timeout = 1000;
500 while(timeout-- && cs->hw.elsa.transcnt)
501 udelay(1000);
502 debugl1(cs, "msi tout=%d", timeout);
503 udelay(RCV_DELAY );
504 modem_write_cmd(cs, MInit_5, strlen(MInit_5));
505 timeout = 1000;
506 while(timeout-- && cs->hw.elsa.transcnt)
507 udelay(1000);
508 debugl1(cs, "msi tout=%d", timeout);
509 udelay(RCV_DELAY);
510 modem_write_cmd(cs, MInit_6, strlen(MInit_6));
511 timeout = 1000;
512 while(timeout-- && cs->hw.elsa.transcnt)
513 udelay(1000);
514 debugl1(cs, "msi tout=%d", timeout);
515 udelay(RCV_DELAY);
516 modem_write_cmd(cs, MInit_7, strlen(MInit_7));
517 timeout = 1000;
518 while(timeout-- && cs->hw.elsa.transcnt)
519 udelay(1000);
520 debugl1(cs, "msi tout=%d", timeout);
521 udelay(RCV_DELAY);
522}
523
524void
525modem_set_dial(struct IsdnCardState *cs, int outgoing) {
526 int timeout;
527#define RCV_DELAY 20000
528
529 modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
530 timeout = 1000;
531 while(timeout-- && cs->hw.elsa.transcnt)
532 udelay(1000);
533 debugl1(cs, "msi tout=%d", timeout);
534 udelay(RCV_DELAY);
535 if (outgoing)
536 modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
537 else
538 modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
539 timeout = 1000;
540 while(timeout-- && cs->hw.elsa.transcnt)
541 udelay(1000);
542 debugl1(cs, "msi tout=%d", timeout);
543 udelay(RCV_DELAY);
544}
545
546void
547modem_l2l1(struct PStack *st, int pr, void *arg)
548{
549 struct BCState *bcs = st->l1.bcs;
550 struct sk_buff *skb = arg;
551 u_long flags;
552
553 if (pr == (PH_DATA | REQUEST)) {
554 spin_lock_irqsave(&bcs->cs->lock, flags);
555 if (bcs->tx_skb) {
556 skb_queue_tail(&bcs->squeue, skb);
557 } else {
558 bcs->tx_skb = skb;
559 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
560 bcs->hw.hscx.count = 0;
561 write_modem(bcs);
562 }
563 spin_unlock_irqrestore(&bcs->cs->lock, flags);
564 } else if (pr == (PH_ACTIVATE | REQUEST)) {
565 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
566 st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
567 set_arcofi(bcs->cs, st->l1.bc);
568 mstartup(bcs->cs);
569 modem_set_dial(bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
570 bcs->cs->hw.elsa.MFlag=2;
571 } else if (pr == (PH_DEACTIVATE | REQUEST)) {
572 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
573 bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
574 arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
575 interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait);
576 bcs->cs->hw.elsa.MFlag=1;
577 } else {
578 printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
579 }
580}
581
582int
583setstack_elsa(struct PStack *st, struct BCState *bcs)
584{
585
586 bcs->channel = st->l1.bc;
587 switch (st->l1.mode) {
588 case L1_MODE_HDLC:
589 case L1_MODE_TRANS:
590 if (open_hscxstate(st->l1.hardware, bcs))
591 return (-1);
592 st->l2.l2l1 = hscx_l2l1;
593 break;
594 case L1_MODE_MODEM:
595 bcs->mode = L1_MODE_MODEM;
596 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
597 bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
598 skb_queue_head_init(&bcs->rqueue);
599 skb_queue_head_init(&bcs->squeue);
600 }
601 bcs->tx_skb = NULL;
602 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
603 bcs->event = 0;
604 bcs->hw.hscx.rcvidx = 0;
605 bcs->tx_cnt = 0;
606 bcs->cs->hw.elsa.bcs = bcs;
607 st->l2.l2l1 = modem_l2l1;
608 break;
609 }
610 st->l1.bcs = bcs;
611 setstack_manager(st);
612 bcs->st = st;
613 setstack_l1_B(st);
614 return (0);
615}
616
617void
618init_modem(struct IsdnCardState *cs) {
619
620 cs->bcs[0].BC_SetStack = setstack_elsa;
621 cs->bcs[1].BC_SetStack = setstack_elsa;
622 cs->bcs[0].BC_Close = close_elsastate;
623 cs->bcs[1].BC_Close = close_elsastate;
624 if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
625 GFP_ATOMIC))) {
626 printk(KERN_WARNING
627 "Elsa: No modem mem hw.elsa.rcvbuf\n");
628 return;
629 }
630 if (!(cs->hw.elsa.transbuf = kmalloc(MAX_MODEM_BUF,
631 GFP_ATOMIC))) {
632 printk(KERN_WARNING
633 "Elsa: No modem mem hw.elsa.transbuf\n");
634 kfree(cs->hw.elsa.rcvbuf);
635 cs->hw.elsa.rcvbuf = NULL;
636 return;
637 }
638 if (mstartup(cs)) {
639 printk(KERN_WARNING "Elsa: problem startup modem\n");
640 }
641 modem_set_init(cs);
642}
643
644void
645release_modem(struct IsdnCardState *cs) {
646
647 cs->hw.elsa.MFlag = 0;
648 if (cs->hw.elsa.transbuf) {
649 if (cs->hw.elsa.rcvbuf) {
650 mshutdown(cs);
651 kfree(cs->hw.elsa.rcvbuf);
652 cs->hw.elsa.rcvbuf = NULL;
653 }
654 kfree(cs->hw.elsa.transbuf);
655 cs->hw.elsa.transbuf = NULL;
656 }
657}
diff --git a/drivers/isdn/hisax/enternow.h b/drivers/isdn/hisax/enternow.h
new file mode 100644
index 00000000000..ed2eec5874c
--- /dev/null
+++ b/drivers/isdn/hisax/enternow.h
@@ -0,0 +1,51 @@
1/* 2001/10/02
2 *
3 * enternow.h Header-file included by
4 * enternow_pci.c
5 *
6 * Author Christoph Ersfeld <info@formula-n.de>
7 * Formula-n Europe AG (www.formula-n.com)
8 * previously Gerdes AG
9 *
10 *
11 * This file is (c) under GNU PUBLIC LICENSE
12 */
13
14
15/* ***************************************************************************************** *
16 * ****************************** datatypes and macros ************************************* *
17 * ***************************************************************************************** */
18
19#define BYTE unsigned char
20#define WORD unsigned int
21#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256))
22#define LOBYTE(w) ((unsigned char)(w & 0x00ff))
23#define InByte(addr) inb(addr)
24#define OutByte(addr,val) outb(val,addr)
25
26
27
28/* ***************************************************************************************** *
29 * *********************************** card-specific *************************************** *
30 * ***************************************************************************************** */
31
32/* für PowerISDN PCI */
33#define TJ_AMD_IRQ 0x20
34#define TJ_LED1 0x40
35#define TJ_LED2 0x80
36
37
38/* Das Fenster zum AMD...
39 * Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
40 * den TigerJet i/o-Raum gemappt
41 * -> 0x01 des AMD bei hw.njet.base + 0C4 */
42#define TJ_AMD_PORT 0xC0
43
44
45
46/* ***************************************************************************************** *
47 * *************************************** Prototypen ************************************** *
48 * ***************************************************************************************** */
49
50BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset);
51void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value);
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
new file mode 100644
index 00000000000..1cc4d11e007
--- /dev/null
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -0,0 +1,399 @@
1/* enternow_pci.c,v 0.99 2001/10/02
2 *
3 * enternow_pci.c Card-specific routines for
4 * Formula-n enter:now ISDN PCI ab
5 * Gerdes AG Power ISDN PCI
6 * Woerltronic SA 16 PCI
7 * (based on HiSax driver by Karsten Keil)
8 *
9 * Author Christoph Ersfeld <info@formula-n.de>
10 * Formula-n Europe AG (www.formula-n.com)
11 * previously Gerdes AG
12 *
13 *
14 * This file is (c) under GNU PUBLIC LICENSE
15 *
16 * Notes:
17 * This driver interfaces to netjet.c which performs B-channel
18 * processing.
19 *
20 * Version 0.99 is the first release of this driver and there are
21 * certainly a few bugs.
22 * It isn't testet on linux 2.4 yet, so consider this code to be
23 * beta.
24 *
25 * Please don't report me any malfunction without sending
26 * (compressed) debug-logs.
27 * It would be nearly impossible to retrace it.
28 *
29 * Log D-channel-processing as follows:
30 *
31 * 1. Load hisax with card-specific parameters, this example ist for
32 * Formula-n enter:now ISDN PCI and compatible
33 * (f.e. Gerdes Power ISDN PCI)
34 *
35 * modprobe hisax type=41 protocol=2 id=gerdes
36 *
37 * if you chose an other value for id, you need to modify the
38 * code below, too.
39 *
40 * 2. set debug-level
41 *
42 * hisaxctrl gerdes 1 0x3ff
43 * hisaxctrl gerdes 11 0x4f
44 * cat /dev/isdnctrl >> ~/log &
45 *
46 * Please take also a look into /var/log/messages if there is
47 * anything importand concerning HISAX.
48 *
49 *
50 * Credits:
51 * Programming the driver for Formula-n enter:now ISDN PCI and
52 * necessary the driver for the used Amd 7930 D-channel-controller
53 * was spnsored by Formula-n Europe AG.
54 * Thanks to Karsten Keil and Petr Novak, who gave me support in
55 * Hisax-specific questions.
56 * I want so say special thanks to Carl-Friedrich Braun, who had to
57 * answer a lot of questions about generally ISDN and about handling
58 * of the Amd-Chip.
59 *
60 */
61
62
63#include <linux/config.h>
64#include "hisax.h"
65#include "isac.h"
66#include "isdnl1.h"
67#include "amd7930_fn.h"
68#include "enternow.h"
69#include <linux/interrupt.h>
70#include <linux/ppp_defs.h>
71#include <linux/pci.h>
72#include <linux/init.h>
73#include "netjet.h"
74
75
76
77const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
78
79
80/* *************************** I/O-Interface functions ************************************* */
81
82
83/* cs->readisac, macro rByteAMD */
84BYTE
85ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset)
86{
87 /* direktes Register */
88 if(offset < 8)
89 return (InByte(cs->hw.njet.isac + 4*offset));
90
91 /* indirektes Register */
92 else {
93 OutByte(cs->hw.njet.isac + 4*AMD_CR, offset);
94 return(InByte(cs->hw.njet.isac + 4*AMD_DR));
95 }
96}
97
98/* cs->writeisac, macro wByteAMD */
99void
100WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value)
101{
102 /* direktes Register */
103 if(offset < 8)
104 OutByte(cs->hw.njet.isac + 4*offset, value);
105
106 /* indirektes Register */
107 else {
108 OutByte(cs->hw.njet.isac + 4*AMD_CR, offset);
109 OutByte(cs->hw.njet.isac + 4*AMD_DR, value);
110 }
111}
112
113
114void
115enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) {
116 if (!val)
117 OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00);
118 else
119 OutByte(cs->hw.njet.base+NETJET_IRQMASK1, TJ_AMD_IRQ);
120}
121
122
123static BYTE dummyrr(struct IsdnCardState *cs, int chan, BYTE off)
124{
125 return(5);
126}
127
128static void dummywr(struct IsdnCardState *cs, int chan, BYTE off, BYTE value)
129{
130
131}
132
133
134/* ******************************************************************************** */
135
136
137static void
138reset_enpci(struct IsdnCardState *cs)
139{
140 if (cs->debug & L1_DEB_ISAC)
141 debugl1(cs, "enter:now PCI: reset");
142
143 /* Reset on, (also for AMD) */
144 cs->hw.njet.ctrl_reg = 0x07;
145 OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
146 mdelay(20);
147 /* Reset off */
148 cs->hw.njet.ctrl_reg = 0x30;
149 OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
150 /* 20ms delay */
151 mdelay(20);
152 cs->hw.njet.auxd = 0; // LED-status
153 cs->hw.njet.dmactrl = 0;
154 OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
155 OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
156 OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off
157}
158
159
160static int
161enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
162{
163 u_long flags;
164 BYTE *chan;
165
166 if (cs->debug & L1_DEB_ISAC)
167 debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt);
168
169 switch (mt) {
170 case CARD_RESET:
171 spin_lock_irqsave(&cs->lock, flags);
172 reset_enpci(cs);
173 Amd7930_init(cs);
174 spin_unlock_irqrestore(&cs->lock, flags);
175 break;
176 case CARD_RELEASE:
177 release_io_netjet(cs);
178 break;
179 case CARD_INIT:
180 reset_enpci(cs);
181 inittiger(cs);
182 /* irq must be on here */
183 Amd7930_init(cs);
184 break;
185 case CARD_TEST:
186 break;
187 case MDL_ASSIGN:
188 /* TEI assigned, LED1 on */
189 cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
190 OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
191 break;
192 case MDL_REMOVE:
193 /* TEI removed, LEDs off */
194 cs->hw.njet.auxd = 0;
195 OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
196 break;
197 case MDL_BC_ASSIGN:
198 /* activate B-channel */
199 chan = (BYTE *)arg;
200
201 if (cs->debug & L1_DEB_ISAC)
202 debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan);
203
204 cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN");
205 /* at least one b-channel in use, LED 2 on */
206 cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
207 OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
208 break;
209 case MDL_BC_RELEASE:
210 /* deactivate B-channel */
211 chan = (BYTE *)arg;
212
213 if (cs->debug & L1_DEB_ISAC)
214 debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan);
215
216 cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE");
217 /* no b-channel active -> LED2 off */
218 if (!(cs->dc.amd7930.lmr1 & 3)) {
219 cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
220 OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
221 }
222 break;
223 default:
224 break;
225
226 }
227 return(0);
228}
229
230static irqreturn_t
231enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
232{
233 struct IsdnCardState *cs = dev_id;
234 BYTE s0val, s1val, ir;
235 u_long flags;
236
237 spin_lock_irqsave(&cs->lock, flags);
238 s1val = InByte(cs->hw.njet.base + NETJET_IRQSTAT1);
239
240 /* AMD threw an interrupt */
241 if (!(s1val & TJ_AMD_IRQ)) {
242 /* read and clear interrupt-register */
243 ir = ReadByteAmd7930(cs, 0x00);
244 Amd7930_interrupt(cs, ir);
245 s1val = 1;
246 } else
247 s1val = 0;
248 s0val = InByte(cs->hw.njet.base + NETJET_IRQSTAT0);
249 if ((s0val | s1val)==0) { // shared IRQ
250 spin_unlock_irqrestore(&cs->lock, flags);
251 return IRQ_NONE;
252 }
253 if (s0val)
254 OutByte(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
255
256 /* DMA-Interrupt: B-channel-stuff */
257 /* set bits in sval to indicate which page is free */
258 if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
259 inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
260 /* the 2nd write page is free */
261 s0val = 0x08;
262 else /* the 1st write page is free */
263 s0val = 0x04;
264 if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
265 inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
266 /* the 2nd read page is free */
267 s0val = s0val | 0x02;
268 else /* the 1st read page is free */
269 s0val = s0val | 0x01;
270 if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */
271 {
272 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
273 spin_unlock_irqrestore(&cs->lock, flags);
274 return IRQ_HANDLED;
275 }
276 cs->hw.njet.irqstat0 = s0val;
277 if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
278 (cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
279 /* we have a read dma int */
280 read_tiger(cs);
281 if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) !=
282 (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
283 /* we have a write dma int */
284 write_tiger(cs);
285 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
286 }
287 spin_unlock_irqrestore(&cs->lock, flags);
288 return IRQ_HANDLED;
289}
290
291
292static struct pci_dev *dev_netjet __initdata = NULL;
293
294/* called by config.c */
295int __init
296setup_enternow_pci(struct IsdnCard *card)
297{
298 int bytecnt;
299 struct IsdnCardState *cs = card->cs;
300 char tmp[64];
301
302#ifdef CONFIG_PCI
303#ifdef __BIG_ENDIAN
304#error "not running on big endian machines now"
305#endif
306 strcpy(tmp, enternow_pci_rev);
307 printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
308 if (cs->typ != ISDN_CTYPE_ENTERNOW)
309 return(0);
310 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
311
312 for ( ;; )
313 {
314 if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
315 PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
316 if (pci_enable_device(dev_netjet))
317 return(0);
318 cs->irq = dev_netjet->irq;
319 if (!cs->irq) {
320 printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
321 return(0);
322 }
323 cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
324 if (!cs->hw.njet.base) {
325 printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
326 return(0);
327 }
328 /* checks Sub-Vendor ID because system crashes with Traverse-Card */
329 if ((dev_netjet->subsystem_vendor != 0x55) ||
330 (dev_netjet->subsystem_device != 0x02)) {
331 printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
332 printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
333 return(0);
334 }
335 } else {
336 printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
337 return(0);
338 }
339
340 cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
341 cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
342
343 /* Reset an */
344 cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff
345 OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
346 /* 20 ms Pause */
347 mdelay(20);
348
349 cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */
350 OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
351 mdelay(10);
352
353 cs->hw.njet.auxd = 0x00; // war 0xc0
354 cs->hw.njet.dmactrl = 0;
355
356 OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
357 OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
358 OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
359
360 break;
361 }
362#else
363
364 printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n");
365 printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n");
366 return (0);
367
368#endif /* CONFIG_PCI */
369
370 bytecnt = 256;
371
372 printk(KERN_INFO
373 "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
374 cs->hw.njet.base, cs->irq);
375 if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) {
376 printk(KERN_WARNING
377 "HiSax: %s config port %lx-%lx already in use\n",
378 CardType[card->typ],
379 cs->hw.njet.base,
380 cs->hw.njet.base + bytecnt);
381 return (0);
382 }
383 setup_Amd7930(cs);
384 cs->hw.njet.last_is0 = 0;
385 /* macro rByteAMD */
386 cs->readisac = &ReadByteAmd7930;
387 /* macro wByteAMD */
388 cs->writeisac = &WriteByteAmd7930;
389 cs->dc.amd7930.setIrqMask = &enpci_setIrqMask;
390
391 cs->BC_Read_Reg = &dummyrr;
392 cs->BC_Write_Reg = &dummywr;
393 cs->BC_Send_Data = &netjet_fill_dma;
394 cs->cardmsg = &enpci_card_msg;
395 cs->irq_func = &enpci_interrupt;
396 cs->irq_flags |= SA_SHIRQ;
397
398 return (1);
399}
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
new file mode 100644
index 00000000000..0d44a3f480a
--- /dev/null
+++ b/drivers/isdn/hisax/fsm.c
@@ -0,0 +1,163 @@
1/* $Id: fsm.c,v 1.14.6.4 2001/09/23 22:24:47 kai Exp $
2 *
3 * Finite state machine
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 * by Kai Germaschewski <kai.germaschewski@gmx.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 * Thanks to Jan den Ouden
13 * Fritz Elfert
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/init.h>
19#include "hisax.h"
20
21#define FSM_TIMER_DEBUG 0
22
23int
24FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
25{
26 int i;
27
28 fsm->jumpmatrix = (FSMFNPTR *)
29 kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
30 if (!fsm->jumpmatrix)
31 return -ENOMEM;
32
33 memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
34
35 for (i = 0; i < fncount; i++)
36 if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
37 printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
38 i,(long)fnlist[i].state,(long)fsm->state_count,
39 (long)fnlist[i].event,(long)fsm->event_count);
40 } else
41 fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
42 fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
43 return 0;
44}
45
46void
47FsmFree(struct Fsm *fsm)
48{
49 kfree((void *) fsm->jumpmatrix);
50}
51
52int
53FsmEvent(struct FsmInst *fi, int event, void *arg)
54{
55 FSMFNPTR r;
56
57 if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) {
58 printk(KERN_ERR "FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
59 (long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count);
60 return(1);
61 }
62 r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
63 if (r) {
64 if (fi->debug)
65 fi->printdebug(fi, "State %s Event %s",
66 fi->fsm->strState[fi->state],
67 fi->fsm->strEvent[event]);
68 r(fi, event, arg);
69 return (0);
70 } else {
71 if (fi->debug)
72 fi->printdebug(fi, "State %s Event %s no routine",
73 fi->fsm->strState[fi->state],
74 fi->fsm->strEvent[event]);
75 return (!0);
76 }
77}
78
79void
80FsmChangeState(struct FsmInst *fi, int newstate)
81{
82 fi->state = newstate;
83 if (fi->debug)
84 fi->printdebug(fi, "ChangeState %s",
85 fi->fsm->strState[newstate]);
86}
87
88static void
89FsmExpireTimer(struct FsmTimer *ft)
90{
91#if FSM_TIMER_DEBUG
92 if (ft->fi->debug)
93 ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
94#endif
95 FsmEvent(ft->fi, ft->event, ft->arg);
96}
97
98void
99FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
100{
101 ft->fi = fi;
102 ft->tl.function = (void *) FsmExpireTimer;
103 ft->tl.data = (long) ft;
104#if FSM_TIMER_DEBUG
105 if (ft->fi->debug)
106 ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
107#endif
108 init_timer(&ft->tl);
109}
110
111void
112FsmDelTimer(struct FsmTimer *ft, int where)
113{
114#if FSM_TIMER_DEBUG
115 if (ft->fi->debug)
116 ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
117#endif
118 del_timer(&ft->tl);
119}
120
121int
122FsmAddTimer(struct FsmTimer *ft,
123 int millisec, int event, void *arg, int where)
124{
125
126#if FSM_TIMER_DEBUG
127 if (ft->fi->debug)
128 ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
129 (long) ft, millisec, where);
130#endif
131
132 if (timer_pending(&ft->tl)) {
133 printk(KERN_WARNING "FsmAddTimer: timer already active!\n");
134 ft->fi->printdebug(ft->fi, "FsmAddTimer already active!");
135 return -1;
136 }
137 init_timer(&ft->tl);
138 ft->event = event;
139 ft->arg = arg;
140 ft->tl.expires = jiffies + (millisec * HZ) / 1000;
141 add_timer(&ft->tl);
142 return 0;
143}
144
145void
146FsmRestartTimer(struct FsmTimer *ft,
147 int millisec, int event, void *arg, int where)
148{
149
150#if FSM_TIMER_DEBUG
151 if (ft->fi->debug)
152 ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
153 (long) ft, millisec, where);
154#endif
155
156 if (timer_pending(&ft->tl))
157 del_timer(&ft->tl);
158 init_timer(&ft->tl);
159 ft->event = event;
160 ft->arg = arg;
161 ft->tl.expires = jiffies + (millisec * HZ) / 1000;
162 add_timer(&ft->tl);
163}
diff --git a/drivers/isdn/hisax/fsm.h b/drivers/isdn/hisax/fsm.h
new file mode 100644
index 00000000000..f02f7da1688
--- /dev/null
+++ b/drivers/isdn/hisax/fsm.h
@@ -0,0 +1,61 @@
1/* $Id: fsm.h,v 1.3.2.2 2001/09/23 22:24:47 kai Exp $
2 *
3 * Finite state machine
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 * by Kai Germaschewski <kai.germaschewski@gmx.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#ifndef __FSM_H__
15#define __FSM_H__
16
17#include <linux/timer.h>
18
19struct FsmInst;
20
21typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
22
23struct Fsm {
24 FSMFNPTR *jumpmatrix;
25 int state_count, event_count;
26 char **strEvent, **strState;
27};
28
29struct FsmInst {
30 struct Fsm *fsm;
31 int state;
32 int debug;
33 void *userdata;
34 int userint;
35 void (*printdebug) (struct FsmInst *, char *, ...);
36};
37
38struct FsmNode {
39 int state, event;
40 void (*routine) (struct FsmInst *, int, void *);
41};
42
43struct FsmTimer {
44 struct FsmInst *fi;
45 struct timer_list tl;
46 int event;
47 void *arg;
48};
49
50int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount);
51void FsmFree(struct Fsm *fsm);
52int FsmEvent(struct FsmInst *fi, int event, void *arg);
53void FsmChangeState(struct FsmInst *fi, int newstate);
54void FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft);
55int FsmAddTimer(struct FsmTimer *ft, int millisec, int event,
56 void *arg, int where);
57void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event,
58 void *arg, int where);
59void FsmDelTimer(struct FsmTimer *ft, int where);
60
61#endif
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
new file mode 100644
index 00000000000..24a05a43f33
--- /dev/null
+++ b/drivers/isdn/hisax/gazel.c
@@ -0,0 +1,684 @@
1/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 keil Exp $
2 *
3 * low level stuff for Gazel isdn cards
4 *
5 * Author BeWan Systems
6 * based on source code from Karsten Keil
7 * Copyright by BeWan Systems
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include "hisax.h"
17#include "isac.h"
18#include "hscx.h"
19#include "isdnl1.h"
20#include "ipac.h"
21#include <linux/pci.h>
22
23extern const char *CardType[];
24const char *gazel_revision = "$Revision: 2.19.2.4 $";
25
26#define R647 1
27#define R685 2
28#define R753 3
29#define R742 4
30
31#define PLX_CNTRL 0x50 /* registre de controle PLX */
32#define RESET_GAZEL 0x4
33#define RESET_9050 0x40000000
34#define PLX_INCSR 0x4C /* registre d'IT du 9050 */
35#define INT_ISAC_EN 0x8 /* 1 = enable IT isac */
36#define INT_ISAC 0x20 /* 1 = IT isac en cours */
37#define INT_HSCX_EN 0x1 /* 1 = enable IT hscx */
38#define INT_HSCX 0x4 /* 1 = IT hscx en cours */
39#define INT_PCI_EN 0x40 /* 1 = enable IT PCI */
40#define INT_IPAC_EN 0x3 /* enable IT ipac */
41
42
43#define byteout(addr,val) outb(val,addr)
44#define bytein(addr) inb(addr)
45
46static inline u_char
47readreg(unsigned int adr, u_short off)
48{
49 return bytein(adr + off);
50}
51
52static inline void
53writereg(unsigned int adr, u_short off, u_char data)
54{
55 byteout(adr + off, data);
56}
57
58
59static inline void
60read_fifo(unsigned int adr, u_char * data, int size)
61{
62 insb(adr, data, size);
63}
64
65static void
66write_fifo(unsigned int adr, u_char * data, int size)
67{
68 outsb(adr, data, size);
69}
70
71static inline u_char
72readreg_ipac(unsigned int adr, u_short off)
73{
74 register u_char ret;
75
76 byteout(adr, off);
77 ret = bytein(adr + 4);
78 return ret;
79}
80
81static inline void
82writereg_ipac(unsigned int adr, u_short off, u_char data)
83{
84 byteout(adr, off);
85 byteout(adr + 4, data);
86}
87
88
89static inline void
90read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
91{
92 byteout(adr, off);
93 insb(adr + 4, data, size);
94}
95
96static void
97write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
98{
99 byteout(adr, off);
100 outsb(adr + 4, data, size);
101}
102
103/* Interface functions */
104
105static u_char
106ReadISAC(struct IsdnCardState *cs, u_char offset)
107{
108 u_short off2 = offset;
109
110 switch (cs->subtyp) {
111 case R647:
112 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
113 case R685:
114 return (readreg(cs->hw.gazel.isac, off2));
115 case R753:
116 case R742:
117 return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2));
118 }
119 return 0;
120}
121
122static void
123WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
124{
125 u_short off2 = offset;
126
127 switch (cs->subtyp) {
128 case R647:
129 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
130 case R685:
131 writereg(cs->hw.gazel.isac, off2, value);
132 break;
133 case R753:
134 case R742:
135 writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value);
136 break;
137 }
138}
139
140static void
141ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
142{
143 switch (cs->subtyp) {
144 case R647:
145 case R685:
146 read_fifo(cs->hw.gazel.isacfifo, data, size);
147 break;
148 case R753:
149 case R742:
150 read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
151 break;
152 }
153}
154
155static void
156WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
157{
158 switch (cs->subtyp) {
159 case R647:
160 case R685:
161 write_fifo(cs->hw.gazel.isacfifo, data, size);
162 break;
163 case R753:
164 case R742:
165 write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
166 break;
167 }
168}
169
170static void
171ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
172{
173 switch (cs->subtyp) {
174 case R647:
175 case R685:
176 read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
177 break;
178 case R753:
179 case R742:
180 read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
181 break;
182 }
183}
184
185static void
186WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
187{
188 switch (cs->subtyp) {
189 case R647:
190 case R685:
191 write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
192 break;
193 case R753:
194 case R742:
195 write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
196 break;
197 }
198}
199
200static u_char
201ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
202{
203 u_short off2 = offset;
204
205 switch (cs->subtyp) {
206 case R647:
207 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
208 case R685:
209 return (readreg(cs->hw.gazel.hscx[hscx], off2));
210 case R753:
211 case R742:
212 return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2));
213 }
214 return 0;
215}
216
217static void
218WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
219{
220 u_short off2 = offset;
221
222 switch (cs->subtyp) {
223 case R647:
224 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
225 case R685:
226 writereg(cs->hw.gazel.hscx[hscx], off2, value);
227 break;
228 case R753:
229 case R742:
230 writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value);
231 break;
232 }
233}
234
235/*
236 * fast interrupt HSCX stuff goes here
237 */
238
239#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
240#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
241#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
242#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
243
244#include "hscx_irq.c"
245
246static irqreturn_t
247gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
248{
249#define MAXCOUNT 5
250 struct IsdnCardState *cs = dev_id;
251 u_char valisac, valhscx;
252 int count = 0;
253 u_long flags;
254
255 spin_lock_irqsave(&cs->lock, flags);
256 do {
257 valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
258 if (valhscx)
259 hscx_int_main(cs, valhscx);
260 valisac = ReadISAC(cs, ISAC_ISTA);
261 if (valisac)
262 isac_interrupt(cs, valisac);
263 count++;
264 } while ((valhscx || valisac) && (count < MAXCOUNT));
265
266 WriteHSCX(cs, 0, HSCX_MASK, 0xFF);
267 WriteHSCX(cs, 1, HSCX_MASK, 0xFF);
268 WriteISAC(cs, ISAC_MASK, 0xFF);
269 WriteISAC(cs, ISAC_MASK, 0x0);
270 WriteHSCX(cs, 0, HSCX_MASK, 0x0);
271 WriteHSCX(cs, 1, HSCX_MASK, 0x0);
272 spin_unlock_irqrestore(&cs->lock, flags);
273 return IRQ_HANDLED;
274}
275
276
277static irqreturn_t
278gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
279{
280 struct IsdnCardState *cs = dev_id;
281 u_char ista, val;
282 int count = 0;
283 u_long flags;
284
285 spin_lock_irqsave(&cs->lock, flags);
286 ista = ReadISAC(cs, IPAC_ISTA - 0x80);
287 do {
288 if (ista & 0x0f) {
289 val = ReadHSCX(cs, 1, HSCX_ISTA);
290 if (ista & 0x01)
291 val |= 0x01;
292 if (ista & 0x04)
293 val |= 0x02;
294 if (ista & 0x08)
295 val |= 0x04;
296 if (val) {
297 hscx_int_main(cs, val);
298 }
299 }
300 if (ista & 0x20) {
301 val = 0xfe & ReadISAC(cs, ISAC_ISTA);
302 if (val) {
303 isac_interrupt(cs, val);
304 }
305 }
306 if (ista & 0x10) {
307 val = 0x01;
308 isac_interrupt(cs, val);
309 }
310 ista = ReadISAC(cs, IPAC_ISTA - 0x80);
311 count++;
312 }
313 while ((ista & 0x3f) && (count < MAXCOUNT));
314
315 WriteISAC(cs, IPAC_MASK - 0x80, 0xFF);
316 WriteISAC(cs, IPAC_MASK - 0x80, 0xC0);
317 spin_unlock_irqrestore(&cs->lock, flags);
318 return IRQ_HANDLED;
319}
320void
321release_io_gazel(struct IsdnCardState *cs)
322{
323 unsigned int i;
324
325 switch (cs->subtyp) {
326 case R647:
327 for (i = 0x0000; i < 0xC000; i += 0x1000)
328 release_region(i + cs->hw.gazel.hscx[0], 16);
329 release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
330 break;
331
332 case R685:
333 release_region(cs->hw.gazel.hscx[0], 0x100);
334 release_region(cs->hw.gazel.cfg_reg, 0x80);
335 break;
336
337 case R753:
338 release_region(cs->hw.gazel.ipac, 0x8);
339 release_region(cs->hw.gazel.cfg_reg, 0x80);
340 break;
341
342 case R742:
343 release_region(cs->hw.gazel.ipac, 8);
344 break;
345 }
346}
347
348static int
349reset_gazel(struct IsdnCardState *cs)
350{
351 unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
352
353 switch (cs->subtyp) {
354 case R647:
355 writereg(addr, 0, 0);
356 HZDELAY(10);
357 writereg(addr, 0, 1);
358 HZDELAY(2);
359 break;
360 case R685:
361 plxcntrl = inl(addr + PLX_CNTRL);
362 plxcntrl |= (RESET_9050 + RESET_GAZEL);
363 outl(plxcntrl, addr + PLX_CNTRL);
364 plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
365 HZDELAY(4);
366 outl(plxcntrl, addr + PLX_CNTRL);
367 HZDELAY(10);
368 outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
369 break;
370 case R753:
371 plxcntrl = inl(addr + PLX_CNTRL);
372 plxcntrl |= (RESET_9050 + RESET_GAZEL);
373 outl(plxcntrl, addr + PLX_CNTRL);
374 plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
375 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
376 HZDELAY(4);
377 outl(plxcntrl, addr + PLX_CNTRL);
378 HZDELAY(10);
379 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
380 WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
381 WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
382 WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
383 WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
384 outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
385 WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
386 break;
387 case R742:
388 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
389 HZDELAY(4);
390 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
391 WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
392 WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
393 WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
394 WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
395 WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
396 break;
397 }
398 return (0);
399}
400
401static int
402Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
403{
404 u_long flags;
405
406 switch (mt) {
407 case CARD_RESET:
408 spin_lock_irqsave(&cs->lock, flags);
409 reset_gazel(cs);
410 spin_unlock_irqrestore(&cs->lock, flags);
411 return (0);
412 case CARD_RELEASE:
413 release_io_gazel(cs);
414 return (0);
415 case CARD_INIT:
416 spin_lock_irqsave(&cs->lock, flags);
417 inithscxisac(cs, 1);
418 if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
419 int i;
420 for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
421 cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
422 cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
423 }
424 }
425 spin_unlock_irqrestore(&cs->lock, flags);
426 return (0);
427 case CARD_TEST:
428 return (0);
429 }
430 return (0);
431}
432
433static int
434reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
435{
436 unsigned int i, j, base = 0, adr = 0, len = 0;
437
438 switch (cs->subtyp) {
439 case R647:
440 base = cs->hw.gazel.hscx[0];
441 if (!request_region(adr = (0xC000 + base), len = 1, "gazel"))
442 goto error;
443 for (i = 0x0000; i < 0xC000; i += 0x1000) {
444 if (!request_region(adr = (i + base), len = 16, "gazel"))
445 goto error;
446 }
447 if (i != 0xC000) {
448 for (j = 0; j < i; j+= 0x1000)
449 release_region(j + base, 16);
450 release_region(0xC000 + base, 1);
451 goto error;
452 }
453 break;
454
455 case R685:
456 if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel"))
457 goto error;
458 if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
459 release_region(cs->hw.gazel.hscx[0],0x100);
460 goto error;
461 }
462 break;
463
464 case R753:
465 if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
466 goto error;
467 if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
468 release_region(cs->hw.gazel.ipac, 8);
469 goto error;
470 }
471 break;
472
473 case R742:
474 if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
475 goto error;
476 break;
477 }
478
479 return 0;
480
481 error:
482 printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
483 CardType[cs->typ], adr, adr + len);
484 return 1;
485}
486
487static int __init
488setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
489{
490 printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
491 // we got an irq parameter, assume it is an ISA card
492 // R742 decodes address even in not started...
493 // R647 returns FF if not present or not started
494 // eventually needs improvment
495 if (readreg_ipac(card->para[1], IPAC_ID) == 1)
496 cs->subtyp = R742;
497 else
498 cs->subtyp = R647;
499
500 setup_isac(cs);
501 cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
502 cs->hw.gazel.ipac = card->para[1];
503 cs->hw.gazel.isac = card->para[1] + 0x8000;
504 cs->hw.gazel.hscx[0] = card->para[1];
505 cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
506 cs->irq = card->para[0];
507 cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
508 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
509 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
510
511 switch (cs->subtyp) {
512 case R647:
513 printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
514 cs->dc.isac.adf2 = 0x87;
515 printk(KERN_INFO
516 "Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
517 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
518 printk(KERN_INFO
519 "Gazel: hscx A:0x%X hscx B:0x%X\n",
520 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
521
522 break;
523 case R742:
524 printk(KERN_INFO "Gazel: Card ISA R742 found\n");
525 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
526 printk(KERN_INFO
527 "Gazel: config irq:%d ipac:0x%X\n",
528 cs->irq, cs->hw.gazel.ipac);
529 break;
530 }
531
532 return (0);
533}
534
535static struct pci_dev *dev_tel __initdata = NULL;
536
537static int __init
538setup_gazelpci(struct IsdnCardState *cs)
539{
540 u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
541 u_char pci_irq = 0, found;
542 u_int nbseek, seekcard;
543
544 printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
545
546 found = 0;
547 seekcard = PCI_DEVICE_ID_PLX_R685;
548 for (nbseek = 0; nbseek < 3; nbseek++) {
549 if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
550 if (pci_enable_device(dev_tel))
551 return 1;
552 pci_irq = dev_tel->irq;
553 pci_ioaddr0 = pci_resource_start(dev_tel, 1);
554 pci_ioaddr1 = pci_resource_start(dev_tel, 2);
555 found = 1;
556 }
557 if (found)
558 break;
559 else {
560 switch (seekcard) {
561 case PCI_DEVICE_ID_PLX_R685:
562 seekcard = PCI_DEVICE_ID_PLX_R753;
563 break;
564 case PCI_DEVICE_ID_PLX_R753:
565 seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
566 break;
567 }
568 }
569 }
570 if (!found) {
571 printk(KERN_WARNING "Gazel: No PCI card found\n");
572 return (1);
573 }
574 if (!pci_irq) {
575 printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
576 return 1;
577 }
578 cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
579 cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
580 setup_isac(cs);
581 pci_ioaddr1 &= 0xfffe;
582 cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
583 cs->hw.gazel.ipac = pci_ioaddr1;
584 cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
585 cs->hw.gazel.hscx[0] = pci_ioaddr1;
586 cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
587 cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
588 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
589 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
590 cs->irq = pci_irq;
591 cs->irq_flags |= SA_SHIRQ;
592
593 switch (seekcard) {
594 case PCI_DEVICE_ID_PLX_R685:
595 printk(KERN_INFO "Gazel: Card PCI R685 found\n");
596 cs->subtyp = R685;
597 cs->dc.isac.adf2 = 0x87;
598 printk(KERN_INFO
599 "Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
600 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
601 printk(KERN_INFO
602 "Gazel: hscx A:0x%X hscx B:0x%X\n",
603 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
604 break;
605 case PCI_DEVICE_ID_PLX_R753:
606 case PCI_DEVICE_ID_PLX_DJINN_ITOO:
607 printk(KERN_INFO "Gazel: Card PCI R753 found\n");
608 cs->subtyp = R753;
609 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
610 printk(KERN_INFO
611 "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n",
612 cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
613 break;
614 }
615
616 return (0);
617}
618
619int __init
620setup_gazel(struct IsdnCard *card)
621{
622 struct IsdnCardState *cs = card->cs;
623 char tmp[64];
624 u_char val;
625
626 strcpy(tmp, gazel_revision);
627 printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
628
629 if (cs->typ != ISDN_CTYPE_GAZEL)
630 return (0);
631
632 if (card->para[0]) {
633 if (setup_gazelisa(card, cs))
634 return (0);
635 } else {
636
637#ifdef CONFIG_PCI
638 if (setup_gazelpci(cs))
639 return (0);
640#else
641 printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
642 return (0);
643#endif /* CONFIG_PCI */
644 }
645
646 if (reserve_regions(card, cs)) {
647 return (0);
648 }
649 if (reset_gazel(cs)) {
650 printk(KERN_WARNING "Gazel: wrong IRQ\n");
651 release_io_gazel(cs);
652 return (0);
653 }
654 cs->readisac = &ReadISAC;
655 cs->writeisac = &WriteISAC;
656 cs->readisacfifo = &ReadISACfifo;
657 cs->writeisacfifo = &WriteISACfifo;
658 cs->BC_Read_Reg = &ReadHSCX;
659 cs->BC_Write_Reg = &WriteHSCX;
660 cs->BC_Send_Data = &hscx_fill_fifo;
661 cs->cardmsg = &Gazel_card_msg;
662
663 switch (cs->subtyp) {
664 case R647:
665 case R685:
666 cs->irq_func = &gazel_interrupt;
667 ISACVersion(cs, "Gazel:");
668 if (HscxVersion(cs, "Gazel:")) {
669 printk(KERN_WARNING
670 "Gazel: wrong HSCX versions check IO address\n");
671 release_io_gazel(cs);
672 return (0);
673 }
674 break;
675 case R742:
676 case R753:
677 cs->irq_func = &gazel_interrupt_ipac;
678 val = ReadISAC(cs, IPAC_ID - 0x80);
679 printk(KERN_INFO "Gazel: IPAC version %x\n", val);
680 break;
681 }
682
683 return (1);
684}
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
new file mode 100644
index 00000000000..1ac46c26b93
--- /dev/null
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -0,0 +1,1714 @@
1/*************************************************************************/
2/* $Id: hfc4s8s_l1.c,v 1.10 2005/02/09 16:31:09 martinb1 Exp $ */
3/* HFC-4S/8S low layer interface for Cologne Chip HFC-4S/8S isdn chips */
4/* The low layer (L1) is implemented as a loadable module for usage with */
5/* the HiSax isdn driver for passive cards. */
6/* */
7/* Author: Werner Cornelius */
8/* (C) 2003 Cornelius Consult (werner@cornelius-consult.de) */
9/* */
10/* Driver maintained by Cologne Chip */
11/* - Martin Bachem, support@colognechip.com */
12/* */
13/* This driver only works with chip revisions >= 1, older revision 0 */
14/* engineering samples (only first manufacturer sample cards) will not */
15/* work and are rejected by the driver. */
16/* */
17/* This file distributed under the GNU GPL. */
18/* */
19/* See Version History at the end of this file */
20/* */
21/*************************************************************************/
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/config.h>
26#include <linux/pci.h>
27#include <linux/interrupt.h>
28#include <linux/delay.h>
29#include <linux/timer.h>
30#include <linux/skbuff.h>
31#include <linux/wait.h>
32#include "hisax_if.h"
33#include "hfc4s8s_l1.h"
34
35static const char hfc4s8s_rev[] = "Revision: 1.10";
36
37/***************************************************************/
38/* adjustable transparent mode fifo threshold */
39/* The value defines the used fifo threshold with the equation */
40/* */
41/* notify number of bytes = 2 * 2 ^ TRANS_FIFO_THRES */
42/* */
43/* The default value is 5 which results in a buffer size of 64 */
44/* and an interrupt rate of 8ms. */
45/* The maximum value is 7 due to fifo size restrictions. */
46/* Values below 3-4 are not recommended due to high interrupt */
47/* load of the processor. For non critical applications the */
48/* value should be raised to 7 to reduce any interrupt overhead*/
49/***************************************************************/
50#define TRANS_FIFO_THRES 5
51
52/*************/
53/* constants */
54/*************/
55#define CLOCKMODE_0 0 /* ext. 24.576 MhZ clk freq, int. single clock mode */
56#define CLOCKMODE_1 1 /* ext. 49.576 MhZ clk freq, int. single clock mode */
57#define CHIP_ID_SHIFT 4
58#define HFC_MAX_ST 8
59#define MAX_D_FRAME_SIZE 270
60#define MAX_B_FRAME_SIZE 1536
61#define TRANS_TIMER_MODE (TRANS_FIFO_THRES & 0xf)
62#define TRANS_FIFO_BYTES (2 << TRANS_FIFO_THRES)
63#define MAX_F_CNT 0x0f
64
65#define CLKDEL_NT 0x6c
66#define CLKDEL_TE 0xf
67#define CTRL0_NT 4
68#define CTRL0_TE 0
69
70#define L1_TIMER_T4 2 /* minimum in jiffies */
71#define L1_TIMER_T3 (7 * HZ) /* activation timeout */
72#define L1_TIMER_T1 ((120 * HZ) / 1000) /* NT mode deactivation timeout */
73
74
75/******************/
76/* types and vars */
77/******************/
78static int card_cnt;
79
80/* private driver_data */
81typedef struct {
82 int chip_id;
83 int clock_mode;
84 int max_st_ports;
85 char *device_name;
86} hfc4s8s_param;
87
88static struct pci_device_id hfc4s8s_ids[] = {
89 {.vendor = PCI_VENDOR_ID_CCD,
90 .device = PCI_DEVICE_ID_4S,
91 .subvendor = 0x1397,
92 .subdevice = 0x08b4,
93 .driver_data =
94 (unsigned long) &((hfc4s8s_param) {CHIP_ID_4S, CLOCKMODE_0, 4,
95 "HFC-4S Evaluation Board"}),
96 },
97 {.vendor = PCI_VENDOR_ID_CCD,
98 .device = PCI_DEVICE_ID_8S,
99 .subvendor = 0x1397,
100 .subdevice = 0x16b8,
101 .driver_data =
102 (unsigned long) &((hfc4s8s_param) {CHIP_ID_8S, CLOCKMODE_0, 8,
103 "HFC-8S Evaluation Board"}),
104 },
105 {.vendor = PCI_VENDOR_ID_CCD,
106 .device = PCI_DEVICE_ID_4S,
107 .subvendor = 0x1397,
108 .subdevice = 0xb520,
109 .driver_data =
110 (unsigned long) &((hfc4s8s_param) {CHIP_ID_4S, CLOCKMODE_1, 4,
111 "IOB4ST"}),
112 },
113 {.vendor = PCI_VENDOR_ID_CCD,
114 .device = PCI_DEVICE_ID_8S,
115 .subvendor = 0x1397,
116 .subdevice = 0xb522,
117 .driver_data =
118 (unsigned long) &((hfc4s8s_param) {CHIP_ID_8S, CLOCKMODE_1, 8,
119 "IOB8ST"}),
120 },
121 {}
122};
123
124MODULE_DEVICE_TABLE(pci, hfc4s8s_ids);
125
126MODULE_AUTHOR("Werner Cornelius, werner@cornelius-consult.de");
127MODULE_DESCRIPTION("ISDN layer 1 for Cologne Chip HFC-4S/8S chips");
128MODULE_LICENSE("GPL");
129
130/***********/
131/* layer 1 */
132/***********/
133struct hfc4s8s_btype {
134 spinlock_t lock;
135 struct hisax_b_if b_if;
136 struct hfc4s8s_l1 *l1p;
137 struct sk_buff_head tx_queue;
138 struct sk_buff *tx_skb;
139 struct sk_buff *rx_skb;
140 __u8 *rx_ptr;
141 int tx_cnt;
142 int bchan;
143 int mode;
144};
145
146struct _hfc4s8s_hw;
147
148struct hfc4s8s_l1 {
149 spinlock_t lock;
150 struct _hfc4s8s_hw *hw; /* pointer to hardware area */
151 int l1_state; /* actual l1 state */
152 struct timer_list l1_timer; /* layer 1 timer structure */
153 int nt_mode; /* set to nt mode */
154 int st_num; /* own index */
155 int enabled; /* interface is enabled */
156 struct sk_buff_head d_tx_queue; /* send queue */
157 int tx_cnt; /* bytes to send */
158 struct hisax_d_if d_if; /* D-channel interface */
159 struct hfc4s8s_btype b_ch[2]; /* B-channel data */
160 struct hisax_b_if *b_table[2];
161};
162
163/**********************/
164/* hardware structure */
165/**********************/
166typedef struct _hfc4s8s_hw {
167 spinlock_t lock;
168
169 int cardnum;
170 int ifnum;
171 int iobase;
172 int nt_mode;
173 u_char *membase;
174 u_char *hw_membase;
175 void *pdev;
176 int max_fifo;
177 hfc4s8s_param driver_data;
178 int irq;
179 int fifo_sched_cnt;
180 struct work_struct tqueue;
181 struct hfc4s8s_l1 l1[HFC_MAX_ST];
182 char card_name[60];
183 struct {
184 u_char r_irq_ctrl;
185 u_char r_ctrl0;
186 volatile u_char r_irq_statech; /* active isdn l1 status */
187 u_char r_irqmsk_statchg; /* enabled isdn status ints */
188 u_char r_irq_fifo_blx[8]; /* fifo status registers */
189 u_char fifo_rx_trans_enables[8]; /* mask for enabled transparent rx fifos */
190 u_char fifo_slow_timer_service[8]; /* mask for fifos needing slower timer service */
191 volatile u_char r_irq_oview; /* contents of overview register */
192 volatile u_char timer_irq;
193 int timer_usg_cnt; /* number of channels using timer */
194 } mr;
195} hfc4s8s_hw;
196
197
198
199/***************************/
200/* inline function defines */
201/***************************/
202#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM /* inline functions mempry mapped */
203
204/* memory write and dummy IO read to avoid PCI byte merge problems */
205#define Write_hfc8(a,b,c) {(*((volatile u_char *)(a->membase+b)) = c); inb(a->iobase+4);}
206/* memory write without dummy IO access for fifo data access */
207#define fWrite_hfc8(a,b,c) (*((volatile u_char *)(a->membase+b)) = c)
208#define Read_hfc8(a,b) (*((volatile u_char *)(a->membase+b)))
209#define Write_hfc16(a,b,c) (*((volatile unsigned short *)(a->membase+b)) = c)
210#define Read_hfc16(a,b) (*((volatile unsigned short *)(a->membase+b)))
211#define Write_hfc32(a,b,c) (*((volatile unsigned long *)(a->membase+b)) = c)
212#define Read_hfc32(a,b) (*((volatile unsigned long *)(a->membase+b)))
213#define wait_busy(a) {while ((Read_hfc8(a, R_STATUS) & M_BUSY));}
214#define PCI_ENA_MEMIO 0x03
215
216#else
217
218/* inline functions io mapped */
219static inline void
220SetRegAddr(hfc4s8s_hw * a, u_char b)
221{
222 outb(b, (a->iobase) + 4);
223}
224
225static inline u_char
226GetRegAddr(hfc4s8s_hw * a)
227{
228 return (inb((volatile u_int) (a->iobase + 4)));
229}
230
231
232static inline void
233Write_hfc8(hfc4s8s_hw * a, u_char b, u_char c)
234{
235 SetRegAddr(a, b);
236 outb(c, a->iobase);
237}
238
239static inline void
240fWrite_hfc8(hfc4s8s_hw * a, u_char c)
241{
242 outb(c, a->iobase);
243}
244
245static inline void
246Write_hfc16(hfc4s8s_hw * a, u_char b, u_short c)
247{
248 SetRegAddr(a, b);
249 outw(c, a->iobase);
250}
251
252static inline void
253Write_hfc32(hfc4s8s_hw * a, u_char b, u_long c)
254{
255 SetRegAddr(a, b);
256 outl(c, a->iobase);
257}
258
259static inline void
260fWrite_hfc32(hfc4s8s_hw * a, u_long c)
261{
262 outl(c, a->iobase);
263}
264
265static inline u_char
266Read_hfc8(hfc4s8s_hw * a, u_char b)
267{
268 SetRegAddr(a, b);
269 return (inb((volatile u_int) a->iobase));
270}
271
272static inline u_char
273fRead_hfc8(hfc4s8s_hw * a)
274{
275 return (inb((volatile u_int) a->iobase));
276}
277
278
279static inline u_short
280Read_hfc16(hfc4s8s_hw * a, u_char b)
281{
282 SetRegAddr(a, b);
283 return (inw((volatile u_int) a->iobase));
284}
285
286static inline u_long
287Read_hfc32(hfc4s8s_hw * a, u_char b)
288{
289 SetRegAddr(a, b);
290 return (inl((volatile u_int) a->iobase));
291}
292
293static inline u_long
294fRead_hfc32(hfc4s8s_hw * a)
295{
296 return (inl((volatile u_int) a->iobase));
297}
298
299static inline void
300wait_busy(hfc4s8s_hw * a)
301{
302 SetRegAddr(a, R_STATUS);
303 while (inb((volatile u_int) a->iobase) & M_BUSY);
304}
305
306#define PCI_ENA_REGIO 0x01
307
308#endif /* CONFIG_HISAX_HFC4S8S_PCIMEM */
309
310/******************************************************/
311/* function to read critical counter registers that */
312/* may be udpated by the chip during read */
313/******************************************************/
314static volatile u_char
315Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
316{
317 u_char ref8;
318 u_char in8;
319 ref8 = Read_hfc8(hw, reg);
320 while (((in8 = Read_hfc8(hw, reg)) != ref8)) {
321 ref8 = in8;
322 }
323 return in8;
324}
325
326static volatile int
327Read_hfc16_stable(hfc4s8s_hw * hw, int reg)
328{
329 int ref16;
330 int in16;
331
332 ref16 = Read_hfc16(hw, reg);
333 while (((in16 = Read_hfc16(hw, reg)) != ref16)) {
334 ref16 = in16;
335 }
336 return in16;
337}
338
339/*****************************/
340/* D-channel call from HiSax */
341/*****************************/
342static void
343dch_l2l1(struct hisax_d_if *iface, int pr, void *arg)
344{
345 struct hfc4s8s_l1 *l1 = iface->ifc.priv;
346 struct sk_buff *skb = (struct sk_buff *) arg;
347 u_long flags;
348
349 switch (pr) {
350
351 case (PH_DATA | REQUEST):
352 if (!l1->enabled) {
353 dev_kfree_skb(skb);
354 break;
355 }
356 spin_lock_irqsave(&l1->lock, flags);
357 skb_queue_tail(&l1->d_tx_queue, skb);
358 if ((skb_queue_len(&l1->d_tx_queue) == 1) &&
359 (l1->tx_cnt <= 0)) {
360 l1->hw->mr.r_irq_fifo_blx[l1->st_num] |=
361 0x10;
362 spin_unlock_irqrestore(&l1->lock, flags);
363 schedule_work(&l1->hw->tqueue);
364 } else
365 spin_unlock_irqrestore(&l1->lock, flags);
366 break;
367
368 case (PH_ACTIVATE | REQUEST):
369 if (!l1->enabled)
370 break;
371 if (!l1->nt_mode) {
372 if (l1->l1_state < 6) {
373 spin_lock_irqsave(&l1->lock,
374 flags);
375
376 Write_hfc8(l1->hw, R_ST_SEL,
377 l1->st_num);
378 Write_hfc8(l1->hw, A_ST_WR_STA,
379 0x60);
380 mod_timer(&l1->l1_timer,
381 jiffies + L1_TIMER_T3);
382 spin_unlock_irqrestore(&l1->lock,
383 flags);
384 } else if (l1->l1_state == 7)
385 l1->d_if.ifc.l1l2(&l1->d_if.ifc,
386 PH_ACTIVATE |
387 INDICATION,
388 NULL);
389 } else {
390 if (l1->l1_state != 3) {
391 spin_lock_irqsave(&l1->lock,
392 flags);
393 Write_hfc8(l1->hw, R_ST_SEL,
394 l1->st_num);
395 Write_hfc8(l1->hw, A_ST_WR_STA,
396 0x60);
397 spin_unlock_irqrestore(&l1->lock,
398 flags);
399 } else if (l1->l1_state == 3)
400 l1->d_if.ifc.l1l2(&l1->d_if.ifc,
401 PH_ACTIVATE |
402 INDICATION,
403 NULL);
404 }
405 break;
406
407 default:
408 printk(KERN_INFO
409 "HFC-4S/8S: Unknown D-chan cmd 0x%x received, ignored\n",
410 pr);
411 break;
412 }
413 if (!l1->enabled)
414 l1->d_if.ifc.l1l2(&l1->d_if.ifc,
415 PH_DEACTIVATE | INDICATION, NULL);
416} /* dch_l2l1 */
417
418/*****************************/
419/* B-channel call from HiSax */
420/*****************************/
421static void
422bch_l2l1(struct hisax_if *ifc, int pr, void *arg)
423{
424 struct hfc4s8s_btype *bch = ifc->priv;
425 struct hfc4s8s_l1 *l1 = bch->l1p;
426 struct sk_buff *skb = (struct sk_buff *) arg;
427 int mode = (int) arg;
428 u_long flags;
429
430 switch (pr) {
431
432 case (PH_DATA | REQUEST):
433 if (!l1->enabled || (bch->mode == L1_MODE_NULL)) {
434 dev_kfree_skb(skb);
435 break;
436 }
437 spin_lock_irqsave(&l1->lock, flags);
438 skb_queue_tail(&bch->tx_queue, skb);
439 if (!bch->tx_skb && (bch->tx_cnt <= 0)) {
440 l1->hw->mr.r_irq_fifo_blx[l1->st_num] |=
441 ((bch->bchan == 1) ? 1 : 4);
442 spin_unlock_irqrestore(&l1->lock, flags);
443 schedule_work(&l1->hw->tqueue);
444 } else
445 spin_unlock_irqrestore(&l1->lock, flags);
446 break;
447
448 case (PH_ACTIVATE | REQUEST):
449 case (PH_DEACTIVATE | REQUEST):
450 if (!l1->enabled)
451 break;
452 if (pr == (PH_DEACTIVATE | REQUEST))
453 mode = L1_MODE_NULL;
454
455 switch (mode) {
456 case L1_MODE_HDLC:
457 spin_lock_irqsave(&l1->lock,
458 flags);
459 l1->hw->mr.timer_usg_cnt++;
460 l1->hw->mr.
461 fifo_slow_timer_service[l1->
462 st_num]
463 |=
464 ((bch->bchan ==
465 1) ? 0x2 : 0x8);
466 Write_hfc8(l1->hw, R_FIFO,
467 (l1->st_num * 8 +
468 ((bch->bchan ==
469 1) ? 0 : 2)));
470 wait_busy(l1->hw);
471 Write_hfc8(l1->hw, A_CON_HDLC, 0xc); /* HDLC mode, flag fill, connect ST */
472 Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
473 Write_hfc8(l1->hw, A_IRQ_MSK, 1); /* enable TX interrupts for hdlc */
474 Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
475 wait_busy(l1->hw);
476
477 Write_hfc8(l1->hw, R_FIFO,
478 (l1->st_num * 8 +
479 ((bch->bchan ==
480 1) ? 1 : 3)));
481 wait_busy(l1->hw);
482 Write_hfc8(l1->hw, A_CON_HDLC, 0xc); /* HDLC mode, flag fill, connect ST */
483 Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
484 Write_hfc8(l1->hw, A_IRQ_MSK, 1); /* enable RX interrupts for hdlc */
485 Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
486
487 Write_hfc8(l1->hw, R_ST_SEL,
488 l1->st_num);
489 l1->hw->mr.r_ctrl0 |=
490 (bch->bchan & 3);
491 Write_hfc8(l1->hw, A_ST_CTRL0,
492 l1->hw->mr.r_ctrl0);
493 bch->mode = L1_MODE_HDLC;
494 spin_unlock_irqrestore(&l1->lock,
495 flags);
496
497 bch->b_if.ifc.l1l2(&bch->b_if.ifc,
498 PH_ACTIVATE |
499 INDICATION,
500 NULL);
501 break;
502
503 case L1_MODE_TRANS:
504 spin_lock_irqsave(&l1->lock,
505 flags);
506 l1->hw->mr.
507 fifo_rx_trans_enables[l1->
508 st_num]
509 |=
510 ((bch->bchan ==
511 1) ? 0x2 : 0x8);
512 l1->hw->mr.timer_usg_cnt++;
513 Write_hfc8(l1->hw, R_FIFO,
514 (l1->st_num * 8 +
515 ((bch->bchan ==
516 1) ? 0 : 2)));
517 wait_busy(l1->hw);
518 Write_hfc8(l1->hw, A_CON_HDLC, 0xf); /* Transparent mode, 1 fill, connect ST */
519 Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
520 Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable TX interrupts */
521 Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
522 wait_busy(l1->hw);
523
524 Write_hfc8(l1->hw, R_FIFO,
525 (l1->st_num * 8 +
526 ((bch->bchan ==
527 1) ? 1 : 3)));
528 wait_busy(l1->hw);
529 Write_hfc8(l1->hw, A_CON_HDLC, 0xf); /* Transparent mode, 1 fill, connect ST */
530 Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
531 Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable RX interrupts */
532 Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
533
534 Write_hfc8(l1->hw, R_ST_SEL,
535 l1->st_num);
536 l1->hw->mr.r_ctrl0 |=
537 (bch->bchan & 3);
538 Write_hfc8(l1->hw, A_ST_CTRL0,
539 l1->hw->mr.r_ctrl0);
540 bch->mode = L1_MODE_TRANS;
541 spin_unlock_irqrestore(&l1->lock,
542 flags);
543
544 bch->b_if.ifc.l1l2(&bch->b_if.ifc,
545 PH_ACTIVATE |
546 INDICATION,
547 NULL);
548 break;
549
550 default:
551 if (bch->mode == L1_MODE_NULL)
552 break;
553 spin_lock_irqsave(&l1->lock,
554 flags);
555 l1->hw->mr.
556 fifo_slow_timer_service[l1->
557 st_num]
558 &=
559 ~((bch->bchan ==
560 1) ? 0x3 : 0xc);
561 l1->hw->mr.
562 fifo_rx_trans_enables[l1->
563 st_num]
564 &=
565 ~((bch->bchan ==
566 1) ? 0x3 : 0xc);
567 l1->hw->mr.timer_usg_cnt--;
568 Write_hfc8(l1->hw, R_FIFO,
569 (l1->st_num * 8 +
570 ((bch->bchan ==
571 1) ? 0 : 2)));
572 wait_busy(l1->hw);
573 Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable TX interrupts */
574 wait_busy(l1->hw);
575 Write_hfc8(l1->hw, R_FIFO,
576 (l1->st_num * 8 +
577 ((bch->bchan ==
578 1) ? 1 : 3)));
579 wait_busy(l1->hw);
580 Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable RX interrupts */
581 Write_hfc8(l1->hw, R_ST_SEL,
582 l1->st_num);
583 l1->hw->mr.r_ctrl0 &=
584 ~(bch->bchan & 3);
585 Write_hfc8(l1->hw, A_ST_CTRL0,
586 l1->hw->mr.r_ctrl0);
587 spin_unlock_irqrestore(&l1->lock,
588 flags);
589
590 bch->mode = L1_MODE_NULL;
591 bch->b_if.ifc.l1l2(&bch->b_if.ifc,
592 PH_DEACTIVATE |
593 INDICATION,
594 NULL);
595 if (bch->tx_skb) {
596 dev_kfree_skb(bch->tx_skb);
597 bch->tx_skb = NULL;
598 }
599 if (bch->rx_skb) {
600 dev_kfree_skb(bch->rx_skb);
601 bch->rx_skb = NULL;
602 }
603 skb_queue_purge(&bch->tx_queue);
604 bch->tx_cnt = 0;
605 bch->rx_ptr = NULL;
606 break;
607 }
608
609 /* timer is only used when at least one b channel */
610 /* is set up to transparent mode */
611 if (l1->hw->mr.timer_usg_cnt) {
612 Write_hfc8(l1->hw, R_IRQMSK_MISC,
613 M_TI_IRQMSK);
614 } else {
615 Write_hfc8(l1->hw, R_IRQMSK_MISC, 0);
616 }
617
618 break;
619
620 default:
621 printk(KERN_INFO
622 "HFC-4S/8S: Unknown B-chan cmd 0x%x received, ignored\n",
623 pr);
624 break;
625 }
626 if (!l1->enabled)
627 bch->b_if.ifc.l1l2(&bch->b_if.ifc,
628 PH_DEACTIVATE | INDICATION, NULL);
629} /* bch_l2l1 */
630
631/**************************/
632/* layer 1 timer function */
633/**************************/
634static void
635hfc_l1_timer(struct hfc4s8s_l1 *l1)
636{
637 u_long flags;
638
639 if (!l1->enabled)
640 return;
641
642 spin_lock_irqsave(&l1->lock, flags);
643 if (l1->nt_mode) {
644 l1->l1_state = 1;
645 Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
646 Write_hfc8(l1->hw, A_ST_WR_STA, 0x11);
647 spin_unlock_irqrestore(&l1->lock, flags);
648 l1->d_if.ifc.l1l2(&l1->d_if.ifc,
649 PH_DEACTIVATE | INDICATION, NULL);
650 spin_lock_irqsave(&l1->lock, flags);
651 l1->l1_state = 1;
652 Write_hfc8(l1->hw, A_ST_WR_STA, 0x1);
653 spin_unlock_irqrestore(&l1->lock, flags);
654 } else {
655 /* activation timed out */
656 Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
657 Write_hfc8(l1->hw, A_ST_WR_STA, 0x13);
658 spin_unlock_irqrestore(&l1->lock, flags);
659 l1->d_if.ifc.l1l2(&l1->d_if.ifc,
660 PH_DEACTIVATE | INDICATION, NULL);
661 spin_lock_irqsave(&l1->lock, flags);
662 Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
663 Write_hfc8(l1->hw, A_ST_WR_STA, 0x3);
664 spin_unlock_irqrestore(&l1->lock, flags);
665 }
666} /* hfc_l1_timer */
667
668/****************************************/
669/* a complete D-frame has been received */
670/****************************************/
671static void
672rx_d_frame(struct hfc4s8s_l1 *l1p, int ech)
673{
674 int z1, z2;
675 u_char f1, f2, df;
676 struct sk_buff *skb;
677 u_char *cp;
678
679
680 if (!l1p->enabled)
681 return;
682 do {
683 /* E/D RX fifo */
684 Write_hfc8(l1p->hw, R_FIFO,
685 (l1p->st_num * 8 + ((ech) ? 7 : 5)));
686 wait_busy(l1p->hw);
687
688 f1 = Read_hfc8_stable(l1p->hw, A_F1);
689 f2 = Read_hfc8(l1p->hw, A_F2);
690 df = f1 - f2;
691 if ((f1 - f2) < 0)
692 df = f1 - f2 + MAX_F_CNT + 1;
693
694
695 if (!df) {
696 return; /* no complete frame in fifo */
697 }
698
699 z1 = Read_hfc16_stable(l1p->hw, A_Z1);
700 z2 = Read_hfc16(l1p->hw, A_Z2);
701
702 z1 = z1 - z2 + 1;
703 if (z1 < 0)
704 z1 += 384;
705
706 if (!(skb = dev_alloc_skb(MAX_D_FRAME_SIZE))) {
707 printk(KERN_INFO
708 "HFC-4S/8S: Could not allocate D/E "
709 "channel receive buffer");
710 Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
711 wait_busy(l1p->hw);
712 return;
713 }
714
715 if (((z1 < 4) || (z1 > MAX_D_FRAME_SIZE))) {
716 if (skb)
717 dev_kfree_skb(skb);
718 /* remove errornous D frame */
719 if (df == 1) {
720 /* reset fifo */
721 Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
722 wait_busy(l1p->hw);
723 return;
724 } else {
725 /* read errornous D frame */
726
727#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
728 SetRegAddr(l1p->hw, A_FIFO_DATA0);
729#endif
730
731 while (z1 >= 4) {
732#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
733 Read_hfc32(l1p->hw, A_FIFO_DATA0);
734#else
735 fRead_hfc32(l1p->hw);
736#endif
737 z1 -= 4;
738 }
739
740 while (z1--)
741#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
742 Read_hfc8(l1p->hw, A_FIFO_DATA0);
743#else
744 fRead_hfc8(l1p->hw);
745#endif
746
747 Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);
748 wait_busy(l1p->hw);
749 return;
750 }
751 }
752
753 cp = skb->data;
754
755#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
756 SetRegAddr(l1p->hw, A_FIFO_DATA0);
757#endif
758
759 while (z1 >= 4) {
760#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
761 *((unsigned long *) cp) =
762 Read_hfc32(l1p->hw, A_FIFO_DATA0);
763#else
764 *((unsigned long *) cp) = fRead_hfc32(l1p->hw);
765#endif
766 cp += 4;
767 z1 -= 4;
768 }
769
770 while (z1--)
771#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
772 *cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0);
773#else
774 *cp++ = fRead_hfc8(l1p->hw);
775#endif
776
777 Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* increment f counter */
778 wait_busy(l1p->hw);
779
780 if (*(--cp)) {
781 dev_kfree_skb(skb);
782 } else {
783 skb->len = (cp - skb->data) - 2;
784 if (ech)
785 l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
786 PH_DATA_E | INDICATION,
787 skb);
788 else
789 l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
790 PH_DATA | INDICATION,
791 skb);
792 }
793 } while (1);
794} /* rx_d_frame */
795
796/*************************************************************/
797/* a B-frame has been received (perhaps not fully completed) */
798/*************************************************************/
799static void
800rx_b_frame(struct hfc4s8s_btype *bch)
801{
802 int z1, z2, hdlc_complete;
803 u_char f1, f2;
804 struct hfc4s8s_l1 *l1 = bch->l1p;
805 struct sk_buff *skb;
806
807 if (!l1->enabled || (bch->mode == L1_MODE_NULL))
808 return;
809
810 do {
811 /* RX Fifo */
812 Write_hfc8(l1->hw, R_FIFO,
813 (l1->st_num * 8 + ((bch->bchan == 1) ? 1 : 3)));
814 wait_busy(l1->hw);
815
816 if (bch->mode == L1_MODE_HDLC) {
817 f1 = Read_hfc8_stable(l1->hw, A_F1);
818 f2 = Read_hfc8(l1->hw, A_F2);
819 hdlc_complete = ((f1 ^ f2) & MAX_F_CNT);
820 } else
821 hdlc_complete = 0;
822 z1 = Read_hfc16_stable(l1->hw, A_Z1);
823 z2 = Read_hfc16(l1->hw, A_Z2);
824 z1 = (z1 - z2);
825 if (hdlc_complete)
826 z1++;
827 if (z1 < 0)
828 z1 += 384;
829
830 if (!z1)
831 break;
832
833 if (!(skb = bch->rx_skb)) {
834 if (!
835 (skb =
836 dev_alloc_skb((bch->mode ==
837 L1_MODE_TRANS) ? z1
838 : (MAX_B_FRAME_SIZE + 3)))) {
839 printk(KERN_ERR
840 "HFC-4S/8S: Could not allocate B "
841 "channel receive buffer");
842 return;
843 }
844 bch->rx_ptr = skb->data;
845 bch->rx_skb = skb;
846 }
847
848 skb->len = (bch->rx_ptr - skb->data) + z1;
849
850 /* HDLC length check */
851 if ((bch->mode == L1_MODE_HDLC) &&
852 ((hdlc_complete && (skb->len < 4)) ||
853 (skb->len > (MAX_B_FRAME_SIZE + 3)))) {
854
855 skb->len = 0;
856 bch->rx_ptr = skb->data;
857 Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
858 wait_busy(l1->hw);
859 return;
860 }
861#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
862 SetRegAddr(l1->hw, A_FIFO_DATA0);
863#endif
864
865 while (z1 >= 4) {
866#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
867 *((unsigned long *) bch->rx_ptr) =
868 Read_hfc32(l1->hw, A_FIFO_DATA0);
869#else
870 *((unsigned long *) bch->rx_ptr) =
871 fRead_hfc32(l1->hw);
872#endif
873 bch->rx_ptr += 4;
874 z1 -= 4;
875 }
876
877 while (z1--)
878#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
879 *(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0);
880#else
881 *(bch->rx_ptr++) = fRead_hfc8(l1->hw);
882#endif
883
884 if (hdlc_complete) {
885 /* increment f counter */
886 Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
887 wait_busy(l1->hw);
888
889 /* hdlc crc check */
890 bch->rx_ptr--;
891 if (*bch->rx_ptr) {
892 skb->len = 0;
893 bch->rx_ptr = skb->data;
894 continue;
895 }
896 skb->len -= 3;
897 }
898 if (hdlc_complete || (bch->mode == L1_MODE_TRANS)) {
899 bch->rx_skb = NULL;
900 bch->rx_ptr = NULL;
901 bch->b_if.ifc.l1l2(&bch->b_if.ifc,
902 PH_DATA | INDICATION, skb);
903 }
904
905 } while (1);
906} /* rx_b_frame */
907
908/********************************************/
909/* a D-frame has been/should be transmitted */
910/********************************************/
911static void
912tx_d_frame(struct hfc4s8s_l1 *l1p)
913{
914 struct sk_buff *skb;
915 u_char f1, f2;
916 u_char *cp;
917 int cnt;
918
919 if (l1p->l1_state != 7)
920 return;
921
922 /* TX fifo */
923 Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4));
924 wait_busy(l1p->hw);
925
926 f1 = Read_hfc8(l1p->hw, A_F1);
927 f2 = Read_hfc8_stable(l1p->hw, A_F2);
928
929 if ((f1 ^ f2) & MAX_F_CNT)
930 return; /* fifo is still filled */
931
932 if (l1p->tx_cnt > 0) {
933 cnt = l1p->tx_cnt;
934 l1p->tx_cnt = 0;
935 l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM,
936 (void *) cnt);
937 }
938
939 if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
940 cp = skb->data;
941 cnt = skb->len;
942#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
943 SetRegAddr(l1p->hw, A_FIFO_DATA0);
944#endif
945
946 while (cnt >= 4) {
947#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
948 fWrite_hfc32(l1p->hw, A_FIFO_DATA0,
949 *(unsigned long *) cp);
950#else
951 SetRegAddr(l1p->hw, A_FIFO_DATA0);
952 fWrite_hfc32(l1p->hw, *(unsigned long *) cp);
953#endif
954 cp += 4;
955 cnt -= 4;
956 }
957
958#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
959 while (cnt--)
960 fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++);
961#else
962 while (cnt--)
963 fWrite_hfc8(l1p->hw, *cp++);
964#endif
965
966 l1p->tx_cnt = skb->truesize;
967 Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* increment f counter */
968 wait_busy(l1p->hw);
969
970 dev_kfree_skb(skb);
971 }
972} /* tx_d_frame */
973
974/******************************************************/
975/* a B-frame may be transmitted (or is not completed) */
976/******************************************************/
977static void
978tx_b_frame(struct hfc4s8s_btype *bch)
979{
980 struct sk_buff *skb;
981 struct hfc4s8s_l1 *l1 = bch->l1p;
982 u_char *cp;
983 int cnt, max, hdlc_num, ack_len = 0;
984
985 if (!l1->enabled || (bch->mode == L1_MODE_NULL))
986 return;
987
988 /* TX fifo */
989 Write_hfc8(l1->hw, R_FIFO,
990 (l1->st_num * 8 + ((bch->bchan == 1) ? 0 : 2)));
991 wait_busy(l1->hw);
992 do {
993
994 if (bch->mode == L1_MODE_HDLC) {
995 hdlc_num = Read_hfc8(l1->hw, A_F1) & MAX_F_CNT;
996 hdlc_num -=
997 (Read_hfc8_stable(l1->hw, A_F2) & MAX_F_CNT);
998 if (hdlc_num < 0)
999 hdlc_num += 16;
1000 if (hdlc_num >= 15)
1001 break; /* fifo still filled up with hdlc frames */
1002 } else
1003 hdlc_num = 0;
1004
1005 if (!(skb = bch->tx_skb)) {
1006 if (!(skb = skb_dequeue(&bch->tx_queue))) {
1007 l1->hw->mr.fifo_slow_timer_service[l1->
1008 st_num]
1009 &= ~((bch->bchan == 1) ? 1 : 4);
1010 break; /* list empty */
1011 }
1012 bch->tx_skb = skb;
1013 bch->tx_cnt = 0;
1014 }
1015
1016 if (!hdlc_num)
1017 l1->hw->mr.fifo_slow_timer_service[l1->st_num] |=
1018 ((bch->bchan == 1) ? 1 : 4);
1019 else
1020 l1->hw->mr.fifo_slow_timer_service[l1->st_num] &=
1021 ~((bch->bchan == 1) ? 1 : 4);
1022
1023 max = Read_hfc16_stable(l1->hw, A_Z2);
1024 max -= Read_hfc16(l1->hw, A_Z1);
1025 if (max <= 0)
1026 max += 384;
1027 max--;
1028
1029 if (max < 16)
1030 break; /* don't write to small amounts of bytes */
1031
1032 cnt = skb->len - bch->tx_cnt;
1033 if (cnt > max)
1034 cnt = max;
1035 cp = skb->data + bch->tx_cnt;
1036 bch->tx_cnt += cnt;
1037
1038#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
1039 SetRegAddr(l1->hw, A_FIFO_DATA0);
1040#endif
1041 while (cnt >= 4) {
1042#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
1043 fWrite_hfc32(l1->hw, A_FIFO_DATA0,
1044 *(unsigned long *) cp);
1045#else
1046 fWrite_hfc32(l1->hw, *(unsigned long *) cp);
1047#endif
1048 cp += 4;
1049 cnt -= 4;
1050 }
1051
1052 while (cnt--)
1053#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
1054 fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++);
1055#else
1056 fWrite_hfc8(l1->hw, *cp++);
1057#endif
1058
1059 if (bch->tx_cnt >= skb->len) {
1060 if (bch->mode == L1_MODE_HDLC) {
1061 /* increment f counter */
1062 Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
1063 }
1064 ack_len += skb->truesize;
1065 bch->tx_skb = 0;
1066 bch->tx_cnt = 0;
1067 dev_kfree_skb(skb);
1068 } else
1069 /* Re-Select */
1070 Write_hfc8(l1->hw, R_FIFO,
1071 (l1->st_num * 8 +
1072 ((bch->bchan == 1) ? 0 : 2)));
1073 wait_busy(l1->hw);
1074 } while (1);
1075
1076 if (ack_len)
1077 bch->b_if.ifc.l1l2((struct hisax_if *) &bch->b_if,
1078 PH_DATA | CONFIRM, (void *) ack_len);
1079} /* tx_b_frame */
1080
1081/*************************************/
1082/* bottom half handler for interrupt */
1083/*************************************/
1084static void
1085hfc4s8s_bh(hfc4s8s_hw * hw)
1086{
1087 u_char b;
1088 struct hfc4s8s_l1 *l1p;
1089 volatile u_char *fifo_stat;
1090 int idx;
1091
1092 /* handle layer 1 state changes */
1093 b = 1;
1094 l1p = hw->l1;
1095 while (b) {
1096 if ((b & hw->mr.r_irq_statech)) {
1097 /* reset l1 event */
1098 hw->mr.r_irq_statech &= ~b;
1099 if (l1p->enabled) {
1100 if (l1p->nt_mode) {
1101 u_char oldstate = l1p->l1_state;
1102
1103 Write_hfc8(l1p->hw, R_ST_SEL,
1104 l1p->st_num);
1105 l1p->l1_state =
1106 Read_hfc8(l1p->hw,
1107 A_ST_RD_STA) & 0xf;
1108
1109 if ((oldstate == 3)
1110 && (l1p->l1_state != 3))
1111 l1p->d_if.ifc.l1l2(&l1p->
1112 d_if.
1113 ifc,
1114 PH_DEACTIVATE
1115 |
1116 INDICATION,
1117 NULL);
1118
1119 if (l1p->l1_state != 2) {
1120 del_timer(&l1p->l1_timer);
1121 if (l1p->l1_state == 3) {
1122 l1p->d_if.ifc.
1123 l1l2(&l1p->
1124 d_if.ifc,
1125 PH_ACTIVATE
1126 |
1127 INDICATION,
1128 NULL);
1129 }
1130 } else {
1131 /* allow transition */
1132 Write_hfc8(hw, A_ST_WR_STA,
1133 M_SET_G2_G3);
1134 mod_timer(&l1p->l1_timer,
1135 jiffies +
1136 L1_TIMER_T1);
1137 }
1138 printk(KERN_INFO
1139 "HFC-4S/8S: NT ch %d l1 state %d -> %d\n",
1140 l1p->st_num, oldstate,
1141 l1p->l1_state);
1142 } else {
1143 u_char oldstate = l1p->l1_state;
1144
1145 Write_hfc8(l1p->hw, R_ST_SEL,
1146 l1p->st_num);
1147 l1p->l1_state =
1148 Read_hfc8(l1p->hw,
1149 A_ST_RD_STA) & 0xf;
1150
1151 if (((l1p->l1_state == 3) &&
1152 ((oldstate == 7) ||
1153 (oldstate == 8))) ||
1154 ((timer_pending
1155 (&l1p->l1_timer))
1156 && (l1p->l1_state == 8))) {
1157 mod_timer(&l1p->l1_timer,
1158 L1_TIMER_T4 +
1159 jiffies);
1160 } else {
1161 if (l1p->l1_state == 7) {
1162 del_timer(&l1p->
1163 l1_timer);
1164 l1p->d_if.ifc.
1165 l1l2(&l1p->
1166 d_if.ifc,
1167 PH_ACTIVATE
1168 |
1169 INDICATION,
1170 NULL);
1171 tx_d_frame(l1p);
1172 }
1173 if (l1p->l1_state == 3) {
1174 if (oldstate != 3)
1175 l1p->d_if.
1176 ifc.
1177 l1l2
1178 (&l1p->
1179 d_if.
1180 ifc,
1181 PH_DEACTIVATE
1182 |
1183 INDICATION,
1184 NULL);
1185 }
1186 }
1187 printk(KERN_INFO
1188 "HFC-4S/8S: TE %d ch %d l1 state %d -> %d\n",
1189 l1p->hw->cardnum,
1190 l1p->st_num, oldstate,
1191 l1p->l1_state);
1192 }
1193 }
1194 }
1195 b <<= 1;
1196 l1p++;
1197 }
1198
1199 /* now handle the fifos */
1200 idx = 0;
1201 fifo_stat = hw->mr.r_irq_fifo_blx;
1202 l1p = hw->l1;
1203 while (idx < hw->driver_data.max_st_ports) {
1204
1205 if (hw->mr.timer_irq) {
1206 *fifo_stat |= hw->mr.fifo_rx_trans_enables[idx];
1207 if (hw->fifo_sched_cnt <= 0) {
1208 *fifo_stat |=
1209 hw->mr.fifo_slow_timer_service[l1p->
1210 st_num];
1211 }
1212 }
1213 /* ignore fifo 6 (TX E fifo) */
1214 *fifo_stat &= 0xff - 0x40;
1215
1216 while (*fifo_stat) {
1217
1218 if (!l1p->nt_mode) {
1219 /* RX Fifo has data to read */
1220 if ((*fifo_stat & 0x20)) {
1221 *fifo_stat &= ~0x20;
1222 rx_d_frame(l1p, 0);
1223 }
1224 /* E Fifo has data to read */
1225 if ((*fifo_stat & 0x80)) {
1226 *fifo_stat &= ~0x80;
1227 rx_d_frame(l1p, 1);
1228 }
1229 /* TX Fifo completed send */
1230 if ((*fifo_stat & 0x10)) {
1231 *fifo_stat &= ~0x10;
1232 tx_d_frame(l1p);
1233 }
1234 }
1235 /* B1 RX Fifo has data to read */
1236 if ((*fifo_stat & 0x2)) {
1237 *fifo_stat &= ~0x2;
1238 rx_b_frame(l1p->b_ch);
1239 }
1240 /* B1 TX Fifo has send completed */
1241 if ((*fifo_stat & 0x1)) {
1242 *fifo_stat &= ~0x1;
1243 tx_b_frame(l1p->b_ch);
1244 }
1245 /* B2 RX Fifo has data to read */
1246 if ((*fifo_stat & 0x8)) {
1247 *fifo_stat &= ~0x8;
1248 rx_b_frame(l1p->b_ch + 1);
1249 }
1250 /* B2 TX Fifo has send completed */
1251 if ((*fifo_stat & 0x4)) {
1252 *fifo_stat &= ~0x4;
1253 tx_b_frame(l1p->b_ch + 1);
1254 }
1255 }
1256 fifo_stat++;
1257 l1p++;
1258 idx++;
1259 }
1260
1261 if (hw->fifo_sched_cnt <= 0)
1262 hw->fifo_sched_cnt += (1 << (7 - TRANS_TIMER_MODE));
1263 hw->mr.timer_irq = 0; /* clear requested timer irq */
1264} /* hfc4s8s_bh */
1265
1266/*********************/
1267/* interrupt handler */
1268/*********************/
1269static irqreturn_t
1270hfc4s8s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
1271{
1272 hfc4s8s_hw *hw = dev_id;
1273 u_char b, ovr;
1274 volatile u_char *ovp;
1275 int idx;
1276 u_char old_ioreg;
1277
1278 if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN))
1279 return IRQ_NONE;
1280
1281#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
1282 /* read current selected regsister */
1283 old_ioreg = GetRegAddr(hw);
1284#endif
1285
1286 /* Layer 1 State change */
1287 hw->mr.r_irq_statech |=
1288 (Read_hfc8(hw, R_SCI) & hw->mr.r_irqmsk_statchg);
1289 if (!
1290 (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))
1291&& !hw->mr.r_irq_statech) {
1292#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
1293 SetRegAddr(hw, old_ioreg);
1294#endif
1295 return IRQ_NONE;
1296 }
1297
1298 /* timer event */
1299 if (Read_hfc8(hw, R_IRQ_MISC) & M_TI_IRQ) {
1300 hw->mr.timer_irq = 1;
1301 hw->fifo_sched_cnt--;
1302 }
1303
1304 /* FIFO event */
1305 if ((ovr = Read_hfc8(hw, R_IRQ_OVIEW))) {
1306 hw->mr.r_irq_oview |= ovr;
1307 idx = R_IRQ_FIFO_BL0;
1308 ovp = hw->mr.r_irq_fifo_blx;
1309 while (ovr) {
1310 if ((ovr & 1)) {
1311 *ovp |= Read_hfc8(hw, idx);
1312 }
1313 ovp++;
1314 idx++;
1315 ovr >>= 1;
1316 }
1317 }
1318
1319 /* queue the request to allow other cards to interrupt */
1320 schedule_work(&hw->tqueue);
1321
1322#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
1323 SetRegAddr(hw, old_ioreg);
1324#endif
1325 return IRQ_HANDLED;
1326} /* hfc4s8s_interrupt */
1327
1328/***********************************************************************/
1329/* reset the complete chip, don't release the chips irq but disable it */
1330/***********************************************************************/
1331static void
1332chipreset(hfc4s8s_hw * hw)
1333{
1334 u_long flags;
1335
1336 spin_lock_irqsave(&hw->lock, flags);
1337 Write_hfc8(hw, R_CTRL, 0); /* use internal RAM */
1338 Write_hfc8(hw, R_RAM_MISC, 0); /* 32k*8 RAM */
1339 Write_hfc8(hw, R_FIFO_MD, 0); /* fifo mode 386 byte/fifo simple mode */
1340 Write_hfc8(hw, R_CIRM, M_SRES); /* reset chip */
1341 hw->mr.r_irq_ctrl = 0; /* interrupt is inactive */
1342 spin_unlock_irqrestore(&hw->lock, flags);
1343
1344 udelay(3);
1345 Write_hfc8(hw, R_CIRM, 0); /* disable reset */
1346 wait_busy(hw);
1347
1348 Write_hfc8(hw, R_PCM_MD0, M_PCM_MD); /* master mode */
1349 Write_hfc8(hw, R_RAM_MISC, M_FZ_MD); /* transmit fifo option */
1350 if (hw->driver_data.clock_mode == 1)
1351 Write_hfc8(hw, R_BRG_PCM_CFG, M_PCM_CLK); /* PCM clk / 2 */
1352 Write_hfc8(hw, R_TI_WD, TRANS_TIMER_MODE); /* timer interval */
1353
1354 memset(&hw->mr, 0, sizeof(hw->mr));
1355} /* chipreset */
1356
1357/********************************************/
1358/* disable/enable hardware in nt or te mode */
1359/********************************************/
1360void
1361hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
1362{
1363 u_long flags;
1364 char if_name[40];
1365 int i;
1366
1367 if (enable) {
1368 /* save system vars */
1369 hw->nt_mode = nt_mode;
1370
1371 /* enable fifo and state irqs, but not global irq enable */
1372 hw->mr.r_irq_ctrl = M_FIFO_IRQ;
1373 Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
1374 hw->mr.r_irqmsk_statchg = 0;
1375 Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg);
1376 Write_hfc8(hw, R_PWM_MD, 0x80);
1377 Write_hfc8(hw, R_PWM1, 26);
1378 if (!nt_mode)
1379 Write_hfc8(hw, R_ST_SYNC, M_AUTO_SYNC);
1380
1381 /* enable the line interfaces and fifos */
1382 for (i = 0; i < hw->driver_data.max_st_ports; i++) {
1383 hw->mr.r_irqmsk_statchg |= (1 << i);
1384 Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg);
1385 Write_hfc8(hw, R_ST_SEL, i);
1386 Write_hfc8(hw, A_ST_CLK_DLY,
1387 ((nt_mode) ? CLKDEL_NT : CLKDEL_TE));
1388 hw->mr.r_ctrl0 = ((nt_mode) ? CTRL0_NT : CTRL0_TE);
1389 Write_hfc8(hw, A_ST_CTRL0, hw->mr.r_ctrl0);
1390 Write_hfc8(hw, A_ST_CTRL2, 3);
1391 Write_hfc8(hw, A_ST_WR_STA, 0); /* enable state machine */
1392
1393 hw->l1[i].enabled = 1;
1394 hw->l1[i].nt_mode = nt_mode;
1395
1396 if (!nt_mode) {
1397 /* setup E-fifo */
1398 Write_hfc8(hw, R_FIFO, i * 8 + 7); /* E fifo */
1399 wait_busy(hw);
1400 Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */
1401 Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */
1402 Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */
1403 Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */
1404 wait_busy(hw);
1405
1406 /* setup D RX-fifo */
1407 Write_hfc8(hw, R_FIFO, i * 8 + 5); /* RX fifo */
1408 wait_busy(hw);
1409 Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */
1410 Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */
1411 Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */
1412 Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */
1413 wait_busy(hw);
1414
1415 /* setup D TX-fifo */
1416 Write_hfc8(hw, R_FIFO, i * 8 + 4); /* TX fifo */
1417 wait_busy(hw);
1418 Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */
1419 Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */
1420 Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */
1421 Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */
1422 wait_busy(hw);
1423 }
1424
1425 sprintf(if_name, "hfc4s8s_%d%d_", hw->cardnum, i);
1426
1427 if (hisax_register
1428 (&hw->l1[i].d_if, hw->l1[i].b_table, if_name,
1429 ((nt_mode) ? 3 : 2))) {
1430
1431 hw->l1[i].enabled = 0;
1432 hw->mr.r_irqmsk_statchg &= ~(1 << i);
1433 Write_hfc8(hw, R_SCI_MSK,
1434 hw->mr.r_irqmsk_statchg);
1435 printk(KERN_INFO
1436 "HFC-4S/8S: Unable to register S/T device %s, break\n",
1437 if_name);
1438 break;
1439 }
1440 }
1441 spin_lock_irqsave(&hw->lock, flags);
1442 hw->mr.r_irq_ctrl |= M_GLOB_IRQ_EN;
1443 Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
1444 spin_unlock_irqrestore(&hw->lock, flags);
1445 } else {
1446 /* disable hardware */
1447 spin_lock_irqsave(&hw->lock, flags);
1448 hw->mr.r_irq_ctrl &= ~M_GLOB_IRQ_EN;
1449 Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
1450 spin_unlock_irqrestore(&hw->lock, flags);
1451
1452 for (i = hw->driver_data.max_st_ports - 1; i >= 0; i--) {
1453 hw->l1[i].enabled = 0;
1454 hisax_unregister(&hw->l1[i].d_if);
1455 del_timer(&hw->l1[i].l1_timer);
1456 skb_queue_purge(&hw->l1[i].d_tx_queue);
1457 skb_queue_purge(&hw->l1[i].b_ch[0].tx_queue);
1458 skb_queue_purge(&hw->l1[i].b_ch[1].tx_queue);
1459 }
1460 chipreset(hw);
1461 }
1462} /* hfc_hardware_enable */
1463
1464/******************************************/
1465/* disable memory mapped ports / io ports */
1466/******************************************/
1467void
1468release_pci_ports(hfc4s8s_hw * hw)
1469{
1470 pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
1471#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
1472 if (hw->membase)
1473 iounmap((void *) hw->membase);
1474#else
1475 if (hw->iobase)
1476 release_region(hw->iobase, 8);
1477#endif
1478}
1479
1480/*****************************************/
1481/* enable memory mapped ports / io ports */
1482/*****************************************/
1483void
1484enable_pci_ports(hfc4s8s_hw * hw)
1485{
1486#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
1487 pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
1488#else
1489 pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_REGIO);
1490#endif
1491}
1492
1493/*************************************/
1494/* initialise the HFC-4s/8s hardware */
1495/* return 0 on success. */
1496/*************************************/
1497static int __devinit
1498setup_instance(hfc4s8s_hw * hw)
1499{
1500 int err = -EIO;
1501 int i;
1502
1503 for (i = 0; i < HFC_MAX_ST; i++) {
1504 struct hfc4s8s_l1 *l1p;
1505
1506 l1p = hw->l1 + i;
1507 spin_lock_init(&l1p->lock);
1508 l1p->hw = hw;
1509 l1p->l1_timer.function = (void *) hfc_l1_timer;
1510 l1p->l1_timer.data = (long) (l1p);
1511 init_timer(&l1p->l1_timer);
1512 l1p->st_num = i;
1513 skb_queue_head_init(&l1p->d_tx_queue);
1514 l1p->d_if.ifc.priv = hw->l1 + i;
1515 l1p->d_if.ifc.l2l1 = (void *) dch_l2l1;
1516
1517 spin_lock_init(&l1p->b_ch[0].lock);
1518 l1p->b_ch[0].b_if.ifc.l2l1 = (void *) bch_l2l1;
1519 l1p->b_ch[0].b_if.ifc.priv = (void *) &l1p->b_ch[0];
1520 l1p->b_ch[0].l1p = hw->l1 + i;
1521 l1p->b_ch[0].bchan = 1;
1522 l1p->b_table[0] = &l1p->b_ch[0].b_if;
1523 skb_queue_head_init(&l1p->b_ch[0].tx_queue);
1524
1525 spin_lock_init(&l1p->b_ch[1].lock);
1526 l1p->b_ch[1].b_if.ifc.l2l1 = (void *) bch_l2l1;
1527 l1p->b_ch[1].b_if.ifc.priv = (void *) &l1p->b_ch[1];
1528 l1p->b_ch[1].l1p = hw->l1 + i;
1529 l1p->b_ch[1].bchan = 2;
1530 l1p->b_table[1] = &l1p->b_ch[1].b_if;
1531 skb_queue_head_init(&l1p->b_ch[1].tx_queue);
1532 }
1533
1534 enable_pci_ports(hw);
1535 chipreset(hw);
1536
1537 i = Read_hfc8(hw, R_CHIP_ID) >> CHIP_ID_SHIFT;
1538 if (i != hw->driver_data.chip_id) {
1539 printk(KERN_INFO
1540 "HFC-4S/8S: invalid chip id 0x%x instead of 0x%x, card ignored\n",
1541 i, hw->driver_data.chip_id);
1542 goto out;
1543 }
1544
1545 i = Read_hfc8(hw, R_CHIP_RV) & 0xf;
1546 if (!i) {
1547 printk(KERN_INFO
1548 "HFC-4S/8S: chip revision 0 not supported, card ignored\n");
1549 goto out;
1550 }
1551
1552 INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw);
1553
1554 if (request_irq
1555 (hw->irq, hfc4s8s_interrupt, SA_SHIRQ, hw->card_name, hw)) {
1556 printk(KERN_INFO
1557 "HFC-4S/8S: unable to alloc irq %d, card ignored\n",
1558 hw->irq);
1559 goto out;
1560 }
1561#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
1562 printk(KERN_INFO
1563 "HFC-4S/8S: found PCI card at membase 0x%p, irq %d\n",
1564 hw->hw_membase, hw->irq);
1565#else
1566 printk(KERN_INFO
1567 "HFC-4S/8S: found PCI card at iobase 0x%x, irq %d\n",
1568 hw->iobase, hw->irq);
1569#endif
1570
1571 hfc_hardware_enable(hw, 1, 0);
1572
1573 return (0);
1574
1575 out:
1576 hw->irq = 0;
1577 release_pci_ports(hw);
1578 kfree(hw);
1579 return (err);
1580}
1581
1582/*****************************************/
1583/* PCI hotplug interface: probe new card */
1584/*****************************************/
1585static int __devinit
1586hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1587{
1588 int err = -ENOMEM;
1589 hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data;
1590 hfc4s8s_hw *hw;
1591
1592 if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) {
1593 printk(KERN_ERR "No kmem for HFC-4S/8S card\n");
1594 return (err);
1595 }
1596 memset(hw, 0, sizeof(hfc4s8s_hw));
1597
1598 hw->pdev = pdev;
1599 err = pci_enable_device(pdev);
1600
1601 if (err)
1602 goto out;
1603
1604 hw->cardnum = card_cnt;
1605 sprintf(hw->card_name, "hfc4s8s_%d", hw->cardnum);
1606 printk(KERN_INFO "HFC-4S/8S: found adapter %s (%s) at %s\n",
1607 driver_data->device_name, hw->card_name, pci_name(pdev));
1608
1609 spin_lock_init(&hw->lock);
1610
1611 hw->driver_data = *driver_data;
1612 hw->irq = pdev->irq;
1613 hw->iobase = pci_resource_start(pdev, 0);
1614
1615#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
1616 hw->hw_membase = (u_char *) pci_resource_start(pdev, 1);
1617 hw->membase = ioremap((ulong) hw->hw_membase, 256);
1618#else
1619 if (!request_region(hw->iobase, 8, hw->card_name)) {
1620 printk(KERN_INFO
1621 "HFC-4S/8S: failed to rquest address space at 0x%04x\n",
1622 hw->iobase);
1623 goto out;
1624 }
1625#endif
1626
1627 pci_set_drvdata(pdev, hw);
1628 err = setup_instance(hw);
1629 if (!err)
1630 card_cnt++;
1631 return (err);
1632
1633 out:
1634 kfree(hw);
1635 return (err);
1636}
1637
1638/**************************************/
1639/* PCI hotplug interface: remove card */
1640/**************************************/
1641static void __devexit
1642hfc4s8s_remove(struct pci_dev *pdev)
1643{
1644 hfc4s8s_hw *hw = pci_get_drvdata(pdev);
1645
1646 printk(KERN_INFO "HFC-4S/8S: removing card %d\n", hw->cardnum);
1647 hfc_hardware_enable(hw, 0, 0);
1648
1649 if (hw->irq)
1650 free_irq(hw->irq, hw);
1651 hw->irq = 0;
1652 release_pci_ports(hw);
1653
1654 card_cnt--;
1655 pci_disable_device(pdev);
1656 kfree(hw);
1657 return;
1658}
1659
1660static struct pci_driver hfc4s8s_driver = {
1661 name:"hfc4s8s_l1",
1662 probe:hfc4s8s_probe,
1663 remove:__devexit_p(hfc4s8s_remove),
1664 id_table:hfc4s8s_ids,
1665};
1666
1667/**********************/
1668/* driver Module init */
1669/**********************/
1670static int __init
1671hfc4s8s_module_init(void)
1672{
1673 int err;
1674
1675 printk(KERN_INFO
1676 "HFC-4S/8S: Layer 1 driver module for HFC-4S/8S isdn chips, %s\n",
1677 hfc4s8s_rev);
1678 printk(KERN_INFO
1679 "HFC-4S/8S: (C) 2003 Cornelius Consult, www.cornelius-consult.de\n");
1680
1681 card_cnt = 0;
1682
1683 err = pci_register_driver(&hfc4s8s_driver);
1684 if (err < 0) {
1685 goto out;
1686 }
1687 printk(KERN_INFO "HFC-4S/8S: found %d cards\n", card_cnt);
1688
1689#if !defined(CONFIG_HOTPLUG)
1690 if (err == 0) {
1691 err = -ENODEV;
1692 pci_unregister_driver(&hfc4s8s_driver);
1693 goto out;
1694 }
1695#endif
1696
1697 return 0;
1698 out:
1699 return (err);
1700} /* hfc4s8s_init_hw */
1701
1702/*************************************/
1703/* driver module exit : */
1704/* release the HFC-4s/8s hardware */
1705/*************************************/
1706static void
1707hfc4s8s_module_exit(void)
1708{
1709 pci_unregister_driver(&hfc4s8s_driver);
1710 printk(KERN_INFO "HFC-4S/8S: module removed\n");
1711} /* hfc4s8s_release_hw */
1712
1713module_init(hfc4s8s_module_init);
1714module_exit(hfc4s8s_module_exit);
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.h b/drivers/isdn/hisax/hfc4s8s_l1.h
new file mode 100644
index 00000000000..e8f9c077fa8
--- /dev/null
+++ b/drivers/isdn/hisax/hfc4s8s_l1.h
@@ -0,0 +1,88 @@
1/***************************************************************/
2/* $Id: hfc4s8s_l1.h,v 1.1 2005/02/02 17:28:55 martinb1 Exp $ */
3/* */
4/* This file is a minimal required extraction of hfc48scu.h */
5/* (Genero 3.2, HFC XML 1.7a for HFC-E1, HFC-4S and HFC-8S) */
6/* */
7/* To get this complete register description contact */
8/* Cologne Chip AG : */
9/* Internet: http://www.colognechip.com/ */
10/* E-Mail: info@colognechip.com */
11/***************************************************************/
12
13#ifndef _HFC4S8S_L1_H_
14#define _HFC4S8S_L1_H_
15
16
17/*
18* include Genero generated HFC-4S/8S header file hfc48scu.h
19* for comlete register description. This will define _HFC48SCU_H_
20* to prevent redefinitions
21*/
22
23// #include "hfc48scu.h"
24
25#ifndef _HFC48SCU_H_
26#define _HFC48SCU_H_
27
28#ifndef PCI_VENDOR_ID_CCD
29#define PCI_VENDOR_ID_CCD 0x1397
30#endif
31
32#define CHIP_ID_4S 0x0C
33#define CHIP_ID_8S 0x08
34#define PCI_DEVICE_ID_4S 0x08B4
35#define PCI_DEVICE_ID_8S 0x16B8
36
37#define R_IRQ_MISC 0x11
38#define M_TI_IRQ 0x02
39#define A_ST_RD_STA 0x30
40#define A_ST_WR_STA 0x30
41#define M_SET_G2_G3 0x80
42#define A_ST_CTRL0 0x31
43#define A_ST_CTRL2 0x33
44#define A_ST_CLK_DLY 0x37
45#define A_Z1 0x04
46#define A_Z2 0x06
47#define R_CIRM 0x00
48#define M_SRES 0x08
49#define R_CTRL 0x01
50#define R_BRG_PCM_CFG 0x02
51#define M_PCM_CLK 0x20
52#define R_RAM_MISC 0x0C
53#define M_FZ_MD 0x80
54#define R_FIFO_MD 0x0D
55#define A_INC_RES_FIFO 0x0E
56#define R_FIFO 0x0F
57#define A_F1 0x0C
58#define A_F2 0x0D
59#define R_IRQ_OVIEW 0x10
60#define R_CHIP_ID 0x16
61#define R_STATUS 0x1C
62#define M_BUSY 0x01
63#define M_MISC_IRQSTA 0x40
64#define M_FR_IRQSTA 0x80
65#define R_CHIP_RV 0x1F
66#define R_IRQ_CTRL 0x13
67#define M_FIFO_IRQ 0x01
68#define M_GLOB_IRQ_EN 0x08
69#define R_PCM_MD0 0x14
70#define M_PCM_MD 0x01
71#define A_FIFO_DATA0 0x80
72#define R_TI_WD 0x1A
73#define R_PWM1 0x39
74#define R_PWM_MD 0x46
75#define R_IRQ_FIFO_BL0 0xC8
76#define A_CON_HDLC 0xFA
77#define A_SUBCH_CFG 0xFB
78#define A_IRQ_MSK 0xFF
79#define R_SCI_MSK 0x12
80#define R_ST_SEL 0x16
81#define R_ST_SYNC 0x17
82#define M_AUTO_SYNC 0x08
83#define R_SCI 0x12
84#define R_IRQMSK_MISC 0x11
85#define M_TI_IRQMSK 0x02
86
87#endif /* _HFC4S8S_L1_H_ */
88#endif /* _HFC48SCU_H_ */
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
new file mode 100644
index 00000000000..ebea3feef00
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -0,0 +1,1082 @@
1/* $Id: hfc_2bds0.c,v 1.18.2.6 2004/02/11 13:21:33 keil Exp $
2 *
3 * specific routines for CCD's HFC 2BDS0
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "hfc_2bds0.h"
16#include "isdnl1.h"
17#include <linux/interrupt.h>
18/*
19#define KDEBUG_DEF
20#include "kdebug.h"
21*/
22
23#define byteout(addr,val) outb(val,addr)
24#define bytein(addr) inb(addr)
25
26static void
27dummyf(struct IsdnCardState *cs, u_char * data, int size)
28{
29 printk(KERN_WARNING "HiSax: hfcd dummy fifo called\n");
30}
31
32static inline u_char
33ReadReg(struct IsdnCardState *cs, int data, u_char reg)
34{
35 register u_char ret;
36
37 if (data) {
38 if (cs->hw.hfcD.cip != reg) {
39 cs->hw.hfcD.cip = reg;
40 byteout(cs->hw.hfcD.addr | 1, reg);
41 }
42 ret = bytein(cs->hw.hfcD.addr);
43#ifdef HFC_REG_DEBUG
44 if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
45 debugl1(cs, "t3c RD %02x %02x", reg, ret);
46#endif
47 } else
48 ret = bytein(cs->hw.hfcD.addr | 1);
49 return (ret);
50}
51
52static inline void
53WriteReg(struct IsdnCardState *cs, int data, u_char reg, u_char value)
54{
55 if (cs->hw.hfcD.cip != reg) {
56 cs->hw.hfcD.cip = reg;
57 byteout(cs->hw.hfcD.addr | 1, reg);
58 }
59 if (data)
60 byteout(cs->hw.hfcD.addr, value);
61#ifdef HFC_REG_DEBUG
62 if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB))
63 debugl1(cs, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
64#endif
65}
66
67/* Interface functions */
68
69static u_char
70readreghfcd(struct IsdnCardState *cs, u_char offset)
71{
72 return(ReadReg(cs, HFCD_DATA, offset));
73}
74
75static void
76writereghfcd(struct IsdnCardState *cs, u_char offset, u_char value)
77{
78 WriteReg(cs, HFCD_DATA, offset, value);
79}
80
81static inline int
82WaitForBusy(struct IsdnCardState *cs)
83{
84 int to = 130;
85
86 while (!(ReadReg(cs, HFCD_DATA, HFCD_STAT) & HFCD_BUSY) && to) {
87 udelay(1);
88 to--;
89 }
90 if (!to)
91 printk(KERN_WARNING "HiSax: WaitForBusy timeout\n");
92 return (to);
93}
94
95static inline int
96WaitNoBusy(struct IsdnCardState *cs)
97{
98 int to = 130;
99
100 while ((ReadReg(cs, HFCD_STATUS, HFCD_STATUS) & HFCD_BUSY) && to) {
101 udelay(1);
102 to--;
103 }
104 if (!to)
105 printk(KERN_WARNING "HiSax: WaitNoBusy timeout\n");
106 return (to);
107}
108
109static int
110SelFiFo(struct IsdnCardState *cs, u_char FiFo)
111{
112 u_char cip;
113
114 if (cs->hw.hfcD.fifo == FiFo)
115 return(1);
116 switch(FiFo) {
117 case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1;
118 break;
119 case 1: cip = HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_B1;
120 break;
121 case 2: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B2;
122 break;
123 case 3: cip = HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_B2;
124 break;
125 case 4: cip = HFCD_FIFO | HFCD_Z1 | HFCD_SEND;
126 break;
127 case 5: cip = HFCD_FIFO | HFCD_Z1 | HFCD_REC;
128 break;
129 default:
130 debugl1(cs, "SelFiFo Error");
131 return(0);
132 }
133 cs->hw.hfcD.fifo = FiFo;
134 WaitNoBusy(cs);
135 cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0);
136 WaitForBusy(cs);
137 return(2);
138}
139
140static int
141GetFreeFifoBytes_B(struct BCState *bcs)
142{
143 int s;
144
145 if (bcs->hw.hfc.f1 == bcs->hw.hfc.f2)
146 return (bcs->cs->hw.hfcD.bfifosize);
147 s = bcs->hw.hfc.send[bcs->hw.hfc.f1] - bcs->hw.hfc.send[bcs->hw.hfc.f2];
148 if (s <= 0)
149 s += bcs->cs->hw.hfcD.bfifosize;
150 s = bcs->cs->hw.hfcD.bfifosize - s;
151 return (s);
152}
153
154static int
155GetFreeFifoBytes_D(struct IsdnCardState *cs)
156{
157 int s;
158
159 if (cs->hw.hfcD.f1 == cs->hw.hfcD.f2)
160 return (cs->hw.hfcD.dfifosize);
161 s = cs->hw.hfcD.send[cs->hw.hfcD.f1] - cs->hw.hfcD.send[cs->hw.hfcD.f2];
162 if (s <= 0)
163 s += cs->hw.hfcD.dfifosize;
164 s = cs->hw.hfcD.dfifosize - s;
165 return (s);
166}
167
168static int
169ReadZReg(struct IsdnCardState *cs, u_char reg)
170{
171 int val;
172
173 WaitNoBusy(cs);
174 val = 256 * ReadReg(cs, HFCD_DATA, reg | HFCB_Z_HIGH);
175 WaitNoBusy(cs);
176 val += ReadReg(cs, HFCD_DATA, reg | HFCB_Z_LOW);
177 return (val);
178}
179
180static struct sk_buff
181*hfc_empty_fifo(struct BCState *bcs, int count)
182{
183 u_char *ptr;
184 struct sk_buff *skb;
185 struct IsdnCardState *cs = bcs->cs;
186 int idx;
187 int chksum;
188 u_char stat, cip;
189
190 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
191 debugl1(cs, "hfc_empty_fifo");
192 idx = 0;
193 if (count > HSCX_BUFMAX + 3) {
194 if (cs->debug & L1_DEB_WARN)
195 debugl1(cs, "hfc_empty_fifo: incoming packet too large");
196 cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
197 while (idx++ < count) {
198 WaitNoBusy(cs);
199 ReadReg(cs, HFCD_DATA_NODEB, cip);
200 }
201 skb = NULL;
202 } else if (count < 4) {
203 if (cs->debug & L1_DEB_WARN)
204 debugl1(cs, "hfc_empty_fifo: incoming packet too small");
205 cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
206#ifdef ERROR_STATISTIC
207 bcs->err_inv++;
208#endif
209 while ((idx++ < count) && WaitNoBusy(cs))
210 ReadReg(cs, HFCD_DATA_NODEB, cip);
211 skb = NULL;
212 } else if (!(skb = dev_alloc_skb(count - 3)))
213 printk(KERN_WARNING "HFC: receive out of memory\n");
214 else {
215 ptr = skb_put(skb, count - 3);
216 idx = 0;
217 cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
218 while (idx < (count - 3)) {
219 if (!WaitNoBusy(cs))
220 break;
221 *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip);
222 ptr++;
223 idx++;
224 }
225 if (idx != count - 3) {
226 debugl1(cs, "RFIFO BUSY error");
227 printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
228 dev_kfree_skb_irq(skb);
229 skb = NULL;
230 } else {
231 WaitNoBusy(cs);
232 chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);
233 WaitNoBusy(cs);
234 chksum += ReadReg(cs, HFCD_DATA, cip);
235 WaitNoBusy(cs);
236 stat = ReadReg(cs, HFCD_DATA, cip);
237 if (cs->debug & L1_DEB_HSCX)
238 debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
239 bcs->channel, chksum, stat);
240 if (stat) {
241 debugl1(cs, "FIFO CRC error");
242 dev_kfree_skb_irq(skb);
243 skb = NULL;
244#ifdef ERROR_STATISTIC
245 bcs->err_crc++;
246#endif
247 }
248 }
249 }
250 WaitForBusy(cs);
251 WaitNoBusy(cs);
252 stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC |
253 HFCB_REC | HFCB_CHANNEL(bcs->channel));
254 WaitForBusy(cs);
255 return (skb);
256}
257
258static void
259hfc_fill_fifo(struct BCState *bcs)
260{
261 struct IsdnCardState *cs = bcs->cs;
262 int idx, fcnt;
263 int count;
264 u_char cip;
265
266 if (!bcs->tx_skb)
267 return;
268 if (bcs->tx_skb->len <= 0)
269 return;
270 SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel));
271 cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
272 WaitNoBusy(cs);
273 bcs->hw.hfc.f1 = ReadReg(cs, HFCD_DATA, cip);
274 WaitNoBusy(cs);
275 cip = HFCB_FIFO | HFCB_F2 | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
276 WaitNoBusy(cs);
277 bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip);
278 bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
279 if (cs->debug & L1_DEB_HSCX)
280 debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
281 bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
282 bcs->hw.hfc.send[bcs->hw.hfc.f1]);
283 fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
284 if (fcnt < 0)
285 fcnt += 32;
286 if (fcnt > 30) {
287 if (cs->debug & L1_DEB_HSCX)
288 debugl1(cs, "hfc_fill_fifo more as 30 frames");
289 return;
290 }
291 count = GetFreeFifoBytes_B(bcs);
292 if (cs->debug & L1_DEB_HSCX)
293 debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx",
294 bcs->channel, bcs->tx_skb->len,
295 count, current->state);
296 if (count < bcs->tx_skb->len) {
297 if (cs->debug & L1_DEB_HSCX)
298 debugl1(cs, "hfc_fill_fifo no fifo mem");
299 return;
300 }
301 cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
302 idx = 0;
303 WaitForBusy(cs);
304 WaitNoBusy(cs);
305 WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
306 while (idx < bcs->tx_skb->len) {
307 if (!WaitNoBusy(cs))
308 break;
309 WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]);
310 idx++;
311 }
312 if (idx != bcs->tx_skb->len) {
313 debugl1(cs, "FIFO Send BUSY error");
314 printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
315 } else {
316 bcs->tx_cnt -= bcs->tx_skb->len;
317 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
318 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
319 u_long flags;
320 spin_lock_irqsave(&bcs->aclock, flags);
321 bcs->ackcnt += bcs->tx_skb->len;
322 spin_unlock_irqrestore(&bcs->aclock, flags);
323 schedule_event(bcs, B_ACKPENDING);
324 }
325 dev_kfree_skb_any(bcs->tx_skb);
326 bcs->tx_skb = NULL;
327 }
328 WaitForBusy(cs);
329 WaitNoBusy(cs);
330 ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
331 WaitForBusy(cs);
332 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
333 return;
334}
335
336static void
337hfc_send_data(struct BCState *bcs)
338{
339 struct IsdnCardState *cs = bcs->cs;
340
341 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
342 hfc_fill_fifo(bcs);
343 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
344 } else
345 debugl1(cs,"send_data %d blocked", bcs->channel);
346}
347
348void
349main_rec_2bds0(struct BCState *bcs)
350{
351 struct IsdnCardState *cs = bcs->cs;
352 int z1, z2, rcnt;
353 u_char f1, f2, cip;
354 int receive, count = 5;
355 struct sk_buff *skb;
356
357 Begin:
358 count--;
359 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
360 debugl1(cs,"rec_data %d blocked", bcs->channel);
361 return;
362 }
363 SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel));
364 cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel);
365 WaitNoBusy(cs);
366 f1 = ReadReg(cs, HFCD_DATA, cip);
367 cip = HFCB_FIFO | HFCB_F2 | HFCB_REC | HFCB_CHANNEL(bcs->channel);
368 WaitNoBusy(cs);
369 f2 = ReadReg(cs, HFCD_DATA, cip);
370 if (f1 != f2) {
371 if (cs->debug & L1_DEB_HSCX)
372 debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
373 bcs->channel, f1, f2);
374 z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
375 z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
376 rcnt = z1 - z2;
377 if (rcnt < 0)
378 rcnt += cs->hw.hfcD.bfifosize;
379 rcnt++;
380 if (cs->debug & L1_DEB_HSCX)
381 debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
382 bcs->channel, z1, z2, rcnt);
383 if ((skb = hfc_empty_fifo(bcs, rcnt))) {
384 skb_queue_tail(&bcs->rqueue, skb);
385 schedule_event(bcs, B_RCVBUFREADY);
386 }
387 rcnt = f1 -f2;
388 if (rcnt<0)
389 rcnt += 32;
390 if (rcnt>1)
391 receive = 1;
392 else
393 receive = 0;
394 } else
395 receive = 0;
396 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
397 if (count && receive)
398 goto Begin;
399 return;
400}
401
402void
403mode_2bs0(struct BCState *bcs, int mode, int bc)
404{
405 struct IsdnCardState *cs = bcs->cs;
406
407 if (cs->debug & L1_DEB_HSCX)
408 debugl1(cs, "HFCD bchannel mode %d bchan %d/%d",
409 mode, bc, bcs->channel);
410 bcs->mode = mode;
411 bcs->channel = bc;
412 switch (mode) {
413 case (L1_MODE_NULL):
414 if (bc) {
415 cs->hw.hfcD.conn |= 0x18;
416 cs->hw.hfcD.sctrl &= ~SCTRL_B2_ENA;
417 } else {
418 cs->hw.hfcD.conn |= 0x3;
419 cs->hw.hfcD.sctrl &= ~SCTRL_B1_ENA;
420 }
421 break;
422 case (L1_MODE_TRANS):
423 if (bc) {
424 cs->hw.hfcD.ctmt |= 2;
425 cs->hw.hfcD.conn &= ~0x18;
426 cs->hw.hfcD.sctrl |= SCTRL_B2_ENA;
427 } else {
428 cs->hw.hfcD.ctmt |= 1;
429 cs->hw.hfcD.conn &= ~0x3;
430 cs->hw.hfcD.sctrl |= SCTRL_B1_ENA;
431 }
432 break;
433 case (L1_MODE_HDLC):
434 if (bc) {
435 cs->hw.hfcD.ctmt &= ~2;
436 cs->hw.hfcD.conn &= ~0x18;
437 cs->hw.hfcD.sctrl |= SCTRL_B2_ENA;
438 } else {
439 cs->hw.hfcD.ctmt &= ~1;
440 cs->hw.hfcD.conn &= ~0x3;
441 cs->hw.hfcD.sctrl |= SCTRL_B1_ENA;
442 }
443 break;
444 }
445 WriteReg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
446 WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
447 WriteReg(cs, HFCD_DATA, HFCD_CONN, cs->hw.hfcD.conn);
448}
449
450static void
451hfc_l2l1(struct PStack *st, int pr, void *arg)
452{
453 struct BCState *bcs = st->l1.bcs;
454 struct sk_buff *skb = arg;
455 u_long flags;
456
457 switch (pr) {
458 case (PH_DATA | REQUEST):
459 spin_lock_irqsave(&bcs->cs->lock, flags);
460 if (bcs->tx_skb) {
461 skb_queue_tail(&bcs->squeue, skb);
462 } else {
463 bcs->tx_skb = skb;
464// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
465 bcs->cs->BC_Send_Data(bcs);
466 }
467 spin_unlock_irqrestore(&bcs->cs->lock, flags);
468 break;
469 case (PH_PULL | INDICATION):
470 spin_lock_irqsave(&bcs->cs->lock, flags);
471 if (bcs->tx_skb) {
472 printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
473 } else {
474// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
475 bcs->tx_skb = skb;
476 bcs->cs->BC_Send_Data(bcs);
477 }
478 spin_unlock_irqrestore(&bcs->cs->lock, flags);
479 break;
480 case (PH_PULL | REQUEST):
481 if (!bcs->tx_skb) {
482 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
483 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
484 } else
485 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
486 break;
487 case (PH_ACTIVATE | REQUEST):
488 spin_lock_irqsave(&bcs->cs->lock, flags);
489 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
490 mode_2bs0(bcs, st->l1.mode, st->l1.bc);
491 spin_unlock_irqrestore(&bcs->cs->lock, flags);
492 l1_msg_b(st, pr, arg);
493 break;
494 case (PH_DEACTIVATE | REQUEST):
495 l1_msg_b(st, pr, arg);
496 break;
497 case (PH_DEACTIVATE | CONFIRM):
498 spin_lock_irqsave(&bcs->cs->lock, flags);
499 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
500 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
501 mode_2bs0(bcs, 0, st->l1.bc);
502 spin_unlock_irqrestore(&bcs->cs->lock, flags);
503 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
504 break;
505 }
506}
507
508void
509close_2bs0(struct BCState *bcs)
510{
511 mode_2bs0(bcs, 0, bcs->channel);
512 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
513 skb_queue_purge(&bcs->rqueue);
514 skb_queue_purge(&bcs->squeue);
515 if (bcs->tx_skb) {
516 dev_kfree_skb_any(bcs->tx_skb);
517 bcs->tx_skb = NULL;
518 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
519 }
520 }
521}
522
523static int
524open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
525{
526 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
527 skb_queue_head_init(&bcs->rqueue);
528 skb_queue_head_init(&bcs->squeue);
529 }
530 bcs->tx_skb = NULL;
531 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
532 bcs->event = 0;
533 bcs->tx_cnt = 0;
534 return (0);
535}
536
537int
538setstack_2b(struct PStack *st, struct BCState *bcs)
539{
540 bcs->channel = st->l1.bc;
541 if (open_hfcstate(st->l1.hardware, bcs))
542 return (-1);
543 st->l1.bcs = bcs;
544 st->l2.l2l1 = hfc_l2l1;
545 setstack_manager(st);
546 bcs->st = st;
547 setstack_l1_B(st);
548 return (0);
549}
550
551static void
552hfcd_bh(struct IsdnCardState *cs)
553{
554 if (!cs)
555 return;
556 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
557 switch (cs->dc.hfcd.ph_state) {
558 case (0):
559 l1_msg(cs, HW_RESET | INDICATION, NULL);
560 break;
561 case (3):
562 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
563 break;
564 case (8):
565 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
566 break;
567 case (6):
568 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
569 break;
570 case (7):
571 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
572 break;
573 default:
574 break;
575 }
576 }
577 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
578 DChannel_proc_rcv(cs);
579 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
580 DChannel_proc_xmt(cs);
581}
582
583static
584int receive_dmsg(struct IsdnCardState *cs)
585{
586 struct sk_buff *skb;
587 int idx;
588 int rcnt, z1, z2;
589 u_char stat, cip, f1, f2;
590 int chksum;
591 int count=5;
592 u_char *ptr;
593
594 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
595 debugl1(cs, "rec_dmsg blocked");
596 return(1);
597 }
598 SelFiFo(cs, 4 | HFCD_REC);
599 cip = HFCD_FIFO | HFCD_F1 | HFCD_REC;
600 WaitNoBusy(cs);
601 f1 = cs->readisac(cs, cip) & 0xf;
602 cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;
603 WaitNoBusy(cs);
604 f2 = cs->readisac(cs, cip) & 0xf;
605 while ((f1 != f2) && count--) {
606 z1 = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_REC);
607 z2 = ReadZReg(cs, HFCD_FIFO | HFCD_Z2 | HFCD_REC);
608 rcnt = z1 - z2;
609 if (rcnt < 0)
610 rcnt += cs->hw.hfcD.dfifosize;
611 rcnt++;
612 if (cs->debug & L1_DEB_ISAC)
613 debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
614 f1, f2, z1, z2, rcnt);
615 idx = 0;
616 cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;
617 if (rcnt > MAX_DFRAME_LEN + 3) {
618 if (cs->debug & L1_DEB_WARN)
619 debugl1(cs, "empty_fifo d: incoming packet too large");
620 while (idx < rcnt) {
621 if (!(WaitNoBusy(cs)))
622 break;
623 ReadReg(cs, HFCD_DATA_NODEB, cip);
624 idx++;
625 }
626 } else if (rcnt < 4) {
627 if (cs->debug & L1_DEB_WARN)
628 debugl1(cs, "empty_fifo d: incoming packet too small");
629 while ((idx++ < rcnt) && WaitNoBusy(cs))
630 ReadReg(cs, HFCD_DATA_NODEB, cip);
631 } else if ((skb = dev_alloc_skb(rcnt - 3))) {
632 ptr = skb_put(skb, rcnt - 3);
633 while (idx < (rcnt - 3)) {
634 if (!(WaitNoBusy(cs)))
635 break;
636 *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip);
637 idx++;
638 ptr++;
639 }
640 if (idx != (rcnt - 3)) {
641 debugl1(cs, "RFIFO D BUSY error");
642 printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");
643 dev_kfree_skb_irq(skb);
644 skb = NULL;
645#ifdef ERROR_STATISTIC
646 cs->err_rx++;
647#endif
648 } else {
649 WaitNoBusy(cs);
650 chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);
651 WaitNoBusy(cs);
652 chksum += ReadReg(cs, HFCD_DATA, cip);
653 WaitNoBusy(cs);
654 stat = ReadReg(cs, HFCD_DATA, cip);
655 if (cs->debug & L1_DEB_ISAC)
656 debugl1(cs, "empty_dfifo chksum %x stat %x",
657 chksum, stat);
658 if (stat) {
659 debugl1(cs, "FIFO CRC error");
660 dev_kfree_skb_irq(skb);
661 skb = NULL;
662#ifdef ERROR_STATISTIC
663 cs->err_crc++;
664#endif
665 } else {
666 skb_queue_tail(&cs->rq, skb);
667 schedule_event(cs, D_RCVBUFREADY);
668 }
669 }
670 } else
671 printk(KERN_WARNING "HFC: D receive out of memory\n");
672 WaitForBusy(cs);
673 cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC;
674 WaitNoBusy(cs);
675 stat = ReadReg(cs, HFCD_DATA, cip);
676 WaitForBusy(cs);
677 cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;
678 WaitNoBusy(cs);
679 f2 = cs->readisac(cs, cip) & 0xf;
680 }
681 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
682 return(1);
683}
684
685static void
686hfc_fill_dfifo(struct IsdnCardState *cs)
687{
688 int idx, fcnt;
689 int count;
690 u_char cip;
691
692 if (!cs->tx_skb)
693 return;
694 if (cs->tx_skb->len <= 0)
695 return;
696
697 SelFiFo(cs, 4 | HFCD_SEND);
698 cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND;
699 WaitNoBusy(cs);
700 cs->hw.hfcD.f1 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
701 WaitNoBusy(cs);
702 cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND;
703 cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
704 cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);
705 if (cs->debug & L1_DEB_ISAC)
706 debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
707 cs->hw.hfcD.f1, cs->hw.hfcD.f2,
708 cs->hw.hfcD.send[cs->hw.hfcD.f1]);
709 fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2;
710 if (fcnt < 0)
711 fcnt += 16;
712 if (fcnt > 14) {
713 if (cs->debug & L1_DEB_HSCX)
714 debugl1(cs, "hfc_fill_Dfifo more as 14 frames");
715 return;
716 }
717 count = GetFreeFifoBytes_D(cs);
718 if (cs->debug & L1_DEB_ISAC)
719 debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)",
720 cs->tx_skb->len, count);
721 if (count < cs->tx_skb->len) {
722 if (cs->debug & L1_DEB_ISAC)
723 debugl1(cs, "hfc_fill_Dfifo no fifo mem");
724 return;
725 }
726 cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND;
727 idx = 0;
728 WaitForBusy(cs);
729 WaitNoBusy(cs);
730 WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]);
731 while (idx < cs->tx_skb->len) {
732 if (!(WaitNoBusy(cs)))
733 break;
734 WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]);
735 idx++;
736 }
737 if (idx != cs->tx_skb->len) {
738 debugl1(cs, "DFIFO Send BUSY error");
739 printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n");
740 }
741 WaitForBusy(cs);
742 WaitNoBusy(cs);
743 ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);
744 dev_kfree_skb_any(cs->tx_skb);
745 cs->tx_skb = NULL;
746 WaitForBusy(cs);
747 return;
748}
749
750static
751struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
752{
753 if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
754 return(&cs->bcs[0]);
755 else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
756 return(&cs->bcs[1]);
757 else
758 return(NULL);
759}
760
761void
762hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
763{
764 u_char exval;
765 struct BCState *bcs;
766 int count=15;
767
768 if (cs->debug & L1_DEB_ISAC)
769 debugl1(cs, "HFCD irq %x %s", val,
770 test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
771 "locked" : "unlocked");
772 val &= cs->hw.hfcD.int_m1;
773 if (val & 0x40) { /* TE state machine irq */
774 exval = cs->readisac(cs, HFCD_STATES) & 0xf;
775 if (cs->debug & L1_DEB_ISAC)
776 debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,
777 exval);
778 cs->dc.hfcd.ph_state = exval;
779 schedule_event(cs, D_L1STATECHANGE);
780 val &= ~0x40;
781 }
782 while (val) {
783 if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
784 cs->hw.hfcD.int_s1 |= val;
785 return;
786 }
787 if (cs->hw.hfcD.int_s1 & 0x18) {
788 exval = val;
789 val = cs->hw.hfcD.int_s1;
790 cs->hw.hfcD.int_s1 = exval;
791 }
792 if (val & 0x08) {
793 if (!(bcs=Sel_BCS(cs, 0))) {
794 if (cs->debug)
795 debugl1(cs, "hfcd spurious 0x08 IRQ");
796 } else
797 main_rec_2bds0(bcs);
798 }
799 if (val & 0x10) {
800 if (!(bcs=Sel_BCS(cs, 1))) {
801 if (cs->debug)
802 debugl1(cs, "hfcd spurious 0x10 IRQ");
803 } else
804 main_rec_2bds0(bcs);
805 }
806 if (val & 0x01) {
807 if (!(bcs=Sel_BCS(cs, 0))) {
808 if (cs->debug)
809 debugl1(cs, "hfcd spurious 0x01 IRQ");
810 } else {
811 if (bcs->tx_skb) {
812 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
813 hfc_fill_fifo(bcs);
814 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
815 } else
816 debugl1(cs,"fill_data %d blocked", bcs->channel);
817 } else {
818 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
819 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
820 hfc_fill_fifo(bcs);
821 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
822 } else
823 debugl1(cs,"fill_data %d blocked", bcs->channel);
824 } else {
825 schedule_event(bcs, B_XMTBUFREADY);
826 }
827 }
828 }
829 }
830 if (val & 0x02) {
831 if (!(bcs=Sel_BCS(cs, 1))) {
832 if (cs->debug)
833 debugl1(cs, "hfcd spurious 0x02 IRQ");
834 } else {
835 if (bcs->tx_skb) {
836 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
837 hfc_fill_fifo(bcs);
838 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
839 } else
840 debugl1(cs,"fill_data %d blocked", bcs->channel);
841 } else {
842 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
843 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
844 hfc_fill_fifo(bcs);
845 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
846 } else
847 debugl1(cs,"fill_data %d blocked", bcs->channel);
848 } else {
849 schedule_event(bcs, B_XMTBUFREADY);
850 }
851 }
852 }
853 }
854 if (val & 0x20) { /* receive dframe */
855 receive_dmsg(cs);
856 }
857 if (val & 0x04) { /* dframe transmitted */
858 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
859 del_timer(&cs->dbusytimer);
860 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
861 schedule_event(cs, D_CLEARBUSY);
862 if (cs->tx_skb) {
863 if (cs->tx_skb->len) {
864 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
865 hfc_fill_dfifo(cs);
866 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
867 } else {
868 debugl1(cs, "hfc_fill_dfifo irq blocked");
869 }
870 goto afterXPR;
871 } else {
872 dev_kfree_skb_irq(cs->tx_skb);
873 cs->tx_cnt = 0;
874 cs->tx_skb = NULL;
875 }
876 }
877 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
878 cs->tx_cnt = 0;
879 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
880 hfc_fill_dfifo(cs);
881 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
882 } else {
883 debugl1(cs, "hfc_fill_dfifo irq blocked");
884 }
885 } else
886 schedule_event(cs, D_XMTBUFREADY);
887 }
888 afterXPR:
889 if (cs->hw.hfcD.int_s1 && count--) {
890 val = cs->hw.hfcD.int_s1;
891 cs->hw.hfcD.int_s1 = 0;
892 if (cs->debug & L1_DEB_ISAC)
893 debugl1(cs, "HFCD irq %x loop %d", val, 15-count);
894 } else
895 val = 0;
896 }
897}
898
899static void
900HFCD_l1hw(struct PStack *st, int pr, void *arg)
901{
902 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
903 struct sk_buff *skb = arg;
904 u_long flags;
905
906 switch (pr) {
907 case (PH_DATA | REQUEST):
908 if (cs->debug & DEB_DLOG_HEX)
909 LogFrame(cs, skb->data, skb->len);
910 if (cs->debug & DEB_DLOG_VERBOSE)
911 dlogframe(cs, skb, 0);
912 spin_lock_irqsave(&cs->lock, flags);
913 if (cs->tx_skb) {
914 skb_queue_tail(&cs->sq, skb);
915#ifdef L2FRAME_DEBUG /* psa */
916 if (cs->debug & L1_DEB_LAPD)
917 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
918#endif
919 } else {
920 cs->tx_skb = skb;
921 cs->tx_cnt = 0;
922#ifdef L2FRAME_DEBUG /* psa */
923 if (cs->debug & L1_DEB_LAPD)
924 Logl2Frame(cs, skb, "PH_DATA", 0);
925#endif
926 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
927 hfc_fill_dfifo(cs);
928 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
929 } else
930 debugl1(cs, "hfc_fill_dfifo blocked");
931
932 }
933 spin_unlock_irqrestore(&cs->lock, flags);
934 break;
935 case (PH_PULL | INDICATION):
936 spin_lock_irqsave(&cs->lock, flags);
937 if (cs->tx_skb) {
938 if (cs->debug & L1_DEB_WARN)
939 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
940 skb_queue_tail(&cs->sq, skb);
941 spin_unlock_irqrestore(&cs->lock, flags);
942 break;
943 }
944 if (cs->debug & DEB_DLOG_HEX)
945 LogFrame(cs, skb->data, skb->len);
946 if (cs->debug & DEB_DLOG_VERBOSE)
947 dlogframe(cs, skb, 0);
948 cs->tx_skb = skb;
949 cs->tx_cnt = 0;
950#ifdef L2FRAME_DEBUG /* psa */
951 if (cs->debug & L1_DEB_LAPD)
952 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
953#endif
954 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
955 hfc_fill_dfifo(cs);
956 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
957 } else
958 debugl1(cs, "hfc_fill_dfifo blocked");
959 spin_unlock_irqrestore(&cs->lock, flags);
960 break;
961 case (PH_PULL | REQUEST):
962#ifdef L2FRAME_DEBUG /* psa */
963 if (cs->debug & L1_DEB_LAPD)
964 debugl1(cs, "-> PH_REQUEST_PULL");
965#endif
966 if (!cs->tx_skb) {
967 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
968 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
969 } else
970 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
971 break;
972 case (HW_RESET | REQUEST):
973 spin_lock_irqsave(&cs->lock, flags);
974 cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
975 udelay(6);
976 cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */
977 cs->hw.hfcD.mst_m |= HFCD_MASTER;
978 cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
979 cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
980 spin_unlock_irqrestore(&cs->lock, flags);
981 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
982 break;
983 case (HW_ENABLE | REQUEST):
984 spin_lock_irqsave(&cs->lock, flags);
985 cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
986 spin_unlock_irqrestore(&cs->lock, flags);
987 break;
988 case (HW_DEACTIVATE | REQUEST):
989 spin_lock_irqsave(&cs->lock, flags);
990 cs->hw.hfcD.mst_m &= ~HFCD_MASTER;
991 cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
992 spin_unlock_irqrestore(&cs->lock, flags);
993 break;
994 case (HW_INFO3 | REQUEST):
995 spin_lock_irqsave(&cs->lock, flags);
996 cs->hw.hfcD.mst_m |= HFCD_MASTER;
997 cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
998 spin_unlock_irqrestore(&cs->lock, flags);
999 break;
1000 default:
1001 if (cs->debug & L1_DEB_WARN)
1002 debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
1003 break;
1004 }
1005}
1006
1007void
1008setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
1009{
1010 st->l1.l1hw = HFCD_l1hw;
1011}
1012
1013static void
1014hfc_dbusy_timer(struct IsdnCardState *cs)
1015{
1016}
1017
1018unsigned int __init
1019*init_send_hfcd(int cnt)
1020{
1021 int i, *send;
1022
1023 if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) {
1024 printk(KERN_WARNING
1025 "HiSax: No memory for hfcd.send\n");
1026 return(NULL);
1027 }
1028 for (i = 0; i < cnt; i++)
1029 send[i] = 0x1fff;
1030 return(send);
1031}
1032
1033void __init
1034init2bds0(struct IsdnCardState *cs)
1035{
1036 cs->setstack_d = setstack_hfcd;
1037 if (!cs->hw.hfcD.send)
1038 cs->hw.hfcD.send = init_send_hfcd(16);
1039 if (!cs->bcs[0].hw.hfc.send)
1040 cs->bcs[0].hw.hfc.send = init_send_hfcd(32);
1041 if (!cs->bcs[1].hw.hfc.send)
1042 cs->bcs[1].hw.hfc.send = init_send_hfcd(32);
1043 cs->BC_Send_Data = &hfc_send_data;
1044 cs->bcs[0].BC_SetStack = setstack_2b;
1045 cs->bcs[1].BC_SetStack = setstack_2b;
1046 cs->bcs[0].BC_Close = close_2bs0;
1047 cs->bcs[1].BC_Close = close_2bs0;
1048 mode_2bs0(cs->bcs, 0, 0);
1049 mode_2bs0(cs->bcs + 1, 0, 1);
1050}
1051
1052void
1053release2bds0(struct IsdnCardState *cs)
1054{
1055 if (cs->bcs[0].hw.hfc.send) {
1056 kfree(cs->bcs[0].hw.hfc.send);
1057 cs->bcs[0].hw.hfc.send = NULL;
1058 }
1059 if (cs->bcs[1].hw.hfc.send) {
1060 kfree(cs->bcs[1].hw.hfc.send);
1061 cs->bcs[1].hw.hfc.send = NULL;
1062 }
1063 if (cs->hw.hfcD.send) {
1064 kfree(cs->hw.hfcD.send);
1065 cs->hw.hfcD.send = NULL;
1066 }
1067}
1068
1069void
1070set_cs_func(struct IsdnCardState *cs)
1071{
1072 cs->readisac = &readreghfcd;
1073 cs->writeisac = &writereghfcd;
1074 cs->readisacfifo = &dummyf;
1075 cs->writeisacfifo = &dummyf;
1076 cs->BC_Read_Reg = &ReadReg;
1077 cs->BC_Write_Reg = &WriteReg;
1078 cs->dbusytimer.function = (void *) hfc_dbusy_timer;
1079 cs->dbusytimer.data = (long) cs;
1080 init_timer(&cs->dbusytimer);
1081 INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs);
1082}
diff --git a/drivers/isdn/hisax/hfc_2bds0.h b/drivers/isdn/hisax/hfc_2bds0.h
new file mode 100644
index 00000000000..30f1924db91
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_2bds0.h
@@ -0,0 +1,128 @@
1/* $Id: hfc_2bds0.h,v 1.6.2.2 2004/01/12 22:52:26 keil Exp $
2 *
3 * specific defines for CCD's HFC 2BDS0
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#define HFCD_CIRM 0x18
14#define HFCD_CTMT 0x19
15#define HFCD_INT_M1 0x1A
16#define HFCD_INT_M2 0x1B
17#define HFCD_INT_S1 0x1E
18#define HFCD_STAT 0x1C
19#define HFCD_STAT_DISB 0x1D
20#define HFCD_STATES 0x30
21#define HFCD_SCTRL 0x31
22#define HFCD_TEST 0x32
23#define HFCD_SQ 0x34
24#define HFCD_CLKDEL 0x37
25#define HFCD_MST_MODE 0x2E
26#define HFCD_CONN 0x2F
27
28#define HFCD_FIFO 0x80
29#define HFCD_Z1 0x10
30#define HFCD_Z2 0x18
31#define HFCD_Z_LOW 0x00
32#define HFCD_Z_HIGH 0x04
33#define HFCD_F1_INC 0x12
34#define HFCD_FIFO_IN 0x16
35#define HFCD_F1 0x1a
36#define HFCD_F2 0x1e
37#define HFCD_F2_INC 0x22
38#define HFCD_FIFO_OUT 0x26
39#define HFCD_REC 0x01
40#define HFCD_SEND 0x00
41
42#define HFCB_FIFO 0x80
43#define HFCB_Z1 0x00
44#define HFCB_Z2 0x08
45#define HFCB_Z_LOW 0x00
46#define HFCB_Z_HIGH 0x04
47#define HFCB_F1_INC 0x28
48#define HFCB_FIFO_IN 0x2c
49#define HFCB_F1 0x30
50#define HFCB_F2 0x34
51#define HFCB_F2_INC 0x38
52#define HFCB_FIFO_OUT 0x3c
53#define HFCB_REC 0x01
54#define HFCB_SEND 0x00
55#define HFCB_B1 0x00
56#define HFCB_B2 0x02
57#define HFCB_CHANNEL(ch) (ch ? HFCB_B2 : HFCB_B1)
58
59#define HFCD_STATUS 0
60#define HFCD_DATA 1
61#define HFCD_DATA_NODEB 2
62
63/* Status (READ) */
64#define HFCD_BUSY 0x01
65#define HFCD_BUSY_NBUSY 0x04
66#define HFCD_TIMER_ELAP 0x10
67#define HFCD_STATINT 0x20
68#define HFCD_FRAMEINT 0x40
69#define HFCD_ANYINT 0x80
70
71/* CTMT (Write) */
72#define HFCD_CLTIMER 0x80
73#define HFCD_TIM25 0x00
74#define HFCD_TIM50 0x08
75#define HFCD_TIM400 0x10
76#define HFCD_TIM800 0x18
77#define HFCD_AUTO_TIMER 0x20
78#define HFCD_TRANSB2 0x02
79#define HFCD_TRANSB1 0x01
80
81/* CIRM (Write) */
82#define HFCD_RESET 0x08
83#define HFCD_MEM8K 0x10
84#define HFCD_INTA 0x01
85#define HFCD_INTB 0x02
86#define HFCD_INTC 0x03
87#define HFCD_INTD 0x04
88#define HFCD_INTE 0x05
89#define HFCD_INTF 0x06
90
91/* INT_M1;INT_S1 */
92#define HFCD_INTS_B1TRANS 0x01
93#define HFCD_INTS_B2TRANS 0x02
94#define HFCD_INTS_DTRANS 0x04
95#define HFCD_INTS_B1REC 0x08
96#define HFCD_INTS_B2REC 0x10
97#define HFCD_INTS_DREC 0x20
98#define HFCD_INTS_L1STATE 0x40
99#define HFCD_INTS_TIMER 0x80
100
101/* INT_M2 */
102#define HFCD_IRQ_ENABLE 0x08
103
104/* STATES */
105#define HFCD_LOAD_STATE 0x10
106#define HFCD_ACTIVATE 0x20
107#define HFCD_DO_ACTION 0x40
108
109/* HFCD_MST_MODE */
110#define HFCD_MASTER 0x01
111
112/* HFCD_SCTRL */
113#define SCTRL_B1_ENA 0x01
114#define SCTRL_B2_ENA 0x02
115#define SCTRL_LOW_PRIO 0x08
116#define SCTRL_SQ_ENA 0x10
117#define SCTRL_TEST 0x20
118#define SCTRL_NONE_CAP 0x40
119#define SCTRL_PWR_DOWN 0x80
120
121/* HFCD_TEST */
122#define HFCD_AUTO_AWAKE 0x01
123
124extern void main_irq_2bds0(struct BCState *bcs);
125extern void init2bds0(struct IsdnCardState *cs);
126extern void release2bds0(struct IsdnCardState *cs);
127extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val);
128extern void set_cs_func(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
new file mode 100644
index 00000000000..bb376f39ac8
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -0,0 +1,593 @@
1/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $
2 *
3 * specific routines for CCD's HFC 2BS0
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "hfc_2bs0.h"
16#include "isac.h"
17#include "isdnl1.h"
18#include <linux/interrupt.h>
19
20static inline int
21WaitForBusy(struct IsdnCardState *cs)
22{
23 int to = 130;
24 u_char val;
25
26 while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
27 val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
28 (cs->hw.hfc.cip & 3));
29 udelay(1);
30 to--;
31 }
32 if (!to) {
33 printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
34 return (0);
35 } else
36 return (to);
37}
38
39static inline int
40WaitNoBusy(struct IsdnCardState *cs)
41{
42 int to = 125;
43
44 while ((cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
45 udelay(1);
46 to--;
47 }
48 if (!to) {
49 printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
50 return (0);
51 } else
52 return (to);
53}
54
55int
56GetFreeFifoBytes(struct BCState *bcs)
57{
58 int s;
59
60 if (bcs->hw.hfc.f1 == bcs->hw.hfc.f2)
61 return (bcs->cs->hw.hfc.fifosize);
62 s = bcs->hw.hfc.send[bcs->hw.hfc.f1] - bcs->hw.hfc.send[bcs->hw.hfc.f2];
63 if (s <= 0)
64 s += bcs->cs->hw.hfc.fifosize;
65 s = bcs->cs->hw.hfc.fifosize - s;
66 return (s);
67}
68
69int
70ReadZReg(struct BCState *bcs, u_char reg)
71{
72 int val;
73
74 WaitNoBusy(bcs->cs);
75 val = 256 * bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH);
76 WaitNoBusy(bcs->cs);
77 val += bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW);
78 return (val);
79}
80
81static void
82hfc_clear_fifo(struct BCState *bcs)
83{
84 struct IsdnCardState *cs = bcs->cs;
85 int idx, cnt;
86 int rcnt, z1, z2;
87 u_char cip, f1, f2;
88
89 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
90 debugl1(cs, "hfc_clear_fifo");
91 cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
92 if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
93 cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
94 WaitForBusy(cs);
95 }
96 WaitNoBusy(cs);
97 f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
98 cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
99 WaitNoBusy(cs);
100 f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
101 z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
102 z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
103 cnt = 32;
104 while (((f1 != f2) || (z1 != z2)) && cnt--) {
105 if (cs->debug & L1_DEB_HSCX)
106 debugl1(cs, "hfc clear %d f1(%d) f2(%d)",
107 bcs->channel, f1, f2);
108 rcnt = z1 - z2;
109 if (rcnt < 0)
110 rcnt += cs->hw.hfc.fifosize;
111 if (rcnt)
112 rcnt++;
113 if (cs->debug & L1_DEB_HSCX)
114 debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
115 bcs->channel, z1, z2, rcnt);
116 cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
117 idx = 0;
118 while ((idx < rcnt) && WaitNoBusy(cs)) {
119 cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
120 idx++;
121 }
122 if (f1 != f2) {
123 WaitNoBusy(cs);
124 cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
125 HFC_CHANNEL(bcs->channel));
126 WaitForBusy(cs);
127 }
128 cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
129 WaitNoBusy(cs);
130 f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
131 cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
132 WaitNoBusy(cs);
133 f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
134 z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
135 z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
136 }
137 return;
138}
139
140
141static struct sk_buff
142*
143hfc_empty_fifo(struct BCState *bcs, int count)
144{
145 u_char *ptr;
146 struct sk_buff *skb;
147 struct IsdnCardState *cs = bcs->cs;
148 int idx;
149 int chksum;
150 u_char stat, cip;
151
152 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
153 debugl1(cs, "hfc_empty_fifo");
154 idx = 0;
155 if (count > HSCX_BUFMAX + 3) {
156 if (cs->debug & L1_DEB_WARN)
157 debugl1(cs, "hfc_empty_fifo: incoming packet too large");
158 cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
159 while ((idx++ < count) && WaitNoBusy(cs))
160 cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
161 WaitNoBusy(cs);
162 stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
163 HFC_CHANNEL(bcs->channel));
164 WaitForBusy(cs);
165 return (NULL);
166 }
167 if ((count < 4) && (bcs->mode != L1_MODE_TRANS)) {
168 if (cs->debug & L1_DEB_WARN)
169 debugl1(cs, "hfc_empty_fifo: incoming packet too small");
170 cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
171 while ((idx++ < count) && WaitNoBusy(cs))
172 cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
173 WaitNoBusy(cs);
174 stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
175 HFC_CHANNEL(bcs->channel));
176 WaitForBusy(cs);
177#ifdef ERROR_STATISTIC
178 bcs->err_inv++;
179#endif
180 return (NULL);
181 }
182 if (bcs->mode == L1_MODE_TRANS)
183 count -= 1;
184 else
185 count -= 3;
186 if (!(skb = dev_alloc_skb(count)))
187 printk(KERN_WARNING "HFC: receive out of memory\n");
188 else {
189 ptr = skb_put(skb, count);
190 idx = 0;
191 cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
192 while ((idx < count) && WaitNoBusy(cs)) {
193 *ptr++ = cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip);
194 idx++;
195 }
196 if (idx != count) {
197 debugl1(cs, "RFIFO BUSY error");
198 printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
199 dev_kfree_skb_any(skb);
200 if (bcs->mode != L1_MODE_TRANS) {
201 WaitNoBusy(cs);
202 stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
203 HFC_CHANNEL(bcs->channel));
204 WaitForBusy(cs);
205 }
206 return (NULL);
207 }
208 if (bcs->mode != L1_MODE_TRANS) {
209 WaitNoBusy(cs);
210 chksum = (cs->BC_Read_Reg(cs, HFC_DATA, cip) << 8);
211 WaitNoBusy(cs);
212 chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
213 WaitNoBusy(cs);
214 stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
215 if (cs->debug & L1_DEB_HSCX)
216 debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
217 bcs->channel, chksum, stat);
218 if (stat) {
219 debugl1(cs, "FIFO CRC error");
220 dev_kfree_skb_any(skb);
221 skb = NULL;
222#ifdef ERROR_STATISTIC
223 bcs->err_crc++;
224#endif
225 }
226 WaitNoBusy(cs);
227 stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
228 HFC_CHANNEL(bcs->channel));
229 WaitForBusy(cs);
230 }
231 }
232 return (skb);
233}
234
235static void
236hfc_fill_fifo(struct BCState *bcs)
237{
238 struct IsdnCardState *cs = bcs->cs;
239 int idx, fcnt;
240 int count;
241 int z1, z2;
242 u_char cip;
243
244 if (!bcs->tx_skb)
245 return;
246 if (bcs->tx_skb->len <= 0)
247 return;
248
249 cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel);
250 if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
251 cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
252 WaitForBusy(cs);
253 }
254 WaitNoBusy(cs);
255 if (bcs->mode != L1_MODE_TRANS) {
256 bcs->hw.hfc.f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
257 cip = HFC_CIP | HFC_F2 | HFC_SEND | HFC_CHANNEL(bcs->channel);
258 WaitNoBusy(cs);
259 bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
260 bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
261 if (cs->debug & L1_DEB_HSCX)
262 debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
263 bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
264 bcs->hw.hfc.send[bcs->hw.hfc.f1]);
265 fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
266 if (fcnt < 0)
267 fcnt += 32;
268 if (fcnt > 30) {
269 if (cs->debug & L1_DEB_HSCX)
270 debugl1(cs, "hfc_fill_fifo more as 30 frames");
271 return;
272 }
273 count = GetFreeFifoBytes(bcs);
274 }
275 else {
276 WaitForBusy(cs);
277 z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
278 z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
279 count = z1 - z2;
280 if (count < 0)
281 count += cs->hw.hfc.fifosize;
282 } /* L1_MODE_TRANS */
283 if (cs->debug & L1_DEB_HSCX)
284 debugl1(cs, "hfc_fill_fifo %d count(%ld/%d)",
285 bcs->channel, bcs->tx_skb->len,
286 count);
287 if (count < bcs->tx_skb->len) {
288 if (cs->debug & L1_DEB_HSCX)
289 debugl1(cs, "hfc_fill_fifo no fifo mem");
290 return;
291 }
292 cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
293 idx = 0;
294 while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
295 cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
296 if (idx != bcs->tx_skb->len) {
297 debugl1(cs, "FIFO Send BUSY error");
298 printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
299 } else {
300 count = bcs->tx_skb->len;
301 bcs->tx_cnt -= count;
302 if (PACKET_NOACK == bcs->tx_skb->pkt_type)
303 count = -1;
304 dev_kfree_skb_any(bcs->tx_skb);
305 bcs->tx_skb = NULL;
306 if (bcs->mode != L1_MODE_TRANS) {
307 WaitForBusy(cs);
308 WaitNoBusy(cs);
309 cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
310 }
311 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
312 (count >= 0)) {
313 u_long flags;
314 spin_lock_irqsave(&bcs->aclock, flags);
315 bcs->ackcnt += count;
316 spin_unlock_irqrestore(&bcs->aclock, flags);
317 schedule_event(bcs, B_ACKPENDING);
318 }
319 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
320 }
321 return;
322}
323
324void
325main_irq_hfc(struct BCState *bcs)
326{
327 struct IsdnCardState *cs = bcs->cs;
328 int z1, z2, rcnt;
329 u_char f1, f2, cip;
330 int receive, transmit, count = 5;
331 struct sk_buff *skb;
332
333 Begin:
334 count--;
335 cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
336 if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
337 cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
338 WaitForBusy(cs);
339 }
340 WaitNoBusy(cs);
341 receive = 0;
342 if (bcs->mode == L1_MODE_HDLC) {
343 f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
344 cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel);
345 WaitNoBusy(cs);
346 f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
347 if (f1 != f2) {
348 if (cs->debug & L1_DEB_HSCX)
349 debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
350 bcs->channel, f1, f2);
351 receive = 1;
352 }
353 }
354 if (receive || (bcs->mode == L1_MODE_TRANS)) {
355 WaitForBusy(cs);
356 z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
357 z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
358 rcnt = z1 - z2;
359 if (rcnt < 0)
360 rcnt += cs->hw.hfc.fifosize;
361 if ((bcs->mode == L1_MODE_HDLC) || (rcnt)) {
362 rcnt++;
363 if (cs->debug & L1_DEB_HSCX)
364 debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
365 bcs->channel, z1, z2, rcnt);
366 /* sti(); */
367 if ((skb = hfc_empty_fifo(bcs, rcnt))) {
368 skb_queue_tail(&bcs->rqueue, skb);
369 schedule_event(bcs, B_RCVBUFREADY);
370 }
371 }
372 receive = 1;
373 }
374 if (bcs->tx_skb) {
375 transmit = 1;
376 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
377 hfc_fill_fifo(bcs);
378 if (test_bit(BC_FLG_BUSY, &bcs->Flag))
379 transmit = 0;
380 } else {
381 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
382 transmit = 1;
383 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
384 hfc_fill_fifo(bcs);
385 if (test_bit(BC_FLG_BUSY, &bcs->Flag))
386 transmit = 0;
387 } else {
388 transmit = 0;
389 schedule_event(bcs, B_XMTBUFREADY);
390 }
391 }
392 if ((receive || transmit) && count)
393 goto Begin;
394 return;
395}
396
397void
398mode_hfc(struct BCState *bcs, int mode, int bc)
399{
400 struct IsdnCardState *cs = bcs->cs;
401
402 if (cs->debug & L1_DEB_HSCX)
403 debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d",
404 mode, bc, bcs->channel);
405 bcs->mode = mode;
406 bcs->channel = bc;
407
408 switch (mode) {
409 case (L1_MODE_NULL):
410 if (bc) {
411 cs->hw.hfc.ctmt &= ~1;
412 cs->hw.hfc.isac_spcr &= ~0x03;
413 }
414 else {
415 cs->hw.hfc.ctmt &= ~2;
416 cs->hw.hfc.isac_spcr &= ~0x0c;
417 }
418 break;
419 case (L1_MODE_TRANS):
420 cs->hw.hfc.ctmt &= ~(1 << bc); /* set HDLC mode */
421 cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
422 hfc_clear_fifo(bcs); /* complete fifo clear */
423 if (bc) {
424 cs->hw.hfc.ctmt |= 1;
425 cs->hw.hfc.isac_spcr &= ~0x03;
426 cs->hw.hfc.isac_spcr |= 0x02;
427 } else {
428 cs->hw.hfc.ctmt |= 2;
429 cs->hw.hfc.isac_spcr &= ~0x0c;
430 cs->hw.hfc.isac_spcr |= 0x08;
431 }
432 break;
433 case (L1_MODE_HDLC):
434 if (bc) {
435 cs->hw.hfc.ctmt &= ~1;
436 cs->hw.hfc.isac_spcr &= ~0x03;
437 cs->hw.hfc.isac_spcr |= 0x02;
438 } else {
439 cs->hw.hfc.ctmt &= ~2;
440 cs->hw.hfc.isac_spcr &= ~0x0c;
441 cs->hw.hfc.isac_spcr |= 0x08;
442 }
443 break;
444 }
445 cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt);
446 cs->writeisac(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr);
447 if (mode == L1_MODE_HDLC)
448 hfc_clear_fifo(bcs);
449}
450
451static void
452hfc_l2l1(struct PStack *st, int pr, void *arg)
453{
454 struct BCState *bcs = st->l1.bcs;
455 struct sk_buff *skb = arg;
456 u_long flags;
457
458 switch (pr) {
459 case (PH_DATA | REQUEST):
460 spin_lock_irqsave(&bcs->cs->lock, flags);
461 if (bcs->tx_skb) {
462 skb_queue_tail(&bcs->squeue, skb);
463 } else {
464 bcs->tx_skb = skb;
465 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
466 bcs->cs->BC_Send_Data(bcs);
467 }
468 spin_unlock_irqrestore(&bcs->cs->lock, flags);
469 break;
470 case (PH_PULL | INDICATION):
471 spin_lock_irqsave(&bcs->cs->lock, flags);
472 if (bcs->tx_skb) {
473 printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
474 } else {
475 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
476 bcs->tx_skb = skb;
477 bcs->cs->BC_Send_Data(bcs);
478 }
479 spin_unlock_irqrestore(&bcs->cs->lock, flags);
480 break;
481 case (PH_PULL | REQUEST):
482 if (!bcs->tx_skb) {
483 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
484 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
485 } else
486 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
487 break;
488 case (PH_ACTIVATE | REQUEST):
489 spin_lock_irqsave(&bcs->cs->lock, flags);
490 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
491 mode_hfc(bcs, st->l1.mode, st->l1.bc);
492 spin_unlock_irqrestore(&bcs->cs->lock, flags);
493 l1_msg_b(st, pr, arg);
494 break;
495 case (PH_DEACTIVATE | REQUEST):
496 l1_msg_b(st, pr, arg);
497 break;
498 case (PH_DEACTIVATE | CONFIRM):
499 spin_lock_irqsave(&bcs->cs->lock, flags);
500 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
501 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
502 mode_hfc(bcs, 0, st->l1.bc);
503 spin_unlock_irqrestore(&bcs->cs->lock, flags);
504 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
505 break;
506 }
507}
508
509
510void
511close_hfcstate(struct BCState *bcs)
512{
513 mode_hfc(bcs, 0, bcs->channel);
514 if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
515 skb_queue_purge(&bcs->rqueue);
516 skb_queue_purge(&bcs->squeue);
517 if (bcs->tx_skb) {
518 dev_kfree_skb_any(bcs->tx_skb);
519 bcs->tx_skb = NULL;
520 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
521 }
522 }
523 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
524}
525
526static int
527open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
528{
529 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
530 skb_queue_head_init(&bcs->rqueue);
531 skb_queue_head_init(&bcs->squeue);
532 }
533 bcs->tx_skb = NULL;
534 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
535 bcs->event = 0;
536 bcs->tx_cnt = 0;
537 return (0);
538}
539
540int
541setstack_hfc(struct PStack *st, struct BCState *bcs)
542{
543 bcs->channel = st->l1.bc;
544 if (open_hfcstate(st->l1.hardware, bcs))
545 return (-1);
546 st->l1.bcs = bcs;
547 st->l2.l2l1 = hfc_l2l1;
548 setstack_manager(st);
549 bcs->st = st;
550 setstack_l1_B(st);
551 return (0);
552}
553
554void __init
555init_send(struct BCState *bcs)
556{
557 int i;
558
559 if (!(bcs->hw.hfc.send = kmalloc(32 * sizeof(unsigned int), GFP_ATOMIC))) {
560 printk(KERN_WARNING
561 "HiSax: No memory for hfc.send\n");
562 return;
563 }
564 for (i = 0; i < 32; i++)
565 bcs->hw.hfc.send[i] = 0x1fff;
566}
567
568void __init
569inithfc(struct IsdnCardState *cs)
570{
571 init_send(&cs->bcs[0]);
572 init_send(&cs->bcs[1]);
573 cs->BC_Send_Data = &hfc_fill_fifo;
574 cs->bcs[0].BC_SetStack = setstack_hfc;
575 cs->bcs[1].BC_SetStack = setstack_hfc;
576 cs->bcs[0].BC_Close = close_hfcstate;
577 cs->bcs[1].BC_Close = close_hfcstate;
578 mode_hfc(cs->bcs, 0, 0);
579 mode_hfc(cs->bcs + 1, 0, 0);
580}
581
582void
583releasehfc(struct IsdnCardState *cs)
584{
585 if (cs->bcs[0].hw.hfc.send) {
586 kfree(cs->bcs[0].hw.hfc.send);
587 cs->bcs[0].hw.hfc.send = NULL;
588 }
589 if (cs->bcs[1].hw.hfc.send) {
590 kfree(cs->bcs[1].hw.hfc.send);
591 cs->bcs[1].hw.hfc.send = NULL;
592 }
593}
diff --git a/drivers/isdn/hisax/hfc_2bs0.h b/drivers/isdn/hisax/hfc_2bs0.h
new file mode 100644
index 00000000000..1a50d4a5c96
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_2bs0.h
@@ -0,0 +1,60 @@
1/* $Id: hfc_2bs0.h,v 1.5.2.2 2004/01/12 22:52:26 keil Exp $
2 *
3 * specific defines for CCD's HFC 2BS0
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#define HFC_CTMT 0xe0
14#define HFC_CIRM 0xc0
15#define HFC_CIP 0x80
16#define HFC_Z1 0x00
17#define HFC_Z2 0x08
18#define HFC_Z_LOW 0x00
19#define HFC_Z_HIGH 0x04
20#define HFC_F1_INC 0x28
21#define HFC_FIFO_IN 0x2c
22#define HFC_F1 0x30
23#define HFC_F2 0x34
24#define HFC_F2_INC 0x38
25#define HFC_FIFO_OUT 0x3c
26#define HFC_B1 0x00
27#define HFC_B2 0x02
28#define HFC_REC 0x01
29#define HFC_SEND 0x00
30#define HFC_CHANNEL(ch) (ch ? HFC_B2 : HFC_B1)
31
32#define HFC_STATUS 0
33#define HFC_DATA 1
34#define HFC_DATA_NODEB 2
35
36/* Status (READ) */
37#define HFC_BUSY 0x01
38#define HFC_TIMINT 0x02
39#define HFC_EXTINT 0x04
40
41/* CTMT (Write) */
42#define HFC_CLTIMER 0x10
43#define HFC_TIM50MS 0x08
44#define HFC_TIMIRQE 0x04
45#define HFC_TRANSB2 0x02
46#define HFC_TRANSB1 0x01
47
48/* CIRM (Write) */
49#define HFC_RESET 0x08
50#define HFC_MEM8K 0x10
51#define HFC_INTA 0x01
52#define HFC_INTB 0x02
53#define HFC_INTC 0x03
54#define HFC_INTD 0x04
55#define HFC_INTE 0x05
56#define HFC_INTF 0x06
57
58extern void main_irq_hfc(struct BCState *bcs);
59extern void inithfc(struct IsdnCardState *cs);
60extern void releasehfc(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
new file mode 100644
index 00000000000..c2db52696a8
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -0,0 +1,1747 @@
1/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $
2 *
3 * low level driver for CCD´s hfc-pci based cards
4 *
5 * Author Werner Cornelius
6 * based on existing driver for CCD hfc ISA cards
7 * Copyright by Werner Cornelius <werner@isdn4linux.de>
8 * by Karsten Keil <keil@isdn4linux.de>
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 * For changes and modifications please read
14 * Documentation/isdn/HiSax.cert
15 *
16 */
17
18#include <linux/init.h>
19#include <linux/config.h>
20#include "hisax.h"
21#include "hfc_pci.h"
22#include "isdnl1.h"
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25
26extern const char *CardType[];
27
28static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
29
30/* table entry in the PCI devices list */
31typedef struct {
32 int vendor_id;
33 int device_id;
34 char *vendor_name;
35 char *card_name;
36} PCI_ENTRY;
37
38#define NT_T1_COUNT 20 /* number of 3.125ms interrupts for G2 timeout */
39#define CLKDEL_TE 0x0e /* CLKDEL in TE mode */
40#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */
41
42static const PCI_ENTRY id_list[] =
43{
44 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"},
45 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"},
46 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"},
47 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"},
48 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"},
49 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"},
50 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"},
51 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
52 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
53 {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
54 {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"},
55 {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
56 {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
57 {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"},
58 {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"},
59 {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"},
60 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
61 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
62 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
63 {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
64 {0, 0, NULL, NULL},
65};
66
67
68#ifdef CONFIG_PCI
69
70/******************************************/
71/* free hardware resources used by driver */
72/******************************************/
73void
74release_io_hfcpci(struct IsdnCardState *cs)
75{
76 printk(KERN_INFO "HiSax: release hfcpci at %p\n",
77 cs->hw.hfcpci.pci_io);
78 cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */
79 Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
80 Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */
81 mdelay(10);
82 Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */
83 mdelay(10);
84 Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
85 pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */
86 del_timer(&cs->hw.hfcpci.timer);
87 kfree(cs->hw.hfcpci.share_start);
88 cs->hw.hfcpci.share_start = NULL;
89 iounmap((void *)cs->hw.hfcpci.pci_io);
90}
91
92/********************************************************************************/
93/* function called to reset the HFC PCI chip. A complete software reset of chip */
94/* and fifos is done. */
95/********************************************************************************/
96static void
97reset_hfcpci(struct IsdnCardState *cs)
98{
99 pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
100 cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */
101 Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
102
103 printk(KERN_INFO "HFC_PCI: resetting card\n");
104 pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */
105 Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */
106 mdelay(10);
107 Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */
108 mdelay(10);
109 if (Read_hfc(cs, HFCPCI_STATUS) & 2)
110 printk(KERN_WARNING "HFC-PCI init bit busy\n");
111
112 cs->hw.hfcpci.fifo_en = 0x30; /* only D fifos enabled */
113 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
114
115 cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */
116 Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
117
118 Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_TE); /* ST-Bit delay for TE-Mode */
119 cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE;
120 Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); /* S/T Auto awake */
121 cs->hw.hfcpci.bswapped = 0; /* no exchange */
122 cs->hw.hfcpci.nt_mode = 0; /* we are in TE mode */
123 cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
124 Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
125
126 cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
127 HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER;
128 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
129
130 /* Clear already pending ints */
131 if (Read_hfc(cs, HFCPCI_INT_S1));
132
133 Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2); /* HFC ST 2 */
134 udelay(10);
135 Write_hfc(cs, HFCPCI_STATES, 2); /* HFC ST 2 */
136 cs->hw.hfcpci.mst_m = HFCPCI_MASTER; /* HFC Master Mode */
137
138 Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
139 cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
140 Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
141 cs->hw.hfcpci.sctrl_r = 0;
142 Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
143
144 /* Init GCI/IOM2 in master mode */
145 /* Slots 0 and 1 are set for B-chan 1 and 2 */
146 /* D- and monitor/CI channel are not enabled */
147 /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
148 /* STIO2 is used as data input, B1+B2 from IOM->ST */
149 /* ST B-channel send disabled -> continous 1s */
150 /* The IOM slots are always enabled */
151 cs->hw.hfcpci.conn = 0x36; /* set data flow directions */
152 Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
153 Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */
154 Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */
155 Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */
156 Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */
157
158 /* Finally enable IRQ output */
159 cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
160 Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
161 if (Read_hfc(cs, HFCPCI_INT_S1));
162}
163
164/***************************************************/
165/* Timer function called when kernel timer expires */
166/***************************************************/
167static void
168hfcpci_Timer(struct IsdnCardState *cs)
169{
170 cs->hw.hfcpci.timer.expires = jiffies + 75;
171 /* WD RESET */
172/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80);
173 add_timer(&cs->hw.hfcpci.timer);
174 */
175}
176
177
178/*********************************/
179/* schedule a new D-channel task */
180/*********************************/
181static void
182sched_event_D_pci(struct IsdnCardState *cs, int event)
183{
184 test_and_set_bit(event, &cs->event);
185 schedule_work(&cs->tqueue);
186}
187
188/*********************************/
189/* schedule a new b_channel task */
190/*********************************/
191static void
192hfcpci_sched_event(struct BCState *bcs, int event)
193{
194 test_and_set_bit(event, &bcs->event);
195 schedule_work(&bcs->tqueue);
196}
197
198/************************************************/
199/* select a b-channel entry matching and active */
200/************************************************/
201static
202struct BCState *
203Sel_BCS(struct IsdnCardState *cs, int channel)
204{
205 if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
206 return (&cs->bcs[0]);
207 else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
208 return (&cs->bcs[1]);
209 else
210 return (NULL);
211}
212
213/***************************************/
214/* clear the desired B-channel rx fifo */
215/***************************************/
216static void hfcpci_clear_fifo_rx(struct IsdnCardState *cs, int fifo)
217{ u_char fifo_state;
218 bzfifo_type *bzr;
219
220 if (fifo) {
221 bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
222 fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B2RX;
223 } else {
224 bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
225 fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B1RX;
226 }
227 if (fifo_state)
228 cs->hw.hfcpci.fifo_en ^= fifo_state;
229 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
230 cs->hw.hfcpci.last_bfifo_cnt[fifo] = 0;
231 bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
232 bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
233 bzr->f1 = MAX_B_FRAMES;
234 bzr->f2 = bzr->f1; /* init F pointers to remain constant */
235 if (fifo_state)
236 cs->hw.hfcpci.fifo_en |= fifo_state;
237 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
238}
239
240/***************************************/
241/* clear the desired B-channel tx fifo */
242/***************************************/
243static void hfcpci_clear_fifo_tx(struct IsdnCardState *cs, int fifo)
244{ u_char fifo_state;
245 bzfifo_type *bzt;
246
247 if (fifo) {
248 bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
249 fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B2TX;
250 } else {
251 bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
252 fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B1TX;
253 }
254 if (fifo_state)
255 cs->hw.hfcpci.fifo_en ^= fifo_state;
256 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
257 bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
258 bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1;
259 bzt->f1 = MAX_B_FRAMES;
260 bzt->f2 = bzt->f1; /* init F pointers to remain constant */
261 if (fifo_state)
262 cs->hw.hfcpci.fifo_en |= fifo_state;
263 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
264}
265
266/*********************************************/
267/* read a complete B-frame out of the buffer */
268/*********************************************/
269static struct sk_buff
270*
271hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count)
272{
273 u_char *ptr, *ptr1, new_f2;
274 struct sk_buff *skb;
275 struct IsdnCardState *cs = bcs->cs;
276 int total, maxlen, new_z2;
277 z_type *zp;
278
279 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
280 debugl1(cs, "hfcpci_empty_fifo");
281 zp = &bz->za[bz->f2]; /* point to Z-Regs */
282 new_z2 = zp->z2 + count; /* new position in fifo */
283 if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
284 new_z2 -= B_FIFO_SIZE; /* buffer wrap */
285 new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
286 if ((count > HSCX_BUFMAX + 3) || (count < 4) ||
287 (*(bdata + (zp->z1 - B_SUB_VAL)))) {
288 if (cs->debug & L1_DEB_WARN)
289 debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count);
290#ifdef ERROR_STATISTIC
291 bcs->err_inv++;
292#endif
293 bz->za[new_f2].z2 = new_z2;
294 bz->f2 = new_f2; /* next buffer */
295 skb = NULL;
296 } else if (!(skb = dev_alloc_skb(count - 3)))
297 printk(KERN_WARNING "HFCPCI: receive out of memory\n");
298 else {
299 total = count;
300 count -= 3;
301 ptr = skb_put(skb, count);
302
303 if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
304 maxlen = count; /* complete transfer */
305 else
306 maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
307
308 ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */
309 memcpy(ptr, ptr1, maxlen); /* copy data */
310 count -= maxlen;
311
312 if (count) { /* rest remaining */
313 ptr += maxlen;
314 ptr1 = bdata; /* start of buffer */
315 memcpy(ptr, ptr1, count); /* rest */
316 }
317 bz->za[new_f2].z2 = new_z2;
318 bz->f2 = new_f2; /* next buffer */
319
320 }
321 return (skb);
322}
323
324/*******************************/
325/* D-channel receive procedure */
326/*******************************/
327static
328int
329receive_dmsg(struct IsdnCardState *cs)
330{
331 struct sk_buff *skb;
332 int maxlen;
333 int rcnt, total;
334 int count = 5;
335 u_char *ptr, *ptr1;
336 dfifo_type *df;
337 z_type *zp;
338
339 df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx;
340 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
341 debugl1(cs, "rec_dmsg blocked");
342 return (1);
343 }
344 while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
345 zp = &df->za[df->f2 & D_FREG_MASK];
346 rcnt = zp->z1 - zp->z2;
347 if (rcnt < 0)
348 rcnt += D_FIFO_SIZE;
349 rcnt++;
350 if (cs->debug & L1_DEB_ISAC)
351 debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
352 df->f1, df->f2, zp->z1, zp->z2, rcnt);
353
354 if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
355 (df->data[zp->z1])) {
356 if (cs->debug & L1_DEB_WARN)
357 debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
358#ifdef ERROR_STATISTIC
359 cs->err_rx++;
360#endif
361 df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */
362 df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
363 } else if ((skb = dev_alloc_skb(rcnt - 3))) {
364 total = rcnt;
365 rcnt -= 3;
366 ptr = skb_put(skb, rcnt);
367
368 if (zp->z2 + rcnt <= D_FIFO_SIZE)
369 maxlen = rcnt; /* complete transfer */
370 else
371 maxlen = D_FIFO_SIZE - zp->z2; /* maximum */
372
373 ptr1 = df->data + zp->z2; /* start of data */
374 memcpy(ptr, ptr1, maxlen); /* copy data */
375 rcnt -= maxlen;
376
377 if (rcnt) { /* rest remaining */
378 ptr += maxlen;
379 ptr1 = df->data; /* start of buffer */
380 memcpy(ptr, ptr1, rcnt); /* rest */
381 }
382 df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */
383 df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1);
384
385 skb_queue_tail(&cs->rq, skb);
386 sched_event_D_pci(cs, D_RCVBUFREADY);
387 } else
388 printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
389 }
390 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
391 return (1);
392}
393
394/*******************************************************************************/
395/* check for transparent receive data and read max one threshold size if avail */
396/*******************************************************************************/
397int
398hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
399{
400 unsigned short *z1r, *z2r;
401 int new_z2, fcnt, maxlen;
402 struct sk_buff *skb;
403 u_char *ptr, *ptr1;
404
405 z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */
406 z2r = z1r + 1;
407
408 if (!(fcnt = *z1r - *z2r))
409 return (0); /* no data avail */
410
411 if (fcnt <= 0)
412 fcnt += B_FIFO_SIZE; /* bytes actually buffered */
413 if (fcnt > HFCPCI_BTRANS_THRESHOLD)
414 fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
415
416 new_z2 = *z2r + fcnt; /* new position in fifo */
417 if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
418 new_z2 -= B_FIFO_SIZE; /* buffer wrap */
419
420 if (!(skb = dev_alloc_skb(fcnt)))
421 printk(KERN_WARNING "HFCPCI: receive out of memory\n");
422 else {
423 ptr = skb_put(skb, fcnt);
424 if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
425 maxlen = fcnt; /* complete transfer */
426 else
427 maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */
428
429 ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */
430 memcpy(ptr, ptr1, maxlen); /* copy data */
431 fcnt -= maxlen;
432
433 if (fcnt) { /* rest remaining */
434 ptr += maxlen;
435 ptr1 = bdata; /* start of buffer */
436 memcpy(ptr, ptr1, fcnt); /* rest */
437 }
438 skb_queue_tail(&bcs->rqueue, skb);
439 hfcpci_sched_event(bcs, B_RCVBUFREADY);
440 }
441
442 *z2r = new_z2; /* new position */
443 return (1);
444} /* hfcpci_empty_fifo_trans */
445
446/**********************************/
447/* B-channel main receive routine */
448/**********************************/
449void
450main_rec_hfcpci(struct BCState *bcs)
451{
452 struct IsdnCardState *cs = bcs->cs;
453 int rcnt, real_fifo;
454 int receive, count = 5;
455 struct sk_buff *skb;
456 bzfifo_type *bz;
457 u_char *bdata;
458 z_type *zp;
459
460
461 if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
462 bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
463 bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
464 real_fifo = 1;
465 } else {
466 bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
467 bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b1;
468 real_fifo = 0;
469 }
470 Begin:
471 count--;
472 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
473 debugl1(cs, "rec_data %d blocked", bcs->channel);
474 return;
475 }
476 if (bz->f1 != bz->f2) {
477 if (cs->debug & L1_DEB_HSCX)
478 debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)",
479 bcs->channel, bz->f1, bz->f2);
480 zp = &bz->za[bz->f2];
481
482 rcnt = zp->z1 - zp->z2;
483 if (rcnt < 0)
484 rcnt += B_FIFO_SIZE;
485 rcnt++;
486 if (cs->debug & L1_DEB_HSCX)
487 debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)",
488 bcs->channel, zp->z1, zp->z2, rcnt);
489 if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) {
490 skb_queue_tail(&bcs->rqueue, skb);
491 hfcpci_sched_event(bcs, B_RCVBUFREADY);
492 }
493 rcnt = bz->f1 - bz->f2;
494 if (rcnt < 0)
495 rcnt += MAX_B_FRAMES + 1;
496 if (cs->hw.hfcpci.last_bfifo_cnt[real_fifo] > rcnt + 1) {
497 rcnt = 0;
498 hfcpci_clear_fifo_rx(cs, real_fifo);
499 }
500 cs->hw.hfcpci.last_bfifo_cnt[real_fifo] = rcnt;
501 if (rcnt > 1)
502 receive = 1;
503 else
504 receive = 0;
505 } else if (bcs->mode == L1_MODE_TRANS)
506 receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
507 else
508 receive = 0;
509 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
510 if (count && receive)
511 goto Begin;
512 return;
513}
514
515/**************************/
516/* D-channel send routine */
517/**************************/
518static void
519hfcpci_fill_dfifo(struct IsdnCardState *cs)
520{
521 int fcnt;
522 int count, new_z1, maxlen;
523 dfifo_type *df;
524 u_char *src, *dst, new_f1;
525
526 if (!cs->tx_skb)
527 return;
528 if (cs->tx_skb->len <= 0)
529 return;
530
531 df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_tx;
532
533 if (cs->debug & L1_DEB_ISAC)
534 debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
535 df->f1, df->f2,
536 df->za[df->f1 & D_FREG_MASK].z1);
537 fcnt = df->f1 - df->f2; /* frame count actually buffered */
538 if (fcnt < 0)
539 fcnt += (MAX_D_FRAMES + 1); /* if wrap around */
540 if (fcnt > (MAX_D_FRAMES - 1)) {
541 if (cs->debug & L1_DEB_ISAC)
542 debugl1(cs, "hfcpci_fill_Dfifo more as 14 frames");
543#ifdef ERROR_STATISTIC
544 cs->err_tx++;
545#endif
546 return;
547 }
548 /* now determine free bytes in FIFO buffer */
549 count = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1;
550 if (count <= 0)
551 count += D_FIFO_SIZE; /* count now contains available bytes */
552
553 if (cs->debug & L1_DEB_ISAC)
554 debugl1(cs, "hfcpci_fill_Dfifo count(%ld/%d)",
555 cs->tx_skb->len, count);
556 if (count < cs->tx_skb->len) {
557 if (cs->debug & L1_DEB_ISAC)
558 debugl1(cs, "hfcpci_fill_Dfifo no fifo mem");
559 return;
560 }
561 count = cs->tx_skb->len; /* get frame len */
562 new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1);
563 new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
564 src = cs->tx_skb->data; /* source pointer */
565 dst = df->data + df->za[df->f1 & D_FREG_MASK].z1;
566 maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1; /* end fifo */
567 if (maxlen > count)
568 maxlen = count; /* limit size */
569 memcpy(dst, src, maxlen); /* first copy */
570
571 count -= maxlen; /* remaining bytes */
572 if (count) {
573 dst = df->data; /* start of buffer */
574 src += maxlen; /* new position */
575 memcpy(dst, src, count);
576 }
577 df->za[new_f1 & D_FREG_MASK].z1 = new_z1; /* for next buffer */
578 df->za[df->f1 & D_FREG_MASK].z1 = new_z1; /* new pos actual buffer */
579 df->f1 = new_f1; /* next frame */
580
581 dev_kfree_skb_any(cs->tx_skb);
582 cs->tx_skb = NULL;
583 return;
584}
585
586/**************************/
587/* B-channel send routine */
588/**************************/
589static void
590hfcpci_fill_fifo(struct BCState *bcs)
591{
592 struct IsdnCardState *cs = bcs->cs;
593 int maxlen, fcnt;
594 int count, new_z1;
595 bzfifo_type *bz;
596 u_char *bdata;
597 u_char new_f1, *src, *dst;
598 unsigned short *z1t, *z2t;
599
600 if (!bcs->tx_skb)
601 return;
602 if (bcs->tx_skb->len <= 0)
603 return;
604
605 if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
606 bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
607 bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2;
608 } else {
609 bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
610 bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1;
611 }
612
613 if (bcs->mode == L1_MODE_TRANS) {
614 z1t = &bz->za[MAX_B_FRAMES].z1;
615 z2t = z1t + 1;
616 if (cs->debug & L1_DEB_HSCX)
617 debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
618 bcs->channel, *z1t, *z2t);
619 fcnt = *z2t - *z1t;
620 if (fcnt <= 0)
621 fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */
622 fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */
623
624 while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
625 if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) {
626 /* data is suitable for fifo */
627 count = bcs->tx_skb->len;
628
629 new_z1 = *z1t + count; /* new buffer Position */
630 if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
631 new_z1 -= B_FIFO_SIZE; /* buffer wrap */
632 src = bcs->tx_skb->data; /* source pointer */
633 dst = bdata + (*z1t - B_SUB_VAL);
634 maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */
635 if (maxlen > count)
636 maxlen = count; /* limit size */
637 memcpy(dst, src, maxlen); /* first copy */
638
639 count -= maxlen; /* remaining bytes */
640 if (count) {
641 dst = bdata; /* start of buffer */
642 src += maxlen; /* new position */
643 memcpy(dst, src, count);
644 }
645 bcs->tx_cnt -= bcs->tx_skb->len;
646 fcnt += bcs->tx_skb->len;
647 *z1t = new_z1; /* now send data */
648 } else if (cs->debug & L1_DEB_HSCX)
649 debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
650 bcs->channel, bcs->tx_skb->len);
651
652 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
653 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
654 u_long flags;
655 spin_lock_irqsave(&bcs->aclock, flags);
656 bcs->ackcnt += bcs->tx_skb->len;
657 spin_unlock_irqrestore(&bcs->aclock, flags);
658 schedule_event(bcs, B_ACKPENDING);
659 }
660
661 dev_kfree_skb_any(bcs->tx_skb);
662 bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
663 }
664 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
665 return;
666 }
667 if (cs->debug & L1_DEB_HSCX)
668 debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)",
669 bcs->channel, bz->f1, bz->f2,
670 bz->za[bz->f1].z1);
671
672 fcnt = bz->f1 - bz->f2; /* frame count actually buffered */
673 if (fcnt < 0)
674 fcnt += (MAX_B_FRAMES + 1); /* if wrap around */
675 if (fcnt > (MAX_B_FRAMES - 1)) {
676 if (cs->debug & L1_DEB_HSCX)
677 debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames");
678 return;
679 }
680 /* now determine free bytes in FIFO buffer */
681 count = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1;
682 if (count <= 0)
683 count += B_FIFO_SIZE; /* count now contains available bytes */
684
685 if (cs->debug & L1_DEB_HSCX)
686 debugl1(cs, "hfcpci_fill_fifo %d count(%ld/%d),%lx",
687 bcs->channel, bcs->tx_skb->len,
688 count, current->state);
689
690 if (count < bcs->tx_skb->len) {
691 if (cs->debug & L1_DEB_HSCX)
692 debugl1(cs, "hfcpci_fill_fifo no fifo mem");
693 return;
694 }
695 count = bcs->tx_skb->len; /* get frame len */
696 new_z1 = bz->za[bz->f1].z1 + count; /* new buffer Position */
697 if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
698 new_z1 -= B_FIFO_SIZE; /* buffer wrap */
699
700 new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
701 src = bcs->tx_skb->data; /* source pointer */
702 dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL);
703 maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1; /* end fifo */
704 if (maxlen > count)
705 maxlen = count; /* limit size */
706 memcpy(dst, src, maxlen); /* first copy */
707
708 count -= maxlen; /* remaining bytes */
709 if (count) {
710 dst = bdata; /* start of buffer */
711 src += maxlen; /* new position */
712 memcpy(dst, src, count);
713 }
714 bcs->tx_cnt -= bcs->tx_skb->len;
715 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
716 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
717 u_long flags;
718 spin_lock_irqsave(&bcs->aclock, flags);
719 bcs->ackcnt += bcs->tx_skb->len;
720 spin_unlock_irqrestore(&bcs->aclock, flags);
721 schedule_event(bcs, B_ACKPENDING);
722 }
723
724 bz->za[new_f1].z1 = new_z1; /* for next buffer */
725 bz->f1 = new_f1; /* next frame */
726
727 dev_kfree_skb_any(bcs->tx_skb);
728 bcs->tx_skb = NULL;
729 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
730 return;
731}
732
733/**********************************************/
734/* D-channel l1 state call for leased NT-mode */
735/**********************************************/
736static void
737dch_nt_l2l1(struct PStack *st, int pr, void *arg)
738{
739 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
740
741 switch (pr) {
742 case (PH_DATA | REQUEST):
743 case (PH_PULL | REQUEST):
744 case (PH_PULL | INDICATION):
745 st->l1.l1hw(st, pr, arg);
746 break;
747 case (PH_ACTIVATE | REQUEST):
748 st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
749 break;
750 case (PH_TESTLOOP | REQUEST):
751 if (1 & (long) arg)
752 debugl1(cs, "PH_TEST_LOOP B1");
753 if (2 & (long) arg)
754 debugl1(cs, "PH_TEST_LOOP B2");
755 if (!(3 & (long) arg))
756 debugl1(cs, "PH_TEST_LOOP DISABLED");
757 st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
758 break;
759 default:
760 if (cs->debug)
761 debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
762 break;
763 }
764}
765
766
767
768/***********************/
769/* set/reset echo mode */
770/***********************/
771static int
772hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
773{
774 u_long flags;
775 int i = *(unsigned int *) ic->parm.num;
776
777 if ((ic->arg == 98) &&
778 (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
779 spin_lock_irqsave(&cs->lock, flags);
780 Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */
781 Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */
782 udelay(10);
783 cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT;
784 Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); /* set NT-mode */
785 udelay(10);
786 Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* HFC ST G1 */
787 udelay(10);
788 Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
789 cs->dc.hfcpci.ph_state = 1;
790 cs->hw.hfcpci.nt_mode = 1;
791 cs->hw.hfcpci.nt_timer = 0;
792 cs->stlist->l2.l2l1 = dch_nt_l2l1;
793 spin_unlock_irqrestore(&cs->lock, flags);
794 debugl1(cs, "NT mode activated");
795 return (0);
796 }
797 if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) ||
798 (cs->hw.hfcpci.nt_mode) || (ic->arg != 12))
799 return (-EINVAL);
800
801 spin_lock_irqsave(&cs->lock, flags);
802 if (i) {
803 cs->logecho = 1;
804 cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */
805 cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
806 cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
807 } else {
808 cs->logecho = 0;
809 cs->hw.hfcpci.trm &= ~0x20; /* disable echo chan */
810 cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
811 cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
812 }
813 cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
814 cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
815 cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */
816 cs->hw.hfcpci.ctmt &= ~2;
817 Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
818 Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
819 Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
820 Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
821 Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
822 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
823 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
824 spin_unlock_irqrestore(&cs->lock, flags);
825 return (0);
826} /* hfcpci_auxcmd */
827
828/*****************************/
829/* E-channel receive routine */
830/*****************************/
831static void
832receive_emsg(struct IsdnCardState *cs)
833{
834 int rcnt;
835 int receive, count = 5;
836 bzfifo_type *bz;
837 u_char *bdata;
838 z_type *zp;
839 u_char *ptr, *ptr1, new_f2;
840 int total, maxlen, new_z2;
841 u_char e_buffer[256];
842
843 bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
844 bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
845 Begin:
846 count--;
847 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
848 debugl1(cs, "echo_rec_data blocked");
849 return;
850 }
851 if (bz->f1 != bz->f2) {
852 if (cs->debug & L1_DEB_ISAC)
853 debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)",
854 bz->f1, bz->f2);
855 zp = &bz->za[bz->f2];
856
857 rcnt = zp->z1 - zp->z2;
858 if (rcnt < 0)
859 rcnt += B_FIFO_SIZE;
860 rcnt++;
861 if (cs->debug & L1_DEB_ISAC)
862 debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
863 zp->z1, zp->z2, rcnt);
864 new_z2 = zp->z2 + rcnt; /* new position in fifo */
865 if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
866 new_z2 -= B_FIFO_SIZE; /* buffer wrap */
867 new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
868 if ((rcnt > 256 + 3) || (count < 4) ||
869 (*(bdata + (zp->z1 - B_SUB_VAL)))) {
870 if (cs->debug & L1_DEB_WARN)
871 debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
872 bz->za[new_f2].z2 = new_z2;
873 bz->f2 = new_f2; /* next buffer */
874 } else {
875 total = rcnt;
876 rcnt -= 3;
877 ptr = e_buffer;
878
879 if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
880 maxlen = rcnt; /* complete transfer */
881 else
882 maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
883
884 ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */
885 memcpy(ptr, ptr1, maxlen); /* copy data */
886 rcnt -= maxlen;
887
888 if (rcnt) { /* rest remaining */
889 ptr += maxlen;
890 ptr1 = bdata; /* start of buffer */
891 memcpy(ptr, ptr1, rcnt); /* rest */
892 }
893 bz->za[new_f2].z2 = new_z2;
894 bz->f2 = new_f2; /* next buffer */
895 if (cs->debug & DEB_DLOG_HEX) {
896 ptr = cs->dlog;
897 if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
898 *ptr++ = 'E';
899 *ptr++ = 'C';
900 *ptr++ = 'H';
901 *ptr++ = 'O';
902 *ptr++ = ':';
903 ptr += QuickHex(ptr, e_buffer, total - 3);
904 ptr--;
905 *ptr++ = '\n';
906 *ptr = 0;
907 HiSax_putstatus(cs, NULL, cs->dlog);
908 } else
909 HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
910 }
911 }
912
913 rcnt = bz->f1 - bz->f2;
914 if (rcnt < 0)
915 rcnt += MAX_B_FRAMES + 1;
916 if (rcnt > 1)
917 receive = 1;
918 else
919 receive = 0;
920 } else
921 receive = 0;
922 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
923 if (count && receive)
924 goto Begin;
925 return;
926} /* receive_emsg */
927
928/*********************/
929/* Interrupt handler */
930/*********************/
931static irqreturn_t
932hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
933{
934 u_long flags;
935 struct IsdnCardState *cs = dev_id;
936 u_char exval;
937 struct BCState *bcs;
938 int count = 15;
939 u_char val, stat;
940
941 if (!(cs->hw.hfcpci.int_m2 & 0x08)) {
942 debugl1(cs, "HFC-PCI: int_m2 %x not initialised", cs->hw.hfcpci.int_m2);
943 return IRQ_NONE; /* not initialised */
944 }
945 spin_lock_irqsave(&cs->lock, flags);
946 if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
947 val = Read_hfc(cs, HFCPCI_INT_S1);
948 if (cs->debug & L1_DEB_ISAC)
949 debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val);
950 } else {
951 spin_unlock_irqrestore(&cs->lock, flags);
952 return IRQ_NONE;
953 }
954 if (cs->debug & L1_DEB_ISAC)
955 debugl1(cs, "HFC-PCI irq %x %s", val,
956 test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
957 "locked" : "unlocked");
958 val &= cs->hw.hfcpci.int_m1;
959 if (val & 0x40) { /* state machine irq */
960 exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
961 if (cs->debug & L1_DEB_ISAC)
962 debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
963 exval);
964 cs->dc.hfcpci.ph_state = exval;
965 sched_event_D_pci(cs, D_L1STATECHANGE);
966 val &= ~0x40;
967 }
968 if (val & 0x80) { /* timer irq */
969 if (cs->hw.hfcpci.nt_mode) {
970 if ((--cs->hw.hfcpci.nt_timer) < 0)
971 sched_event_D_pci(cs, D_L1STATECHANGE);
972 }
973 val &= ~0x80;
974 Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
975 }
976 while (val) {
977 if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
978 cs->hw.hfcpci.int_s1 |= val;
979 spin_unlock_irqrestore(&cs->lock, flags);
980 return IRQ_HANDLED;
981 }
982 if (cs->hw.hfcpci.int_s1 & 0x18) {
983 exval = val;
984 val = cs->hw.hfcpci.int_s1;
985 cs->hw.hfcpci.int_s1 = exval;
986 }
987 if (val & 0x08) {
988 if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
989 if (cs->debug)
990 debugl1(cs, "hfcpci spurious 0x08 IRQ");
991 } else
992 main_rec_hfcpci(bcs);
993 }
994 if (val & 0x10) {
995 if (cs->logecho)
996 receive_emsg(cs);
997 else if (!(bcs = Sel_BCS(cs, 1))) {
998 if (cs->debug)
999 debugl1(cs, "hfcpci spurious 0x10 IRQ");
1000 } else
1001 main_rec_hfcpci(bcs);
1002 }
1003 if (val & 0x01) {
1004 if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
1005 if (cs->debug)
1006 debugl1(cs, "hfcpci spurious 0x01 IRQ");
1007 } else {
1008 if (bcs->tx_skb) {
1009 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1010 hfcpci_fill_fifo(bcs);
1011 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1012 } else
1013 debugl1(cs, "fill_data %d blocked", bcs->channel);
1014 } else {
1015 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
1016 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1017 hfcpci_fill_fifo(bcs);
1018 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1019 } else
1020 debugl1(cs, "fill_data %d blocked", bcs->channel);
1021 } else {
1022 hfcpci_sched_event(bcs, B_XMTBUFREADY);
1023 }
1024 }
1025 }
1026 }
1027 if (val & 0x02) {
1028 if (!(bcs = Sel_BCS(cs, 1))) {
1029 if (cs->debug)
1030 debugl1(cs, "hfcpci spurious 0x02 IRQ");
1031 } else {
1032 if (bcs->tx_skb) {
1033 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1034 hfcpci_fill_fifo(bcs);
1035 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1036 } else
1037 debugl1(cs, "fill_data %d blocked", bcs->channel);
1038 } else {
1039 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
1040 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1041 hfcpci_fill_fifo(bcs);
1042 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1043 } else
1044 debugl1(cs, "fill_data %d blocked", bcs->channel);
1045 } else {
1046 hfcpci_sched_event(bcs, B_XMTBUFREADY);
1047 }
1048 }
1049 }
1050 }
1051 if (val & 0x20) { /* receive dframe */
1052 receive_dmsg(cs);
1053 }
1054 if (val & 0x04) { /* dframe transmitted */
1055 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
1056 del_timer(&cs->dbusytimer);
1057 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
1058 sched_event_D_pci(cs, D_CLEARBUSY);
1059 if (cs->tx_skb) {
1060 if (cs->tx_skb->len) {
1061 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1062 hfcpci_fill_dfifo(cs);
1063 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1064 } else {
1065 debugl1(cs, "hfcpci_fill_dfifo irq blocked");
1066 }
1067 goto afterXPR;
1068 } else {
1069 dev_kfree_skb_irq(cs->tx_skb);
1070 cs->tx_cnt = 0;
1071 cs->tx_skb = NULL;
1072 }
1073 }
1074 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
1075 cs->tx_cnt = 0;
1076 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1077 hfcpci_fill_dfifo(cs);
1078 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1079 } else {
1080 debugl1(cs, "hfcpci_fill_dfifo irq blocked");
1081 }
1082 } else
1083 sched_event_D_pci(cs, D_XMTBUFREADY);
1084 }
1085 afterXPR:
1086 if (cs->hw.hfcpci.int_s1 && count--) {
1087 val = cs->hw.hfcpci.int_s1;
1088 cs->hw.hfcpci.int_s1 = 0;
1089 if (cs->debug & L1_DEB_ISAC)
1090 debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count);
1091 } else
1092 val = 0;
1093 }
1094 spin_unlock_irqrestore(&cs->lock, flags);
1095 return IRQ_HANDLED;
1096}
1097
1098/********************************************************************/
1099/* timer callback for D-chan busy resolution. Currently no function */
1100/********************************************************************/
1101static void
1102hfcpci_dbusy_timer(struct IsdnCardState *cs)
1103{
1104}
1105
1106/*************************************/
1107/* Layer 1 D-channel hardware access */
1108/*************************************/
1109static void
1110HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
1111{
1112 u_long flags;
1113 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
1114 struct sk_buff *skb = arg;
1115
1116 switch (pr) {
1117 case (PH_DATA | REQUEST):
1118 if (cs->debug & DEB_DLOG_HEX)
1119 LogFrame(cs, skb->data, skb->len);
1120 if (cs->debug & DEB_DLOG_VERBOSE)
1121 dlogframe(cs, skb, 0);
1122 spin_lock_irqsave(&cs->lock, flags);
1123 if (cs->tx_skb) {
1124 skb_queue_tail(&cs->sq, skb);
1125#ifdef L2FRAME_DEBUG /* psa */
1126 if (cs->debug & L1_DEB_LAPD)
1127 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
1128#endif
1129 } else {
1130 cs->tx_skb = skb;
1131 cs->tx_cnt = 0;
1132#ifdef L2FRAME_DEBUG /* psa */
1133 if (cs->debug & L1_DEB_LAPD)
1134 Logl2Frame(cs, skb, "PH_DATA", 0);
1135#endif
1136 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1137 hfcpci_fill_dfifo(cs);
1138 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1139 } else
1140 debugl1(cs, "hfcpci_fill_dfifo blocked");
1141
1142 }
1143 spin_unlock_irqrestore(&cs->lock, flags);
1144 break;
1145 case (PH_PULL | INDICATION):
1146 spin_lock_irqsave(&cs->lock, flags);
1147 if (cs->tx_skb) {
1148 if (cs->debug & L1_DEB_WARN)
1149 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
1150 skb_queue_tail(&cs->sq, skb);
1151 spin_unlock_irqrestore(&cs->lock, flags);
1152 break;
1153 }
1154 if (cs->debug & DEB_DLOG_HEX)
1155 LogFrame(cs, skb->data, skb->len);
1156 if (cs->debug & DEB_DLOG_VERBOSE)
1157 dlogframe(cs, skb, 0);
1158 cs->tx_skb = skb;
1159 cs->tx_cnt = 0;
1160#ifdef L2FRAME_DEBUG /* psa */
1161 if (cs->debug & L1_DEB_LAPD)
1162 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
1163#endif
1164 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1165 hfcpci_fill_dfifo(cs);
1166 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1167 } else
1168 debugl1(cs, "hfcpci_fill_dfifo blocked");
1169 spin_unlock_irqrestore(&cs->lock, flags);
1170 break;
1171 case (PH_PULL | REQUEST):
1172#ifdef L2FRAME_DEBUG /* psa */
1173 if (cs->debug & L1_DEB_LAPD)
1174 debugl1(cs, "-> PH_REQUEST_PULL");
1175#endif
1176 if (!cs->tx_skb) {
1177 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1178 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1179 } else
1180 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1181 break;
1182 case (HW_RESET | REQUEST):
1183 spin_lock_irqsave(&cs->lock, flags);
1184 Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3); /* HFC ST 3 */
1185 udelay(6);
1186 Write_hfc(cs, HFCPCI_STATES, 3); /* HFC ST 2 */
1187 cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
1188 Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1189 Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
1190 spin_unlock_irqrestore(&cs->lock, flags);
1191 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
1192 break;
1193 case (HW_ENABLE | REQUEST):
1194 spin_lock_irqsave(&cs->lock, flags);
1195 Write_hfc(cs, HFCPCI_STATES, HFCPCI_DO_ACTION);
1196 spin_unlock_irqrestore(&cs->lock, flags);
1197 break;
1198 case (HW_DEACTIVATE | REQUEST):
1199 spin_lock_irqsave(&cs->lock, flags);
1200 cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
1201 Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1202 spin_unlock_irqrestore(&cs->lock, flags);
1203 break;
1204 case (HW_INFO3 | REQUEST):
1205 spin_lock_irqsave(&cs->lock, flags);
1206 cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
1207 Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1208 spin_unlock_irqrestore(&cs->lock, flags);
1209 break;
1210 case (HW_TESTLOOP | REQUEST):
1211 spin_lock_irqsave(&cs->lock, flags);
1212 switch ((int) arg) {
1213 case (1):
1214 Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */
1215 Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */
1216 cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1;
1217 Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
1218 break;
1219
1220 case (2):
1221 Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* tx slot */
1222 Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* rx slot */
1223 cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08;
1224 Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
1225 break;
1226
1227 default:
1228 spin_unlock_irqrestore(&cs->lock, flags);
1229 if (cs->debug & L1_DEB_WARN)
1230 debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
1231 return;
1232 }
1233 cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */
1234 Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
1235 spin_unlock_irqrestore(&cs->lock, flags);
1236 break;
1237 default:
1238 if (cs->debug & L1_DEB_WARN)
1239 debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
1240 break;
1241 }
1242}
1243
1244/***********************************************/
1245/* called during init setting l1 stack pointer */
1246/***********************************************/
1247void
1248setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
1249{
1250 st->l1.l1hw = HFCPCI_l1hw;
1251}
1252
1253/**************************************/
1254/* send B-channel data if not blocked */
1255/**************************************/
1256static void
1257hfcpci_send_data(struct BCState *bcs)
1258{
1259 struct IsdnCardState *cs = bcs->cs;
1260
1261 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1262 hfcpci_fill_fifo(bcs);
1263 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1264 } else
1265 debugl1(cs, "send_data %d blocked", bcs->channel);
1266}
1267
1268/***************************************************************/
1269/* activate/deactivate hardware for selected channels and mode */
1270/***************************************************************/
1271void
1272mode_hfcpci(struct BCState *bcs, int mode, int bc)
1273{
1274 struct IsdnCardState *cs = bcs->cs;
1275 int fifo2;
1276
1277 if (cs->debug & L1_DEB_HSCX)
1278 debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d",
1279 mode, bc, bcs->channel);
1280 bcs->mode = mode;
1281 bcs->channel = bc;
1282 fifo2 = bc;
1283 if (cs->chanlimit > 1) {
1284 cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
1285 cs->hw.hfcpci.sctrl_e &= ~0x80;
1286 } else {
1287 if (bc) {
1288 if (mode != L1_MODE_NULL) {
1289 cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */
1290 cs->hw.hfcpci.sctrl_e |= 0x80;
1291 } else {
1292 cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
1293 cs->hw.hfcpci.sctrl_e &= ~0x80;
1294 }
1295 fifo2 = 0;
1296 } else {
1297 cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
1298 cs->hw.hfcpci.sctrl_e &= ~0x80;
1299 }
1300 }
1301 switch (mode) {
1302 case (L1_MODE_NULL):
1303 if (bc) {
1304 cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
1305 cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
1306 } else {
1307 cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA;
1308 cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA;
1309 }
1310 if (fifo2) {
1311 cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
1312 cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1313 } else {
1314 cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
1315 cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1316 }
1317 break;
1318 case (L1_MODE_TRANS):
1319 hfcpci_clear_fifo_rx(cs, fifo2);
1320 hfcpci_clear_fifo_tx(cs, fifo2);
1321 if (bc) {
1322 cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
1323 cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
1324 } else {
1325 cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
1326 cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
1327 }
1328 if (fifo2) {
1329 cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
1330 cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1331 cs->hw.hfcpci.ctmt |= 2;
1332 cs->hw.hfcpci.conn &= ~0x18;
1333 } else {
1334 cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
1335 cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1336 cs->hw.hfcpci.ctmt |= 1;
1337 cs->hw.hfcpci.conn &= ~0x03;
1338 }
1339 break;
1340 case (L1_MODE_HDLC):
1341 hfcpci_clear_fifo_rx(cs, fifo2);
1342 hfcpci_clear_fifo_tx(cs, fifo2);
1343 if (bc) {
1344 cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
1345 cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
1346 } else {
1347 cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
1348 cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
1349 }
1350 if (fifo2) {
1351 cs->hw.hfcpci.last_bfifo_cnt[1] = 0;
1352 cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
1353 cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1354 cs->hw.hfcpci.ctmt &= ~2;
1355 cs->hw.hfcpci.conn &= ~0x18;
1356 } else {
1357 cs->hw.hfcpci.last_bfifo_cnt[0] = 0;
1358 cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
1359 cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1360 cs->hw.hfcpci.ctmt &= ~1;
1361 cs->hw.hfcpci.conn &= ~0x03;
1362 }
1363 break;
1364 case (L1_MODE_EXTRN):
1365 if (bc) {
1366 cs->hw.hfcpci.conn |= 0x10;
1367 cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
1368 cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
1369 cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
1370 cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1371 } else {
1372 cs->hw.hfcpci.conn |= 0x02;
1373 cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
1374 cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
1375 cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
1376 cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1377 }
1378 break;
1379 }
1380 Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);
1381 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1382 Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
1383 Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
1384 Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
1385 Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
1386 Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
1387}
1388
1389/******************************/
1390/* Layer2 -> Layer 1 Transfer */
1391/******************************/
1392static void
1393hfcpci_l2l1(struct PStack *st, int pr, void *arg)
1394{
1395 struct BCState *bcs = st->l1.bcs;
1396 u_long flags;
1397 struct sk_buff *skb = arg;
1398
1399 switch (pr) {
1400 case (PH_DATA | REQUEST):
1401 spin_lock_irqsave(&bcs->cs->lock, flags);
1402 if (bcs->tx_skb) {
1403 skb_queue_tail(&bcs->squeue, skb);
1404 } else {
1405 bcs->tx_skb = skb;
1406// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1407 bcs->cs->BC_Send_Data(bcs);
1408 }
1409 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1410 break;
1411 case (PH_PULL | INDICATION):
1412 spin_lock_irqsave(&bcs->cs->lock, flags);
1413 if (bcs->tx_skb) {
1414 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1415 printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
1416 break;
1417 }
1418// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1419 bcs->tx_skb = skb;
1420 bcs->cs->BC_Send_Data(bcs);
1421 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1422 break;
1423 case (PH_PULL | REQUEST):
1424 if (!bcs->tx_skb) {
1425 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1426 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1427 } else
1428 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1429 break;
1430 case (PH_ACTIVATE | REQUEST):
1431 spin_lock_irqsave(&bcs->cs->lock, flags);
1432 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
1433 mode_hfcpci(bcs, st->l1.mode, st->l1.bc);
1434 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1435 l1_msg_b(st, pr, arg);
1436 break;
1437 case (PH_DEACTIVATE | REQUEST):
1438 l1_msg_b(st, pr, arg);
1439 break;
1440 case (PH_DEACTIVATE | CONFIRM):
1441 spin_lock_irqsave(&bcs->cs->lock, flags);
1442 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
1443 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1444 mode_hfcpci(bcs, 0, st->l1.bc);
1445 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1446 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
1447 break;
1448 }
1449}
1450
1451/******************************************/
1452/* deactivate B-channel access and queues */
1453/******************************************/
1454static void
1455close_hfcpci(struct BCState *bcs)
1456{
1457 mode_hfcpci(bcs, 0, bcs->channel);
1458 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
1459 skb_queue_purge(&bcs->rqueue);
1460 skb_queue_purge(&bcs->squeue);
1461 if (bcs->tx_skb) {
1462 dev_kfree_skb_any(bcs->tx_skb);
1463 bcs->tx_skb = NULL;
1464 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1465 }
1466 }
1467}
1468
1469/*************************************/
1470/* init B-channel queues and control */
1471/*************************************/
1472static int
1473open_hfcpcistate(struct IsdnCardState *cs, struct BCState *bcs)
1474{
1475 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
1476 skb_queue_head_init(&bcs->rqueue);
1477 skb_queue_head_init(&bcs->squeue);
1478 }
1479 bcs->tx_skb = NULL;
1480 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1481 bcs->event = 0;
1482 bcs->tx_cnt = 0;
1483 return (0);
1484}
1485
1486/*********************************/
1487/* inits the stack for B-channel */
1488/*********************************/
1489static int
1490setstack_2b(struct PStack *st, struct BCState *bcs)
1491{
1492 bcs->channel = st->l1.bc;
1493 if (open_hfcpcistate(st->l1.hardware, bcs))
1494 return (-1);
1495 st->l1.bcs = bcs;
1496 st->l2.l2l1 = hfcpci_l2l1;
1497 setstack_manager(st);
1498 bcs->st = st;
1499 setstack_l1_B(st);
1500 return (0);
1501}
1502
1503/***************************/
1504/* handle L1 state changes */
1505/***************************/
1506static void
1507hfcpci_bh(struct IsdnCardState *cs)
1508{
1509 u_long flags;
1510// struct PStack *stptr;
1511
1512 if (!cs)
1513 return;
1514 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
1515 if (!cs->hw.hfcpci.nt_mode)
1516 switch (cs->dc.hfcpci.ph_state) {
1517 case (0):
1518 l1_msg(cs, HW_RESET | INDICATION, NULL);
1519 break;
1520 case (3):
1521 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
1522 break;
1523 case (8):
1524 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
1525 break;
1526 case (6):
1527 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
1528 break;
1529 case (7):
1530 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
1531 break;
1532 default:
1533 break;
1534 } else {
1535 spin_lock_irqsave(&cs->lock, flags);
1536 switch (cs->dc.hfcpci.ph_state) {
1537 case (2):
1538 if (cs->hw.hfcpci.nt_timer < 0) {
1539 cs->hw.hfcpci.nt_timer = 0;
1540 cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
1541 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1542 /* Clear already pending ints */
1543 if (Read_hfc(cs, HFCPCI_INT_S1));
1544 Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
1545 udelay(10);
1546 Write_hfc(cs, HFCPCI_STATES, 4);
1547 cs->dc.hfcpci.ph_state = 4;
1548 } else {
1549 cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER;
1550 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1551 cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER;
1552 cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125;
1553 Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
1554 Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
1555 cs->hw.hfcpci.nt_timer = NT_T1_COUNT;
1556 Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3); /* allow G2 -> G3 transition */
1557 }
1558 break;
1559 case (1):
1560 case (3):
1561 case (4):
1562 cs->hw.hfcpci.nt_timer = 0;
1563 cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
1564 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1565 break;
1566 default:
1567 break;
1568 }
1569 spin_unlock_irqrestore(&cs->lock, flags);
1570 }
1571 }
1572 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
1573 DChannel_proc_rcv(cs);
1574 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
1575 DChannel_proc_xmt(cs);
1576}
1577
1578
1579/********************************/
1580/* called for card init message */
1581/********************************/
1582void __init
1583inithfcpci(struct IsdnCardState *cs)
1584{
1585 cs->bcs[0].BC_SetStack = setstack_2b;
1586 cs->bcs[1].BC_SetStack = setstack_2b;
1587 cs->bcs[0].BC_Close = close_hfcpci;
1588 cs->bcs[1].BC_Close = close_hfcpci;
1589 cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
1590 cs->dbusytimer.data = (long) cs;
1591 init_timer(&cs->dbusytimer);
1592 mode_hfcpci(cs->bcs, 0, 0);
1593 mode_hfcpci(cs->bcs + 1, 0, 1);
1594}
1595
1596
1597
1598/*******************************************/
1599/* handle card messages from control layer */
1600/*******************************************/
1601static int
1602hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
1603{
1604 u_long flags;
1605
1606 if (cs->debug & L1_DEB_ISAC)
1607 debugl1(cs, "HFCPCI: card_msg %x", mt);
1608 switch (mt) {
1609 case CARD_RESET:
1610 spin_lock_irqsave(&cs->lock, flags);
1611 reset_hfcpci(cs);
1612 spin_unlock_irqrestore(&cs->lock, flags);
1613 return (0);
1614 case CARD_RELEASE:
1615 release_io_hfcpci(cs);
1616 return (0);
1617 case CARD_INIT:
1618 spin_lock_irqsave(&cs->lock, flags);
1619 inithfcpci(cs);
1620 reset_hfcpci(cs);
1621 spin_unlock_irqrestore(&cs->lock, flags);
1622 msleep(80); /* Timeout 80ms */
1623 /* now switch timer interrupt off */
1624 spin_lock_irqsave(&cs->lock, flags);
1625 cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
1626 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1627 /* reinit mode reg */
1628 Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1629 spin_unlock_irqrestore(&cs->lock, flags);
1630 return (0);
1631 case CARD_TEST:
1632 return (0);
1633 }
1634 return (0);
1635}
1636
1637
1638/* this variable is used as card index when more than one cards are present */
1639static struct pci_dev *dev_hfcpci __initdata = NULL;
1640
1641#endif /* CONFIG_PCI */
1642
1643int __init
1644setup_hfcpci(struct IsdnCard *card)
1645{
1646 u_long flags;
1647 struct IsdnCardState *cs = card->cs;
1648 char tmp[64];
1649 int i;
1650 struct pci_dev *tmp_hfcpci = NULL;
1651
1652#ifdef __BIG_ENDIAN
1653#error "not running on big endian machines now"
1654#endif
1655 strcpy(tmp, hfcpci_revision);
1656 printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
1657#ifdef CONFIG_PCI
1658 cs->hw.hfcpci.int_s1 = 0;
1659 cs->dc.hfcpci.ph_state = 0;
1660 cs->hw.hfcpci.fifo = 255;
1661 if (cs->typ == ISDN_CTYPE_HFC_PCI) {
1662 i = 0;
1663 while (id_list[i].vendor_id) {
1664 tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
1665 id_list[i].device_id,
1666 dev_hfcpci);
1667 i++;
1668 if (tmp_hfcpci) {
1669 if (pci_enable_device(tmp_hfcpci))
1670 continue;
1671 pci_set_master(tmp_hfcpci);
1672 if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
1673 continue;
1674 else
1675 break;
1676 }
1677 }
1678
1679 if (tmp_hfcpci) {
1680 i--;
1681 dev_hfcpci = tmp_hfcpci; /* old device */
1682 cs->hw.hfcpci.dev = dev_hfcpci;
1683 cs->irq = dev_hfcpci->irq;
1684 if (!cs->irq) {
1685 printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
1686 return (0);
1687 }
1688 cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
1689 printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
1690 } else {
1691 printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
1692 return (0);
1693 }
1694 if (!cs->hw.hfcpci.pci_io) {
1695 printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
1696 return (0);
1697 }
1698 /* Allocate memory for FIFOS */
1699 /* Because the HFC-PCI needs a 32K physical alignment, we */
1700 /* need to allocate the double mem and align the address */
1701 if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
1702 printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
1703 return 0;
1704 }
1705 cs->hw.hfcpci.fifos = (void *)
1706 (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
1707 pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
1708 cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
1709 printk(KERN_INFO
1710 "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
1711 (u_int) cs->hw.hfcpci.pci_io,
1712 (u_int) cs->hw.hfcpci.fifos,
1713 (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
1714 cs->irq, HZ);
1715 spin_lock_irqsave(&cs->lock, flags);
1716 pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
1717 cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
1718 cs->hw.hfcpci.int_m1 = 0;
1719 Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1720 Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
1721 /* At this point the needed PCI config is done */
1722 /* fifos are still not enabled */
1723 INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs);
1724 cs->setstack_d = setstack_hfcpci;
1725 cs->BC_Send_Data = &hfcpci_send_data;
1726 cs->readisac = NULL;
1727 cs->writeisac = NULL;
1728 cs->readisacfifo = NULL;
1729 cs->writeisacfifo = NULL;
1730 cs->BC_Read_Reg = NULL;
1731 cs->BC_Write_Reg = NULL;
1732 cs->irq_func = &hfcpci_interrupt;
1733 cs->irq_flags |= SA_SHIRQ;
1734 cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
1735 cs->hw.hfcpci.timer.data = (long) cs;
1736 init_timer(&cs->hw.hfcpci.timer);
1737 cs->cardmsg = &hfcpci_card_msg;
1738 cs->auxcmd = &hfcpci_auxcmd;
1739 spin_unlock_irqrestore(&cs->lock, flags);
1740 return (1);
1741 } else
1742 return (0); /* no valid card type */
1743#else
1744 printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
1745 return (0);
1746#endif /* CONFIG_PCI */
1747}
diff --git a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h
new file mode 100644
index 00000000000..4df036ed1af
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_pci.h
@@ -0,0 +1,236 @@
1/* $Id: hfc_pci.h,v 1.10.2.2 2004/01/12 22:52:26 keil Exp $
2 *
3 * specific defines for CCD's HFC 2BDS0 PCI chips
4 *
5 * Author Werner Cornelius
6 * Copyright by Werner Cornelius <werner@isdn4linux.de>
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
13/*********************************************/
14/* thresholds for transparent B-channel mode */
15/* change mask and threshold simultaneously */
16/*********************************************/
17#define HFCPCI_BTRANS_THRESHOLD 128
18#define HFCPCI_BTRANS_THRESMASK 0x00
19
20
21
22/* defines for PCI config */
23
24#define PCI_ENA_MEMIO 0x02
25#define PCI_ENA_MASTER 0x04
26
27
28/* GCI/IOM bus monitor registers */
29
30#define HCFPCI_C_I 0x08
31#define HFCPCI_TRxR 0x0C
32#define HFCPCI_MON1_D 0x28
33#define HFCPCI_MON2_D 0x2C
34
35
36/* GCI/IOM bus timeslot registers */
37
38#define HFCPCI_B1_SSL 0x80
39#define HFCPCI_B2_SSL 0x84
40#define HFCPCI_AUX1_SSL 0x88
41#define HFCPCI_AUX2_SSL 0x8C
42#define HFCPCI_B1_RSL 0x90
43#define HFCPCI_B2_RSL 0x94
44#define HFCPCI_AUX1_RSL 0x98
45#define HFCPCI_AUX2_RSL 0x9C
46
47/* GCI/IOM bus data registers */
48
49#define HFCPCI_B1_D 0xA0
50#define HFCPCI_B2_D 0xA4
51#define HFCPCI_AUX1_D 0xA8
52#define HFCPCI_AUX2_D 0xAC
53
54/* GCI/IOM bus configuration registers */
55
56#define HFCPCI_MST_EMOD 0xB4
57#define HFCPCI_MST_MODE 0xB8
58#define HFCPCI_CONNECT 0xBC
59
60
61/* Interrupt and status registers */
62
63#define HFCPCI_FIFO_EN 0x44
64#define HFCPCI_TRM 0x48
65#define HFCPCI_B_MODE 0x4C
66#define HFCPCI_CHIP_ID 0x58
67#define HFCPCI_CIRM 0x60
68#define HFCPCI_CTMT 0x64
69#define HFCPCI_INT_M1 0x68
70#define HFCPCI_INT_M2 0x6C
71#define HFCPCI_INT_S1 0x78
72#define HFCPCI_INT_S2 0x7C
73#define HFCPCI_STATUS 0x70
74
75/* S/T section registers */
76
77#define HFCPCI_STATES 0xC0
78#define HFCPCI_SCTRL 0xC4
79#define HFCPCI_SCTRL_E 0xC8
80#define HFCPCI_SCTRL_R 0xCC
81#define HFCPCI_SQ 0xD0
82#define HFCPCI_CLKDEL 0xDC
83#define HFCPCI_B1_REC 0xF0
84#define HFCPCI_B1_SEND 0xF0
85#define HFCPCI_B2_REC 0xF4
86#define HFCPCI_B2_SEND 0xF4
87#define HFCPCI_D_REC 0xF8
88#define HFCPCI_D_SEND 0xF8
89#define HFCPCI_E_REC 0xFC
90
91
92/* bits in status register (READ) */
93#define HFCPCI_PCI_PROC 0x02
94#define HFCPCI_NBUSY 0x04
95#define HFCPCI_TIMER_ELAP 0x10
96#define HFCPCI_STATINT 0x20
97#define HFCPCI_FRAMEINT 0x40
98#define HFCPCI_ANYINT 0x80
99
100/* bits in CTMT (Write) */
101#define HFCPCI_CLTIMER 0x80
102#define HFCPCI_TIM3_125 0x04
103#define HFCPCI_TIM25 0x10
104#define HFCPCI_TIM50 0x14
105#define HFCPCI_TIM400 0x18
106#define HFCPCI_TIM800 0x1C
107#define HFCPCI_AUTO_TIMER 0x20
108#define HFCPCI_TRANSB2 0x02
109#define HFCPCI_TRANSB1 0x01
110
111/* bits in CIRM (Write) */
112#define HFCPCI_AUX_MSK 0x07
113#define HFCPCI_RESET 0x08
114#define HFCPCI_B1_REV 0x40
115#define HFCPCI_B2_REV 0x80
116
117/* bits in INT_M1 and INT_S1 */
118#define HFCPCI_INTS_B1TRANS 0x01
119#define HFCPCI_INTS_B2TRANS 0x02
120#define HFCPCI_INTS_DTRANS 0x04
121#define HFCPCI_INTS_B1REC 0x08
122#define HFCPCI_INTS_B2REC 0x10
123#define HFCPCI_INTS_DREC 0x20
124#define HFCPCI_INTS_L1STATE 0x40
125#define HFCPCI_INTS_TIMER 0x80
126
127/* bits in INT_M2 */
128#define HFCPCI_PROC_TRANS 0x01
129#define HFCPCI_GCI_I_CHG 0x02
130#define HFCPCI_GCI_MON_REC 0x04
131#define HFCPCI_IRQ_ENABLE 0x08
132#define HFCPCI_PMESEL 0x80
133
134/* bits in STATES */
135#define HFCPCI_STATE_MSK 0x0F
136#define HFCPCI_LOAD_STATE 0x10
137#define HFCPCI_ACTIVATE 0x20
138#define HFCPCI_DO_ACTION 0x40
139#define HFCPCI_NT_G2_G3 0x80
140
141/* bits in HFCD_MST_MODE */
142#define HFCPCI_MASTER 0x01
143#define HFCPCI_SLAVE 0x00
144/* remaining bits are for codecs control */
145
146/* bits in HFCD_SCTRL */
147#define SCTRL_B1_ENA 0x01
148#define SCTRL_B2_ENA 0x02
149#define SCTRL_MODE_TE 0x00
150#define SCTRL_MODE_NT 0x04
151#define SCTRL_LOW_PRIO 0x08
152#define SCTRL_SQ_ENA 0x10
153#define SCTRL_TEST 0x20
154#define SCTRL_NONE_CAP 0x40
155#define SCTRL_PWR_DOWN 0x80
156
157/* bits in SCTRL_E */
158#define HFCPCI_AUTO_AWAKE 0x01
159#define HFCPCI_DBIT_1 0x04
160#define HFCPCI_IGNORE_COL 0x08
161#define HFCPCI_CHG_B1_B2 0x80
162
163/****************************/
164/* bits in FIFO_EN register */
165/****************************/
166#define HFCPCI_FIFOEN_B1 0x03
167#define HFCPCI_FIFOEN_B2 0x0C
168#define HFCPCI_FIFOEN_DTX 0x10
169#define HFCPCI_FIFOEN_B1TX 0x01
170#define HFCPCI_FIFOEN_B1RX 0x02
171#define HFCPCI_FIFOEN_B2TX 0x04
172#define HFCPCI_FIFOEN_B2RX 0x08
173
174
175/***********************************/
176/* definitions of fifo memory area */
177/***********************************/
178#define MAX_D_FRAMES 15
179#define MAX_B_FRAMES 31
180#define B_SUB_VAL 0x200
181#define B_FIFO_SIZE (0x2000 - B_SUB_VAL)
182#define D_FIFO_SIZE 512
183#define D_FREG_MASK 0xF
184
185typedef struct {
186 unsigned short z1; /* Z1 pointer 16 Bit */
187 unsigned short z2; /* Z2 pointer 16 Bit */
188 } z_type;
189
190typedef struct {
191 u_char data[D_FIFO_SIZE]; /* FIFO data space */
192 u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
193 u_char f1,f2; /* f pointers */
194 u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
195 z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */
196 u_char fill3[0x4000-0x2100]; /* align 16K */
197 } dfifo_type;
198
199typedef struct {
200 z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */
201 u_char f1,f2; /* f pointers */
202 u_char fill[0x2100-0x2082]; /* alignment */
203 } bzfifo_type;
204
205
206typedef union {
207 struct {
208 dfifo_type d_tx; /* D-send channel */
209 dfifo_type d_rx; /* D-receive channel */
210 } d_chan;
211 struct {
212 u_char fill1[0x200];
213 u_char txdat_b1[B_FIFO_SIZE];
214 bzfifo_type txbz_b1;
215
216 bzfifo_type txbz_b2;
217 u_char txdat_b2[B_FIFO_SIZE];
218
219 u_char fill2[D_FIFO_SIZE];
220
221 u_char rxdat_b1[B_FIFO_SIZE];
222 bzfifo_type rxbz_b1;
223
224 bzfifo_type rxbz_b2;
225 u_char rxdat_b2[B_FIFO_SIZE];
226 } b_chans;
227 u_char fill[32768];
228 } fifo_area;
229
230
231#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c)
232#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b))
233
234extern void main_irq_hcpci(struct BCState *bcs);
235extern void inithfcpci(struct IsdnCardState *cs);
236extern void releasehfcpci(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
new file mode 100644
index 00000000000..a307fcb6c63
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -0,0 +1,1521 @@
1/* $Id: hfc_sx.c,v 1.12.2.5 2004/02/11 13:21:33 keil Exp $
2 *
3 * level driver for Cologne Chip Designs hfc-s+/sp based cards
4 *
5 * Author Werner Cornelius
6 * based on existing driver for CCD HFC PCI cards
7 * Copyright by Werner Cornelius <werner@isdn4linux.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include <linux/init.h>
15#include "hisax.h"
16#include "hfc_sx.h"
17#include "isdnl1.h"
18#include <linux/interrupt.h>
19#include <linux/isapnp.h>
20
21extern const char *CardType[];
22
23static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";
24
25/***************************************/
26/* IRQ-table for CCDs demo board */
27/* IRQs 6,5,10,11,12,15 are supported */
28/***************************************/
29
30/* Teles 16.3c Vendor Id TAG2620, Version 1.0, Vendor version 2.1
31 *
32 * Thanks to Uwe Wisniewski
33 *
34 * ISA-SLOT Signal PIN
35 * B25 IRQ3 92 IRQ_G
36 * B23 IRQ5 94 IRQ_A
37 * B4 IRQ2/9 95 IRQ_B
38 * D3 IRQ10 96 IRQ_C
39 * D4 IRQ11 97 IRQ_D
40 * D5 IRQ12 98 IRQ_E
41 * D6 IRQ15 99 IRQ_F
42 */
43
44#undef CCD_DEMO_BOARD
45#ifdef CCD_DEMO_BOARD
46static u_char ccd_sp_irqtab[16] = {
47 0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6
48};
49#else /* Teles 16.3c */
50static u_char ccd_sp_irqtab[16] = {
51 0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6
52};
53#endif
54#define NT_T1_COUNT 20 /* number of 3.125ms interrupts for G2 timeout */
55
56#define byteout(addr,val) outb(val,addr)
57#define bytein(addr) inb(addr)
58
59/******************************/
60/* In/Out access to registers */
61/******************************/
62static inline void
63Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val)
64{
65 byteout(cs->hw.hfcsx.base+1, regnum);
66 byteout(cs->hw.hfcsx.base, val);
67}
68
69static inline u_char
70Read_hfc(struct IsdnCardState *cs, u_char regnum)
71{
72 u_char ret;
73
74 byteout(cs->hw.hfcsx.base+1, regnum);
75 ret = bytein(cs->hw.hfcsx.base);
76 return(ret);
77}
78
79
80/**************************************************/
81/* select a fifo and remember which one for reuse */
82/**************************************************/
83static void
84fifo_select(struct IsdnCardState *cs, u_char fifo)
85{
86 if (fifo == cs->hw.hfcsx.last_fifo)
87 return; /* still valid */
88
89 byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL);
90 byteout(cs->hw.hfcsx.base, fifo);
91 while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
92 udelay(4);
93 byteout(cs->hw.hfcsx.base, fifo);
94 while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
95}
96
97/******************************************/
98/* reset the specified fifo to defaults. */
99/* If its a send fifo init needed markers */
100/******************************************/
101static void
102reset_fifo(struct IsdnCardState *cs, u_char fifo)
103{
104 fifo_select(cs, fifo); /* first select the fifo */
105 byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);
106 byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */
107 udelay(1);
108 while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
109}
110
111
112/*************************************************************/
113/* write_fifo writes the skb contents to the desired fifo */
114/* if no space is available or an error occurs 0 is returned */
115/* the skb is not released in any way. */
116/*************************************************************/
117static int
118write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max)
119{
120 unsigned short *msp;
121 int fifo_size, count, z1, z2;
122 u_char f_msk, f1, f2, *src;
123
124 if (skb->len <= 0) return(0);
125 if (fifo & 1) return(0); /* no write fifo */
126
127 fifo_select(cs, fifo);
128 if (fifo & 4) {
129 fifo_size = D_FIFO_SIZE; /* D-channel */
130 f_msk = MAX_D_FRAMES;
131 if (trans_max) return(0); /* only HDLC */
132 }
133 else {
134 fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */
135 f_msk = MAX_B_FRAMES;
136 }
137
138 z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
139 z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
140
141 /* Check for transparent mode */
142 if (trans_max) {
143 z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
144 z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
145 count = z2 - z1;
146 if (count <= 0)
147 count += fifo_size; /* free bytes */
148 if (count < skb->len+1) return(0); /* no room */
149 count = fifo_size - count; /* bytes still not send */
150 if (count > 2 * trans_max) return(0); /* delay to long */
151 count = skb->len;
152 src = skb->data;
153 while (count--)
154 Write_hfc(cs, HFCSX_FIF_DWR, *src++);
155 return(1); /* success */
156 }
157
158 msp = ((struct hfcsx_extra *)(cs->hw.hfcsx.extra))->marker;
159 msp += (((fifo >> 1) & 3) * (MAX_B_FRAMES+1));
160 f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;
161 f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;
162
163 count = f1 - f2; /* frame count actually buffered */
164 if (count < 0)
165 count += (f_msk + 1); /* if wrap around */
166 if (count > f_msk-1) {
167 if (cs->debug & L1_DEB_ISAC_FIFO)
168 debugl1(cs, "hfcsx_write_fifo %d more as %d frames",fifo,f_msk-1);
169 return(0);
170 }
171
172 *(msp + f1) = z1; /* remember marker */
173
174 if (cs->debug & L1_DEB_ISAC_FIFO)
175 debugl1(cs, "hfcsx_write_fifo %d f1(%x) f2(%x) z1(f1)(%x)",
176 fifo, f1, f2, z1);
177 /* now determine free bytes in FIFO buffer */
178 count = *(msp + f2) - z1;
179 if (count <= 0)
180 count += fifo_size; /* count now contains available bytes */
181
182 if (cs->debug & L1_DEB_ISAC_FIFO)
183 debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)",
184 fifo, skb->len, count);
185 if (count < skb->len) {
186 if (cs->debug & L1_DEB_ISAC_FIFO)
187 debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo);
188 return(0);
189 }
190
191 count = skb->len; /* get frame len */
192 src = skb->data; /* source pointer */
193 while (count--)
194 Write_hfc(cs, HFCSX_FIF_DWR, *src++);
195
196 Read_hfc(cs, HFCSX_FIF_INCF1); /* increment F1 */
197 udelay(1);
198 while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
199 return(1);
200}
201
202/***************************************************************/
203/* read_fifo reads data to an skb from the desired fifo */
204/* if no data is available or an error occurs NULL is returned */
205/* the skb is not released in any way. */
206/***************************************************************/
207static struct sk_buff *
208read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
209{ int fifo_size, count, z1, z2;
210 u_char f_msk, f1, f2, *dst;
211 struct sk_buff *skb;
212
213 if (!(fifo & 1)) return(NULL); /* no read fifo */
214 fifo_select(cs, fifo);
215 if (fifo & 4) {
216 fifo_size = D_FIFO_SIZE; /* D-channel */
217 f_msk = MAX_D_FRAMES;
218 if (trans_max) return(NULL); /* only hdlc */
219 }
220 else {
221 fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */
222 f_msk = MAX_B_FRAMES;
223 }
224
225 /* transparent mode */
226 if (trans_max) {
227 z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
228 z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
229 z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
230 z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
231 /* now determine bytes in actual FIFO buffer */
232 count = z1 - z2;
233 if (count <= 0)
234 count += fifo_size; /* count now contains buffered bytes */
235 count++;
236 if (count > trans_max)
237 count = trans_max; /* limit length */
238 if ((skb = dev_alloc_skb(count))) {
239 dst = skb_put(skb, count);
240 while (count--)
241 *dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
242 return(skb);
243 }
244 else return(NULL); /* no memory */
245 }
246
247 do {
248 f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;
249 f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;
250
251 if (f1 == f2) return(NULL); /* no frame available */
252
253 z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
254 z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
255 z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
256 z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
257
258 if (cs->debug & L1_DEB_ISAC_FIFO)
259 debugl1(cs, "hfcsx_read_fifo %d f1(%x) f2(%x) z1(f2)(%x) z2(f2)(%x)",
260 fifo, f1, f2, z1, z2);
261 /* now determine bytes in actual FIFO buffer */
262 count = z1 - z2;
263 if (count <= 0)
264 count += fifo_size; /* count now contains buffered bytes */
265 count++;
266
267 if (cs->debug & L1_DEB_ISAC_FIFO)
268 debugl1(cs, "hfcsx_read_fifo %d count %ld)",
269 fifo, count);
270
271 if ((count > fifo_size) || (count < 4)) {
272 if (cs->debug & L1_DEB_WARN)
273 debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);
274 while (count) {
275 count--; /* empty fifo */
276 Read_hfc(cs, HFCSX_FIF_DRD);
277 }
278 skb = NULL;
279 } else
280 if ((skb = dev_alloc_skb(count - 3))) {
281 count -= 3;
282 dst = skb_put(skb, count);
283
284 while (count--)
285 *dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
286
287 Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 1 */
288 Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 2 */
289 if (Read_hfc(cs, HFCSX_FIF_DRD)) {
290 dev_kfree_skb_irq(skb);
291 if (cs->debug & L1_DEB_ISAC_FIFO)
292 debugl1(cs, "hfcsx_read_fifo %d crc error", fifo);
293 skb = NULL;
294 }
295 } else {
296 printk(KERN_WARNING "HFC-SX: receive out of memory\n");
297 return(NULL);
298 }
299
300 Read_hfc(cs, HFCSX_FIF_INCF2); /* increment F2 */
301 udelay(1);
302 while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
303 udelay(1);
304 } while (!skb); /* retry in case of crc error */
305 return(skb);
306}
307
308/******************************************/
309/* free hardware resources used by driver */
310/******************************************/
311void
312release_io_hfcsx(struct IsdnCardState *cs)
313{
314 cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
315 Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
316 Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */
317 msleep(30); /* Timeout 30ms */
318 Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */
319 del_timer(&cs->hw.hfcsx.timer);
320 release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */
321 kfree(cs->hw.hfcsx.extra);
322 cs->hw.hfcsx.extra = NULL;
323}
324
325/**********************************************************/
326/* set_fifo_size determines the size of the RAM and FIFOs */
327/* returning 0 -> need to reset the chip again. */
328/**********************************************************/
329static int set_fifo_size(struct IsdnCardState *cs)
330{
331
332 if (cs->hw.hfcsx.b_fifo_size) return(1); /* already determined */
333
334 if ((cs->hw.hfcsx.chip >> 4) == 9) {
335 cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_32K;
336 return(1);
337 }
338
339 cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_8K;
340 cs->hw.hfcsx.cirm |= 0x10; /* only 8K of ram */
341 return(0);
342
343}
344
345/********************************************************************************/
346/* function called to reset the HFC SX chip. A complete software reset of chip */
347/* and fifos is done. */
348/********************************************************************************/
349static void
350reset_hfcsx(struct IsdnCardState *cs)
351{
352 cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
353 Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
354
355 printk(KERN_INFO "HFC_SX: resetting card\n");
356 while (1) {
357 Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */
358 mdelay(30);
359 Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */
360 mdelay(20);
361 if (Read_hfc(cs, HFCSX_STATUS) & 2)
362 printk(KERN_WARNING "HFC-SX init bit busy\n");
363 cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */
364 if (!set_fifo_size(cs)) continue;
365 break;
366 }
367
368 cs->hw.hfcsx.trm = 0 + HFCSX_BTRANS_THRESMASK; /* no echo connect , threshold */
369 Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
370
371 Write_hfc(cs, HFCSX_CLKDEL, 0x0e); /* ST-Bit delay for TE-Mode */
372 cs->hw.hfcsx.sctrl_e = HFCSX_AUTO_AWAKE;
373 Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e); /* S/T Auto awake */
374 cs->hw.hfcsx.bswapped = 0; /* no exchange */
375 cs->hw.hfcsx.nt_mode = 0; /* we are in TE mode */
376 cs->hw.hfcsx.ctmt = HFCSX_TIM3_125 | HFCSX_AUTO_TIMER;
377 Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
378
379 cs->hw.hfcsx.int_m1 = HFCSX_INTS_DTRANS | HFCSX_INTS_DREC |
380 HFCSX_INTS_L1STATE | HFCSX_INTS_TIMER;
381 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
382
383 /* Clear already pending ints */
384 if (Read_hfc(cs, HFCSX_INT_S1));
385
386 Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 2); /* HFC ST 2 */
387 udelay(10);
388 Write_hfc(cs, HFCSX_STATES, 2); /* HFC ST 2 */
389 cs->hw.hfcsx.mst_m = HFCSX_MASTER; /* HFC Master Mode */
390
391 Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
392 cs->hw.hfcsx.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
393 Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
394 cs->hw.hfcsx.sctrl_r = 0;
395 Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
396
397 /* Init GCI/IOM2 in master mode */
398 /* Slots 0 and 1 are set for B-chan 1 and 2 */
399 /* D- and monitor/CI channel are not enabled */
400 /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
401 /* STIO2 is used as data input, B1+B2 from IOM->ST */
402 /* ST B-channel send disabled -> continous 1s */
403 /* The IOM slots are always enabled */
404 cs->hw.hfcsx.conn = 0x36; /* set data flow directions */
405 Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
406 Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */
407 Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */
408 Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */
409 Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */
410
411 /* Finally enable IRQ output */
412 cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
413 Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
414 if (Read_hfc(cs, HFCSX_INT_S2));
415}
416
417/***************************************************/
418/* Timer function called when kernel timer expires */
419/***************************************************/
420static void
421hfcsx_Timer(struct IsdnCardState *cs)
422{
423 cs->hw.hfcsx.timer.expires = jiffies + 75;
424 /* WD RESET */
425/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcsx.ctmt | 0x80);
426 add_timer(&cs->hw.hfcsx.timer);
427 */
428}
429
430/************************************************/
431/* select a b-channel entry matching and active */
432/************************************************/
433static
434struct BCState *
435Sel_BCS(struct IsdnCardState *cs, int channel)
436{
437 if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
438 return (&cs->bcs[0]);
439 else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
440 return (&cs->bcs[1]);
441 else
442 return (NULL);
443}
444
445/*******************************/
446/* D-channel receive procedure */
447/*******************************/
448static
449int
450receive_dmsg(struct IsdnCardState *cs)
451{
452 struct sk_buff *skb;
453 int count = 5;
454
455 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
456 debugl1(cs, "rec_dmsg blocked");
457 return (1);
458 }
459
460 do {
461 skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);
462 if (skb) {
463 skb_queue_tail(&cs->rq, skb);
464 schedule_event(cs, D_RCVBUFREADY);
465 }
466 } while (--count && skb);
467
468 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
469 return (1);
470}
471
472/**********************************/
473/* B-channel main receive routine */
474/**********************************/
475void
476main_rec_hfcsx(struct BCState *bcs)
477{
478 struct IsdnCardState *cs = bcs->cs;
479 int count = 5;
480 struct sk_buff *skb;
481
482 Begin:
483 count--;
484 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
485 debugl1(cs, "rec_data %d blocked", bcs->channel);
486 return;
487 }
488 skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ?
489 HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,
490 (bcs->mode == L1_MODE_TRANS) ?
491 HFCSX_BTRANS_THRESHOLD : 0);
492
493 if (skb) {
494 skb_queue_tail(&bcs->rqueue, skb);
495 schedule_event(bcs, B_RCVBUFREADY);
496 }
497
498 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
499 if (count && skb)
500 goto Begin;
501 return;
502}
503
504/**************************/
505/* D-channel send routine */
506/**************************/
507static void
508hfcsx_fill_dfifo(struct IsdnCardState *cs)
509{
510 if (!cs->tx_skb)
511 return;
512 if (cs->tx_skb->len <= 0)
513 return;
514
515 if (write_fifo(cs, cs->tx_skb, HFCSX_SEL_D_TX, 0)) {
516 dev_kfree_skb_any(cs->tx_skb);
517 cs->tx_skb = NULL;
518 }
519 return;
520}
521
522/**************************/
523/* B-channel send routine */
524/**************************/
525static void
526hfcsx_fill_fifo(struct BCState *bcs)
527{
528 struct IsdnCardState *cs = bcs->cs;
529
530 if (!bcs->tx_skb)
531 return;
532 if (bcs->tx_skb->len <= 0)
533 return;
534
535 if (write_fifo(cs, bcs->tx_skb,
536 ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ?
537 HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX,
538 (bcs->mode == L1_MODE_TRANS) ?
539 HFCSX_BTRANS_THRESHOLD : 0)) {
540
541 bcs->tx_cnt -= bcs->tx_skb->len;
542 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
543 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
544 u_long flags;
545 spin_lock_irqsave(&bcs->aclock, flags);
546 bcs->ackcnt += bcs->tx_skb->len;
547 spin_unlock_irqrestore(&bcs->aclock, flags);
548 schedule_event(bcs, B_ACKPENDING);
549 }
550 dev_kfree_skb_any(bcs->tx_skb);
551 bcs->tx_skb = NULL;
552 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
553 }
554}
555
556/**********************************************/
557/* D-channel l1 state call for leased NT-mode */
558/**********************************************/
559static void
560dch_nt_l2l1(struct PStack *st, int pr, void *arg)
561{
562 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
563
564 switch (pr) {
565 case (PH_DATA | REQUEST):
566 case (PH_PULL | REQUEST):
567 case (PH_PULL | INDICATION):
568 st->l1.l1hw(st, pr, arg);
569 break;
570 case (PH_ACTIVATE | REQUEST):
571 st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
572 break;
573 case (PH_TESTLOOP | REQUEST):
574 if (1 & (long) arg)
575 debugl1(cs, "PH_TEST_LOOP B1");
576 if (2 & (long) arg)
577 debugl1(cs, "PH_TEST_LOOP B2");
578 if (!(3 & (long) arg))
579 debugl1(cs, "PH_TEST_LOOP DISABLED");
580 st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
581 break;
582 default:
583 if (cs->debug)
584 debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
585 break;
586 }
587}
588
589
590
591/***********************/
592/* set/reset echo mode */
593/***********************/
594static int
595hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
596{
597 unsigned long flags;
598 int i = *(unsigned int *) ic->parm.num;
599
600 if ((ic->arg == 98) &&
601 (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {
602 spin_lock_irqsave(&cs->lock, flags);
603 Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */
604 udelay(10);
605 cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;
606 Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl); /* set NT-mode */
607 udelay(10);
608 Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 1); /* HFC ST G1 */
609 udelay(10);
610 Write_hfc(cs, HFCSX_STATES, 1 | HFCSX_ACTIVATE | HFCSX_DO_ACTION);
611 cs->dc.hfcsx.ph_state = 1;
612 cs->hw.hfcsx.nt_mode = 1;
613 cs->hw.hfcsx.nt_timer = 0;
614 spin_unlock_irqrestore(&cs->lock, flags);
615 cs->stlist->l2.l2l1 = dch_nt_l2l1;
616 debugl1(cs, "NT mode activated");
617 return (0);
618 }
619 if ((cs->chanlimit > 1) || (cs->hw.hfcsx.bswapped) ||
620 (cs->hw.hfcsx.nt_mode) || (ic->arg != 12))
621 return (-EINVAL);
622
623 if (i) {
624 cs->logecho = 1;
625 cs->hw.hfcsx.trm |= 0x20; /* enable echo chan */
626 cs->hw.hfcsx.int_m1 |= HFCSX_INTS_B2REC;
627 /* reset Channel !!!!! */
628 } else {
629 cs->logecho = 0;
630 cs->hw.hfcsx.trm &= ~0x20; /* disable echo chan */
631 cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_B2REC;
632 }
633 cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;
634 cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
635 cs->hw.hfcsx.conn |= 0x10; /* B2-IOM -> B2-ST */
636 cs->hw.hfcsx.ctmt &= ~2;
637 spin_lock_irqsave(&cs->lock, flags);
638 Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
639 Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
640 Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
641 Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
642 Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
643 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
644 spin_unlock_irqrestore(&cs->lock, flags);
645 return (0);
646} /* hfcsx_auxcmd */
647
648/*****************************/
649/* E-channel receive routine */
650/*****************************/
651static void
652receive_emsg(struct IsdnCardState *cs)
653{
654 int count = 5;
655 u_char *ptr;
656 struct sk_buff *skb;
657
658 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
659 debugl1(cs, "echo_rec_data blocked");
660 return;
661 }
662 do {
663 skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);
664 if (skb) {
665 if (cs->debug & DEB_DLOG_HEX) {
666 ptr = cs->dlog;
667 if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
668 *ptr++ = 'E';
669 *ptr++ = 'C';
670 *ptr++ = 'H';
671 *ptr++ = 'O';
672 *ptr++ = ':';
673 ptr += QuickHex(ptr, skb->data, skb->len);
674 ptr--;
675 *ptr++ = '\n';
676 *ptr = 0;
677 HiSax_putstatus(cs, NULL, cs->dlog);
678 } else
679 HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len);
680 }
681 dev_kfree_skb_any(skb);
682 }
683 } while (--count && skb);
684
685 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
686 return;
687} /* receive_emsg */
688
689
690/*********************/
691/* Interrupt handler */
692/*********************/
693static irqreturn_t
694hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
695{
696 struct IsdnCardState *cs = dev_id;
697 u_char exval;
698 struct BCState *bcs;
699 int count = 15;
700 u_long flags;
701 u_char val, stat;
702
703 if (!(cs->hw.hfcsx.int_m2 & 0x08))
704 return IRQ_NONE; /* not initialised */
705
706 spin_lock_irqsave(&cs->lock, flags);
707 if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) {
708 val = Read_hfc(cs, HFCSX_INT_S1);
709 if (cs->debug & L1_DEB_ISAC)
710 debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val);
711 } else {
712 spin_unlock_irqrestore(&cs->lock, flags);
713 return IRQ_NONE;
714 }
715 if (cs->debug & L1_DEB_ISAC)
716 debugl1(cs, "HFC-SX irq %x %s", val,
717 test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
718 "locked" : "unlocked");
719 val &= cs->hw.hfcsx.int_m1;
720 if (val & 0x40) { /* state machine irq */
721 exval = Read_hfc(cs, HFCSX_STATES) & 0xf;
722 if (cs->debug & L1_DEB_ISAC)
723 debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,
724 exval);
725 cs->dc.hfcsx.ph_state = exval;
726 schedule_event(cs, D_L1STATECHANGE);
727 val &= ~0x40;
728 }
729 if (val & 0x80) { /* timer irq */
730 if (cs->hw.hfcsx.nt_mode) {
731 if ((--cs->hw.hfcsx.nt_timer) < 0)
732 schedule_event(cs, D_L1STATECHANGE);
733 }
734 val &= ~0x80;
735 Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
736 }
737 while (val) {
738 if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
739 cs->hw.hfcsx.int_s1 |= val;
740 spin_unlock_irqrestore(&cs->lock, flags);
741 return IRQ_HANDLED;
742 }
743 if (cs->hw.hfcsx.int_s1 & 0x18) {
744 exval = val;
745 val = cs->hw.hfcsx.int_s1;
746 cs->hw.hfcsx.int_s1 = exval;
747 }
748 if (val & 0x08) {
749 if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {
750 if (cs->debug)
751 debugl1(cs, "hfcsx spurious 0x08 IRQ");
752 } else
753 main_rec_hfcsx(bcs);
754 }
755 if (val & 0x10) {
756 if (cs->logecho)
757 receive_emsg(cs);
758 else if (!(bcs = Sel_BCS(cs, 1))) {
759 if (cs->debug)
760 debugl1(cs, "hfcsx spurious 0x10 IRQ");
761 } else
762 main_rec_hfcsx(bcs);
763 }
764 if (val & 0x01) {
765 if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {
766 if (cs->debug)
767 debugl1(cs, "hfcsx spurious 0x01 IRQ");
768 } else {
769 if (bcs->tx_skb) {
770 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
771 hfcsx_fill_fifo(bcs);
772 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
773 } else
774 debugl1(cs, "fill_data %d blocked", bcs->channel);
775 } else {
776 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
777 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
778 hfcsx_fill_fifo(bcs);
779 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
780 } else
781 debugl1(cs, "fill_data %d blocked", bcs->channel);
782 } else {
783 schedule_event(bcs, B_XMTBUFREADY);
784 }
785 }
786 }
787 }
788 if (val & 0x02) {
789 if (!(bcs = Sel_BCS(cs, 1))) {
790 if (cs->debug)
791 debugl1(cs, "hfcsx spurious 0x02 IRQ");
792 } else {
793 if (bcs->tx_skb) {
794 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
795 hfcsx_fill_fifo(bcs);
796 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
797 } else
798 debugl1(cs, "fill_data %d blocked", bcs->channel);
799 } else {
800 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
801 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
802 hfcsx_fill_fifo(bcs);
803 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
804 } else
805 debugl1(cs, "fill_data %d blocked", bcs->channel);
806 } else {
807 schedule_event(bcs, B_XMTBUFREADY);
808 }
809 }
810 }
811 }
812 if (val & 0x20) { /* receive dframe */
813 receive_dmsg(cs);
814 }
815 if (val & 0x04) { /* dframe transmitted */
816 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
817 del_timer(&cs->dbusytimer);
818 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
819 schedule_event(cs, D_CLEARBUSY);
820 if (cs->tx_skb) {
821 if (cs->tx_skb->len) {
822 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
823 hfcsx_fill_dfifo(cs);
824 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
825 } else {
826 debugl1(cs, "hfcsx_fill_dfifo irq blocked");
827 }
828 goto afterXPR;
829 } else {
830 dev_kfree_skb_irq(cs->tx_skb);
831 cs->tx_cnt = 0;
832 cs->tx_skb = NULL;
833 }
834 }
835 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
836 cs->tx_cnt = 0;
837 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
838 hfcsx_fill_dfifo(cs);
839 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
840 } else {
841 debugl1(cs, "hfcsx_fill_dfifo irq blocked");
842 }
843 } else
844 schedule_event(cs, D_XMTBUFREADY);
845 }
846 afterXPR:
847 if (cs->hw.hfcsx.int_s1 && count--) {
848 val = cs->hw.hfcsx.int_s1;
849 cs->hw.hfcsx.int_s1 = 0;
850 if (cs->debug & L1_DEB_ISAC)
851 debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count);
852 } else
853 val = 0;
854 }
855 spin_unlock_irqrestore(&cs->lock, flags);
856 return IRQ_HANDLED;
857}
858
859/********************************************************************/
860/* timer callback for D-chan busy resolution. Currently no function */
861/********************************************************************/
862static void
863hfcsx_dbusy_timer(struct IsdnCardState *cs)
864{
865}
866
867/*************************************/
868/* Layer 1 D-channel hardware access */
869/*************************************/
870static void
871HFCSX_l1hw(struct PStack *st, int pr, void *arg)
872{
873 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
874 struct sk_buff *skb = arg;
875 u_long flags;
876
877 switch (pr) {
878 case (PH_DATA | REQUEST):
879 if (cs->debug & DEB_DLOG_HEX)
880 LogFrame(cs, skb->data, skb->len);
881 if (cs->debug & DEB_DLOG_VERBOSE)
882 dlogframe(cs, skb, 0);
883 spin_lock_irqsave(&cs->lock, flags);
884 if (cs->tx_skb) {
885 skb_queue_tail(&cs->sq, skb);
886#ifdef L2FRAME_DEBUG /* psa */
887 if (cs->debug & L1_DEB_LAPD)
888 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
889#endif
890 } else {
891 cs->tx_skb = skb;
892 cs->tx_cnt = 0;
893#ifdef L2FRAME_DEBUG /* psa */
894 if (cs->debug & L1_DEB_LAPD)
895 Logl2Frame(cs, skb, "PH_DATA", 0);
896#endif
897 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
898 hfcsx_fill_dfifo(cs);
899 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
900 } else
901 debugl1(cs, "hfcsx_fill_dfifo blocked");
902
903 }
904 spin_unlock_irqrestore(&cs->lock, flags);
905 break;
906 case (PH_PULL | INDICATION):
907 spin_lock_irqsave(&cs->lock, flags);
908 if (cs->tx_skb) {
909 if (cs->debug & L1_DEB_WARN)
910 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
911 skb_queue_tail(&cs->sq, skb);
912 spin_unlock_irqrestore(&cs->lock, flags);
913 break;
914 }
915 if (cs->debug & DEB_DLOG_HEX)
916 LogFrame(cs, skb->data, skb->len);
917 if (cs->debug & DEB_DLOG_VERBOSE)
918 dlogframe(cs, skb, 0);
919 cs->tx_skb = skb;
920 cs->tx_cnt = 0;
921#ifdef L2FRAME_DEBUG /* psa */
922 if (cs->debug & L1_DEB_LAPD)
923 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
924#endif
925 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
926 hfcsx_fill_dfifo(cs);
927 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
928 } else
929 debugl1(cs, "hfcsx_fill_dfifo blocked");
930 spin_unlock_irqrestore(&cs->lock, flags);
931 break;
932 case (PH_PULL | REQUEST):
933#ifdef L2FRAME_DEBUG /* psa */
934 if (cs->debug & L1_DEB_LAPD)
935 debugl1(cs, "-> PH_REQUEST_PULL");
936#endif
937 if (!cs->tx_skb) {
938 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
939 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
940 } else
941 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
942 break;
943 case (HW_RESET | REQUEST):
944 spin_lock_irqsave(&cs->lock, flags);
945 Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */
946 udelay(6);
947 Write_hfc(cs, HFCSX_STATES, 3); /* HFC ST 2 */
948 cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
949 Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
950 Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
951 spin_unlock_irqrestore(&cs->lock, flags);
952 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
953 break;
954 case (HW_ENABLE | REQUEST):
955 spin_lock_irqsave(&cs->lock, flags);
956 Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
957 spin_unlock_irqrestore(&cs->lock, flags);
958 break;
959 case (HW_DEACTIVATE | REQUEST):
960 spin_lock_irqsave(&cs->lock, flags);
961 cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER;
962 Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
963 spin_unlock_irqrestore(&cs->lock, flags);
964 break;
965 case (HW_INFO3 | REQUEST):
966 spin_lock_irqsave(&cs->lock, flags);
967 cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
968 Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
969 spin_unlock_irqrestore(&cs->lock, flags);
970 break;
971 case (HW_TESTLOOP | REQUEST):
972 spin_lock_irqsave(&cs->lock, flags);
973 switch ((int) arg) {
974 case (1):
975 Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */
976 Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* rx slot */
977 cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;
978 Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
979 break;
980 case (2):
981 Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */
982 Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */
983 cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;
984 Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
985 break;
986 default:
987 spin_unlock_irqrestore(&cs->lock, flags);
988 if (cs->debug & L1_DEB_WARN)
989 debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);
990 return;
991 }
992 cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */
993 Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
994 spin_unlock_irqrestore(&cs->lock, flags);
995 break;
996 default:
997 if (cs->debug & L1_DEB_WARN)
998 debugl1(cs, "hfcsx_l1hw unknown pr %4x", pr);
999 break;
1000 }
1001}
1002
1003/***********************************************/
1004/* called during init setting l1 stack pointer */
1005/***********************************************/
1006void
1007setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
1008{
1009 st->l1.l1hw = HFCSX_l1hw;
1010}
1011
1012/**************************************/
1013/* send B-channel data if not blocked */
1014/**************************************/
1015static void
1016hfcsx_send_data(struct BCState *bcs)
1017{
1018 struct IsdnCardState *cs = bcs->cs;
1019
1020 if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1021 hfcsx_fill_fifo(bcs);
1022 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1023 } else
1024 debugl1(cs, "send_data %d blocked", bcs->channel);
1025}
1026
1027/***************************************************************/
1028/* activate/deactivate hardware for selected channels and mode */
1029/***************************************************************/
1030void
1031mode_hfcsx(struct BCState *bcs, int mode, int bc)
1032{
1033 struct IsdnCardState *cs = bcs->cs;
1034 int fifo2;
1035
1036 if (cs->debug & L1_DEB_HSCX)
1037 debugl1(cs, "HFCSX bchannel mode %d bchan %d/%d",
1038 mode, bc, bcs->channel);
1039 bcs->mode = mode;
1040 bcs->channel = bc;
1041 fifo2 = bc;
1042 if (cs->chanlimit > 1) {
1043 cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
1044 cs->hw.hfcsx.sctrl_e &= ~0x80;
1045 } else {
1046 if (bc) {
1047 if (mode != L1_MODE_NULL) {
1048 cs->hw.hfcsx.bswapped = 1; /* B1 and B2 exchanged */
1049 cs->hw.hfcsx.sctrl_e |= 0x80;
1050 } else {
1051 cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
1052 cs->hw.hfcsx.sctrl_e &= ~0x80;
1053 }
1054 fifo2 = 0;
1055 } else {
1056 cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
1057 cs->hw.hfcsx.sctrl_e &= ~0x80;
1058 }
1059 }
1060 switch (mode) {
1061 case (L1_MODE_NULL):
1062 if (bc) {
1063 cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
1064 cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;
1065 } else {
1066 cs->hw.hfcsx.sctrl &= ~SCTRL_B1_ENA;
1067 cs->hw.hfcsx.sctrl_r &= ~SCTRL_B1_ENA;
1068 }
1069 if (fifo2) {
1070 cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
1071 } else {
1072 cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
1073 }
1074 break;
1075 case (L1_MODE_TRANS):
1076 if (bc) {
1077 cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
1078 cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
1079 } else {
1080 cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
1081 cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
1082 }
1083 if (fifo2) {
1084 cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
1085 cs->hw.hfcsx.ctmt |= 2;
1086 cs->hw.hfcsx.conn &= ~0x18;
1087 } else {
1088 cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
1089 cs->hw.hfcsx.ctmt |= 1;
1090 cs->hw.hfcsx.conn &= ~0x03;
1091 }
1092 break;
1093 case (L1_MODE_HDLC):
1094 if (bc) {
1095 cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
1096 cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
1097 } else {
1098 cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
1099 cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
1100 }
1101 if (fifo2) {
1102 cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
1103 cs->hw.hfcsx.ctmt &= ~2;
1104 cs->hw.hfcsx.conn &= ~0x18;
1105 } else {
1106 cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
1107 cs->hw.hfcsx.ctmt &= ~1;
1108 cs->hw.hfcsx.conn &= ~0x03;
1109 }
1110 break;
1111 case (L1_MODE_EXTRN):
1112 if (bc) {
1113 cs->hw.hfcsx.conn |= 0x10;
1114 cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
1115 cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
1116 cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
1117 } else {
1118 cs->hw.hfcsx.conn |= 0x02;
1119 cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
1120 cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
1121 cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
1122 }
1123 break;
1124 }
1125 Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e);
1126 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
1127 Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
1128 Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
1129 Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
1130 Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
1131 if (mode != L1_MODE_EXTRN) {
1132 reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX);
1133 reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX);
1134 }
1135}
1136
1137/******************************/
1138/* Layer2 -> Layer 1 Transfer */
1139/******************************/
1140static void
1141hfcsx_l2l1(struct PStack *st, int pr, void *arg)
1142{
1143 struct BCState *bcs = st->l1.bcs;
1144 struct sk_buff *skb = arg;
1145 u_long flags;
1146
1147 switch (pr) {
1148 case (PH_DATA | REQUEST):
1149 spin_lock_irqsave(&bcs->cs->lock, flags);
1150 if (bcs->tx_skb) {
1151 skb_queue_tail(&bcs->squeue, skb);
1152 } else {
1153 bcs->tx_skb = skb;
1154// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1155 bcs->cs->BC_Send_Data(bcs);
1156 }
1157 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1158 break;
1159 case (PH_PULL | INDICATION):
1160 spin_lock_irqsave(&bcs->cs->lock, flags);
1161 if (bcs->tx_skb) {
1162 printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
1163 } else {
1164// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1165 bcs->tx_skb = skb;
1166 bcs->cs->BC_Send_Data(bcs);
1167 }
1168 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1169 break;
1170 case (PH_PULL | REQUEST):
1171 if (!bcs->tx_skb) {
1172 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1173 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1174 } else
1175 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1176 break;
1177 case (PH_ACTIVATE | REQUEST):
1178 spin_lock_irqsave(&bcs->cs->lock, flags);
1179 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
1180 mode_hfcsx(bcs, st->l1.mode, st->l1.bc);
1181 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1182 l1_msg_b(st, pr, arg);
1183 break;
1184 case (PH_DEACTIVATE | REQUEST):
1185 l1_msg_b(st, pr, arg);
1186 break;
1187 case (PH_DEACTIVATE | CONFIRM):
1188 spin_lock_irqsave(&bcs->cs->lock, flags);
1189 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
1190 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1191 mode_hfcsx(bcs, 0, st->l1.bc);
1192 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1193 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
1194 break;
1195 }
1196}
1197
1198/******************************************/
1199/* deactivate B-channel access and queues */
1200/******************************************/
1201static void
1202close_hfcsx(struct BCState *bcs)
1203{
1204 mode_hfcsx(bcs, 0, bcs->channel);
1205 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
1206 skb_queue_purge(&bcs->rqueue);
1207 skb_queue_purge(&bcs->squeue);
1208 if (bcs->tx_skb) {
1209 dev_kfree_skb_any(bcs->tx_skb);
1210 bcs->tx_skb = NULL;
1211 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1212 }
1213 }
1214}
1215
1216/*************************************/
1217/* init B-channel queues and control */
1218/*************************************/
1219static int
1220open_hfcsxstate(struct IsdnCardState *cs, struct BCState *bcs)
1221{
1222 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
1223 skb_queue_head_init(&bcs->rqueue);
1224 skb_queue_head_init(&bcs->squeue);
1225 }
1226 bcs->tx_skb = NULL;
1227 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1228 bcs->event = 0;
1229 bcs->tx_cnt = 0;
1230 return (0);
1231}
1232
1233/*********************************/
1234/* inits the stack for B-channel */
1235/*********************************/
1236static int
1237setstack_2b(struct PStack *st, struct BCState *bcs)
1238{
1239 bcs->channel = st->l1.bc;
1240 if (open_hfcsxstate(st->l1.hardware, bcs))
1241 return (-1);
1242 st->l1.bcs = bcs;
1243 st->l2.l2l1 = hfcsx_l2l1;
1244 setstack_manager(st);
1245 bcs->st = st;
1246 setstack_l1_B(st);
1247 return (0);
1248}
1249
1250/***************************/
1251/* handle L1 state changes */
1252/***************************/
1253static void
1254hfcsx_bh(struct IsdnCardState *cs)
1255{
1256 u_long flags;
1257
1258 if (!cs)
1259 return;
1260 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
1261 if (!cs->hw.hfcsx.nt_mode)
1262 switch (cs->dc.hfcsx.ph_state) {
1263 case (0):
1264 l1_msg(cs, HW_RESET | INDICATION, NULL);
1265 break;
1266 case (3):
1267 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
1268 break;
1269 case (8):
1270 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
1271 break;
1272 case (6):
1273 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
1274 break;
1275 case (7):
1276 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
1277 break;
1278 default:
1279 break;
1280 } else {
1281 switch (cs->dc.hfcsx.ph_state) {
1282 case (2):
1283 spin_lock_irqsave(&cs->lock, flags);
1284 if (cs->hw.hfcsx.nt_timer < 0) {
1285 cs->hw.hfcsx.nt_timer = 0;
1286 cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
1287 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
1288 /* Clear already pending ints */
1289 if (Read_hfc(cs, HFCSX_INT_S1));
1290
1291 Write_hfc(cs, HFCSX_STATES, 4 | HFCSX_LOAD_STATE);
1292 udelay(10);
1293 Write_hfc(cs, HFCSX_STATES, 4);
1294 cs->dc.hfcsx.ph_state = 4;
1295 } else {
1296 cs->hw.hfcsx.int_m1 |= HFCSX_INTS_TIMER;
1297 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
1298 cs->hw.hfcsx.ctmt &= ~HFCSX_AUTO_TIMER;
1299 cs->hw.hfcsx.ctmt |= HFCSX_TIM3_125;
1300 Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
1301 Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
1302 cs->hw.hfcsx.nt_timer = NT_T1_COUNT;
1303 Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */
1304 }
1305 spin_unlock_irqrestore(&cs->lock, flags);
1306 break;
1307 case (1):
1308 case (3):
1309 case (4):
1310 spin_lock_irqsave(&cs->lock, flags);
1311 cs->hw.hfcsx.nt_timer = 0;
1312 cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
1313 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
1314 spin_unlock_irqrestore(&cs->lock, flags);
1315 break;
1316 default:
1317 break;
1318 }
1319 }
1320 }
1321 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
1322 DChannel_proc_rcv(cs);
1323 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
1324 DChannel_proc_xmt(cs);
1325}
1326
1327
1328/********************************/
1329/* called for card init message */
1330/********************************/
1331void __devinit
1332inithfcsx(struct IsdnCardState *cs)
1333{
1334 cs->setstack_d = setstack_hfcsx;
1335 cs->BC_Send_Data = &hfcsx_send_data;
1336 cs->bcs[0].BC_SetStack = setstack_2b;
1337 cs->bcs[1].BC_SetStack = setstack_2b;
1338 cs->bcs[0].BC_Close = close_hfcsx;
1339 cs->bcs[1].BC_Close = close_hfcsx;
1340 mode_hfcsx(cs->bcs, 0, 0);
1341 mode_hfcsx(cs->bcs + 1, 0, 1);
1342}
1343
1344
1345
1346/*******************************************/
1347/* handle card messages from control layer */
1348/*******************************************/
1349static int
1350hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
1351{
1352 u_long flags;
1353
1354 if (cs->debug & L1_DEB_ISAC)
1355 debugl1(cs, "HFCSX: card_msg %x", mt);
1356 switch (mt) {
1357 case CARD_RESET:
1358 spin_lock_irqsave(&cs->lock, flags);
1359 reset_hfcsx(cs);
1360 spin_unlock_irqrestore(&cs->lock, flags);
1361 return (0);
1362 case CARD_RELEASE:
1363 release_io_hfcsx(cs);
1364 return (0);
1365 case CARD_INIT:
1366 spin_lock_irqsave(&cs->lock, flags);
1367 inithfcsx(cs);
1368 spin_unlock_irqrestore(&cs->lock, flags);
1369 msleep(80); /* Timeout 80ms */
1370 /* now switch timer interrupt off */
1371 spin_lock_irqsave(&cs->lock, flags);
1372 cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
1373 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
1374 /* reinit mode reg */
1375 Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
1376 spin_unlock_irqrestore(&cs->lock, flags);
1377 return (0);
1378 case CARD_TEST:
1379 return (0);
1380 }
1381 return (0);
1382}
1383
1384#ifdef __ISAPNP__
1385static struct isapnp_device_id hfc_ids[] __devinitdata = {
1386 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
1387 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
1388 (unsigned long) "Teles 16.3c2" },
1389 { 0, }
1390};
1391
1392static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];
1393static struct pnp_card *pnp_c __devinitdata = NULL;
1394#endif
1395
1396int __devinit
1397setup_hfcsx(struct IsdnCard *card)
1398{
1399 struct IsdnCardState *cs = card->cs;
1400 char tmp[64];
1401
1402 strcpy(tmp, hfcsx_revision);
1403 printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
1404#ifdef __ISAPNP__
1405 if (!card->para[1] && isapnp_present()) {
1406 struct pnp_dev *pnp_d;
1407 while(ipid->card_vendor) {
1408 if ((pnp_c = pnp_find_card(ipid->card_vendor,
1409 ipid->card_device, pnp_c))) {
1410 pnp_d = NULL;
1411 if ((pnp_d = pnp_find_dev(pnp_c,
1412 ipid->vendor, ipid->function, pnp_d))) {
1413 int err;
1414
1415 printk(KERN_INFO "HiSax: %s detected\n",
1416 (char *)ipid->driver_data);
1417 pnp_disable_dev(pnp_d);
1418 err = pnp_activate_dev(pnp_d);
1419 if (err<0) {
1420 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
1421 __FUNCTION__, err);
1422 return(0);
1423 }
1424 card->para[1] = pnp_port_start(pnp_d, 0);
1425 card->para[0] = pnp_irq(pnp_d, 0);
1426 if (!card->para[0] || !card->para[1]) {
1427 printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
1428 card->para[0], card->para[1]);
1429 pnp_disable_dev(pnp_d);
1430 return(0);
1431 }
1432 break;
1433 } else {
1434 printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
1435 }
1436 }
1437 ipid++;
1438 pnp_c = NULL;
1439 }
1440 if (!ipid->card_vendor) {
1441 printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
1442 return(0);
1443 }
1444 }
1445#endif
1446 cs->hw.hfcsx.base = card->para[1] & 0xfffe;
1447 cs->irq = card->para[0];
1448 cs->hw.hfcsx.int_s1 = 0;
1449 cs->dc.hfcsx.ph_state = 0;
1450 cs->hw.hfcsx.fifo = 255;
1451 if ((cs->typ == ISDN_CTYPE_HFC_SX) ||
1452 (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) {
1453 if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) {
1454 printk(KERN_WARNING
1455 "HiSax: HFC-SX io-base %#lx already in use\n",
1456 cs->hw.hfcsx.base);
1457 return(0);
1458 }
1459 byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
1460 byteout(cs->hw.hfcsx.base + 1,
1461 ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
1462 udelay(10);
1463 cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
1464 switch (cs->hw.hfcsx.chip >> 4) {
1465 case 1:
1466 tmp[0] ='+';
1467 break;
1468 case 9:
1469 tmp[0] ='P';
1470 break;
1471 default:
1472 printk(KERN_WARNING
1473 "HFC-SX: invalid chip id 0x%x\n",
1474 cs->hw.hfcsx.chip >> 4);
1475 release_region(cs->hw.hfcsx.base, 2);
1476 return(0);
1477 }
1478 if (!ccd_sp_irqtab[cs->irq & 0xF]) {
1479 printk(KERN_WARNING
1480 "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF);
1481 release_region(cs->hw.hfcsx.base, 2);
1482 return(0);
1483 }
1484 if (!(cs->hw.hfcsx.extra = (void *)
1485 kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
1486 release_region(cs->hw.hfcsx.base, 2);
1487 printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
1488 return(0);
1489 }
1490 printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
1491 tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ);
1492 cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */
1493 cs->hw.hfcsx.int_m1 = 0;
1494 Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
1495 Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
1496 } else
1497 return (0); /* no valid card type */
1498
1499 cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
1500 cs->dbusytimer.data = (long) cs;
1501 init_timer(&cs->dbusytimer);
1502 INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs);
1503 cs->readisac = NULL;
1504 cs->writeisac = NULL;
1505 cs->readisacfifo = NULL;
1506 cs->writeisacfifo = NULL;
1507 cs->BC_Read_Reg = NULL;
1508 cs->BC_Write_Reg = NULL;
1509 cs->irq_func = &hfcsx_interrupt;
1510
1511 cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
1512 cs->hw.hfcsx.timer.data = (long) cs;
1513 cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
1514 cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
1515 init_timer(&cs->hw.hfcsx.timer);
1516
1517 reset_hfcsx(cs);
1518 cs->cardmsg = &hfcsx_card_msg;
1519 cs->auxcmd = &hfcsx_auxcmd;
1520 return (1);
1521}
diff --git a/drivers/isdn/hisax/hfc_sx.h b/drivers/isdn/hisax/hfc_sx.h
new file mode 100644
index 00000000000..12f54159344
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_sx.h
@@ -0,0 +1,197 @@
1/* $Id: hfc_sx.h,v 1.2.6.1 2001/09/23 22:24:48 kai Exp $
2 *
3 * specific defines for CCD's HFC 2BDS0 S+,SP chips
4 *
5 * Author Werner Cornelius
6 * based on existing driver for CCD HFC PCI cards
7 * Copyright by Werner Cornelius <werner@isdn4linux.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14/*********************************************/
15/* thresholds for transparent B-channel mode */
16/* change mask and threshold simultaneously */
17/*********************************************/
18#define HFCSX_BTRANS_THRESHOLD 128
19#define HFCSX_BTRANS_THRESMASK 0x00
20
21/* GCI/IOM bus monitor registers */
22
23#define HFCSX_C_I 0x02
24#define HFCSX_TRxR 0x03
25#define HFCSX_MON1_D 0x0A
26#define HFCSX_MON2_D 0x0B
27
28
29/* GCI/IOM bus timeslot registers */
30
31#define HFCSX_B1_SSL 0x20
32#define HFCSX_B2_SSL 0x21
33#define HFCSX_AUX1_SSL 0x22
34#define HFCSX_AUX2_SSL 0x23
35#define HFCSX_B1_RSL 0x24
36#define HFCSX_B2_RSL 0x25
37#define HFCSX_AUX1_RSL 0x26
38#define HFCSX_AUX2_RSL 0x27
39
40/* GCI/IOM bus data registers */
41
42#define HFCSX_B1_D 0x28
43#define HFCSX_B2_D 0x29
44#define HFCSX_AUX1_D 0x2A
45#define HFCSX_AUX2_D 0x2B
46
47/* GCI/IOM bus configuration registers */
48
49#define HFCSX_MST_EMOD 0x2D
50#define HFCSX_MST_MODE 0x2E
51#define HFCSX_CONNECT 0x2F
52
53
54/* Interrupt and status registers */
55
56#define HFCSX_TRM 0x12
57#define HFCSX_B_MODE 0x13
58#define HFCSX_CHIP_ID 0x16
59#define HFCSX_CIRM 0x18
60#define HFCSX_CTMT 0x19
61#define HFCSX_INT_M1 0x1A
62#define HFCSX_INT_M2 0x1B
63#define HFCSX_INT_S1 0x1E
64#define HFCSX_INT_S2 0x1F
65#define HFCSX_STATUS 0x1C
66
67/* S/T section registers */
68
69#define HFCSX_STATES 0x30
70#define HFCSX_SCTRL 0x31
71#define HFCSX_SCTRL_E 0x32
72#define HFCSX_SCTRL_R 0x33
73#define HFCSX_SQ 0x34
74#define HFCSX_CLKDEL 0x37
75#define HFCSX_B1_REC 0x3C
76#define HFCSX_B1_SEND 0x3C
77#define HFCSX_B2_REC 0x3D
78#define HFCSX_B2_SEND 0x3D
79#define HFCSX_D_REC 0x3E
80#define HFCSX_D_SEND 0x3E
81#define HFCSX_E_REC 0x3F
82
83/****************/
84/* FIFO section */
85/****************/
86#define HFCSX_FIF_SEL 0x10
87#define HFCSX_FIF_Z1L 0x80
88#define HFCSX_FIF_Z1H 0x84
89#define HFCSX_FIF_Z2L 0x88
90#define HFCSX_FIF_Z2H 0x8C
91#define HFCSX_FIF_INCF1 0xA8
92#define HFCSX_FIF_DWR 0xAC
93#define HFCSX_FIF_F1 0xB0
94#define HFCSX_FIF_F2 0xB4
95#define HFCSX_FIF_INCF2 0xB8
96#define HFCSX_FIF_DRD 0xBC
97
98/* bits in status register (READ) */
99#define HFCSX_SX_PROC 0x02
100#define HFCSX_NBUSY 0x04
101#define HFCSX_TIMER_ELAP 0x10
102#define HFCSX_STATINT 0x20
103#define HFCSX_FRAMEINT 0x40
104#define HFCSX_ANYINT 0x80
105
106/* bits in CTMT (Write) */
107#define HFCSX_CLTIMER 0x80
108#define HFCSX_TIM3_125 0x04
109#define HFCSX_TIM25 0x10
110#define HFCSX_TIM50 0x14
111#define HFCSX_TIM400 0x18
112#define HFCSX_TIM800 0x1C
113#define HFCSX_AUTO_TIMER 0x20
114#define HFCSX_TRANSB2 0x02
115#define HFCSX_TRANSB1 0x01
116
117/* bits in CIRM (Write) */
118#define HFCSX_IRQ_SELMSK 0x07
119#define HFCSX_IRQ_SELDIS 0x00
120#define HFCSX_RESET 0x08
121#define HFCSX_FIFO_RESET 0x80
122
123
124/* bits in INT_M1 and INT_S1 */
125#define HFCSX_INTS_B1TRANS 0x01
126#define HFCSX_INTS_B2TRANS 0x02
127#define HFCSX_INTS_DTRANS 0x04
128#define HFCSX_INTS_B1REC 0x08
129#define HFCSX_INTS_B2REC 0x10
130#define HFCSX_INTS_DREC 0x20
131#define HFCSX_INTS_L1STATE 0x40
132#define HFCSX_INTS_TIMER 0x80
133
134/* bits in INT_M2 */
135#define HFCSX_PROC_TRANS 0x01
136#define HFCSX_GCI_I_CHG 0x02
137#define HFCSX_GCI_MON_REC 0x04
138#define HFCSX_IRQ_ENABLE 0x08
139
140/* bits in STATES */
141#define HFCSX_STATE_MSK 0x0F
142#define HFCSX_LOAD_STATE 0x10
143#define HFCSX_ACTIVATE 0x20
144#define HFCSX_DO_ACTION 0x40
145#define HFCSX_NT_G2_G3 0x80
146
147/* bits in HFCD_MST_MODE */
148#define HFCSX_MASTER 0x01
149#define HFCSX_SLAVE 0x00
150/* remaining bits are for codecs control */
151
152/* bits in HFCD_SCTRL */
153#define SCTRL_B1_ENA 0x01
154#define SCTRL_B2_ENA 0x02
155#define SCTRL_MODE_TE 0x00
156#define SCTRL_MODE_NT 0x04
157#define SCTRL_LOW_PRIO 0x08
158#define SCTRL_SQ_ENA 0x10
159#define SCTRL_TEST 0x20
160#define SCTRL_NONE_CAP 0x40
161#define SCTRL_PWR_DOWN 0x80
162
163/* bits in SCTRL_E */
164#define HFCSX_AUTO_AWAKE 0x01
165#define HFCSX_DBIT_1 0x04
166#define HFCSX_IGNORE_COL 0x08
167#define HFCSX_CHG_B1_B2 0x80
168
169/**********************************/
170/* definitions for FIFO selection */
171/**********************************/
172#define HFCSX_SEL_D_RX 5
173#define HFCSX_SEL_D_TX 4
174#define HFCSX_SEL_B1_RX 1
175#define HFCSX_SEL_B1_TX 0
176#define HFCSX_SEL_B2_RX 3
177#define HFCSX_SEL_B2_TX 2
178
179#define MAX_D_FRAMES 15
180#define MAX_B_FRAMES 31
181#define B_SUB_VAL_32K 0x0200
182#define B_FIFO_SIZE_32K (0x2000 - B_SUB_VAL_32K)
183#define B_SUB_VAL_8K 0x1A00
184#define B_FIFO_SIZE_8K (0x2000 - B_SUB_VAL_8K)
185#define D_FIFO_SIZE 512
186#define D_FREG_MASK 0xF
187
188/************************************************************/
189/* structure holding additional dynamic data -> send marker */
190/************************************************************/
191struct hfcsx_extra {
192 unsigned short marker[2*(MAX_B_FRAMES+1) + (MAX_D_FRAMES+1)];
193};
194
195extern void main_irq_hfcsx(struct BCState *bcs);
196extern void inithfcsx(struct IsdnCardState *cs);
197extern void releasehfcsx(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
new file mode 100644
index 00000000000..ffd74b84f50
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -0,0 +1,1828 @@
1/*
2 * hfc_usb.c
3 *
4 * $Id: hfc_usb.c,v 4.34 2005/01/26 17:25:53 martinb1 Exp $
5 *
6 * modular HiSax ISDN driver for Colognechip HFC-S USB chip
7 *
8 * Authors : Peter Sprenger (sprenger@moving-bytes.de)
9 * Martin Bachem (info@colognechip.com)
10 *
11 * based on the first hfc_usb driver of
12 * Werner Cornelius (werner@isdn-development.de)
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 * See Version Histroy at the bottom of this file
29 *
30*/
31
32#include <linux/types.h>
33#include <linux/stddef.h>
34#include <linux/timer.h>
35#include <linux/config.h>
36#include <linux/init.h>
37#include <linux/module.h>
38#include <linux/kernel_stat.h>
39#include <linux/usb.h>
40#include <linux/kernel.h>
41#include <linux/smp_lock.h>
42#include <linux/sched.h>
43#include "hisax.h"
44#include "hisax_if.h"
45#include "hfc_usb.h"
46
47/*
48* Version Information
49* (do not modify the CVS Makros $Revision: 4.34 $ and $Date: 2005/01/26 17:25:53 $ !)
50*/
51static const char *hfcusb_revision =
52 "Revision: 4.34 $ Date: 2005/01/26 17:25:53 $ ";
53
54/* Hisax debug support
55* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG
56*/
57#ifdef CONFIG_HISAX_DEBUG
58#include <linux/moduleparam.h>
59#define __debug_variable hfc_debug
60#include "hisax_debug.h"
61static u_int debug;
62module_param(debug, uint, 0);
63int hfc_debug;
64#endif
65
66
67/****************************************/
68/* data defining the devices to be used */
69/****************************************/
70static struct usb_device_id hfc_usb_idtab[] = {
71 {USB_DEVICE(0x0959, 0x2bd0)}, /* Colognechip USB eval TA */
72 {USB_DEVICE(0x0675, 0x1688)}, /* DrayTek miniVigor 128 USB ISDN TA */
73 {USB_DEVICE(0x07b0, 0x0007)}, /* Billion USB TA 2 */
74 {USB_DEVICE(0x0742, 0x2008)}, /* Stollmann USB TA */
75 {USB_DEVICE(0x0742, 0x2009)}, /* Aceex USB ISDN TA */
76 {USB_DEVICE(0x0742, 0x200A)}, /* OEM USB ISDN TA */
77 {USB_DEVICE(0x08e3, 0x0301)}, /* OliTec ISDN USB */
78 {USB_DEVICE(0x07fa, 0x0846)}, /* Bewan ISDN USB TA */
79 {USB_DEVICE(0x07fa, 0x0847)}, /* Djinn Numeris USB */
80 {USB_DEVICE(0x07b0, 0x0006)}, /* Twister ISDN USB TA */
81 {} /* end with an all-zeroes entry */
82};
83
84/* driver internal device specific data:
85* VendorID, ProductID, Devicename, LED_SCHEME,
86* LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2
87*/
88vendor_data vdata[] = {
89 /* CologneChip Eval TA */
90 {0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)",
91 LED_OFF, {4, 0, 2, 1}
92 }
93 ,
94 /* DrayTek miniVigor 128 USB ISDN TA */
95 {0x0675, 0x1688, "DrayTek miniVigor 128 USB ISDN TA",
96 LED_SCHEME1, {1, 2, 0, 0}
97 }
98 ,
99 /* Billion TA */
100 {0x07b0, 0x0007, "Billion tiny USB ISDN TA 128",
101 LED_SCHEME1, {0x80, -64, -32, -16}
102 }
103 ,
104 /* Stollmann TA */
105 {0x0742, 0x2008, "Stollmann USB TA",
106 LED_SCHEME1, {4, 0, 2, 1}
107 }
108 ,
109 /* Aceex USB ISDN TA */
110 {0x0742, 0x2009, "Aceex USB ISDN TA",
111 LED_SCHEME1, {4, 0, 2, 1}
112 }
113 ,
114 /* OEM USB ISDN TA */
115 {0x0742, 0x200A, "OEM USB ISDN TA",
116 LED_SCHEME1, {4, 0, 2, 1}
117 }
118 ,
119 /* Olitec TA */
120 {0x08e3, 0x0301, "Olitec USB RNIS",
121 LED_SCHEME1, {2, 0, 1, 4}
122 }
123 ,
124 /* Bewan TA */
125 {0x07fa, 0x0846, "Bewan Modem RNIS USB",
126 LED_SCHEME1, {0x80, -64, -32, -16}
127 }
128 ,
129 /* Bewan TA */
130 {0x07fa, 0x0847, "Djinn Numeris USB",
131 LED_SCHEME1, {0x80, -64, -32, -16}
132 }
133 ,
134 /* Twister ISDN TA */
135 {0x07b0, 0x0006, "Twister ISDN TA",
136 LED_SCHEME1, {0x80, -64, -32, -16}
137 }
138 ,
139 {0, 0, 0} /* EOL element */
140};
141
142/***************************************************************/
143/* structure defining input+output fifos (interrupt/bulk mode) */
144/***************************************************************/
145struct usb_fifo; /* forward definition */
146typedef struct iso_urb_struct {
147 struct urb *purb;
148 __u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */
149 struct usb_fifo *owner_fifo; /* pointer to owner fifo */
150} iso_urb_struct;
151
152
153struct hfcusb_data; /* forward definition */
154typedef struct usb_fifo {
155 int fifonum; /* fifo index attached to this structure */
156 int active; /* fifo is currently active */
157 struct hfcusb_data *hfc; /* pointer to main structure */
158 int pipe; /* address of endpoint */
159 __u8 usb_packet_maxlen; /* maximum length for usb transfer */
160 unsigned int max_size; /* maximum size of receive/send packet */
161 __u8 intervall; /* interrupt interval */
162 struct sk_buff *skbuff; /* actual used buffer */
163 struct urb *urb; /* transfer structure for usb routines */
164 __u8 buffer[128]; /* buffer incoming/outgoing data */
165 int bit_line; /* how much bits are in the fifo? */
166
167 volatile __u8 usb_transfer_mode; /* switched between ISO and INT */
168 iso_urb_struct iso[2]; /* need two urbs to have one always for pending */
169 struct hisax_if *hif; /* hisax interface */
170 int delete_flg; /* only delete skbuff once */
171 int last_urblen; /* remember length of last packet */
172
173} usb_fifo;
174
175/*********************************************/
176/* structure holding all data for one device */
177/*********************************************/
178typedef struct hfcusb_data {
179 /* HiSax Interface for loadable Layer1 drivers */
180 struct hisax_d_if d_if; /* see hisax_if.h */
181 struct hisax_b_if b_if[2]; /* see hisax_if.h */
182 int protocol;
183
184 struct usb_device *dev; /* our device */
185 int if_used; /* used interface number */
186 int alt_used; /* used alternate config */
187 int ctrl_paksize; /* control pipe packet size */
188 int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */
189 int cfg_used; /* configuration index used */
190 int vend_idx; /* vendor found */
191 int b_mode[2]; /* B-channel mode */
192 int l1_activated; /* layer 1 activated */
193 int disc_flag; /* TRUE if device was disonnected to avoid some USB actions */
194 int packet_size, iso_packet_size;
195
196 /* control pipe background handling */
197 ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */
198 volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt; /* input/output pointer + count */
199 struct urb *ctrl_urb; /* transfer structure for control channel */
200
201 struct usb_ctrlrequest ctrl_write; /* buffer for control write request */
202 struct usb_ctrlrequest ctrl_read; /* same for read request */
203
204 __u8 old_led_state, led_state, led_new_data, led_b_active;
205
206 volatile __u8 threshold_mask; /* threshold actually reported */
207 volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */
208
209 usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */
210
211 volatile __u8 l1_state; /* actual l1 state */
212 struct timer_list t3_timer; /* timer 3 for activation/deactivation */
213 struct timer_list t4_timer; /* timer 4 for activation/deactivation */
214 struct timer_list led_timer; /* timer flashing leds */
215
216} hfcusb_data;
217
218
219static void collect_rx_frame(usb_fifo * fifo, __u8 * data, int len,
220 int finish);
221
222
223static inline const char *
224symbolic(struct hfcusb_symbolic_list list[], const int num)
225{
226 int i;
227 for (i = 0; list[i].name != NULL; i++)
228 if (list[i].num == num)
229 return (list[i].name);
230 return "<unkown>";
231}
232
233
234/******************************************************/
235/* start next background transfer for control channel */
236/******************************************************/
237static void
238ctrl_start_transfer(hfcusb_data * hfc)
239{
240 if (hfc->ctrl_cnt) {
241 hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;
242 hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;
243 hfc->ctrl_urb->transfer_buffer = NULL;
244 hfc->ctrl_urb->transfer_buffer_length = 0;
245 hfc->ctrl_write.wIndex =
246 hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
247 hfc->ctrl_write.wValue =
248 hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
249
250 usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */
251 }
252} /* ctrl_start_transfer */
253
254/************************************/
255/* queue a control transfer request */
256/* return 0 on success. */
257/************************************/
258static int
259queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val, int action)
260{
261 ctrl_buft *buf;
262
263 if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
264 return (1); /* no space left */
265 buf = &hfc->ctrl_buff[hfc->ctrl_in_idx]; /* pointer to new index */
266 buf->hfc_reg = reg;
267 buf->reg_val = val;
268 buf->action = action;
269 if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
270 hfc->ctrl_in_idx = 0; /* pointer wrap */
271 if (++hfc->ctrl_cnt == 1)
272 ctrl_start_transfer(hfc);
273 return (0);
274} /* queue_control_request */
275
276static int
277control_action_handler(hfcusb_data * hfc, int reg, int val, int action)
278{
279 if (!action)
280 return (1); /* no action defined */
281 return (0);
282}
283
284/***************************************************************/
285/* control completion routine handling background control cmds */
286/***************************************************************/
287static void
288ctrl_complete(struct urb *urb, struct pt_regs *regs)
289{
290 hfcusb_data *hfc = (hfcusb_data *) urb->context;
291 ctrl_buft *buf;
292
293 urb->dev = hfc->dev;
294 if (hfc->ctrl_cnt) {
295 buf = &hfc->ctrl_buff[hfc->ctrl_out_idx];
296 control_action_handler(hfc, buf->hfc_reg, buf->reg_val,
297 buf->action);
298
299 hfc->ctrl_cnt--; /* decrement actual count */
300 if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
301 hfc->ctrl_out_idx = 0; /* pointer wrap */
302
303 ctrl_start_transfer(hfc); /* start next transfer */
304 }
305} /* ctrl_complete */
306
307/***************************************************/
308/* write led data to auxport & invert if necessary */
309/***************************************************/
310static void
311write_led(hfcusb_data * hfc, __u8 led_state)
312{
313 if (led_state != hfc->old_led_state) {
314 hfc->old_led_state = led_state;
315 queue_control_request(hfc, HFCUSB_P_DATA, led_state, 1);
316 }
317}
318
319/**************************/
320/* handle LED bits */
321/**************************/
322static void
323set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset)
324{
325 if (unset) {
326 if (led_bits < 0)
327 hfc->led_state |= abs(led_bits);
328 else
329 hfc->led_state &= ~led_bits;
330 } else {
331 if (led_bits < 0)
332 hfc->led_state &= ~abs(led_bits);
333 else
334 hfc->led_state |= led_bits;
335 }
336}
337
338/******************************************/
339/* invert B-channel LEDs if data is sent */
340/******************************************/
341static void
342led_timer(hfcusb_data * hfc)
343{
344 static int cnt = 0;
345
346 if (cnt) {
347 if (hfc->led_b_active & 1)
348 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
349 0);
350 if (hfc->led_b_active & 2)
351 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
352 0);
353 } else {
354 if (!(hfc->led_b_active & 1) || hfc->led_new_data & 1)
355 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
356 1);
357 if (!(hfc->led_b_active & 2) || hfc->led_new_data & 2)
358 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
359 1);
360 }
361
362 write_led(hfc, hfc->led_state);
363 hfc->led_new_data = 0;
364
365 cnt = !cnt;
366
367 /* restart 4 hz timer */
368 if (!timer_pending(&hfc->led_timer)) {
369 add_timer(&hfc->led_timer);
370 hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
371 }
372}
373
374/**************************/
375/* handle LED requests */
376/**************************/
377static void
378handle_led(hfcusb_data * hfc, int event)
379{
380 /* if no scheme -> no LED action */
381 if (vdata[hfc->vend_idx].led_scheme == LED_OFF)
382 return;
383
384 switch (event) {
385 case LED_POWER_ON:
386 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[0],
387 0);
388 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
389 1);
390 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
391 1);
392 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
393 1);
394 break;
395 case LED_POWER_OFF: /* no Power off handling */
396 break;
397 case LED_S0_ON:
398 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
399 0);
400 break;
401 case LED_S0_OFF:
402 set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
403 1);
404 break;
405 case LED_B1_ON:
406 hfc->led_b_active |= 1;
407 break;
408 case LED_B1_OFF:
409 hfc->led_b_active &= ~1;
410 break;
411 case LED_B1_DATA:
412 hfc->led_new_data |= 1;
413 break;
414 case LED_B2_ON:
415 hfc->led_b_active |= 2;
416 break;
417 case LED_B2_OFF:
418 hfc->led_b_active &= ~2;
419 break;
420 case LED_B2_DATA:
421 hfc->led_new_data |= 2;
422 break;
423 }
424
425 write_led(hfc, hfc->led_state);
426}
427
428/********************************/
429/* called when timer t3 expires */
430/********************************/
431static void
432l1_timer_expire_t3(hfcusb_data * hfc)
433{
434 hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
435 NULL);
436#ifdef CONFIG_HISAX_DEBUG
437 DBG(ISDN_DBG,
438 "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)");
439#endif
440 hfc->l1_activated = FALSE;
441 handle_led(hfc, LED_S0_OFF);
442 /* deactivate : */
443 queue_control_request(hfc, HFCUSB_STATES, 0x10, 1);
444 queue_control_request(hfc, HFCUSB_STATES, 3, 1);
445}
446
447/********************************/
448/* called when timer t4 expires */
449/********************************/
450static void
451l1_timer_expire_t4(hfcusb_data * hfc)
452{
453 hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
454 NULL);
455#ifdef CONFIG_HISAX_DEBUG
456 DBG(ISDN_DBG,
457 "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)");
458#endif
459 hfc->l1_activated = FALSE;
460 handle_led(hfc, LED_S0_OFF);
461}
462
463/*****************************/
464/* handle S0 state changes */
465/*****************************/
466static void
467state_handler(hfcusb_data * hfc, __u8 state)
468{
469 __u8 old_state;
470
471 old_state = hfc->l1_state;
472 if (state == old_state || state < 1 || state > 8)
473 return;
474
475#ifdef CONFIG_HISAX_DEBUG
476 DBG(ISDN_DBG, "HFC-S USB: new S0 state:%d old_state:%d", state,
477 old_state);
478#endif
479 if (state < 4 || state == 7 || state == 8) {
480 if (timer_pending(&hfc->t3_timer))
481 del_timer(&hfc->t3_timer);
482#ifdef CONFIG_HISAX_DEBUG
483 DBG(ISDN_DBG, "HFC-S USB: T3 deactivated");
484#endif
485 }
486 if (state >= 7) {
487 if (timer_pending(&hfc->t4_timer))
488 del_timer(&hfc->t4_timer);
489#ifdef CONFIG_HISAX_DEBUG
490 DBG(ISDN_DBG, "HFC-S USB: T4 deactivated");
491#endif
492 }
493
494 if (state == 7 && !hfc->l1_activated) {
495 hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
496 PH_ACTIVATE | INDICATION, NULL);
497#ifdef CONFIG_HISAX_DEBUG
498 DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent");
499#endif
500 hfc->l1_activated = TRUE;
501 handle_led(hfc, LED_S0_ON);
502 } else if (state <= 3 /* && activated */ ) {
503 if (old_state == 7 || old_state == 8) {
504#ifdef CONFIG_HISAX_DEBUG
505 DBG(ISDN_DBG, "HFC-S USB: T4 activated");
506#endif
507 if (!timer_pending(&hfc->t4_timer)) {
508 hfc->t4_timer.expires =
509 jiffies + (HFC_TIMER_T4 * HZ) / 1000;
510 add_timer(&hfc->t4_timer);
511 }
512 } else {
513 hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
514 PH_DEACTIVATE | INDICATION,
515 NULL);
516#ifdef CONFIG_HISAX_DEBUG
517 DBG(ISDN_DBG,
518 "HFC-S USB: PH_DEACTIVATE | INDICATION sent");
519#endif
520 hfc->l1_activated = FALSE;
521 handle_led(hfc, LED_S0_OFF);
522 }
523 }
524 hfc->l1_state = state;
525}
526
527/* prepare iso urb */
528static void
529fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
530 void *buf, int num_packets, int packet_size, int interval,
531 usb_complete_t complete, void *context)
532{
533 int k;
534
535 spin_lock_init(&urb->lock);
536 urb->dev = dev;
537 urb->pipe = pipe;
538 urb->complete = complete;
539 urb->number_of_packets = num_packets;
540 urb->transfer_buffer_length = packet_size * num_packets;
541 urb->context = context;
542 urb->transfer_buffer = buf;
543 urb->transfer_flags = URB_ISO_ASAP;
544 urb->actual_length = 0;
545 urb->interval = interval;
546 for (k = 0; k < num_packets; k++) {
547 urb->iso_frame_desc[k].offset = packet_size * k;
548 urb->iso_frame_desc[k].length = packet_size;
549 urb->iso_frame_desc[k].actual_length = 0;
550 }
551}
552
553/* allocs urbs and start isoc transfer with two pending urbs to avoid
554 gaps in the transfer chain */
555static int
556start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,
557 usb_complete_t complete, int packet_size)
558{
559 int i, k, errcode;
560
561 printk(KERN_INFO "HFC-S USB: starting ISO-chain for Fifo %i\n",
562 fifo->fifonum);
563
564 /* allocate Memory for Iso out Urbs */
565 for (i = 0; i < 2; i++) {
566 if (!(fifo->iso[i].purb)) {
567 fifo->iso[i].purb =
568 usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
569 if (!(fifo->iso[i].purb)) {
570 printk(KERN_INFO
571 "alloc urb for fifo %i failed!!!",
572 fifo->fifonum);
573 }
574 fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
575
576 /* Init the first iso */
577 if (ISO_BUFFER_SIZE >=
578 (fifo->usb_packet_maxlen *
579 num_packets_per_urb)) {
580 fill_isoc_urb(fifo->iso[i].purb,
581 fifo->hfc->dev, fifo->pipe,
582 fifo->iso[i].buffer,
583 num_packets_per_urb,
584 fifo->usb_packet_maxlen,
585 fifo->intervall, complete,
586 &fifo->iso[i]);
587 memset(fifo->iso[i].buffer, 0,
588 sizeof(fifo->iso[i].buffer));
589 /* defining packet delimeters in fifo->buffer */
590 for (k = 0; k < num_packets_per_urb; k++) {
591 fifo->iso[i].purb->
592 iso_frame_desc[k].offset =
593 k * packet_size;
594 fifo->iso[i].purb->
595 iso_frame_desc[k].length =
596 packet_size;
597 }
598 } else {
599 printk(KERN_INFO
600 "HFC-S USB: ISO Buffer size to small!\n");
601 }
602 }
603 fifo->bit_line = BITLINE_INF;
604
605 errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL);
606 fifo->active = (errcode >= 0) ? 1 : 0;
607 if (errcode < 0) {
608 printk(KERN_INFO "HFC-S USB: %s URB nr:%d\n",
609 symbolic(urb_errlist, errcode), i);
610 };
611 }
612 return (fifo->active);
613}
614
615/* stops running iso chain and frees their pending urbs */
616static void
617stop_isoc_chain(usb_fifo * fifo)
618{
619 int i;
620
621 for (i = 0; i < 2; i++) {
622 if (fifo->iso[i].purb) {
623#ifdef CONFIG_HISAX_DEBUG
624 DBG(USB_DBG,
625 "HFC-S USB: Stopping iso chain for fifo %i.%i",
626 fifo->fifonum, i);
627#endif
628 usb_unlink_urb(fifo->iso[i].purb);
629 usb_free_urb(fifo->iso[i].purb);
630 fifo->iso[i].purb = NULL;
631 }
632 }
633 if (fifo->urb) {
634 usb_unlink_urb(fifo->urb);
635 usb_free_urb(fifo->urb);
636 fifo->urb = NULL;
637 }
638 fifo->active = 0;
639}
640
641/* defines how much ISO packets are handled in one URB */
642static int iso_packets[8] =
643 { ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B,
644 ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D
645};
646
647/*****************************************************/
648/* transmit completion routine for all ISO tx fifos */
649/*****************************************************/
650static void
651tx_iso_complete(struct urb *urb, struct pt_regs *regs)
652{
653 iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
654 usb_fifo *fifo = context_iso_urb->owner_fifo;
655 hfcusb_data *hfc = fifo->hfc;
656 int k, tx_offset, num_isoc_packets, sink, len, current_len,
657 errcode;
658 int frame_complete, transp_mode, fifon, status;
659 __u8 threshbit;
660 __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 };
661
662 fifon = fifo->fifonum;
663 status = urb->status;
664
665 tx_offset = 0;
666
667 if (fifo->active && !status) {
668 transp_mode = 0;
669 if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
670 transp_mode = TRUE;
671
672 /* is FifoFull-threshold set for our channel? */
673 threshbit = threshtable[fifon] & hfc->threshold_mask;
674 num_isoc_packets = iso_packets[fifon];
675
676 /* predict dataflow to avoid fifo overflow */
677 if (fifon >= HFCUSB_D_TX) {
678 sink = (threshbit) ? SINK_DMIN : SINK_DMAX;
679 } else {
680 sink = (threshbit) ? SINK_MIN : SINK_MAX;
681 }
682 fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,
683 context_iso_urb->buffer, num_isoc_packets,
684 fifo->usb_packet_maxlen, fifo->intervall,
685 tx_iso_complete, urb->context);
686 memset(context_iso_urb->buffer, 0,
687 sizeof(context_iso_urb->buffer));
688 frame_complete = FALSE;
689 /* Generate next Iso Packets */
690 for (k = 0; k < num_isoc_packets; ++k) {
691 if (fifo->skbuff) {
692 len = fifo->skbuff->len;
693 /* we lower data margin every msec */
694 fifo->bit_line -= sink;
695 current_len = (0 - fifo->bit_line) / 8;
696 /* maximum 15 byte for every ISO packet makes our life easier */
697 if (current_len > 14)
698 current_len = 14;
699 current_len =
700 (len <=
701 current_len) ? len : current_len;
702 /* how much bit do we put on the line? */
703 fifo->bit_line += current_len * 8;
704
705 context_iso_urb->buffer[tx_offset] = 0;
706 if (current_len == len) {
707 if (!transp_mode) {
708 /* here frame completion */
709 context_iso_urb->
710 buffer[tx_offset] = 1;
711 /* add 2 byte flags and 16bit CRC at end of ISDN frame */
712 fifo->bit_line += 32;
713 }
714 frame_complete = TRUE;
715 }
716
717 memcpy(context_iso_urb->buffer +
718 tx_offset + 1, fifo->skbuff->data,
719 current_len);
720 skb_pull(fifo->skbuff, current_len);
721
722 /* define packet delimeters within the URB buffer */
723 urb->iso_frame_desc[k].offset = tx_offset;
724 urb->iso_frame_desc[k].length =
725 current_len + 1;
726
727 tx_offset += (current_len + 1);
728 if (!transp_mode) {
729 if (fifon == HFCUSB_B1_TX)
730 handle_led(hfc,
731 LED_B1_DATA);
732 if (fifon == HFCUSB_B2_TX)
733 handle_led(hfc,
734 LED_B2_DATA);
735 }
736 } else {
737 urb->iso_frame_desc[k].offset =
738 tx_offset++;
739
740 urb->iso_frame_desc[k].length = 1;
741 fifo->bit_line -= sink; /* we lower data margin every msec */
742
743 if (fifo->bit_line < BITLINE_INF) {
744 fifo->bit_line = BITLINE_INF;
745 }
746 }
747
748 if (frame_complete) {
749 fifo->delete_flg = TRUE;
750 fifo->hif->l1l2(fifo->hif,
751 PH_DATA | CONFIRM,
752 (void *) fifo->skbuff->
753 truesize);
754 if (fifo->skbuff && fifo->delete_flg) {
755 dev_kfree_skb_any(fifo->skbuff);
756 fifo->skbuff = NULL;
757 fifo->delete_flg = FALSE;
758 }
759 frame_complete = FALSE;
760 }
761 }
762 errcode = usb_submit_urb(urb, GFP_ATOMIC);
763 if (errcode < 0) {
764 printk(KERN_INFO
765 "HFC-S USB: error submitting ISO URB: %d \n",
766 errcode);
767 }
768 } else {
769 if (status && !hfc->disc_flag) {
770 printk(KERN_INFO
771 "HFC-S USB: tx_iso_complete : urb->status %s (%i), fifonum=%d\n",
772 symbolic(urb_errlist, status), status,
773 fifon);
774 }
775 }
776} /* tx_iso_complete */
777
778/*****************************************************/
779/* receive completion routine for all ISO tx fifos */
780/*****************************************************/
781static void
782rx_iso_complete(struct urb *urb, struct pt_regs *regs)
783{
784 iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
785 usb_fifo *fifo = context_iso_urb->owner_fifo;
786 hfcusb_data *hfc = fifo->hfc;
787 int k, len, errcode, offset, num_isoc_packets, fifon, maxlen,
788 status;
789 unsigned int iso_status;
790 __u8 *buf;
791 static __u8 eof[8];
792#ifdef CONFIG_HISAX_DEBUG
793 __u8 i;
794#endif
795
796 fifon = fifo->fifonum;
797 status = urb->status;
798
799 if (urb->status == -EOVERFLOW) {
800#ifdef CONFIG_HISAX_DEBUG
801 DBG(USB_DBG,
802 "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",
803 fifon);
804#endif
805 status = 0;
806 }
807 if (fifo->active && !status) {
808 num_isoc_packets = iso_packets[fifon];
809 maxlen = fifo->usb_packet_maxlen;
810 for (k = 0; k < num_isoc_packets; ++k) {
811 len = urb->iso_frame_desc[k].actual_length;
812 offset = urb->iso_frame_desc[k].offset;
813 buf = context_iso_urb->buffer + offset;
814 iso_status = urb->iso_frame_desc[k].status;
815#ifdef CONFIG_HISAX_DEBUG
816 if (iso_status && !hfc->disc_flag)
817 DBG(USB_DBG,
818 "HFC-S USB: ISO packet failure - status:%x",
819 iso_status);
820
821 if ((fifon == 5) && (debug > 1)) {
822 printk(KERN_INFO
823 "HFC-S USB: ISO-D-RX lst_urblen:%2d "
824 "act_urblen:%2d max-urblen:%2d "
825 "EOF:0x%0x DATA: ",
826 fifo->last_urblen, len, maxlen,
827 eof[5]);
828 for (i = 0; i < len; i++)
829 printk("%.2x ", buf[i]);
830 printk("\n");
831 }
832#endif
833 if (fifo->last_urblen != maxlen) {
834 /* the threshold mask is in the 2nd status byte */
835 hfc->threshold_mask = buf[1];
836 /* care for L1 state only for D-Channel
837 to avoid overlapped iso completions */
838 if (fifon == 5) {
839 /* the S0 state is in the upper half
840 of the 1st status byte */
841 state_handler(hfc, buf[0] >> 4);
842 }
843 eof[fifon] = buf[0] & 1;
844 if (len > 2)
845 collect_rx_frame(fifo, buf + 2,
846 len - 2,
847 (len <
848 maxlen) ?
849 eof[fifon] : 0);
850 } else {
851 collect_rx_frame(fifo, buf, len,
852 (len <
853 maxlen) ? eof[fifon] :
854 0);
855 }
856 fifo->last_urblen = len;
857 }
858
859 fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,
860 context_iso_urb->buffer, num_isoc_packets,
861 fifo->usb_packet_maxlen, fifo->intervall,
862 rx_iso_complete, urb->context);
863 errcode = usb_submit_urb(urb, GFP_ATOMIC);
864 if (errcode < 0) {
865 printk(KERN_INFO
866 "HFC-S USB: error submitting ISO URB: %d \n",
867 errcode);
868 }
869 } else {
870 if (status && !hfc->disc_flag) {
871 printk(KERN_INFO
872 "HFC-S USB: rx_iso_complete : "
873 "urb->status %d, fifonum %d\n",
874 status, fifon);
875 }
876 }
877} /* rx_iso_complete */
878
879/*****************************************************/
880/* collect data from interrupt or isochron in */
881/*****************************************************/
882static void
883collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
884{
885 hfcusb_data *hfc = fifo->hfc;
886 int transp_mode, fifon;
887#ifdef CONFIG_HISAX_DEBUG
888 int i;
889#endif
890 fifon = fifo->fifonum;
891 transp_mode = 0;
892 if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
893 transp_mode = TRUE;
894
895 if (!fifo->skbuff) {
896 fifo->skbuff = dev_alloc_skb(fifo->max_size + 3);
897 if (!fifo->skbuff) {
898 printk(KERN_INFO
899 "HFC-S USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",
900 fifon);
901 return;
902 }
903 }
904 if (len) {
905 if (fifo->skbuff->len + len < fifo->max_size) {
906 memcpy(skb_put(fifo->skbuff, len), data, len);
907 } else {
908#ifdef CONFIG_HISAX_DEBUG
909 printk(KERN_INFO "HFC-S USB: ");
910 for (i = 0; i < 15; i++)
911 printk("%.2x ",
912 fifo->skbuff->data[fifo->skbuff->
913 len - 15 + i]);
914 printk("\n");
915#endif
916 printk(KERN_INFO
917 "HCF-USB: got frame exceeded fifo->max_size:%d on fifo:%d\n",
918 fifo->max_size, fifon);
919 }
920 }
921 if (transp_mode && fifo->skbuff->len >= 128) {
922 fifo->hif->l1l2(fifo->hif, PH_DATA | INDICATION,
923 fifo->skbuff);
924 fifo->skbuff = NULL;
925 return;
926 }
927 /* we have a complete hdlc packet */
928 if (finish) {
929 if ((!fifo->skbuff->data[fifo->skbuff->len - 1])
930 && (fifo->skbuff->len > 3)) {
931 /* remove CRC & status */
932 skb_trim(fifo->skbuff, fifo->skbuff->len - 3);
933 if (fifon == HFCUSB_PCM_RX) {
934 fifo->hif->l1l2(fifo->hif,
935 PH_DATA_E | INDICATION,
936 fifo->skbuff);
937 } else
938 fifo->hif->l1l2(fifo->hif,
939 PH_DATA | INDICATION,
940 fifo->skbuff);
941 fifo->skbuff = NULL; /* buffer was freed from upper layer */
942 } else {
943 if (fifo->skbuff->len > 3) {
944 printk(KERN_INFO
945 "HFC-S USB: got frame %d bytes but CRC ERROR on fifo:%d!!!\n",
946 fifo->skbuff->len, fifon);
947#ifdef CONFIG_HISAX_DEBUG
948 if (debug > 1) {
949 printk(KERN_INFO "HFC-S USB: ");
950 for (i = 0; i < 15; i++)
951 printk("%.2x ",
952 fifo->skbuff->
953 data[fifo->skbuff->
954 len - 15 + i]);
955 printk("\n");
956 }
957#endif
958 }
959#ifdef CONFIG_HISAX_DEBUG
960 else {
961 printk(KERN_INFO
962 "HFC-S USB: frame to small (%d bytes)!!!\n",
963 fifo->skbuff->len);
964 }
965#endif
966 skb_trim(fifo->skbuff, 0);
967 }
968 }
969
970 /* LED flashing only in HDLC mode */
971 if (!transp_mode) {
972 if (fifon == HFCUSB_B1_RX)
973 handle_led(hfc, LED_B1_DATA);
974 if (fifon == HFCUSB_B2_RX)
975 handle_led(hfc, LED_B2_DATA);
976 }
977}
978
979/***********************************************/
980/* receive completion routine for all rx fifos */
981/***********************************************/
982static void
983rx_complete(struct urb *urb, struct pt_regs *regs)
984{
985 int len;
986 int status;
987 __u8 *buf, maxlen, fifon;
988 usb_fifo *fifo = (usb_fifo *) urb->context;
989 hfcusb_data *hfc = fifo->hfc;
990 static __u8 eof[8];
991#ifdef CONFIG_HISAX_DEBUG
992 __u8 i;
993#endif
994
995 urb->dev = hfc->dev; /* security init */
996
997 fifon = fifo->fifonum;
998 if ((!fifo->active) || (urb->status)) {
999#ifdef CONFIG_HISAX_DEBUG
1000 DBG(USB_DBG, "HFC-S USB: RX-Fifo %i is going down (%i)",
1001 fifon, urb->status);
1002#endif
1003 fifo->urb->interval = 0; /* cancel automatic rescheduling */
1004 if (fifo->skbuff) {
1005 dev_kfree_skb_any(fifo->skbuff);
1006 fifo->skbuff = NULL;
1007 }
1008 return;
1009 }
1010 len = urb->actual_length;
1011 buf = fifo->buffer;
1012 maxlen = fifo->usb_packet_maxlen;
1013
1014#ifdef CONFIG_HISAX_DEBUG
1015 if ((fifon == 5) && (debug > 1)) {
1016 printk(KERN_INFO
1017 "HFC-S USB: INT-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ",
1018 fifo->last_urblen, len, maxlen, eof[5]);
1019 for (i = 0; i < len; i++)
1020 printk("%.2x ", buf[i]);
1021 printk("\n");
1022 }
1023#endif
1024
1025 if (fifo->last_urblen != fifo->usb_packet_maxlen) {
1026 /* the threshold mask is in the 2nd status byte */
1027 hfc->threshold_mask = buf[1];
1028 /* the S0 state is in the upper half of the 1st status byte */
1029 state_handler(hfc, buf[0] >> 4);
1030 eof[fifon] = buf[0] & 1;
1031 /* if we have more than the 2 status bytes -> collect data */
1032 if (len > 2)
1033 collect_rx_frame(fifo, buf + 2,
1034 urb->actual_length - 2,
1035 (len < maxlen) ? eof[fifon] : 0);
1036 } else {
1037 collect_rx_frame(fifo, buf, urb->actual_length,
1038 (len < maxlen) ? eof[fifon] : 0);
1039 }
1040 fifo->last_urblen = urb->actual_length;
1041 status = usb_submit_urb(urb, GFP_ATOMIC);
1042 if (status) {
1043 printk(KERN_INFO
1044 "HFC-S USB: error resubmitting URN at rx_complete...\n");
1045 }
1046} /* rx_complete */
1047
1048/***************************************************/
1049/* start the interrupt transfer for the given fifo */
1050/***************************************************/
1051static void
1052start_int_fifo(usb_fifo * fifo)
1053{
1054 int errcode;
1055
1056 printk(KERN_INFO "HFC-S USB: starting intr IN fifo:%d\n",
1057 fifo->fifonum);
1058
1059 if (!fifo->urb) {
1060 fifo->urb = usb_alloc_urb(0, GFP_KERNEL);
1061 if (!fifo->urb)
1062 return;
1063 }
1064 usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe,
1065 fifo->buffer, fifo->usb_packet_maxlen,
1066 rx_complete, fifo, fifo->intervall);
1067 fifo->active = 1; /* must be marked active */
1068 errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);
1069 if (errcode) {
1070 printk(KERN_INFO
1071 "HFC-S USB: submit URB error(start_int_info): status:%i\n",
1072 errcode);
1073 fifo->active = 0;
1074 fifo->skbuff = NULL;
1075 }
1076} /* start_int_fifo */
1077
1078/*****************************/
1079/* set the B-channel mode */
1080/*****************************/
1081static void
1082set_hfcmode(hfcusb_data * hfc, int channel, int mode)
1083{
1084 __u8 val, idx_table[2] = { 0, 2 };
1085
1086 if (hfc->disc_flag) {
1087 return;
1088 }
1089#ifdef CONFIG_HISAX_DEBUG
1090 DBG(ISDN_DBG, "HFC-S USB: setting channel %d to mode %d", channel,
1091 mode);
1092#endif
1093 hfc->b_mode[channel] = mode;
1094
1095 /* setup CON_HDLC */
1096 val = 0;
1097 if (mode != L1_MODE_NULL)
1098 val = 8; /* enable fifo? */
1099 if (mode == L1_MODE_TRANS)
1100 val |= 2; /* set transparent bit */
1101
1102 /* set FIFO to transmit register */
1103 queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel], 1);
1104 queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);
1105 /* reset fifo */
1106 queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);
1107 /* set FIFO to receive register */
1108 queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel] + 1, 1);
1109 queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);
1110 /* reset fifo */
1111 queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);
1112
1113 val = 0x40;
1114 if (hfc->b_mode[0])
1115 val |= 1;
1116 if (hfc->b_mode[1])
1117 val |= 2;
1118 queue_control_request(hfc, HFCUSB_SCTRL, val, 1);
1119
1120 val = 0;
1121 if (hfc->b_mode[0])
1122 val |= 1;
1123 if (hfc->b_mode[1])
1124 val |= 2;
1125 queue_control_request(hfc, HFCUSB_SCTRL_R, val, 1);
1126
1127 if (mode == L1_MODE_NULL) {
1128 if (channel)
1129 handle_led(hfc, LED_B2_OFF);
1130 else
1131 handle_led(hfc, LED_B1_OFF);
1132 } else {
1133 if (channel)
1134 handle_led(hfc, LED_B2_ON);
1135 else
1136 handle_led(hfc, LED_B1_ON);
1137 }
1138}
1139
1140void
1141hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
1142{
1143 usb_fifo *fifo = my_hisax_if->priv;
1144 hfcusb_data *hfc = fifo->hfc;
1145
1146 switch (pr) {
1147 case PH_ACTIVATE | REQUEST:
1148 if (fifo->fifonum == HFCUSB_D_TX) {
1149#ifdef CONFIG_HISAX_DEBUG
1150 DBG(ISDN_DBG,
1151 "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST");
1152#endif
1153 if (hfc->l1_state != 3
1154 && hfc->l1_state != 7) {
1155 hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
1156 PH_DEACTIVATE |
1157 INDICATION,
1158 NULL);
1159#ifdef CONFIG_HISAX_DEBUG
1160 DBG(ISDN_DBG,
1161 "HFC-S USB: PH_DEACTIVATE | INDICATION sent (not state 3 or 7)");
1162#endif
1163 } else {
1164 if (hfc->l1_state == 7) { /* l1 already active */
1165 hfc->d_if.ifc.l1l2(&hfc->
1166 d_if.
1167 ifc,
1168 PH_ACTIVATE
1169 |
1170 INDICATION,
1171 NULL);
1172#ifdef CONFIG_HISAX_DEBUG
1173 DBG(ISDN_DBG,
1174 "HFC-S USB: PH_ACTIVATE | INDICATION sent again ;)");
1175#endif
1176 } else {
1177 /* force sending sending INFO1 */
1178 queue_control_request(hfc,
1179 HFCUSB_STATES,
1180 0x14,
1181 1);
1182 mdelay(1);
1183 /* start l1 activation */
1184 queue_control_request(hfc,
1185 HFCUSB_STATES,
1186 0x04,
1187 1);
1188 if (!timer_pending
1189 (&hfc->t3_timer)) {
1190 hfc->t3_timer.
1191 expires =
1192 jiffies +
1193 (HFC_TIMER_T3 *
1194 HZ) / 1000;
1195 add_timer(&hfc->
1196 t3_timer);
1197 }
1198 }
1199 }
1200 } else {
1201#ifdef CONFIG_HISAX_DEBUG
1202 DBG(ISDN_DBG,
1203 "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST");
1204#endif
1205 set_hfcmode(hfc,
1206 (fifo->fifonum ==
1207 HFCUSB_B1_TX) ? 0 : 1,
1208 (int) arg);
1209 fifo->hif->l1l2(fifo->hif,
1210 PH_ACTIVATE | INDICATION,
1211 NULL);
1212 }
1213 break;
1214 case PH_DEACTIVATE | REQUEST:
1215 if (fifo->fifonum == HFCUSB_D_TX) {
1216#ifdef CONFIG_HISAX_DEBUG
1217 DBG(ISDN_DBG,
1218 "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST");
1219#endif
1220 printk(KERN_INFO
1221 "HFC-S USB: ISDN TE device should not deativate...\n");
1222 } else {
1223#ifdef CONFIG_HISAX_DEBUG
1224 DBG(ISDN_DBG,
1225 "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST");
1226#endif
1227 set_hfcmode(hfc,
1228 (fifo->fifonum ==
1229 HFCUSB_B1_TX) ? 0 : 1,
1230 (int) L1_MODE_NULL);
1231 fifo->hif->l1l2(fifo->hif,
1232 PH_DEACTIVATE | INDICATION,
1233 NULL);
1234 }
1235 break;
1236 case PH_DATA | REQUEST:
1237 if (fifo->skbuff && fifo->delete_flg) {
1238 dev_kfree_skb_any(fifo->skbuff);
1239 fifo->skbuff = NULL;
1240 fifo->delete_flg = FALSE;
1241 }
1242 fifo->skbuff = arg; /* we have a new buffer */
1243 break;
1244 default:
1245 printk(KERN_INFO
1246 "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n",
1247 pr);
1248 break;
1249 }
1250}
1251
1252/***************************************************************************/
1253/* usb_init is called once when a new matching device is detected to setup */
1254/* main parameters. It registers the driver at the main hisax module. */
1255/* on success 0 is returned. */
1256/***************************************************************************/
1257static int
1258usb_init(hfcusb_data * hfc)
1259{
1260 usb_fifo *fifo;
1261 int i, err;
1262 u_char b;
1263 struct hisax_b_if *p_b_if[2];
1264
1265 /* check the chip id */
1266 if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {
1267 printk(KERN_INFO "HFC-USB: cannot read chip id\n");
1268 return (1);
1269 }
1270 if (b != HFCUSB_CHIPID) {
1271 printk(KERN_INFO "HFC-S USB: Invalid chip id 0x%02x\n", b);
1272 return (1);
1273 }
1274
1275 /* first set the needed config, interface and alternate */
1276 err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
1277
1278 /* do Chip reset */
1279 write_usb(hfc, HFCUSB_CIRM, 8);
1280 /* aux = output, reset off */
1281 write_usb(hfc, HFCUSB_CIRM, 0x10);
1282
1283 /* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */
1284 write_usb(hfc, HFCUSB_USB_SIZE,
1285 (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4));
1286
1287 /* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */
1288 write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
1289
1290 /* enable PCM/GCI master mode */
1291 write_usb(hfc, HFCUSB_MST_MODE1, 0); /* set default values */
1292 write_usb(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */
1293
1294 /* init the fifos */
1295 write_usb(hfc, HFCUSB_F_THRES,
1296 (HFCUSB_TX_THRESHOLD /
1297 8) | ((HFCUSB_RX_THRESHOLD / 8) << 4));
1298
1299 fifo = hfc->fifos;
1300 for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
1301 write_usb(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
1302 fifo[i].skbuff = NULL; /* init buffer pointer */
1303 fifo[i].max_size =
1304 (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
1305 fifo[i].last_urblen = 0;
1306 /* set 2 bit for D- & E-channel */
1307 write_usb(hfc, HFCUSB_HDLC_PAR,
1308 ((i <= HFCUSB_B2_RX) ? 0 : 2));
1309 /* rx hdlc, enable IFF for D-channel */
1310 write_usb(hfc, HFCUSB_CON_HDLC,
1311 ((i == HFCUSB_D_TX) ? 0x09 : 0x08));
1312 write_usb(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */
1313 }
1314
1315 write_usb(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */
1316 write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
1317 write_usb(hfc, HFCUSB_STATES, 3); /* enable state machine */
1318
1319 write_usb(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
1320 write_usb(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode */
1321
1322 /* set both B-channel to not connected */
1323 hfc->b_mode[0] = L1_MODE_NULL;
1324 hfc->b_mode[1] = L1_MODE_NULL;
1325
1326 hfc->l1_activated = FALSE;
1327 hfc->disc_flag = FALSE;
1328 hfc->led_state = 0;
1329 hfc->led_new_data = 0;
1330 hfc->old_led_state = 0;
1331
1332 /* init the t3 timer */
1333 init_timer(&hfc->t3_timer);
1334 hfc->t3_timer.data = (long) hfc;
1335 hfc->t3_timer.function = (void *) l1_timer_expire_t3;
1336
1337 /* init the t4 timer */
1338 init_timer(&hfc->t4_timer);
1339 hfc->t4_timer.data = (long) hfc;
1340 hfc->t4_timer.function = (void *) l1_timer_expire_t4;
1341
1342 /* init the led timer */
1343 init_timer(&hfc->led_timer);
1344 hfc->led_timer.data = (long) hfc;
1345 hfc->led_timer.function = (void *) led_timer;
1346
1347 /* trigger 4 hz led timer */
1348 if (!timer_pending(&hfc->led_timer)) {
1349 hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
1350 add_timer(&hfc->led_timer);
1351 }
1352
1353 /* init the background machinery for control requests */
1354 hfc->ctrl_read.bRequestType = 0xc0;
1355 hfc->ctrl_read.bRequest = 1;
1356 hfc->ctrl_read.wLength = 1;
1357 hfc->ctrl_write.bRequestType = 0x40;
1358 hfc->ctrl_write.bRequest = 0;
1359 hfc->ctrl_write.wLength = 0;
1360 usb_fill_control_urb(hfc->ctrl_urb,
1361 hfc->dev,
1362 hfc->ctrl_out_pipe,
1363 (u_char *) & hfc->ctrl_write,
1364 NULL, 0, ctrl_complete, hfc);
1365 /* Init All Fifos */
1366 for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
1367 hfc->fifos[i].iso[0].purb = NULL;
1368 hfc->fifos[i].iso[1].purb = NULL;
1369 hfc->fifos[i].active = 0;
1370 }
1371 /* register Modul to upper Hisax Layers */
1372 hfc->d_if.owner = THIS_MODULE;
1373 hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];
1374 hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;
1375 for (i = 0; i < 2; i++) {
1376 hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX + i * 2];
1377 hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;
1378 p_b_if[i] = &hfc->b_if[i];
1379 }
1380 /* default Prot: EURO ISDN, should be a module_param */
1381 hfc->protocol = 2;
1382 hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
1383
1384#ifdef CONFIG_HISAX_DEBUG
1385 hfc_debug = debug;
1386#endif
1387
1388 for (i = 0; i < 4; i++)
1389 hfc->fifos[i].hif = &p_b_if[i / 2]->ifc;
1390 for (i = 4; i < 8; i++)
1391 hfc->fifos[i].hif = &hfc->d_if.ifc;
1392
1393 /* 3 (+1) INT IN + 3 ISO OUT */
1394 if (hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) {
1395 start_int_fifo(hfc->fifos + HFCUSB_D_RX);
1396 if (hfc->fifos[HFCUSB_PCM_RX].pipe)
1397 start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);
1398 start_int_fifo(hfc->fifos + HFCUSB_B1_RX);
1399 start_int_fifo(hfc->fifos + HFCUSB_B2_RX);
1400 }
1401 /* 3 (+1) ISO IN + 3 ISO OUT */
1402 if (hfc->cfg_used == CNF_3ISO3ISO || hfc->cfg_used == CNF_4ISO3ISO) {
1403 start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D,
1404 rx_iso_complete, 16);
1405 if (hfc->fifos[HFCUSB_PCM_RX].pipe)
1406 start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX,
1407 ISOC_PACKETS_D, rx_iso_complete,
1408 16);
1409 start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B,
1410 rx_iso_complete, 16);
1411 start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B,
1412 rx_iso_complete, 16);
1413 }
1414
1415 start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D,
1416 tx_iso_complete, 1);
1417 start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B,
1418 tx_iso_complete, 1);
1419 start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B,
1420 tx_iso_complete, 1);
1421
1422 handle_led(hfc, LED_POWER_ON);
1423
1424 return (0);
1425} /* usb_init */
1426
1427/*************************************************/
1428/* function called to probe a new plugged device */
1429/*************************************************/
1430static int
1431hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
1432{
1433 struct usb_device *dev = interface_to_usbdev(intf);
1434 hfcusb_data *context;
1435 struct usb_host_interface *iface = intf->cur_altsetting;
1436 struct usb_host_interface *iface_used = NULL;
1437 struct usb_host_endpoint *ep;
1438 int ifnum = iface->desc.bInterfaceNumber;
1439 int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf,
1440 attr, cfg_found, cidx, ep_addr;
1441 int cmptbl[16], small_match, iso_packet_size, packet_size,
1442 alt_used = 0;
1443
1444 vend_idx = 0xffff;
1445 for (i = 0; vdata[i].vendor; i++) {
1446 if (dev->descriptor.idVendor == vdata[i].vendor
1447 && dev->descriptor.idProduct == vdata[i].prod_id)
1448 vend_idx = i;
1449 }
1450#ifdef CONFIG_HISAX_DEBUG
1451 DBG(USB_DBG,
1452 "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum,
1453 iface->desc.bAlternateSetting, intf->minor);
1454#endif
1455 printk(KERN_INFO
1456 "HFC-S USB: probing interface(%d) actalt(%d) minor(%d)\n",
1457 ifnum, iface->desc.bAlternateSetting, intf->minor);
1458
1459 if (vend_idx != 0xffff) {
1460#ifdef CONFIG_HISAX_DEBUG
1461 DBG(USB_DBG, "HFC-S USB: found vendor idx:%d name:%s",
1462 vend_idx, vdata[vend_idx].vend_name);
1463#endif
1464 /* if vendor and product ID is OK, start probing alternate settings */
1465 alt_idx = 0;
1466 small_match = 0xffff;
1467
1468 /* default settings */
1469 iso_packet_size = 16;
1470 packet_size = 64;
1471
1472 while (alt_idx < intf->num_altsetting) {
1473 iface = intf->altsetting + alt_idx;
1474 probe_alt_setting = iface->desc.bAlternateSetting;
1475 cfg_used = 0;
1476
1477 /* check for config EOL element */
1478 while (validconf[cfg_used][0]) {
1479 cfg_found = TRUE;
1480 vcf = validconf[cfg_used];
1481 /* first endpoint descriptor */
1482 ep = iface->endpoint;
1483#ifdef CONFIG_HISAX_DEBUG
1484 DBG(USB_DBG,
1485 "HFC-S USB: (if=%d alt=%d cfg_used=%d)\n",
1486 ifnum, probe_alt_setting, cfg_used);
1487#endif
1488 memcpy(cmptbl, vcf, 16 * sizeof(int));
1489
1490 /* check for all endpoints in this alternate setting */
1491 for (i = 0; i < iface->desc.bNumEndpoints;
1492 i++) {
1493 ep_addr =
1494 ep->desc.bEndpointAddress;
1495 /* get endpoint base */
1496 idx = ((ep_addr & 0x7f) - 1) * 2;
1497 if (ep_addr & 0x80)
1498 idx++;
1499 attr = ep->desc.bmAttributes;
1500 if (cmptbl[idx] == EP_NUL) {
1501 cfg_found = FALSE;
1502 }
1503 if (attr == USB_ENDPOINT_XFER_INT
1504 && cmptbl[idx] == EP_INT)
1505 cmptbl[idx] = EP_NUL;
1506 if (attr == USB_ENDPOINT_XFER_BULK
1507 && cmptbl[idx] == EP_BLK)
1508 cmptbl[idx] = EP_NUL;
1509 if (attr == USB_ENDPOINT_XFER_ISOC
1510 && cmptbl[idx] == EP_ISO)
1511 cmptbl[idx] = EP_NUL;
1512
1513 /* check if all INT endpoints match minimum interval */
1514 if (attr == USB_ENDPOINT_XFER_INT
1515 && ep->desc.bInterval <
1516 vcf[17]) {
1517#ifdef CONFIG_HISAX_DEBUG
1518 if (cfg_found)
1519 DBG(USB_DBG,
1520 "HFC-S USB: Interrupt Endpoint interval < %d found - skipping config",
1521 vcf[17]);
1522#endif
1523 cfg_found = FALSE;
1524 }
1525 ep++;
1526 }
1527 for (i = 0; i < 16; i++) {
1528 /* all entries must be EP_NOP or EP_NUL for a valid config */
1529 if (cmptbl[i] != EP_NOP
1530 && cmptbl[i] != EP_NUL)
1531 cfg_found = FALSE;
1532 }
1533 if (cfg_found) {
1534 if (cfg_used < small_match) {
1535 small_match = cfg_used;
1536 alt_used =
1537 probe_alt_setting;
1538 iface_used = iface;
1539 }
1540#ifdef CONFIG_HISAX_DEBUG
1541 DBG(USB_DBG,
1542 "HFC-USB: small_match=%x %x\n",
1543 small_match, alt_used);
1544#endif
1545 }
1546 cfg_used++;
1547 }
1548 alt_idx++;
1549 } /* (alt_idx < intf->num_altsetting) */
1550
1551 /* found a valid USB Ta Endpint config */
1552 if (small_match != 0xffff) {
1553 iface = iface_used;
1554 if (!
1555 (context =
1556 kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
1557 return (-ENOMEM); /* got no mem */
1558 memset(context, 0, sizeof(hfcusb_data));
1559
1560 ep = iface->endpoint;
1561 vcf = validconf[small_match];
1562
1563 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
1564 ep_addr = ep->desc.bEndpointAddress;
1565 /* get endpoint base */
1566 idx = ((ep_addr & 0x7f) - 1) * 2;
1567 if (ep_addr & 0x80)
1568 idx++;
1569 cidx = idx & 7;
1570 attr = ep->desc.bmAttributes;
1571
1572 /* init Endpoints */
1573 if (vcf[idx] != EP_NOP
1574 && vcf[idx] != EP_NUL) {
1575 switch (attr) {
1576 case USB_ENDPOINT_XFER_INT:
1577 context->
1578 fifos[cidx].
1579 pipe =
1580 usb_rcvintpipe
1581 (dev,
1582 ep->desc.
1583 bEndpointAddress);
1584 context->
1585 fifos[cidx].
1586 usb_transfer_mode
1587 = USB_INT;
1588 packet_size =
1589 ep->desc.
1590 wMaxPacketSize;
1591 break;
1592 case USB_ENDPOINT_XFER_BULK:
1593 if (ep_addr & 0x80)
1594 context->
1595 fifos
1596 [cidx].
1597 pipe =
1598 usb_rcvbulkpipe
1599 (dev,
1600 ep->
1601 desc.
1602 bEndpointAddress);
1603 else
1604 context->
1605 fifos
1606 [cidx].
1607 pipe =
1608 usb_sndbulkpipe
1609 (dev,
1610 ep->
1611 desc.
1612 bEndpointAddress);
1613 context->
1614 fifos[cidx].
1615 usb_transfer_mode
1616 = USB_BULK;
1617 packet_size =
1618 ep->desc.
1619 wMaxPacketSize;
1620 break;
1621 case USB_ENDPOINT_XFER_ISOC:
1622 if (ep_addr & 0x80)
1623 context->
1624 fifos
1625 [cidx].
1626 pipe =
1627 usb_rcvisocpipe
1628 (dev,
1629 ep->
1630 desc.
1631 bEndpointAddress);
1632 else
1633 context->
1634 fifos
1635 [cidx].
1636 pipe =
1637 usb_sndisocpipe
1638 (dev,
1639 ep->
1640 desc.
1641 bEndpointAddress);
1642 context->
1643 fifos[cidx].
1644 usb_transfer_mode
1645 = USB_ISOC;
1646 iso_packet_size =
1647 ep->desc.
1648 wMaxPacketSize;
1649 break;
1650 default:
1651 context->
1652 fifos[cidx].
1653 pipe = 0;
1654 } /* switch attribute */
1655
1656 if (context->fifos[cidx].pipe) {
1657 context->fifos[cidx].
1658 fifonum = cidx;
1659 context->fifos[cidx].hfc =
1660 context;
1661 context->fifos[cidx].
1662 usb_packet_maxlen =
1663 ep->desc.
1664 wMaxPacketSize;
1665 context->fifos[cidx].
1666 intervall =
1667 ep->desc.bInterval;
1668 context->fifos[cidx].
1669 skbuff = NULL;
1670 }
1671 }
1672 ep++;
1673 }
1674 context->dev = dev; /* save device */
1675 context->if_used = ifnum; /* save used interface */
1676 context->alt_used = alt_used; /* and alternate config */
1677 context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
1678 context->cfg_used = vcf[16]; /* store used config */
1679 context->vend_idx = vend_idx; /* store found vendor */
1680 context->packet_size = packet_size;
1681 context->iso_packet_size = iso_packet_size;
1682
1683 /* create the control pipes needed for register access */
1684 context->ctrl_in_pipe =
1685 usb_rcvctrlpipe(context->dev, 0);
1686 context->ctrl_out_pipe =
1687 usb_sndctrlpipe(context->dev, 0);
1688 context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
1689
1690 printk(KERN_INFO
1691 "HFC-S USB: detected \"%s\"\n",
1692 vdata[vend_idx].vend_name);
1693#ifdef CONFIG_HISAX_DEBUG
1694 DBG(USB_DBG,
1695 "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n",
1696 conf_str[small_match], context->if_used,
1697 context->alt_used);
1698 printk(KERN_INFO
1699 "HFC-S USB: E-channel (\"ECHO:\") logging ");
1700 if (validconf[small_match][18])
1701 printk(" possible\n");
1702 else
1703 printk("NOT possible\n");
1704#endif
1705 /* init the chip and register the driver */
1706 if (usb_init(context)) {
1707 if (context->ctrl_urb) {
1708 usb_unlink_urb(context->ctrl_urb);
1709 usb_free_urb(context->ctrl_urb);
1710 context->ctrl_urb = NULL;
1711 }
1712 kfree(context);
1713 return (-EIO);
1714 }
1715 usb_set_intfdata(intf, context);
1716 return (0);
1717 }
1718 } else {
1719 printk(KERN_INFO
1720 "HFC-S USB: no valid vendor found in USB descriptor\n");
1721 }
1722 return (-EIO);
1723}
1724
1725/****************************************************/
1726/* function called when an active device is removed */
1727/****************************************************/
1728static void
1729hfc_usb_disconnect(struct usb_interface
1730 *intf)
1731{
1732 hfcusb_data *context = usb_get_intfdata(intf);
1733 int i;
1734 printk(KERN_INFO "HFC-S USB: device disconnect\n");
1735 context->disc_flag = TRUE;
1736 usb_set_intfdata(intf, NULL);
1737 if (!context)
1738 return;
1739 if (timer_pending(&context->t3_timer))
1740 del_timer(&context->t3_timer);
1741 if (timer_pending(&context->t4_timer))
1742 del_timer(&context->t4_timer);
1743 if (timer_pending(&context->led_timer))
1744 del_timer(&context->led_timer);
1745 /* tell all fifos to terminate */
1746 for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
1747 if (context->fifos[i].usb_transfer_mode == USB_ISOC) {
1748 if (context->fifos[i].active > 0) {
1749 stop_isoc_chain(&context->fifos[i]);
1750#ifdef CONFIG_HISAX_DEBUG
1751 DBG(USB_DBG,
1752 "HFC-S USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i",
1753 i);
1754#endif
1755 }
1756 } else {
1757 if (context->fifos[i].active > 0) {
1758 context->fifos[i].active = 0;
1759#ifdef CONFIG_HISAX_DEBUG
1760 DBG(USB_DBG,
1761 "HFC-S USB: hfc_usb_disconnect: unlinking URB for Fifo no %i",
1762 i);
1763#endif
1764 }
1765 if (context->fifos[i].urb) {
1766 usb_unlink_urb(context->fifos[i].urb);
1767 usb_free_urb(context->fifos[i].urb);
1768 context->fifos[i].urb = NULL;
1769 }
1770 }
1771 context->fifos[i].active = 0;
1772 }
1773 /* wait for all URBS to terminate */
1774 mdelay(10);
1775 if (context->ctrl_urb) {
1776 usb_unlink_urb(context->ctrl_urb);
1777 usb_free_urb(context->ctrl_urb);
1778 context->ctrl_urb = NULL;
1779 }
1780 hisax_unregister(&context->d_if);
1781 kfree(context); /* free our structure again */
1782} /* hfc_usb_disconnect */
1783
1784/************************************/
1785/* our driver information structure */
1786/************************************/
1787static struct usb_driver hfc_drv = {
1788 .owner = THIS_MODULE,.name =
1789 "hfc_usb",.id_table = hfc_usb_idtab,.probe =
1790 hfc_usb_probe,.disconnect = hfc_usb_disconnect,
1791};
1792static void __exit
1793hfc_usb_exit(void)
1794{
1795#ifdef CONFIG_HISAX_DEBUG
1796 DBG(USB_DBG, "HFC-S USB: calling \"hfc_usb_exit\" ...");
1797#endif
1798 usb_deregister(&hfc_drv); /* release our driver */
1799 printk(KERN_INFO "HFC-S USB: module removed\n");
1800}
1801
1802static int __init
1803hfc_usb_init(void)
1804{
1805#ifndef CONFIG_HISAX_DEBUG
1806 unsigned int debug = -1;
1807#endif
1808 char revstr[30], datestr[30], dummy[30];
1809 sscanf(hfcusb_revision,
1810 "%s %s $ %s %s %s $ ", dummy, revstr,
1811 dummy, datestr, dummy);
1812 printk(KERN_INFO
1813 "HFC-S USB: driver module revision %s date %s loaded, (debug=%i)\n",
1814 revstr, datestr, debug);
1815 if (usb_register(&hfc_drv)) {
1816 printk(KERN_INFO
1817 "HFC-S USB: Unable to register HFC-S USB module at usb stack\n");
1818 return (-1); /* unable to register */
1819 }
1820 return (0);
1821}
1822
1823module_init(hfc_usb_init);
1824module_exit(hfc_usb_exit);
1825MODULE_AUTHOR(DRIVER_AUTHOR);
1826MODULE_DESCRIPTION(DRIVER_DESC);
1827MODULE_LICENSE("GPL");
1828MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
new file mode 100644
index 00000000000..b171600cf64
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -0,0 +1,228 @@
1/*
2* hfc_usb.h
3*
4* $Id: hfc_usb.h,v 4.1 2005/01/26 17:25:53 martinb1 Exp $
5*/
6
7#ifndef __HFC_USB_H__
8#define __HFC_USB_H__
9
10#define DRIVER_AUTHOR "Peter Sprenger (sprenger@moving-byters.de)"
11#define DRIVER_DESC "HFC-S USB based HiSAX ISDN driver"
12
13#define VERBOSE_USB_DEBUG
14
15#define TRUE 1
16#define FALSE 0
17
18
19/***********/
20/* defines */
21/***********/
22#define HFC_CTRL_TIMEOUT 20 /* 5ms timeout writing/reading regs */
23#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */
24#define HFC_TIMER_T4 500 /* time for state change interval */
25
26#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */
27#define HFCUSB_L1_DRX 1 /* D-frame received */
28#define HFCUSB_L1_ERX 2 /* E-frame received */
29#define HFCUSB_L1_DTX 4 /* D-frames completed */
30
31#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
32
33#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
34#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */
35
36#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
37#define HFCUSB_CIRM 0x00 /* cirm register index */
38#define HFCUSB_USB_SIZE 0x07 /* int length register */
39#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
40#define HFCUSB_F_CROSS 0x0b /* bit order register */
41#define HFCUSB_CLKDEL 0x37 /* bit delay register */
42#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
43#define HFCUSB_HDLC_PAR 0xfb
44#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
45#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
46#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
47#define HFCUSB_F_THRES 0x0c /* threshold register */
48#define HFCUSB_FIFO 0x0f /* fifo select register */
49#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
50#define HFCUSB_MST_MODE0 0x14
51#define HFCUSB_MST_MODE1 0x15
52#define HFCUSB_P_DATA 0x1f
53#define HFCUSB_INC_RES_F 0x0e
54#define HFCUSB_STATES 0x30
55
56#define HFCUSB_CHIPID 0x40 /* ID value of HFC-S USB */
57
58/******************/
59/* fifo registers */
60/******************/
61#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
62#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
63#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
64#define HFCUSB_B2_TX 2
65#define HFCUSB_B2_RX 3
66#define HFCUSB_D_TX 4
67#define HFCUSB_D_RX 5
68#define HFCUSB_PCM_TX 6
69#define HFCUSB_PCM_RX 7
70
71/*
72* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
73* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
74*/
75#define USB_INT 0
76#define USB_BULK 1
77#define USB_ISOC 2
78
79#define ISOC_PACKETS_D 8
80#define ISOC_PACKETS_B 8
81#define ISO_BUFFER_SIZE 128
82
83// ISO send definitions
84#define SINK_MAX 68
85#define SINK_MIN 48
86#define SINK_DMIN 12
87#define SINK_DMAX 18
88#define BITLINE_INF (-64*8)
89
90
91/**********/
92/* macros */
93/**********/
94#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
95#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
96
97
98/*******************/
99/* Debugging Flags */
100/*******************/
101#define USB_DBG 1
102#define ISDN_DBG 2
103
104
105/* *********************/
106/* USB related defines */
107/***********************/
108#define HFC_CTRL_BUFSIZE 32
109
110
111
112/*************************************************/
113/* entry and size of output/input control buffer */
114/*************************************************/
115typedef struct {
116 __u8 hfc_reg; /* register number */
117 __u8 reg_val; /* value to be written (or read) */
118 int action; /* data for action handler */
119} ctrl_buft;
120
121
122/********************/
123/* URB error codes: */
124/********************/
125/* Used to represent a list of values and their respective symbolic names */
126struct hfcusb_symbolic_list {
127 const int num;
128 const char *name;
129};
130
131static struct hfcusb_symbolic_list urb_errlist[] = {
132 {-ENOMEM, "No memory for allocation of internal structures"},
133 {-ENOSPC, "The host controller's bandwidth is already consumed"},
134 {-ENOENT, "URB was canceled by unlink_urb"},
135 {-EXDEV, "ISO transfer only partially completed"},
136 {-EAGAIN, "Too match scheduled for the future"},
137 {-ENXIO, "URB already queued"},
138 {-EFBIG, "Too much ISO frames requested"},
139 {-ENOSR, "Buffer error (overrun)"},
140 {-EPIPE, "Specified endpoint is stalled (device not responding)"},
141 {-EOVERFLOW, "Babble (bad cable?)"},
142 {-EPROTO, "Bit-stuff error (bad cable?)"},
143 {-EILSEQ, "CRC/Timeout"},
144 {-ETIMEDOUT, "NAK (device does not respond)"},
145 {-ESHUTDOWN, "Device unplugged"},
146 {-1, NULL}
147};
148
149
150/*****************************************************/
151/* device dependant information to support different */
152/* ISDN Ta's using the HFC-S USB chip */
153/*****************************************************/
154
155/* USB descriptor need to contain one of the following EndPoint combination: */
156#define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT
157#define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT
158#define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT
159#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT
160
161#define EP_NUL 1 // Endpoint at this position not allowed
162#define EP_NOP 2 // all type of endpoints allowed at this position
163#define EP_ISO 3 // Isochron endpoint mandatory at this position
164#define EP_BLK 4 // Bulk endpoint mandatory at this position
165#define EP_INT 5 // Interrupt endpoint mandatory at this position
166
167/* this array represents all endpoints possible in the HCF-USB the last
168* 3 entries are the configuration number, the minimum interval for
169* Interrupt endpoints & boolean if E-channel logging possible
170*/
171int validconf[][19] = {
172 // INT in, ISO out config
173 {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT,
174 EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
175 CNF_4INT3ISO, 2, 1},
176 {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_NUL,
177 EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
178 CNF_3INT3ISO, 2, 0},
179 // ISO in, ISO out config
180 {EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
181 EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NOP, EP_ISO,
182 CNF_4ISO3ISO, 2, 1},
183 {EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
184 EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NUL, EP_NUL,
185 CNF_3ISO3ISO, 2, 0},
186 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // EOL element
187};
188
189// string description of chosen config
190char *conf_str[] = {
191 "4 Interrupt IN + 3 Isochron OUT",
192 "3 Interrupt IN + 3 Isochron OUT",
193 "4 Isochron IN + 3 Isochron OUT",
194 "3 Isochron IN + 3 Isochron OUT"
195};
196
197
198typedef struct {
199 int vendor; // vendor id
200 int prod_id; // product id
201 char *vend_name; // vendor string
202 __u8 led_scheme; // led display scheme
203 signed short led_bits[8]; // array of 8 possible LED bitmask settings
204} vendor_data;
205
206#define LED_OFF 0 // no LED support
207#define LED_SCHEME1 1 // LED standard scheme
208#define LED_SCHEME2 2 // not used yet...
209
210#define LED_POWER_ON 1
211#define LED_POWER_OFF 2
212#define LED_S0_ON 3
213#define LED_S0_OFF 4
214#define LED_B1_ON 5
215#define LED_B1_OFF 6
216#define LED_B1_DATA 7
217#define LED_B2_ON 8
218#define LED_B2_OFF 9
219#define LED_B2_DATA 10
220
221#define LED_NORMAL 0 // LEDs are normal
222#define LED_INVERTED 1 // LEDs are inverted
223
224/* time in ms to perform a Flashing LED when B-Channel has traffic */
225#define LED_TIME 250
226
227
228#endif // __HFC_USB_H__
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
new file mode 100644
index 00000000000..6fc55fea170
--- /dev/null
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -0,0 +1,266 @@
1/* $Id: hfcscard.c,v 1.10.2.4 2004/01/14 16:04:48 keil Exp $
2 *
3 * low level stuff for hfcs based cards (Teles3c, ACER P10)
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include <linux/isapnp.h>
15#include "hisax.h"
16#include "hfc_2bds0.h"
17#include "isdnl1.h"
18
19extern const char *CardType[];
20
21static const char *hfcs_revision = "$Revision: 1.10.2.4 $";
22
23static irqreturn_t
24hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
25{
26 struct IsdnCardState *cs = dev_id;
27 u_char val, stat;
28 u_long flags;
29
30 spin_lock_irqsave(&cs->lock, flags);
31 if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) &
32 (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
33 val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
34 if (cs->debug & L1_DEB_ISAC)
35 debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
36 hfc2bds0_interrupt(cs, val);
37 } else {
38 if (cs->debug & L1_DEB_ISAC)
39 debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
40 }
41 spin_unlock_irqrestore(&cs->lock, flags);
42 return IRQ_HANDLED;
43}
44
45static void
46hfcs_Timer(struct IsdnCardState *cs)
47{
48 cs->hw.hfcD.timer.expires = jiffies + 75;
49 /* WD RESET */
50/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
51 add_timer(&cs->hw.hfcD.timer);
52*/
53}
54
55void
56release_io_hfcs(struct IsdnCardState *cs)
57{
58 release2bds0(cs);
59 del_timer(&cs->hw.hfcD.timer);
60 if (cs->hw.hfcD.addr)
61 release_region(cs->hw.hfcD.addr, 2);
62}
63
64static void
65reset_hfcs(struct IsdnCardState *cs)
66{
67 printk(KERN_INFO "HFCS: resetting card\n");
68 cs->hw.hfcD.cirm = HFCD_RESET;
69 if (cs->typ == ISDN_CTYPE_TELES3C)
70 cs->hw.hfcD.cirm |= HFCD_MEM8K;
71 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */
72 mdelay(10);
73 cs->hw.hfcD.cirm = 0;
74 if (cs->typ == ISDN_CTYPE_TELES3C)
75 cs->hw.hfcD.cirm |= HFCD_MEM8K;
76 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */
77 mdelay(10);
78 if (cs->typ == ISDN_CTYPE_TELES3C)
79 cs->hw.hfcD.cirm |= HFCD_INTB;
80 else if (cs->typ == ISDN_CTYPE_ACERP10)
81 cs->hw.hfcD.cirm |= HFCD_INTA;
82 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
83 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
84 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
85 cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
86 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
87 cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
88 cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
89 HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
90 HFCD_INTS_DREC | HFCD_INTS_L1STATE;
91 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
92 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
93 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
94 udelay(10);
95 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
96 cs->hw.hfcD.mst_m = HFCD_MASTER;
97 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */
98 cs->hw.hfcD.sctrl = 0;
99 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
100}
101
102static int
103hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
104{
105 u_long flags;
106 int delay;
107
108 if (cs->debug & L1_DEB_ISAC)
109 debugl1(cs, "HFCS: card_msg %x", mt);
110 switch (mt) {
111 case CARD_RESET:
112 spin_lock_irqsave(&cs->lock, flags);
113 reset_hfcs(cs);
114 spin_unlock_irqrestore(&cs->lock, flags);
115 return(0);
116 case CARD_RELEASE:
117 release_io_hfcs(cs);
118 return(0);
119 case CARD_INIT:
120 delay = (75*HZ)/100 +1;
121 cs->hw.hfcD.timer.expires = jiffies + delay;
122 add_timer(&cs->hw.hfcD.timer);
123 spin_lock_irqsave(&cs->lock, flags);
124 reset_hfcs(cs);
125 init2bds0(cs);
126 spin_unlock_irqrestore(&cs->lock, flags);
127 delay = (80*HZ)/1000 +1;
128 msleep(80);
129 spin_lock_irqsave(&cs->lock, flags);
130 cs->hw.hfcD.ctmt |= HFCD_TIM800;
131 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
132 cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
133 spin_unlock_irqrestore(&cs->lock, flags);
134 return(0);
135 case CARD_TEST:
136 return(0);
137 }
138 return(0);
139}
140
141#ifdef __ISAPNP__
142static struct isapnp_device_id hfc_ids[] __initdata = {
143 { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
144 ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
145 (unsigned long) "Acer P10" },
146 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
147 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
148 (unsigned long) "Billion 2" },
149 { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
150 ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
151 (unsigned long) "Billion 1" },
152 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
153 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
154 (unsigned long) "IStar PnP" },
155 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
156 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
157 (unsigned long) "Teles 16.3c" },
158 { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
159 ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
160 (unsigned long) "Tornado Tipa C" },
161 { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
162 ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
163 (unsigned long) "Genius Speed Surfer" },
164 { 0, }
165};
166
167static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
168static struct pnp_card *pnp_c __devinitdata = NULL;
169#endif
170
171int __init
172setup_hfcs(struct IsdnCard *card)
173{
174 struct IsdnCardState *cs = card->cs;
175 char tmp[64];
176
177 strcpy(tmp, hfcs_revision);
178 printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
179
180#ifdef __ISAPNP__
181 if (!card->para[1] && isapnp_present()) {
182 struct pnp_dev *pnp_d;
183 while(ipid->card_vendor) {
184 if ((pnp_c = pnp_find_card(ipid->card_vendor,
185 ipid->card_device, pnp_c))) {
186 pnp_d = NULL;
187 if ((pnp_d = pnp_find_dev(pnp_c,
188 ipid->vendor, ipid->function, pnp_d))) {
189 int err;
190
191 printk(KERN_INFO "HiSax: %s detected\n",
192 (char *)ipid->driver_data);
193 pnp_disable_dev(pnp_d);
194 err = pnp_activate_dev(pnp_d);
195 if (err<0) {
196 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
197 __FUNCTION__, err);
198 return(0);
199 }
200 card->para[1] = pnp_port_start(pnp_d, 0);
201 card->para[0] = pnp_irq(pnp_d, 0);
202 if (!card->para[0] || !card->para[1]) {
203 printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
204 card->para[0], card->para[1]);
205 pnp_disable_dev(pnp_d);
206 return(0);
207 }
208 break;
209 } else {
210 printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
211 }
212 }
213 ipid++;
214 pnp_c = NULL;
215 }
216 if (!ipid->card_vendor) {
217 printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
218 return(0);
219 }
220 }
221#endif
222 cs->hw.hfcD.addr = card->para[1] & 0xfffe;
223 cs->irq = card->para[0];
224 cs->hw.hfcD.cip = 0;
225 cs->hw.hfcD.int_s1 = 0;
226 cs->hw.hfcD.send = NULL;
227 cs->bcs[0].hw.hfc.send = NULL;
228 cs->bcs[1].hw.hfc.send = NULL;
229 cs->hw.hfcD.dfifosize = 512;
230 cs->dc.hfcd.ph_state = 0;
231 cs->hw.hfcD.fifo = 255;
232 if (cs->typ == ISDN_CTYPE_TELES3C) {
233 cs->hw.hfcD.bfifosize = 1024 + 512;
234 } else if (cs->typ == ISDN_CTYPE_ACERP10) {
235 cs->hw.hfcD.bfifosize = 7*1024 + 512;
236 } else
237 return (0);
238 if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
239 printk(KERN_WARNING
240 "HiSax: %s config port %x-%x already in use\n",
241 CardType[card->typ],
242 cs->hw.hfcD.addr,
243 cs->hw.hfcD.addr + 2);
244 return (0);
245 }
246 printk(KERN_INFO
247 "HFCS: defined at 0x%x IRQ %d HZ %d\n",
248 cs->hw.hfcD.addr,
249 cs->irq, HZ);
250 if (cs->typ == ISDN_CTYPE_TELES3C) {
251 /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
252 outb(0x00, cs->hw.hfcD.addr);
253 outb(0x56, cs->hw.hfcD.addr | 1);
254 } else if (cs->typ == ISDN_CTYPE_ACERP10) {
255 /* Acer P10 IO ADR is 0x300 */
256 outb(0x00, cs->hw.hfcD.addr);
257 outb(0x57, cs->hw.hfcD.addr | 1);
258 }
259 set_cs_func(cs);
260 cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
261 cs->hw.hfcD.timer.data = (long) cs;
262 init_timer(&cs->hw.hfcD.timer);
263 cs->cardmsg = &hfcs_card_msg;
264 cs->irq_func = &hfcs_interrupt;
265 return (1);
266}
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
new file mode 100644
index 00000000000..dc5791728d5
--- /dev/null
+++ b/drivers/isdn/hisax/hisax.h
@@ -0,0 +1,1341 @@
1/* $Id: hisax.h,v 2.64.2.4 2004/02/11 13:21:33 keil Exp $
2 *
3 * Basic declarations, defines and prototypes
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9#include <linux/config.h>
10#include <linux/errno.h>
11#include <linux/fs.h>
12#include <linux/major.h>
13#include <asm/segment.h>
14#include <asm/io.h>
15#include <linux/delay.h>
16#include <linux/kernel.h>
17#include <linux/signal.h>
18#include <linux/slab.h>
19#include <linux/mm.h>
20#include <linux/mman.h>
21#include <linux/ioport.h>
22#include <linux/timer.h>
23#include <linux/wait.h>
24#include <linux/isdnif.h>
25#include <linux/tty.h>
26#include <linux/serial_reg.h>
27#include <linux/netdevice.h>
28
29#define ERROR_STATISTIC
30
31#define REQUEST 0
32#define CONFIRM 1
33#define INDICATION 2
34#define RESPONSE 3
35
36#define HW_ENABLE 0x0000
37#define HW_RESET 0x0004
38#define HW_POWERUP 0x0008
39#define HW_ACTIVATE 0x0010
40#define HW_DEACTIVATE 0x0018
41
42#define HW_INFO1 0x0010
43#define HW_INFO2 0x0020
44#define HW_INFO3 0x0030
45#define HW_INFO4 0x0040
46#define HW_INFO4_P8 0x0040
47#define HW_INFO4_P10 0x0048
48#define HW_RSYNC 0x0060
49#define HW_TESTLOOP 0x0070
50#define CARD_RESET 0x00F0
51#define CARD_INIT 0x00F2
52#define CARD_RELEASE 0x00F3
53#define CARD_TEST 0x00F4
54#define CARD_AUX_IND 0x00F5
55
56#define PH_ACTIVATE 0x0100
57#define PH_DEACTIVATE 0x0110
58#define PH_DATA 0x0120
59#define PH_PULL 0x0130
60#define PH_TESTLOOP 0x0140
61#define PH_PAUSE 0x0150
62#define MPH_ACTIVATE 0x0180
63#define MPH_DEACTIVATE 0x0190
64#define MPH_INFORMATION 0x01A0
65
66#define DL_ESTABLISH 0x0200
67#define DL_RELEASE 0x0210
68#define DL_DATA 0x0220
69#define DL_FLUSH 0x0224
70#define DL_UNIT_DATA 0x0230
71
72#define MDL_BC_RELEASE 0x0278 // Formula-n enter:now
73#define MDL_BC_ASSIGN 0x027C // Formula-n enter:now
74#define MDL_ASSIGN 0x0280
75#define MDL_REMOVE 0x0284
76#define MDL_ERROR 0x0288
77#define MDL_INFO_SETUP 0x02E0
78#define MDL_INFO_CONN 0x02E4
79#define MDL_INFO_REL 0x02E8
80
81#define CC_SETUP 0x0300
82#define CC_RESUME 0x0304
83#define CC_MORE_INFO 0x0310
84#define CC_IGNORE 0x0320
85#define CC_REJECT 0x0324
86#define CC_SETUP_COMPL 0x0330
87#define CC_PROCEEDING 0x0340
88#define CC_ALERTING 0x0344
89#define CC_PROGRESS 0x0348
90#define CC_CONNECT 0x0350
91#define CC_CHARGE 0x0354
92#define CC_NOTIFY 0x0358
93#define CC_DISCONNECT 0x0360
94#define CC_RELEASE 0x0368
95#define CC_SUSPEND 0x0370
96#define CC_PROCEED_SEND 0x0374
97#define CC_REDIR 0x0378
98#define CC_T302 0x0382
99#define CC_T303 0x0383
100#define CC_T304 0x0384
101#define CC_T305 0x0385
102#define CC_T308_1 0x0388
103#define CC_T308_2 0x038A
104#define CC_T309 0x0309
105#define CC_T310 0x0390
106#define CC_T313 0x0393
107#define CC_T318 0x0398
108#define CC_T319 0x0399
109#define CC_TSPID 0x03A0
110#define CC_NOSETUP_RSP 0x03E0
111#define CC_SETUP_ERR 0x03E1
112#define CC_SUSPEND_ERR 0x03E2
113#define CC_RESUME_ERR 0x03E3
114#define CC_CONNECT_ERR 0x03E4
115#define CC_RELEASE_ERR 0x03E5
116#define CC_RESTART 0x03F4
117#define CC_TDSS1_IO 0x13F4 /* DSS1 IO user timer */
118#define CC_TNI1_IO 0x13F5 /* NI1 IO user timer */
119
120/* define maximum number of possible waiting incoming calls */
121#define MAX_WAITING_CALLS 2
122
123
124#ifdef __KERNEL__
125
126/* include l3dss1 & ni1 specific process structures, but no other defines */
127#ifdef CONFIG_HISAX_EURO
128 #define l3dss1_process
129 #include "l3dss1.h"
130 #undef l3dss1_process
131#endif /* CONFIG_HISAX_EURO */
132
133#ifdef CONFIG_HISAX_NI1
134 #define l3ni1_process
135 #include "l3ni1.h"
136 #undef l3ni1_process
137#endif /* CONFIG_HISAX_NI1 */
138
139#define MAX_DFRAME_LEN 260
140#define MAX_DFRAME_LEN_L1 300
141#define HSCX_BUFMAX 4096
142#define MAX_DATA_SIZE (HSCX_BUFMAX - 4)
143#define MAX_DATA_MEM (HSCX_BUFMAX + 64)
144#define RAW_BUFMAX (((HSCX_BUFMAX*6)/5) + 5)
145#define MAX_HEADER_LEN 4
146#define MAX_WINDOW 8
147#define MAX_MON_FRAME 32
148#define MAX_DLOG_SPACE 2048
149#define MAX_BLOG_SPACE 256
150
151/* #define I4L_IRQ_FLAG SA_INTERRUPT */
152#define I4L_IRQ_FLAG 0
153
154/*
155 * Statemachine
156 */
157
158struct FsmInst;
159
160typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
161
162struct Fsm {
163 FSMFNPTR *jumpmatrix;
164 int state_count, event_count;
165 char **strEvent, **strState;
166};
167
168struct FsmInst {
169 struct Fsm *fsm;
170 int state;
171 int debug;
172 void *userdata;
173 int userint;
174 void (*printdebug) (struct FsmInst *, char *, ...);
175};
176
177struct FsmNode {
178 int state, event;
179 void (*routine) (struct FsmInst *, int, void *);
180};
181
182struct FsmTimer {
183 struct FsmInst *fi;
184 struct timer_list tl;
185 int event;
186 void *arg;
187};
188
189struct L3Timer {
190 struct l3_process *pc;
191 struct timer_list tl;
192 int event;
193};
194
195#define FLG_L1_ACTIVATING 1
196#define FLG_L1_ACTIVATED 2
197#define FLG_L1_DEACTTIMER 3
198#define FLG_L1_ACTTIMER 4
199#define FLG_L1_T3RUN 5
200#define FLG_L1_PULL_REQ 6
201#define FLG_L1_UINT 7
202
203struct Layer1 {
204 void *hardware;
205 struct BCState *bcs;
206 struct PStack **stlistp;
207 long Flags;
208 struct FsmInst l1m;
209 struct FsmTimer timer;
210 void (*l1l2) (struct PStack *, int, void *);
211 void (*l1hw) (struct PStack *, int, void *);
212 void (*l1tei) (struct PStack *, int, void *);
213 int mode, bc;
214 int delay;
215};
216
217#define GROUP_TEI 127
218#define TEI_SAPI 63
219#define CTRL_SAPI 0
220#define PACKET_NOACK 250
221
222/* Layer2 Flags */
223
224#define FLG_LAPB 0
225#define FLG_LAPD 1
226#define FLG_ORIG 2
227#define FLG_MOD128 3
228#define FLG_PEND_REL 4
229#define FLG_L3_INIT 5
230#define FLG_T200_RUN 6
231#define FLG_ACK_PEND 7
232#define FLG_REJEXC 8
233#define FLG_OWN_BUSY 9
234#define FLG_PEER_BUSY 10
235#define FLG_DCHAN_BUSY 11
236#define FLG_L1_ACTIV 12
237#define FLG_ESTAB_PEND 13
238#define FLG_PTP 14
239#define FLG_FIXED_TEI 15
240#define FLG_L2BLOCK 16
241
242struct Layer2 {
243 int tei;
244 int sap;
245 int maxlen;
246 u_long flag;
247 spinlock_t lock;
248 u_int vs, va, vr;
249 int rc;
250 unsigned int window;
251 unsigned int sow;
252 struct sk_buff *windowar[MAX_WINDOW];
253 struct sk_buff_head i_queue;
254 struct sk_buff_head ui_queue;
255 void (*l2l1) (struct PStack *, int, void *);
256 void (*l2l3) (struct PStack *, int, void *);
257 void (*l2tei) (struct PStack *, int, void *);
258 struct FsmInst l2m;
259 struct FsmTimer t200, t203;
260 int T200, N200, T203;
261 int debug;
262 char debug_id[16];
263};
264
265struct Layer3 {
266 void (*l3l4) (struct PStack *, int, void *);
267 void (*l3ml3) (struct PStack *, int, void *);
268 void (*l3l2) (struct PStack *, int, void *);
269 struct FsmInst l3m;
270 struct FsmTimer l3m_timer;
271 struct sk_buff_head squeue;
272 struct l3_process *proc;
273 struct l3_process *global;
274 int N303;
275 int debug;
276 char debug_id[8];
277};
278
279struct LLInterface {
280 void (*l4l3) (struct PStack *, int, void *);
281 int (*l4l3_proto) (struct PStack *, isdn_ctrl *);
282 void *userdata;
283 u_long flag;
284};
285
286#define FLG_LLI_L1WAKEUP 1
287#define FLG_LLI_L2WAKEUP 2
288
289struct Management {
290 int ri;
291 struct FsmInst tei_m;
292 struct FsmTimer t202;
293 int T202, N202, debug;
294 void (*layer) (struct PStack *, int, void *);
295};
296
297#define NO_CAUSE 254
298
299struct Param {
300 u_char cause;
301 u_char loc;
302 u_char diag[6];
303 int bchannel;
304 int chargeinfo;
305 int spv; /* SPV Flag */
306 setup_parm setup; /* from isdnif.h numbers and Serviceindicator */
307 u_char moderate; /* transfer mode and rate (bearer octet 4) */
308};
309
310
311struct PStack {
312 struct PStack *next;
313 struct Layer1 l1;
314 struct Layer2 l2;
315 struct Layer3 l3;
316 struct LLInterface lli;
317 struct Management ma;
318 int protocol; /* EDSS1, 1TR6 or NI1 */
319
320 /* protocol specific data fields */
321 union
322 { u_char uuuu; /* only as dummy */
323#ifdef CONFIG_HISAX_EURO
324 dss1_stk_priv dss1; /* private dss1 data */
325#endif /* CONFIG_HISAX_EURO */
326#ifdef CONFIG_HISAX_NI1
327 ni1_stk_priv ni1; /* private ni1 data */
328#endif /* CONFIG_HISAX_NI1 */
329 } prot;
330};
331
332struct l3_process {
333 int callref;
334 int state;
335 struct L3Timer timer;
336 int N303;
337 int debug;
338 struct Param para;
339 struct Channel *chan;
340 struct PStack *st;
341 struct l3_process *next;
342 ulong redir_result;
343
344 /* protocol specific data fields */
345 union
346 { u_char uuuu; /* only when euro not defined, avoiding empty union */
347#ifdef CONFIG_HISAX_EURO
348 dss1_proc_priv dss1; /* private dss1 data */
349#endif /* CONFIG_HISAX_EURO */
350#ifdef CONFIG_HISAX_NI1
351 ni1_proc_priv ni1; /* private ni1 data */
352#endif /* CONFIG_HISAX_NI1 */
353 } prot;
354};
355
356struct hscx_hw {
357 int hscx;
358 int rcvidx;
359 int count; /* Current skb sent count */
360 u_char *rcvbuf; /* B-Channel receive Buffer */
361 u_char tsaxr0;
362 u_char tsaxr1;
363};
364
365struct w6692B_hw {
366 int bchan;
367 int rcvidx;
368 int count; /* Current skb sent count */
369 u_char *rcvbuf; /* B-Channel receive Buffer */
370};
371
372struct isar_reg {
373 unsigned long Flags;
374 volatile u_char bstat;
375 volatile u_char iis;
376 volatile u_char cmsb;
377 volatile u_char clsb;
378 volatile u_char par[8];
379};
380
381struct isar_hw {
382 int dpath;
383 int rcvidx;
384 int txcnt;
385 int mml;
386 u_char state;
387 u_char cmd;
388 u_char mod;
389 u_char newcmd;
390 u_char newmod;
391 char try_mod;
392 struct timer_list ftimer;
393 u_char *rcvbuf; /* B-Channel receive Buffer */
394 u_char conmsg[16];
395 struct isar_reg *reg;
396};
397
398struct hdlc_stat_reg {
399#ifdef __BIG_ENDIAN
400 u_char fill __attribute__((packed));
401 u_char mode __attribute__((packed));
402 u_char xml __attribute__((packed));
403 u_char cmd __attribute__((packed));
404#else
405 u_char cmd __attribute__((packed));
406 u_char xml __attribute__((packed));
407 u_char mode __attribute__((packed));
408 u_char fill __attribute__((packed));
409#endif
410};
411
412struct hdlc_hw {
413 union {
414 u_int ctrl;
415 struct hdlc_stat_reg sr;
416 } ctrl;
417 u_int stat;
418 int rcvidx;
419 int count; /* Current skb sent count */
420 u_char *rcvbuf; /* B-Channel receive Buffer */
421};
422
423struct hfcB_hw {
424 unsigned int *send;
425 int f1;
426 int f2;
427};
428
429struct tiger_hw {
430 u_int *send;
431 u_int *s_irq;
432 u_int *s_end;
433 u_int *sendp;
434 u_int *rec;
435 int free;
436 u_char *rcvbuf;
437 u_char *sendbuf;
438 u_char *sp;
439 int sendcnt;
440 u_int s_tot;
441 u_int r_bitcnt;
442 u_int r_tot;
443 u_int r_err;
444 u_int r_fcs;
445 u_char r_state;
446 u_char r_one;
447 u_char r_val;
448 u_char s_state;
449};
450
451struct amd7930_hw {
452 u_char *tx_buff;
453 u_char *rv_buff;
454 int rv_buff_in;
455 int rv_buff_out;
456 struct sk_buff *rv_skb;
457 struct hdlc_state *hdlc_state;
458 struct work_struct tq_rcv;
459 struct work_struct tq_xmt;
460};
461
462#define BC_FLG_INIT 1
463#define BC_FLG_ACTIV 2
464#define BC_FLG_BUSY 3
465#define BC_FLG_NOFRAME 4
466#define BC_FLG_HALF 5
467#define BC_FLG_EMPTY 6
468#define BC_FLG_ORIG 7
469#define BC_FLG_DLEETX 8
470#define BC_FLG_LASTDLE 9
471#define BC_FLG_FIRST 10
472#define BC_FLG_LASTDATA 11
473#define BC_FLG_NMD_DATA 12
474#define BC_FLG_FTI_RUN 13
475#define BC_FLG_LL_OK 14
476#define BC_FLG_LL_CONN 15
477#define BC_FLG_FTI_FTS 16
478#define BC_FLG_FRH_WAIT 17
479
480#define L1_MODE_NULL 0
481#define L1_MODE_TRANS 1
482#define L1_MODE_HDLC 2
483#define L1_MODE_EXTRN 3
484#define L1_MODE_HDLC_56K 4
485#define L1_MODE_MODEM 7
486#define L1_MODE_V32 8
487#define L1_MODE_FAX 9
488
489struct BCState {
490 int channel;
491 int mode;
492 u_long Flag;
493 struct IsdnCardState *cs;
494 int tx_cnt; /* B-Channel transmit counter */
495 struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
496 struct sk_buff_head rqueue; /* B-Channel receive Queue */
497 struct sk_buff_head squeue; /* B-Channel send Queue */
498 int ackcnt;
499 spinlock_t aclock;
500 struct PStack *st;
501 u_char *blog;
502 u_char *conmsg;
503 struct timer_list transbusy;
504 struct work_struct tqueue;
505 u_long event;
506 int (*BC_SetStack) (struct PStack *, struct BCState *);
507 void (*BC_Close) (struct BCState *);
508#ifdef ERROR_STATISTIC
509 int err_crc;
510 int err_tx;
511 int err_rdo;
512 int err_inv;
513#endif
514 union {
515 struct hscx_hw hscx;
516 struct hdlc_hw hdlc;
517 struct isar_hw isar;
518 struct hfcB_hw hfc;
519 struct tiger_hw tiger;
520 struct amd7930_hw amd7930;
521 struct w6692B_hw w6692;
522 struct hisax_b_if *b_if;
523 } hw;
524};
525
526struct Channel {
527 struct PStack *b_st, *d_st;
528 struct IsdnCardState *cs;
529 struct BCState *bcs;
530 int chan;
531 int incoming;
532 struct FsmInst fi;
533 struct FsmTimer drel_timer, dial_timer;
534 int debug;
535 int l2_protocol, l2_active_protocol;
536 int l3_protocol;
537 int data_open;
538 struct l3_process *proc;
539 setup_parm setup; /* from isdnif.h numbers and Serviceindicator */
540 u_long Flags; /* for remembering action done in l4 */
541 int leased;
542};
543
544struct elsa_hw {
545 struct pci_dev *dev;
546 unsigned long base;
547 unsigned int cfg;
548 unsigned int ctrl;
549 unsigned int ale;
550 unsigned int isac;
551 unsigned int itac;
552 unsigned int hscx;
553 unsigned int trig;
554 unsigned int timer;
555 unsigned int counter;
556 unsigned int status;
557 struct timer_list tl;
558 unsigned int MFlag;
559 struct BCState *bcs;
560 u_char *transbuf;
561 u_char *rcvbuf;
562 unsigned int transp;
563 unsigned int rcvp;
564 unsigned int transcnt;
565 unsigned int rcvcnt;
566 u_char IER;
567 u_char FCR;
568 u_char LCR;
569 u_char MCR;
570 u_char ctrl_reg;
571};
572
573struct teles3_hw {
574 unsigned int cfg_reg;
575 signed int isac;
576 signed int hscx[2];
577 signed int isacfifo;
578 signed int hscxfifo[2];
579};
580
581struct teles0_hw {
582 unsigned int cfg_reg;
583 void __iomem *membase;
584 unsigned long phymem;
585};
586
587struct avm_hw {
588 unsigned int cfg_reg;
589 unsigned int isac;
590 unsigned int hscx[2];
591 unsigned int isacfifo;
592 unsigned int hscxfifo[2];
593 unsigned int counter;
594 struct pci_dev *dev;
595};
596
597struct ix1_hw {
598 unsigned int cfg_reg;
599 unsigned int isac_ale;
600 unsigned int isac;
601 unsigned int hscx_ale;
602 unsigned int hscx;
603};
604
605struct diva_hw {
606 unsigned long cfg_reg;
607 unsigned long pci_cfg;
608 unsigned int ctrl;
609 unsigned long isac_adr;
610 unsigned int isac;
611 unsigned long hscx_adr;
612 unsigned int hscx;
613 unsigned int status;
614 struct timer_list tl;
615 u_char ctrl_reg;
616 struct pci_dev *dev;
617};
618
619struct asus_hw {
620 unsigned int cfg_reg;
621 unsigned int adr;
622 unsigned int isac;
623 unsigned int hscx;
624 unsigned int u7;
625 unsigned int pots;
626};
627
628
629struct hfc_hw {
630 unsigned int addr;
631 unsigned int fifosize;
632 unsigned char cirm;
633 unsigned char ctmt;
634 unsigned char cip;
635 u_char isac_spcr;
636 struct timer_list timer;
637};
638
639struct sedl_hw {
640 unsigned int cfg_reg;
641 unsigned int adr;
642 unsigned int isac;
643 unsigned int hscx;
644 unsigned int reset_on;
645 unsigned int reset_off;
646 struct isar_reg isar;
647 unsigned int chip;
648 unsigned int bus;
649 struct pci_dev *dev;
650};
651
652struct spt_hw {
653 unsigned int cfg_reg;
654 unsigned int isac;
655 unsigned int hscx[2];
656 unsigned char res_irq;
657};
658
659struct mic_hw {
660 unsigned int cfg_reg;
661 unsigned int adr;
662 unsigned int isac;
663 unsigned int hscx;
664};
665
666struct njet_hw {
667 unsigned long base;
668 unsigned int isac;
669 unsigned int auxa;
670 unsigned char auxd;
671 unsigned char dmactrl;
672 unsigned char ctrl_reg;
673 unsigned char irqmask0;
674 unsigned char irqstat0;
675 unsigned char last_is0;
676 struct pci_dev *dev;
677};
678
679struct hfcPCI_hw {
680 unsigned char cirm;
681 unsigned char ctmt;
682 unsigned char conn;
683 unsigned char mst_m;
684 unsigned char int_m1;
685 unsigned char int_m2;
686 unsigned char int_s1;
687 unsigned char sctrl;
688 unsigned char sctrl_r;
689 unsigned char sctrl_e;
690 unsigned char trm;
691 unsigned char stat;
692 unsigned char fifo;
693 unsigned char fifo_en;
694 unsigned char bswapped;
695 unsigned char nt_mode;
696 int nt_timer;
697 struct pci_dev *dev;
698 unsigned char *pci_io; /* start of PCI IO memory */
699 void *share_start; /* shared memory for Fifos start */
700 void *fifos; /* FIFO memory */
701 int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */
702 struct timer_list timer;
703};
704
705struct hfcSX_hw {
706 unsigned long base;
707 unsigned char cirm;
708 unsigned char ctmt;
709 unsigned char conn;
710 unsigned char mst_m;
711 unsigned char int_m1;
712 unsigned char int_m2;
713 unsigned char int_s1;
714 unsigned char sctrl;
715 unsigned char sctrl_r;
716 unsigned char sctrl_e;
717 unsigned char trm;
718 unsigned char stat;
719 unsigned char fifo;
720 unsigned char bswapped;
721 unsigned char nt_mode;
722 unsigned char chip;
723 int b_fifo_size;
724 unsigned char last_fifo;
725 void *extra;
726 int nt_timer;
727 struct timer_list timer;
728};
729
730struct hfcD_hw {
731 unsigned int addr;
732 unsigned int bfifosize;
733 unsigned int dfifosize;
734 unsigned char cirm;
735 unsigned char ctmt;
736 unsigned char cip;
737 unsigned char conn;
738 unsigned char mst_m;
739 unsigned char int_m1;
740 unsigned char int_m2;
741 unsigned char int_s1;
742 unsigned char sctrl;
743 unsigned char stat;
744 unsigned char fifo;
745 unsigned char f1;
746 unsigned char f2;
747 unsigned int *send;
748 struct timer_list timer;
749};
750
751struct isurf_hw {
752 unsigned int reset;
753 unsigned long phymem;
754 void __iomem *isac;
755 void __iomem *isar;
756 struct isar_reg isar_r;
757};
758
759struct saphir_hw {
760 struct pci_dev *dev;
761 unsigned int cfg_reg;
762 unsigned int ale;
763 unsigned int isac;
764 unsigned int hscx;
765 struct timer_list timer;
766};
767
768struct bkm_hw {
769 struct pci_dev *dev;
770 unsigned long base;
771 /* A4T stuff */
772 unsigned long isac_adr;
773 unsigned int isac_ale;
774 unsigned long jade_adr;
775 unsigned int jade_ale;
776 /* Scitel Quadro stuff */
777 unsigned long plx_adr;
778 unsigned long data_adr;
779};
780
781struct gazel_hw {
782 struct pci_dev *dev;
783 unsigned int cfg_reg;
784 unsigned int pciaddr[2];
785 signed int ipac;
786 signed int isac;
787 signed int hscx[2];
788 signed int isacfifo;
789 signed int hscxfifo[2];
790 unsigned char timeslot;
791 unsigned char iom2;
792};
793
794struct w6692_hw {
795 struct pci_dev *dev;
796 unsigned int iobase;
797 struct timer_list timer;
798};
799
800#ifdef CONFIG_HISAX_TESTEMU
801struct te_hw {
802 unsigned char *sfifo;
803 unsigned char *sfifo_w;
804 unsigned char *sfifo_r;
805 unsigned char *sfifo_e;
806 int sfifo_cnt;
807 unsigned int stat;
808 wait_queue_head_t rwaitq;
809 wait_queue_head_t swaitq;
810};
811#endif
812
813struct arcofi_msg {
814 struct arcofi_msg *next;
815 u_char receive;
816 u_char len;
817 u_char msg[10];
818};
819
820struct isac_chip {
821 int ph_state;
822 u_char *mon_tx;
823 u_char *mon_rx;
824 int mon_txp;
825 int mon_txc;
826 int mon_rxp;
827 struct arcofi_msg *arcofi_list;
828 struct timer_list arcofitimer;
829 wait_queue_head_t arcofi_wait;
830 u_char arcofi_bc;
831 u_char arcofi_state;
832 u_char mocr;
833 u_char adf2;
834};
835
836struct hfcd_chip {
837 int ph_state;
838};
839
840struct hfcpci_chip {
841 int ph_state;
842};
843
844struct hfcsx_chip {
845 int ph_state;
846};
847
848struct w6692_chip {
849 int ph_state;
850};
851
852struct amd7930_chip {
853 u_char lmr1;
854 u_char ph_state;
855 u_char old_state;
856 u_char flg_t3;
857 unsigned int tx_xmtlen;
858 struct timer_list timer3;
859 void (*ph_command) (struct IsdnCardState *, u_char, char *);
860 void (*setIrqMask) (struct IsdnCardState *, u_char);
861};
862
863struct icc_chip {
864 int ph_state;
865 u_char *mon_tx;
866 u_char *mon_rx;
867 int mon_txp;
868 int mon_txc;
869 int mon_rxp;
870 struct arcofi_msg *arcofi_list;
871 struct timer_list arcofitimer;
872 wait_queue_head_t arcofi_wait;
873 u_char arcofi_bc;
874 u_char arcofi_state;
875 u_char mocr;
876 u_char adf2;
877};
878
879#define HW_IOM1 0
880#define HW_IPAC 1
881#define HW_ISAR 2
882#define HW_ARCOFI 3
883#define FLG_TWO_DCHAN 4
884#define FLG_L1_DBUSY 5
885#define FLG_DBUSY_TIMER 6
886#define FLG_LOCK_ATOMIC 7
887#define FLG_ARCOFI_TIMER 8
888#define FLG_ARCOFI_ERROR 9
889#define FLG_HW_L1_UINT 10
890
891struct IsdnCardState {
892 spinlock_t lock;
893 u_char typ;
894 u_char subtyp;
895 int protocol;
896 u_int irq;
897 u_long irq_flags;
898 u_long HW_Flags;
899 int *busy_flag;
900 int chanlimit; /* limited number of B-chans to use */
901 int logecho; /* log echo if supported by card */
902 union {
903 struct elsa_hw elsa;
904 struct teles0_hw teles0;
905 struct teles3_hw teles3;
906 struct avm_hw avm;
907 struct ix1_hw ix1;
908 struct diva_hw diva;
909 struct asus_hw asus;
910 struct hfc_hw hfc;
911 struct sedl_hw sedl;
912 struct spt_hw spt;
913 struct mic_hw mic;
914 struct njet_hw njet;
915 struct hfcD_hw hfcD;
916 struct hfcPCI_hw hfcpci;
917 struct hfcSX_hw hfcsx;
918 struct ix1_hw niccy;
919 struct isurf_hw isurf;
920 struct saphir_hw saphir;
921#ifdef CONFIG_HISAX_TESTEMU
922 struct te_hw te;
923#endif
924 struct bkm_hw ax;
925 struct gazel_hw gazel;
926 struct w6692_hw w6692;
927 struct hisax_d_if *hisax_d_if;
928 } hw;
929 int myid;
930 isdn_if iif;
931 spinlock_t statlock;
932 u_char *status_buf;
933 u_char *status_read;
934 u_char *status_write;
935 u_char *status_end;
936 u_char (*readisac) (struct IsdnCardState *, u_char);
937 void (*writeisac) (struct IsdnCardState *, u_char, u_char);
938 void (*readisacfifo) (struct IsdnCardState *, u_char *, int);
939 void (*writeisacfifo) (struct IsdnCardState *, u_char *, int);
940 u_char (*BC_Read_Reg) (struct IsdnCardState *, int, u_char);
941 void (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char);
942 void (*BC_Send_Data) (struct BCState *);
943 int (*cardmsg) (struct IsdnCardState *, int, void *);
944 void (*setstack_d) (struct PStack *, struct IsdnCardState *);
945 void (*DC_Close) (struct IsdnCardState *);
946 int (*irq_func) (int, void *, struct pt_regs *);
947 int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
948 struct Channel channel[2+MAX_WAITING_CALLS];
949 struct BCState bcs[2+MAX_WAITING_CALLS];
950 struct PStack *stlist;
951 struct sk_buff_head rq, sq; /* D-channel queues */
952 int cardnr;
953 char *dlog;
954 int debug;
955 union {
956 struct isac_chip isac;
957 struct hfcd_chip hfcd;
958 struct hfcpci_chip hfcpci;
959 struct hfcsx_chip hfcsx;
960 struct w6692_chip w6692;
961 struct amd7930_chip amd7930;
962 struct icc_chip icc;
963 } dc;
964 u_char *rcvbuf;
965 int rcvidx;
966 struct sk_buff *tx_skb;
967 int tx_cnt;
968 u_long event;
969 struct work_struct tqueue;
970 struct timer_list dbusytimer;
971#ifdef ERROR_STATISTIC
972 int err_crc;
973 int err_tx;
974 int err_rx;
975#endif
976};
977
978
979#define schedule_event(s, ev) do {test_and_set_bit(ev, &s->event);schedule_work(&s->tqueue); } while(0)
980
981#define MON0_RX 1
982#define MON1_RX 2
983#define MON0_TX 4
984#define MON1_TX 8
985
986
987#ifdef ISDN_CHIP_ISAC
988#undef ISDN_CHIP_ISAC
989#endif
990
991#ifdef CONFIG_HISAX_16_0
992#define CARD_TELES0 1
993#ifndef ISDN_CHIP_ISAC
994#define ISDN_CHIP_ISAC 1
995#endif
996#else
997#define CARD_TELES0 0
998#endif
999
1000#ifdef CONFIG_HISAX_16_3
1001#define CARD_TELES3 1
1002#ifndef ISDN_CHIP_ISAC
1003#define ISDN_CHIP_ISAC 1
1004#endif
1005#else
1006#define CARD_TELES3 0
1007#endif
1008
1009#ifdef CONFIG_HISAX_TELESPCI
1010#define CARD_TELESPCI 1
1011#ifndef ISDN_CHIP_ISAC
1012#define ISDN_CHIP_ISAC 1
1013#endif
1014#else
1015#define CARD_TELESPCI 0
1016#endif
1017
1018#ifdef CONFIG_HISAX_AVM_A1
1019#define CARD_AVM_A1 1
1020#ifndef ISDN_CHIP_ISAC
1021#define ISDN_CHIP_ISAC 1
1022#endif
1023#else
1024#define CARD_AVM_A1 0
1025#endif
1026
1027#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
1028#define CARD_AVM_A1_PCMCIA 1
1029#ifndef ISDN_CHIP_ISAC
1030#define ISDN_CHIP_ISAC 1
1031#endif
1032#else
1033#define CARD_AVM_A1_PCMCIA 0
1034#endif
1035
1036#ifdef CONFIG_HISAX_FRITZPCI
1037#define CARD_FRITZPCI 1
1038#ifndef ISDN_CHIP_ISAC
1039#define ISDN_CHIP_ISAC 1
1040#endif
1041#else
1042#define CARD_FRITZPCI 0
1043#endif
1044
1045#ifdef CONFIG_HISAX_ELSA
1046#define CARD_ELSA 1
1047#ifndef ISDN_CHIP_ISAC
1048#define ISDN_CHIP_ISAC 1
1049#endif
1050#else
1051#define CARD_ELSA 0
1052#endif
1053
1054#ifdef CONFIG_HISAX_IX1MICROR2
1055#define CARD_IX1MICROR2 1
1056#ifndef ISDN_CHIP_ISAC
1057#define ISDN_CHIP_ISAC 1
1058#endif
1059#else
1060#define CARD_IX1MICROR2 0
1061#endif
1062
1063#ifdef CONFIG_HISAX_DIEHLDIVA
1064#define CARD_DIEHLDIVA 1
1065#ifndef ISDN_CHIP_ISAC
1066#define ISDN_CHIP_ISAC 1
1067#endif
1068#else
1069#define CARD_DIEHLDIVA 0
1070#endif
1071
1072#ifdef CONFIG_HISAX_ASUSCOM
1073#define CARD_ASUSCOM 1
1074#ifndef ISDN_CHIP_ISAC
1075#define ISDN_CHIP_ISAC 1
1076#endif
1077#else
1078#define CARD_ASUSCOM 0
1079#endif
1080
1081#ifdef CONFIG_HISAX_TELEINT
1082#define CARD_TELEINT 1
1083#ifndef ISDN_CHIP_ISAC
1084#define ISDN_CHIP_ISAC 1
1085#endif
1086#else
1087#define CARD_TELEINT 0
1088#endif
1089
1090#ifdef CONFIG_HISAX_SEDLBAUER
1091#define CARD_SEDLBAUER 1
1092#ifndef ISDN_CHIP_ISAC
1093#define ISDN_CHIP_ISAC 1
1094#endif
1095#else
1096#define CARD_SEDLBAUER 0
1097#endif
1098
1099#ifdef CONFIG_HISAX_SPORTSTER
1100#define CARD_SPORTSTER 1
1101#ifndef ISDN_CHIP_ISAC
1102#define ISDN_CHIP_ISAC 1
1103#endif
1104#else
1105#define CARD_SPORTSTER 0
1106#endif
1107
1108#ifdef CONFIG_HISAX_MIC
1109#define CARD_MIC 1
1110#ifndef ISDN_CHIP_ISAC
1111#define ISDN_CHIP_ISAC 1
1112#endif
1113#else
1114#define CARD_MIC 0
1115#endif
1116
1117#ifdef CONFIG_HISAX_NETJET
1118#define CARD_NETJET_S 1
1119#ifndef ISDN_CHIP_ISAC
1120#define ISDN_CHIP_ISAC 1
1121#endif
1122#else
1123#define CARD_NETJET_S 0
1124#endif
1125
1126#ifdef CONFIG_HISAX_HFCS
1127#define CARD_HFCS 1
1128#else
1129#define CARD_HFCS 0
1130#endif
1131
1132#ifdef CONFIG_HISAX_HFC_PCI
1133#define CARD_HFC_PCI 1
1134#else
1135#define CARD_HFC_PCI 0
1136#endif
1137
1138#ifdef CONFIG_HISAX_HFC_SX
1139#define CARD_HFC_SX 1
1140#else
1141#define CARD_HFC_SX 0
1142#endif
1143
1144#ifdef CONFIG_HISAX_AMD7930
1145#define CARD_AMD7930 1
1146#else
1147#define CARD_AMD7930 0
1148#endif
1149
1150#ifdef CONFIG_HISAX_NICCY
1151#define CARD_NICCY 1
1152#ifndef ISDN_CHIP_ISAC
1153#define ISDN_CHIP_ISAC 1
1154#endif
1155#else
1156#define CARD_NICCY 0
1157#endif
1158
1159#ifdef CONFIG_HISAX_ISURF
1160#define CARD_ISURF 1
1161#ifndef ISDN_CHIP_ISAC
1162#define ISDN_CHIP_ISAC 1
1163#endif
1164#else
1165#define CARD_ISURF 0
1166#endif
1167
1168#ifdef CONFIG_HISAX_S0BOX
1169#define CARD_S0BOX 1
1170#ifndef ISDN_CHIP_ISAC
1171#define ISDN_CHIP_ISAC 1
1172#endif
1173#else
1174#define CARD_S0BOX 0
1175#endif
1176
1177#ifdef CONFIG_HISAX_HSTSAPHIR
1178#define CARD_HSTSAPHIR 1
1179#ifndef ISDN_CHIP_ISAC
1180#define ISDN_CHIP_ISAC 1
1181#endif
1182#else
1183#define CARD_HSTSAPHIR 0
1184#endif
1185
1186#ifdef CONFIG_HISAX_TESTEMU
1187#define CARD_TESTEMU 1
1188#define ISDN_CTYPE_TESTEMU 99
1189#undef ISDN_CTYPE_COUNT
1190#define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
1191#else
1192#define CARD_TESTEMU 0
1193#endif
1194
1195#ifdef CONFIG_HISAX_BKM_A4T
1196#define CARD_BKM_A4T 1
1197#ifndef ISDN_CHIP_ISAC
1198#define ISDN_CHIP_ISAC 1
1199#endif
1200#else
1201#define CARD_BKM_A4T 0
1202#endif
1203
1204#ifdef CONFIG_HISAX_SCT_QUADRO
1205#define CARD_SCT_QUADRO 1
1206#ifndef ISDN_CHIP_ISAC
1207#define ISDN_CHIP_ISAC 1
1208#endif
1209#else
1210#define CARD_SCT_QUADRO 0
1211#endif
1212
1213#ifdef CONFIG_HISAX_GAZEL
1214#define CARD_GAZEL 1
1215#ifndef ISDN_CHIP_ISAC
1216#define ISDN_CHIP_ISAC 1
1217#endif
1218#else
1219#define CARD_GAZEL 0
1220#endif
1221
1222#ifdef CONFIG_HISAX_W6692
1223#define CARD_W6692 1
1224#ifndef ISDN_CHIP_W6692
1225#define ISDN_CHIP_W6692 1
1226#endif
1227#else
1228#define CARD_W6692 0
1229#endif
1230
1231#ifdef CONFIG_HISAX_NETJET_U
1232#define CARD_NETJET_U 1
1233#ifndef ISDN_CHIP_ICC
1234#define ISDN_CHIP_ICC 1
1235#endif
1236#ifndef HISAX_UINTERFACE
1237#define HISAX_UINTERFACE 1
1238#endif
1239#else
1240#define CARD_NETJET_U 0
1241#endif
1242
1243#ifdef CONFIG_HISAX_ENTERNOW_PCI
1244#define CARD_FN_ENTERNOW_PCI 1
1245#endif
1246
1247#define TEI_PER_CARD 1
1248
1249/* L1 Debug */
1250#define L1_DEB_WARN 0x01
1251#define L1_DEB_INTSTAT 0x02
1252#define L1_DEB_ISAC 0x04
1253#define L1_DEB_ISAC_FIFO 0x08
1254#define L1_DEB_HSCX 0x10
1255#define L1_DEB_HSCX_FIFO 0x20
1256#define L1_DEB_LAPD 0x40
1257#define L1_DEB_IPAC 0x80
1258#define L1_DEB_RECEIVE_FRAME 0x100
1259#define L1_DEB_MONITOR 0x200
1260#define DEB_DLOG_HEX 0x400
1261#define DEB_DLOG_VERBOSE 0x800
1262
1263#define L2FRAME_DEBUG
1264
1265#ifdef L2FRAME_DEBUG
1266extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
1267#endif
1268
1269#include "hisax_cfg.h"
1270
1271void init_bcstate(struct IsdnCardState *cs, int bc);
1272
1273void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs);
1274unsigned int random_ri(void);
1275void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st);
1276void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
1277
1278void setstack_l1_B(struct PStack *st);
1279
1280void setstack_tei(struct PStack *st);
1281void setstack_manager(struct PStack *st);
1282
1283void setstack_isdnl2(struct PStack *st, char *debug_id);
1284void releasestack_isdnl2(struct PStack *st);
1285void setstack_transl2(struct PStack *st);
1286void releasestack_transl2(struct PStack *st);
1287void lli_writewakeup(struct PStack *st, int len);
1288
1289void setstack_l3dc(struct PStack *st, struct Channel *chanp);
1290void setstack_l3bc(struct PStack *st, struct Channel *chanp);
1291void releasestack_isdnl3(struct PStack *st);
1292
1293u_char *findie(u_char * p, int size, u_char ie, int wanted_set);
1294int getcallref(u_char * p);
1295int newcallref(void);
1296
1297int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount);
1298void FsmFree(struct Fsm *fsm);
1299int FsmEvent(struct FsmInst *fi, int event, void *arg);
1300void FsmChangeState(struct FsmInst *fi, int newstate);
1301void FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft);
1302int FsmAddTimer(struct FsmTimer *ft, int millisec, int event,
1303 void *arg, int where);
1304void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event,
1305 void *arg, int where);
1306void FsmDelTimer(struct FsmTimer *ft, int where);
1307int jiftime(char *s, long mark);
1308
1309int HiSax_command(isdn_ctrl * ic);
1310int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
1311void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
1312void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
1313void HiSax_reportcard(int cardnr, int sel);
1314int QuickHex(char *txt, u_char * p, int cnt);
1315void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
1316void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
1317void iecpy(u_char * dest, u_char * iestart, int ieoffset);
1318#ifdef ISDN_CHIP_ISAC
1319void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
1320#endif /* ISDN_CHIP_ISAC */
1321#endif /* __KERNEL__ */
1322
1323#define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
1324
1325int ll_run(struct IsdnCardState *cs, int addfeatures);
1326void ll_stop(struct IsdnCardState *cs);
1327int CallcNew(void);
1328void CallcFree(void);
1329int CallcNewChan(struct IsdnCardState *cs);
1330void CallcFreeChan(struct IsdnCardState *cs);
1331int Isdnl1New(void);
1332void Isdnl1Free(void);
1333int Isdnl2New(void);
1334void Isdnl2Free(void);
1335int Isdnl3New(void);
1336void Isdnl3Free(void);
1337void init_tei(struct IsdnCardState *cs, int protocol);
1338void release_tei(struct IsdnCardState *cs);
1339char *HiSax_getrev(const char *revision);
1340int TeiNew(void);
1341void TeiFree(void);
diff --git a/drivers/isdn/hisax/hisax_cfg.h b/drivers/isdn/hisax/hisax_cfg.h
new file mode 100644
index 00000000000..ca3fe6259bc
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_cfg.h
@@ -0,0 +1,64 @@
1/* $Id: hisax_cfg.h,v 1.1.2.1 2004/01/24 20:47:23 keil Exp $
2 * define of the basic HiSax configuration structures
3 * and pcmcia interface
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#define ISDN_CTYPE_16_0 1
11#define ISDN_CTYPE_8_0 2
12#define ISDN_CTYPE_16_3 3
13#define ISDN_CTYPE_PNP 4
14#define ISDN_CTYPE_A1 5
15#define ISDN_CTYPE_ELSA 6
16#define ISDN_CTYPE_ELSA_PNP 7
17#define ISDN_CTYPE_TELESPCMCIA 8
18#define ISDN_CTYPE_IX1MICROR2 9
19#define ISDN_CTYPE_ELSA_PCMCIA 10
20#define ISDN_CTYPE_DIEHLDIVA 11
21#define ISDN_CTYPE_ASUSCOM 12
22#define ISDN_CTYPE_TELEINT 13
23#define ISDN_CTYPE_TELES3C 14
24#define ISDN_CTYPE_SEDLBAUER 15
25#define ISDN_CTYPE_SPORTSTER 16
26#define ISDN_CTYPE_MIC 17
27#define ISDN_CTYPE_ELSA_PCI 18
28#define ISDN_CTYPE_COMPAQ_ISA 19
29#define ISDN_CTYPE_NETJET_S 20
30#define ISDN_CTYPE_TELESPCI 21
31#define ISDN_CTYPE_SEDLBAUER_PCMCIA 22
32#define ISDN_CTYPE_AMD7930 23
33#define ISDN_CTYPE_NICCY 24
34#define ISDN_CTYPE_S0BOX 25
35#define ISDN_CTYPE_A1_PCMCIA 26
36#define ISDN_CTYPE_FRITZPCI 27
37#define ISDN_CTYPE_SEDLBAUER_FAX 28
38#define ISDN_CTYPE_ISURF 29
39#define ISDN_CTYPE_ACERP10 30
40#define ISDN_CTYPE_HSTSAPHIR 31
41#define ISDN_CTYPE_BKM_A4T 32
42#define ISDN_CTYPE_SCT_QUADRO 33
43#define ISDN_CTYPE_GAZEL 34
44#define ISDN_CTYPE_HFC_PCI 35
45#define ISDN_CTYPE_W6692 36
46#define ISDN_CTYPE_HFC_SX 37
47#define ISDN_CTYPE_NETJET_U 38
48#define ISDN_CTYPE_HFC_SP_PCMCIA 39
49#define ISDN_CTYPE_DYNAMIC 40
50#define ISDN_CTYPE_ENTERNOW 41
51#define ISDN_CTYPE_COUNT 41
52
53typedef struct IsdnCardState IsdnCardState_t;
54typedef struct IsdnCard IsdnCard_t;
55
56struct IsdnCard {
57 int typ;
58 int protocol; /* EDSS1, 1TR6 or NI1 */
59 unsigned long para[4];
60 IsdnCardState_t *cs;
61};
62
63extern void HiSax_closecard(int);
64extern int hisax_init_pcmcia(void *, int *, IsdnCard_t *);
diff --git a/drivers/isdn/hisax/hisax_debug.h b/drivers/isdn/hisax/hisax_debug.h
new file mode 100644
index 00000000000..ba518a7a7fb
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_debug.h
@@ -0,0 +1,81 @@
1/*
2 * Common debugging macros for use with the hisax driver
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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 * How to use:
12 *
13 * Before including this file, you need to
14 * #define __debug_variable my_debug
15 * where my_debug is a variable in your code which
16 * determines the debug bitmask.
17 *
18 * If CONFIG_HISAX_DEBUG is not set, all macros evaluate to nothing
19 *
20 */
21
22#ifndef __HISAX_DEBUG_H__
23#define __HISAX_DEBUG_H__
24
25#include <linux/config.h>
26
27#ifdef CONFIG_HISAX_DEBUG
28
29#define DBG(level, format, arg...) do { \
30if (level & __debug_variable) \
31printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
32} while (0)
33
34#define DBG_PACKET(level,data,count) \
35 if (level & __debug_variable) dump_packet(__FUNCTION__,data,count)
36
37#define DBG_SKB(level,skb) \
38 if ((level & __debug_variable) && skb) dump_packet(__FUNCTION__,skb->data,skb->len)
39
40
41static void __attribute__((unused))
42dump_packet(const char *name,const u_char *data,int pkt_len)
43{
44#define DUMP_HDR_SIZE 20
45#define DUMP_TLR_SIZE 8
46 if (pkt_len) {
47 int i,len1,len2;
48
49 printk(KERN_DEBUG "%s: length=%d,data=",name,pkt_len);
50
51 if (pkt_len > DUMP_HDR_SIZE+ DUMP_TLR_SIZE) {
52 len1 = DUMP_HDR_SIZE;
53 len2 = DUMP_TLR_SIZE;
54 } else {
55 len1 = pkt_len > DUMP_HDR_SIZE ? DUMP_HDR_SIZE : pkt_len;
56 len2 = 0;
57 }
58 for (i = 0; i < len1; ++i) {
59 printk ("%.2x", data[i]);
60 }
61 if (len2) {
62 printk ("..");
63 for (i = pkt_len-DUMP_TLR_SIZE; i < pkt_len; ++i) {
64 printk ("%.2x", data[i]);
65 }
66 }
67 printk ("\n");
68 }
69#undef DUMP_HDR_SIZE
70#undef DUMP_TLR_SIZE
71}
72
73#else
74
75#define DBG(level, format, arg...) do {} while (0)
76#define DBG_PACKET(level,data,count) do {} while (0)
77#define DBG_SKB(level,skb) do {} while (0)
78
79#endif
80
81#endif
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
new file mode 100644
index 00000000000..b4d795d4015
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -0,0 +1,1028 @@
1/*
2 * Driver for AVM Fritz!PCI, Fritz!PCI v2, Fritz!PnP ISDN cards
3 *
4 * Author Kai Germaschewski
5 * Copyright 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
6 * 2001 by Karsten Keil <keil@isdn4linux.de>
7 *
8 * based upon Karsten Keil's original avm_pci.c driver
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
14 * SoHaNet Technology GmbH, Berlin
15 * for supporting the development of this driver
16 */
17
18
19/* TODO:
20 *
21 * o POWER PC
22 * o clean up debugging
23 * o tx_skb at PH_DEACTIVATE time
24 */
25
26#include <linux/version.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/pci.h>
30#include <linux/isapnp.h>
31#include <linux/kmod.h>
32#include <linux/slab.h>
33#include <linux/skbuff.h>
34#include <linux/netdevice.h>
35#include <linux/delay.h>
36
37#include <asm/io.h>
38
39#include "hisax_fcpcipnp.h"
40
41// debugging cruft
42#define __debug_variable debug
43#include "hisax_debug.h"
44
45#ifdef CONFIG_HISAX_DEBUG
46static int debug = 0;
47/* static int hdlcfifosize = 32; */
48module_param(debug, int, 0);
49/* module_param(hdlcfifosize, int, 0); */
50#endif
51
52MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
53MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
54
55static struct pci_device_id fcpci_ids[] = {
56 { .vendor = PCI_VENDOR_ID_AVM,
57 .device = PCI_DEVICE_ID_AVM_A1,
58 .subvendor = PCI_ANY_ID,
59 .subdevice = PCI_ANY_ID,
60 .driver_data = (unsigned long) "Fritz!Card PCI",
61 },
62 { .vendor = PCI_VENDOR_ID_AVM,
63 .device = PCI_DEVICE_ID_AVM_A1_V2,
64 .subvendor = PCI_ANY_ID,
65 .subdevice = PCI_ANY_ID,
66 .driver_data = (unsigned long) "Fritz!Card PCI v2" },
67 {}
68};
69
70MODULE_DEVICE_TABLE(pci, fcpci_ids);
71
72#ifdef __ISAPNP__
73static struct pnp_device_id fcpnp_ids[] __devinitdata = {
74 {
75 .id = "AVM0900",
76 .driver_data = (unsigned long) "Fritz!Card PnP",
77 },
78};
79
80MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
81#endif
82
83static int protocol = 2; /* EURO-ISDN Default */
84module_param(protocol, int, 0);
85MODULE_LICENSE("GPL");
86
87// ----------------------------------------------------------------------
88
89#define AVM_INDEX 0x04
90#define AVM_DATA 0x10
91
92#define AVM_IDX_HDLC_1 0x00
93#define AVM_IDX_HDLC_2 0x01
94#define AVM_IDX_ISAC_FIFO 0x02
95#define AVM_IDX_ISAC_REG_LOW 0x04
96#define AVM_IDX_ISAC_REG_HIGH 0x06
97
98#define AVM_STATUS0 0x02
99
100#define AVM_STATUS0_IRQ_ISAC 0x01
101#define AVM_STATUS0_IRQ_HDLC 0x02
102#define AVM_STATUS0_IRQ_TIMER 0x04
103#define AVM_STATUS0_IRQ_MASK 0x07
104
105#define AVM_STATUS0_RESET 0x01
106#define AVM_STATUS0_DIS_TIMER 0x02
107#define AVM_STATUS0_RES_TIMER 0x04
108#define AVM_STATUS0_ENA_IRQ 0x08
109#define AVM_STATUS0_TESTBIT 0x10
110
111#define AVM_STATUS1 0x03
112#define AVM_STATUS1_ENA_IOM 0x80
113
114#define HDLC_FIFO 0x0
115#define HDLC_STATUS 0x4
116#define HDLC_CTRL 0x4
117
118#define HDLC_MODE_ITF_FLG 0x01
119#define HDLC_MODE_TRANS 0x02
120#define HDLC_MODE_CCR_7 0x04
121#define HDLC_MODE_CCR_16 0x08
122#define HDLC_MODE_TESTLOOP 0x80
123
124#define HDLC_INT_XPR 0x80
125#define HDLC_INT_XDU 0x40
126#define HDLC_INT_RPR 0x20
127#define HDLC_INT_MASK 0xE0
128
129#define HDLC_STAT_RME 0x01
130#define HDLC_STAT_RDO 0x10
131#define HDLC_STAT_CRCVFRRAB 0x0E
132#define HDLC_STAT_CRCVFR 0x06
133#define HDLC_STAT_RML_MASK 0xff00
134
135#define HDLC_CMD_XRS 0x80
136#define HDLC_CMD_XME 0x01
137#define HDLC_CMD_RRS 0x20
138#define HDLC_CMD_XML_MASK 0xff00
139
140#define AVM_HDLC_FIFO_1 0x10
141#define AVM_HDLC_FIFO_2 0x18
142
143#define AVM_HDLC_STATUS_1 0x14
144#define AVM_HDLC_STATUS_2 0x1c
145
146#define AVM_ISACSX_INDEX 0x04
147#define AVM_ISACSX_DATA 0x08
148
149// ----------------------------------------------------------------------
150// Fritz!PCI
151
152static unsigned char fcpci_read_isac(struct isac *isac, unsigned char offset)
153{
154 struct fritz_adapter *adapter = isac->priv;
155 unsigned char idx = (offset > 0x2f) ?
156 AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
157 unsigned char val;
158 unsigned long flags;
159
160 spin_lock_irqsave(&adapter->hw_lock, flags);
161 outb(idx, adapter->io + AVM_INDEX);
162 val = inb(adapter->io + AVM_DATA + (offset & 0xf));
163 spin_unlock_irqrestore(&adapter->hw_lock, flags);
164 DBG(0x1000, " port %#x, value %#x",
165 offset, val);
166 return val;
167}
168
169static void fcpci_write_isac(struct isac *isac, unsigned char offset,
170 unsigned char value)
171{
172 struct fritz_adapter *adapter = isac->priv;
173 unsigned char idx = (offset > 0x2f) ?
174 AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
175 unsigned long flags;
176
177 DBG(0x1000, " port %#x, value %#x",
178 offset, value);
179 spin_lock_irqsave(&adapter->hw_lock, flags);
180 outb(idx, adapter->io + AVM_INDEX);
181 outb(value, adapter->io + AVM_DATA + (offset & 0xf));
182 spin_unlock_irqrestore(&adapter->hw_lock, flags);
183}
184
185static void fcpci_read_isac_fifo(struct isac *isac, unsigned char * data,
186 int size)
187{
188 struct fritz_adapter *adapter = isac->priv;
189 unsigned long flags;
190
191 spin_lock_irqsave(&adapter->hw_lock, flags);
192 outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
193 insb(adapter->io + AVM_DATA, data, size);
194 spin_unlock_irqrestore(&adapter->hw_lock, flags);
195}
196
197static void fcpci_write_isac_fifo(struct isac *isac, unsigned char * data,
198 int size)
199{
200 struct fritz_adapter *adapter = isac->priv;
201 unsigned long flags;
202
203 spin_lock_irqsave(&adapter->hw_lock, flags);
204 outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
205 outsb(adapter->io + AVM_DATA, data, size);
206 spin_unlock_irqrestore(&adapter->hw_lock, flags);
207}
208
209static u32 fcpci_read_hdlc_status(struct fritz_adapter *adapter, int nr)
210{
211 u32 val;
212 int idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
213 unsigned long flags;
214
215 spin_lock_irqsave(&adapter->hw_lock, flags);
216 outl(idx, adapter->io + AVM_INDEX);
217 val = inl(adapter->io + AVM_DATA + HDLC_STATUS);
218 spin_unlock_irqrestore(&adapter->hw_lock, flags);
219 return val;
220}
221
222static void __fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
223{
224 struct fritz_adapter *adapter = bcs->adapter;
225 int idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
226
227 DBG(0x40, "hdlc %c wr%x ctrl %x",
228 'A' + bcs->channel, which, bcs->ctrl.ctrl);
229
230 outl(idx, adapter->io + AVM_INDEX);
231 outl(bcs->ctrl.ctrl, adapter->io + AVM_DATA + HDLC_CTRL);
232}
233
234static void fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
235{
236 struct fritz_adapter *adapter = bcs->adapter;
237 unsigned long flags;
238
239 spin_lock_irqsave(&adapter->hw_lock, flags);
240 __fcpci_write_ctrl(bcs, which);
241 spin_unlock_irqrestore(&adapter->hw_lock, flags);
242}
243
244// ----------------------------------------------------------------------
245// Fritz!PCI v2
246
247static unsigned char fcpci2_read_isac(struct isac *isac, unsigned char offset)
248{
249 struct fritz_adapter *adapter = isac->priv;
250 unsigned char val;
251 unsigned long flags;
252
253 spin_lock_irqsave(&adapter->hw_lock, flags);
254 outl(offset, adapter->io + AVM_ISACSX_INDEX);
255 val = inl(adapter->io + AVM_ISACSX_DATA);
256 spin_unlock_irqrestore(&adapter->hw_lock, flags);
257 DBG(0x1000, " port %#x, value %#x",
258 offset, val);
259
260 return val;
261}
262
263static void fcpci2_write_isac(struct isac *isac, unsigned char offset,
264 unsigned char value)
265{
266 struct fritz_adapter *adapter = isac->priv;
267 unsigned long flags;
268
269 DBG(0x1000, " port %#x, value %#x",
270 offset, value);
271 spin_lock_irqsave(&adapter->hw_lock, flags);
272 outl(offset, adapter->io + AVM_ISACSX_INDEX);
273 outl(value, adapter->io + AVM_ISACSX_DATA);
274 spin_unlock_irqrestore(&adapter->hw_lock, flags);
275}
276
277static void fcpci2_read_isac_fifo(struct isac *isac, unsigned char * data,
278 int size)
279{
280 struct fritz_adapter *adapter = isac->priv;
281 int i;
282 unsigned long flags;
283
284 spin_lock_irqsave(&adapter->hw_lock, flags);
285 outl(0, adapter->io + AVM_ISACSX_INDEX);
286 for (i = 0; i < size; i++)
287 data[i] = inl(adapter->io + AVM_ISACSX_DATA);
288 spin_unlock_irqrestore(&adapter->hw_lock, flags);
289}
290
291static void fcpci2_write_isac_fifo(struct isac *isac, unsigned char * data,
292 int size)
293{
294 struct fritz_adapter *adapter = isac->priv;
295 int i;
296 unsigned long flags;
297
298 spin_lock_irqsave(&adapter->hw_lock, flags);
299 outl(0, adapter->io + AVM_ISACSX_INDEX);
300 for (i = 0; i < size; i++)
301 outl(data[i], adapter->io + AVM_ISACSX_DATA);
302 spin_unlock_irqrestore(&adapter->hw_lock, flags);
303}
304
305static u32 fcpci2_read_hdlc_status(struct fritz_adapter *adapter, int nr)
306{
307 int offset = nr ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
308
309 return inl(adapter->io + offset);
310}
311
312static void fcpci2_write_ctrl(struct fritz_bcs *bcs, int which)
313{
314 struct fritz_adapter *adapter = bcs->adapter;
315 int offset = bcs->channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
316
317 DBG(0x40, "hdlc %c wr%x ctrl %x",
318 'A' + bcs->channel, which, bcs->ctrl.ctrl);
319
320 outl(bcs->ctrl.ctrl, adapter->io + offset);
321}
322
323// ----------------------------------------------------------------------
324// Fritz!PnP (ISAC access as for Fritz!PCI)
325
326static u32 fcpnp_read_hdlc_status(struct fritz_adapter *adapter, int nr)
327{
328 unsigned char idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
329 u32 val;
330 unsigned long flags;
331
332 spin_lock_irqsave(&adapter->hw_lock, flags);
333 outb(idx, adapter->io + AVM_INDEX);
334 val = inb(adapter->io + AVM_DATA + HDLC_STATUS);
335 if (val & HDLC_INT_RPR)
336 val |= inb(adapter->io + AVM_DATA + HDLC_STATUS + 1) << 8;
337 spin_unlock_irqrestore(&adapter->hw_lock, flags);
338 return val;
339}
340
341static void __fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
342{
343 struct fritz_adapter *adapter = bcs->adapter;
344 unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
345
346 DBG(0x40, "hdlc %c wr%x ctrl %x",
347 'A' + bcs->channel, which, bcs->ctrl.ctrl);
348
349 outb(idx, adapter->io + AVM_INDEX);
350 if (which & 4)
351 outb(bcs->ctrl.sr.mode,
352 adapter->io + AVM_DATA + HDLC_STATUS + 2);
353 if (which & 2)
354 outb(bcs->ctrl.sr.xml,
355 adapter->io + AVM_DATA + HDLC_STATUS + 1);
356 if (which & 1)
357 outb(bcs->ctrl.sr.cmd,
358 adapter->io + AVM_DATA + HDLC_STATUS + 0);
359}
360
361static void fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
362{
363 struct fritz_adapter *adapter = bcs->adapter;
364 unsigned long flags;
365
366 spin_lock_irqsave(&adapter->hw_lock, flags);
367 __fcpnp_write_ctrl(bcs, which);
368 spin_unlock_irqrestore(&adapter->hw_lock, flags);
369}
370
371// ----------------------------------------------------------------------
372
373static inline void B_L1L2(struct fritz_bcs *bcs, int pr, void *arg)
374{
375 struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
376
377 DBG(2, "pr %#x", pr);
378 ifc->l1l2(ifc, pr, arg);
379}
380
381static void hdlc_fill_fifo(struct fritz_bcs *bcs)
382{
383 struct fritz_adapter *adapter = bcs->adapter;
384 struct sk_buff *skb = bcs->tx_skb;
385 int count;
386 unsigned long flags;
387 unsigned char *p;
388
389 DBG(0x40, "hdlc_fill_fifo");
390
391 if (skb->len == 0)
392 BUG();
393
394 bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
395 if (bcs->tx_skb->len > bcs->fifo_size) {
396 count = bcs->fifo_size;
397 } else {
398 count = bcs->tx_skb->len;
399 if (bcs->mode != L1_MODE_TRANS)
400 bcs->ctrl.sr.cmd |= HDLC_CMD_XME;
401 }
402 DBG(0x40, "hdlc_fill_fifo %d/%d", count, bcs->tx_skb->len);
403 p = bcs->tx_skb->data;
404 skb_pull(bcs->tx_skb, count);
405 bcs->tx_cnt += count;
406 bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count);
407
408 switch (adapter->type) {
409 case AVM_FRITZ_PCI:
410 spin_lock_irqsave(&adapter->hw_lock, flags);
411 // sets the correct AVM_INDEX, too
412 __fcpci_write_ctrl(bcs, 3);
413 outsl(adapter->io + AVM_DATA + HDLC_FIFO,
414 p, (count + 3) / 4);
415 spin_unlock_irqrestore(&adapter->hw_lock, flags);
416 break;
417 case AVM_FRITZ_PCIV2:
418 fcpci2_write_ctrl(bcs, 3);
419 outsl(adapter->io +
420 (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
421 p, (count + 3) / 4);
422 break;
423 case AVM_FRITZ_PNP:
424 spin_lock_irqsave(&adapter->hw_lock, flags);
425 // sets the correct AVM_INDEX, too
426 __fcpnp_write_ctrl(bcs, 3);
427 outsb(adapter->io + AVM_DATA, p, count);
428 spin_unlock_irqrestore(&adapter->hw_lock, flags);
429 break;
430 }
431}
432
433static inline void hdlc_empty_fifo(struct fritz_bcs *bcs, int count)
434{
435 struct fritz_adapter *adapter = bcs->adapter;
436 unsigned char *p;
437 unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
438
439 DBG(0x10, "hdlc_empty_fifo %d", count);
440 if (bcs->rcvidx + count > HSCX_BUFMAX) {
441 DBG(0x10, "hdlc_empty_fifo: incoming packet too large");
442 return;
443 }
444 p = bcs->rcvbuf + bcs->rcvidx;
445 bcs->rcvidx += count;
446 switch (adapter->type) {
447 case AVM_FRITZ_PCI:
448 spin_lock(&adapter->hw_lock);
449 outl(idx, adapter->io + AVM_INDEX);
450 insl(adapter->io + AVM_DATA + HDLC_FIFO,
451 p, (count + 3) / 4);
452 spin_unlock(&adapter->hw_lock);
453 break;
454 case AVM_FRITZ_PCIV2:
455 insl(adapter->io +
456 (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
457 p, (count + 3) / 4);
458 break;
459 case AVM_FRITZ_PNP:
460 spin_lock(&adapter->hw_lock);
461 outb(idx, adapter->io + AVM_INDEX);
462 insb(adapter->io + AVM_DATA, p, count);
463 spin_unlock(&adapter->hw_lock);
464 break;
465 }
466}
467
468static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat)
469{
470 struct fritz_adapter *adapter = bcs->adapter;
471 struct sk_buff *skb;
472 int len;
473
474 if (stat & HDLC_STAT_RDO) {
475 DBG(0x10, "RDO");
476 bcs->ctrl.sr.xml = 0;
477 bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;
478 adapter->write_ctrl(bcs, 1);
479 bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
480 adapter->write_ctrl(bcs, 1);
481 bcs->rcvidx = 0;
482 return;
483 }
484
485 len = (stat & HDLC_STAT_RML_MASK) >> 8;
486 if (len == 0)
487 len = bcs->fifo_size;
488
489 hdlc_empty_fifo(bcs, len);
490
491 if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
492 if (((stat & HDLC_STAT_CRCVFRRAB)== HDLC_STAT_CRCVFR) ||
493 (bcs->mode == L1_MODE_TRANS)) {
494 skb = dev_alloc_skb(bcs->rcvidx);
495 if (!skb) {
496 printk(KERN_WARNING "HDLC: receive out of memory\n");
497 } else {
498 memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,
499 bcs->rcvidx);
500 DBG_SKB(1, skb);
501 B_L1L2(bcs, PH_DATA | INDICATION, skb);
502 }
503 bcs->rcvidx = 0;
504 } else {
505 DBG(0x10, "ch%d invalid frame %#x",
506 bcs->channel, stat);
507 bcs->rcvidx = 0;
508 }
509 }
510}
511
512static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
513{
514 struct fritz_adapter *adapter = bcs->adapter;
515
516
517 /* Here we lost an TX interrupt, so
518 * restart transmitting the whole frame.
519 */
520 bcs->ctrl.sr.xml = 0;
521 bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
522 adapter->write_ctrl(bcs, 1);
523 bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
524
525 if (!bcs->tx_skb) {
526 DBG(0x10, "XDU without skb");
527 adapter->write_ctrl(bcs, 1);
528 return;
529 }
530 /* only hdlc restarts the frame, transparent mode must continue */
531 if (bcs->mode == L1_MODE_HDLC) {
532 skb_push(bcs->tx_skb, bcs->tx_cnt);
533 bcs->tx_cnt = 0;
534 }
535}
536
537static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
538{
539 struct sk_buff *skb;
540
541 skb = bcs->tx_skb;
542 if (!skb)
543 return;
544
545 if (skb->len) {
546 hdlc_fill_fifo(bcs);
547 return;
548 }
549 bcs->tx_cnt = 0;
550 bcs->tx_skb = NULL;
551 B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
552 dev_kfree_skb_irq(skb);
553}
554
555static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
556{
557 DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
558 if (stat & HDLC_INT_RPR) {
559 DBG(0x10, "RPR");
560 hdlc_rpr_irq(bcs, stat);
561 }
562 if (stat & HDLC_INT_XDU) {
563 DBG(0x10, "XDU");
564 hdlc_xdu_irq(bcs);
565 hdlc_xpr_irq(bcs);
566 return;
567 }
568 if (stat & HDLC_INT_XPR) {
569 DBG(0x10, "XPR");
570 hdlc_xpr_irq(bcs);
571 }
572}
573
574static inline void hdlc_irq(struct fritz_adapter *adapter)
575{
576 int nr;
577 u32 stat;
578
579 for (nr = 0; nr < 2; nr++) {
580 stat = adapter->read_hdlc_status(adapter, nr);
581 DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
582 if (stat & HDLC_INT_MASK)
583 hdlc_irq_one(&adapter->bcs[nr], stat);
584 }
585}
586
587static void modehdlc(struct fritz_bcs *bcs, int mode)
588{
589 struct fritz_adapter *adapter = bcs->adapter;
590
591 DBG(0x40, "hdlc %c mode %d --> %d",
592 'A' + bcs->channel, bcs->mode, mode);
593
594 if (bcs->mode == mode)
595 return;
596
597 bcs->fifo_size = 32;
598 bcs->ctrl.ctrl = 0;
599 bcs->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
600 switch (mode) {
601 case L1_MODE_NULL:
602 bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
603 adapter->write_ctrl(bcs, 5);
604 break;
605 case L1_MODE_TRANS:
606 case L1_MODE_HDLC:
607 bcs->rcvidx = 0;
608 bcs->tx_cnt = 0;
609 bcs->tx_skb = NULL;
610 if (mode == L1_MODE_TRANS) {
611 bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
612 } else {
613 bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
614 }
615 adapter->write_ctrl(bcs, 5);
616 bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
617 adapter->write_ctrl(bcs, 1);
618 bcs->ctrl.sr.cmd = 0;
619 break;
620 }
621 bcs->mode = mode;
622}
623
624static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
625{
626 struct fritz_bcs *bcs = ifc->priv;
627 struct sk_buff *skb = arg;
628 int mode;
629
630 DBG(0x10, "pr %#x", pr);
631
632 switch (pr) {
633 case PH_DATA | REQUEST:
634 if (bcs->tx_skb)
635 BUG();
636
637 bcs->tx_skb = skb;
638 DBG_SKB(1, skb);
639 hdlc_fill_fifo(bcs);
640 break;
641 case PH_ACTIVATE | REQUEST:
642 mode = (int) arg;
643 DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
644 modehdlc(bcs, mode);
645 B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
646 break;
647 case PH_DEACTIVATE | REQUEST:
648 DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
649 modehdlc(bcs, L1_MODE_NULL);
650 B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
651 break;
652 }
653}
654
655// ----------------------------------------------------------------------
656
657static irqreturn_t
658fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
659{
660 struct fritz_adapter *adapter = dev;
661 unsigned char val;
662
663 val = inb(adapter->io + AVM_STATUS0);
664 if (!(val & AVM_STATUS0_IRQ_MASK))
665 /* hopefully a shared IRQ reqest */
666 return IRQ_NONE;
667 DBG(2, "STATUS0 %#x", val);
668 if (val & AVM_STATUS0_IRQ_ISAC)
669 isacsx_irq(&adapter->isac);
670 if (val & AVM_STATUS0_IRQ_HDLC)
671 hdlc_irq(adapter);
672 if (val & AVM_STATUS0_IRQ_ISAC)
673 isacsx_irq(&adapter->isac);
674 return IRQ_HANDLED;
675}
676
677static irqreturn_t
678fcpci_irq(int intno, void *dev, struct pt_regs *regs)
679{
680 struct fritz_adapter *adapter = dev;
681 unsigned char sval;
682
683 sval = inb(adapter->io + 2);
684 if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
685 /* possibly a shared IRQ reqest */
686 return IRQ_NONE;
687 DBG(2, "sval %#x", sval);
688 if (!(sval & AVM_STATUS0_IRQ_ISAC))
689 isac_irq(&adapter->isac);
690
691 if (!(sval & AVM_STATUS0_IRQ_HDLC))
692 hdlc_irq(adapter);
693 return IRQ_HANDLED;
694}
695
696// ----------------------------------------------------------------------
697
698static inline void fcpci2_init(struct fritz_adapter *adapter)
699{
700 outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);
701 outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
702
703}
704
705static inline void fcpci_init(struct fritz_adapter *adapter)
706{
707 outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
708 AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
709
710 outb(AVM_STATUS1_ENA_IOM | adapter->irq,
711 adapter->io + AVM_STATUS1);
712 mdelay(10);
713}
714
715// ----------------------------------------------------------------------
716
717static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
718{
719 u32 val = 0;
720 int retval;
721
722 DBG(1,"");
723
724 isac_init(&adapter->isac); // FIXME is this okay now
725
726 retval = -EBUSY;
727 if (!request_region(adapter->io, 32, "fcpcipnp"))
728 goto err;
729
730 switch (adapter->type) {
731 case AVM_FRITZ_PCIV2:
732 retval = request_irq(adapter->irq, fcpci2_irq, SA_SHIRQ,
733 "fcpcipnp", adapter);
734 break;
735 case AVM_FRITZ_PCI:
736 retval = request_irq(adapter->irq, fcpci_irq, SA_SHIRQ,
737 "fcpcipnp", adapter);
738 break;
739 case AVM_FRITZ_PNP:
740 retval = request_irq(adapter->irq, fcpci_irq, 0,
741 "fcpcipnp", adapter);
742 break;
743 }
744 if (retval)
745 goto err_region;
746
747 switch (adapter->type) {
748 case AVM_FRITZ_PCIV2:
749 case AVM_FRITZ_PCI:
750 val = inl(adapter->io);
751 break;
752 case AVM_FRITZ_PNP:
753 val = inb(adapter->io);
754 val |= inb(adapter->io + 1) << 8;
755 break;
756 }
757
758 DBG(1, "stat %#x Class %X Rev %d",
759 val, val & 0xff, (val>>8) & 0xff);
760
761 spin_lock_init(&adapter->hw_lock);
762 adapter->isac.priv = adapter;
763 switch (adapter->type) {
764 case AVM_FRITZ_PCIV2:
765 adapter->isac.read_isac = &fcpci2_read_isac;
766 adapter->isac.write_isac = &fcpci2_write_isac;
767 adapter->isac.read_isac_fifo = &fcpci2_read_isac_fifo;
768 adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;
769
770 adapter->read_hdlc_status = &fcpci2_read_hdlc_status;
771 adapter->write_ctrl = &fcpci2_write_ctrl;
772 break;
773 case AVM_FRITZ_PCI:
774 adapter->isac.read_isac = &fcpci_read_isac;
775 adapter->isac.write_isac = &fcpci_write_isac;
776 adapter->isac.read_isac_fifo = &fcpci_read_isac_fifo;
777 adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
778
779 adapter->read_hdlc_status = &fcpci_read_hdlc_status;
780 adapter->write_ctrl = &fcpci_write_ctrl;
781 break;
782 case AVM_FRITZ_PNP:
783 adapter->isac.read_isac = &fcpci_read_isac;
784 adapter->isac.write_isac = &fcpci_write_isac;
785 adapter->isac.read_isac_fifo = &fcpci_read_isac_fifo;
786 adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
787
788 adapter->read_hdlc_status = &fcpnp_read_hdlc_status;
789 adapter->write_ctrl = &fcpnp_write_ctrl;
790 break;
791 }
792
793 // Reset
794 outb(0, adapter->io + AVM_STATUS0);
795 mdelay(10);
796 outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
797 mdelay(10);
798 outb(0, adapter->io + AVM_STATUS0);
799 mdelay(10);
800
801 switch (adapter->type) {
802 case AVM_FRITZ_PCIV2:
803 fcpci2_init(adapter);
804 isacsx_setup(&adapter->isac);
805 break;
806 case AVM_FRITZ_PCI:
807 case AVM_FRITZ_PNP:
808 fcpci_init(adapter);
809 isac_setup(&adapter->isac);
810 break;
811 }
812 val = adapter->read_hdlc_status(adapter, 0);
813 DBG(0x20, "HDLC A STA %x", val);
814 val = adapter->read_hdlc_status(adapter, 1);
815 DBG(0x20, "HDLC B STA %x", val);
816
817 adapter->bcs[0].mode = -1;
818 adapter->bcs[1].mode = -1;
819 modehdlc(&adapter->bcs[0], L1_MODE_NULL);
820 modehdlc(&adapter->bcs[1], L1_MODE_NULL);
821
822 return 0;
823
824 err_region:
825 release_region(adapter->io, 32);
826 err:
827 return retval;
828}
829
830static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
831{
832 DBG(1,"");
833
834 outb(0, adapter->io + AVM_STATUS0);
835 free_irq(adapter->irq, adapter);
836 release_region(adapter->io, 32);
837}
838
839// ----------------------------------------------------------------------
840
841static struct fritz_adapter * __devinit
842new_adapter(void)
843{
844 struct fritz_adapter *adapter;
845 struct hisax_b_if *b_if[2];
846 int i;
847
848 adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
849 if (!adapter)
850 return NULL;
851
852 memset(adapter, 0, sizeof(struct fritz_adapter));
853
854 adapter->isac.hisax_d_if.owner = THIS_MODULE;
855 adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
856 adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
857
858 for (i = 0; i < 2; i++) {
859 adapter->bcs[i].adapter = adapter;
860 adapter->bcs[i].channel = i;
861 adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
862 adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
863 }
864
865 for (i = 0; i < 2; i++)
866 b_if[i] = &adapter->bcs[i].b_if;
867
868 hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp", protocol);
869
870 return adapter;
871}
872
873static void delete_adapter(struct fritz_adapter *adapter)
874{
875 hisax_unregister(&adapter->isac.hisax_d_if);
876 kfree(adapter);
877}
878
879static int __devinit fcpci_probe(struct pci_dev *pdev,
880 const struct pci_device_id *ent)
881{
882 struct fritz_adapter *adapter;
883 int retval;
884
885 retval = -ENOMEM;
886 adapter = new_adapter();
887 if (!adapter)
888 goto err;
889
890 pci_set_drvdata(pdev, adapter);
891
892 if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
893 adapter->type = AVM_FRITZ_PCIV2;
894 else
895 adapter->type = AVM_FRITZ_PCI;
896
897 retval = pci_enable_device(pdev);
898 if (retval)
899 goto err_free;
900
901 adapter->io = pci_resource_start(pdev, 1);
902 adapter->irq = pdev->irq;
903
904 printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
905 (char *) ent->driver_data, pci_name(pdev));
906
907 retval = fcpcipnp_setup(adapter);
908 if (retval)
909 goto err_free;
910
911 return 0;
912
913 err_free:
914 delete_adapter(adapter);
915 err:
916 return retval;
917}
918
919#ifdef __ISAPNP__
920static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
921{
922 struct fritz_adapter *adapter;
923 int retval;
924
925 if (!pdev)
926 return(-ENODEV);
927
928 retval = -ENOMEM;
929 adapter = new_adapter();
930 if (!adapter)
931 goto err;
932
933 pnp_set_drvdata(pdev, adapter);
934
935 adapter->type = AVM_FRITZ_PNP;
936
937 pnp_disable_dev(pdev);
938 retval = pnp_activate_dev(pdev);
939 if (retval < 0) {
940 printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
941 (char *)dev_id->driver_data, retval);
942 goto err_free;
943 }
944 adapter->io = pnp_port_start(pdev, 0);
945 adapter->irq = pnp_irq(pdev, 0);
946
947 printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
948 (char *) dev_id->driver_data, adapter->io, adapter->irq);
949
950 retval = fcpcipnp_setup(adapter);
951 if (retval)
952 goto err_free;
953
954 return 0;
955
956 err_free:
957 delete_adapter(adapter);
958 err:
959 return retval;
960}
961
962static void __devexit fcpnp_remove(struct pnp_dev *pdev)
963{
964 struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
965
966 if (adapter) {
967 fcpcipnp_release(adapter);
968 delete_adapter(adapter);
969 }
970 pnp_disable_dev(pdev);
971}
972
973static struct pnp_driver fcpnp_driver = {
974 .name = "fcpnp",
975 .probe = fcpnp_probe,
976 .remove = __devexit_p(fcpnp_remove),
977 .id_table = fcpnp_ids,
978};
979#endif
980
981static void __devexit fcpci_remove(struct pci_dev *pdev)
982{
983 struct fritz_adapter *adapter = pci_get_drvdata(pdev);
984
985 fcpcipnp_release(adapter);
986 pci_disable_device(pdev);
987 delete_adapter(adapter);
988}
989
990static struct pci_driver fcpci_driver = {
991 .name = "fcpci",
992 .probe = fcpci_probe,
993 .remove = __devexit_p(fcpci_remove),
994 .id_table = fcpci_ids,
995};
996
997static int __init hisax_fcpcipnp_init(void)
998{
999 int retval;
1000
1001 printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
1002
1003 retval = pci_register_driver(&fcpci_driver);
1004 if (retval)
1005 goto out;
1006#ifdef __ISAPNP__
1007 retval = pnp_register_driver(&fcpnp_driver);
1008 if (retval < 0)
1009 goto out_unregister_pci;
1010#endif
1011 return 0;
1012
1013 out_unregister_pci:
1014 pci_unregister_driver(&fcpci_driver);
1015 out:
1016 return retval;
1017}
1018
1019static void __exit hisax_fcpcipnp_exit(void)
1020{
1021#ifdef __ISAPNP__
1022 pnp_unregister_driver(&fcpnp_driver);
1023#endif
1024 pci_unregister_driver(&fcpci_driver);
1025}
1026
1027module_init(hisax_fcpcipnp_init);
1028module_exit(hisax_fcpcipnp_exit);
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.h b/drivers/isdn/hisax/hisax_fcpcipnp.h
new file mode 100644
index 00000000000..bd8a22e4d6a
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.h
@@ -0,0 +1,58 @@
1#include "hisax_if.h"
2#include "hisax_isac.h"
3#include <linux/pci.h>
4
5#define HSCX_BUFMAX 4096
6
7enum {
8 AVM_FRITZ_PCI,
9 AVM_FRITZ_PNP,
10 AVM_FRITZ_PCIV2,
11};
12
13struct hdlc_stat_reg {
14#ifdef __BIG_ENDIAN
15 u_char fill __attribute__((packed));
16 u_char mode __attribute__((packed));
17 u_char xml __attribute__((packed));
18 u_char cmd __attribute__((packed));
19#else
20 u_char cmd __attribute__((packed));
21 u_char xml __attribute__((packed));
22 u_char mode __attribute__((packed));
23 u_char fill __attribute__((packed));
24#endif
25};
26
27struct fritz_bcs {
28 struct hisax_b_if b_if;
29 struct fritz_adapter *adapter;
30 int mode;
31 int channel;
32
33 union {
34 u_int ctrl;
35 struct hdlc_stat_reg sr;
36 } ctrl;
37 u_int stat;
38 int rcvidx;
39 int fifo_size;
40 u_char rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */
41
42 int tx_cnt; /* B-Channel transmit counter */
43 struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
44};
45
46struct fritz_adapter {
47 int type;
48 spinlock_t hw_lock;
49 unsigned int io;
50 unsigned int irq;
51 struct isac isac;
52
53 struct fritz_bcs bcs[2];
54
55 u32 (*read_hdlc_status) (struct fritz_adapter *adapter, int nr);
56 void (*write_ctrl) (struct fritz_bcs *bcs, int which);
57};
58
diff --git a/drivers/isdn/hisax/hisax_if.h b/drivers/isdn/hisax/hisax_if.h
new file mode 100644
index 00000000000..4898fce2d50
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_if.h
@@ -0,0 +1,66 @@
1/*
2 * Interface between low level (hardware) drivers and
3 * HiSax protocol stack
4 *
5 * Author Kai Germaschewski
6 * Copyright 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#ifndef __HISAX_IF_H__
14#define __HISAX_IF_H__
15
16#include <linux/skbuff.h>
17
18#define REQUEST 0
19#define CONFIRM 1
20#define INDICATION 2
21#define RESPONSE 3
22
23#define PH_ACTIVATE 0x0100
24#define PH_DEACTIVATE 0x0110
25#define PH_DATA 0x0120
26#define PH_PULL 0x0130
27#define PH_DATA_E 0x0140
28
29#define L1_MODE_NULL 0
30#define L1_MODE_TRANS 1
31#define L1_MODE_HDLC 2
32#define L1_MODE_EXTRN 3
33#define L1_MODE_HDLC_56K 4
34#define L1_MODE_MODEM 7
35#define L1_MODE_V32 8
36#define L1_MODE_FAX 9
37
38struct hisax_if {
39 void *priv; // private to driver
40 void (*l1l2)(struct hisax_if *, int pr, void *arg);
41 void (*l2l1)(struct hisax_if *, int pr, void *arg);
42};
43
44struct hisax_b_if {
45 struct hisax_if ifc;
46
47 // private to hisax
48 struct BCState *bcs;
49};
50
51struct hisax_d_if {
52 struct hisax_if ifc;
53
54 // private to hisax
55 struct module *owner;
56 struct IsdnCardState *cs;
57 struct hisax_b_if *b_if[2];
58 struct sk_buff_head erq;
59 long ph_state;
60};
61
62int hisax_register(struct hisax_d_if *hisax_if, struct hisax_b_if *b_if[],
63 char *name, int protocol);
64void hisax_unregister(struct hisax_d_if *hisax_if);
65
66#endif
diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
new file mode 100644
index 00000000000..f4972f6c1f5
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_isac.c
@@ -0,0 +1,897 @@
1/*
2 * Driver for ISAC-S and ISAC-SX
3 * ISDN Subscriber Access Controller for Terminals
4 *
5 * Author Kai Germaschewski
6 * Copyright 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
7 * 2001 by Karsten Keil <keil@isdn4linux.de>
8 *
9 * based upon Karsten Keil's original isac.c driver
10 *
11 * This software may be used and distributed according to the terms
12 * of the GNU General Public License, incorporated herein by reference.
13 *
14 * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
15 * SoHaNet Technology GmbH, Berlin
16 * for supporting the development of this driver
17 */
18
19/* TODO:
20 * specifically handle level vs edge triggered?
21 */
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/netdevice.h>
26#include "hisax_isac.h"
27
28// debugging cruft
29
30#define __debug_variable debug
31#include "hisax_debug.h"
32
33#ifdef CONFIG_HISAX_DEBUG
34static int debug = 1;
35module_param(debug, int, 0);
36
37static char *ISACVer[] = {
38 "2086/2186 V1.1",
39 "2085 B1",
40 "2085 B2",
41 "2085 V2.3"
42};
43#endif
44
45MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
46MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
47MODULE_LICENSE("GPL");
48
49#define DBG_WARN 0x0001
50#define DBG_IRQ 0x0002
51#define DBG_L1M 0x0004
52#define DBG_PR 0x0008
53#define DBG_RFIFO 0x0100
54#define DBG_RPACKET 0x0200
55#define DBG_XFIFO 0x1000
56#define DBG_XPACKET 0x2000
57
58// we need to distinguish ISAC-S and ISAC-SX
59#define TYPE_ISAC 0x00
60#define TYPE_ISACSX 0x01
61
62// registers etc.
63#define ISAC_MASK 0x20
64#define ISAC_ISTA 0x20
65#define ISAC_ISTA_EXI 0x01
66#define ISAC_ISTA_SIN 0x02
67#define ISAC_ISTA_CISQ 0x04
68#define ISAC_ISTA_XPR 0x10
69#define ISAC_ISTA_RSC 0x20
70#define ISAC_ISTA_RPF 0x40
71#define ISAC_ISTA_RME 0x80
72
73#define ISAC_STAR 0x21
74#define ISAC_CMDR 0x21
75#define ISAC_CMDR_XRES 0x01
76#define ISAC_CMDR_XME 0x02
77#define ISAC_CMDR_XTF 0x08
78#define ISAC_CMDR_RRES 0x40
79#define ISAC_CMDR_RMC 0x80
80
81#define ISAC_EXIR 0x24
82#define ISAC_EXIR_MOS 0x04
83#define ISAC_EXIR_XDU 0x40
84#define ISAC_EXIR_XMR 0x80
85
86#define ISAC_ADF2 0x39
87#define ISAC_SPCR 0x30
88#define ISAC_ADF1 0x38
89
90#define ISAC_CIR0 0x31
91#define ISAC_CIX0 0x31
92#define ISAC_CIR0_CIC0 0x02
93#define ISAC_CIR0_CIC1 0x01
94
95#define ISAC_CIR1 0x33
96#define ISAC_CIX1 0x33
97#define ISAC_STCR 0x37
98#define ISAC_MODE 0x22
99
100#define ISAC_RSTA 0x27
101#define ISAC_RSTA_RDO 0x40
102#define ISAC_RSTA_CRC 0x20
103#define ISAC_RSTA_RAB 0x10
104
105#define ISAC_RBCL 0x25
106#define ISAC_RBCH 0x2A
107#define ISAC_TIMR 0x23
108#define ISAC_SQXR 0x3b
109#define ISAC_MOSR 0x3a
110#define ISAC_MOCR 0x3a
111#define ISAC_MOR0 0x32
112#define ISAC_MOX0 0x32
113#define ISAC_MOR1 0x34
114#define ISAC_MOX1 0x34
115
116#define ISAC_RBCH_XAC 0x80
117
118#define ISAC_CMD_TIM 0x0
119#define ISAC_CMD_RES 0x1
120#define ISAC_CMD_SSP 0x2
121#define ISAC_CMD_SCP 0x3
122#define ISAC_CMD_AR8 0x8
123#define ISAC_CMD_AR10 0x9
124#define ISAC_CMD_ARL 0xa
125#define ISAC_CMD_DI 0xf
126
127#define ISACSX_MASK 0x60
128#define ISACSX_ISTA 0x60
129#define ISACSX_ISTA_ICD 0x01
130#define ISACSX_ISTA_CIC 0x10
131
132#define ISACSX_MASKD 0x20
133#define ISACSX_ISTAD 0x20
134#define ISACSX_ISTAD_XDU 0x04
135#define ISACSX_ISTAD_XMR 0x08
136#define ISACSX_ISTAD_XPR 0x10
137#define ISACSX_ISTAD_RFO 0x20
138#define ISACSX_ISTAD_RPF 0x40
139#define ISACSX_ISTAD_RME 0x80
140
141#define ISACSX_CMDRD 0x21
142#define ISACSX_CMDRD_XRES 0x01
143#define ISACSX_CMDRD_XME 0x02
144#define ISACSX_CMDRD_XTF 0x08
145#define ISACSX_CMDRD_RRES 0x40
146#define ISACSX_CMDRD_RMC 0x80
147
148#define ISACSX_MODED 0x22
149
150#define ISACSX_RBCLD 0x26
151
152#define ISACSX_RSTAD 0x28
153#define ISACSX_RSTAD_RAB 0x10
154#define ISACSX_RSTAD_CRC 0x20
155#define ISACSX_RSTAD_RDO 0x40
156#define ISACSX_RSTAD_VFR 0x80
157
158#define ISACSX_CIR0 0x2e
159#define ISACSX_CIR0_CIC0 0x08
160#define ISACSX_CIX0 0x2e
161
162#define ISACSX_TR_CONF0 0x30
163
164#define ISACSX_TR_CONF2 0x32
165
166static struct Fsm l1fsm;
167
168enum {
169 ST_L1_RESET,
170 ST_L1_F3_PDOWN,
171 ST_L1_F3_PUP,
172 ST_L1_F3_PEND_DEACT,
173 ST_L1_F4,
174 ST_L1_F5,
175 ST_L1_F6,
176 ST_L1_F7,
177 ST_L1_F8,
178};
179
180#define L1_STATE_COUNT (ST_L1_F8+1)
181
182static char *strL1State[] =
183{
184 "ST_L1_RESET",
185 "ST_L1_F3_PDOWN",
186 "ST_L1_F3_PUP",
187 "ST_L1_F3_PEND_DEACT",
188 "ST_L1_F4",
189 "ST_L1_F5",
190 "ST_L1_F6",
191 "ST_L1_F7",
192 "ST_L1_F8",
193};
194
195enum {
196 EV_PH_DR, // 0000
197 EV_PH_RES, // 0001
198 EV_PH_TMA, // 0010
199 EV_PH_SLD, // 0011
200 EV_PH_RSY, // 0100
201 EV_PH_DR6, // 0101
202 EV_PH_EI, // 0110
203 EV_PH_PU, // 0111
204 EV_PH_AR, // 1000
205 EV_PH_9, // 1001
206 EV_PH_ARL, // 1010
207 EV_PH_CVR, // 1011
208 EV_PH_AI8, // 1100
209 EV_PH_AI10, // 1101
210 EV_PH_AIL, // 1110
211 EV_PH_DC, // 1111
212 EV_PH_ACTIVATE_REQ,
213 EV_PH_DEACTIVATE_REQ,
214 EV_TIMER3,
215};
216
217#define L1_EVENT_COUNT (EV_TIMER3 + 1)
218
219static char *strL1Event[] =
220{
221 "EV_PH_DR", // 0000
222 "EV_PH_RES", // 0001
223 "EV_PH_TMA", // 0010
224 "EV_PH_SLD", // 0011
225 "EV_PH_RSY", // 0100
226 "EV_PH_DR6", // 0101
227 "EV_PH_EI", // 0110
228 "EV_PH_PU", // 0111
229 "EV_PH_AR", // 1000
230 "EV_PH_9", // 1001
231 "EV_PH_ARL", // 1010
232 "EV_PH_CVR", // 1011
233 "EV_PH_AI8", // 1100
234 "EV_PH_AI10", // 1101
235 "EV_PH_AIL", // 1110
236 "EV_PH_DC", // 1111
237 "EV_PH_ACTIVATE_REQ",
238 "EV_PH_DEACTIVATE_REQ",
239 "EV_TIMER3",
240};
241
242static inline void D_L1L2(struct isac *isac, int pr, void *arg)
243{
244 struct hisax_if *ifc = (struct hisax_if *) &isac->hisax_d_if;
245
246 DBG(DBG_PR, "pr %#x", pr);
247 ifc->l1l2(ifc, pr, arg);
248}
249
250static void ph_command(struct isac *isac, unsigned int command)
251{
252 DBG(DBG_L1M, "ph_command %#x", command);
253 switch (isac->type) {
254 case TYPE_ISAC:
255 isac->write_isac(isac, ISAC_CIX0, (command << 2) | 3);
256 break;
257 case TYPE_ISACSX:
258 isac->write_isac(isac, ISACSX_CIX0, (command << 4) | (7 << 1));
259 break;
260 }
261}
262
263// ----------------------------------------------------------------------
264
265static void l1_di(struct FsmInst *fi, int event, void *arg)
266{
267 struct isac *isac = fi->userdata;
268
269 FsmChangeState(fi, ST_L1_RESET);
270 ph_command(isac, ISAC_CMD_DI);
271}
272
273static void l1_di_deact_ind(struct FsmInst *fi, int event, void *arg)
274{
275 struct isac *isac = fi->userdata;
276
277 FsmChangeState(fi, ST_L1_RESET);
278 D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
279 ph_command(isac, ISAC_CMD_DI);
280}
281
282static void l1_go_f3pdown(struct FsmInst *fi, int event, void *arg)
283{
284 FsmChangeState(fi, ST_L1_F3_PDOWN);
285}
286
287static void l1_go_f3pend_deact_ind(struct FsmInst *fi, int event, void *arg)
288{
289 struct isac *isac = fi->userdata;
290
291 FsmChangeState(fi, ST_L1_F3_PEND_DEACT);
292 D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
293 ph_command(isac, ISAC_CMD_DI);
294}
295
296static void l1_go_f3pend(struct FsmInst *fi, int event, void *arg)
297{
298 struct isac *isac = fi->userdata;
299
300 FsmChangeState(fi, ST_L1_F3_PEND_DEACT);
301 ph_command(isac, ISAC_CMD_DI);
302}
303
304static void l1_go_f4(struct FsmInst *fi, int event, void *arg)
305{
306 FsmChangeState(fi, ST_L1_F4);
307}
308
309static void l1_go_f5(struct FsmInst *fi, int event, void *arg)
310{
311 FsmChangeState(fi, ST_L1_F5);
312}
313
314static void l1_go_f6(struct FsmInst *fi, int event, void *arg)
315{
316 FsmChangeState(fi, ST_L1_F6);
317}
318
319static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg)
320{
321 struct isac *isac = fi->userdata;
322
323 FsmChangeState(fi, ST_L1_F6);
324 D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
325}
326
327static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg)
328{
329 struct isac *isac = fi->userdata;
330
331 FsmDelTimer(&isac->timer, 0);
332 FsmChangeState(fi, ST_L1_F7);
333 ph_command(isac, ISAC_CMD_AR8);
334 D_L1L2(isac, PH_ACTIVATE | INDICATION, NULL);
335}
336
337static void l1_go_f8(struct FsmInst *fi, int event, void *arg)
338{
339 FsmChangeState(fi, ST_L1_F8);
340}
341
342static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg)
343{
344 struct isac *isac = fi->userdata;
345
346 FsmChangeState(fi, ST_L1_F8);
347 D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
348}
349
350static void l1_ar8(struct FsmInst *fi, int event, void *arg)
351{
352 struct isac *isac = fi->userdata;
353
354 FsmRestartTimer(&isac->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
355 ph_command(isac, ISAC_CMD_AR8);
356}
357
358static void l1_timer3(struct FsmInst *fi, int event, void *arg)
359{
360 struct isac *isac = fi->userdata;
361
362 ph_command(isac, ISAC_CMD_DI);
363 D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
364}
365
366// state machines according to data sheet PSB 2186 / 3186
367
368static struct FsmNode L1FnList[] __initdata =
369{
370 {ST_L1_RESET, EV_PH_RES, l1_di},
371 {ST_L1_RESET, EV_PH_EI, l1_di},
372 {ST_L1_RESET, EV_PH_DC, l1_go_f3pdown},
373 {ST_L1_RESET, EV_PH_AR, l1_go_f6},
374 {ST_L1_RESET, EV_PH_AI8, l1_go_f7_act_ind},
375
376 {ST_L1_F3_PDOWN, EV_PH_RES, l1_di},
377 {ST_L1_F3_PDOWN, EV_PH_EI, l1_di},
378 {ST_L1_F3_PDOWN, EV_PH_AR, l1_go_f6},
379 {ST_L1_F3_PDOWN, EV_PH_RSY, l1_go_f5},
380 {ST_L1_F3_PDOWN, EV_PH_PU, l1_go_f4},
381 {ST_L1_F3_PDOWN, EV_PH_AI8, l1_go_f7_act_ind},
382 {ST_L1_F3_PDOWN, EV_PH_ACTIVATE_REQ, l1_ar8},
383 {ST_L1_F3_PDOWN, EV_TIMER3, l1_timer3},
384
385 {ST_L1_F3_PEND_DEACT, EV_PH_RES, l1_di},
386 {ST_L1_F3_PEND_DEACT, EV_PH_EI, l1_di},
387 {ST_L1_F3_PEND_DEACT, EV_PH_DC, l1_go_f3pdown},
388 {ST_L1_F3_PEND_DEACT, EV_PH_RSY, l1_go_f5},
389 {ST_L1_F3_PEND_DEACT, EV_PH_AR, l1_go_f6},
390 {ST_L1_F3_PEND_DEACT, EV_PH_AI8, l1_go_f7_act_ind},
391
392 {ST_L1_F4, EV_PH_RES, l1_di},
393 {ST_L1_F4, EV_PH_EI, l1_di},
394 {ST_L1_F4, EV_PH_RSY, l1_go_f5},
395 {ST_L1_F4, EV_PH_AI8, l1_go_f7_act_ind},
396 {ST_L1_F4, EV_TIMER3, l1_timer3},
397 {ST_L1_F4, EV_PH_DC, l1_go_f3pdown},
398
399 {ST_L1_F5, EV_PH_RES, l1_di},
400 {ST_L1_F5, EV_PH_EI, l1_di},
401 {ST_L1_F5, EV_PH_AR, l1_go_f6},
402 {ST_L1_F5, EV_PH_AI8, l1_go_f7_act_ind},
403 {ST_L1_F5, EV_TIMER3, l1_timer3},
404 {ST_L1_F5, EV_PH_DR, l1_go_f3pend},
405 {ST_L1_F5, EV_PH_DC, l1_go_f3pdown},
406
407 {ST_L1_F6, EV_PH_RES, l1_di},
408 {ST_L1_F6, EV_PH_EI, l1_di},
409 {ST_L1_F6, EV_PH_RSY, l1_go_f8},
410 {ST_L1_F6, EV_PH_AI8, l1_go_f7_act_ind},
411 {ST_L1_F6, EV_PH_DR6, l1_go_f3pend},
412 {ST_L1_F6, EV_TIMER3, l1_timer3},
413 {ST_L1_F6, EV_PH_DC, l1_go_f3pdown},
414
415 {ST_L1_F7, EV_PH_RES, l1_di_deact_ind},
416 {ST_L1_F7, EV_PH_EI, l1_di_deact_ind},
417 {ST_L1_F7, EV_PH_AR, l1_go_f6_deact_ind},
418 {ST_L1_F7, EV_PH_RSY, l1_go_f8_deact_ind},
419 {ST_L1_F7, EV_PH_DR, l1_go_f3pend_deact_ind},
420
421 {ST_L1_F8, EV_PH_RES, l1_di},
422 {ST_L1_F8, EV_PH_EI, l1_di},
423 {ST_L1_F8, EV_PH_AR, l1_go_f6},
424 {ST_L1_F8, EV_PH_DR, l1_go_f3pend},
425 {ST_L1_F8, EV_PH_AI8, l1_go_f7_act_ind},
426 {ST_L1_F8, EV_TIMER3, l1_timer3},
427 {ST_L1_F8, EV_PH_DC, l1_go_f3pdown},
428};
429
430static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
431{
432 va_list args;
433 char buf[256];
434
435 va_start(args, fmt);
436 vsprintf(buf, fmt, args);
437 DBG(DBG_L1M, "%s", buf);
438 va_end(args);
439}
440
441static void isac_version(struct isac *cs)
442{
443 int val;
444
445 val = cs->read_isac(cs, ISAC_RBCH);
446 DBG(1, "ISAC version (%x): %s", val, ISACVer[(val >> 5) & 3]);
447}
448
449static void isac_empty_fifo(struct isac *isac, int count)
450{
451 // this also works for isacsx, since
452 // CMDR(D) register works the same
453 u_char *ptr;
454
455 DBG(DBG_IRQ, "count %d", count);
456
457 if ((isac->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
458 DBG(DBG_WARN, "overrun %d", isac->rcvidx + count);
459 isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
460 isac->rcvidx = 0;
461 return;
462 }
463 ptr = isac->rcvbuf + isac->rcvidx;
464 isac->rcvidx += count;
465 isac->read_isac_fifo(isac, ptr, count);
466 isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
467 DBG_PACKET(DBG_RFIFO, ptr, count);
468}
469
470static void isac_fill_fifo(struct isac *isac)
471{
472 // this also works for isacsx, since
473 // CMDR(D) register works the same
474
475 int count;
476 unsigned char cmd;
477 u_char *ptr;
478
479 if (!isac->tx_skb)
480 BUG();
481
482 count = isac->tx_skb->len;
483 if (count <= 0)
484 BUG();
485
486 DBG(DBG_IRQ, "count %d", count);
487
488 if (count > 0x20) {
489 count = 0x20;
490 cmd = ISAC_CMDR_XTF;
491 } else {
492 cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
493 }
494
495 ptr = isac->tx_skb->data;
496 skb_pull(isac->tx_skb, count);
497 isac->tx_cnt += count;
498 DBG_PACKET(DBG_XFIFO, ptr, count);
499 isac->write_isac_fifo(isac, ptr, count);
500 isac->write_isac(isac, ISAC_CMDR, cmd);
501}
502
503static void isac_retransmit(struct isac *isac)
504{
505 if (!isac->tx_skb) {
506 DBG(DBG_WARN, "no skb");
507 return;
508 }
509 skb_push(isac->tx_skb, isac->tx_cnt);
510 isac->tx_cnt = 0;
511}
512
513
514static inline void isac_cisq_interrupt(struct isac *isac)
515{
516 unsigned char val;
517
518 val = isac->read_isac(isac, ISAC_CIR0);
519 DBG(DBG_IRQ, "CIR0 %#x", val);
520 if (val & ISAC_CIR0_CIC0) {
521 DBG(DBG_IRQ, "CODR0 %#x", (val >> 2) & 0xf);
522 FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
523 }
524 if (val & ISAC_CIR0_CIC1) {
525 val = isac->read_isac(isac, ISAC_CIR1);
526 DBG(DBG_WARN, "ISAC CIR1 %#x", val );
527 }
528}
529
530static inline void isac_rme_interrupt(struct isac *isac)
531{
532 unsigned char val;
533 int count;
534 struct sk_buff *skb;
535
536 val = isac->read_isac(isac, ISAC_RSTA);
537 if ((val & (ISAC_RSTA_RDO | ISAC_RSTA_CRC | ISAC_RSTA_RAB) )
538 != ISAC_RSTA_CRC) {
539 DBG(DBG_WARN, "RSTA %#x, dropped", val);
540 isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
541 goto out;
542 }
543
544 count = isac->read_isac(isac, ISAC_RBCL) & 0x1f;
545 DBG(DBG_IRQ, "RBCL %#x", count);
546 if (count == 0)
547 count = 0x20;
548
549 isac_empty_fifo(isac, count);
550 count = isac->rcvidx;
551 if (count < 1) {
552 DBG(DBG_WARN, "count %d < 1", count);
553 goto out;
554 }
555
556 skb = alloc_skb(count, GFP_ATOMIC);
557 if (!skb) {
558 DBG(DBG_WARN, "no memory, dropping\n");
559 goto out;
560 }
561 memcpy(skb_put(skb, count), isac->rcvbuf, count);
562 DBG_SKB(DBG_RPACKET, skb);
563 D_L1L2(isac, PH_DATA | INDICATION, skb);
564 out:
565 isac->rcvidx = 0;
566}
567
568static inline void isac_xpr_interrupt(struct isac *isac)
569{
570 if (!isac->tx_skb)
571 return;
572
573 if (isac->tx_skb->len > 0) {
574 isac_fill_fifo(isac);
575 return;
576 }
577 dev_kfree_skb_irq(isac->tx_skb);
578 isac->tx_cnt = 0;
579 isac->tx_skb = NULL;
580 D_L1L2(isac, PH_DATA | CONFIRM, NULL);
581}
582
583static inline void isac_exi_interrupt(struct isac *isac)
584{
585 unsigned char val;
586
587 val = isac->read_isac(isac, ISAC_EXIR);
588 DBG(2, "EXIR %#x", val);
589
590 if (val & ISAC_EXIR_XMR) {
591 DBG(DBG_WARN, "ISAC XMR");
592 isac_retransmit(isac);
593 }
594 if (val & ISAC_EXIR_XDU) {
595 DBG(DBG_WARN, "ISAC XDU");
596 isac_retransmit(isac);
597 }
598 if (val & ISAC_EXIR_MOS) { /* MOS */
599 DBG(DBG_WARN, "MOS");
600 val = isac->read_isac(isac, ISAC_MOSR);
601 DBG(2, "ISAC MOSR %#x", val);
602 }
603}
604
605void isac_irq(struct isac *isac)
606{
607 unsigned char val;
608
609 val = isac->read_isac(isac, ISAC_ISTA);
610 DBG(DBG_IRQ, "ISTA %#x", val);
611
612 if (val & ISAC_ISTA_EXI) {
613 DBG(DBG_IRQ, "EXI");
614 isac_exi_interrupt(isac);
615 }
616 if (val & ISAC_ISTA_XPR) {
617 DBG(DBG_IRQ, "XPR");
618 isac_xpr_interrupt(isac);
619 }
620 if (val & ISAC_ISTA_RME) {
621 DBG(DBG_IRQ, "RME");
622 isac_rme_interrupt(isac);
623 }
624 if (val & ISAC_ISTA_RPF) {
625 DBG(DBG_IRQ, "RPF");
626 isac_empty_fifo(isac, 0x20);
627 }
628 if (val & ISAC_ISTA_CISQ) {
629 DBG(DBG_IRQ, "CISQ");
630 isac_cisq_interrupt(isac);
631 }
632 if (val & ISAC_ISTA_RSC) {
633 DBG(DBG_WARN, "RSC");
634 }
635 if (val & ISAC_ISTA_SIN) {
636 DBG(DBG_WARN, "SIN");
637 }
638 isac->write_isac(isac, ISAC_MASK, 0xff);
639 isac->write_isac(isac, ISAC_MASK, 0x00);
640}
641
642// ======================================================================
643
644static inline void isacsx_cic_interrupt(struct isac *isac)
645{
646 unsigned char val;
647
648 val = isac->read_isac(isac, ISACSX_CIR0);
649 DBG(DBG_IRQ, "CIR0 %#x", val);
650 if (val & ISACSX_CIR0_CIC0) {
651 DBG(DBG_IRQ, "CODR0 %#x", val >> 4);
652 FsmEvent(&isac->l1m, val >> 4, NULL);
653 }
654}
655
656static inline void isacsx_rme_interrupt(struct isac *isac)
657{
658 int count;
659 struct sk_buff *skb;
660 unsigned char val;
661
662 val = isac->read_isac(isac, ISACSX_RSTAD);
663 if ((val & (ISACSX_RSTAD_VFR |
664 ISACSX_RSTAD_RDO |
665 ISACSX_RSTAD_CRC |
666 ISACSX_RSTAD_RAB))
667 != (ISACSX_RSTAD_VFR | ISACSX_RSTAD_CRC)) {
668 DBG(DBG_WARN, "RSTAD %#x, dropped", val);
669 isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
670 goto out;
671 }
672
673 count = isac->read_isac(isac, ISACSX_RBCLD) & 0x1f;
674 DBG(DBG_IRQ, "RBCLD %#x", count);
675 if (count == 0)
676 count = 0x20;
677
678 isac_empty_fifo(isac, count);
679 // strip trailing status byte
680 count = isac->rcvidx - 1;
681 if (count < 1) {
682 DBG(DBG_WARN, "count %d < 1", count);
683 goto out;
684 }
685
686 skb = dev_alloc_skb(count);
687 if (!skb) {
688 DBG(DBG_WARN, "no memory, dropping");
689 goto out;
690 }
691 memcpy(skb_put(skb, count), isac->rcvbuf, count);
692 DBG_SKB(DBG_RPACKET, skb);
693 D_L1L2(isac, PH_DATA | INDICATION, skb);
694 out:
695 isac->rcvidx = 0;
696}
697
698static inline void isacsx_xpr_interrupt(struct isac *isac)
699{
700 if (!isac->tx_skb)
701 return;
702
703 if (isac->tx_skb->len > 0) {
704 isac_fill_fifo(isac);
705 return;
706 }
707 dev_kfree_skb_irq(isac->tx_skb);
708 isac->tx_skb = NULL;
709 isac->tx_cnt = 0;
710 D_L1L2(isac, PH_DATA | CONFIRM, NULL);
711}
712
713static inline void isacsx_icd_interrupt(struct isac *isac)
714{
715 unsigned char val;
716
717 val = isac->read_isac(isac, ISACSX_ISTAD);
718 DBG(DBG_IRQ, "ISTAD %#x", val);
719 if (val & ISACSX_ISTAD_XDU) {
720 DBG(DBG_WARN, "ISTAD XDU");
721 isac_retransmit(isac);
722 }
723 if (val & ISACSX_ISTAD_XMR) {
724 DBG(DBG_WARN, "ISTAD XMR");
725 isac_retransmit(isac);
726 }
727 if (val & ISACSX_ISTAD_XPR) {
728 DBG(DBG_IRQ, "ISTAD XPR");
729 isacsx_xpr_interrupt(isac);
730 }
731 if (val & ISACSX_ISTAD_RFO) {
732 DBG(DBG_WARN, "ISTAD RFO");
733 isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
734 }
735 if (val & ISACSX_ISTAD_RME) {
736 DBG(DBG_IRQ, "ISTAD RME");
737 isacsx_rme_interrupt(isac);
738 }
739 if (val & ISACSX_ISTAD_RPF) {
740 DBG(DBG_IRQ, "ISTAD RPF");
741 isac_empty_fifo(isac, 0x20);
742 }
743}
744
745void isacsx_irq(struct isac *isac)
746{
747 unsigned char val;
748
749 val = isac->read_isac(isac, ISACSX_ISTA);
750 DBG(DBG_IRQ, "ISTA %#x", val);
751
752 if (val & ISACSX_ISTA_ICD)
753 isacsx_icd_interrupt(isac);
754 if (val & ISACSX_ISTA_CIC)
755 isacsx_cic_interrupt(isac);
756}
757
758void isac_init(struct isac *isac)
759{
760 isac->tx_skb = NULL;
761 isac->l1m.fsm = &l1fsm;
762 isac->l1m.state = ST_L1_RESET;
763#ifdef CONFIG_HISAX_DEBUG
764 isac->l1m.debug = 1;
765#else
766 isac->l1m.debug = 0;
767#endif
768 isac->l1m.userdata = isac;
769 isac->l1m.printdebug = l1m_debug;
770 FsmInitTimer(&isac->l1m, &isac->timer);
771}
772
773void isac_setup(struct isac *isac)
774{
775 int val, eval;
776
777 isac->type = TYPE_ISAC;
778 isac_version(isac);
779
780 ph_command(isac, ISAC_CMD_RES);
781
782 isac->write_isac(isac, ISAC_MASK, 0xff);
783 isac->mocr = 0xaa;
784 if (test_bit(ISAC_IOM1, &isac->flags)) {
785 /* IOM 1 Mode */
786 isac->write_isac(isac, ISAC_ADF2, 0x0);
787 isac->write_isac(isac, ISAC_SPCR, 0xa);
788 isac->write_isac(isac, ISAC_ADF1, 0x2);
789 isac->write_isac(isac, ISAC_STCR, 0x70);
790 isac->write_isac(isac, ISAC_MODE, 0xc9);
791 } else {
792 /* IOM 2 Mode */
793 if (!isac->adf2)
794 isac->adf2 = 0x80;
795 isac->write_isac(isac, ISAC_ADF2, isac->adf2);
796 isac->write_isac(isac, ISAC_SQXR, 0x2f);
797 isac->write_isac(isac, ISAC_SPCR, 0x00);
798 isac->write_isac(isac, ISAC_STCR, 0x70);
799 isac->write_isac(isac, ISAC_MODE, 0xc9);
800 isac->write_isac(isac, ISAC_TIMR, 0x00);
801 isac->write_isac(isac, ISAC_ADF1, 0x00);
802 }
803 val = isac->read_isac(isac, ISAC_STAR);
804 DBG(2, "ISAC STAR %x", val);
805 val = isac->read_isac(isac, ISAC_MODE);
806 DBG(2, "ISAC MODE %x", val);
807 val = isac->read_isac(isac, ISAC_ADF2);
808 DBG(2, "ISAC ADF2 %x", val);
809 val = isac->read_isac(isac, ISAC_ISTA);
810 DBG(2, "ISAC ISTA %x", val);
811 if (val & 0x01) {
812 eval = isac->read_isac(isac, ISAC_EXIR);
813 DBG(2, "ISAC EXIR %x", eval);
814 }
815 val = isac->read_isac(isac, ISAC_CIR0);
816 DBG(2, "ISAC CIR0 %x", val);
817 FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
818
819 isac->write_isac(isac, ISAC_MASK, 0x0);
820 // RESET Receiver and Transmitter
821 isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_XRES | ISAC_CMDR_RRES);
822}
823
824void isacsx_setup(struct isac *isac)
825{
826 isac->type = TYPE_ISACSX;
827 // clear LDD
828 isac->write_isac(isac, ISACSX_TR_CONF0, 0x00);
829 // enable transmitter
830 isac->write_isac(isac, ISACSX_TR_CONF2, 0x00);
831 // transparent mode 0, RAC, stop/go
832 isac->write_isac(isac, ISACSX_MODED, 0xc9);
833 // all HDLC IRQ unmasked
834 isac->write_isac(isac, ISACSX_MASKD, 0x03);
835 // unmask ICD, CID IRQs
836 isac->write_isac(isac, ISACSX_MASK,
837 ~(ISACSX_ISTA_ICD | ISACSX_ISTA_CIC));
838}
839
840void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
841{
842 struct isac *isac = hisax_d_if->priv;
843 struct sk_buff *skb = arg;
844
845 DBG(DBG_PR, "pr %#x", pr);
846
847 switch (pr) {
848 case PH_ACTIVATE | REQUEST:
849 FsmEvent(&isac->l1m, EV_PH_ACTIVATE_REQ, NULL);
850 break;
851 case PH_DEACTIVATE | REQUEST:
852 FsmEvent(&isac->l1m, EV_PH_DEACTIVATE_REQ, NULL);
853 break;
854 case PH_DATA | REQUEST:
855 DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);
856 DBG_SKB(DBG_XPACKET, skb);
857 if (isac->l1m.state != ST_L1_F7) {
858 DBG(1, "L1 wrong state %d\n", isac->l1m.state);
859 dev_kfree_skb(skb);
860 break;
861 }
862 if (isac->tx_skb)
863 BUG();
864
865 isac->tx_skb = skb;
866 isac_fill_fifo(isac);
867 break;
868 }
869}
870
871static int __init hisax_isac_init(void)
872{
873 printk(KERN_INFO "hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0\n");
874
875 l1fsm.state_count = L1_STATE_COUNT;
876 l1fsm.event_count = L1_EVENT_COUNT;
877 l1fsm.strState = strL1State;
878 l1fsm.strEvent = strL1Event;
879 return FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
880}
881
882static void __exit hisax_isac_exit(void)
883{
884 FsmFree(&l1fsm);
885}
886
887EXPORT_SYMBOL(isac_init);
888EXPORT_SYMBOL(isac_d_l2l1);
889
890EXPORT_SYMBOL(isacsx_setup);
891EXPORT_SYMBOL(isacsx_irq);
892
893EXPORT_SYMBOL(isac_setup);
894EXPORT_SYMBOL(isac_irq);
895
896module_init(hisax_isac_init);
897module_exit(hisax_isac_exit);
diff --git a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h
new file mode 100644
index 00000000000..08890cf4d92
--- /dev/null
+++ b/drivers/isdn/hisax/hisax_isac.h
@@ -0,0 +1,45 @@
1#ifndef __HISAX_ISAC_H__
2#define __HISAX_ISAC_H__
3
4#include <linux/kernel.h>
5#include "fsm.h"
6#include "hisax_if.h"
7
8#define TIMER3_VALUE 7000
9#define MAX_DFRAME_LEN_L1 300
10
11#define ISAC_IOM1 0
12
13struct isac {
14 void *priv;
15
16 u_long flags;
17 struct hisax_d_if hisax_d_if;
18 struct FsmInst l1m;
19 struct FsmTimer timer;
20 u_char mocr;
21 u_char adf2;
22 int type;
23
24 u_char rcvbuf[MAX_DFRAME_LEN_L1];
25 int rcvidx;
26
27 struct sk_buff *tx_skb;
28 int tx_cnt;
29
30 u_char (*read_isac) (struct isac *, u_char);
31 void (*write_isac) (struct isac *, u_char, u_char);
32 void (*read_isac_fifo) (struct isac *, u_char *, int);
33 void (*write_isac_fifo)(struct isac *, u_char *, int);
34};
35
36void isac_init(struct isac *isac);
37void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
38
39void isac_setup(struct isac *isac);
40void isac_irq(struct isac *isac);
41
42void isacsx_setup(struct isac *isac);
43void isacsx_irq(struct isac *isac);
44
45#endif
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
new file mode 100644
index 00000000000..5bbbe3e9512
--- /dev/null
+++ b/drivers/isdn/hisax/hscx.c
@@ -0,0 +1,280 @@
1/* $Id: hscx.c,v 1.24.2.4 2004/01/24 20:47:23 keil Exp $
2 *
3 * HSCX specific routines
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "hscx.h"
16#include "isac.h"
17#include "isdnl1.h"
18#include <linux/interrupt.h>
19
20static char *HSCXVer[] =
21{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
22 "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
23
24int
25HscxVersion(struct IsdnCardState *cs, char *s)
26{
27 int verA, verB;
28
29 verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf;
30 verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf;
31 printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s,
32 HSCXVer[verA], HSCXVer[verB]);
33 if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
34 return (1);
35 else
36 return (0);
37}
38
39void
40modehscx(struct BCState *bcs, int mode, int bc)
41{
42 struct IsdnCardState *cs = bcs->cs;
43 int hscx = bcs->hw.hscx.hscx;
44
45 if (cs->debug & L1_DEB_HSCX)
46 debugl1(cs, "hscx %c mode %d ichan %d",
47 'A' + hscx, mode, bc);
48 bcs->mode = mode;
49 bcs->channel = bc;
50 cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
51 cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
52 cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
53 cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
54 cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
55 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
56 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
57 cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
58 cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
59 cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
60
61 /* Switch IOM 1 SSI */
62 if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0))
63 bc = 1 - bc;
64
65 if (bc == 0) {
66 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
67 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
68 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
69 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
70 } else {
71 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
72 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
73 }
74 switch (mode) {
75 case (L1_MODE_NULL):
76 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
77 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
78 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
79 break;
80 case (L1_MODE_TRANS):
81 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
82 break;
83 case (L1_MODE_HDLC):
84 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
85 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
86 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
87 break;
88 }
89 if (mode)
90 cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41);
91 cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00);
92}
93
94void
95hscx_l2l1(struct PStack *st, int pr, void *arg)
96{
97 struct BCState *bcs = st->l1.bcs;
98 u_long flags;
99 struct sk_buff *skb = arg;
100
101 switch (pr) {
102 case (PH_DATA | REQUEST):
103 spin_lock_irqsave(&bcs->cs->lock, flags);
104 if (bcs->tx_skb) {
105 skb_queue_tail(&bcs->squeue, skb);
106 } else {
107 bcs->tx_skb = skb;
108 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
109 bcs->hw.hscx.count = 0;
110 bcs->cs->BC_Send_Data(bcs);
111 }
112 spin_unlock_irqrestore(&bcs->cs->lock, flags);
113 break;
114 case (PH_PULL | INDICATION):
115 spin_lock_irqsave(&bcs->cs->lock, flags);
116 if (bcs->tx_skb) {
117 printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
118 } else {
119 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
120 bcs->tx_skb = skb;
121 bcs->hw.hscx.count = 0;
122 bcs->cs->BC_Send_Data(bcs);
123 }
124 spin_unlock_irqrestore(&bcs->cs->lock, flags);
125 break;
126 case (PH_PULL | REQUEST):
127 if (!bcs->tx_skb) {
128 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
129 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
130 } else
131 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
132 break;
133 case (PH_ACTIVATE | REQUEST):
134 spin_lock_irqsave(&bcs->cs->lock, flags);
135 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
136 modehscx(bcs, st->l1.mode, st->l1.bc);
137 spin_unlock_irqrestore(&bcs->cs->lock, flags);
138 l1_msg_b(st, pr, arg);
139 break;
140 case (PH_DEACTIVATE | REQUEST):
141 l1_msg_b(st, pr, arg);
142 break;
143 case (PH_DEACTIVATE | CONFIRM):
144 spin_lock_irqsave(&bcs->cs->lock, flags);
145 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
146 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
147 modehscx(bcs, 0, st->l1.bc);
148 spin_unlock_irqrestore(&bcs->cs->lock, flags);
149 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
150 break;
151 }
152}
153
154void
155close_hscxstate(struct BCState *bcs)
156{
157 modehscx(bcs, 0, bcs->channel);
158 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
159 if (bcs->hw.hscx.rcvbuf) {
160 kfree(bcs->hw.hscx.rcvbuf);
161 bcs->hw.hscx.rcvbuf = NULL;
162 }
163 if (bcs->blog) {
164 kfree(bcs->blog);
165 bcs->blog = NULL;
166 }
167 skb_queue_purge(&bcs->rqueue);
168 skb_queue_purge(&bcs->squeue);
169 if (bcs->tx_skb) {
170 dev_kfree_skb_any(bcs->tx_skb);
171 bcs->tx_skb = NULL;
172 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
173 }
174 }
175}
176
177int
178open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
179{
180 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
181 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
182 printk(KERN_WARNING
183 "HiSax: No memory for hscx.rcvbuf\n");
184 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
185 return (1);
186 }
187 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
188 printk(KERN_WARNING
189 "HiSax: No memory for bcs->blog\n");
190 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
191 kfree(bcs->hw.hscx.rcvbuf);
192 bcs->hw.hscx.rcvbuf = NULL;
193 return (2);
194 }
195 skb_queue_head_init(&bcs->rqueue);
196 skb_queue_head_init(&bcs->squeue);
197 }
198 bcs->tx_skb = NULL;
199 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
200 bcs->event = 0;
201 bcs->hw.hscx.rcvidx = 0;
202 bcs->tx_cnt = 0;
203 return (0);
204}
205
206int
207setstack_hscx(struct PStack *st, struct BCState *bcs)
208{
209 bcs->channel = st->l1.bc;
210 if (open_hscxstate(st->l1.hardware, bcs))
211 return (-1);
212 st->l1.bcs = bcs;
213 st->l2.l2l1 = hscx_l2l1;
214 setstack_manager(st);
215 bcs->st = st;
216 setstack_l1_B(st);
217 return (0);
218}
219
220void
221clear_pending_hscx_ints(struct IsdnCardState *cs)
222{
223 int val, eval;
224
225 val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
226 debugl1(cs, "HSCX B ISTA %x", val);
227 if (val & 0x01) {
228 eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
229 debugl1(cs, "HSCX B EXIR %x", eval);
230 }
231 if (val & 0x02) {
232 eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
233 debugl1(cs, "HSCX A EXIR %x", eval);
234 }
235 val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
236 debugl1(cs, "HSCX A ISTA %x", val);
237 val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
238 debugl1(cs, "HSCX B STAR %x", val);
239 val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
240 debugl1(cs, "HSCX A STAR %x", val);
241 /* disable all IRQ */
242 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
243 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
244}
245
246void
247inithscx(struct IsdnCardState *cs)
248{
249 cs->bcs[0].BC_SetStack = setstack_hscx;
250 cs->bcs[1].BC_SetStack = setstack_hscx;
251 cs->bcs[0].BC_Close = close_hscxstate;
252 cs->bcs[1].BC_Close = close_hscxstate;
253 cs->bcs[0].hw.hscx.hscx = 0;
254 cs->bcs[1].hw.hscx.hscx = 1;
255 cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
256 cs->bcs[0].hw.hscx.tsaxr1 = 3;
257 cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
258 cs->bcs[1].hw.hscx.tsaxr1 = 3;
259 modehscx(cs->bcs, 0, 0);
260 modehscx(cs->bcs + 1, 0, 0);
261}
262
263void
264inithscxisac(struct IsdnCardState *cs, int part)
265{
266 if (part & 1) {
267 clear_pending_isac_ints(cs);
268 clear_pending_hscx_ints(cs);
269 initisac(cs);
270 inithscx(cs);
271 }
272 if (part & 2) {
273 /* Reenable all IRQ */
274 cs->writeisac(cs, ISAC_MASK, 0);
275 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
276 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
277 /* RESET Receiver and Transmitter */
278 cs->writeisac(cs, ISAC_CMDR, 0x41);
279 }
280}
diff --git a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h
new file mode 100644
index 00000000000..268bfd3549b
--- /dev/null
+++ b/drivers/isdn/hisax/hscx.h
@@ -0,0 +1,41 @@
1/* $Id: hscx.h,v 1.8.2.2 2004/01/12 22:52:26 keil Exp $
2 *
3 * HSCX specific defines
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13/* All Registers original Siemens Spec */
14
15#define HSCX_ISTA 0x20
16#define HSCX_CCR1 0x2f
17#define HSCX_CCR2 0x2c
18#define HSCX_TSAR 0x31
19#define HSCX_TSAX 0x30
20#define HSCX_XCCR 0x32
21#define HSCX_RCCR 0x33
22#define HSCX_MODE 0x22
23#define HSCX_CMDR 0x21
24#define HSCX_EXIR 0x24
25#define HSCX_XAD1 0x24
26#define HSCX_XAD2 0x25
27#define HSCX_RAH2 0x27
28#define HSCX_RSTA 0x27
29#define HSCX_TIMR 0x23
30#define HSCX_STAR 0x21
31#define HSCX_RBCL 0x25
32#define HSCX_XBCH 0x2d
33#define HSCX_VSTR 0x2e
34#define HSCX_RLCR 0x2e
35#define HSCX_MASK 0x20
36
37extern int HscxVersion(struct IsdnCardState *cs, char *s);
38extern void modehscx(struct BCState *bcs, int mode, int bc);
39extern void clear_pending_hscx_ints(struct IsdnCardState *cs);
40extern void inithscx(struct IsdnCardState *cs);
41extern void inithscxisac(struct IsdnCardState *cs, int part);
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
new file mode 100644
index 00000000000..5fe9d42d03a
--- /dev/null
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -0,0 +1,292 @@
1/* $Id: hscx_irq.c,v 1.18.2.3 2004/02/11 13:21:34 keil Exp $
2 *
3 * low level b-channel stuff for Siemens HSCX
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * This is an include file for fast inline IRQ stuff
12 *
13 */
14
15
16static inline void
17waitforCEC(struct IsdnCardState *cs, int hscx)
18{
19 int to = 50;
20
21 while ((READHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
22 udelay(1);
23 to--;
24 }
25 if (!to)
26 printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
27}
28
29
30static inline void
31waitforXFW(struct IsdnCardState *cs, int hscx)
32{
33 int to = 50;
34
35 while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
36 udelay(1);
37 to--;
38 }
39 if (!to)
40 printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
41}
42
43static inline void
44WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
45{
46 waitforCEC(cs, hscx);
47 WRITEHSCX(cs, hscx, HSCX_CMDR, data);
48}
49
50
51
52static void
53hscx_empty_fifo(struct BCState *bcs, int count)
54{
55 u_char *ptr;
56 struct IsdnCardState *cs = bcs->cs;
57
58 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
59 debugl1(cs, "hscx_empty_fifo");
60
61 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
62 if (cs->debug & L1_DEB_WARN)
63 debugl1(cs, "hscx_empty_fifo: incoming packet too large");
64 WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
65 bcs->hw.hscx.rcvidx = 0;
66 return;
67 }
68 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
69 bcs->hw.hscx.rcvidx += count;
70 READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
71 WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
72 if (cs->debug & L1_DEB_HSCX_FIFO) {
73 char *t = bcs->blog;
74
75 t += sprintf(t, "hscx_empty_fifo %c cnt %d",
76 bcs->hw.hscx.hscx ? 'B' : 'A', count);
77 QuickHex(t, ptr, count);
78 debugl1(cs, bcs->blog);
79 }
80}
81
82static void
83hscx_fill_fifo(struct BCState *bcs)
84{
85 struct IsdnCardState *cs = bcs->cs;
86 int more, count;
87 int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
88 u_char *ptr;
89
90 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
91 debugl1(cs, "hscx_fill_fifo");
92
93 if (!bcs->tx_skb)
94 return;
95 if (bcs->tx_skb->len <= 0)
96 return;
97
98 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
99 if (bcs->tx_skb->len > fifo_size) {
100 more = !0;
101 count = fifo_size;
102 } else
103 count = bcs->tx_skb->len;
104
105 waitforXFW(cs, bcs->hw.hscx.hscx);
106 ptr = bcs->tx_skb->data;
107 skb_pull(bcs->tx_skb, count);
108 bcs->tx_cnt -= count;
109 bcs->hw.hscx.count += count;
110 WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
111 WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
112 if (cs->debug & L1_DEB_HSCX_FIFO) {
113 char *t = bcs->blog;
114
115 t += sprintf(t, "hscx_fill_fifo %c cnt %d",
116 bcs->hw.hscx.hscx ? 'B' : 'A', count);
117 QuickHex(t, ptr, count);
118 debugl1(cs, bcs->blog);
119 }
120}
121
122static inline void
123hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
124{
125 u_char r;
126 struct BCState *bcs = cs->bcs + hscx;
127 struct sk_buff *skb;
128 int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
129 int count;
130
131 if (!test_bit(BC_FLG_INIT, &bcs->Flag))
132 return;
133
134 if (val & 0x80) { /* RME */
135 r = READHSCX(cs, hscx, HSCX_RSTA);
136 if ((r & 0xf0) != 0xa0) {
137 if (!(r & 0x80)) {
138 if (cs->debug & L1_DEB_WARN)
139 debugl1(cs, "HSCX invalid frame");
140#ifdef ERROR_STATISTIC
141 bcs->err_inv++;
142#endif
143 }
144 if ((r & 0x40) && bcs->mode) {
145 if (cs->debug & L1_DEB_WARN)
146 debugl1(cs, "HSCX RDO mode=%d",
147 bcs->mode);
148#ifdef ERROR_STATISTIC
149 bcs->err_rdo++;
150#endif
151 }
152 if (!(r & 0x20)) {
153 if (cs->debug & L1_DEB_WARN)
154 debugl1(cs, "HSCX CRC error");
155#ifdef ERROR_STATISTIC
156 bcs->err_crc++;
157#endif
158 }
159 WriteHSCXCMDR(cs, hscx, 0x80);
160 } else {
161 count = READHSCX(cs, hscx, HSCX_RBCL) & (
162 test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
163 if (count == 0)
164 count = fifo_size;
165 hscx_empty_fifo(bcs, count);
166 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
167 if (cs->debug & L1_DEB_HSCX_FIFO)
168 debugl1(cs, "HX Frame %d", count);
169 if (!(skb = dev_alloc_skb(count)))
170 printk(KERN_WARNING "HSCX: receive out of memory\n");
171 else {
172 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
173 skb_queue_tail(&bcs->rqueue, skb);
174 }
175 }
176 }
177 bcs->hw.hscx.rcvidx = 0;
178 schedule_event(bcs, B_RCVBUFREADY);
179 }
180 if (val & 0x40) { /* RPF */
181 hscx_empty_fifo(bcs, fifo_size);
182 if (bcs->mode == L1_MODE_TRANS) {
183 /* receive audio data */
184 if (!(skb = dev_alloc_skb(fifo_size)))
185 printk(KERN_WARNING "HiSax: receive out of memory\n");
186 else {
187 memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
188 skb_queue_tail(&bcs->rqueue, skb);
189 }
190 bcs->hw.hscx.rcvidx = 0;
191 schedule_event(bcs, B_RCVBUFREADY);
192 }
193 }
194 if (val & 0x10) { /* XPR */
195 if (bcs->tx_skb) {
196 if (bcs->tx_skb->len) {
197 hscx_fill_fifo(bcs);
198 return;
199 } else {
200 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
201 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
202 u_long flags;
203 spin_lock_irqsave(&bcs->aclock, flags);
204 bcs->ackcnt += bcs->hw.hscx.count;
205 spin_unlock_irqrestore(&bcs->aclock, flags);
206 schedule_event(bcs, B_ACKPENDING);
207 }
208 dev_kfree_skb_irq(bcs->tx_skb);
209 bcs->hw.hscx.count = 0;
210 bcs->tx_skb = NULL;
211 }
212 }
213 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
214 bcs->hw.hscx.count = 0;
215 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
216 hscx_fill_fifo(bcs);
217 } else {
218 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
219 schedule_event(bcs, B_XMTBUFREADY);
220 }
221 }
222}
223
224static inline void
225hscx_int_main(struct IsdnCardState *cs, u_char val)
226{
227
228 u_char exval;
229 struct BCState *bcs;
230
231 if (val & 0x01) {
232 bcs = cs->bcs + 1;
233 exval = READHSCX(cs, 1, HSCX_EXIR);
234 if (exval & 0x40) {
235 if (bcs->mode == 1)
236 hscx_fill_fifo(bcs);
237 else {
238#ifdef ERROR_STATISTIC
239 bcs->err_tx++;
240#endif
241 /* Here we lost an TX interrupt, so
242 * restart transmitting the whole frame.
243 */
244 if (bcs->tx_skb) {
245 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
246 bcs->tx_cnt += bcs->hw.hscx.count;
247 bcs->hw.hscx.count = 0;
248 }
249 WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
250 if (cs->debug & L1_DEB_WARN)
251 debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
252 }
253 } else if (cs->debug & L1_DEB_HSCX)
254 debugl1(cs, "HSCX B EXIR %x", exval);
255 }
256 if (val & 0xf8) {
257 if (cs->debug & L1_DEB_HSCX)
258 debugl1(cs, "HSCX B interrupt %x", val);
259 hscx_interrupt(cs, val, 1);
260 }
261 if (val & 0x02) {
262 bcs = cs->bcs;
263 exval = READHSCX(cs, 0, HSCX_EXIR);
264 if (exval & 0x40) {
265 if (bcs->mode == L1_MODE_TRANS)
266 hscx_fill_fifo(bcs);
267 else {
268 /* Here we lost an TX interrupt, so
269 * restart transmitting the whole frame.
270 */
271#ifdef ERROR_STATISTIC
272 bcs->err_tx++;
273#endif
274 if (bcs->tx_skb) {
275 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
276 bcs->tx_cnt += bcs->hw.hscx.count;
277 bcs->hw.hscx.count = 0;
278 }
279 WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
280 if (cs->debug & L1_DEB_WARN)
281 debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
282 }
283 } else if (cs->debug & L1_DEB_HSCX)
284 debugl1(cs, "HSCX A EXIR %x", exval);
285 }
286 if (val & 0x04) {
287 exval = READHSCX(cs, 0, HSCX_ISTA);
288 if (cs->debug & L1_DEB_HSCX)
289 debugl1(cs, "HSCX A interrupt %x", exval);
290 hscx_interrupt(cs, exval, 0);
291 }
292}
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
new file mode 100644
index 00000000000..dcf31f83c60
--- /dev/null
+++ b/drivers/isdn/hisax/icc.c
@@ -0,0 +1,685 @@
1/* $Id: icc.c,v 1.8.2.3 2004/01/13 14:31:25 keil Exp $
2 *
3 * ICC specific routines
4 *
5 * Author Matt Henderson & Guy Ellis
6 * Copyright by Traverse Technologies Pty Ltd, www.travers.com.au
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 * 1999.6.25 Initial implementation of routines for Siemens ISDN
12 * Communication Controller PEB 2070 based on the ISAC routines
13 * written by Karsten Keil.
14 *
15 */
16
17#include <linux/init.h>
18#include "hisax.h"
19#include "icc.h"
20// #include "arcofi.h"
21#include "isdnl1.h"
22#include <linux/interrupt.h>
23
24#define DBUSY_TIMER_VALUE 80
25#define ARCOFI_USE 0
26
27static char *ICCVer[] __initdata =
28{"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
29
30void __init
31ICCVersion(struct IsdnCardState *cs, char *s)
32{
33 int val;
34
35 val = cs->readisac(cs, ICC_RBCH);
36 printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]);
37}
38
39static void
40ph_command(struct IsdnCardState *cs, unsigned int command)
41{
42 if (cs->debug & L1_DEB_ISAC)
43 debugl1(cs, "ph_command %x", command);
44 cs->writeisac(cs, ICC_CIX0, (command << 2) | 3);
45}
46
47
48static void
49icc_new_ph(struct IsdnCardState *cs)
50{
51 switch (cs->dc.icc.ph_state) {
52 case (ICC_IND_EI1):
53 ph_command(cs, ICC_CMD_DI);
54 l1_msg(cs, HW_RESET | INDICATION, NULL);
55 break;
56 case (ICC_IND_DC):
57 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
58 break;
59 case (ICC_IND_DR):
60 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
61 break;
62 case (ICC_IND_PU):
63 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
64 break;
65 case (ICC_IND_FJ):
66 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
67 break;
68 case (ICC_IND_AR):
69 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
70 break;
71 case (ICC_IND_AI):
72 l1_msg(cs, HW_INFO4 | INDICATION, NULL);
73 break;
74 default:
75 break;
76 }
77}
78
79static void
80icc_bh(struct IsdnCardState *cs)
81{
82 struct PStack *stptr;
83
84 if (!cs)
85 return;
86 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
87 if (cs->debug)
88 debugl1(cs, "D-Channel Busy cleared");
89 stptr = cs->stlist;
90 while (stptr != NULL) {
91 stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
92 stptr = stptr->next;
93 }
94 }
95 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
96 icc_new_ph(cs);
97 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
98 DChannel_proc_rcv(cs);
99 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
100 DChannel_proc_xmt(cs);
101#if ARCOFI_USE
102 if (!test_bit(HW_ARCOFI, &cs->HW_Flags))
103 return;
104 if (test_and_clear_bit(D_RX_MON1, &cs->event))
105 arcofi_fsm(cs, ARCOFI_RX_END, NULL);
106 if (test_and_clear_bit(D_TX_MON1, &cs->event))
107 arcofi_fsm(cs, ARCOFI_TX_END, NULL);
108#endif
109}
110
111void
112icc_empty_fifo(struct IsdnCardState *cs, int count)
113{
114 u_char *ptr;
115
116 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
117 debugl1(cs, "icc_empty_fifo");
118
119 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
120 if (cs->debug & L1_DEB_WARN)
121 debugl1(cs, "icc_empty_fifo overrun %d",
122 cs->rcvidx + count);
123 cs->writeisac(cs, ICC_CMDR, 0x80);
124 cs->rcvidx = 0;
125 return;
126 }
127 ptr = cs->rcvbuf + cs->rcvidx;
128 cs->rcvidx += count;
129 cs->readisacfifo(cs, ptr, count);
130 cs->writeisac(cs, ICC_CMDR, 0x80);
131 if (cs->debug & L1_DEB_ISAC_FIFO) {
132 char *t = cs->dlog;
133
134 t += sprintf(t, "icc_empty_fifo cnt %d", count);
135 QuickHex(t, ptr, count);
136 debugl1(cs, cs->dlog);
137 }
138}
139
140static void
141icc_fill_fifo(struct IsdnCardState *cs)
142{
143 int count, more;
144 u_char *ptr;
145
146 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
147 debugl1(cs, "icc_fill_fifo");
148
149 if (!cs->tx_skb)
150 return;
151
152 count = cs->tx_skb->len;
153 if (count <= 0)
154 return;
155
156 more = 0;
157 if (count > 32) {
158 more = !0;
159 count = 32;
160 }
161 ptr = cs->tx_skb->data;
162 skb_pull(cs->tx_skb, count);
163 cs->tx_cnt += count;
164 cs->writeisacfifo(cs, ptr, count);
165 cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa);
166 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
167 debugl1(cs, "icc_fill_fifo dbusytimer running");
168 del_timer(&cs->dbusytimer);
169 }
170 init_timer(&cs->dbusytimer);
171 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
172 add_timer(&cs->dbusytimer);
173 if (cs->debug & L1_DEB_ISAC_FIFO) {
174 char *t = cs->dlog;
175
176 t += sprintf(t, "icc_fill_fifo cnt %d", count);
177 QuickHex(t, ptr, count);
178 debugl1(cs, cs->dlog);
179 }
180}
181
182void
183icc_interrupt(struct IsdnCardState *cs, u_char val)
184{
185 u_char exval, v1;
186 struct sk_buff *skb;
187 unsigned int count;
188
189 if (cs->debug & L1_DEB_ISAC)
190 debugl1(cs, "ICC interrupt %x", val);
191 if (val & 0x80) { /* RME */
192 exval = cs->readisac(cs, ICC_RSTA);
193 if ((exval & 0x70) != 0x20) {
194 if (exval & 0x40) {
195 if (cs->debug & L1_DEB_WARN)
196 debugl1(cs, "ICC RDO");
197#ifdef ERROR_STATISTIC
198 cs->err_rx++;
199#endif
200 }
201 if (!(exval & 0x20)) {
202 if (cs->debug & L1_DEB_WARN)
203 debugl1(cs, "ICC CRC error");
204#ifdef ERROR_STATISTIC
205 cs->err_crc++;
206#endif
207 }
208 cs->writeisac(cs, ICC_CMDR, 0x80);
209 } else {
210 count = cs->readisac(cs, ICC_RBCL) & 0x1f;
211 if (count == 0)
212 count = 32;
213 icc_empty_fifo(cs, count);
214 if ((count = cs->rcvidx) > 0) {
215 cs->rcvidx = 0;
216 if (!(skb = alloc_skb(count, GFP_ATOMIC)))
217 printk(KERN_WARNING "HiSax: D receive out of memory\n");
218 else {
219 memcpy(skb_put(skb, count), cs->rcvbuf, count);
220 skb_queue_tail(&cs->rq, skb);
221 }
222 }
223 }
224 cs->rcvidx = 0;
225 schedule_event(cs, D_RCVBUFREADY);
226 }
227 if (val & 0x40) { /* RPF */
228 icc_empty_fifo(cs, 32);
229 }
230 if (val & 0x20) { /* RSC */
231 /* never */
232 if (cs->debug & L1_DEB_WARN)
233 debugl1(cs, "ICC RSC interrupt");
234 }
235 if (val & 0x10) { /* XPR */
236 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
237 del_timer(&cs->dbusytimer);
238 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
239 schedule_event(cs, D_CLEARBUSY);
240 if (cs->tx_skb) {
241 if (cs->tx_skb->len) {
242 icc_fill_fifo(cs);
243 goto afterXPR;
244 } else {
245 dev_kfree_skb_irq(cs->tx_skb);
246 cs->tx_cnt = 0;
247 cs->tx_skb = NULL;
248 }
249 }
250 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
251 cs->tx_cnt = 0;
252 icc_fill_fifo(cs);
253 } else
254 schedule_event(cs, D_XMTBUFREADY);
255 }
256 afterXPR:
257 if (val & 0x04) { /* CISQ */
258 exval = cs->readisac(cs, ICC_CIR0);
259 if (cs->debug & L1_DEB_ISAC)
260 debugl1(cs, "ICC CIR0 %02X", exval );
261 if (exval & 2) {
262 cs->dc.icc.ph_state = (exval >> 2) & 0xf;
263 if (cs->debug & L1_DEB_ISAC)
264 debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state);
265 schedule_event(cs, D_L1STATECHANGE);
266 }
267 if (exval & 1) {
268 exval = cs->readisac(cs, ICC_CIR1);
269 if (cs->debug & L1_DEB_ISAC)
270 debugl1(cs, "ICC CIR1 %02X", exval );
271 }
272 }
273 if (val & 0x02) { /* SIN */
274 /* never */
275 if (cs->debug & L1_DEB_WARN)
276 debugl1(cs, "ICC SIN interrupt");
277 }
278 if (val & 0x01) { /* EXI */
279 exval = cs->readisac(cs, ICC_EXIR);
280 if (cs->debug & L1_DEB_WARN)
281 debugl1(cs, "ICC EXIR %02x", exval);
282 if (exval & 0x80) { /* XMR */
283 debugl1(cs, "ICC XMR");
284 printk(KERN_WARNING "HiSax: ICC XMR\n");
285 }
286 if (exval & 0x40) { /* XDU */
287 debugl1(cs, "ICC XDU");
288 printk(KERN_WARNING "HiSax: ICC XDU\n");
289#ifdef ERROR_STATISTIC
290 cs->err_tx++;
291#endif
292 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
293 del_timer(&cs->dbusytimer);
294 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
295 schedule_event(cs, D_CLEARBUSY);
296 if (cs->tx_skb) { /* Restart frame */
297 skb_push(cs->tx_skb, cs->tx_cnt);
298 cs->tx_cnt = 0;
299 icc_fill_fifo(cs);
300 } else {
301 printk(KERN_WARNING "HiSax: ICC XDU no skb\n");
302 debugl1(cs, "ICC XDU no skb");
303 }
304 }
305 if (exval & 0x04) { /* MOS */
306 v1 = cs->readisac(cs, ICC_MOSR);
307 if (cs->debug & L1_DEB_MONITOR)
308 debugl1(cs, "ICC MOSR %02x", v1);
309#if ARCOFI_USE
310 if (v1 & 0x08) {
311 if (!cs->dc.icc.mon_rx) {
312 if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
313 if (cs->debug & L1_DEB_WARN)
314 debugl1(cs, "ICC MON RX out of memory!");
315 cs->dc.icc.mocr &= 0xf0;
316 cs->dc.icc.mocr |= 0x0a;
317 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
318 goto afterMONR0;
319 } else
320 cs->dc.icc.mon_rxp = 0;
321 }
322 if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
323 cs->dc.icc.mocr &= 0xf0;
324 cs->dc.icc.mocr |= 0x0a;
325 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
326 cs->dc.icc.mon_rxp = 0;
327 if (cs->debug & L1_DEB_WARN)
328 debugl1(cs, "ICC MON RX overflow!");
329 goto afterMONR0;
330 }
331 cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0);
332 if (cs->debug & L1_DEB_MONITOR)
333 debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]);
334 if (cs->dc.icc.mon_rxp == 1) {
335 cs->dc.icc.mocr |= 0x04;
336 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
337 }
338 }
339 afterMONR0:
340 if (v1 & 0x80) {
341 if (!cs->dc.icc.mon_rx) {
342 if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
343 if (cs->debug & L1_DEB_WARN)
344 debugl1(cs, "ICC MON RX out of memory!");
345 cs->dc.icc.mocr &= 0x0f;
346 cs->dc.icc.mocr |= 0xa0;
347 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
348 goto afterMONR1;
349 } else
350 cs->dc.icc.mon_rxp = 0;
351 }
352 if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
353 cs->dc.icc.mocr &= 0x0f;
354 cs->dc.icc.mocr |= 0xa0;
355 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
356 cs->dc.icc.mon_rxp = 0;
357 if (cs->debug & L1_DEB_WARN)
358 debugl1(cs, "ICC MON RX overflow!");
359 goto afterMONR1;
360 }
361 cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1);
362 if (cs->debug & L1_DEB_MONITOR)
363 debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]);
364 cs->dc.icc.mocr |= 0x40;
365 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
366 }
367 afterMONR1:
368 if (v1 & 0x04) {
369 cs->dc.icc.mocr &= 0xf0;
370 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
371 cs->dc.icc.mocr |= 0x0a;
372 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
373 schedule_event(cs, D_RX_MON0);
374 }
375 if (v1 & 0x40) {
376 cs->dc.icc.mocr &= 0x0f;
377 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
378 cs->dc.icc.mocr |= 0xa0;
379 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
380 schedule_event(cs, D_RX_MON1);
381 }
382 if (v1 & 0x02) {
383 if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc &&
384 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) &&
385 !(v1 & 0x08))) {
386 cs->dc.icc.mocr &= 0xf0;
387 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
388 cs->dc.icc.mocr |= 0x0a;
389 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
390 if (cs->dc.icc.mon_txc &&
391 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
392 schedule_event(cs, D_TX_MON0);
393 goto AfterMOX0;
394 }
395 if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
396 schedule_event(cs, D_TX_MON0);
397 goto AfterMOX0;
398 }
399 cs->writeisac(cs, ICC_MOX0,
400 cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
401 if (cs->debug & L1_DEB_MONITOR)
402 debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]);
403 }
404 AfterMOX0:
405 if (v1 & 0x20) {
406 if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc &&
407 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) &&
408 !(v1 & 0x80))) {
409 cs->dc.icc.mocr &= 0x0f;
410 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
411 cs->dc.icc.mocr |= 0xa0;
412 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
413 if (cs->dc.icc.mon_txc &&
414 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
415 schedule_event(cs, D_TX_MON1);
416 goto AfterMOX1;
417 }
418 if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
419 schedule_event(cs, D_TX_MON1);
420 goto AfterMOX1;
421 }
422 cs->writeisac(cs, ICC_MOX1,
423 cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
424 if (cs->debug & L1_DEB_MONITOR)
425 debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]);
426 }
427 AfterMOX1:
428#endif
429 }
430 }
431}
432
433static void
434ICC_l1hw(struct PStack *st, int pr, void *arg)
435{
436 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
437 struct sk_buff *skb = arg;
438 u_long flags;
439 int val;
440
441 switch (pr) {
442 case (PH_DATA |REQUEST):
443 if (cs->debug & DEB_DLOG_HEX)
444 LogFrame(cs, skb->data, skb->len);
445 if (cs->debug & DEB_DLOG_VERBOSE)
446 dlogframe(cs, skb, 0);
447 spin_lock_irqsave(&cs->lock, flags);
448 if (cs->tx_skb) {
449 skb_queue_tail(&cs->sq, skb);
450#ifdef L2FRAME_DEBUG /* psa */
451 if (cs->debug & L1_DEB_LAPD)
452 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
453#endif
454 } else {
455 cs->tx_skb = skb;
456 cs->tx_cnt = 0;
457#ifdef L2FRAME_DEBUG /* psa */
458 if (cs->debug & L1_DEB_LAPD)
459 Logl2Frame(cs, skb, "PH_DATA", 0);
460#endif
461 icc_fill_fifo(cs);
462 }
463 spin_unlock_irqrestore(&cs->lock, flags);
464 break;
465 case (PH_PULL |INDICATION):
466 spin_lock_irqsave(&cs->lock, flags);
467 if (cs->tx_skb) {
468 if (cs->debug & L1_DEB_WARN)
469 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
470 skb_queue_tail(&cs->sq, skb);
471 break;
472 }
473 if (cs->debug & DEB_DLOG_HEX)
474 LogFrame(cs, skb->data, skb->len);
475 if (cs->debug & DEB_DLOG_VERBOSE)
476 dlogframe(cs, skb, 0);
477 cs->tx_skb = skb;
478 cs->tx_cnt = 0;
479#ifdef L2FRAME_DEBUG /* psa */
480 if (cs->debug & L1_DEB_LAPD)
481 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
482#endif
483 icc_fill_fifo(cs);
484 spin_unlock_irqrestore(&cs->lock, flags);
485 break;
486 case (PH_PULL | REQUEST):
487#ifdef L2FRAME_DEBUG /* psa */
488 if (cs->debug & L1_DEB_LAPD)
489 debugl1(cs, "-> PH_REQUEST_PULL");
490#endif
491 if (!cs->tx_skb) {
492 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
493 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
494 } else
495 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
496 break;
497 case (HW_RESET | REQUEST):
498 spin_lock_irqsave(&cs->lock, flags);
499 if ((cs->dc.icc.ph_state == ICC_IND_EI1) ||
500 (cs->dc.icc.ph_state == ICC_IND_DR))
501 ph_command(cs, ICC_CMD_DI);
502 else
503 ph_command(cs, ICC_CMD_RES);
504 spin_unlock_irqrestore(&cs->lock, flags);
505 break;
506 case (HW_ENABLE | REQUEST):
507 spin_lock_irqsave(&cs->lock, flags);
508 ph_command(cs, ICC_CMD_DI);
509 spin_unlock_irqrestore(&cs->lock, flags);
510 break;
511 case (HW_INFO1 | REQUEST):
512 spin_lock_irqsave(&cs->lock, flags);
513 ph_command(cs, ICC_CMD_AR);
514 spin_unlock_irqrestore(&cs->lock, flags);
515 break;
516 case (HW_INFO3 | REQUEST):
517 spin_lock_irqsave(&cs->lock, flags);
518 ph_command(cs, ICC_CMD_AI);
519 spin_unlock_irqrestore(&cs->lock, flags);
520 break;
521 case (HW_TESTLOOP | REQUEST):
522 spin_lock_irqsave(&cs->lock, flags);
523 val = 0;
524 if (1 & (long) arg)
525 val |= 0x0c;
526 if (2 & (long) arg)
527 val |= 0x3;
528 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
529 /* IOM 1 Mode */
530 if (!val) {
531 cs->writeisac(cs, ICC_SPCR, 0xa);
532 cs->writeisac(cs, ICC_ADF1, 0x2);
533 } else {
534 cs->writeisac(cs, ICC_SPCR, val);
535 cs->writeisac(cs, ICC_ADF1, 0xa);
536 }
537 } else {
538 /* IOM 2 Mode */
539 cs->writeisac(cs, ICC_SPCR, val);
540 if (val)
541 cs->writeisac(cs, ICC_ADF1, 0x8);
542 else
543 cs->writeisac(cs, ICC_ADF1, 0x0);
544 }
545 spin_unlock_irqrestore(&cs->lock, flags);
546 break;
547 case (HW_DEACTIVATE | RESPONSE):
548 skb_queue_purge(&cs->rq);
549 skb_queue_purge(&cs->sq);
550 if (cs->tx_skb) {
551 dev_kfree_skb_any(cs->tx_skb);
552 cs->tx_skb = NULL;
553 }
554 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
555 del_timer(&cs->dbusytimer);
556 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
557 schedule_event(cs, D_CLEARBUSY);
558 break;
559 default:
560 if (cs->debug & L1_DEB_WARN)
561 debugl1(cs, "icc_l1hw unknown %04x", pr);
562 break;
563 }
564}
565
566void
567setstack_icc(struct PStack *st, struct IsdnCardState *cs)
568{
569 st->l1.l1hw = ICC_l1hw;
570}
571
572void
573DC_Close_icc(struct IsdnCardState *cs) {
574 if (cs->dc.icc.mon_rx) {
575 kfree(cs->dc.icc.mon_rx);
576 cs->dc.icc.mon_rx = NULL;
577 }
578 if (cs->dc.icc.mon_tx) {
579 kfree(cs->dc.icc.mon_tx);
580 cs->dc.icc.mon_tx = NULL;
581 }
582}
583
584static void
585dbusy_timer_handler(struct IsdnCardState *cs)
586{
587 struct PStack *stptr;
588 int rbch, star;
589
590 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
591 rbch = cs->readisac(cs, ICC_RBCH);
592 star = cs->readisac(cs, ICC_STAR);
593 if (cs->debug)
594 debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
595 rbch, star);
596 if (rbch & ICC_RBCH_XAC) { /* D-Channel Busy */
597 test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
598 stptr = cs->stlist;
599 while (stptr != NULL) {
600 stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
601 stptr = stptr->next;
602 }
603 } else {
604 /* discard frame; reset transceiver */
605 test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
606 if (cs->tx_skb) {
607 dev_kfree_skb_any(cs->tx_skb);
608 cs->tx_cnt = 0;
609 cs->tx_skb = NULL;
610 } else {
611 printk(KERN_WARNING "HiSax: ICC D-Channel Busy no skb\n");
612 debugl1(cs, "D-Channel Busy no skb");
613 }
614 cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */
615 cs->irq_func(cs->irq, cs, NULL);
616 }
617 }
618}
619
620void __init
621initicc(struct IsdnCardState *cs)
622{
623 cs->setstack_d = setstack_icc;
624 cs->DC_Close = DC_Close_icc;
625 cs->dc.icc.mon_tx = NULL;
626 cs->dc.icc.mon_rx = NULL;
627 cs->writeisac(cs, ICC_MASK, 0xff);
628 cs->dc.icc.mocr = 0xaa;
629 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
630 /* IOM 1 Mode */
631 cs->writeisac(cs, ICC_ADF2, 0x0);
632 cs->writeisac(cs, ICC_SPCR, 0xa);
633 cs->writeisac(cs, ICC_ADF1, 0x2);
634 cs->writeisac(cs, ICC_STCR, 0x70);
635 cs->writeisac(cs, ICC_MODE, 0xc9);
636 } else {
637 /* IOM 2 Mode */
638 if (!cs->dc.icc.adf2)
639 cs->dc.icc.adf2 = 0x80;
640 cs->writeisac(cs, ICC_ADF2, cs->dc.icc.adf2);
641 cs->writeisac(cs, ICC_SQXR, 0xa0);
642 cs->writeisac(cs, ICC_SPCR, 0x20);
643 cs->writeisac(cs, ICC_STCR, 0x70);
644 cs->writeisac(cs, ICC_MODE, 0xca);
645 cs->writeisac(cs, ICC_TIMR, 0x00);
646 cs->writeisac(cs, ICC_ADF1, 0x20);
647 }
648 ph_command(cs, ICC_CMD_RES);
649 cs->writeisac(cs, ICC_MASK, 0x0);
650 ph_command(cs, ICC_CMD_DI);
651}
652
653void __init
654clear_pending_icc_ints(struct IsdnCardState *cs)
655{
656 int val, eval;
657
658 val = cs->readisac(cs, ICC_STAR);
659 debugl1(cs, "ICC STAR %x", val);
660 val = cs->readisac(cs, ICC_MODE);
661 debugl1(cs, "ICC MODE %x", val);
662 val = cs->readisac(cs, ICC_ADF2);
663 debugl1(cs, "ICC ADF2 %x", val);
664 val = cs->readisac(cs, ICC_ISTA);
665 debugl1(cs, "ICC ISTA %x", val);
666 if (val & 0x01) {
667 eval = cs->readisac(cs, ICC_EXIR);
668 debugl1(cs, "ICC EXIR %x", eval);
669 }
670 val = cs->readisac(cs, ICC_CIR0);
671 debugl1(cs, "ICC CIR0 %x", val);
672 cs->dc.icc.ph_state = (val >> 2) & 0xf;
673 schedule_event(cs, D_L1STATECHANGE);
674 /* Disable all IRQ */
675 cs->writeisac(cs, ICC_MASK, 0xFF);
676}
677
678void __devinit
679setup_icc(struct IsdnCardState *cs)
680{
681 INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs);
682 cs->dbusytimer.function = (void *) dbusy_timer_handler;
683 cs->dbusytimer.data = (long) cs;
684 init_timer(&cs->dbusytimer);
685}
diff --git a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h
new file mode 100644
index 00000000000..b3bb3d5de53
--- /dev/null
+++ b/drivers/isdn/hisax/icc.h
@@ -0,0 +1,72 @@
1/* $Id: icc.h,v 1.4.2.2 2004/01/12 22:52:26 keil Exp $
2 *
3 * ICC specific routines
4 *
5 * Author Matt Henderson & Guy Ellis
6 * Copyright by Traverse Technologies Pty Ltd, www.travers.com.au
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 * 1999.7.14 Initial implementation of routines for Siemens ISDN
12 * Communication Controller PEB 2070 based on the ISAC routines
13 * written by Karsten Keil.
14 */
15
16/* All Registers original Siemens Spec */
17
18#define ICC_MASK 0x20
19#define ICC_ISTA 0x20
20#define ICC_STAR 0x21
21#define ICC_CMDR 0x21
22#define ICC_EXIR 0x24
23#define ICC_ADF2 0x39
24#define ICC_SPCR 0x30
25#define ICC_ADF1 0x38
26#define ICC_CIR0 0x31
27#define ICC_CIX0 0x31
28#define ICC_CIR1 0x33
29#define ICC_CIX1 0x33
30#define ICC_STCR 0x37
31#define ICC_MODE 0x22
32#define ICC_RSTA 0x27
33#define ICC_RBCL 0x25
34#define ICC_RBCH 0x2A
35#define ICC_TIMR 0x23
36#define ICC_SQXR 0x3b
37#define ICC_MOSR 0x3a
38#define ICC_MOCR 0x3a
39#define ICC_MOR0 0x32
40#define ICC_MOX0 0x32
41#define ICC_MOR1 0x34
42#define ICC_MOX1 0x34
43
44#define ICC_RBCH_XAC 0x80
45
46#define ICC_CMD_TIM 0x0
47#define ICC_CMD_RES 0x1
48#define ICC_CMD_DU 0x3
49#define ICC_CMD_EI1 0x4
50#define ICC_CMD_SSP 0x5
51#define ICC_CMD_DT 0x6
52#define ICC_CMD_AR 0x8
53#define ICC_CMD_ARL 0xA
54#define ICC_CMD_AI 0xC
55#define ICC_CMD_DI 0xF
56
57#define ICC_IND_DR 0x0
58#define ICC_IND_FJ 0x2
59#define ICC_IND_EI1 0x4
60#define ICC_IND_INT 0x6
61#define ICC_IND_PU 0x7
62#define ICC_IND_AR 0x8
63#define ICC_IND_ARL 0xA
64#define ICC_IND_AI 0xC
65#define ICC_IND_AIL 0xE
66#define ICC_IND_DC 0xF
67
68extern void __init ICCVersion(struct IsdnCardState *cs, char *s);
69extern void initicc(struct IsdnCardState *cs);
70extern void icc_interrupt(struct IsdnCardState *cs, u_char val);
71extern void clear_pending_icc_ints(struct IsdnCardState *cs);
72extern void setup_icc(struct IsdnCardState *);
diff --git a/drivers/isdn/hisax/ipac.h b/drivers/isdn/hisax/ipac.h
new file mode 100644
index 00000000000..f92a04a9282
--- /dev/null
+++ b/drivers/isdn/hisax/ipac.h
@@ -0,0 +1,29 @@
1/* $Id: ipac.h,v 1.7.2.2 2004/01/12 22:52:26 keil Exp $
2 *
3 * IPAC specific defines
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13/* All Registers original Siemens Spec */
14
15#define IPAC_CONF 0xC0
16#define IPAC_MASK 0xC1
17#define IPAC_ISTA 0xC1
18#define IPAC_ID 0xC2
19#define IPAC_ACFG 0xC3
20#define IPAC_AOE 0xC4
21#define IPAC_ARX 0xC5
22#define IPAC_ATX 0xC5
23#define IPAC_PITA1 0xC6
24#define IPAC_PITA2 0xC7
25#define IPAC_POTA1 0xC8
26#define IPAC_POTA2 0xC9
27#define IPAC_PCFG 0xCA
28#define IPAC_SCFG 0xCB
29#define IPAC_TIMR2 0xCC
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
new file mode 100644
index 00000000000..6485e232d86
--- /dev/null
+++ b/drivers/isdn/hisax/ipacx.c
@@ -0,0 +1,1004 @@
1/*
2 *
3 * IPACX specific routines
4 *
5 * Author Joerg Petersohn
6 * Derived from hisax_isac.c, isac.c, hscx.c and others
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 <linux/kernel.h>
13#include <linux/config.h>
14#include <linux/init.h>
15#include "hisax_if.h"
16#include "hisax.h"
17#include "isdnl1.h"
18#include "ipacx.h"
19
20#define DBUSY_TIMER_VALUE 80
21#define TIMER3_VALUE 7000
22#define MAX_DFRAME_LEN_L1 300
23#define B_FIFO_SIZE 64
24#define D_FIFO_SIZE 32
25
26
27// ipacx interrupt mask values
28#define _MASK_IMASK 0x2E // global mask
29#define _MASKB_IMASK 0x0B
30#define _MASKD_IMASK 0x03 // all on
31
32//----------------------------------------------------------
33// local function declarations
34//----------------------------------------------------------
35static void ph_command(struct IsdnCardState *cs, unsigned int command);
36static inline void cic_int(struct IsdnCardState *cs);
37static void dch_l2l1(struct PStack *st, int pr, void *arg);
38static void dbusy_timer_handler(struct IsdnCardState *cs);
39static void ipacx_new_ph(struct IsdnCardState *cs);
40static void dch_bh(struct IsdnCardState *cs);
41static void dch_empty_fifo(struct IsdnCardState *cs, int count);
42static void dch_fill_fifo(struct IsdnCardState *cs);
43static inline void dch_int(struct IsdnCardState *cs);
44static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
45static void __devinit dch_init(struct IsdnCardState *cs);
46static void bch_l2l1(struct PStack *st, int pr, void *arg);
47static void bch_empty_fifo(struct BCState *bcs, int count);
48static void bch_fill_fifo(struct BCState *bcs);
49static void bch_int(struct IsdnCardState *cs, u_char hscx);
50static void bch_mode(struct BCState *bcs, int mode, int bc);
51static void bch_close_state(struct BCState *bcs);
52static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs);
53static int bch_setstack(struct PStack *st, struct BCState *bcs);
54static void __devinit bch_init(struct IsdnCardState *cs, int hscx);
55static void __init clear_pending_ints(struct IsdnCardState *cs);
56
57//----------------------------------------------------------
58// Issue Layer 1 command to chip
59//----------------------------------------------------------
60static void
61ph_command(struct IsdnCardState *cs, unsigned int command)
62{
63 if (cs->debug &L1_DEB_ISAC)
64 debugl1(cs, "ph_command (%#x) in (%#x)", command,
65 cs->dc.isac.ph_state);
66//###################################
67// printk(KERN_INFO "ph_command (%#x)\n", command);
68//###################################
69 cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E);
70}
71
72//----------------------------------------------------------
73// Transceiver interrupt handler
74//----------------------------------------------------------
75static inline void
76cic_int(struct IsdnCardState *cs)
77{
78 u_char event;
79
80 event = cs->readisac(cs, IPACX_CIR0) >> 4;
81 if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event);
82//#########################################
83// printk(KERN_INFO "cic_int(%x)\n", event);
84//#########################################
85 cs->dc.isac.ph_state = event;
86 schedule_event(cs, D_L1STATECHANGE);
87}
88
89//==========================================================
90// D channel functions
91//==========================================================
92
93//----------------------------------------------------------
94// Command entry point
95//----------------------------------------------------------
96static void
97dch_l2l1(struct PStack *st, int pr, void *arg)
98{
99 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
100 struct sk_buff *skb = arg;
101 u_char cda1_cr, cda2_cr;
102
103 switch (pr) {
104 case (PH_DATA |REQUEST):
105 if (cs->debug &DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len);
106 if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
107 if (cs->tx_skb) {
108 skb_queue_tail(&cs->sq, skb);
109#ifdef L2FRAME_DEBUG
110 if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0);
111#endif
112 } else {
113 cs->tx_skb = skb;
114 cs->tx_cnt = 0;
115#ifdef L2FRAME_DEBUG
116 if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0);
117#endif
118 dch_fill_fifo(cs);
119 }
120 break;
121
122 case (PH_PULL |INDICATION):
123 if (cs->tx_skb) {
124 if (cs->debug & L1_DEB_WARN)
125 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
126 skb_queue_tail(&cs->sq, skb);
127 break;
128 }
129 if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len);
130 if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
131 cs->tx_skb = skb;
132 cs->tx_cnt = 0;
133#ifdef L2FRAME_DEBUG
134 if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
135#endif
136 dch_fill_fifo(cs);
137 break;
138
139 case (PH_PULL | REQUEST):
140#ifdef L2FRAME_DEBUG
141 if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL");
142#endif
143 if (!cs->tx_skb) {
144 clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
145 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
146 } else
147 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
148 break;
149
150 case (HW_RESET | REQUEST):
151 case (HW_ENABLE | REQUEST):
152 if ((cs->dc.isac.ph_state == IPACX_IND_RES) ||
153 (cs->dc.isac.ph_state == IPACX_IND_DR) ||
154 (cs->dc.isac.ph_state == IPACX_IND_DC))
155 ph_command(cs, IPACX_CMD_TIM);
156 else
157 ph_command(cs, IPACX_CMD_RES);
158 break;
159
160 case (HW_INFO3 | REQUEST):
161 ph_command(cs, IPACX_CMD_AR8);
162 break;
163
164 case (HW_TESTLOOP | REQUEST):
165 cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1
166 cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1
167 cda1_cr = cs->readisac(cs, IPACX_CDA1_CR);
168 cda2_cr = cs->readisac(cs, IPACX_CDA2_CR);
169 if ((long)arg &1) { // loop B1
170 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a);
171 }
172 else { // B1 off
173 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x0a);
174 }
175 if ((long)arg &2) { // loop B2
176 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x14);
177 }
178 else { // B2 off
179 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x14);
180 }
181 break;
182
183 case (HW_DEACTIVATE | RESPONSE):
184 skb_queue_purge(&cs->rq);
185 skb_queue_purge(&cs->sq);
186 if (cs->tx_skb) {
187 dev_kfree_skb_any(cs->tx_skb);
188 cs->tx_skb = NULL;
189 }
190 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
191 del_timer(&cs->dbusytimer);
192 break;
193
194 default:
195 if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_l2l1 unknown %04x", pr);
196 break;
197 }
198}
199
200//----------------------------------------------------------
201//----------------------------------------------------------
202static void
203dbusy_timer_handler(struct IsdnCardState *cs)
204{
205 struct PStack *st;
206 int rbchd, stard;
207
208 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
209 rbchd = cs->readisac(cs, IPACX_RBCHD);
210 stard = cs->readisac(cs, IPACX_STARD);
211 if (cs->debug)
212 debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard);
213 if (!(stard &0x40)) { // D-Channel Busy
214 set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
215 for (st = cs->stlist; st; st = st->next) {
216 st->l1.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on
217 }
218 } else {
219 // seems we lost an interrupt; reset transceiver */
220 clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
221 if (cs->tx_skb) {
222 dev_kfree_skb_any(cs->tx_skb);
223 cs->tx_cnt = 0;
224 cs->tx_skb = NULL;
225 } else {
226 printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
227 debugl1(cs, "D-Channel Busy no skb");
228 }
229 cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR
230 }
231 }
232}
233
234//----------------------------------------------------------
235// L1 state machine intermediate layer to isdnl1 module
236//----------------------------------------------------------
237static void
238ipacx_new_ph(struct IsdnCardState *cs)
239{
240 switch (cs->dc.isac.ph_state) {
241 case (IPACX_IND_RES):
242 ph_command(cs, IPACX_CMD_DI);
243 l1_msg(cs, HW_RESET | INDICATION, NULL);
244 break;
245
246 case (IPACX_IND_DC):
247 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
248 break;
249
250 case (IPACX_IND_DR):
251 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
252 break;
253
254 case (IPACX_IND_PU):
255 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
256 break;
257
258 case (IPACX_IND_RSY):
259 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
260 break;
261
262 case (IPACX_IND_AR):
263 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
264 break;
265
266 case (IPACX_IND_AI8):
267 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
268 break;
269
270 case (IPACX_IND_AI10):
271 l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
272 break;
273
274 default:
275 break;
276 }
277}
278
279//----------------------------------------------------------
280// bottom half handler for D channel
281//----------------------------------------------------------
282static void
283dch_bh(struct IsdnCardState *cs)
284{
285 struct PStack *st;
286
287 if (!cs) return;
288
289 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
290 if (cs->debug) debugl1(cs, "D-Channel Busy cleared");
291 for (st = cs->stlist; st; st = st->next) {
292 st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
293 }
294 }
295
296 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
297 DChannel_proc_rcv(cs);
298 }
299
300 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
301 DChannel_proc_xmt(cs);
302 }
303
304 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
305 ipacx_new_ph(cs);
306 }
307}
308
309//----------------------------------------------------------
310// Fill buffer from receive FIFO
311//----------------------------------------------------------
312static void
313dch_empty_fifo(struct IsdnCardState *cs, int count)
314{
315 u_char *ptr;
316
317 if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
318 debugl1(cs, "dch_empty_fifo()");
319
320 // message too large, remove
321 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
322 if (cs->debug &L1_DEB_WARN)
323 debugl1(cs, "dch_empty_fifo() incoming message too large");
324 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
325 cs->rcvidx = 0;
326 return;
327 }
328
329 ptr = cs->rcvbuf + cs->rcvidx;
330 cs->rcvidx += count;
331
332 cs->readisacfifo(cs, ptr, count);
333 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
334
335 if (cs->debug &L1_DEB_ISAC_FIFO) {
336 char *t = cs->dlog;
337
338 t += sprintf(t, "dch_empty_fifo() cnt %d", count);
339 QuickHex(t, ptr, count);
340 debugl1(cs, cs->dlog);
341 }
342}
343
344//----------------------------------------------------------
345// Fill transmit FIFO
346//----------------------------------------------------------
347static void
348dch_fill_fifo(struct IsdnCardState *cs)
349{
350 int count;
351 u_char cmd, *ptr;
352
353 if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
354 debugl1(cs, "dch_fill_fifo()");
355
356 if (!cs->tx_skb) return;
357 count = cs->tx_skb->len;
358 if (count <= 0) return;
359
360 if (count > D_FIFO_SIZE) {
361 count = D_FIFO_SIZE;
362 cmd = 0x08; // XTF
363 } else {
364 cmd = 0x0A; // XTF | XME
365 }
366
367 ptr = cs->tx_skb->data;
368 skb_pull(cs->tx_skb, count);
369 cs->tx_cnt += count;
370 cs->writeisacfifo(cs, ptr, count);
371 cs->writeisac(cs, IPACX_CMDRD, cmd);
372
373 // set timeout for transmission contol
374 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
375 debugl1(cs, "dch_fill_fifo dbusytimer running");
376 del_timer(&cs->dbusytimer);
377 }
378 init_timer(&cs->dbusytimer);
379 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
380 add_timer(&cs->dbusytimer);
381
382 if (cs->debug &L1_DEB_ISAC_FIFO) {
383 char *t = cs->dlog;
384
385 t += sprintf(t, "dch_fill_fifo() cnt %d", count);
386 QuickHex(t, ptr, count);
387 debugl1(cs, cs->dlog);
388 }
389}
390
391//----------------------------------------------------------
392// D channel interrupt handler
393//----------------------------------------------------------
394static inline void
395dch_int(struct IsdnCardState *cs)
396{
397 struct sk_buff *skb;
398 u_char istad, rstad;
399 int count;
400
401 istad = cs->readisac(cs, IPACX_ISTAD);
402//##############################################
403// printk(KERN_WARNING "dch_int(istad=%02x)\n", istad);
404//##############################################
405
406 if (istad &0x80) { // RME
407 rstad = cs->readisac(cs, IPACX_RSTAD);
408 if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
409 if (!(rstad &0x80))
410 if (cs->debug &L1_DEB_WARN)
411 debugl1(cs, "dch_int(): invalid frame");
412 if ((rstad &0x40))
413 if (cs->debug &L1_DEB_WARN)
414 debugl1(cs, "dch_int(): RDO");
415 if (!(rstad &0x20))
416 if (cs->debug &L1_DEB_WARN)
417 debugl1(cs, "dch_int(): CRC error");
418 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
419 } else { // received frame ok
420 count = cs->readisac(cs, IPACX_RBCLD);
421 if (count) count--; // RSTAB is last byte
422 count &= D_FIFO_SIZE-1;
423 if (count == 0) count = D_FIFO_SIZE;
424 dch_empty_fifo(cs, count);
425 if ((count = cs->rcvidx) > 0) {
426 cs->rcvidx = 0;
427 if (!(skb = dev_alloc_skb(count)))
428 printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n");
429 else {
430 memcpy(skb_put(skb, count), cs->rcvbuf, count);
431 skb_queue_tail(&cs->rq, skb);
432 }
433 }
434 }
435 cs->rcvidx = 0;
436 schedule_event(cs, D_RCVBUFREADY);
437 }
438
439 if (istad &0x40) { // RPF
440 dch_empty_fifo(cs, D_FIFO_SIZE);
441 }
442
443 if (istad &0x20) { // RFO
444 if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): RFO");
445 cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES
446 }
447
448 if (istad &0x10) { // XPR
449 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
450 del_timer(&cs->dbusytimer);
451 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
452 schedule_event(cs, D_CLEARBUSY);
453 if (cs->tx_skb) {
454 if (cs->tx_skb->len) {
455 dch_fill_fifo(cs);
456 goto afterXPR;
457 }
458 else {
459 dev_kfree_skb_irq(cs->tx_skb);
460 cs->tx_skb = NULL;
461 cs->tx_cnt = 0;
462 }
463 }
464 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
465 cs->tx_cnt = 0;
466 dch_fill_fifo(cs);
467 }
468 else {
469 schedule_event(cs, D_XMTBUFREADY);
470 }
471 }
472 afterXPR:
473
474 if (istad &0x0C) { // XDU or XMR
475 if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU");
476 if (cs->tx_skb) {
477 skb_push(cs->tx_skb, cs->tx_cnt); // retransmit
478 cs->tx_cnt = 0;
479 dch_fill_fifo(cs);
480 } else {
481 printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
482 debugl1(cs, "ISAC XDU no skb");
483 }
484 }
485}
486
487//----------------------------------------------------------
488//----------------------------------------------------------
489static void __devinit
490dch_setstack(struct PStack *st, struct IsdnCardState *cs)
491{
492 st->l1.l1hw = dch_l2l1;
493}
494
495//----------------------------------------------------------
496//----------------------------------------------------------
497static void __devinit
498dch_init(struct IsdnCardState *cs)
499{
500 printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n");
501
502 cs->setstack_d = dch_setstack;
503
504 cs->dbusytimer.function = (void *) dbusy_timer_handler;
505 cs->dbusytimer.data = (long) cs;
506 init_timer(&cs->dbusytimer);
507
508 cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD
509 cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter
510 cs->writeisac(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go
511 cs->writeisac(cs, IPACX_MON_CR, 0x00); // disable monitor channel
512}
513
514
515//==========================================================
516// B channel functions
517//==========================================================
518
519//----------------------------------------------------------
520// Entry point for commands
521//----------------------------------------------------------
522static void
523bch_l2l1(struct PStack *st, int pr, void *arg)
524{
525 struct BCState *bcs = st->l1.bcs;
526 struct sk_buff *skb = arg;
527 u_long flags;
528
529 switch (pr) {
530 case (PH_DATA | REQUEST):
531 spin_lock_irqsave(&bcs->cs->lock, flags);
532 if (bcs->tx_skb) {
533 skb_queue_tail(&bcs->squeue, skb);
534 } else {
535 bcs->tx_skb = skb;
536 set_bit(BC_FLG_BUSY, &bcs->Flag);
537 bcs->hw.hscx.count = 0;
538 bch_fill_fifo(bcs);
539 }
540 spin_unlock_irqrestore(&bcs->cs->lock, flags);
541 break;
542 case (PH_PULL | INDICATION):
543 spin_lock_irqsave(&bcs->cs->lock, flags);
544 if (bcs->tx_skb) {
545 printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n");
546 } else {
547 set_bit(BC_FLG_BUSY, &bcs->Flag);
548 bcs->tx_skb = skb;
549 bcs->hw.hscx.count = 0;
550 bch_fill_fifo(bcs);
551 }
552 spin_unlock_irqrestore(&bcs->cs->lock, flags);
553 break;
554 case (PH_PULL | REQUEST):
555 if (!bcs->tx_skb) {
556 clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
557 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
558 } else
559 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
560 break;
561 case (PH_ACTIVATE | REQUEST):
562 spin_lock_irqsave(&bcs->cs->lock, flags);
563 set_bit(BC_FLG_ACTIV, &bcs->Flag);
564 bch_mode(bcs, st->l1.mode, st->l1.bc);
565 spin_unlock_irqrestore(&bcs->cs->lock, flags);
566 l1_msg_b(st, pr, arg);
567 break;
568 case (PH_DEACTIVATE | REQUEST):
569 l1_msg_b(st, pr, arg);
570 break;
571 case (PH_DEACTIVATE | CONFIRM):
572 spin_lock_irqsave(&bcs->cs->lock, flags);
573 clear_bit(BC_FLG_ACTIV, &bcs->Flag);
574 clear_bit(BC_FLG_BUSY, &bcs->Flag);
575 bch_mode(bcs, 0, st->l1.bc);
576 spin_unlock_irqrestore(&bcs->cs->lock, flags);
577 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
578 break;
579 }
580}
581
582//----------------------------------------------------------
583// Read B channel fifo to receive buffer
584//----------------------------------------------------------
585static void
586bch_empty_fifo(struct BCState *bcs, int count)
587{
588 u_char *ptr, hscx;
589 struct IsdnCardState *cs;
590 int cnt;
591
592 cs = bcs->cs;
593 hscx = bcs->hw.hscx.hscx;
594 if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
595 debugl1(cs, "bch_empty_fifo()");
596
597 // message too large, remove
598 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
599 if (cs->debug &L1_DEB_WARN)
600 debugl1(cs, "bch_empty_fifo() incoming packet too large");
601 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC
602 bcs->hw.hscx.rcvidx = 0;
603 return;
604 }
605
606 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
607 cnt = count;
608 while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB);
609 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC
610
611 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
612 bcs->hw.hscx.rcvidx += count;
613
614 if (cs->debug &L1_DEB_HSCX_FIFO) {
615 char *t = bcs->blog;
616
617 t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
618 QuickHex(t, ptr, count);
619 debugl1(cs, bcs->blog);
620 }
621}
622
623//----------------------------------------------------------
624// Fill buffer to transmit FIFO
625//----------------------------------------------------------
626static void
627bch_fill_fifo(struct BCState *bcs)
628{
629 struct IsdnCardState *cs;
630 int more, count, cnt;
631 u_char *ptr, *p, hscx;
632
633 cs = bcs->cs;
634 if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
635 debugl1(cs, "bch_fill_fifo()");
636
637 if (!bcs->tx_skb) return;
638 if (bcs->tx_skb->len <= 0) return;
639
640 hscx = bcs->hw.hscx.hscx;
641 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
642 if (bcs->tx_skb->len > B_FIFO_SIZE) {
643 more = 1;
644 count = B_FIFO_SIZE;
645 } else {
646 count = bcs->tx_skb->len;
647 }
648 cnt = count;
649
650 p = ptr = bcs->tx_skb->data;
651 skb_pull(bcs->tx_skb, count);
652 bcs->tx_cnt -= count;
653 bcs->hw.hscx.count += count;
654 while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++);
655 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a));
656
657 if (cs->debug &L1_DEB_HSCX_FIFO) {
658 char *t = bcs->blog;
659
660 t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count);
661 QuickHex(t, ptr, count);
662 debugl1(cs, bcs->blog);
663 }
664}
665
666//----------------------------------------------------------
667// B channel interrupt handler
668//----------------------------------------------------------
669static void
670bch_int(struct IsdnCardState *cs, u_char hscx)
671{
672 u_char istab;
673 struct BCState *bcs;
674 struct sk_buff *skb;
675 int count;
676 u_char rstab;
677
678 bcs = cs->bcs + hscx;
679 istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB);
680//##############################################
681// printk(KERN_WARNING "bch_int(istab=%02x)\n", istab);
682//##############################################
683 if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return;
684
685 if (istab &0x80) { // RME
686 rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB);
687 if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
688 if (!(rstab &0x80))
689 if (cs->debug &L1_DEB_WARN)
690 debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
691 if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL))
692 if (cs->debug &L1_DEB_WARN)
693 debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
694 if (!(rstab &0x20))
695 if (cs->debug &L1_DEB_WARN)
696 debugl1(cs, "bch_int() B-%d: CRC error", hscx);
697 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC
698 }
699 else { // received frame ok
700 count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) &(B_FIFO_SIZE-1);
701 if (count == 0) count = B_FIFO_SIZE;
702 bch_empty_fifo(bcs, count);
703 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
704 if (cs->debug &L1_DEB_HSCX_FIFO)
705 debugl1(cs, "bch_int Frame %d", count);
706 if (!(skb = dev_alloc_skb(count)))
707 printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n");
708 else {
709 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
710 skb_queue_tail(&bcs->rqueue, skb);
711 }
712 }
713 }
714 bcs->hw.hscx.rcvidx = 0;
715 schedule_event(bcs, B_RCVBUFREADY);
716 }
717
718 if (istab &0x40) { // RPF
719 bch_empty_fifo(bcs, B_FIFO_SIZE);
720
721 if (bcs->mode == L1_MODE_TRANS) { // queue every chunk
722 // receive transparent audio data
723 if (!(skb = dev_alloc_skb(B_FIFO_SIZE)))
724 printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n");
725 else {
726 memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE);
727 skb_queue_tail(&bcs->rqueue, skb);
728 }
729 bcs->hw.hscx.rcvidx = 0;
730 schedule_event(bcs, B_RCVBUFREADY);
731 }
732 }
733
734 if (istab &0x20) { // RFO
735 if (cs->debug &L1_DEB_WARN)
736 debugl1(cs, "bch_int() B-%d: RFO error", hscx);
737 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES
738 }
739
740 if (istab &0x10) { // XPR
741 if (bcs->tx_skb) {
742 if (bcs->tx_skb->len) {
743 bch_fill_fifo(bcs);
744 goto afterXPR;
745 } else {
746 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
747 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
748 u_long flags;
749 spin_lock_irqsave(&bcs->aclock, flags);
750 bcs->ackcnt += bcs->hw.hscx.count;
751 spin_unlock_irqrestore(&bcs->aclock, flags);
752 schedule_event(bcs, B_ACKPENDING);
753 }
754 }
755 dev_kfree_skb_irq(bcs->tx_skb);
756 bcs->hw.hscx.count = 0;
757 bcs->tx_skb = NULL;
758 }
759 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
760 bcs->hw.hscx.count = 0;
761 set_bit(BC_FLG_BUSY, &bcs->Flag);
762 bch_fill_fifo(bcs);
763 } else {
764 clear_bit(BC_FLG_BUSY, &bcs->Flag);
765 schedule_event(bcs, B_XMTBUFREADY);
766 }
767 }
768 afterXPR:
769
770 if (istab &0x04) { // XDU
771 if (bcs->mode == L1_MODE_TRANS) {
772 bch_fill_fifo(bcs);
773 }
774 else {
775 if (bcs->tx_skb) { // restart transmitting the whole frame
776 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
777 bcs->tx_cnt += bcs->hw.hscx.count;
778 bcs->hw.hscx.count = 0;
779 }
780 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES
781 if (cs->debug &L1_DEB_WARN)
782 debugl1(cs, "bch_int() B-%d XDU error", hscx);
783 }
784 }
785}
786
787//----------------------------------------------------------
788//----------------------------------------------------------
789static void
790bch_mode(struct BCState *bcs, int mode, int bc)
791{
792 struct IsdnCardState *cs = bcs->cs;
793 int hscx = bcs->hw.hscx.hscx;
794
795 bc = bc ? 1 : 0; // in case bc is greater than 1
796 if (cs->debug & L1_DEB_HSCX)
797 debugl1(cs, "mode_bch() switch B-% mode %d chan %d", hscx, mode, bc);
798 bcs->mode = mode;
799 bcs->channel = bc;
800
801 // map controller to according timeslot
802 if (!hscx)
803 {
804 cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc);
805 cs->writeisac(cs, IPACX_BCHA_CR, 0x88);
806 }
807 else
808 {
809 cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc);
810 cs->writeisac(cs, IPACX_BCHB_CR, 0x88);
811 }
812
813 switch (mode) {
814 case (L1_MODE_NULL):
815 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0); // rec off
816 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x30); // std adj.
817 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF); // ints off
818 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments
819 break;
820 case (L1_MODE_TRANS):
821 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88); // ext transp mode
822 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x00); // xxx00000
823 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments
824 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK);
825 break;
826 case (L1_MODE_HDLC):
827 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8); // transp mode 0
828 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled
829 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments
830 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK);
831 break;
832 }
833}
834
835//----------------------------------------------------------
836//----------------------------------------------------------
837static void
838bch_close_state(struct BCState *bcs)
839{
840 bch_mode(bcs, 0, bcs->channel);
841 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
842 if (bcs->hw.hscx.rcvbuf) {
843 kfree(bcs->hw.hscx.rcvbuf);
844 bcs->hw.hscx.rcvbuf = NULL;
845 }
846 if (bcs->blog) {
847 kfree(bcs->blog);
848 bcs->blog = NULL;
849 }
850 skb_queue_purge(&bcs->rqueue);
851 skb_queue_purge(&bcs->squeue);
852 if (bcs->tx_skb) {
853 dev_kfree_skb_any(bcs->tx_skb);
854 bcs->tx_skb = NULL;
855 clear_bit(BC_FLG_BUSY, &bcs->Flag);
856 }
857 }
858}
859
860//----------------------------------------------------------
861//----------------------------------------------------------
862static int
863bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
864{
865 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
866 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
867 printk(KERN_WARNING
868 "HiSax open_bchstate(): No memory for hscx.rcvbuf\n");
869 clear_bit(BC_FLG_INIT, &bcs->Flag);
870 return (1);
871 }
872 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
873 printk(KERN_WARNING
874 "HiSax open_bchstate: No memory for bcs->blog\n");
875 clear_bit(BC_FLG_INIT, &bcs->Flag);
876 kfree(bcs->hw.hscx.rcvbuf);
877 bcs->hw.hscx.rcvbuf = NULL;
878 return (2);
879 }
880 skb_queue_head_init(&bcs->rqueue);
881 skb_queue_head_init(&bcs->squeue);
882 }
883 bcs->tx_skb = NULL;
884 clear_bit(BC_FLG_BUSY, &bcs->Flag);
885 bcs->event = 0;
886 bcs->hw.hscx.rcvidx = 0;
887 bcs->tx_cnt = 0;
888 return (0);
889}
890
891//----------------------------------------------------------
892//----------------------------------------------------------
893static int
894bch_setstack(struct PStack *st, struct BCState *bcs)
895{
896 bcs->channel = st->l1.bc;
897 if (bch_open_state(st->l1.hardware, bcs)) return (-1);
898 st->l1.bcs = bcs;
899 st->l2.l2l1 = bch_l2l1;
900 setstack_manager(st);
901 bcs->st = st;
902 setstack_l1_B(st);
903 return (0);
904}
905
906//----------------------------------------------------------
907//----------------------------------------------------------
908static void __devinit
909bch_init(struct IsdnCardState *cs, int hscx)
910{
911 cs->bcs[hscx].BC_SetStack = bch_setstack;
912 cs->bcs[hscx].BC_Close = bch_close_state;
913 cs->bcs[hscx].hw.hscx.hscx = hscx;
914 cs->bcs[hscx].cs = cs;
915 bch_mode(cs->bcs + hscx, 0, hscx);
916}
917
918
919//==========================================================
920// Shared functions
921//==========================================================
922
923//----------------------------------------------------------
924// Main interrupt handler
925//----------------------------------------------------------
926void
927interrupt_ipacx(struct IsdnCardState *cs)
928{
929 u_char ista;
930
931 while ((ista = cs->readisac(cs, IPACX_ISTA))) {
932//#################################################
933// printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista);
934//#################################################
935 if (ista &0x80) bch_int(cs, 0); // B channel interrupts
936 if (ista &0x40) bch_int(cs, 1);
937
938 if (ista &0x01) dch_int(cs); // D channel
939 if (ista &0x10) cic_int(cs); // Layer 1 state
940 }
941}
942
943//----------------------------------------------------------
944// Clears chip interrupt status
945//----------------------------------------------------------
946static void __init
947clear_pending_ints(struct IsdnCardState *cs)
948{
949 int ista;
950
951 // all interrupts off
952 cs->writeisac(cs, IPACX_MASK, 0xff);
953 cs->writeisac(cs, IPACX_MASKD, 0xff);
954 cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff);
955 cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff);
956
957 ista = cs->readisac(cs, IPACX_ISTA);
958 if (ista &0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB);
959 if (ista &0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB);
960 if (ista &0x10) cs->readisac(cs, IPACX_CIR0);
961 if (ista &0x01) cs->readisac(cs, IPACX_ISTAD);
962}
963
964//----------------------------------------------------------
965// Does chip configuration work
966// Work to do depends on bit mask in part
967//----------------------------------------------------------
968void __init
969init_ipacx(struct IsdnCardState *cs, int part)
970{
971 if (part &1) { // initialise chip
972//##################################################
973// printk(KERN_INFO "init_ipacx(%x)\n", part);
974//##################################################
975 clear_pending_ints(cs);
976 bch_init(cs, 0);
977 bch_init(cs, 1);
978 dch_init(cs);
979 }
980 if (part &2) { // reenable all interrupts and start chip
981 cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK);
982 cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK);
983 cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK);
984 cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register
985
986 // reset HDLC Transmitters/receivers
987 cs->writeisac(cs, IPACX_CMDRD, 0x41);
988 cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41);
989 cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41);
990 ph_command(cs, IPACX_CMD_RES);
991 }
992}
993
994
995void __devinit
996setup_ipacx(struct IsdnCardState *cs)
997{
998 INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs);
999 cs->dbusytimer.function = (void *) dbusy_timer_handler;
1000 cs->dbusytimer.data = (long) cs;
1001 init_timer(&cs->dbusytimer);
1002}
1003//----------------- end of file -----------------------
1004
diff --git a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h
new file mode 100644
index 00000000000..e8a22e8f34b
--- /dev/null
+++ b/drivers/isdn/hisax/ipacx.h
@@ -0,0 +1,162 @@
1/*
2 *
3 * IPACX specific defines
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10/* All Registers original Siemens Spec */
11
12#ifndef INCLUDE_IPACX_H
13#define INCLUDE_IPACX_H
14
15/* D-channel registers */
16#define IPACX_RFIFOD 0x00 /* RD */
17#define IPACX_XFIFOD 0x00 /* WR */
18#define IPACX_ISTAD 0x20 /* RD */
19#define IPACX_MASKD 0x20 /* WR */
20#define IPACX_STARD 0x21 /* RD */
21#define IPACX_CMDRD 0x21 /* WR */
22#define IPACX_MODED 0x22 /* RD/WR */
23#define IPACX_EXMD1 0x23 /* RD/WR */
24#define IPACX_TIMR1 0x24 /* RD/WR */
25#define IPACX_SAP1 0x25 /* WR */
26#define IPACX_SAP2 0x26 /* WR */
27#define IPACX_RBCLD 0x26 /* RD */
28#define IPACX_RBCHD 0x27 /* RD */
29#define IPACX_TEI1 0x27 /* WR */
30#define IPACX_TEI2 0x28 /* WR */
31#define IPACX_RSTAD 0x28 /* RD */
32#define IPACX_TMD 0x29 /* RD/WR */
33#define IPACX_CIR0 0x2E /* RD */
34#define IPACX_CIX0 0x2E /* WR */
35#define IPACX_CIR1 0x2F /* RD */
36#define IPACX_CIX1 0x2F /* WR */
37
38/* Transceiver registers */
39#define IPACX_TR_CONF0 0x30 /* RD/WR */
40#define IPACX_TR_CONF1 0x31 /* RD/WR */
41#define IPACX_TR_CONF2 0x32 /* RD/WR */
42#define IPACX_TR_STA 0x33 /* RD */
43#define IPACX_TR_CMD 0x34 /* RD/WR */
44#define IPACX_SQRR1 0x35 /* RD */
45#define IPACX_SQXR1 0x35 /* WR */
46#define IPACX_SQRR2 0x36 /* RD */
47#define IPACX_SQXR2 0x36 /* WR */
48#define IPACX_SQRR3 0x37 /* RD */
49#define IPACX_SQXR3 0x37 /* WR */
50#define IPACX_ISTATR 0x38 /* RD */
51#define IPACX_MASKTR 0x39 /* RD/WR */
52#define IPACX_TR_MODE 0x3A /* RD/WR */
53#define IPACX_ACFG1 0x3C /* RD/WR */
54#define IPACX_ACFG2 0x3D /* RD/WR */
55#define IPACX_AOE 0x3E /* RD/WR */
56#define IPACX_ARX 0x3F /* RD */
57#define IPACX_ATX 0x3F /* WR */
58
59/* IOM: Timeslot, DPS, CDA */
60#define IPACX_CDA10 0x40 /* RD/WR */
61#define IPACX_CDA11 0x41 /* RD/WR */
62#define IPACX_CDA20 0x42 /* RD/WR */
63#define IPACX_CDA21 0x43 /* RD/WR */
64#define IPACX_CDA_TSDP10 0x44 /* RD/WR */
65#define IPACX_CDA_TSDP11 0x45 /* RD/WR */
66#define IPACX_CDA_TSDP20 0x46 /* RD/WR */
67#define IPACX_CDA_TSDP21 0x47 /* RD/WR */
68#define IPACX_BCHA_TSDP_BC1 0x48 /* RD/WR */
69#define IPACX_BCHA_TSDP_BC2 0x49 /* RD/WR */
70#define IPACX_BCHB_TSDP_BC1 0x4A /* RD/WR */
71#define IPACX_BCHB_TSDP_BC2 0x4B /* RD/WR */
72#define IPACX_TR_TSDP_BC1 0x4C /* RD/WR */
73#define IPACX_TR_TSDP_BC2 0x4D /* RD/WR */
74#define IPACX_CDA1_CR 0x4E /* RD/WR */
75#define IPACX_CDA2_CR 0x4F /* RD/WR */
76
77/* IOM: Contol, Sync transfer, Monitor */
78#define IPACX_TR_CR 0x50 /* RD/WR */
79#define IPACX_TRC_CR 0x50 /* RD/WR */
80#define IPACX_BCHA_CR 0x51 /* RD/WR */
81#define IPACX_BCHB_CR 0x52 /* RD/WR */
82#define IPACX_DCI_CR 0x53 /* RD/WR */
83#define IPACX_DCIC_CR 0x53 /* RD/WR */
84#define IPACX_MON_CR 0x54 /* RD/WR */
85#define IPACX_SDS1_CR 0x55 /* RD/WR */
86#define IPACX_SDS2_CR 0x56 /* RD/WR */
87#define IPACX_IOM_CR 0x57 /* RD/WR */
88#define IPACX_STI 0x58 /* RD */
89#define IPACX_ASTI 0x58 /* WR */
90#define IPACX_MSTI 0x59 /* RD/WR */
91#define IPACX_SDS_CONF 0x5A /* RD/WR */
92#define IPACX_MCDA 0x5B /* RD */
93#define IPACX_MOR 0x5C /* RD */
94#define IPACX_MOX 0x5C /* WR */
95#define IPACX_MOSR 0x5D /* RD */
96#define IPACX_MOCR 0x5E /* RD/WR */
97#define IPACX_MSTA 0x5F /* RD */
98#define IPACX_MCONF 0x5F /* WR */
99
100/* Interrupt and general registers */
101#define IPACX_ISTA 0x60 /* RD */
102#define IPACX_MASK 0x60 /* WR */
103#define IPACX_AUXI 0x61 /* RD */
104#define IPACX_AUXM 0x61 /* WR */
105#define IPACX_MODE1 0x62 /* RD/WR */
106#define IPACX_MODE2 0x63 /* RD/WR */
107#define IPACX_ID 0x64 /* RD */
108#define IPACX_SRES 0x64 /* WR */
109#define IPACX_TIMR2 0x65 /* RD/WR */
110
111/* B-channel registers */
112#define IPACX_OFF_B1 0x70
113#define IPACX_OFF_B2 0x80
114
115#define IPACX_ISTAB 0x00 /* RD */
116#define IPACX_MASKB 0x00 /* WR */
117#define IPACX_STARB 0x01 /* RD */
118#define IPACX_CMDRB 0x01 /* WR */
119#define IPACX_MODEB 0x02 /* RD/WR */
120#define IPACX_EXMB 0x03 /* RD/WR */
121#define IPACX_RAH1 0x05 /* WR */
122#define IPACX_RAH2 0x06 /* WR */
123#define IPACX_RBCLB 0x06 /* RD */
124#define IPACX_RBCHB 0x07 /* RD */
125#define IPACX_RAL1 0x07 /* WR */
126#define IPACX_RAL2 0x08 /* WR */
127#define IPACX_RSTAB 0x08 /* RD */
128#define IPACX_TMB 0x09 /* RD/WR */
129#define IPACX_RFIFOB 0x0A /*- RD */
130#define IPACX_XFIFOB 0x0A /*- WR */
131
132/* Layer 1 Commands */
133#define IPACX_CMD_TIM 0x0
134#define IPACX_CMD_RES 0x1
135#define IPACX_CMD_SSP 0x2
136#define IPACX_CMD_SCP 0x3
137#define IPACX_CMD_AR8 0x8
138#define IPACX_CMD_AR10 0x9
139#define IPACX_CMD_ARL 0xa
140#define IPACX_CMD_DI 0xf
141
142/* Layer 1 Indications */
143#define IPACX_IND_DR 0x0
144#define IPACX_IND_RES 0x1
145#define IPACX_IND_TMA 0x2
146#define IPACX_IND_SLD 0x3
147#define IPACX_IND_RSY 0x4
148#define IPACX_IND_DR6 0x5
149#define IPACX_IND_PU 0x7
150#define IPACX_IND_AR 0x8
151#define IPACX_IND_ARL 0xa
152#define IPACX_IND_CVR 0xb
153#define IPACX_IND_AI8 0xc
154#define IPACX_IND_AI10 0xd
155#define IPACX_IND_AIL 0xe
156#define IPACX_IND_DC 0xf
157
158extern void init_ipacx(struct IsdnCardState *, int);
159extern void interrupt_ipacx(struct IsdnCardState *);
160extern void setup_isac(struct IsdnCardState *);
161
162#endif
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
new file mode 100644
index 00000000000..20b94995295
--- /dev/null
+++ b/drivers/isdn/hisax/isac.c
@@ -0,0 +1,684 @@
1/* $Id: isac.c,v 1.31.2.3 2004/01/13 14:31:25 keil Exp $
2 *
3 * ISAC specific routines
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * For changes and modifications please read
12 * Documentation/isdn/HiSax.cert
13 *
14 */
15
16#include "hisax.h"
17#include "isac.h"
18#include "arcofi.h"
19#include "isdnl1.h"
20#include <linux/interrupt.h>
21#include <linux/init.h>
22
23#define DBUSY_TIMER_VALUE 80
24#define ARCOFI_USE 1
25
26static char *ISACVer[] __devinitdata =
27{"2086/2186 V1.1", "2085 B1", "2085 B2",
28 "2085 V2.3"};
29
30void
31ISACVersion(struct IsdnCardState *cs, char *s)
32{
33 int val;
34
35 val = cs->readisac(cs, ISAC_RBCH);
36 printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]);
37}
38
39static void
40ph_command(struct IsdnCardState *cs, unsigned int command)
41{
42 if (cs->debug & L1_DEB_ISAC)
43 debugl1(cs, "ph_command %x", command);
44 cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3);
45}
46
47
48static void
49isac_new_ph(struct IsdnCardState *cs)
50{
51 switch (cs->dc.isac.ph_state) {
52 case (ISAC_IND_RS):
53 case (ISAC_IND_EI):
54 ph_command(cs, ISAC_CMD_DUI);
55 l1_msg(cs, HW_RESET | INDICATION, NULL);
56 break;
57 case (ISAC_IND_DID):
58 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
59 break;
60 case (ISAC_IND_DR):
61 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
62 break;
63 case (ISAC_IND_PU):
64 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
65 break;
66 case (ISAC_IND_RSY):
67 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
68 break;
69 case (ISAC_IND_ARD):
70 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
71 break;
72 case (ISAC_IND_AI8):
73 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
74 break;
75 case (ISAC_IND_AI10):
76 l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
77 break;
78 default:
79 break;
80 }
81}
82
83static void
84isac_bh(struct IsdnCardState *cs)
85{
86 struct PStack *stptr;
87
88 if (!cs)
89 return;
90 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
91 if (cs->debug)
92 debugl1(cs, "D-Channel Busy cleared");
93 stptr = cs->stlist;
94 while (stptr != NULL) {
95 stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
96 stptr = stptr->next;
97 }
98 }
99 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
100 isac_new_ph(cs);
101 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
102 DChannel_proc_rcv(cs);
103 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
104 DChannel_proc_xmt(cs);
105#if ARCOFI_USE
106 if (!test_bit(HW_ARCOFI, &cs->HW_Flags))
107 return;
108 if (test_and_clear_bit(D_RX_MON1, &cs->event))
109 arcofi_fsm(cs, ARCOFI_RX_END, NULL);
110 if (test_and_clear_bit(D_TX_MON1, &cs->event))
111 arcofi_fsm(cs, ARCOFI_TX_END, NULL);
112#endif
113}
114
115void
116isac_empty_fifo(struct IsdnCardState *cs, int count)
117{
118 u_char *ptr;
119
120 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
121 debugl1(cs, "isac_empty_fifo");
122
123 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
124 if (cs->debug & L1_DEB_WARN)
125 debugl1(cs, "isac_empty_fifo overrun %d",
126 cs->rcvidx + count);
127 cs->writeisac(cs, ISAC_CMDR, 0x80);
128 cs->rcvidx = 0;
129 return;
130 }
131 ptr = cs->rcvbuf + cs->rcvidx;
132 cs->rcvidx += count;
133 cs->readisacfifo(cs, ptr, count);
134 cs->writeisac(cs, ISAC_CMDR, 0x80);
135 if (cs->debug & L1_DEB_ISAC_FIFO) {
136 char *t = cs->dlog;
137
138 t += sprintf(t, "isac_empty_fifo cnt %d", count);
139 QuickHex(t, ptr, count);
140 debugl1(cs, cs->dlog);
141 }
142}
143
144static void
145isac_fill_fifo(struct IsdnCardState *cs)
146{
147 int count, more;
148 u_char *ptr;
149
150 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
151 debugl1(cs, "isac_fill_fifo");
152
153 if (!cs->tx_skb)
154 return;
155
156 count = cs->tx_skb->len;
157 if (count <= 0)
158 return;
159
160 more = 0;
161 if (count > 32) {
162 more = !0;
163 count = 32;
164 }
165 ptr = cs->tx_skb->data;
166 skb_pull(cs->tx_skb, count);
167 cs->tx_cnt += count;
168 cs->writeisacfifo(cs, ptr, count);
169 cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa);
170 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
171 debugl1(cs, "isac_fill_fifo dbusytimer running");
172 del_timer(&cs->dbusytimer);
173 }
174 init_timer(&cs->dbusytimer);
175 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
176 add_timer(&cs->dbusytimer);
177 if (cs->debug & L1_DEB_ISAC_FIFO) {
178 char *t = cs->dlog;
179
180 t += sprintf(t, "isac_fill_fifo cnt %d", count);
181 QuickHex(t, ptr, count);
182 debugl1(cs, cs->dlog);
183 }
184}
185
186void
187isac_interrupt(struct IsdnCardState *cs, u_char val)
188{
189 u_char exval, v1;
190 struct sk_buff *skb;
191 unsigned int count;
192
193 if (cs->debug & L1_DEB_ISAC)
194 debugl1(cs, "ISAC interrupt %x", val);
195 if (val & 0x80) { /* RME */
196 exval = cs->readisac(cs, ISAC_RSTA);
197 if ((exval & 0x70) != 0x20) {
198 if (exval & 0x40) {
199 if (cs->debug & L1_DEB_WARN)
200 debugl1(cs, "ISAC RDO");
201#ifdef ERROR_STATISTIC
202 cs->err_rx++;
203#endif
204 }
205 if (!(exval & 0x20)) {
206 if (cs->debug & L1_DEB_WARN)
207 debugl1(cs, "ISAC CRC error");
208#ifdef ERROR_STATISTIC
209 cs->err_crc++;
210#endif
211 }
212 cs->writeisac(cs, ISAC_CMDR, 0x80);
213 } else {
214 count = cs->readisac(cs, ISAC_RBCL) & 0x1f;
215 if (count == 0)
216 count = 32;
217 isac_empty_fifo(cs, count);
218 if ((count = cs->rcvidx) > 0) {
219 cs->rcvidx = 0;
220 if (!(skb = alloc_skb(count, GFP_ATOMIC)))
221 printk(KERN_WARNING "HiSax: D receive out of memory\n");
222 else {
223 memcpy(skb_put(skb, count), cs->rcvbuf, count);
224 skb_queue_tail(&cs->rq, skb);
225 }
226 }
227 }
228 cs->rcvidx = 0;
229 schedule_event(cs, D_RCVBUFREADY);
230 }
231 if (val & 0x40) { /* RPF */
232 isac_empty_fifo(cs, 32);
233 }
234 if (val & 0x20) { /* RSC */
235 /* never */
236 if (cs->debug & L1_DEB_WARN)
237 debugl1(cs, "ISAC RSC interrupt");
238 }
239 if (val & 0x10) { /* XPR */
240 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
241 del_timer(&cs->dbusytimer);
242 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
243 schedule_event(cs, D_CLEARBUSY);
244 if (cs->tx_skb) {
245 if (cs->tx_skb->len) {
246 isac_fill_fifo(cs);
247 goto afterXPR;
248 } else {
249 dev_kfree_skb_irq(cs->tx_skb);
250 cs->tx_cnt = 0;
251 cs->tx_skb = NULL;
252 }
253 }
254 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
255 cs->tx_cnt = 0;
256 isac_fill_fifo(cs);
257 } else
258 schedule_event(cs, D_XMTBUFREADY);
259 }
260 afterXPR:
261 if (val & 0x04) { /* CISQ */
262 exval = cs->readisac(cs, ISAC_CIR0);
263 if (cs->debug & L1_DEB_ISAC)
264 debugl1(cs, "ISAC CIR0 %02X", exval );
265 if (exval & 2) {
266 cs->dc.isac.ph_state = (exval >> 2) & 0xf;
267 if (cs->debug & L1_DEB_ISAC)
268 debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
269 schedule_event(cs, D_L1STATECHANGE);
270 }
271 if (exval & 1) {
272 exval = cs->readisac(cs, ISAC_CIR1);
273 if (cs->debug & L1_DEB_ISAC)
274 debugl1(cs, "ISAC CIR1 %02X", exval );
275 }
276 }
277 if (val & 0x02) { /* SIN */
278 /* never */
279 if (cs->debug & L1_DEB_WARN)
280 debugl1(cs, "ISAC SIN interrupt");
281 }
282 if (val & 0x01) { /* EXI */
283 exval = cs->readisac(cs, ISAC_EXIR);
284 if (cs->debug & L1_DEB_WARN)
285 debugl1(cs, "ISAC EXIR %02x", exval);
286 if (exval & 0x80) { /* XMR */
287 debugl1(cs, "ISAC XMR");
288 printk(KERN_WARNING "HiSax: ISAC XMR\n");
289 }
290 if (exval & 0x40) { /* XDU */
291 debugl1(cs, "ISAC XDU");
292 printk(KERN_WARNING "HiSax: ISAC XDU\n");
293#ifdef ERROR_STATISTIC
294 cs->err_tx++;
295#endif
296 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
297 del_timer(&cs->dbusytimer);
298 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
299 schedule_event(cs, D_CLEARBUSY);
300 if (cs->tx_skb) { /* Restart frame */
301 skb_push(cs->tx_skb, cs->tx_cnt);
302 cs->tx_cnt = 0;
303 isac_fill_fifo(cs);
304 } else {
305 printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
306 debugl1(cs, "ISAC XDU no skb");
307 }
308 }
309 if (exval & 0x04) { /* MOS */
310 v1 = cs->readisac(cs, ISAC_MOSR);
311 if (cs->debug & L1_DEB_MONITOR)
312 debugl1(cs, "ISAC MOSR %02x", v1);
313#if ARCOFI_USE
314 if (v1 & 0x08) {
315 if (!cs->dc.isac.mon_rx) {
316 if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
317 if (cs->debug & L1_DEB_WARN)
318 debugl1(cs, "ISAC MON RX out of memory!");
319 cs->dc.isac.mocr &= 0xf0;
320 cs->dc.isac.mocr |= 0x0a;
321 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
322 goto afterMONR0;
323 } else
324 cs->dc.isac.mon_rxp = 0;
325 }
326 if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
327 cs->dc.isac.mocr &= 0xf0;
328 cs->dc.isac.mocr |= 0x0a;
329 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
330 cs->dc.isac.mon_rxp = 0;
331 if (cs->debug & L1_DEB_WARN)
332 debugl1(cs, "ISAC MON RX overflow!");
333 goto afterMONR0;
334 }
335 cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
336 if (cs->debug & L1_DEB_MONITOR)
337 debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
338 if (cs->dc.isac.mon_rxp == 1) {
339 cs->dc.isac.mocr |= 0x04;
340 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
341 }
342 }
343 afterMONR0:
344 if (v1 & 0x80) {
345 if (!cs->dc.isac.mon_rx) {
346 if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
347 if (cs->debug & L1_DEB_WARN)
348 debugl1(cs, "ISAC MON RX out of memory!");
349 cs->dc.isac.mocr &= 0x0f;
350 cs->dc.isac.mocr |= 0xa0;
351 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
352 goto afterMONR1;
353 } else
354 cs->dc.isac.mon_rxp = 0;
355 }
356 if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
357 cs->dc.isac.mocr &= 0x0f;
358 cs->dc.isac.mocr |= 0xa0;
359 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
360 cs->dc.isac.mon_rxp = 0;
361 if (cs->debug & L1_DEB_WARN)
362 debugl1(cs, "ISAC MON RX overflow!");
363 goto afterMONR1;
364 }
365 cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
366 if (cs->debug & L1_DEB_MONITOR)
367 debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
368 cs->dc.isac.mocr |= 0x40;
369 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
370 }
371 afterMONR1:
372 if (v1 & 0x04) {
373 cs->dc.isac.mocr &= 0xf0;
374 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
375 cs->dc.isac.mocr |= 0x0a;
376 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
377 schedule_event(cs, D_RX_MON0);
378 }
379 if (v1 & 0x40) {
380 cs->dc.isac.mocr &= 0x0f;
381 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
382 cs->dc.isac.mocr |= 0xa0;
383 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
384 schedule_event(cs, D_RX_MON1);
385 }
386 if (v1 & 0x02) {
387 if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc &&
388 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) &&
389 !(v1 & 0x08))) {
390 cs->dc.isac.mocr &= 0xf0;
391 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
392 cs->dc.isac.mocr |= 0x0a;
393 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
394 if (cs->dc.isac.mon_txc &&
395 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
396 schedule_event(cs, D_TX_MON0);
397 goto AfterMOX0;
398 }
399 if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
400 schedule_event(cs, D_TX_MON0);
401 goto AfterMOX0;
402 }
403 cs->writeisac(cs, ISAC_MOX0,
404 cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
405 if (cs->debug & L1_DEB_MONITOR)
406 debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
407 }
408 AfterMOX0:
409 if (v1 & 0x20) {
410 if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc &&
411 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) &&
412 !(v1 & 0x80))) {
413 cs->dc.isac.mocr &= 0x0f;
414 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
415 cs->dc.isac.mocr |= 0xa0;
416 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
417 if (cs->dc.isac.mon_txc &&
418 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
419 schedule_event(cs, D_TX_MON1);
420 goto AfterMOX1;
421 }
422 if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
423 schedule_event(cs, D_TX_MON1);
424 goto AfterMOX1;
425 }
426 cs->writeisac(cs, ISAC_MOX1,
427 cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
428 if (cs->debug & L1_DEB_MONITOR)
429 debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
430 }
431 AfterMOX1:;
432#endif
433 }
434 }
435}
436
437static void
438ISAC_l1hw(struct PStack *st, int pr, void *arg)
439{
440 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
441 struct sk_buff *skb = arg;
442 u_long flags;
443 int val;
444
445 switch (pr) {
446 case (PH_DATA |REQUEST):
447 if (cs->debug & DEB_DLOG_HEX)
448 LogFrame(cs, skb->data, skb->len);
449 if (cs->debug & DEB_DLOG_VERBOSE)
450 dlogframe(cs, skb, 0);
451 spin_lock_irqsave(&cs->lock, flags);
452 if (cs->tx_skb) {
453 skb_queue_tail(&cs->sq, skb);
454#ifdef L2FRAME_DEBUG /* psa */
455 if (cs->debug & L1_DEB_LAPD)
456 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
457#endif
458 } else {
459 cs->tx_skb = skb;
460 cs->tx_cnt = 0;
461#ifdef L2FRAME_DEBUG /* psa */
462 if (cs->debug & L1_DEB_LAPD)
463 Logl2Frame(cs, skb, "PH_DATA", 0);
464#endif
465 isac_fill_fifo(cs);
466 }
467 spin_unlock_irqrestore(&cs->lock, flags);
468 break;
469 case (PH_PULL |INDICATION):
470 spin_lock_irqsave(&cs->lock, flags);
471 if (cs->tx_skb) {
472 if (cs->debug & L1_DEB_WARN)
473 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
474 skb_queue_tail(&cs->sq, skb);
475 } else {
476 if (cs->debug & DEB_DLOG_HEX)
477 LogFrame(cs, skb->data, skb->len);
478 if (cs->debug & DEB_DLOG_VERBOSE)
479 dlogframe(cs, skb, 0);
480 cs->tx_skb = skb;
481 cs->tx_cnt = 0;
482#ifdef L2FRAME_DEBUG /* psa */
483 if (cs->debug & L1_DEB_LAPD)
484 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
485#endif
486 isac_fill_fifo(cs);
487 }
488 spin_unlock_irqrestore(&cs->lock, flags);
489 break;
490 case (PH_PULL | REQUEST):
491#ifdef L2FRAME_DEBUG /* psa */
492 if (cs->debug & L1_DEB_LAPD)
493 debugl1(cs, "-> PH_REQUEST_PULL");
494#endif
495 if (!cs->tx_skb) {
496 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
497 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
498 } else
499 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
500 break;
501 case (HW_RESET | REQUEST):
502 spin_lock_irqsave(&cs->lock, flags);
503 if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
504 (cs->dc.isac.ph_state == ISAC_IND_DR) ||
505 (cs->dc.isac.ph_state == ISAC_IND_RS))
506 ph_command(cs, ISAC_CMD_TIM);
507 else
508 ph_command(cs, ISAC_CMD_RS);
509 spin_unlock_irqrestore(&cs->lock, flags);
510 break;
511 case (HW_ENABLE | REQUEST):
512 spin_lock_irqsave(&cs->lock, flags);
513 ph_command(cs, ISAC_CMD_TIM);
514 spin_unlock_irqrestore(&cs->lock, flags);
515 break;
516 case (HW_INFO3 | REQUEST):
517 spin_lock_irqsave(&cs->lock, flags);
518 ph_command(cs, ISAC_CMD_AR8);
519 spin_unlock_irqrestore(&cs->lock, flags);
520 break;
521 case (HW_TESTLOOP | REQUEST):
522 spin_lock_irqsave(&cs->lock, flags);
523 val = 0;
524 if (1 & (long) arg)
525 val |= 0x0c;
526 if (2 & (long) arg)
527 val |= 0x3;
528 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
529 /* IOM 1 Mode */
530 if (!val) {
531 cs->writeisac(cs, ISAC_SPCR, 0xa);
532 cs->writeisac(cs, ISAC_ADF1, 0x2);
533 } else {
534 cs->writeisac(cs, ISAC_SPCR, val);
535 cs->writeisac(cs, ISAC_ADF1, 0xa);
536 }
537 } else {
538 /* IOM 2 Mode */
539 cs->writeisac(cs, ISAC_SPCR, val);
540 if (val)
541 cs->writeisac(cs, ISAC_ADF1, 0x8);
542 else
543 cs->writeisac(cs, ISAC_ADF1, 0x0);
544 }
545 spin_unlock_irqrestore(&cs->lock, flags);
546 break;
547 case (HW_DEACTIVATE | RESPONSE):
548 skb_queue_purge(&cs->rq);
549 skb_queue_purge(&cs->sq);
550 if (cs->tx_skb) {
551 dev_kfree_skb_any(cs->tx_skb);
552 cs->tx_skb = NULL;
553 }
554 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
555 del_timer(&cs->dbusytimer);
556 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
557 schedule_event(cs, D_CLEARBUSY);
558 break;
559 default:
560 if (cs->debug & L1_DEB_WARN)
561 debugl1(cs, "isac_l1hw unknown %04x", pr);
562 break;
563 }
564}
565
566void
567setstack_isac(struct PStack *st, struct IsdnCardState *cs)
568{
569 st->l1.l1hw = ISAC_l1hw;
570}
571
572void
573DC_Close_isac(struct IsdnCardState *cs) {
574 if (cs->dc.isac.mon_rx) {
575 kfree(cs->dc.isac.mon_rx);
576 cs->dc.isac.mon_rx = NULL;
577 }
578 if (cs->dc.isac.mon_tx) {
579 kfree(cs->dc.isac.mon_tx);
580 cs->dc.isac.mon_tx = NULL;
581 }
582}
583
584static void
585dbusy_timer_handler(struct IsdnCardState *cs)
586{
587 struct PStack *stptr;
588 int rbch, star;
589
590 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
591 rbch = cs->readisac(cs, ISAC_RBCH);
592 star = cs->readisac(cs, ISAC_STAR);
593 if (cs->debug)
594 debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
595 rbch, star);
596 if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */
597 test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
598 stptr = cs->stlist;
599 while (stptr != NULL) {
600 stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
601 stptr = stptr->next;
602 }
603 } else {
604 /* discard frame; reset transceiver */
605 test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
606 if (cs->tx_skb) {
607 dev_kfree_skb_any(cs->tx_skb);
608 cs->tx_cnt = 0;
609 cs->tx_skb = NULL;
610 } else {
611 printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
612 debugl1(cs, "D-Channel Busy no skb");
613 }
614 cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
615 cs->irq_func(cs->irq, cs, NULL);
616 }
617 }
618}
619
620void __devinit
621initisac(struct IsdnCardState *cs)
622{
623 cs->setstack_d = setstack_isac;
624 cs->DC_Close = DC_Close_isac;
625 cs->dc.isac.mon_tx = NULL;
626 cs->dc.isac.mon_rx = NULL;
627 cs->writeisac(cs, ISAC_MASK, 0xff);
628 cs->dc.isac.mocr = 0xaa;
629 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
630 /* IOM 1 Mode */
631 cs->writeisac(cs, ISAC_ADF2, 0x0);
632 cs->writeisac(cs, ISAC_SPCR, 0xa);
633 cs->writeisac(cs, ISAC_ADF1, 0x2);
634 cs->writeisac(cs, ISAC_STCR, 0x70);
635 cs->writeisac(cs, ISAC_MODE, 0xc9);
636 } else {
637 /* IOM 2 Mode */
638 if (!cs->dc.isac.adf2)
639 cs->dc.isac.adf2 = 0x80;
640 cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2);
641 cs->writeisac(cs, ISAC_SQXR, 0x2f);
642 cs->writeisac(cs, ISAC_SPCR, 0x00);
643 cs->writeisac(cs, ISAC_STCR, 0x70);
644 cs->writeisac(cs, ISAC_MODE, 0xc9);
645 cs->writeisac(cs, ISAC_TIMR, 0x00);
646 cs->writeisac(cs, ISAC_ADF1, 0x00);
647 }
648 ph_command(cs, ISAC_CMD_RS);
649 cs->writeisac(cs, ISAC_MASK, 0x0);
650}
651
652void __devinit
653clear_pending_isac_ints(struct IsdnCardState *cs)
654{
655 int val, eval;
656
657 val = cs->readisac(cs, ISAC_STAR);
658 debugl1(cs, "ISAC STAR %x", val);
659 val = cs->readisac(cs, ISAC_MODE);
660 debugl1(cs, "ISAC MODE %x", val);
661 val = cs->readisac(cs, ISAC_ADF2);
662 debugl1(cs, "ISAC ADF2 %x", val);
663 val = cs->readisac(cs, ISAC_ISTA);
664 debugl1(cs, "ISAC ISTA %x", val);
665 if (val & 0x01) {
666 eval = cs->readisac(cs, ISAC_EXIR);
667 debugl1(cs, "ISAC EXIR %x", eval);
668 }
669 val = cs->readisac(cs, ISAC_CIR0);
670 debugl1(cs, "ISAC CIR0 %x", val);
671 cs->dc.isac.ph_state = (val >> 2) & 0xf;
672 schedule_event(cs, D_L1STATECHANGE);
673 /* Disable all IRQ */
674 cs->writeisac(cs, ISAC_MASK, 0xFF);
675}
676
677void __devinit
678setup_isac(struct IsdnCardState *cs)
679{
680 INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs);
681 cs->dbusytimer.function = (void *) dbusy_timer_handler;
682 cs->dbusytimer.data = (long) cs;
683 init_timer(&cs->dbusytimer);
684}
diff --git a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h
new file mode 100644
index 00000000000..8f8331e4486
--- /dev/null
+++ b/drivers/isdn/hisax/isac.h
@@ -0,0 +1,70 @@
1/* $Id: isac.h,v 1.9.2.2 2004/01/12 22:52:27 keil Exp $
2 *
3 * ISAC specific defines
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13/* All Registers original Siemens Spec */
14
15#define ISAC_MASK 0x20
16#define ISAC_ISTA 0x20
17#define ISAC_STAR 0x21
18#define ISAC_CMDR 0x21
19#define ISAC_EXIR 0x24
20#define ISAC_ADF2 0x39
21#define ISAC_SPCR 0x30
22#define ISAC_ADF1 0x38
23#define ISAC_CIR0 0x31
24#define ISAC_CIX0 0x31
25#define ISAC_CIR1 0x33
26#define ISAC_CIX1 0x33
27#define ISAC_STCR 0x37
28#define ISAC_MODE 0x22
29#define ISAC_RSTA 0x27
30#define ISAC_RBCL 0x25
31#define ISAC_RBCH 0x2A
32#define ISAC_TIMR 0x23
33#define ISAC_SQXR 0x3b
34#define ISAC_MOSR 0x3a
35#define ISAC_MOCR 0x3a
36#define ISAC_MOR0 0x32
37#define ISAC_MOX0 0x32
38#define ISAC_MOR1 0x34
39#define ISAC_MOX1 0x34
40
41#define ISAC_RBCH_XAC 0x80
42
43#define ISAC_CMD_TIM 0x0
44#define ISAC_CMD_RS 0x1
45#define ISAC_CMD_SCZ 0x4
46#define ISAC_CMD_SSZ 0x2
47#define ISAC_CMD_AR8 0x8
48#define ISAC_CMD_AR10 0x9
49#define ISAC_CMD_ARL 0xA
50#define ISAC_CMD_DUI 0xF
51
52#define ISAC_IND_RS 0x1
53#define ISAC_IND_PU 0x7
54#define ISAC_IND_DR 0x0
55#define ISAC_IND_SD 0x2
56#define ISAC_IND_DIS 0x3
57#define ISAC_IND_EI 0x6
58#define ISAC_IND_RSY 0x4
59#define ISAC_IND_ARD 0x8
60#define ISAC_IND_TI 0xA
61#define ISAC_IND_ATI 0xB
62#define ISAC_IND_AI8 0xC
63#define ISAC_IND_AI10 0xD
64#define ISAC_IND_DID 0xF
65
66extern void ISACVersion(struct IsdnCardState *, char *);
67extern void setup_isac(struct IsdnCardState *);
68extern void initisac(struct IsdnCardState *);
69extern void isac_interrupt(struct IsdnCardState *, u_char);
70extern void clear_pending_isac_ints(struct IsdnCardState *);
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
new file mode 100644
index 00000000000..ee081321efb
--- /dev/null
+++ b/drivers/isdn/hisax/isar.c
@@ -0,0 +1,1909 @@
1/* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $
2 *
3 * isar.c ISAR (Siemens PSB 7110) specific routines
4 *
5 * Author Karsten Keil (keil@isdn4linux.de)
6 *
7 * This file is (c) under GNU General Public License
8 *
9 */
10
11#include <linux/init.h>
12#include "hisax.h"
13#include "isar.h"
14#include "isdnl1.h"
15#include <linux/interrupt.h>
16
17#define DBG_LOADFIRM 0
18#define DUMP_MBOXFRAME 2
19
20#define DLE 0x10
21#define ETX 0x03
22
23#define FAXMODCNT 13
24const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
25static u_int modmask = 0x1fff;
26static int frm_extra_delay = 2;
27static int para_TOA = 6;
28const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
29
30void isar_setup(struct IsdnCardState *cs);
31static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
32static void ll_deliver_faxstat(struct BCState *bcs, u_char status);
33
34static inline int
35waitforHIA(struct IsdnCardState *cs, int timeout)
36{
37
38 while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) {
39 udelay(1);
40 timeout--;
41 }
42 if (!timeout)
43 printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n");
44 return(timeout);
45}
46
47
48int
49sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
50 u_char *msg)
51{
52 int i;
53
54 if (!waitforHIA(cs, 4000))
55 return(0);
56#if DUMP_MBOXFRAME
57 if (cs->debug & L1_DEB_HSCX)
58 debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len);
59#endif
60 cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg);
61 cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len);
62 cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0);
63 if (msg && len) {
64 cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]);
65 for (i=1; i<len; i++)
66 cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]);
67#if DUMP_MBOXFRAME>1
68 if (cs->debug & L1_DEB_HSCX_FIFO) {
69 char tmp[256], *t;
70
71 i = len;
72 while (i>0) {
73 t = tmp;
74 t += sprintf(t, "sendmbox cnt %d", len);
75 QuickHex(t, &msg[len-i], (i>64) ? 64:i);
76 debugl1(cs, tmp);
77 i -= 64;
78 }
79 }
80#endif
81 }
82 cs->BC_Write_Reg(cs, 1, ISAR_HIS, his);
83 waitforHIA(cs, 10000);
84 return(1);
85}
86
87/* Call only with IRQ disabled !!! */
88inline void
89rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
90{
91 int i;
92
93 cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0);
94 if (msg && ireg->clsb) {
95 msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX);
96 for (i=1; i < ireg->clsb; i++)
97 msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX);
98#if DUMP_MBOXFRAME>1
99 if (cs->debug & L1_DEB_HSCX_FIFO) {
100 char tmp[256], *t;
101
102 i = ireg->clsb;
103 while (i>0) {
104 t = tmp;
105 t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
106 QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i);
107 debugl1(cs, tmp);
108 i -= 64;
109 }
110 }
111#endif
112 }
113 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
114}
115
116/* Call only with IRQ disabled !!! */
117inline void
118get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
119{
120 ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);
121 ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H);
122 ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);
123#if DUMP_MBOXFRAME
124 if (cs->debug & L1_DEB_HSCX)
125 debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
126 ireg->clsb);
127#endif
128}
129
130int
131waitrecmsg(struct IsdnCardState *cs, u_char *len,
132 u_char *msg, int maxdelay)
133{
134 int timeout = 0;
135 struct isar_reg *ir = cs->bcs[0].hw.isar.reg;
136
137
138 while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
139 (timeout++ < maxdelay))
140 udelay(1);
141 if (timeout >= maxdelay) {
142 printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");
143 return(0);
144 }
145 get_irq_infos(cs, ir);
146 rcv_mbox(cs, ir, msg);
147 *len = ir->clsb;
148 return(1);
149}
150
151int
152ISARVersion(struct IsdnCardState *cs, char *s)
153{
154 int ver;
155 u_char msg[] = ISAR_MSG_HWVER;
156 u_char tmp[64];
157 u_char len;
158 u_long flags;
159 int debug;
160
161 cs->cardmsg(cs, CARD_RESET, NULL);
162 spin_lock_irqsave(&cs->lock, flags);
163 /* disable ISAR IRQ */
164 cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
165 debug = cs->debug;
166 cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
167 if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) {
168 spin_unlock_irqrestore(&cs->lock, flags);
169 return(-1);
170 }
171 if (!waitrecmsg(cs, &len, tmp, 100000)) {
172 spin_unlock_irqrestore(&cs->lock, flags);
173 return(-2);
174 }
175 cs->debug = debug;
176 if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) {
177 if (len == 1) {
178 ver = tmp[0] & 0xf;
179 printk(KERN_INFO "%s ISAR version %d\n", s, ver);
180 } else
181 ver = -3;
182 } else
183 ver = -4;
184 spin_unlock_irqrestore(&cs->lock, flags);
185 return(ver);
186}
187
188int
189isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf)
190{
191 int ret, size, cnt, debug;
192 u_char len, nom, noc;
193 u_short sadr, left, *sp;
194 u_char __user *p = buf;
195 u_char *msg, *tmpmsg, *mp, tmp[64];
196 u_long flags;
197 struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
198
199 struct {u_short sadr;
200 u_short len;
201 u_short d_key;
202 } blk_head;
203
204#define BLK_HEAD_SIZE 6
205 if (1 != (ret = ISARVersion(cs, "Testing"))) {
206 printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret);
207 return(1);
208 }
209 debug = cs->debug;
210#if DBG_LOADFIRM<2
211 cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
212#endif
213
214 if ((ret = copy_from_user(&size, p, sizeof(int)))) {
215 printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
216 return ret;
217 }
218 p += sizeof(int);
219 printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
220 cnt = 0;
221 /* disable ISAR IRQ */
222 cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
223 if (!(msg = kmalloc(256, GFP_KERNEL))) {
224 printk(KERN_ERR"isar_load_firmware no buffer\n");
225 return (1);
226 }
227 if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) {
228 printk(KERN_ERR"isar_load_firmware no tmp buffer\n");
229 kfree(msg);
230 return (1);
231 }
232 spin_lock_irqsave(&cs->lock, flags);
233 /* disable ISAR IRQ */
234 cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
235 spin_unlock_irqrestore(&cs->lock, flags);
236 while (cnt < size) {
237 if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) {
238 printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
239 goto reterror;
240 }
241#ifdef __BIG_ENDIAN
242 sadr = (blk_head.sadr & 0xff)*256 + blk_head.sadr/256;
243 blk_head.sadr = sadr;
244 sadr = (blk_head.len & 0xff)*256 + blk_head.len/256;
245 blk_head.len = sadr;
246 sadr = (blk_head.d_key & 0xff)*256 + blk_head.d_key/256;
247 blk_head.d_key = sadr;
248#endif /* __BIG_ENDIAN */
249 cnt += BLK_HEAD_SIZE;
250 p += BLK_HEAD_SIZE;
251 printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n",
252 blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);
253 sadr = blk_head.sadr;
254 left = blk_head.len;
255 spin_lock_irqsave(&cs->lock, flags);
256 if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) {
257 printk(KERN_ERR"isar sendmsg dkey failed\n");
258 ret = 1;goto reterr_unlock;
259 }
260 if (!waitrecmsg(cs, &len, tmp, 100000)) {
261 printk(KERN_ERR"isar waitrecmsg dkey failed\n");
262 ret = 1;goto reterr_unlock;
263 }
264 if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) {
265 printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",
266 ireg->iis, ireg->cmsb, len);
267 ret = 1;goto reterr_unlock;
268 }
269 spin_unlock_irqrestore(&cs->lock, flags);
270 while (left>0) {
271 if (left > 126)
272 noc = 126;
273 else
274 noc = left;
275 nom = 2*noc;
276 mp = msg;
277 *mp++ = sadr / 256;
278 *mp++ = sadr % 256;
279 left -= noc;
280 *mp++ = noc;
281 if ((ret = copy_from_user(tmpmsg, p, nom))) {
282 printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
283 goto reterror;
284 }
285 p += nom;
286 cnt += nom;
287 nom += 3;
288 sp = (u_short *)tmpmsg;
289#if DBG_LOADFIRM
290 printk(KERN_DEBUG"isar: load %3d words at %04x left %d\n",
291 noc, sadr, left);
292#endif
293 sadr += noc;
294 while(noc) {
295#ifdef __BIG_ENDIAN
296 *mp++ = *sp % 256;
297 *mp++ = *sp / 256;
298#else
299 *mp++ = *sp / 256;
300 *mp++ = *sp % 256;
301#endif /* __BIG_ENDIAN */
302 sp++;
303 noc--;
304 }
305 spin_lock_irqsave(&cs->lock, flags);
306 if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) {
307 printk(KERN_ERR"isar sendmsg prog failed\n");
308 ret = 1;goto reterr_unlock;
309 }
310 if (!waitrecmsg(cs, &len, tmp, 100000)) {
311 printk(KERN_ERR"isar waitrecmsg prog failed\n");
312 ret = 1;goto reterr_unlock;
313 }
314 if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) {
315 printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",
316 ireg->iis, ireg->cmsb, len);
317 ret = 1;goto reterr_unlock;
318 }
319 spin_unlock_irqrestore(&cs->lock, flags);
320 }
321 printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
322 blk_head.len);
323 }
324 /* 10ms delay */
325 cnt = 10;
326 while (cnt--)
327 udelay(1000);
328 msg[0] = 0xff;
329 msg[1] = 0xfe;
330 ireg->bstat = 0;
331 spin_lock_irqsave(&cs->lock, flags);
332 if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) {
333 printk(KERN_ERR"isar sendmsg start dsp failed\n");
334 ret = 1;goto reterr_unlock;
335 }
336 if (!waitrecmsg(cs, &len, tmp, 100000)) {
337 printk(KERN_ERR"isar waitrecmsg start dsp failed\n");
338 ret = 1;goto reterr_unlock;
339 }
340 if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) {
341 printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",
342 ireg->iis, ireg->cmsb, len);
343 ret = 1;goto reterr_unlock;
344 } else
345 printk(KERN_DEBUG"isar start dsp success\n");
346 /* NORMAL mode entered */
347 /* Enable IRQs of ISAR */
348 cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);
349 spin_unlock_irqrestore(&cs->lock, flags);
350 cnt = 1000; /* max 1s */
351 while ((!ireg->bstat) && cnt) {
352 udelay(1000);
353 cnt--;
354 }
355 if (!cnt) {
356 printk(KERN_ERR"isar no general status event received\n");
357 ret = 1;goto reterror;
358 } else {
359 printk(KERN_DEBUG"isar general status event %x\n",
360 ireg->bstat);
361 }
362 /* 10ms delay */
363 cnt = 10;
364 while (cnt--)
365 udelay(1000);
366 spin_lock_irqsave(&cs->lock, flags);
367 ireg->iis = 0;
368 if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
369 printk(KERN_ERR"isar sendmsg self tst failed\n");
370 ret = 1;goto reterr_unlock;
371 }
372 cnt = 10000; /* max 100 ms */
373 spin_unlock_irqrestore(&cs->lock, flags);
374 while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
375 udelay(10);
376 cnt--;
377 }
378 udelay(1000);
379 if (!cnt) {
380 printk(KERN_ERR"isar no self tst response\n");
381 ret = 1;goto reterror;
382 }
383 if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)
384 && (ireg->par[0] == 0)) {
385 printk(KERN_DEBUG"isar selftest OK\n");
386 } else {
387 printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",
388 ireg->cmsb, ireg->clsb, ireg->par[0]);
389 ret = 1;goto reterror;
390 }
391 spin_lock_irqsave(&cs->lock, flags);
392 ireg->iis = 0;
393 if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
394 printk(KERN_ERR"isar RQST SVN failed\n");
395 ret = 1;goto reterr_unlock;
396 }
397 spin_unlock_irqrestore(&cs->lock, flags);
398 cnt = 30000; /* max 300 ms */
399 while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
400 udelay(10);
401 cnt--;
402 }
403 udelay(1000);
404 if (!cnt) {
405 printk(KERN_ERR"isar no SVN response\n");
406 ret = 1;goto reterror;
407 } else {
408 if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1))
409 printk(KERN_DEBUG"isar software version %#x\n",
410 ireg->par[0]);
411 else {
412 printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",
413 ireg->cmsb, ireg->clsb, cnt);
414 ret = 1;goto reterror;
415 }
416 }
417 spin_lock_irqsave(&cs->lock, flags);
418 cs->debug = debug;
419 isar_setup(cs);
420
421 ret = 0;
422reterr_unlock:
423 spin_unlock_irqrestore(&cs->lock, flags);
424reterror:
425 cs->debug = debug;
426 if (ret)
427 /* disable ISAR IRQ */
428 cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
429 kfree(msg);
430 kfree(tmpmsg);
431 return(ret);
432}
433
434extern void BChannel_bh(struct BCState *);
435#define B_LL_NOCARRIER 8
436#define B_LL_CONNECT 9
437#define B_LL_OK 10
438
439static void
440isar_bh(struct BCState *bcs)
441{
442 BChannel_bh(bcs);
443 if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event))
444 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR);
445 if (test_and_clear_bit(B_LL_CONNECT, &bcs->event))
446 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
447 if (test_and_clear_bit(B_LL_OK, &bcs->event))
448 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK);
449}
450
451static void
452send_DLE_ETX(struct BCState *bcs)
453{
454 u_char dleetx[2] = {DLE,ETX};
455 struct sk_buff *skb;
456
457 if ((skb = dev_alloc_skb(2))) {
458 memcpy(skb_put(skb, 2), dleetx, 2);
459 skb_queue_tail(&bcs->rqueue, skb);
460 schedule_event(bcs, B_RCVBUFREADY);
461 } else {
462 printk(KERN_WARNING "HiSax: skb out of memory\n");
463 }
464}
465
466static inline int
467dle_count(unsigned char *buf, int len)
468{
469 int count = 0;
470
471 while (len--)
472 if (*buf++ == DLE)
473 count++;
474 return count;
475}
476
477static inline void
478insert_dle(unsigned char *dest, unsigned char *src, int count) {
479 /* <DLE> in input stream have to be flagged as <DLE><DLE> */
480 while (count--) {
481 *dest++ = *src;
482 if (*src++ == DLE)
483 *dest++ = DLE;
484 }
485}
486
487static void
488isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
489{
490 u_char *ptr;
491 struct sk_buff *skb;
492 struct isar_reg *ireg = bcs->hw.isar.reg;
493
494 if (!ireg->clsb) {
495 debugl1(cs, "isar zero len frame");
496 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
497 return;
498 }
499 switch (bcs->mode) {
500 case L1_MODE_NULL:
501 debugl1(cs, "isar mode 0 spurious IIS_RDATA %x/%x/%x",
502 ireg->iis, ireg->cmsb, ireg->clsb);
503 printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n",
504 ireg->iis, ireg->cmsb, ireg->clsb);
505 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
506 break;
507 case L1_MODE_TRANS:
508 case L1_MODE_V32:
509 if ((skb = dev_alloc_skb(ireg->clsb))) {
510 rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));
511 skb_queue_tail(&bcs->rqueue, skb);
512 schedule_event(bcs, B_RCVBUFREADY);
513 } else {
514 printk(KERN_WARNING "HiSax: skb out of memory\n");
515 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
516 }
517 break;
518 case L1_MODE_HDLC:
519 if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
520 if (cs->debug & L1_DEB_WARN)
521 debugl1(cs, "isar_rcv_frame: incoming packet too large");
522 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
523 bcs->hw.isar.rcvidx = 0;
524 } else if (ireg->cmsb & HDLC_ERROR) {
525 if (cs->debug & L1_DEB_WARN)
526 debugl1(cs, "isar frame error %x len %d",
527 ireg->cmsb, ireg->clsb);
528#ifdef ERROR_STATISTIC
529 if (ireg->cmsb & HDLC_ERR_RER)
530 bcs->err_inv++;
531 if (ireg->cmsb & HDLC_ERR_CER)
532 bcs->err_crc++;
533#endif
534 bcs->hw.isar.rcvidx = 0;
535 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
536 } else {
537 if (ireg->cmsb & HDLC_FSD)
538 bcs->hw.isar.rcvidx = 0;
539 ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
540 bcs->hw.isar.rcvidx += ireg->clsb;
541 rcv_mbox(cs, ireg, ptr);
542 if (ireg->cmsb & HDLC_FED) {
543 if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
544 if (cs->debug & L1_DEB_WARN)
545 debugl1(cs, "isar frame to short %d",
546 bcs->hw.isar.rcvidx);
547 } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2))) {
548 printk(KERN_WARNING "ISAR: receive out of memory\n");
549 } else {
550 memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
551 bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
552 skb_queue_tail(&bcs->rqueue, skb);
553 schedule_event(bcs, B_RCVBUFREADY);
554 }
555 bcs->hw.isar.rcvidx = 0;
556 }
557 }
558 break;
559 case L1_MODE_FAX:
560 if (bcs->hw.isar.state != STFAX_ACTIV) {
561 if (cs->debug & L1_DEB_WARN)
562 debugl1(cs, "isar_rcv_frame: not ACTIV");
563 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
564 bcs->hw.isar.rcvidx = 0;
565 break;
566 }
567 if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
568 rcv_mbox(cs, ireg, bcs->hw.isar.rcvbuf);
569 bcs->hw.isar.rcvidx = ireg->clsb +
570 dle_count(bcs->hw.isar.rcvbuf, ireg->clsb);
571 if (cs->debug & L1_DEB_HSCX)
572 debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)",
573 ireg->clsb, bcs->hw.isar.rcvidx);
574 if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
575 insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx),
576 bcs->hw.isar.rcvbuf, ireg->clsb);
577 skb_queue_tail(&bcs->rqueue, skb);
578 schedule_event(bcs, B_RCVBUFREADY);
579 if (ireg->cmsb & SART_NMD) { /* ABORT */
580 if (cs->debug & L1_DEB_WARN)
581 debugl1(cs, "isar_rcv_frame: no more data");
582 bcs->hw.isar.rcvidx = 0;
583 send_DLE_ETX(bcs);
584 sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
585 ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
586 0, NULL);
587 bcs->hw.isar.state = STFAX_ESCAPE;
588 schedule_event(bcs, B_LL_NOCARRIER);
589 }
590 } else {
591 printk(KERN_WARNING "HiSax: skb out of memory\n");
592 }
593 break;
594 }
595 if (bcs->hw.isar.cmd != PCTRL_CMD_FRH) {
596 if (cs->debug & L1_DEB_WARN)
597 debugl1(cs, "isar_rcv_frame: unknown fax mode %x",
598 bcs->hw.isar.cmd);
599 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
600 bcs->hw.isar.rcvidx = 0;
601 break;
602 }
603 /* PCTRL_CMD_FRH */
604 if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
605 if (cs->debug & L1_DEB_WARN)
606 debugl1(cs, "isar_rcv_frame: incoming packet too large");
607 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
608 bcs->hw.isar.rcvidx = 0;
609 } else if (ireg->cmsb & HDLC_ERROR) {
610 if (cs->debug & L1_DEB_WARN)
611 debugl1(cs, "isar frame error %x len %d",
612 ireg->cmsb, ireg->clsb);
613 bcs->hw.isar.rcvidx = 0;
614 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
615 } else {
616 if (ireg->cmsb & HDLC_FSD) {
617 bcs->hw.isar.rcvidx = 0;
618 }
619 ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
620 bcs->hw.isar.rcvidx += ireg->clsb;
621 rcv_mbox(cs, ireg, ptr);
622 if (ireg->cmsb & HDLC_FED) {
623 int len = bcs->hw.isar.rcvidx +
624 dle_count(bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx);
625 if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
626 if (cs->debug & L1_DEB_WARN)
627 debugl1(cs, "isar frame to short %d",
628 bcs->hw.isar.rcvidx);
629 printk(KERN_WARNING "ISAR: frame to short %d\n",
630 bcs->hw.isar.rcvidx);
631 } else if (!(skb = dev_alloc_skb(len))) {
632 printk(KERN_WARNING "ISAR: receive out of memory\n");
633 } else {
634 insert_dle((u_char *)skb_put(skb, len),
635 bcs->hw.isar.rcvbuf,
636 bcs->hw.isar.rcvidx);
637 skb_queue_tail(&bcs->rqueue, skb);
638 schedule_event(bcs, B_RCVBUFREADY);
639 send_DLE_ETX(bcs);
640 schedule_event(bcs, B_LL_OK);
641 test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
642 }
643 bcs->hw.isar.rcvidx = 0;
644 }
645 }
646 if (ireg->cmsb & SART_NMD) { /* ABORT */
647 if (cs->debug & L1_DEB_WARN)
648 debugl1(cs, "isar_rcv_frame: no more data");
649 bcs->hw.isar.rcvidx = 0;
650 sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
651 ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
652 bcs->hw.isar.state = STFAX_ESCAPE;
653 if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) {
654 send_DLE_ETX(bcs);
655 schedule_event(bcs, B_LL_NOCARRIER);
656 }
657 }
658 break;
659 default:
660 printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode);
661 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
662 break;
663 }
664}
665
666void
667isar_fill_fifo(struct BCState *bcs)
668{
669 struct IsdnCardState *cs = bcs->cs;
670 int count;
671 u_char msb;
672 u_char *ptr;
673
674 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
675 debugl1(cs, "isar_fill_fifo");
676 if (!bcs->tx_skb)
677 return;
678 if (bcs->tx_skb->len <= 0)
679 return;
680 if (!(bcs->hw.isar.reg->bstat &
681 (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
682 return;
683 if (bcs->tx_skb->len > bcs->hw.isar.mml) {
684 msb = 0;
685 count = bcs->hw.isar.mml;
686 } else {
687 count = bcs->tx_skb->len;
688 msb = HDLC_FED;
689 }
690 ptr = bcs->tx_skb->data;
691 if (!bcs->hw.isar.txcnt) {
692 msb |= HDLC_FST;
693 if ((bcs->mode == L1_MODE_FAX) &&
694 (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) {
695 if (bcs->tx_skb->len > 1) {
696 if ((ptr[0]== 0xff) && (ptr[1] == 0x13))
697 /* last frame */
698 test_and_set_bit(BC_FLG_LASTDATA,
699 &bcs->Flag);
700 }
701 }
702 }
703 skb_pull(bcs->tx_skb, count);
704 bcs->tx_cnt -= count;
705 bcs->hw.isar.txcnt += count;
706 switch (bcs->mode) {
707 case L1_MODE_NULL:
708 printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
709 break;
710 case L1_MODE_TRANS:
711 case L1_MODE_V32:
712 sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
713 0, count, ptr);
714 break;
715 case L1_MODE_HDLC:
716 sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
717 msb, count, ptr);
718 break;
719 case L1_MODE_FAX:
720 if (bcs->hw.isar.state != STFAX_ACTIV) {
721 if (cs->debug & L1_DEB_WARN)
722 debugl1(cs, "isar_fill_fifo: not ACTIV");
723 } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
724 sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
725 msb, count, ptr);
726 } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) {
727 sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
728 0, count, ptr);
729 } else {
730 if (cs->debug & L1_DEB_WARN)
731 debugl1(cs, "isar_fill_fifo: not FTH/FTM");
732 }
733 break;
734 default:
735 if (cs->debug)
736 debugl1(cs, "isar_fill_fifo mode(%x) error", bcs->mode);
737 printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode);
738 break;
739 }
740}
741
742inline
743struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
744{
745 if ((!dpath) || (dpath == 3))
746 return(NULL);
747 if (cs->bcs[0].hw.isar.dpath == dpath)
748 return(&cs->bcs[0]);
749 if (cs->bcs[1].hw.isar.dpath == dpath)
750 return(&cs->bcs[1]);
751 return(NULL);
752}
753
754void
755send_frames(struct BCState *bcs)
756{
757 if (bcs->tx_skb) {
758 if (bcs->tx_skb->len) {
759 isar_fill_fifo(bcs);
760 return;
761 } else {
762 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
763 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
764 u_long flags;
765 spin_lock_irqsave(&bcs->aclock, flags);
766 bcs->ackcnt += bcs->hw.isar.txcnt;
767 spin_unlock_irqrestore(&bcs->aclock, flags);
768 schedule_event(bcs, B_ACKPENDING);
769 }
770 if (bcs->mode == L1_MODE_FAX) {
771 if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
772 if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
773 test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag);
774 }
775 } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) {
776 if (test_bit(BC_FLG_DLEETX, &bcs->Flag)) {
777 test_and_set_bit(BC_FLG_LASTDATA, &bcs->Flag);
778 test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag);
779 }
780 }
781 }
782 dev_kfree_skb_any(bcs->tx_skb);
783 bcs->hw.isar.txcnt = 0;
784 bcs->tx_skb = NULL;
785 }
786 }
787 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
788 bcs->hw.isar.txcnt = 0;
789 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
790 isar_fill_fifo(bcs);
791 } else {
792 if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) {
793 if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
794 if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) {
795 u_char dummy = 0;
796 sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) |
797 ISAR_HIS_SDATA, 0x01, 1, &dummy);
798 }
799 test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag);
800 } else {
801 schedule_event(bcs, B_LL_CONNECT);
802 }
803 }
804 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
805 schedule_event(bcs, B_XMTBUFREADY);
806 }
807}
808
809inline void
810check_send(struct IsdnCardState *cs, u_char rdm)
811{
812 struct BCState *bcs;
813
814 if (rdm & BSTAT_RDM1) {
815 if ((bcs = sel_bcs_isar(cs, 1))) {
816 if (bcs->mode) {
817 send_frames(bcs);
818 }
819 }
820 }
821 if (rdm & BSTAT_RDM2) {
822 if ((bcs = sel_bcs_isar(cs, 2))) {
823 if (bcs->mode) {
824 send_frames(bcs);
825 }
826 }
827 }
828
829}
830
831const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
832 "300", "600", "1200", "2400", "4800", "7200",
833 "9600nt", "9600t", "12000", "14400", "WRONG"};
834const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
835 "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
836
837static void
838isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) {
839 struct IsdnCardState *cs = bcs->cs;
840 u_char ril = ireg->par[0];
841 u_char rim;
842
843 if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags))
844 return;
845 if (ril > 14) {
846 if (cs->debug & L1_DEB_WARN)
847 debugl1(cs, "wrong pstrsp ril=%d",ril);
848 ril = 15;
849 }
850 switch(ireg->par[1]) {
851 case 0:
852 rim = 0;
853 break;
854 case 0x20:
855 rim = 2;
856 break;
857 case 0x40:
858 rim = 3;
859 break;
860 case 0x41:
861 rim = 4;
862 break;
863 case 0x51:
864 rim = 5;
865 break;
866 case 0x61:
867 rim = 6;
868 break;
869 case 0x71:
870 rim = 7;
871 break;
872 case 0x82:
873 rim = 8;
874 break;
875 case 0x92:
876 rim = 9;
877 break;
878 case 0xa2:
879 rim = 10;
880 break;
881 default:
882 rim = 1;
883 break;
884 }
885 sprintf(bcs->hw.isar.conmsg,"%s %s", dmril[ril], dmrim[rim]);
886 bcs->conmsg = bcs->hw.isar.conmsg;
887 if (cs->debug & L1_DEB_HSCX)
888 debugl1(cs, "pump strsp %s", bcs->conmsg);
889}
890
891static void
892isar_pump_statev_modem(struct BCState *bcs, u_char devt) {
893 struct IsdnCardState *cs = bcs->cs;
894 u_char dps = SET_DPS(bcs->hw.isar.dpath);
895
896 switch(devt) {
897 case PSEV_10MS_TIMER:
898 if (cs->debug & L1_DEB_HSCX)
899 debugl1(cs, "pump stev TIMER");
900 break;
901 case PSEV_CON_ON:
902 if (cs->debug & L1_DEB_HSCX)
903 debugl1(cs, "pump stev CONNECT");
904 l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL);
905 break;
906 case PSEV_CON_OFF:
907 if (cs->debug & L1_DEB_HSCX)
908 debugl1(cs, "pump stev NO CONNECT");
909 sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
910 l1_msg_b(bcs->st, PH_DEACTIVATE | REQUEST, NULL);
911 break;
912 case PSEV_V24_OFF:
913 if (cs->debug & L1_DEB_HSCX)
914 debugl1(cs, "pump stev V24 OFF");
915 break;
916 case PSEV_CTS_ON:
917 if (cs->debug & L1_DEB_HSCX)
918 debugl1(cs, "pump stev CTS ON");
919 break;
920 case PSEV_CTS_OFF:
921 if (cs->debug & L1_DEB_HSCX)
922 debugl1(cs, "pump stev CTS OFF");
923 break;
924 case PSEV_DCD_ON:
925 if (cs->debug & L1_DEB_HSCX)
926 debugl1(cs, "pump stev CARRIER ON");
927 test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags);
928 sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
929 break;
930 case PSEV_DCD_OFF:
931 if (cs->debug & L1_DEB_HSCX)
932 debugl1(cs, "pump stev CARRIER OFF");
933 break;
934 case PSEV_DSR_ON:
935 if (cs->debug & L1_DEB_HSCX)
936 debugl1(cs, "pump stev DSR ON");
937 break;
938 case PSEV_DSR_OFF:
939 if (cs->debug & L1_DEB_HSCX)
940 debugl1(cs, "pump stev DSR_OFF");
941 break;
942 case PSEV_REM_RET:
943 if (cs->debug & L1_DEB_HSCX)
944 debugl1(cs, "pump stev REMOTE RETRAIN");
945 break;
946 case PSEV_REM_REN:
947 if (cs->debug & L1_DEB_HSCX)
948 debugl1(cs, "pump stev REMOTE RENEGOTIATE");
949 break;
950 case PSEV_GSTN_CLR:
951 if (cs->debug & L1_DEB_HSCX)
952 debugl1(cs, "pump stev GSTN CLEAR", devt);
953 break;
954 default:
955 if (cs->debug & L1_DEB_HSCX)
956 debugl1(cs, "unknown pump stev %x", devt);
957 break;
958 }
959}
960
961static void
962ll_deliver_faxstat(struct BCState *bcs, u_char status)
963{
964 isdn_ctrl ic;
965 struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
966
967 if (bcs->cs->debug & L1_DEB_HSCX)
968 debugl1(bcs->cs, "HL->LL FAXIND %x", status);
969 ic.driver = bcs->cs->myid;
970 ic.command = ISDN_STAT_FAXIND;
971 ic.arg = chanp->chan;
972 ic.parm.aux.cmd = status;
973 bcs->cs->iif.statcallb(&ic);
974}
975
976static void
977isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
978 struct IsdnCardState *cs = bcs->cs;
979 u_char dps = SET_DPS(bcs->hw.isar.dpath);
980 u_char p1;
981
982 switch(devt) {
983 case PSEV_10MS_TIMER:
984 if (cs->debug & L1_DEB_HSCX)
985 debugl1(cs, "pump stev TIMER");
986 break;
987 case PSEV_RSP_READY:
988 if (cs->debug & L1_DEB_HSCX)
989 debugl1(cs, "pump stev RSP_READY");
990 bcs->hw.isar.state = STFAX_READY;
991 l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL);
992 if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
993 isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FRH, 3);
994 } else {
995 isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FTH, 3);
996 }
997 break;
998 case PSEV_LINE_TX_H:
999 if (bcs->hw.isar.state == STFAX_LINE) {
1000 if (cs->debug & L1_DEB_HSCX)
1001 debugl1(cs, "pump stev LINE_TX_H");
1002 bcs->hw.isar.state = STFAX_CONT;
1003 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
1004 } else {
1005 if (cs->debug & L1_DEB_WARN)
1006 debugl1(cs, "pump stev LINE_TX_H wrong st %x",
1007 bcs->hw.isar.state);
1008 }
1009 break;
1010 case PSEV_LINE_RX_H:
1011 if (bcs->hw.isar.state == STFAX_LINE) {
1012 if (cs->debug & L1_DEB_HSCX)
1013 debugl1(cs, "pump stev LINE_RX_H");
1014 bcs->hw.isar.state = STFAX_CONT;
1015 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
1016 } else {
1017 if (cs->debug & L1_DEB_WARN)
1018 debugl1(cs, "pump stev LINE_RX_H wrong st %x",
1019 bcs->hw.isar.state);
1020 }
1021 break;
1022 case PSEV_LINE_TX_B:
1023 if (bcs->hw.isar.state == STFAX_LINE) {
1024 if (cs->debug & L1_DEB_HSCX)
1025 debugl1(cs, "pump stev LINE_TX_B");
1026 bcs->hw.isar.state = STFAX_CONT;
1027 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
1028 } else {
1029 if (cs->debug & L1_DEB_WARN)
1030 debugl1(cs, "pump stev LINE_TX_B wrong st %x",
1031 bcs->hw.isar.state);
1032 }
1033 break;
1034 case PSEV_LINE_RX_B:
1035 if (bcs->hw.isar.state == STFAX_LINE) {
1036 if (cs->debug & L1_DEB_HSCX)
1037 debugl1(cs, "pump stev LINE_RX_B");
1038 bcs->hw.isar.state = STFAX_CONT;
1039 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
1040 } else {
1041 if (cs->debug & L1_DEB_WARN)
1042 debugl1(cs, "pump stev LINE_RX_B wrong st %x",
1043 bcs->hw.isar.state);
1044 }
1045 break;
1046 case PSEV_RSP_CONN:
1047 if (bcs->hw.isar.state == STFAX_CONT) {
1048 if (cs->debug & L1_DEB_HSCX)
1049 debugl1(cs, "pump stev RSP_CONN");
1050 bcs->hw.isar.state = STFAX_ACTIV;
1051 test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags);
1052 sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
1053 if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
1054 /* 1s Flags before data */
1055 if (test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag))
1056 del_timer(&bcs->hw.isar.ftimer);
1057 /* 1000 ms */
1058 bcs->hw.isar.ftimer.expires =
1059 jiffies + ((1000 * HZ)/1000);
1060 test_and_set_bit(BC_FLG_LL_CONN,
1061 &bcs->Flag);
1062 add_timer(&bcs->hw.isar.ftimer);
1063 } else {
1064 schedule_event(bcs, B_LL_CONNECT);
1065 }
1066 } else {
1067 if (cs->debug & L1_DEB_WARN)
1068 debugl1(cs, "pump stev RSP_CONN wrong st %x",
1069 bcs->hw.isar.state);
1070 }
1071 break;
1072 case PSEV_FLAGS_DET:
1073 if (cs->debug & L1_DEB_HSCX)
1074 debugl1(cs, "pump stev FLAGS_DET");
1075 break;
1076 case PSEV_RSP_DISC:
1077 if (cs->debug & L1_DEB_HSCX)
1078 debugl1(cs, "pump stev RSP_DISC");
1079 if (bcs->hw.isar.state == STFAX_ESCAPE) {
1080 p1 = 5;
1081 switch(bcs->hw.isar.newcmd) {
1082 case 0:
1083 bcs->hw.isar.state = STFAX_READY;
1084 break;
1085 case PCTRL_CMD_FTM:
1086 p1 = 2;
1087 case PCTRL_CMD_FTH:
1088 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
1089 PCTRL_CMD_SILON, 1, &p1);
1090 bcs->hw.isar.state = STFAX_SILDET;
1091 break;
1092 case PCTRL_CMD_FRM:
1093 if (frm_extra_delay)
1094 mdelay(frm_extra_delay);
1095 case PCTRL_CMD_FRH:
1096 p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod;
1097 bcs->hw.isar.newmod = 0;
1098 bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
1099 bcs->hw.isar.newcmd = 0;
1100 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
1101 bcs->hw.isar.cmd, 1, &p1);
1102 bcs->hw.isar.state = STFAX_LINE;
1103 bcs->hw.isar.try_mod = 3;
1104 break;
1105 default:
1106 if (cs->debug & L1_DEB_HSCX)
1107 debugl1(cs, "RSP_DISC unknown newcmd %x", bcs->hw.isar.newcmd);
1108 break;
1109 }
1110 } else if (bcs->hw.isar.state == STFAX_ACTIV) {
1111 if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) {
1112 schedule_event(bcs, B_LL_OK);
1113 } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
1114 send_DLE_ETX(bcs);
1115 schedule_event(bcs, B_LL_NOCARRIER);
1116 } else {
1117 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
1118 }
1119 bcs->hw.isar.state = STFAX_READY;
1120 } else {
1121 bcs->hw.isar.state = STFAX_READY;
1122 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
1123 }
1124 break;
1125 case PSEV_RSP_SILDET:
1126 if (cs->debug & L1_DEB_HSCX)
1127 debugl1(cs, "pump stev RSP_SILDET");
1128 if (bcs->hw.isar.state == STFAX_SILDET) {
1129 p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod;
1130 bcs->hw.isar.newmod = 0;
1131 bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
1132 bcs->hw.isar.newcmd = 0;
1133 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
1134 bcs->hw.isar.cmd, 1, &p1);
1135 bcs->hw.isar.state = STFAX_LINE;
1136 bcs->hw.isar.try_mod = 3;
1137 }
1138 break;
1139 case PSEV_RSP_SILOFF:
1140 if (cs->debug & L1_DEB_HSCX)
1141 debugl1(cs, "pump stev RSP_SILOFF");
1142 break;
1143 case PSEV_RSP_FCERR:
1144 if (bcs->hw.isar.state == STFAX_LINE) {
1145 if (cs->debug & L1_DEB_HSCX)
1146 debugl1(cs, "pump stev RSP_FCERR try %d",
1147 bcs->hw.isar.try_mod);
1148 if (bcs->hw.isar.try_mod--) {
1149 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
1150 bcs->hw.isar.cmd, 1,
1151 &bcs->hw.isar.mod);
1152 break;
1153 }
1154 }
1155 if (cs->debug & L1_DEB_HSCX)
1156 debugl1(cs, "pump stev RSP_FCERR");
1157 bcs->hw.isar.state = STFAX_ESCAPE;
1158 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
1159 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
1160 break;
1161 default:
1162 break;
1163 }
1164}
1165
1166static char debbuf[128];
1167
1168void
1169isar_int_main(struct IsdnCardState *cs)
1170{
1171 struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
1172 struct BCState *bcs;
1173
1174 get_irq_infos(cs, ireg);
1175 switch (ireg->iis & ISAR_IIS_MSCMSD) {
1176 case ISAR_IIS_RDATA:
1177 if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
1178 isar_rcv_frame(cs, bcs);
1179 } else {
1180 debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x",
1181 ireg->iis, ireg->cmsb, ireg->clsb);
1182 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
1183 }
1184 break;
1185 case ISAR_IIS_GSTEV:
1186 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
1187 ireg->bstat |= ireg->cmsb;
1188 check_send(cs, ireg->cmsb);
1189 break;
1190 case ISAR_IIS_BSTEV:
1191#ifdef ERROR_STATISTIC
1192 if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
1193 if (ireg->cmsb == BSTEV_TBO)
1194 bcs->err_tx++;
1195 if (ireg->cmsb == BSTEV_RBO)
1196 bcs->err_rdo++;
1197 }
1198#endif
1199 if (cs->debug & L1_DEB_WARN)
1200 debugl1(cs, "Buffer STEV dpath%d msb(%x)",
1201 ireg->iis>>6, ireg->cmsb);
1202 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
1203 break;
1204 case ISAR_IIS_PSTEV:
1205 if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
1206 rcv_mbox(cs, ireg, (u_char *)ireg->par);
1207 if (bcs->mode == L1_MODE_V32) {
1208 isar_pump_statev_modem(bcs, ireg->cmsb);
1209 } else if (bcs->mode == L1_MODE_FAX) {
1210 isar_pump_statev_fax(bcs, ireg->cmsb);
1211 } else if (ireg->cmsb == PSEV_10MS_TIMER) {
1212 if (cs->debug & L1_DEB_HSCX)
1213 debugl1(cs, "pump stev TIMER");
1214 } else {
1215 if (cs->debug & L1_DEB_WARN)
1216 debugl1(cs, "isar IIS_PSTEV pmode %d stat %x",
1217 bcs->mode, ireg->cmsb);
1218 }
1219 } else {
1220 debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x",
1221 ireg->iis, ireg->cmsb, ireg->clsb);
1222 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
1223 }
1224 break;
1225 case ISAR_IIS_PSTRSP:
1226 if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
1227 rcv_mbox(cs, ireg, (u_char *)ireg->par);
1228 isar_pump_status_rsp(bcs, ireg);
1229 } else {
1230 debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x",
1231 ireg->iis, ireg->cmsb, ireg->clsb);
1232 cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
1233 }
1234 break;
1235 case ISAR_IIS_DIAG:
1236 case ISAR_IIS_BSTRSP:
1237 case ISAR_IIS_IOM2RSP:
1238 rcv_mbox(cs, ireg, (u_char *)ireg->par);
1239 if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO))
1240 == L1_DEB_HSCX) {
1241 u_char *tp=debbuf;
1242
1243 tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
1244 ireg->iis, ireg->cmsb);
1245 QuickHex(tp, (u_char *)ireg->par, ireg->clsb);
1246 debugl1(cs, debbuf);
1247 }
1248 break;
1249 case ISAR_IIS_INVMSG:
1250 rcv_mbox(cs, ireg, debbuf);
1251 if (cs->debug & L1_DEB_WARN)
1252 debugl1(cs, "invalid msg his:%x",
1253 ireg->cmsb);
1254 break;
1255 default:
1256 rcv_mbox(cs, ireg, debbuf);
1257 if (cs->debug & L1_DEB_WARN)
1258 debugl1(cs, "unhandled msg iis(%x) ctrl(%x/%x)",
1259 ireg->iis, ireg->cmsb, ireg->clsb);
1260 break;
1261 }
1262}
1263
1264static void
1265ftimer_handler(struct BCState *bcs) {
1266 if (bcs->cs->debug)
1267 debugl1(bcs->cs, "ftimer flags %04x",
1268 bcs->Flag);
1269 test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag);
1270 if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
1271 schedule_event(bcs, B_LL_CONNECT);
1272 }
1273 if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) {
1274 schedule_event(bcs, B_LL_OK);
1275 }
1276}
1277
1278static void
1279setup_pump(struct BCState *bcs) {
1280 struct IsdnCardState *cs = bcs->cs;
1281 u_char dps = SET_DPS(bcs->hw.isar.dpath);
1282 u_char ctrl, param[6];
1283
1284 switch (bcs->mode) {
1285 case L1_MODE_NULL:
1286 case L1_MODE_TRANS:
1287 case L1_MODE_HDLC:
1288 sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
1289 break;
1290 case L1_MODE_V32:
1291 ctrl = PMOD_DATAMODEM;
1292 if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
1293 ctrl |= PCTRL_ORIG;
1294 param[5] = PV32P6_CTN;
1295 } else {
1296 param[5] = PV32P6_ATN;
1297 }
1298 param[0] = para_TOA; /* 6 db */
1299 param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
1300 PV32P2_V22C | PV32P2_V21 | PV32P2_BEL;
1301 param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
1302 param[3] = PV32P4_UT144;
1303 param[4] = PV32P5_UT144;
1304 sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
1305 break;
1306 case L1_MODE_FAX:
1307 ctrl = PMOD_FAX;
1308 if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
1309 ctrl |= PCTRL_ORIG;
1310 param[1] = PFAXP2_CTN;
1311 } else {
1312 param[1] = PFAXP2_ATN;
1313 }
1314 param[0] = para_TOA; /* 6 db */
1315 sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
1316 bcs->hw.isar.state = STFAX_NULL;
1317 bcs->hw.isar.newcmd = 0;
1318 bcs->hw.isar.newmod = 0;
1319 test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag);
1320 break;
1321 }
1322 udelay(1000);
1323 sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
1324 udelay(1000);
1325}
1326
1327static void
1328setup_sart(struct BCState *bcs) {
1329 struct IsdnCardState *cs = bcs->cs;
1330 u_char dps = SET_DPS(bcs->hw.isar.dpath);
1331 u_char ctrl, param[2];
1332
1333 switch (bcs->mode) {
1334 case L1_MODE_NULL:
1335 sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0,
1336 NULL);
1337 break;
1338 case L1_MODE_TRANS:
1339 sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2,
1340 "\0\0");
1341 break;
1342 case L1_MODE_HDLC:
1343 param[0] = 0;
1344 sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
1345 param);
1346 break;
1347 case L1_MODE_V32:
1348 ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
1349 param[0] = S_P1_CHS_8;
1350 param[1] = S_P2_BFT_DEF;
1351 sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2,
1352 param);
1353 break;
1354 case L1_MODE_FAX:
1355 /* SART must not configured with FAX */
1356 break;
1357 }
1358 udelay(1000);
1359 sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
1360 udelay(1000);
1361}
1362
1363static void
1364setup_iom2(struct BCState *bcs) {
1365 struct IsdnCardState *cs = bcs->cs;
1366 u_char dps = SET_DPS(bcs->hw.isar.dpath);
1367 u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0};
1368
1369 if (bcs->channel)
1370 msg[1] = msg[3] = 1;
1371 switch (bcs->mode) {
1372 case L1_MODE_NULL:
1373 cmsb = 0;
1374 /* dummy slot */
1375 msg[1] = msg[3] = bcs->hw.isar.dpath + 2;
1376 break;
1377 case L1_MODE_TRANS:
1378 case L1_MODE_HDLC:
1379 break;
1380 case L1_MODE_V32:
1381 case L1_MODE_FAX:
1382 cmsb |= IOM_CTRL_ALAW | IOM_CTRL_RCV;
1383 break;
1384 }
1385 sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg);
1386 udelay(1000);
1387 sendmsg(cs, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL);
1388 udelay(1000);
1389}
1390
1391int
1392modeisar(struct BCState *bcs, int mode, int bc)
1393{
1394 struct IsdnCardState *cs = bcs->cs;
1395
1396 /* Here we are selecting the best datapath for requested mode */
1397 if(bcs->mode == L1_MODE_NULL) { /* New Setup */
1398 bcs->channel = bc;
1399 switch (mode) {
1400 case L1_MODE_NULL: /* init */
1401 if (!bcs->hw.isar.dpath)
1402 /* no init for dpath 0 */
1403 return(0);
1404 break;
1405 case L1_MODE_TRANS:
1406 case L1_MODE_HDLC:
1407 /* best is datapath 2 */
1408 if (!test_and_set_bit(ISAR_DP2_USE,
1409 &bcs->hw.isar.reg->Flags))
1410 bcs->hw.isar.dpath = 2;
1411 else if (!test_and_set_bit(ISAR_DP1_USE,
1412 &bcs->hw.isar.reg->Flags))
1413 bcs->hw.isar.dpath = 1;
1414 else {
1415 printk(KERN_WARNING"isar modeisar both pathes in use\n");
1416 return(1);
1417 }
1418 break;
1419 case L1_MODE_V32:
1420 case L1_MODE_FAX:
1421 /* only datapath 1 */
1422 if (!test_and_set_bit(ISAR_DP1_USE,
1423 &bcs->hw.isar.reg->Flags))
1424 bcs->hw.isar.dpath = 1;
1425 else {
1426 printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n");
1427 debugl1(cs, "isar modeisar analog funktions only with DP1");
1428 return(1);
1429 }
1430 break;
1431 }
1432 }
1433 if (cs->debug & L1_DEB_HSCX)
1434 debugl1(cs, "isar dp%d mode %d->%d ichan %d",
1435 bcs->hw.isar.dpath, bcs->mode, mode, bc);
1436 bcs->mode = mode;
1437 setup_pump(bcs);
1438 setup_iom2(bcs);
1439 setup_sart(bcs);
1440 if (bcs->mode == L1_MODE_NULL) {
1441 /* Clear resources */
1442 if (bcs->hw.isar.dpath == 1)
1443 test_and_clear_bit(ISAR_DP1_USE, &bcs->hw.isar.reg->Flags);
1444 else if (bcs->hw.isar.dpath == 2)
1445 test_and_clear_bit(ISAR_DP2_USE, &bcs->hw.isar.reg->Flags);
1446 bcs->hw.isar.dpath = 0;
1447 }
1448 return(0);
1449}
1450
1451static void
1452isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para)
1453{
1454 struct IsdnCardState *cs = bcs->cs;
1455 u_char dps = SET_DPS(bcs->hw.isar.dpath);
1456 u_char ctrl = 0, nom = 0, p1 = 0;
1457
1458 switch(cmd) {
1459 case ISDN_FAX_CLASS1_FTM:
1460 test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
1461 if (bcs->hw.isar.state == STFAX_READY) {
1462 p1 = para;
1463 ctrl = PCTRL_CMD_FTM;
1464 nom = 1;
1465 bcs->hw.isar.state = STFAX_LINE;
1466 bcs->hw.isar.cmd = ctrl;
1467 bcs->hw.isar.mod = para;
1468 bcs->hw.isar.newmod = 0;
1469 bcs->hw.isar.newcmd = 0;
1470 bcs->hw.isar.try_mod = 3;
1471 } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
1472 (bcs->hw.isar.cmd == PCTRL_CMD_FTM) &&
1473 (bcs->hw.isar.mod == para)) {
1474 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
1475 } else {
1476 bcs->hw.isar.newmod = para;
1477 bcs->hw.isar.newcmd = PCTRL_CMD_FTM;
1478 nom = 0;
1479 ctrl = PCTRL_CMD_ESC;
1480 bcs->hw.isar.state = STFAX_ESCAPE;
1481 }
1482 break;
1483 case ISDN_FAX_CLASS1_FTH:
1484 test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
1485 if (bcs->hw.isar.state == STFAX_READY) {
1486 p1 = para;
1487 ctrl = PCTRL_CMD_FTH;
1488 nom = 1;
1489 bcs->hw.isar.state = STFAX_LINE;
1490 bcs->hw.isar.cmd = ctrl;
1491 bcs->hw.isar.mod = para;
1492 bcs->hw.isar.newmod = 0;
1493 bcs->hw.isar.newcmd = 0;
1494 bcs->hw.isar.try_mod = 3;
1495 } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
1496 (bcs->hw.isar.cmd == PCTRL_CMD_FTH) &&
1497 (bcs->hw.isar.mod == para)) {
1498 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
1499 } else {
1500 bcs->hw.isar.newmod = para;
1501 bcs->hw.isar.newcmd = PCTRL_CMD_FTH;
1502 nom = 0;
1503 ctrl = PCTRL_CMD_ESC;
1504 bcs->hw.isar.state = STFAX_ESCAPE;
1505 }
1506 break;
1507 case ISDN_FAX_CLASS1_FRM:
1508 test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
1509 if (bcs->hw.isar.state == STFAX_READY) {
1510 p1 = para;
1511 ctrl = PCTRL_CMD_FRM;
1512 nom = 1;
1513 bcs->hw.isar.state = STFAX_LINE;
1514 bcs->hw.isar.cmd = ctrl;
1515 bcs->hw.isar.mod = para;
1516 bcs->hw.isar.newmod = 0;
1517 bcs->hw.isar.newcmd = 0;
1518 bcs->hw.isar.try_mod = 3;
1519 } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
1520 (bcs->hw.isar.cmd == PCTRL_CMD_FRM) &&
1521 (bcs->hw.isar.mod == para)) {
1522 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
1523 } else {
1524 bcs->hw.isar.newmod = para;
1525 bcs->hw.isar.newcmd = PCTRL_CMD_FRM;
1526 nom = 0;
1527 ctrl = PCTRL_CMD_ESC;
1528 bcs->hw.isar.state = STFAX_ESCAPE;
1529 }
1530 break;
1531 case ISDN_FAX_CLASS1_FRH:
1532 test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
1533 if (bcs->hw.isar.state == STFAX_READY) {
1534 p1 = para;
1535 ctrl = PCTRL_CMD_FRH;
1536 nom = 1;
1537 bcs->hw.isar.state = STFAX_LINE;
1538 bcs->hw.isar.cmd = ctrl;
1539 bcs->hw.isar.mod = para;
1540 bcs->hw.isar.newmod = 0;
1541 bcs->hw.isar.newcmd = 0;
1542 bcs->hw.isar.try_mod = 3;
1543 } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
1544 (bcs->hw.isar.cmd == PCTRL_CMD_FRH) &&
1545 (bcs->hw.isar.mod == para)) {
1546 ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
1547 } else {
1548 bcs->hw.isar.newmod = para;
1549 bcs->hw.isar.newcmd = PCTRL_CMD_FRH;
1550 nom = 0;
1551 ctrl = PCTRL_CMD_ESC;
1552 bcs->hw.isar.state = STFAX_ESCAPE;
1553 }
1554 break;
1555 case ISDN_FAXPUMP_HALT:
1556 bcs->hw.isar.state = STFAX_NULL;
1557 nom = 0;
1558 ctrl = PCTRL_CMD_HALT;
1559 break;
1560 }
1561 if (ctrl)
1562 sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
1563}
1564
1565void
1566isar_setup(struct IsdnCardState *cs)
1567{
1568 u_char msg;
1569 int i;
1570
1571 /* Dpath 1, 2 */
1572 msg = 61;
1573 for (i=0; i<2; i++) {
1574 /* Buffer Config */
1575 sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
1576 ISAR_HIS_P12CFG, 4, 1, &msg);
1577 cs->bcs[i].hw.isar.mml = msg;
1578 cs->bcs[i].mode = 0;
1579 cs->bcs[i].hw.isar.dpath = i + 1;
1580 modeisar(&cs->bcs[i], 0, 0);
1581 INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]);
1582 }
1583}
1584
1585void
1586isar_l2l1(struct PStack *st, int pr, void *arg)
1587{
1588 struct BCState *bcs = st->l1.bcs;
1589 struct sk_buff *skb = arg;
1590 int ret;
1591 u_long flags;
1592
1593 switch (pr) {
1594 case (PH_DATA | REQUEST):
1595 spin_lock_irqsave(&bcs->cs->lock, flags);
1596 if (bcs->tx_skb) {
1597 skb_queue_tail(&bcs->squeue, skb);
1598 } else {
1599 bcs->tx_skb = skb;
1600 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1601 if (bcs->cs->debug & L1_DEB_HSCX)
1602 debugl1(bcs->cs, "DRQ set BC_FLG_BUSY");
1603 bcs->hw.isar.txcnt = 0;
1604 bcs->cs->BC_Send_Data(bcs);
1605 }
1606 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1607 break;
1608 case (PH_PULL | INDICATION):
1609 spin_lock_irqsave(&bcs->cs->lock, flags);
1610 if (bcs->tx_skb) {
1611 printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n");
1612 } else {
1613 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1614 if (bcs->cs->debug & L1_DEB_HSCX)
1615 debugl1(bcs->cs, "PUI set BC_FLG_BUSY");
1616 bcs->tx_skb = skb;
1617 bcs->hw.isar.txcnt = 0;
1618 bcs->cs->BC_Send_Data(bcs);
1619 }
1620 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1621 break;
1622 case (PH_PULL | REQUEST):
1623 if (!bcs->tx_skb) {
1624 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1625 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1626 } else
1627 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1628 break;
1629 case (PH_ACTIVATE | REQUEST):
1630 spin_lock_irqsave(&bcs->cs->lock, flags);
1631 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
1632 bcs->hw.isar.conmsg[0] = 0;
1633 if (test_bit(FLG_ORIG, &st->l2.flag))
1634 test_and_set_bit(BC_FLG_ORIG, &bcs->Flag);
1635 else
1636 test_and_clear_bit(BC_FLG_ORIG, &bcs->Flag);
1637 switch(st->l1.mode) {
1638 case L1_MODE_TRANS:
1639 case L1_MODE_HDLC:
1640 ret = modeisar(bcs, st->l1.mode, st->l1.bc);
1641 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1642 if (ret)
1643 l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
1644 else
1645 l1_msg_b(st, PH_ACTIVATE | REQUEST, arg);
1646 break;
1647 case L1_MODE_V32:
1648 case L1_MODE_FAX:
1649 ret = modeisar(bcs, st->l1.mode, st->l1.bc);
1650 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1651 if (ret)
1652 l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
1653 break;
1654 default:
1655 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1656 break;
1657 }
1658 break;
1659 case (PH_DEACTIVATE | REQUEST):
1660 l1_msg_b(st, pr, arg);
1661 break;
1662 case (PH_DEACTIVATE | CONFIRM):
1663 spin_lock_irqsave(&bcs->cs->lock, flags);
1664 switch(st->l1.mode) {
1665 case L1_MODE_TRANS:
1666 case L1_MODE_HDLC:
1667 case L1_MODE_V32:
1668 break;
1669 case L1_MODE_FAX:
1670 isar_pump_cmd(bcs, ISDN_FAXPUMP_HALT, 0);
1671 break;
1672 }
1673 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
1674 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1675 if (bcs->cs->debug & L1_DEB_HSCX)
1676 debugl1(bcs->cs, "PDAC clear BC_FLG_BUSY");
1677 modeisar(bcs, 0, st->l1.bc);
1678 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1679 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
1680 break;
1681 }
1682}
1683
1684void
1685close_isarstate(struct BCState *bcs)
1686{
1687 modeisar(bcs, 0, bcs->channel);
1688 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
1689 if (bcs->hw.isar.rcvbuf) {
1690 kfree(bcs->hw.isar.rcvbuf);
1691 bcs->hw.isar.rcvbuf = NULL;
1692 }
1693 skb_queue_purge(&bcs->rqueue);
1694 skb_queue_purge(&bcs->squeue);
1695 if (bcs->tx_skb) {
1696 dev_kfree_skb_any(bcs->tx_skb);
1697 bcs->tx_skb = NULL;
1698 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1699 if (bcs->cs->debug & L1_DEB_HSCX)
1700 debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY");
1701 }
1702 }
1703 del_timer(&bcs->hw.isar.ftimer);
1704}
1705
1706int
1707open_isarstate(struct IsdnCardState *cs, struct BCState *bcs)
1708{
1709 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
1710 if (!(bcs->hw.isar.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
1711 printk(KERN_WARNING
1712 "HiSax: No memory for isar.rcvbuf\n");
1713 return (1);
1714 }
1715 skb_queue_head_init(&bcs->rqueue);
1716 skb_queue_head_init(&bcs->squeue);
1717 }
1718 bcs->tx_skb = NULL;
1719 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1720 if (cs->debug & L1_DEB_HSCX)
1721 debugl1(cs, "openisar clear BC_FLG_BUSY");
1722 bcs->event = 0;
1723 bcs->hw.isar.rcvidx = 0;
1724 bcs->tx_cnt = 0;
1725 return (0);
1726}
1727
1728int
1729setstack_isar(struct PStack *st, struct BCState *bcs)
1730{
1731 bcs->channel = st->l1.bc;
1732 if (open_isarstate(st->l1.hardware, bcs))
1733 return (-1);
1734 st->l1.bcs = bcs;
1735 st->l2.l2l1 = isar_l2l1;
1736 setstack_manager(st);
1737 bcs->st = st;
1738 setstack_l1_B(st);
1739 return (0);
1740}
1741
1742int
1743isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
1744 u_long adr;
1745 int features, i;
1746 struct BCState *bcs;
1747
1748 if (cs->debug & L1_DEB_HSCX)
1749 debugl1(cs, "isar_auxcmd cmd/ch %x/%d", ic->command, ic->arg);
1750 switch (ic->command) {
1751 case (ISDN_CMD_FAXCMD):
1752 bcs = cs->channel[ic->arg].bcs;
1753 if (cs->debug & L1_DEB_HSCX)
1754 debugl1(cs, "isar_auxcmd cmd/subcmd %d/%d",
1755 ic->parm.aux.cmd, ic->parm.aux.subcmd);
1756 switch(ic->parm.aux.cmd) {
1757 case ISDN_FAX_CLASS1_CTRL:
1758 if (ic->parm.aux.subcmd == ETX)
1759 test_and_set_bit(BC_FLG_DLEETX,
1760 &bcs->Flag);
1761 break;
1762 case ISDN_FAX_CLASS1_FTS:
1763 if (ic->parm.aux.subcmd == AT_QUERY) {
1764 ic->command = ISDN_STAT_FAXIND;
1765 ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
1766 cs->iif.statcallb(ic);
1767 return(0);
1768 } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
1769 strcpy(ic->parm.aux.para, "0-255");
1770 ic->command = ISDN_STAT_FAXIND;
1771 ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
1772 cs->iif.statcallb(ic);
1773 return(0);
1774 } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
1775 if (cs->debug & L1_DEB_HSCX)
1776 debugl1(cs, "isar_auxcmd %s=%d",
1777 FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
1778 if (bcs->hw.isar.state == STFAX_READY) {
1779 if (! ic->parm.aux.para[0]) {
1780 ic->command = ISDN_STAT_FAXIND;
1781 ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
1782 cs->iif.statcallb(ic);
1783 return(0);
1784 }
1785 if (! test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) {
1786 /* n*10 ms */
1787 bcs->hw.isar.ftimer.expires =
1788 jiffies + ((ic->parm.aux.para[0] * 10 * HZ)/1000);
1789 test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag);
1790 add_timer(&bcs->hw.isar.ftimer);
1791 return(0);
1792 } else {
1793 if (cs->debug)
1794 debugl1(cs, "isar FTS=%d and FTI busy",
1795 ic->parm.aux.para[0]);
1796 }
1797 } else {
1798 if (cs->debug)
1799 debugl1(cs, "isar FTS=%d and isar.state not ready(%x)",
1800 ic->parm.aux.para[0],bcs->hw.isar.state);
1801 }
1802 ic->command = ISDN_STAT_FAXIND;
1803 ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
1804 cs->iif.statcallb(ic);
1805 }
1806 break;
1807 case ISDN_FAX_CLASS1_FRM:
1808 case ISDN_FAX_CLASS1_FRH:
1809 case ISDN_FAX_CLASS1_FTM:
1810 case ISDN_FAX_CLASS1_FTH:
1811 if (ic->parm.aux.subcmd == AT_QUERY) {
1812 sprintf(ic->parm.aux.para,
1813 "%d", bcs->hw.isar.mod);
1814 ic->command = ISDN_STAT_FAXIND;
1815 ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
1816 cs->iif.statcallb(ic);
1817 return(0);
1818 } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
1819 char *p = ic->parm.aux.para;
1820 for(i=0;i<FAXMODCNT;i++)
1821 if ((1<<i) & modmask)
1822 p += sprintf(p, "%d,", faxmodulation[i]);
1823 p--;
1824 *p=0;
1825 ic->command = ISDN_STAT_FAXIND;
1826 ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
1827 cs->iif.statcallb(ic);
1828 return(0);
1829 } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
1830 if (cs->debug & L1_DEB_HSCX)
1831 debugl1(cs, "isar_auxcmd %s=%d",
1832 FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
1833 for(i=0;i<FAXMODCNT;i++)
1834 if (faxmodulation[i]==ic->parm.aux.para[0])
1835 break;
1836 if ((i < FAXMODCNT) && ((1<<i) & modmask) &&
1837 test_bit(BC_FLG_INIT, &bcs->Flag)) {
1838 isar_pump_cmd(bcs,
1839 ic->parm.aux.cmd,
1840 ic->parm.aux.para[0]);
1841 return(0);
1842 }
1843 }
1844 /* wrong modulation or not activ */
1845 /* fall through */
1846 default:
1847 ic->command = ISDN_STAT_FAXIND;
1848 ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
1849 cs->iif.statcallb(ic);
1850 }
1851 break;
1852 case (ISDN_CMD_IOCTL):
1853 switch (ic->arg) {
1854 case 9: /* load firmware */
1855 features = ISDN_FEATURE_L2_MODEM |
1856 ISDN_FEATURE_L2_FAX |
1857 ISDN_FEATURE_L3_FCLASS1;
1858 memcpy(&adr, ic->parm.num, sizeof(ulong));
1859 if (isar_load_firmware(cs, (u_char __user *)adr))
1860 return(1);
1861 else
1862 ll_run(cs, features);
1863 break;
1864 case 20:
1865 features = *(unsigned int *) ic->parm.num;
1866 printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n",
1867 modmask, features);
1868 modmask = features;
1869 break;
1870 case 21:
1871 features = *(unsigned int *) ic->parm.num;
1872 printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n",
1873 frm_extra_delay, features);
1874 if (features >= 0)
1875 frm_extra_delay = features;
1876 break;
1877 case 22:
1878 features = *(unsigned int *) ic->parm.num;
1879 printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n",
1880 para_TOA, features);
1881 if (features >= 0 && features < 32)
1882 para_TOA = features;
1883 break;
1884 default:
1885 printk(KERN_DEBUG "HiSax: invalid ioctl %d\n",
1886 (int) ic->arg);
1887 return(-EINVAL);
1888 }
1889 break;
1890 default:
1891 return(-EINVAL);
1892 }
1893 return(0);
1894}
1895
1896void __devinit
1897initisar(struct IsdnCardState *cs)
1898{
1899 cs->bcs[0].BC_SetStack = setstack_isar;
1900 cs->bcs[1].BC_SetStack = setstack_isar;
1901 cs->bcs[0].BC_Close = close_isarstate;
1902 cs->bcs[1].BC_Close = close_isarstate;
1903 cs->bcs[0].hw.isar.ftimer.function = (void *) ftimer_handler;
1904 cs->bcs[0].hw.isar.ftimer.data = (long) &cs->bcs[0];
1905 init_timer(&cs->bcs[0].hw.isar.ftimer);
1906 cs->bcs[1].hw.isar.ftimer.function = (void *) ftimer_handler;
1907 cs->bcs[1].hw.isar.ftimer.data = (long) &cs->bcs[1];
1908 init_timer(&cs->bcs[1].hw.isar.ftimer);
1909}
diff --git a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h
new file mode 100644
index 00000000000..bf767658639
--- /dev/null
+++ b/drivers/isdn/hisax/isar.h
@@ -0,0 +1,222 @@
1/* $Id: isar.h,v 1.11.2.2 2004/01/12 22:52:27 keil Exp $
2 *
3 * ISAR (Siemens PSB 7110) specific defines
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#define ISAR_IRQMSK 0x04
14#define ISAR_IRQSTA 0x04
15#define ISAR_IRQBIT 0x75
16#define ISAR_CTRL_H 0x61
17#define ISAR_CTRL_L 0x60
18#define ISAR_IIS 0x58
19#define ISAR_IIA 0x58
20#define ISAR_HIS 0x50
21#define ISAR_HIA 0x50
22#define ISAR_MBOX 0x4c
23#define ISAR_WADR 0x4a
24#define ISAR_RADR 0x48
25
26#define ISAR_HIS_VNR 0x14
27#define ISAR_HIS_DKEY 0x02
28#define ISAR_HIS_FIRM 0x1e
29#define ISAR_HIS_STDSP 0x08
30#define ISAR_HIS_DIAG 0x05
31#define ISAR_HIS_WAITSTATE 0x27
32#define ISAR_HIS_TIMERIRQ 0x25
33#define ISAR_HIS_P0CFG 0x3c
34#define ISAR_HIS_P12CFG 0x24
35#define ISAR_HIS_SARTCFG 0x25
36#define ISAR_HIS_PUMPCFG 0x26
37#define ISAR_HIS_PUMPCTRL 0x2a
38#define ISAR_HIS_IOM2CFG 0x27
39#define ISAR_HIS_IOM2REQ 0x07
40#define ISAR_HIS_IOM2CTRL 0x2b
41#define ISAR_HIS_BSTREQ 0x0c
42#define ISAR_HIS_PSTREQ 0x0e
43#define ISAR_HIS_SDATA 0x20
44#define ISAR_HIS_DPS1 0x40
45#define ISAR_HIS_DPS2 0x80
46#define SET_DPS(x) ((x<<6) & 0xc0)
47
48#define ISAR_CMD_TIMERIRQ_OFF 0x20
49#define ISAR_CMD_TIMERIRQ_ON 0x21
50
51
52#define ISAR_IIS_MSCMSD 0x3f
53#define ISAR_IIS_VNR 0x15
54#define ISAR_IIS_DKEY 0x03
55#define ISAR_IIS_FIRM 0x1f
56#define ISAR_IIS_STDSP 0x09
57#define ISAR_IIS_DIAG 0x25
58#define ISAR_IIS_GSTEV 0x00
59#define ISAR_IIS_BSTEV 0x28
60#define ISAR_IIS_BSTRSP 0x2c
61#define ISAR_IIS_PSTRSP 0x2e
62#define ISAR_IIS_PSTEV 0x2a
63#define ISAR_IIS_IOM2RSP 0x27
64#define ISAR_IIS_RDATA 0x20
65#define ISAR_IIS_INVMSG 0x3f
66
67#define ISAR_CTRL_SWVER 0x10
68#define ISAR_CTRL_STST 0x40
69
70#define ISAR_MSG_HWVER {0x20, 0, 1}
71
72#define ISAR_DP1_USE 1
73#define ISAR_DP2_USE 2
74#define ISAR_RATE_REQ 3
75
76#define PMOD_DISABLE 0
77#define PMOD_FAX 1
78#define PMOD_DATAMODEM 2
79#define PMOD_HALFDUPLEX 3
80#define PMOD_V110 4
81#define PMOD_DTMF 5
82#define PMOD_DTMF_TRANS 6
83#define PMOD_BYPASS 7
84
85#define PCTRL_ORIG 0x80
86#define PV32P2_V23R 0x40
87#define PV32P2_V22A 0x20
88#define PV32P2_V22B 0x10
89#define PV32P2_V22C 0x08
90#define PV32P2_V21 0x02
91#define PV32P2_BEL 0x01
92
93// LSB MSB in ISAR doc wrong !!! Arghhh
94#define PV32P3_AMOD 0x80
95#define PV32P3_V32B 0x02
96#define PV32P3_V23B 0x01
97#define PV32P4_48 0x11
98#define PV32P5_48 0x05
99#define PV32P4_UT48 0x11
100#define PV32P5_UT48 0x0d
101#define PV32P4_96 0x11
102#define PV32P5_96 0x03
103#define PV32P4_UT96 0x11
104#define PV32P5_UT96 0x0f
105#define PV32P4_B96 0x91
106#define PV32P5_B96 0x0b
107#define PV32P4_UTB96 0xd1
108#define PV32P5_UTB96 0x0f
109#define PV32P4_120 0xb1
110#define PV32P5_120 0x09
111#define PV32P4_UT120 0xf1
112#define PV32P5_UT120 0x0f
113#define PV32P4_144 0x99
114#define PV32P5_144 0x09
115#define PV32P4_UT144 0xf9
116#define PV32P5_UT144 0x0f
117#define PV32P6_CTN 0x01
118#define PV32P6_ATN 0x02
119
120#define PFAXP2_CTN 0x01
121#define PFAXP2_ATN 0x04
122
123#define PSEV_10MS_TIMER 0x02
124#define PSEV_CON_ON 0x18
125#define PSEV_CON_OFF 0x19
126#define PSEV_V24_OFF 0x20
127#define PSEV_CTS_ON 0x21
128#define PSEV_CTS_OFF 0x22
129#define PSEV_DCD_ON 0x23
130#define PSEV_DCD_OFF 0x24
131#define PSEV_DSR_ON 0x25
132#define PSEV_DSR_OFF 0x26
133#define PSEV_REM_RET 0xcc
134#define PSEV_REM_REN 0xcd
135#define PSEV_GSTN_CLR 0xd4
136
137#define PSEV_RSP_READY 0xbc
138#define PSEV_LINE_TX_H 0xb3
139#define PSEV_LINE_TX_B 0xb2
140#define PSEV_LINE_RX_H 0xb1
141#define PSEV_LINE_RX_B 0xb0
142#define PSEV_RSP_CONN 0xb5
143#define PSEV_RSP_DISC 0xb7
144#define PSEV_RSP_FCERR 0xb9
145#define PSEV_RSP_SILDET 0xbe
146#define PSEV_RSP_SILOFF 0xab
147#define PSEV_FLAGS_DET 0xba
148
149#define PCTRL_CMD_FTH 0xa7
150#define PCTRL_CMD_FRH 0xa5
151#define PCTRL_CMD_FTM 0xa8
152#define PCTRL_CMD_FRM 0xa6
153#define PCTRL_CMD_SILON 0xac
154#define PCTRL_CMD_CONT 0xa2
155#define PCTRL_CMD_ESC 0xa4
156#define PCTRL_CMD_SILOFF 0xab
157#define PCTRL_CMD_HALT 0xa9
158
159#define PCTRL_LOC_RET 0xcf
160#define PCTRL_LOC_REN 0xce
161
162#define SMODE_DISABLE 0
163#define SMODE_V14 2
164#define SMODE_HDLC 3
165#define SMODE_BINARY 4
166#define SMODE_FSK_V14 5
167
168#define SCTRL_HDMC_BOTH 0x00
169#define SCTRL_HDMC_DTX 0x80
170#define SCTRL_HDMC_DRX 0x40
171#define S_P1_OVSP 0x40
172#define S_P1_SNP 0x20
173#define S_P1_EOP 0x10
174#define S_P1_EDP 0x08
175#define S_P1_NSB 0x04
176#define S_P1_CHS_8 0x03
177#define S_P1_CHS_7 0x02
178#define S_P1_CHS_6 0x01
179#define S_P1_CHS_5 0x00
180
181#define S_P2_BFT_DEF 0x10
182
183#define IOM_CTRL_ENA 0x80
184#define IOM_CTRL_NOPCM 0x00
185#define IOM_CTRL_ALAW 0x02
186#define IOM_CTRL_ULAW 0x04
187#define IOM_CTRL_RCV 0x01
188
189#define IOM_P1_TXD 0x10
190
191#define HDLC_FED 0x40
192#define HDLC_FSD 0x20
193#define HDLC_FST 0x20
194#define HDLC_ERROR 0x1c
195#define HDLC_ERR_FAD 0x10
196#define HDLC_ERR_RER 0x08
197#define HDLC_ERR_CER 0x04
198#define SART_NMD 0x01
199
200#define BSTAT_RDM0 0x1
201#define BSTAT_RDM1 0x2
202#define BSTAT_RDM2 0x4
203#define BSTAT_RDM3 0x8
204#define BSTEV_TBO 0x1f
205#define BSTEV_RBO 0x2f
206
207/* FAX State Machine */
208#define STFAX_NULL 0
209#define STFAX_READY 1
210#define STFAX_LINE 2
211#define STFAX_CONT 3
212#define STFAX_ACTIV 4
213#define STFAX_ESCAPE 5
214#define STFAX_SILDET 6
215
216#define ISDN_FAXPUMP_HALT 100
217
218extern int ISARVersion(struct IsdnCardState *cs, char *s);
219extern void isar_int_main(struct IsdnCardState *cs);
220extern void initisar(struct IsdnCardState *cs);
221extern void isar_fill_fifo(struct BCState *bcs);
222extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic);
diff --git a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/hisax/isdnhdlc.c
new file mode 100644
index 00000000000..cbdf54c5af8
--- /dev/null
+++ b/drivers/isdn/hisax/isdnhdlc.c
@@ -0,0 +1,628 @@
1/*
2 * isdnhdlc.c -- General purpose ISDN HDLC decoder.
3 *
4 *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
5 * 2001 Frode Isaksen <fisaksen@bewan.com>
6 * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/crc-ccitt.h>
26#include "isdnhdlc.h"
27
28/*-------------------------------------------------------------------*/
29
30MODULE_AUTHOR("Wolfgang Mües <wolfgang@iksw-muees.de>, "
31 "Frode Isaksen <fisaksen@bewan.com>, "
32 "Kai Germaschewski <kai.germaschewski@gmx.de>");
33MODULE_DESCRIPTION("General purpose ISDN HDLC decoder");
34MODULE_LICENSE("GPL");
35
36/*-------------------------------------------------------------------*/
37
38/* bit swap table.
39 * Very handy for devices with different bit order,
40 * and neccessary for each transparent B-channel access for all
41 * devices which works with this HDLC decoder without bit reversal.
42 */
43const unsigned char isdnhdlc_bit_rev_tab[256] = {
44 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
45 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
46 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
47 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
48 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
49 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
50 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
51 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
52 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
53 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
54 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
55 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
56 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
57 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
58 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
59 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
60};
61
62enum {
63 HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
64 HDLC_GET_DATA,HDLC_FAST_FLAG
65};
66
67enum {
68 HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
69 HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
70 HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
71 HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
72};
73
74void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56)
75{
76 hdlc->bit_shift = 0;
77 hdlc->hdlc_bits1 = 0;
78 hdlc->data_bits = 0;
79 hdlc->ffbit_shift = 0;
80 hdlc->data_received = 0;
81 hdlc->state = HDLC_GET_DATA;
82 hdlc->do_adapt56 = do_adapt56;
83 hdlc->dchannel = 0;
84 hdlc->crc = 0;
85 hdlc->cbin = 0;
86 hdlc->shift_reg = 0;
87 hdlc->ffvalue = 0;
88 hdlc->dstpos = 0;
89}
90
91void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56)
92{
93 hdlc->bit_shift = 0;
94 hdlc->hdlc_bits1 = 0;
95 hdlc->data_bits = 0;
96 hdlc->ffbit_shift = 0;
97 hdlc->data_received = 0;
98 hdlc->do_closing = 0;
99 hdlc->ffvalue = 0;
100 if (is_d_channel) {
101 hdlc->dchannel = 1;
102 hdlc->state = HDLC_SEND_FIRST_FLAG;
103 } else {
104 hdlc->dchannel = 0;
105 hdlc->state = HDLC_SEND_FAST_FLAG;
106 hdlc->ffvalue = 0x7e;
107 }
108 hdlc->cbin = 0x7e;
109 hdlc->bit_shift = 0;
110 if(do_adapt56){
111 hdlc->do_adapt56 = 1;
112 hdlc->data_bits = 0;
113 hdlc->state = HDLC_SENDFLAG_B0;
114 } else {
115 hdlc->do_adapt56 = 0;
116 hdlc->data_bits = 8;
117 }
118 hdlc->shift_reg = 0;
119}
120
121/*
122 isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.
123
124 The source buffer is scanned for valid HDLC frames looking for
125 flags (01111110) to indicate the start of a frame. If the start of
126 the frame is found, the bit stuffing is removed (0 after 5 1's).
127 When a new flag is found, the complete frame has been received
128 and the CRC is checked.
129 If a valid frame is found, the function returns the frame length
130 excluding the CRC with the bit HDLC_END_OF_FRAME set.
131 If the beginning of a valid frame is found, the function returns
132 the length.
133 If a framing error is found (too many 1s and not a flag) the function
134 returns the length with the bit HDLC_FRAMING_ERROR set.
135 If a CRC error is found the function returns the length with the
136 bit HDLC_CRC_ERROR set.
137 If the frame length exceeds the destination buffer size, the function
138 returns the length with the bit HDLC_LENGTH_ERROR set.
139
140 src - source buffer
141 slen - source buffer length
142 count - number of bytes removed (decoded) from the source buffer
143 dst _ destination buffer
144 dsize - destination buffer size
145 returns - number of decoded bytes in the destination buffer and status
146 flag.
147 */
148int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src,
149 int slen, int *count, unsigned char *dst, int dsize)
150{
151 int status=0;
152
153 static const unsigned char fast_flag[]={
154 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
155 };
156
157 static const unsigned char fast_flag_value[]={
158 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
159 };
160
161 static const unsigned char fast_abort[]={
162 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
163 };
164
165 *count = slen;
166
167 while(slen > 0){
168 if(hdlc->bit_shift==0){
169 hdlc->cbin = *src++;
170 slen--;
171 hdlc->bit_shift = 8;
172 if(hdlc->do_adapt56){
173 hdlc->bit_shift --;
174 }
175 }
176
177 switch(hdlc->state){
178 case STOPPED:
179 return 0;
180 case HDLC_FAST_IDLE:
181 if(hdlc->cbin == 0xff){
182 hdlc->bit_shift = 0;
183 break;
184 }
185 hdlc->state = HDLC_GET_FLAG_B0;
186 hdlc->hdlc_bits1 = 0;
187 hdlc->bit_shift = 8;
188 break;
189 case HDLC_GET_FLAG_B0:
190 if(!(hdlc->cbin & 0x80)) {
191 hdlc->state = HDLC_GETFLAG_B1A6;
192 hdlc->hdlc_bits1 = 0;
193 } else {
194 if(!hdlc->do_adapt56){
195 if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
196 hdlc->state = HDLC_FAST_IDLE;
197 }
198 }
199 hdlc->cbin<<=1;
200 hdlc->bit_shift --;
201 break;
202 case HDLC_GETFLAG_B1A6:
203 if(hdlc->cbin & 0x80){
204 hdlc->hdlc_bits1++;
205 if(hdlc->hdlc_bits1==6){
206 hdlc->state = HDLC_GETFLAG_B7;
207 }
208 } else {
209 hdlc->hdlc_bits1 = 0;
210 }
211 hdlc->cbin<<=1;
212 hdlc->bit_shift --;
213 break;
214 case HDLC_GETFLAG_B7:
215 if(hdlc->cbin & 0x80) {
216 hdlc->state = HDLC_GET_FLAG_B0;
217 } else {
218 hdlc->state = HDLC_GET_DATA;
219 hdlc->crc = 0xffff;
220 hdlc->shift_reg = 0;
221 hdlc->hdlc_bits1 = 0;
222 hdlc->data_bits = 0;
223 hdlc->data_received = 0;
224 }
225 hdlc->cbin<<=1;
226 hdlc->bit_shift --;
227 break;
228 case HDLC_GET_DATA:
229 if(hdlc->cbin & 0x80){
230 hdlc->hdlc_bits1++;
231 switch(hdlc->hdlc_bits1){
232 case 6:
233 break;
234 case 7:
235 if(hdlc->data_received) {
236 // bad frame
237 status = -HDLC_FRAMING_ERROR;
238 }
239 if(!hdlc->do_adapt56){
240 if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
241 hdlc->state = HDLC_FAST_IDLE;
242 hdlc->bit_shift=1;
243 break;
244 }
245 } else {
246 hdlc->state = HDLC_GET_FLAG_B0;
247 }
248 break;
249 default:
250 hdlc->shift_reg>>=1;
251 hdlc->shift_reg |= 0x80;
252 hdlc->data_bits++;
253 break;
254 }
255 } else {
256 switch(hdlc->hdlc_bits1){
257 case 5:
258 break;
259 case 6:
260 if(hdlc->data_received){
261 if (hdlc->dstpos < 2) {
262 status = -HDLC_FRAMING_ERROR;
263 } else if (hdlc->crc != 0xf0b8){
264 // crc error
265 status = -HDLC_CRC_ERROR;
266 } else {
267 // remove CRC
268 hdlc->dstpos -= 2;
269 // good frame
270 status = hdlc->dstpos;
271 }
272 }
273 hdlc->crc = 0xffff;
274 hdlc->shift_reg = 0;
275 hdlc->data_bits = 0;
276 if(!hdlc->do_adapt56){
277 if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
278 hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
279 hdlc->state = HDLC_FAST_FLAG;
280 hdlc->ffbit_shift = hdlc->bit_shift;
281 hdlc->bit_shift = 1;
282 } else {
283 hdlc->state = HDLC_GET_DATA;
284 hdlc->data_received = 0;
285 }
286 } else {
287 hdlc->state = HDLC_GET_DATA;
288 hdlc->data_received = 0;
289 }
290 break;
291 default:
292 hdlc->shift_reg>>=1;
293 hdlc->data_bits++;
294 break;
295 }
296 hdlc->hdlc_bits1 = 0;
297 }
298 if (status) {
299 hdlc->dstpos = 0;
300 *count -= slen;
301 hdlc->cbin <<= 1;
302 hdlc->bit_shift--;
303 return status;
304 }
305 if(hdlc->data_bits==8){
306 hdlc->data_bits = 0;
307 hdlc->data_received = 1;
308 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
309
310 // good byte received
311 if (hdlc->dstpos < dsize) {
312 dst[hdlc->dstpos++] = hdlc->shift_reg;
313 } else {
314 // frame too long
315 status = -HDLC_LENGTH_ERROR;
316 hdlc->dstpos = 0;
317 }
318 }
319 hdlc->cbin <<= 1;
320 hdlc->bit_shift--;
321 break;
322 case HDLC_FAST_FLAG:
323 if(hdlc->cbin==hdlc->ffvalue){
324 hdlc->bit_shift = 0;
325 break;
326 } else {
327 if(hdlc->cbin == 0xff){
328 hdlc->state = HDLC_FAST_IDLE;
329 hdlc->bit_shift=0;
330 } else if(hdlc->ffbit_shift==8){
331 hdlc->state = HDLC_GETFLAG_B7;
332 break;
333 } else {
334 hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
335 hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
336 if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
337 hdlc->data_bits = hdlc->ffbit_shift-1;
338 hdlc->state = HDLC_GET_DATA;
339 hdlc->data_received = 0;
340 }
341 }
342 break;
343 default:
344 break;
345 }
346 }
347 *count -= slen;
348 return 0;
349}
350
351/*
352 isdnhdlc_encode - encodes HDLC frames to a transparent bit stream.
353
354 The bit stream starts with a beginning flag (01111110). After
355 that each byte is added to the bit stream with bit stuffing added
356 (0 after 5 1's).
357 When the last byte has been removed from the source buffer, the
358 CRC (2 bytes is added) and the frame terminates with the ending flag.
359 For the dchannel, the idle character (all 1's) is also added at the end.
360 If this function is called with empty source buffer (slen=0), flags or
361 idle character will be generated.
362
363 src - source buffer
364 slen - source buffer length
365 count - number of bytes removed (encoded) from source buffer
366 dst _ destination buffer
367 dsize - destination buffer size
368 returns - number of encoded bytes in the destination buffer
369*/
370int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
371 unsigned short slen, int *count,
372 unsigned char *dst, int dsize)
373{
374 static const unsigned char xfast_flag_value[] = {
375 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
376 };
377
378 int len = 0;
379
380 *count = slen;
381
382 while (dsize > 0) {
383 if(hdlc->bit_shift==0){
384 if(slen && !hdlc->do_closing){
385 hdlc->shift_reg = *src++;
386 slen--;
387 if (slen == 0)
388 hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */
389 hdlc->bit_shift = 8;
390 } else {
391 if(hdlc->state == HDLC_SEND_DATA){
392 if(hdlc->data_received){
393 hdlc->state = HDLC_SEND_CRC1;
394 hdlc->crc ^= 0xffff;
395 hdlc->bit_shift = 8;
396 hdlc->shift_reg = hdlc->crc & 0xff;
397 } else if(!hdlc->do_adapt56){
398 hdlc->state = HDLC_SEND_FAST_FLAG;
399 } else {
400 hdlc->state = HDLC_SENDFLAG_B0;
401 }
402 }
403
404 }
405 }
406
407 switch(hdlc->state){
408 case STOPPED:
409 while (dsize--)
410 *dst++ = 0xff;
411
412 return dsize;
413 case HDLC_SEND_FAST_FLAG:
414 hdlc->do_closing = 0;
415 if(slen == 0){
416 *dst++ = hdlc->ffvalue;
417 len++;
418 dsize--;
419 break;
420 }
421 if(hdlc->bit_shift==8){
422 hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
423 hdlc->state = HDLC_SEND_DATA;
424 hdlc->crc = 0xffff;
425 hdlc->hdlc_bits1 = 0;
426 hdlc->data_received = 1;
427 }
428 break;
429 case HDLC_SENDFLAG_B0:
430 hdlc->do_closing = 0;
431 hdlc->cbin <<= 1;
432 hdlc->data_bits++;
433 hdlc->hdlc_bits1 = 0;
434 hdlc->state = HDLC_SENDFLAG_B1A6;
435 break;
436 case HDLC_SENDFLAG_B1A6:
437 hdlc->cbin <<= 1;
438 hdlc->data_bits++;
439 hdlc->cbin++;
440 if(++hdlc->hdlc_bits1 == 6)
441 hdlc->state = HDLC_SENDFLAG_B7;
442 break;
443 case HDLC_SENDFLAG_B7:
444 hdlc->cbin <<= 1;
445 hdlc->data_bits++;
446 if(slen == 0){
447 hdlc->state = HDLC_SENDFLAG_B0;
448 break;
449 }
450 if(hdlc->bit_shift==8){
451 hdlc->state = HDLC_SEND_DATA;
452 hdlc->crc = 0xffff;
453 hdlc->hdlc_bits1 = 0;
454 hdlc->data_received = 1;
455 }
456 break;
457 case HDLC_SEND_FIRST_FLAG:
458 hdlc->data_received = 1;
459 if(hdlc->data_bits==8){
460 hdlc->state = HDLC_SEND_DATA;
461 hdlc->crc = 0xffff;
462 hdlc->hdlc_bits1 = 0;
463 break;
464 }
465 hdlc->cbin <<= 1;
466 hdlc->data_bits++;
467 if(hdlc->shift_reg & 0x01)
468 hdlc->cbin++;
469 hdlc->shift_reg >>= 1;
470 hdlc->bit_shift--;
471 if(hdlc->bit_shift==0){
472 hdlc->state = HDLC_SEND_DATA;
473 hdlc->crc = 0xffff;
474 hdlc->hdlc_bits1 = 0;
475 }
476 break;
477 case HDLC_SEND_DATA:
478 hdlc->cbin <<= 1;
479 hdlc->data_bits++;
480 if(hdlc->hdlc_bits1 == 5){
481 hdlc->hdlc_bits1 = 0;
482 break;
483 }
484 if(hdlc->bit_shift==8){
485 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
486 }
487 if(hdlc->shift_reg & 0x01){
488 hdlc->hdlc_bits1++;
489 hdlc->cbin++;
490 hdlc->shift_reg >>= 1;
491 hdlc->bit_shift--;
492 } else {
493 hdlc->hdlc_bits1 = 0;
494 hdlc->shift_reg >>= 1;
495 hdlc->bit_shift--;
496 }
497 break;
498 case HDLC_SEND_CRC1:
499 hdlc->cbin <<= 1;
500 hdlc->data_bits++;
501 if(hdlc->hdlc_bits1 == 5){
502 hdlc->hdlc_bits1 = 0;
503 break;
504 }
505 if(hdlc->shift_reg & 0x01){
506 hdlc->hdlc_bits1++;
507 hdlc->cbin++;
508 hdlc->shift_reg >>= 1;
509 hdlc->bit_shift--;
510 } else {
511 hdlc->hdlc_bits1 = 0;
512 hdlc->shift_reg >>= 1;
513 hdlc->bit_shift--;
514 }
515 if(hdlc->bit_shift==0){
516 hdlc->shift_reg = (hdlc->crc >> 8);
517 hdlc->state = HDLC_SEND_CRC2;
518 hdlc->bit_shift = 8;
519 }
520 break;
521 case HDLC_SEND_CRC2:
522 hdlc->cbin <<= 1;
523 hdlc->data_bits++;
524 if(hdlc->hdlc_bits1 == 5){
525 hdlc->hdlc_bits1 = 0;
526 break;
527 }
528 if(hdlc->shift_reg & 0x01){
529 hdlc->hdlc_bits1++;
530 hdlc->cbin++;
531 hdlc->shift_reg >>= 1;
532 hdlc->bit_shift--;
533 } else {
534 hdlc->hdlc_bits1 = 0;
535 hdlc->shift_reg >>= 1;
536 hdlc->bit_shift--;
537 }
538 if(hdlc->bit_shift==0){
539 hdlc->shift_reg = 0x7e;
540 hdlc->state = HDLC_SEND_CLOSING_FLAG;
541 hdlc->bit_shift = 8;
542 }
543 break;
544 case HDLC_SEND_CLOSING_FLAG:
545 hdlc->cbin <<= 1;
546 hdlc->data_bits++;
547 if(hdlc->hdlc_bits1 == 5){
548 hdlc->hdlc_bits1 = 0;
549 break;
550 }
551 if(hdlc->shift_reg & 0x01){
552 hdlc->cbin++;
553 }
554 hdlc->shift_reg >>= 1;
555 hdlc->bit_shift--;
556 if(hdlc->bit_shift==0){
557 hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
558 if(hdlc->dchannel){
559 hdlc->ffvalue = 0x7e;
560 hdlc->state = HDLC_SEND_IDLE1;
561 hdlc->bit_shift = 8-hdlc->data_bits;
562 if(hdlc->bit_shift==0)
563 hdlc->state = HDLC_SEND_FAST_IDLE;
564 } else {
565 if(!hdlc->do_adapt56){
566 hdlc->state = HDLC_SEND_FAST_FLAG;
567 hdlc->data_received = 0;
568 } else {
569 hdlc->state = HDLC_SENDFLAG_B0;
570 hdlc->data_received = 0;
571 }
572 // Finished with this frame, send flags
573 if (dsize > 1) dsize = 1;
574 }
575 }
576 break;
577 case HDLC_SEND_IDLE1:
578 hdlc->do_closing = 0;
579 hdlc->cbin <<= 1;
580 hdlc->cbin++;
581 hdlc->data_bits++;
582 hdlc->bit_shift--;
583 if(hdlc->bit_shift==0){
584 hdlc->state = HDLC_SEND_FAST_IDLE;
585 hdlc->bit_shift = 0;
586 }
587 break;
588 case HDLC_SEND_FAST_IDLE:
589 hdlc->do_closing = 0;
590 hdlc->cbin = 0xff;
591 hdlc->data_bits = 8;
592 if(hdlc->bit_shift == 8){
593 hdlc->cbin = 0x7e;
594 hdlc->state = HDLC_SEND_FIRST_FLAG;
595 } else {
596 *dst++ = hdlc->cbin;
597 hdlc->bit_shift = hdlc->data_bits = 0;
598 len++;
599 dsize = 0;
600 }
601 break;
602 default:
603 break;
604 }
605 if(hdlc->do_adapt56){
606 if(hdlc->data_bits==7){
607 hdlc->cbin <<= 1;
608 hdlc->cbin++;
609 hdlc->data_bits++;
610 }
611 }
612 if(hdlc->data_bits==8){
613 *dst++ = hdlc->cbin;
614 hdlc->data_bits = 0;
615 len++;
616 dsize--;
617 }
618 }
619 *count -= slen;
620
621 return len;
622}
623
624EXPORT_SYMBOL(isdnhdlc_bit_rev_tab);
625EXPORT_SYMBOL(isdnhdlc_rcv_init);
626EXPORT_SYMBOL(isdnhdlc_decode);
627EXPORT_SYMBOL(isdnhdlc_out_init);
628EXPORT_SYMBOL(isdnhdlc_encode);
diff --git a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h
new file mode 100644
index 00000000000..269315988dc
--- /dev/null
+++ b/drivers/isdn/hisax/isdnhdlc.h
@@ -0,0 +1,72 @@
1/*
2 * isdnhdlc.h -- General purpose ISDN HDLC decoder.
3 *
4 * Implementation of a HDLC decoder/encoder in software.
5 * Neccessary because some ISDN devices don't have HDLC
6 * controllers. Also included: a bit reversal table.
7 *
8 *Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
9 * 2001 Frode Isaksen <fisaksen@bewan.com>
10 * 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#ifndef __ISDNHDLC_H__
28#define __ISDNHDLC_H__
29
30struct isdnhdlc_vars {
31 int bit_shift;
32 int hdlc_bits1;
33 int data_bits;
34 int ffbit_shift; // encoding only
35 int state;
36 int dstpos;
37
38 unsigned short crc;
39
40 unsigned char cbin;
41 unsigned char shift_reg;
42 unsigned char ffvalue;
43
44 int data_received:1; // set if transferring data
45 int dchannel:1; // set if D channel (send idle instead of flags)
46 int do_adapt56:1; // set if 56K adaptation
47 int do_closing:1; // set if in closing phase (need to send CRC + flag
48};
49
50
51/*
52 The return value from isdnhdlc_decode is
53 the frame length, 0 if no complete frame was decoded,
54 or a negative error number
55*/
56#define HDLC_FRAMING_ERROR 1
57#define HDLC_CRC_ERROR 2
58#define HDLC_LENGTH_ERROR 3
59
60extern const unsigned char isdnhdlc_bit_rev_tab[256];
61
62extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56);
63
64extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
65 unsigned char *dst, int dsize);
66
67extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56);
68
69extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
70 unsigned char *dst,int dsize);
71
72#endif /* __ISDNHDLC_H__ */
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
new file mode 100644
index 00000000000..4d08d27f149
--- /dev/null
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -0,0 +1,932 @@
1/* $Id: isdnl1.c,v 2.46.2.5 2004/02/11 13:21:34 keil Exp $
2 *
3 * common low level stuff for Siemens Chipsetbased isdn cards
4 *
5 * Author Karsten Keil
6 * based on the teles driver from Jan den Ouden
7 * Copyright by Karsten Keil <keil@isdn4linux.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 * For changes and modifications please read
13 * Documentation/isdn/HiSax.cert
14 *
15 * Thanks to Jan den Ouden
16 * Fritz Elfert
17 * Beat Doebeli
18 *
19 */
20
21const char *l1_revision = "$Revision: 2.46.2.5 $";
22
23#include <linux/init.h>
24#include "hisax.h"
25#include "isdnl1.h"
26
27#define TIMER3_VALUE 7000
28
29static struct Fsm l1fsm_b;
30static struct Fsm l1fsm_s;
31
32enum {
33 ST_L1_F2,
34 ST_L1_F3,
35 ST_L1_F4,
36 ST_L1_F5,
37 ST_L1_F6,
38 ST_L1_F7,
39 ST_L1_F8,
40};
41
42#define L1S_STATE_COUNT (ST_L1_F8+1)
43
44static char *strL1SState[] =
45{
46 "ST_L1_F2",
47 "ST_L1_F3",
48 "ST_L1_F4",
49 "ST_L1_F5",
50 "ST_L1_F6",
51 "ST_L1_F7",
52 "ST_L1_F8",
53};
54
55#ifdef HISAX_UINTERFACE
56static
57struct Fsm l1fsm_u =
58{NULL, 0, 0, NULL, NULL};
59
60enum {
61 ST_L1_RESET,
62 ST_L1_DEACT,
63 ST_L1_SYNC2,
64 ST_L1_TRANS,
65};
66
67#define L1U_STATE_COUNT (ST_L1_TRANS+1)
68
69static char *strL1UState[] =
70{
71 "ST_L1_RESET",
72 "ST_L1_DEACT",
73 "ST_L1_SYNC2",
74 "ST_L1_TRANS",
75};
76#endif
77
78enum {
79 ST_L1_NULL,
80 ST_L1_WAIT_ACT,
81 ST_L1_WAIT_DEACT,
82 ST_L1_ACTIV,
83};
84
85#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
86
87static char *strL1BState[] =
88{
89 "ST_L1_NULL",
90 "ST_L1_WAIT_ACT",
91 "ST_L1_WAIT_DEACT",
92 "ST_L1_ACTIV",
93};
94
95enum {
96 EV_PH_ACTIVATE,
97 EV_PH_DEACTIVATE,
98 EV_RESET_IND,
99 EV_DEACT_CNF,
100 EV_DEACT_IND,
101 EV_POWER_UP,
102 EV_RSYNC_IND,
103 EV_INFO2_IND,
104 EV_INFO4_IND,
105 EV_TIMER_DEACT,
106 EV_TIMER_ACT,
107 EV_TIMER3,
108};
109
110#define L1_EVENT_COUNT (EV_TIMER3 + 1)
111
112static char *strL1Event[] =
113{
114 "EV_PH_ACTIVATE",
115 "EV_PH_DEACTIVATE",
116 "EV_RESET_IND",
117 "EV_DEACT_CNF",
118 "EV_DEACT_IND",
119 "EV_POWER_UP",
120 "EV_RSYNC_IND",
121 "EV_INFO2_IND",
122 "EV_INFO4_IND",
123 "EV_TIMER_DEACT",
124 "EV_TIMER_ACT",
125 "EV_TIMER3",
126};
127
128void
129debugl1(struct IsdnCardState *cs, char *fmt, ...)
130{
131 va_list args;
132 char tmp[8];
133
134 va_start(args, fmt);
135 sprintf(tmp, "Card%d ", cs->cardnr + 1);
136 VHiSax_putstatus(cs, tmp, fmt, args);
137 va_end(args);
138}
139
140static void
141l1m_debug(struct FsmInst *fi, char *fmt, ...)
142{
143 va_list args;
144 struct PStack *st = fi->userdata;
145 struct IsdnCardState *cs = st->l1.hardware;
146 char tmp[8];
147
148 va_start(args, fmt);
149 sprintf(tmp, "Card%d ", cs->cardnr + 1);
150 VHiSax_putstatus(cs, tmp, fmt, args);
151 va_end(args);
152}
153
154void
155L1activated(struct IsdnCardState *cs)
156{
157 struct PStack *st;
158
159 st = cs->stlist;
160 while (st) {
161 if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
162 st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
163 else
164 st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL);
165 st = st->next;
166 }
167}
168
169void
170L1deactivated(struct IsdnCardState *cs)
171{
172 struct PStack *st;
173
174 st = cs->stlist;
175 while (st) {
176 if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
177 st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
178 st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL);
179 st = st->next;
180 }
181 test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
182}
183
184void
185DChannel_proc_xmt(struct IsdnCardState *cs)
186{
187 struct PStack *stptr;
188
189 if (cs->tx_skb)
190 return;
191
192 stptr = cs->stlist;
193 while (stptr != NULL) {
194 if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) {
195 stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL);
196 break;
197 } else
198 stptr = stptr->next;
199 }
200}
201
202void
203DChannel_proc_rcv(struct IsdnCardState *cs)
204{
205 struct sk_buff *skb, *nskb;
206 struct PStack *stptr = cs->stlist;
207 int found, tei, sapi;
208
209 if (stptr)
210 if (test_bit(FLG_L1_ACTTIMER, &stptr->l1.Flags))
211 FsmEvent(&stptr->l1.l1m, EV_TIMER_ACT, NULL);
212 while ((skb = skb_dequeue(&cs->rq))) {
213#ifdef L2FRAME_DEBUG /* psa */
214 if (cs->debug & L1_DEB_LAPD)
215 Logl2Frame(cs, skb, "PH_DATA", 1);
216#endif
217 stptr = cs->stlist;
218 if (skb->len<3) {
219 debugl1(cs, "D-channel frame too short(%d)",skb->len);
220 dev_kfree_skb(skb);
221 return;
222 }
223 if ((skb->data[0] & 1) || !(skb->data[1] &1)) {
224 debugl1(cs, "D-channel frame wrong EA0/EA1");
225 dev_kfree_skb(skb);
226 return;
227 }
228 sapi = skb->data[0] >> 2;
229 tei = skb->data[1] >> 1;
230 if (cs->debug & DEB_DLOG_HEX)
231 LogFrame(cs, skb->data, skb->len);
232 if (cs->debug & DEB_DLOG_VERBOSE)
233 dlogframe(cs, skb, 1);
234 if (tei == GROUP_TEI) {
235 if (sapi == CTRL_SAPI) { /* sapi 0 */
236 while (stptr != NULL) {
237 if ((nskb = skb_clone(skb, GFP_ATOMIC)))
238 stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb);
239 else
240 printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n");
241 stptr = stptr->next;
242 }
243 } else if (sapi == TEI_SAPI) {
244 while (stptr != NULL) {
245 if ((nskb = skb_clone(skb, GFP_ATOMIC)))
246 stptr->l1.l1tei(stptr, PH_DATA | INDICATION, nskb);
247 else
248 printk(KERN_WARNING "HiSax: tei broadcast buffer shortage\n");
249 stptr = stptr->next;
250 }
251 }
252 dev_kfree_skb(skb);
253 } else if (sapi == CTRL_SAPI) { /* sapi 0 */
254 found = 0;
255 while (stptr != NULL)
256 if (tei == stptr->l2.tei) {
257 stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb);
258 found = !0;
259 break;
260 } else
261 stptr = stptr->next;
262 if (!found)
263 dev_kfree_skb(skb);
264 } else
265 dev_kfree_skb(skb);
266 }
267}
268
269static void
270BChannel_proc_xmt(struct BCState *bcs)
271{
272 struct PStack *st = bcs->st;
273
274 if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {
275 debugl1(bcs->cs, "BC_BUSY Error");
276 return;
277 }
278
279 if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))
280 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
281 if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {
282 if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) {
283 st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
284 }
285 }
286}
287
288static void
289BChannel_proc_rcv(struct BCState *bcs)
290{
291 struct sk_buff *skb;
292
293 if (bcs->st->l1.l1m.state == ST_L1_WAIT_ACT) {
294 FsmDelTimer(&bcs->st->l1.timer, 4);
295 FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL);
296 }
297 while ((skb = skb_dequeue(&bcs->rqueue))) {
298 bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb);
299 }
300}
301
302static void
303BChannel_proc_ack(struct BCState *bcs)
304{
305 u_long flags;
306 int ack;
307
308 spin_lock_irqsave(&bcs->aclock, flags);
309 ack = bcs->ackcnt;
310 bcs->ackcnt = 0;
311 spin_unlock_irqrestore(&bcs->aclock, flags);
312 if (ack)
313 lli_writewakeup(bcs->st, ack);
314}
315
316void
317BChannel_bh(struct BCState *bcs)
318{
319 if (!bcs)
320 return;
321 if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event))
322 BChannel_proc_rcv(bcs);
323 if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event))
324 BChannel_proc_xmt(bcs);
325 if (test_and_clear_bit(B_ACKPENDING, &bcs->event))
326 BChannel_proc_ack(bcs);
327}
328
329void
330HiSax_addlist(struct IsdnCardState *cs,
331 struct PStack *st)
332{
333 st->next = cs->stlist;
334 cs->stlist = st;
335}
336
337void
338HiSax_rmlist(struct IsdnCardState *cs,
339 struct PStack *st)
340{
341 struct PStack *p;
342
343 FsmDelTimer(&st->l1.timer, 0);
344 if (cs->stlist == st)
345 cs->stlist = st->next;
346 else {
347 p = cs->stlist;
348 while (p)
349 if (p->next == st) {
350 p->next = st->next;
351 return;
352 } else
353 p = p->next;
354 }
355}
356
357void
358init_bcstate(struct IsdnCardState *cs, int bc)
359{
360 struct BCState *bcs = cs->bcs + bc;
361
362 bcs->cs = cs;
363 bcs->channel = bc;
364 INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs);
365 spin_lock_init(&bcs->aclock);
366 bcs->BC_SetStack = NULL;
367 bcs->BC_Close = NULL;
368 bcs->Flag = 0;
369}
370
371#ifdef L2FRAME_DEBUG /* psa */
372
373char *
374l2cmd(u_char cmd)
375{
376 switch (cmd & ~0x10) {
377 case 1:
378 return "RR";
379 case 5:
380 return "RNR";
381 case 9:
382 return "REJ";
383 case 0x6f:
384 return "SABME";
385 case 0x0f:
386 return "DM";
387 case 3:
388 return "UI";
389 case 0x43:
390 return "DISC";
391 case 0x63:
392 return "UA";
393 case 0x87:
394 return "FRMR";
395 case 0xaf:
396 return "XID";
397 default:
398 if (!(cmd & 1))
399 return "I";
400 else
401 return "invalid command";
402 }
403}
404
405static char tmpdeb[32];
406
407char *
408l2frames(u_char * ptr)
409{
410 switch (ptr[2] & ~0x10) {
411 case 1:
412 case 5:
413 case 9:
414 sprintf(tmpdeb, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);
415 break;
416 case 0x6f:
417 case 0x0f:
418 case 3:
419 case 0x43:
420 case 0x63:
421 case 0x87:
422 case 0xaf:
423 sprintf(tmpdeb, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);
424 break;
425 default:
426 if (!(ptr[2] & 1)) {
427 sprintf(tmpdeb, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);
428 break;
429 } else
430 return "invalid command";
431 }
432
433
434 return tmpdeb;
435}
436
437void
438Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir)
439{
440 u_char *ptr;
441
442 ptr = skb->data;
443
444 if (ptr[0] & 1 || !(ptr[1] & 1))
445 debugl1(cs, "Address not LAPD");
446 else
447 debugl1(cs, "%s %s: %s%c (sapi %d, tei %d)",
448 (dir ? "<-" : "->"), buf, l2frames(ptr),
449 ((ptr[0] & 2) >> 1) == dir ? 'C' : 'R', ptr[0] >> 2, ptr[1] >> 1);
450}
451#endif
452
453static void
454l1_reset(struct FsmInst *fi, int event, void *arg)
455{
456 FsmChangeState(fi, ST_L1_F3);
457}
458
459static void
460l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
461{
462 struct PStack *st = fi->userdata;
463
464 FsmChangeState(fi, ST_L1_F3);
465 if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
466 st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
467}
468
469static void
470l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
471{
472 struct PStack *st = fi->userdata;
473
474 FsmChangeState(fi, ST_L1_F3);
475 FsmRestartTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
476 test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
477}
478
479static void
480l1_power_up_s(struct FsmInst *fi, int event, void *arg)
481{
482 struct PStack *st = fi->userdata;
483
484 if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) {
485 FsmChangeState(fi, ST_L1_F4);
486 st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
487 FsmRestartTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
488 test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
489 } else
490 FsmChangeState(fi, ST_L1_F3);
491}
492
493static void
494l1_go_F5(struct FsmInst *fi, int event, void *arg)
495{
496 FsmChangeState(fi, ST_L1_F5);
497}
498
499static void
500l1_go_F8(struct FsmInst *fi, int event, void *arg)
501{
502 FsmChangeState(fi, ST_L1_F8);
503}
504
505static void
506l1_info2_ind(struct FsmInst *fi, int event, void *arg)
507{
508 struct PStack *st = fi->userdata;
509
510#ifdef HISAX_UINTERFACE
511 if (test_bit(FLG_L1_UINT, &st->l1.Flags))
512 FsmChangeState(fi, ST_L1_SYNC2);
513 else
514#endif
515 FsmChangeState(fi, ST_L1_F6);
516 st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
517}
518
519static void
520l1_info4_ind(struct FsmInst *fi, int event, void *arg)
521{
522 struct PStack *st = fi->userdata;
523
524#ifdef HISAX_UINTERFACE
525 if (test_bit(FLG_L1_UINT, &st->l1.Flags))
526 FsmChangeState(fi, ST_L1_TRANS);
527 else
528#endif
529 FsmChangeState(fi, ST_L1_F7);
530 st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
531 if (test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags))
532 FsmDelTimer(&st->l1.timer, 4);
533 if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) {
534 if (test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags))
535 FsmDelTimer(&st->l1.timer, 3);
536 FsmRestartTimer(&st->l1.timer, 110, EV_TIMER_ACT, NULL, 2);
537 test_and_set_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
538 }
539}
540
541static void
542l1_timer3(struct FsmInst *fi, int event, void *arg)
543{
544 struct PStack *st = fi->userdata;
545
546 test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags);
547 if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
548 L1deactivated(st->l1.hardware);
549
550#ifdef HISAX_UINTERFACE
551 if (!test_bit(FLG_L1_UINT, &st->l1.Flags))
552#endif
553 if (st->l1.l1m.state != ST_L1_F6) {
554 FsmChangeState(fi, ST_L1_F3);
555 st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
556 }
557}
558
559static void
560l1_timer_act(struct FsmInst *fi, int event, void *arg)
561{
562 struct PStack *st = fi->userdata;
563
564 test_and_clear_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
565 test_and_set_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
566 L1activated(st->l1.hardware);
567}
568
569static void
570l1_timer_deact(struct FsmInst *fi, int event, void *arg)
571{
572 struct PStack *st = fi->userdata;
573
574 test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
575 test_and_clear_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
576 L1deactivated(st->l1.hardware);
577 st->l1.l1hw(st, HW_DEACTIVATE | RESPONSE, NULL);
578}
579
580static void
581l1_activate_s(struct FsmInst *fi, int event, void *arg)
582{
583 struct PStack *st = fi->userdata;
584
585 st->l1.l1hw(st, HW_RESET | REQUEST, NULL);
586}
587
588static void
589l1_activate_no(struct FsmInst *fi, int event, void *arg)
590{
591 struct PStack *st = fi->userdata;
592
593 if ((!test_bit(FLG_L1_DEACTTIMER, &st->l1.Flags)) && (!test_bit(FLG_L1_T3RUN, &st->l1.Flags))) {
594 test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
595 L1deactivated(st->l1.hardware);
596 }
597}
598
599static struct FsmNode L1SFnList[] __initdata =
600{
601 {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
602 {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
603 {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
604 {ST_L1_F3, EV_RESET_IND, l1_reset},
605 {ST_L1_F4, EV_RESET_IND, l1_reset},
606 {ST_L1_F5, EV_RESET_IND, l1_reset},
607 {ST_L1_F6, EV_RESET_IND, l1_reset},
608 {ST_L1_F7, EV_RESET_IND, l1_reset},
609 {ST_L1_F8, EV_RESET_IND, l1_reset},
610 {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
611 {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
612 {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
613 {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
614 {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
615 {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
616 {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
617 {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
618 {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
619 {ST_L1_F3, EV_POWER_UP, l1_power_up_s},
620 {ST_L1_F4, EV_RSYNC_IND, l1_go_F5},
621 {ST_L1_F6, EV_RSYNC_IND, l1_go_F8},
622 {ST_L1_F7, EV_RSYNC_IND, l1_go_F8},
623 {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
624 {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
625 {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
626 {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
627 {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
628 {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
629 {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
630 {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
631 {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
632 {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
633 {ST_L1_F3, EV_TIMER3, l1_timer3},
634 {ST_L1_F4, EV_TIMER3, l1_timer3},
635 {ST_L1_F5, EV_TIMER3, l1_timer3},
636 {ST_L1_F6, EV_TIMER3, l1_timer3},
637 {ST_L1_F8, EV_TIMER3, l1_timer3},
638 {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
639 {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
640 {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
641 {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
642 {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
643 {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
644 {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
645};
646
647#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
648
649#ifdef HISAX_UINTERFACE
650static void
651l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
652{
653 struct PStack *st = fi->userdata;
654
655 FsmChangeState(fi, ST_L1_RESET);
656 FsmRestartTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
657 test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
658 st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
659}
660
661static void
662l1_power_up_u(struct FsmInst *fi, int event, void *arg)
663{
664 struct PStack *st = fi->userdata;
665
666 FsmRestartTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
667 test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
668}
669
670static void
671l1_info0_ind(struct FsmInst *fi, int event, void *arg)
672{
673 FsmChangeState(fi, ST_L1_DEACT);
674}
675
676static void
677l1_activate_u(struct FsmInst *fi, int event, void *arg)
678{
679 struct PStack *st = fi->userdata;
680
681 st->l1.l1hw(st, HW_INFO1 | REQUEST, NULL);
682}
683
684static struct FsmNode L1UFnList[] __initdata =
685{
686 {ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u},
687 {ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u},
688 {ST_L1_SYNC2, EV_DEACT_IND, l1_deact_req_u},
689 {ST_L1_TRANS, EV_DEACT_IND, l1_deact_req_u},
690 {ST_L1_DEACT, EV_PH_ACTIVATE, l1_activate_u},
691 {ST_L1_DEACT, EV_POWER_UP, l1_power_up_u},
692 {ST_L1_DEACT, EV_INFO2_IND, l1_info2_ind},
693 {ST_L1_TRANS, EV_INFO2_IND, l1_info2_ind},
694 {ST_L1_RESET, EV_DEACT_CNF, l1_info0_ind},
695 {ST_L1_DEACT, EV_INFO4_IND, l1_info4_ind},
696 {ST_L1_SYNC2, EV_INFO4_IND, l1_info4_ind},
697 {ST_L1_RESET, EV_INFO4_IND, l1_info4_ind},
698 {ST_L1_DEACT, EV_TIMER3, l1_timer3},
699 {ST_L1_SYNC2, EV_TIMER3, l1_timer3},
700 {ST_L1_TRANS, EV_TIMER_ACT, l1_timer_act},
701 {ST_L1_DEACT, EV_TIMER_DEACT, l1_timer_deact},
702 {ST_L1_SYNC2, EV_TIMER_DEACT, l1_timer_deact},
703 {ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
704};
705
706#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
707
708#endif
709
710static void
711l1b_activate(struct FsmInst *fi, int event, void *arg)
712{
713 struct PStack *st = fi->userdata;
714
715 FsmChangeState(fi, ST_L1_WAIT_ACT);
716 FsmRestartTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
717}
718
719static void
720l1b_deactivate(struct FsmInst *fi, int event, void *arg)
721{
722 struct PStack *st = fi->userdata;
723
724 FsmChangeState(fi, ST_L1_WAIT_DEACT);
725 FsmRestartTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
726}
727
728static void
729l1b_timer_act(struct FsmInst *fi, int event, void *arg)
730{
731 struct PStack *st = fi->userdata;
732
733 FsmChangeState(fi, ST_L1_ACTIV);
734 st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
735}
736
737static void
738l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
739{
740 struct PStack *st = fi->userdata;
741
742 FsmChangeState(fi, ST_L1_NULL);
743 st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
744}
745
746static struct FsmNode L1BFnList[] __initdata =
747{
748 {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
749 {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
750 {ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
751 {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
752};
753
754#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
755
756int __init
757Isdnl1New(void)
758{
759 int retval;
760
761 l1fsm_s.state_count = L1S_STATE_COUNT;
762 l1fsm_s.event_count = L1_EVENT_COUNT;
763 l1fsm_s.strEvent = strL1Event;
764 l1fsm_s.strState = strL1SState;
765 retval = FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
766 if (retval)
767 return retval;
768
769 l1fsm_b.state_count = L1B_STATE_COUNT;
770 l1fsm_b.event_count = L1_EVENT_COUNT;
771 l1fsm_b.strEvent = strL1Event;
772 l1fsm_b.strState = strL1BState;
773 retval = FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
774 if (retval) {
775 FsmFree(&l1fsm_s);
776 return retval;
777 }
778#ifdef HISAX_UINTERFACE
779 l1fsm_u.state_count = L1U_STATE_COUNT;
780 l1fsm_u.event_count = L1_EVENT_COUNT;
781 l1fsm_u.strEvent = strL1Event;
782 l1fsm_u.strState = strL1UState;
783 retval = FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
784 if (retval) {
785 FsmFree(&l1fsm_s);
786 FsmFree(&l1fsm_b);
787 return retval;
788 }
789#endif
790 return 0;
791}
792
793void Isdnl1Free(void)
794{
795#ifdef HISAX_UINTERFACE
796 FsmFree(&l1fsm_u);
797#endif
798 FsmFree(&l1fsm_s);
799 FsmFree(&l1fsm_b);
800}
801
802static void
803dch_l2l1(struct PStack *st, int pr, void *arg)
804{
805 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
806
807 switch (pr) {
808 case (PH_DATA | REQUEST):
809 case (PH_PULL | REQUEST):
810 case (PH_PULL |INDICATION):
811 st->l1.l1hw(st, pr, arg);
812 break;
813 case (PH_ACTIVATE | REQUEST):
814 if (cs->debug)
815 debugl1(cs, "PH_ACTIVATE_REQ %s",
816 st->l1.l1m.fsm->strState[st->l1.l1m.state]);
817 if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags))
818 st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
819 else {
820 test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
821 FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg);
822 }
823 break;
824 case (PH_TESTLOOP | REQUEST):
825 if (1 & (long) arg)
826 debugl1(cs, "PH_TEST_LOOP B1");
827 if (2 & (long) arg)
828 debugl1(cs, "PH_TEST_LOOP B2");
829 if (!(3 & (long) arg))
830 debugl1(cs, "PH_TEST_LOOP DISABLED");
831 st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
832 break;
833 default:
834 if (cs->debug)
835 debugl1(cs, "dch_l2l1 msg %04X unhandled", pr);
836 break;
837 }
838}
839
840void
841l1_msg(struct IsdnCardState *cs, int pr, void *arg) {
842 struct PStack *st;
843
844 st = cs->stlist;
845
846 while (st) {
847 switch(pr) {
848 case (HW_RESET | INDICATION):
849 FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
850 break;
851 case (HW_DEACTIVATE | CONFIRM):
852 FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
853 break;
854 case (HW_DEACTIVATE | INDICATION):
855 FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
856 break;
857 case (HW_POWERUP | CONFIRM):
858 FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
859 break;
860 case (HW_RSYNC | INDICATION):
861 FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
862 break;
863 case (HW_INFO2 | INDICATION):
864 FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
865 break;
866 case (HW_INFO4_P8 | INDICATION):
867 case (HW_INFO4_P10 | INDICATION):
868 FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
869 break;
870 default:
871 if (cs->debug)
872 debugl1(cs, "l1msg %04X unhandled", pr);
873 break;
874 }
875 st = st->next;
876 }
877}
878
879void
880l1_msg_b(struct PStack *st, int pr, void *arg) {
881 switch(pr) {
882 case (PH_ACTIVATE | REQUEST):
883 FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, NULL);
884 break;
885 case (PH_DEACTIVATE | REQUEST):
886 FsmEvent(&st->l1.l1m, EV_PH_DEACTIVATE, NULL);
887 break;
888 }
889}
890
891void
892setstack_HiSax(struct PStack *st, struct IsdnCardState *cs)
893{
894 st->l1.hardware = cs;
895 st->protocol = cs->protocol;
896 st->l1.l1m.fsm = &l1fsm_s;
897 st->l1.l1m.state = ST_L1_F3;
898 st->l1.Flags = 0;
899#ifdef HISAX_UINTERFACE
900 if (test_bit(FLG_HW_L1_UINT, &cs->HW_Flags)) {
901 st->l1.l1m.fsm = &l1fsm_u;
902 st->l1.l1m.state = ST_L1_RESET;
903 st->l1.Flags = FLG_L1_UINT;
904 }
905#endif
906 st->l1.l1m.debug = cs->debug;
907 st->l1.l1m.userdata = st;
908 st->l1.l1m.userint = 0;
909 st->l1.l1m.printdebug = l1m_debug;
910 FsmInitTimer(&st->l1.l1m, &st->l1.timer);
911 setstack_tei(st);
912 setstack_manager(st);
913 st->l1.stlistp = &(cs->stlist);
914 st->l2.l2l1 = dch_l2l1;
915 if (cs->setstack_d)
916 cs->setstack_d(st, cs);
917}
918
919void
920setstack_l1_B(struct PStack *st)
921{
922 struct IsdnCardState *cs = st->l1.hardware;
923
924 st->l1.l1m.fsm = &l1fsm_b;
925 st->l1.l1m.state = ST_L1_NULL;
926 st->l1.l1m.debug = cs->debug;
927 st->l1.l1m.userdata = st;
928 st->l1.l1m.userint = 0;
929 st->l1.l1m.printdebug = l1m_debug;
930 st->l1.Flags = 0;
931 FsmInitTimer(&st->l1.l1m, &st->l1.timer);
932}
diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
new file mode 100644
index 00000000000..0e88cfabdf1
--- /dev/null
+++ b/drivers/isdn/hisax/isdnl1.h
@@ -0,0 +1,32 @@
1/* $Id: isdnl1.h,v 2.12.2.3 2004/02/11 13:21:34 keil Exp $
2 *
3 * Layer 1 defines
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#define D_RCVBUFREADY 0
11#define D_XMTBUFREADY 1
12#define D_L1STATECHANGE 2
13#define D_CLEARBUSY 3
14#define D_RX_MON0 4
15#define D_RX_MON1 5
16#define D_TX_MON0 6
17#define D_TX_MON1 7
18#define E_RCVBUFREADY 8
19
20#define B_RCVBUFREADY 0
21#define B_XMTBUFREADY 1
22#define B_ACKPENDING 2
23
24extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
25extern void DChannel_proc_xmt(struct IsdnCardState *cs);
26extern void DChannel_proc_rcv(struct IsdnCardState *cs);
27extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
28extern void l1_msg_b(struct PStack *st, int pr, void *arg);
29
30#ifdef L2FRAME_DEBUG
31extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
32#endif
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
new file mode 100644
index 00000000000..d311b5fbf89
--- /dev/null
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -0,0 +1,1860 @@
1/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 keil Exp $
2 *
3 * Author Karsten Keil
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
12 *
13 * Thanks to Jan den Ouden
14 * Fritz Elfert
15 *
16 */
17
18#include <linux/init.h>
19#include "hisax.h"
20#include "isdnl2.h"
21
22const char *l2_revision = "$Revision: 2.30.2.4 $";
23
24static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
25
26static struct Fsm l2fsm;
27
28enum {
29 ST_L2_1,
30 ST_L2_2,
31 ST_L2_3,
32 ST_L2_4,
33 ST_L2_5,
34 ST_L2_6,
35 ST_L2_7,
36 ST_L2_8,
37};
38
39#define L2_STATE_COUNT (ST_L2_8+1)
40
41static char *strL2State[] =
42{
43 "ST_L2_1",
44 "ST_L2_2",
45 "ST_L2_3",
46 "ST_L2_4",
47 "ST_L2_5",
48 "ST_L2_6",
49 "ST_L2_7",
50 "ST_L2_8",
51};
52
53enum {
54 EV_L2_UI,
55 EV_L2_SABME,
56 EV_L2_DISC,
57 EV_L2_DM,
58 EV_L2_UA,
59 EV_L2_FRMR,
60 EV_L2_SUPER,
61 EV_L2_I,
62 EV_L2_DL_DATA,
63 EV_L2_ACK_PULL,
64 EV_L2_DL_UNIT_DATA,
65 EV_L2_DL_ESTABLISH_REQ,
66 EV_L2_DL_RELEASE_REQ,
67 EV_L2_MDL_ASSIGN,
68 EV_L2_MDL_REMOVE,
69 EV_L2_MDL_ERROR,
70 EV_L1_DEACTIVATE,
71 EV_L2_T200,
72 EV_L2_T203,
73 EV_L2_SET_OWN_BUSY,
74 EV_L2_CLEAR_OWN_BUSY,
75 EV_L2_FRAME_ERROR,
76};
77
78#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
79
80static char *strL2Event[] =
81{
82 "EV_L2_UI",
83 "EV_L2_SABME",
84 "EV_L2_DISC",
85 "EV_L2_DM",
86 "EV_L2_UA",
87 "EV_L2_FRMR",
88 "EV_L2_SUPER",
89 "EV_L2_I",
90 "EV_L2_DL_DATA",
91 "EV_L2_ACK_PULL",
92 "EV_L2_DL_UNIT_DATA",
93 "EV_L2_DL_ESTABLISH_REQ",
94 "EV_L2_DL_RELEASE_REQ",
95 "EV_L2_MDL_ASSIGN",
96 "EV_L2_MDL_REMOVE",
97 "EV_L2_MDL_ERROR",
98 "EV_L1_DEACTIVATE",
99 "EV_L2_T200",
100 "EV_L2_T203",
101 "EV_L2_SET_OWN_BUSY",
102 "EV_L2_CLEAR_OWN_BUSY",
103 "EV_L2_FRAME_ERROR",
104};
105
106static int l2addrsize(struct Layer2 *l2);
107
108static void
109set_peer_busy(struct Layer2 *l2) {
110 test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
111 if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue))
112 test_and_set_bit(FLG_L2BLOCK, &l2->flag);
113}
114
115static void
116clear_peer_busy(struct Layer2 *l2) {
117 if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
118 test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
119}
120
121static void
122InitWin(struct Layer2 *l2)
123{
124 int i;
125
126 for (i = 0; i < MAX_WINDOW; i++)
127 l2->windowar[i] = NULL;
128}
129
130static int
131freewin1(struct Layer2 *l2)
132{
133 int i, cnt = 0;
134
135 for (i = 0; i < MAX_WINDOW; i++) {
136 if (l2->windowar[i]) {
137 cnt++;
138 dev_kfree_skb(l2->windowar[i]);
139 l2->windowar[i] = NULL;
140 }
141 }
142 return cnt;
143}
144
145inline void
146freewin(struct PStack *st)
147{
148 freewin1(&st->l2);
149}
150
151static void
152ReleaseWin(struct Layer2 *l2)
153{
154 int cnt;
155
156 if((cnt = freewin1(l2)))
157 printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
158}
159
160inline unsigned int
161cansend(struct PStack *st)
162{
163 unsigned int p1;
164
165 if(test_bit(FLG_MOD128, &st->l2.flag))
166 p1 = (st->l2.vs - st->l2.va) % 128;
167 else
168 p1 = (st->l2.vs - st->l2.va) % 8;
169 return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
170}
171
172inline void
173clear_exception(struct Layer2 *l2)
174{
175 test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
176 test_and_clear_bit(FLG_REJEXC, &l2->flag);
177 test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
178 clear_peer_busy(l2);
179}
180
181inline int
182l2headersize(struct Layer2 *l2, int ui)
183{
184 return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
185 (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));
186}
187
188inline int
189l2addrsize(struct Layer2 *l2)
190{
191 return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
192}
193
194static int
195sethdraddr(struct Layer2 *l2, u_char * header, int rsp)
196{
197 u_char *ptr = header;
198 int crbit = rsp;
199
200 if (test_bit(FLG_LAPD, &l2->flag)) {
201 *ptr++ = (l2->sap << 2) | (rsp ? 2 : 0);
202 *ptr++ = (l2->tei << 1) | 1;
203 return (2);
204 } else {
205 if (test_bit(FLG_ORIG, &l2->flag))
206 crbit = !crbit;
207 if (crbit)
208 *ptr++ = 1;
209 else
210 *ptr++ = 3;
211 return (1);
212 }
213}
214
215inline static void
216enqueue_super(struct PStack *st,
217 struct sk_buff *skb)
218{
219 if (test_bit(FLG_LAPB, &st->l2.flag))
220 st->l1.bcs->tx_cnt += skb->len;
221 st->l2.l2l1(st, PH_DATA | REQUEST, skb);
222}
223
224#define enqueue_ui(a, b) enqueue_super(a, b)
225
226inline int
227IsUI(u_char * data)
228{
229 return ((data[0] & 0xef) == UI);
230}
231
232inline int
233IsUA(u_char * data)
234{
235 return ((data[0] & 0xef) == UA);
236}
237
238inline int
239IsDM(u_char * data)
240{
241 return ((data[0] & 0xef) == DM);
242}
243
244inline int
245IsDISC(u_char * data)
246{
247 return ((data[0] & 0xef) == DISC);
248}
249
250inline int
251IsRR(u_char * data, struct PStack *st)
252{
253 if (test_bit(FLG_MOD128, &st->l2.flag))
254 return (data[0] == RR);
255 else
256 return ((data[0] & 0xf) == 1);
257}
258
259inline int
260IsSFrame(u_char * data, struct PStack *st)
261{
262 register u_char d = *data;
263
264 if (!test_bit(FLG_MOD128, &st->l2.flag))
265 d &= 0xf;
266 return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
267}
268
269inline int
270IsSABME(u_char * data, struct PStack *st)
271{
272 u_char d = data[0] & ~0x10;
273
274 return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
275}
276
277inline int
278IsREJ(u_char * data, struct PStack *st)
279{
280 return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
281}
282
283inline int
284IsFRMR(u_char * data)
285{
286 return ((data[0] & 0xef) == FRMR);
287}
288
289inline int
290IsRNR(u_char * data, struct PStack *st)
291{
292 return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
293}
294
295int
296iframe_error(struct PStack *st, struct sk_buff *skb)
297{
298 int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
299 int rsp = *skb->data & 0x2;
300
301 if (test_bit(FLG_ORIG, &st->l2.flag))
302 rsp = !rsp;
303
304 if (rsp)
305 return 'L';
306
307
308 if (skb->len < i)
309 return 'N';
310
311 if ((skb->len - i) > st->l2.maxlen)
312 return 'O';
313
314
315 return 0;
316}
317
318int
319super_error(struct PStack *st, struct sk_buff *skb)
320{
321 if (skb->len != l2addrsize(&st->l2) +
322 (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1))
323 return 'N';
324
325 return 0;
326}
327
328int
329unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
330{
331 int rsp = (*skb->data & 0x2) >> 1;
332 if (test_bit(FLG_ORIG, &st->l2.flag))
333 rsp = !rsp;
334
335 if (rsp != wantrsp)
336 return 'L';
337
338 if (skb->len != l2addrsize(&st->l2) + 1)
339 return 'N';
340
341 return 0;
342}
343
344int
345UI_error(struct PStack *st, struct sk_buff *skb)
346{
347 int rsp = *skb->data & 0x2;
348 if (test_bit(FLG_ORIG, &st->l2.flag))
349 rsp = !rsp;
350
351 if (rsp)
352 return 'L';
353
354 if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1)
355 return 'O';
356
357 return 0;
358}
359
360int
361FRMR_error(struct PStack *st, struct sk_buff *skb)
362{
363 int headers = l2addrsize(&st->l2) + 1;
364 u_char *datap = skb->data + headers;
365 int rsp = *skb->data & 0x2;
366
367 if (test_bit(FLG_ORIG, &st->l2.flag))
368 rsp = !rsp;
369
370 if (!rsp)
371 return 'L';
372
373 if (test_bit(FLG_MOD128, &st->l2.flag)) {
374 if (skb->len < headers + 5)
375 return 'N';
376 else
377 l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
378 datap[0], datap[1], datap[2],
379 datap[3], datap[4]);
380 } else {
381 if (skb->len < headers + 3)
382 return 'N';
383 else
384 l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
385 datap[0], datap[1], datap[2]);
386 }
387
388 return 0;
389}
390
391static unsigned int
392legalnr(struct PStack *st, unsigned int nr)
393{
394 struct Layer2 *l2 = &st->l2;
395
396 if(test_bit(FLG_MOD128, &l2->flag))
397 return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
398 else
399 return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
400}
401
402static void
403setva(struct PStack *st, unsigned int nr)
404{
405 struct Layer2 *l2 = &st->l2;
406 int len;
407 u_long flags;
408
409 spin_lock_irqsave(&l2->lock, flags);
410 while (l2->va != nr) {
411 (l2->va)++;
412 if(test_bit(FLG_MOD128, &l2->flag))
413 l2->va %= 128;
414 else
415 l2->va %= 8;
416 len = l2->windowar[l2->sow]->len;
417 if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
418 len = -1;
419 dev_kfree_skb(l2->windowar[l2->sow]);
420 l2->windowar[l2->sow] = NULL;
421 l2->sow = (l2->sow + 1) % l2->window;
422 spin_unlock_irqrestore(&l2->lock, flags);
423 if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >=0))
424 lli_writewakeup(st, len);
425 spin_lock_irqsave(&l2->lock, flags);
426 }
427 spin_unlock_irqrestore(&l2->lock, flags);
428}
429
430static void
431send_uframe(struct PStack *st, u_char cmd, u_char cr)
432{
433 struct sk_buff *skb;
434 u_char tmp[MAX_HEADER_LEN];
435 int i;
436
437 i = sethdraddr(&st->l2, tmp, cr);
438 tmp[i++] = cmd;
439 if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
440 printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n");
441 return;
442 }
443 memcpy(skb_put(skb, i), tmp, i);
444 enqueue_super(st, skb);
445}
446
447inline u_char
448get_PollFlag(struct PStack * st, struct sk_buff * skb)
449{
450 return (skb->data[l2addrsize(&(st->l2))] & 0x10);
451}
452
453inline void
454FreeSkb(struct sk_buff *skb)
455{
456 dev_kfree_skb(skb);
457}
458
459
460inline u_char
461get_PollFlagFree(struct PStack *st, struct sk_buff *skb)
462{
463 u_char PF;
464
465 PF = get_PollFlag(st, skb);
466 FreeSkb(skb);
467 return (PF);
468}
469
470inline void
471start_t200(struct PStack *st, int i)
472{
473 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
474 test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
475}
476
477inline void
478restart_t200(struct PStack *st, int i)
479{
480 FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
481 test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
482}
483
484inline void
485stop_t200(struct PStack *st, int i)
486{
487 if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
488 FsmDelTimer(&st->l2.t200, i);
489}
490
491inline void
492st5_dl_release_l2l3(struct PStack *st)
493{
494 int pr;
495
496 if(test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
497 pr = DL_RELEASE | CONFIRM;
498 else
499 pr = DL_RELEASE | INDICATION;
500
501 st->l2.l2l3(st, pr, NULL);
502}
503
504inline void
505lapb_dl_release_l2l3(struct PStack *st, int f)
506{
507 if (test_bit(FLG_LAPB, &st->l2.flag))
508 st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
509 st->l2.l2l3(st, DL_RELEASE | f, NULL);
510}
511
512static void
513establishlink(struct FsmInst *fi)
514{
515 struct PStack *st = fi->userdata;
516 u_char cmd;
517
518 clear_exception(&st->l2);
519 st->l2.rc = 0;
520 cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10;
521 send_uframe(st, cmd, CMD);
522 FsmDelTimer(&st->l2.t203, 1);
523 restart_t200(st, 1);
524 test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
525 freewin(st);
526 FsmChangeState(fi, ST_L2_5);
527}
528
529static void
530l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
531{
532 struct sk_buff *skb = arg;
533 struct PStack *st = fi->userdata;
534
535 if (get_PollFlagFree(st, skb))
536 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
537 else
538 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
539}
540
541static void
542l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
543{
544 struct sk_buff *skb = arg;
545 struct PStack *st = fi->userdata;
546
547 if (get_PollFlagFree(st, skb))
548 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
549 else {
550 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
551 establishlink(fi);
552 test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
553 }
554}
555
556static void
557l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
558{
559 struct sk_buff *skb = arg;
560 struct PStack *st = fi->userdata;
561
562 if (get_PollFlagFree(st, skb))
563 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
564 else {
565 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
566 }
567 establishlink(fi);
568 test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
569}
570
571static void
572l2_go_st3(struct FsmInst *fi, int event, void *arg)
573{
574 FsmChangeState(fi, ST_L2_3);
575}
576
577static void
578l2_mdl_assign(struct FsmInst *fi, int event, void *arg)
579{
580 struct PStack *st = fi->userdata;
581
582 FsmChangeState(fi, ST_L2_3);
583 st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
584}
585
586static void
587l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
588{
589 struct PStack *st = fi->userdata;
590 struct sk_buff *skb = arg;
591
592 skb_queue_tail(&st->l2.ui_queue, skb);
593 FsmChangeState(fi, ST_L2_2);
594 st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
595}
596
597static void
598l2_queue_ui(struct FsmInst *fi, int event, void *arg)
599{
600 struct PStack *st = fi->userdata;
601 struct sk_buff *skb = arg;
602
603 skb_queue_tail(&st->l2.ui_queue, skb);
604}
605
606static void
607tx_ui(struct PStack *st)
608{
609 struct sk_buff *skb;
610 u_char header[MAX_HEADER_LEN];
611 int i;
612
613 i = sethdraddr(&(st->l2), header, CMD);
614 header[i++] = UI;
615 while ((skb = skb_dequeue(&st->l2.ui_queue))) {
616 memcpy(skb_push(skb, i), header, i);
617 enqueue_ui(st, skb);
618 }
619}
620
621static void
622l2_send_ui(struct FsmInst *fi, int event, void *arg)
623{
624 struct PStack *st = fi->userdata;
625 struct sk_buff *skb = arg;
626
627 skb_queue_tail(&st->l2.ui_queue, skb);
628 tx_ui(st);
629}
630
631static void
632l2_got_ui(struct FsmInst *fi, int event, void *arg)
633{
634 struct PStack *st = fi->userdata;
635 struct sk_buff *skb = arg;
636
637 skb_pull(skb, l2headersize(&st->l2, 1));
638 st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
639/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
640 * in states 1-3 for broadcast
641 */
642
643
644}
645
646static void
647l2_establish(struct FsmInst *fi, int event, void *arg)
648{
649 struct PStack *st = fi->userdata;
650
651 establishlink(fi);
652 test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
653}
654
655static void
656l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
657{
658 struct PStack *st = fi->userdata;
659
660 skb_queue_purge(&st->l2.i_queue);
661 test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
662 test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
663}
664
665static void
666l2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
667{
668 struct PStack *st = fi->userdata;
669
670 skb_queue_purge(&st->l2.i_queue);
671 establishlink(fi);
672 test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
673}
674
675static void
676l2_release(struct FsmInst *fi, int event, void *arg)
677{
678 struct PStack *st = fi->userdata;
679
680 st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
681}
682
683static void
684l2_pend_rel(struct FsmInst *fi, int event, void *arg)
685{
686 struct PStack *st = fi->userdata;
687
688 test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
689}
690
691static void
692l2_disconnect(struct FsmInst *fi, int event, void *arg)
693{
694 struct PStack *st = fi->userdata;
695
696 skb_queue_purge(&st->l2.i_queue);
697 freewin(st);
698 FsmChangeState(fi, ST_L2_6);
699 st->l2.rc = 0;
700 send_uframe(st, DISC | 0x10, CMD);
701 FsmDelTimer(&st->l2.t203, 1);
702 restart_t200(st, 2);
703}
704
705static void
706l2_start_multi(struct FsmInst *fi, int event, void *arg)
707{
708 struct PStack *st = fi->userdata;
709 struct sk_buff *skb = arg;
710
711 send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
712
713 clear_exception(&st->l2);
714 st->l2.vs = 0;
715 st->l2.va = 0;
716 st->l2.vr = 0;
717 st->l2.sow = 0;
718 FsmChangeState(fi, ST_L2_7);
719 FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
720
721 st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
722}
723
724static void
725l2_send_UA(struct FsmInst *fi, int event, void *arg)
726{
727 struct PStack *st = fi->userdata;
728 struct sk_buff *skb = arg;
729
730 send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
731}
732
733static void
734l2_send_DM(struct FsmInst *fi, int event, void *arg)
735{
736 struct PStack *st = fi->userdata;
737 struct sk_buff *skb = arg;
738
739 send_uframe(st, DM | get_PollFlagFree(st, skb), RSP);
740}
741
742static void
743l2_restart_multi(struct FsmInst *fi, int event, void *arg)
744{
745 struct PStack *st = fi->userdata;
746 struct sk_buff *skb = arg;
747 int est = 0, state;
748
749 state = fi->state;
750
751 send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
752
753 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
754
755 if (st->l2.vs != st->l2.va) {
756 skb_queue_purge(&st->l2.i_queue);
757 est = 1;
758 }
759
760 clear_exception(&st->l2);
761 st->l2.vs = 0;
762 st->l2.va = 0;
763 st->l2.vr = 0;
764 st->l2.sow = 0;
765 FsmChangeState(fi, ST_L2_7);
766 stop_t200(st, 3);
767 FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
768
769 if (est)
770 st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
771
772 if ((ST_L2_7==state) || (ST_L2_8 == state))
773 if (skb_queue_len(&st->l2.i_queue) && cansend(st))
774 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
775}
776
777static void
778l2_stop_multi(struct FsmInst *fi, int event, void *arg)
779{
780 struct PStack *st = fi->userdata;
781 struct sk_buff *skb = arg;
782
783 FsmChangeState(fi, ST_L2_4);
784 FsmDelTimer(&st->l2.t203, 3);
785 stop_t200(st, 4);
786
787 send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
788
789 skb_queue_purge(&st->l2.i_queue);
790 freewin(st);
791 lapb_dl_release_l2l3(st, INDICATION);
792}
793
794static void
795l2_connected(struct FsmInst *fi, int event, void *arg)
796{
797 struct PStack *st = fi->userdata;
798 struct sk_buff *skb = arg;
799 int pr=-1;
800
801 if (!get_PollFlag(st, skb)) {
802 l2_mdl_error_ua(fi, event, arg);
803 return;
804 }
805 FreeSkb(skb);
806
807 if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
808 l2_disconnect(fi, event, arg);
809
810 if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
811 pr = DL_ESTABLISH | CONFIRM;
812 } else if (st->l2.vs != st->l2.va) {
813 skb_queue_purge(&st->l2.i_queue);
814 pr = DL_ESTABLISH | INDICATION;
815 }
816
817 stop_t200(st, 5);
818
819 st->l2.vr = 0;
820 st->l2.vs = 0;
821 st->l2.va = 0;
822 st->l2.sow = 0;
823 FsmChangeState(fi, ST_L2_7);
824 FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
825
826 if (pr != -1)
827 st->l2.l2l3(st, pr, NULL);
828
829 if (skb_queue_len(&st->l2.i_queue) && cansend(st))
830 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
831}
832
833static void
834l2_released(struct FsmInst *fi, int event, void *arg)
835{
836 struct PStack *st = fi->userdata;
837 struct sk_buff *skb = arg;
838
839 if (!get_PollFlag(st, skb)) {
840 l2_mdl_error_ua(fi, event, arg);
841 return;
842 }
843 FreeSkb(skb);
844
845 stop_t200(st, 6);
846 lapb_dl_release_l2l3(st, CONFIRM);
847 FsmChangeState(fi, ST_L2_4);
848}
849
850static void
851l2_reestablish(struct FsmInst *fi, int event, void *arg)
852{
853 struct PStack *st = fi->userdata;
854 struct sk_buff *skb = arg;
855
856 if (!get_PollFlagFree(st, skb)) {
857 establishlink(fi);
858 test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
859 }
860}
861
862static void
863l2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
864{
865 struct PStack *st = fi->userdata;
866 struct sk_buff *skb = arg;
867
868 if (get_PollFlagFree(st, skb)) {
869 stop_t200(st, 7);
870 if (!test_bit(FLG_L3_INIT, &st->l2.flag))
871 skb_queue_purge(&st->l2.i_queue);
872 if (test_bit(FLG_LAPB, &st->l2.flag))
873 st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
874 st5_dl_release_l2l3(st);
875 FsmChangeState(fi, ST_L2_4);
876 }
877}
878
879static void
880l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
881{
882 struct PStack *st = fi->userdata;
883 struct sk_buff *skb = arg;
884
885 if (get_PollFlagFree(st, skb)) {
886 stop_t200(st, 8);
887 lapb_dl_release_l2l3(st, CONFIRM);
888 FsmChangeState(fi, ST_L2_4);
889 }
890}
891
892inline void
893enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
894{
895 struct sk_buff *skb;
896 struct Layer2 *l2;
897 u_char tmp[MAX_HEADER_LEN];
898 int i;
899
900 l2 = &st->l2;
901 i = sethdraddr(l2, tmp, cr);
902 if (test_bit(FLG_MOD128, &l2->flag)) {
903 tmp[i++] = typ;
904 tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
905 } else
906 tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
907 if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
908 printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n");
909 return;
910 }
911 memcpy(skb_put(skb, i), tmp, i);
912 enqueue_super(st, skb);
913}
914
915inline void
916enquiry_response(struct PStack *st)
917{
918 if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
919 enquiry_cr(st, RNR, RSP, 1);
920 else
921 enquiry_cr(st, RR, RSP, 1);
922 test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
923}
924
925inline void
926transmit_enquiry(struct PStack *st)
927{
928 if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
929 enquiry_cr(st, RNR, CMD, 1);
930 else
931 enquiry_cr(st, RR, CMD, 1);
932 test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
933 start_t200(st, 9);
934}
935
936
937static void
938nrerrorrecovery(struct FsmInst *fi)
939{
940 struct PStack *st = fi->userdata;
941
942 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
943 establishlink(fi);
944 test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
945}
946
947static void
948invoke_retransmission(struct PStack *st, unsigned int nr)
949{
950 struct Layer2 *l2 = &st->l2;
951 u_int p1;
952 u_long flags;
953
954 spin_lock_irqsave(&l2->lock, flags);
955 if (l2->vs != nr) {
956 while (l2->vs != nr) {
957 (l2->vs)--;
958 if(test_bit(FLG_MOD128, &l2->flag)) {
959 l2->vs %= 128;
960 p1 = (l2->vs - l2->va) % 128;
961 } else {
962 l2->vs %= 8;
963 p1 = (l2->vs - l2->va) % 8;
964 }
965 p1 = (p1 + l2->sow) % l2->window;
966 if (test_bit(FLG_LAPB, &l2->flag))
967 st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
968 skb_queue_head(&l2->i_queue, l2->windowar[p1]);
969 l2->windowar[p1] = NULL;
970 }
971 spin_unlock_irqrestore(&l2->lock, flags);
972 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
973 return;
974 }
975 spin_unlock_irqrestore(&l2->lock, flags);
976}
977
978static void
979l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
980{
981 struct PStack *st = fi->userdata;
982 struct sk_buff *skb = arg;
983 int PollFlag, rsp, typ = RR;
984 unsigned int nr;
985 struct Layer2 *l2 = &st->l2;
986
987 rsp = *skb->data & 0x2;
988 if (test_bit(FLG_ORIG, &l2->flag))
989 rsp = !rsp;
990
991 skb_pull(skb, l2addrsize(l2));
992 if (IsRNR(skb->data, st)) {
993 set_peer_busy(l2);
994 typ = RNR;
995 } else
996 clear_peer_busy(l2);
997 if (IsREJ(skb->data, st))
998 typ = REJ;
999
1000 if (test_bit(FLG_MOD128, &l2->flag)) {
1001 PollFlag = (skb->data[1] & 0x1) == 0x1;
1002 nr = skb->data[1] >> 1;
1003 } else {
1004 PollFlag = (skb->data[0] & 0x10);
1005 nr = (skb->data[0] >> 5) & 0x7;
1006 }
1007 FreeSkb(skb);
1008
1009 if (PollFlag) {
1010 if (rsp)
1011 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
1012 else
1013 enquiry_response(st);
1014 }
1015 if (legalnr(st, nr)) {
1016 if (typ == REJ) {
1017 setva(st, nr);
1018 invoke_retransmission(st, nr);
1019 stop_t200(st, 10);
1020 if (FsmAddTimer(&st->l2.t203, st->l2.T203,
1021 EV_L2_T203, NULL, 6))
1022 l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ");
1023 } else if ((nr == l2->vs) && (typ == RR)) {
1024 setva(st, nr);
1025 stop_t200(st, 11);
1026 FsmRestartTimer(&st->l2.t203, st->l2.T203,
1027 EV_L2_T203, NULL, 7);
1028 } else if ((l2->va != nr) || (typ == RNR)) {
1029 setva(st, nr);
1030 if(typ != RR) FsmDelTimer(&st->l2.t203, 9);
1031 restart_t200(st, 12);
1032 }
1033 if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
1034 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
1035 } else
1036 nrerrorrecovery(fi);
1037}
1038
1039static void
1040l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
1041{
1042 struct PStack *st = fi->userdata;
1043 struct sk_buff *skb = arg;
1044
1045 if (test_bit(FLG_LAPB, &st->l2.flag))
1046 st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
1047 if (!test_bit(FLG_L3_INIT, &st->l2.flag))
1048 skb_queue_tail(&st->l2.i_queue, skb);
1049 else
1050 FreeSkb(skb);
1051}
1052
1053static void
1054l2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
1055{
1056 struct PStack *st = fi->userdata;
1057 struct sk_buff *skb = arg;
1058
1059 if (test_bit(FLG_LAPB, &st->l2.flag))
1060 st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
1061 skb_queue_tail(&st->l2.i_queue, skb);
1062 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
1063}
1064
1065static void
1066l2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
1067{
1068 struct PStack *st = fi->userdata;
1069 struct sk_buff *skb = arg;
1070
1071 if (test_bit(FLG_LAPB, &st->l2.flag))
1072 st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
1073 skb_queue_tail(&st->l2.i_queue, skb);
1074}
1075
1076static void
1077l2_got_iframe(struct FsmInst *fi, int event, void *arg)
1078{
1079 struct PStack *st = fi->userdata;
1080 struct sk_buff *skb = arg;
1081 struct Layer2 *l2 = &(st->l2);
1082 int PollFlag, ns, i;
1083 unsigned int nr;
1084
1085 i = l2addrsize(l2);
1086 if (test_bit(FLG_MOD128, &l2->flag)) {
1087 PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
1088 ns = skb->data[i] >> 1;
1089 nr = (skb->data[i + 1] >> 1) & 0x7f;
1090 } else {
1091 PollFlag = (skb->data[i] & 0x10);
1092 ns = (skb->data[i] >> 1) & 0x7;
1093 nr = (skb->data[i] >> 5) & 0x7;
1094 }
1095 if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
1096 FreeSkb(skb);
1097 if(PollFlag) enquiry_response(st);
1098 } else if (l2->vr == ns) {
1099 (l2->vr)++;
1100 if(test_bit(FLG_MOD128, &l2->flag))
1101 l2->vr %= 128;
1102 else
1103 l2->vr %= 8;
1104 test_and_clear_bit(FLG_REJEXC, &l2->flag);
1105
1106 if (PollFlag)
1107 enquiry_response(st);
1108 else
1109 test_and_set_bit(FLG_ACK_PEND, &l2->flag);
1110 skb_pull(skb, l2headersize(l2, 0));
1111 st->l2.l2l3(st, DL_DATA | INDICATION, skb);
1112 } else {
1113 /* n(s)!=v(r) */
1114 FreeSkb(skb);
1115 if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
1116 if (PollFlag)
1117 enquiry_response(st);
1118 } else {
1119 enquiry_cr(st, REJ, RSP, PollFlag);
1120 test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
1121 }
1122 }
1123
1124 if (legalnr(st, nr)) {
1125 if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) {
1126 if (nr == st->l2.vs) {
1127 stop_t200(st, 13);
1128 FsmRestartTimer(&st->l2.t203, st->l2.T203,
1129 EV_L2_T203, NULL, 7);
1130 } else if (nr != st->l2.va)
1131 restart_t200(st, 14);
1132 }
1133 setva(st, nr);
1134 } else {
1135 nrerrorrecovery(fi);
1136 return;
1137 }
1138
1139 if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7))
1140 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
1141 if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
1142 enquiry_cr(st, RR, RSP, 0);
1143}
1144
1145static void
1146l2_got_tei(struct FsmInst *fi, int event, void *arg)
1147{
1148 struct PStack *st = fi->userdata;
1149
1150 st->l2.tei = (long) arg;
1151
1152 if (fi->state == ST_L2_3) {
1153 establishlink(fi);
1154 test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
1155 } else
1156 FsmChangeState(fi, ST_L2_4);
1157 if (skb_queue_len(&st->l2.ui_queue))
1158 tx_ui(st);
1159}
1160
1161static void
1162l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
1163{
1164 struct PStack *st = fi->userdata;
1165
1166 if (test_bit(FLG_LAPD, &st->l2.flag) &&
1167 test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
1168 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
1169 } else if (st->l2.rc == st->l2.N200) {
1170 FsmChangeState(fi, ST_L2_4);
1171 test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
1172 skb_queue_purge(&st->l2.i_queue);
1173 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
1174 if (test_bit(FLG_LAPB, &st->l2.flag))
1175 st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
1176 st5_dl_release_l2l3(st);
1177 } else {
1178 st->l2.rc++;
1179 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
1180 send_uframe(st, (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM)
1181 | 0x10, CMD);
1182 }
1183}
1184
1185static void
1186l2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
1187{
1188 struct PStack *st = fi->userdata;
1189
1190 if (test_bit(FLG_LAPD, &st->l2.flag) &&
1191 test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
1192 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
1193 } else if (st->l2.rc == st->l2.N200) {
1194 FsmChangeState(fi, ST_L2_4);
1195 test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
1196 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
1197 lapb_dl_release_l2l3(st, CONFIRM);
1198 } else {
1199 st->l2.rc++;
1200 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
1201 NULL, 9);
1202 send_uframe(st, DISC | 0x10, CMD);
1203 }
1204}
1205
1206static void
1207l2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
1208{
1209 struct PStack *st = fi->userdata;
1210
1211 if (test_bit(FLG_LAPD, &st->l2.flag) &&
1212 test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
1213 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
1214 return;
1215 }
1216 test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
1217 st->l2.rc = 0;
1218 FsmChangeState(fi, ST_L2_8);
1219
1220 transmit_enquiry(st);
1221 st->l2.rc++;
1222}
1223
1224static void
1225l2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
1226{
1227 struct PStack *st = fi->userdata;
1228
1229 if (test_bit(FLG_LAPD, &st->l2.flag) &&
1230 test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
1231 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
1232 return;
1233 }
1234 test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
1235 if (st->l2.rc == st->l2.N200) {
1236 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I');
1237 establishlink(fi);
1238 test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
1239 } else {
1240 transmit_enquiry(st);
1241 st->l2.rc++;
1242 }
1243}
1244
1245static void
1246l2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
1247{
1248 struct PStack *st = fi->userdata;
1249
1250 if (test_bit(FLG_LAPD, &st->l2.flag) &&
1251 test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
1252 FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 9);
1253 return;
1254 }
1255 FsmChangeState(fi, ST_L2_8);
1256 transmit_enquiry(st);
1257 st->l2.rc = 0;
1258}
1259
1260static void
1261l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
1262{
1263 struct PStack *st = fi->userdata;
1264 struct sk_buff *skb, *oskb;
1265 struct Layer2 *l2 = &st->l2;
1266 u_char header[MAX_HEADER_LEN];
1267 int i;
1268 int unsigned p1;
1269 u_long flags;
1270
1271 if (!cansend(st))
1272 return;
1273
1274 skb = skb_dequeue(&l2->i_queue);
1275 if (!skb)
1276 return;
1277
1278 spin_lock_irqsave(&l2->lock, flags);
1279 if(test_bit(FLG_MOD128, &l2->flag))
1280 p1 = (l2->vs - l2->va) % 128;
1281 else
1282 p1 = (l2->vs - l2->va) % 8;
1283 p1 = (p1 + l2->sow) % l2->window;
1284 if (l2->windowar[p1]) {
1285 printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
1286 p1);
1287 dev_kfree_skb(l2->windowar[p1]);
1288 }
1289 l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
1290
1291 i = sethdraddr(&st->l2, header, CMD);
1292
1293 if (test_bit(FLG_MOD128, &l2->flag)) {
1294 header[i++] = l2->vs << 1;
1295 header[i++] = l2->vr << 1;
1296 l2->vs = (l2->vs + 1) % 128;
1297 } else {
1298 header[i++] = (l2->vr << 5) | (l2->vs << 1);
1299 l2->vs = (l2->vs + 1) % 8;
1300 }
1301 spin_unlock_irqrestore(&l2->lock, flags);
1302 p1 = skb->data - skb->head;
1303 if (p1 >= i)
1304 memcpy(skb_push(skb, i), header, i);
1305 else {
1306 printk(KERN_WARNING
1307 "isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
1308 oskb = skb;
1309 skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
1310 memcpy(skb_put(skb, i), header, i);
1311 memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
1312 FreeSkb(oskb);
1313 }
1314 st->l2.l2l1(st, PH_PULL | INDICATION, skb);
1315 test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
1316 if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
1317 FsmDelTimer(&st->l2.t203, 13);
1318 FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
1319 }
1320 if (skb_queue_len(&l2->i_queue) && cansend(st))
1321 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
1322}
1323
1324static void
1325l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
1326{
1327 struct PStack *st = fi->userdata;
1328 struct sk_buff *skb = arg;
1329 int PollFlag, rsp, rnr = 0;
1330 unsigned int nr;
1331 struct Layer2 *l2 = &st->l2;
1332
1333 rsp = *skb->data & 0x2;
1334 if (test_bit(FLG_ORIG, &l2->flag))
1335 rsp = !rsp;
1336
1337 skb_pull(skb, l2addrsize(l2));
1338
1339 if (IsRNR(skb->data, st)) {
1340 set_peer_busy(l2);
1341 rnr = 1;
1342 } else
1343 clear_peer_busy(l2);
1344
1345 if (test_bit(FLG_MOD128, &l2->flag)) {
1346 PollFlag = (skb->data[1] & 0x1) == 0x1;
1347 nr = skb->data[1] >> 1;
1348 } else {
1349 PollFlag = (skb->data[0] & 0x10);
1350 nr = (skb->data[0] >> 5) & 0x7;
1351 }
1352 FreeSkb(skb);
1353
1354 if (rsp && PollFlag) {
1355 if (legalnr(st, nr)) {
1356 if (rnr) {
1357 restart_t200(st, 15);
1358 } else {
1359 stop_t200(st, 16);
1360 FsmAddTimer(&l2->t203, l2->T203,
1361 EV_L2_T203, NULL, 5);
1362 setva(st, nr);
1363 }
1364 invoke_retransmission(st, nr);
1365 FsmChangeState(fi, ST_L2_7);
1366 if (skb_queue_len(&l2->i_queue) && cansend(st))
1367 st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
1368 } else
1369 nrerrorrecovery(fi);
1370 } else {
1371 if (!rsp && PollFlag)
1372 enquiry_response(st);
1373 if (legalnr(st, nr)) {
1374 setva(st, nr);
1375 } else
1376 nrerrorrecovery(fi);
1377 }
1378}
1379
1380static void
1381l2_got_FRMR(struct FsmInst *fi, int event, void *arg)
1382{
1383 struct PStack *st = fi->userdata;
1384 struct sk_buff *skb = arg;
1385
1386 skb_pull(skb, l2addrsize(&st->l2) + 1);
1387
1388 if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */
1389 (IsUA(skb->data) && (fi->state == ST_L2_7))) {
1390 st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
1391 establishlink(fi);
1392 test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
1393 }
1394 FreeSkb(skb);
1395}
1396
1397static void
1398l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
1399{
1400 struct PStack *st = fi->userdata;
1401
1402 skb_queue_purge(&st->l2.ui_queue);
1403 st->l2.tei = -1;
1404 FsmChangeState(fi, ST_L2_1);
1405}
1406
1407static void
1408l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
1409{
1410 struct PStack *st = fi->userdata;
1411
1412 skb_queue_purge(&st->l2.ui_queue);
1413 st->l2.tei = -1;
1414 st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
1415 FsmChangeState(fi, ST_L2_1);
1416}
1417
1418static void
1419l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
1420{
1421 struct PStack *st = fi->userdata;
1422
1423 skb_queue_purge(&st->l2.i_queue);
1424 skb_queue_purge(&st->l2.ui_queue);
1425 freewin(st);
1426 st->l2.tei = -1;
1427 stop_t200(st, 17);
1428 st5_dl_release_l2l3(st);
1429 FsmChangeState(fi, ST_L2_1);
1430}
1431
1432static void
1433l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
1434{
1435 struct PStack *st = fi->userdata;
1436
1437 skb_queue_purge(&st->l2.ui_queue);
1438 st->l2.tei = -1;
1439 stop_t200(st, 18);
1440 st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
1441 FsmChangeState(fi, ST_L2_1);
1442}
1443
1444static void
1445l2_tei_remove(struct FsmInst *fi, int event, void *arg)
1446{
1447 struct PStack *st = fi->userdata;
1448
1449 skb_queue_purge(&st->l2.i_queue);
1450 skb_queue_purge(&st->l2.ui_queue);
1451 freewin(st);
1452 st->l2.tei = -1;
1453 stop_t200(st, 17);
1454 FsmDelTimer(&st->l2.t203, 19);
1455 st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
1456 FsmChangeState(fi, ST_L2_1);
1457}
1458
1459static void
1460l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
1461{
1462 struct PStack *st = fi->userdata;
1463
1464 skb_queue_purge(&st->l2.i_queue);
1465 skb_queue_purge(&st->l2.ui_queue);
1466 if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
1467 st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
1468}
1469
1470static void
1471l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
1472{
1473 struct PStack *st = fi->userdata;
1474
1475 skb_queue_purge(&st->l2.i_queue);
1476 skb_queue_purge(&st->l2.ui_queue);
1477 freewin(st);
1478 stop_t200(st, 19);
1479 st5_dl_release_l2l3(st);
1480 FsmChangeState(fi, ST_L2_4);
1481}
1482
1483static void
1484l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
1485{
1486 struct PStack *st = fi->userdata;
1487
1488 skb_queue_purge(&st->l2.ui_queue);
1489 stop_t200(st, 20);
1490 st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
1491 FsmChangeState(fi, ST_L2_4);
1492}
1493
1494static void
1495l2_persistant_da(struct FsmInst *fi, int event, void *arg)
1496{
1497 struct PStack *st = fi->userdata;
1498
1499 skb_queue_purge(&st->l2.i_queue);
1500 skb_queue_purge(&st->l2.ui_queue);
1501 freewin(st);
1502 stop_t200(st, 19);
1503 FsmDelTimer(&st->l2.t203, 19);
1504 st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
1505 FsmChangeState(fi, ST_L2_4);
1506}
1507
1508static void
1509l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
1510{
1511 struct PStack *st = fi->userdata;
1512
1513 if(!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) {
1514 enquiry_cr(st, RNR, RSP, 0);
1515 test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
1516 }
1517}
1518
1519static void
1520l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
1521{
1522 struct PStack *st = fi->userdata;
1523
1524 if(!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) {
1525 enquiry_cr(st, RR, RSP, 0);
1526 test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
1527 }
1528}
1529
1530static void
1531l2_frame_error(struct FsmInst *fi, int event, void *arg)
1532{
1533 struct PStack *st = fi->userdata;
1534
1535 st->ma.layer(st, MDL_ERROR | INDICATION, arg);
1536}
1537
1538static void
1539l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
1540{
1541 struct PStack *st = fi->userdata;
1542
1543 st->ma.layer(st, MDL_ERROR | INDICATION, arg);
1544 establishlink(fi);
1545 test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
1546}
1547
1548static struct FsmNode L2FnList[] __initdata =
1549{
1550 {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
1551 {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
1552 {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
1553 {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
1554 {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
1555 {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
1556 {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
1557 {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
1558 {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
1559 {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
1560 {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
1561 {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
1562 {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
1563 {ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign},
1564 {ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui},
1565 {ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui},
1566 {ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui},
1567 {ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui},
1568 {ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui},
1569 {ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui},
1570 {ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui},
1571 {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
1572 {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
1573 {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
1574 {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
1575 {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
1576 {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
1577 {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
1578 {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
1579 {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
1580 {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
1581 {ST_L2_4, EV_L2_SABME, l2_start_multi},
1582 {ST_L2_5, EV_L2_SABME, l2_send_UA},
1583 {ST_L2_6, EV_L2_SABME, l2_send_DM},
1584 {ST_L2_7, EV_L2_SABME, l2_restart_multi},
1585 {ST_L2_8, EV_L2_SABME, l2_restart_multi},
1586 {ST_L2_4, EV_L2_DISC, l2_send_DM},
1587 {ST_L2_5, EV_L2_DISC, l2_send_DM},
1588 {ST_L2_6, EV_L2_DISC, l2_send_UA},
1589 {ST_L2_7, EV_L2_DISC, l2_stop_multi},
1590 {ST_L2_8, EV_L2_DISC, l2_stop_multi},
1591 {ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
1592 {ST_L2_5, EV_L2_UA, l2_connected},
1593 {ST_L2_6, EV_L2_UA, l2_released},
1594 {ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
1595 {ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
1596 {ST_L2_4, EV_L2_DM, l2_reestablish},
1597 {ST_L2_5, EV_L2_DM, l2_st5_dm_release},
1598 {ST_L2_6, EV_L2_DM, l2_st6_dm_release},
1599 {ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
1600 {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
1601 {ST_L2_1, EV_L2_UI, l2_got_ui},
1602 {ST_L2_2, EV_L2_UI, l2_got_ui},
1603 {ST_L2_3, EV_L2_UI, l2_got_ui},
1604 {ST_L2_4, EV_L2_UI, l2_got_ui},
1605 {ST_L2_5, EV_L2_UI, l2_got_ui},
1606 {ST_L2_6, EV_L2_UI, l2_got_ui},
1607 {ST_L2_7, EV_L2_UI, l2_got_ui},
1608 {ST_L2_8, EV_L2_UI, l2_got_ui},
1609 {ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
1610 {ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
1611 {ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
1612 {ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
1613 {ST_L2_7, EV_L2_I, l2_got_iframe},
1614 {ST_L2_8, EV_L2_I, l2_got_iframe},
1615 {ST_L2_5, EV_L2_T200, l2_st5_tout_200},
1616 {ST_L2_6, EV_L2_T200, l2_st6_tout_200},
1617 {ST_L2_7, EV_L2_T200, l2_st7_tout_200},
1618 {ST_L2_8, EV_L2_T200, l2_st8_tout_200},
1619 {ST_L2_7, EV_L2_T203, l2_st7_tout_203},
1620 {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
1621 {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
1622 {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
1623 {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
1624 {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
1625 {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
1626 {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
1627 {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
1628 {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
1629 {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
1630 {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
1631 {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
1632 {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
1633 {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
1634 {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
1635 {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
1636 {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
1637 {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
1638};
1639
1640#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
1641
1642static void
1643isdnl2_l1l2(struct PStack *st, int pr, void *arg)
1644{
1645 struct sk_buff *skb = arg;
1646 u_char *datap;
1647 int ret = 1, len;
1648 int c = 0;
1649
1650 switch (pr) {
1651 case (PH_DATA | INDICATION):
1652 datap = skb->data;
1653 len = l2addrsize(&st->l2);
1654 if (skb->len > len)
1655 datap += len;
1656 else {
1657 FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
1658 FreeSkb(skb);
1659 return;
1660 }
1661 if (!(*datap & 1)) { /* I-Frame */
1662 if(!(c = iframe_error(st, skb)))
1663 ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
1664 } else if (IsSFrame(datap, st)) { /* S-Frame */
1665 if(!(c = super_error(st, skb)))
1666 ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
1667 } else if (IsUI(datap)) {
1668 if(!(c = UI_error(st, skb)))
1669 ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
1670 } else if (IsSABME(datap, st)) {
1671 if(!(c = unnum_error(st, skb, CMD)))
1672 ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb);
1673 } else if (IsUA(datap)) {
1674 if(!(c = unnum_error(st, skb, RSP)))
1675 ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
1676 } else if (IsDISC(datap)) {
1677 if(!(c = unnum_error(st, skb, CMD)))
1678 ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
1679 } else if (IsDM(datap)) {
1680 if(!(c = unnum_error(st, skb, RSP)))
1681 ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
1682 } else if (IsFRMR(datap)) {
1683 if(!(c = FRMR_error(st,skb)))
1684 ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
1685 } else {
1686 FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
1687 FreeSkb(skb);
1688 ret = 0;
1689 }
1690 if(c) {
1691 FreeSkb(skb);
1692 FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
1693 ret = 0;
1694 }
1695 if (ret)
1696 FreeSkb(skb);
1697 break;
1698 case (PH_PULL | CONFIRM):
1699 FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
1700 break;
1701 case (PH_PAUSE | INDICATION):
1702 test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag);
1703 break;
1704 case (PH_PAUSE | CONFIRM):
1705 test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag);
1706 break;
1707 case (PH_ACTIVATE | CONFIRM):
1708 case (PH_ACTIVATE | INDICATION):
1709 test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
1710 if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
1711 FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
1712 break;
1713 case (PH_DEACTIVATE | INDICATION):
1714 case (PH_DEACTIVATE | CONFIRM):
1715 test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
1716 FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
1717 break;
1718 default:
1719 l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr);
1720 break;
1721 }
1722}
1723
1724static void
1725isdnl2_l3l2(struct PStack *st, int pr, void *arg)
1726{
1727 switch (pr) {
1728 case (DL_DATA | REQUEST):
1729 if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
1730 dev_kfree_skb((struct sk_buff *) arg);
1731 }
1732 break;
1733 case (DL_UNIT_DATA | REQUEST):
1734 if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
1735 dev_kfree_skb((struct sk_buff *) arg);
1736 }
1737 break;
1738 case (DL_ESTABLISH | REQUEST):
1739 if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
1740 if (test_bit(FLG_LAPD, &st->l2.flag) ||
1741 test_bit(FLG_ORIG, &st->l2.flag)) {
1742 FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
1743 }
1744 } else {
1745 if (test_bit(FLG_LAPD, &st->l2.flag) ||
1746 test_bit(FLG_ORIG, &st->l2.flag)) {
1747 test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
1748 }
1749 st->l2.l2l1(st, PH_ACTIVATE, NULL);
1750 }
1751 break;
1752 case (DL_RELEASE | REQUEST):
1753 if (test_bit(FLG_LAPB, &st->l2.flag)) {
1754 st->l2.l2l1(st, PH_DEACTIVATE, NULL);
1755 }
1756 FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg);
1757 break;
1758 case (MDL_ASSIGN | REQUEST):
1759 FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
1760 break;
1761 case (MDL_REMOVE | REQUEST):
1762 FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg);
1763 break;
1764 case (MDL_ERROR | RESPONSE):
1765 FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg);
1766 break;
1767 }
1768}
1769
1770void
1771releasestack_isdnl2(struct PStack *st)
1772{
1773 FsmDelTimer(&st->l2.t200, 21);
1774 FsmDelTimer(&st->l2.t203, 16);
1775 skb_queue_purge(&st->l2.i_queue);
1776 skb_queue_purge(&st->l2.ui_queue);
1777 ReleaseWin(&st->l2);
1778}
1779
1780static void
1781l2m_debug(struct FsmInst *fi, char *fmt, ...)
1782{
1783 va_list args;
1784 struct PStack *st = fi->userdata;
1785
1786 va_start(args, fmt);
1787 VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args);
1788 va_end(args);
1789}
1790
1791void
1792setstack_isdnl2(struct PStack *st, char *debug_id)
1793{
1794 spin_lock_init(&st->l2.lock);
1795 st->l1.l1l2 = isdnl2_l1l2;
1796 st->l3.l3l2 = isdnl2_l3l2;
1797
1798 skb_queue_head_init(&st->l2.i_queue);
1799 skb_queue_head_init(&st->l2.ui_queue);
1800 InitWin(&st->l2);
1801 st->l2.debug = 0;
1802
1803 st->l2.l2m.fsm = &l2fsm;
1804 if (test_bit(FLG_LAPB, &st->l2.flag))
1805 st->l2.l2m.state = ST_L2_4;
1806 else
1807 st->l2.l2m.state = ST_L2_1;
1808 st->l2.l2m.debug = 0;
1809 st->l2.l2m.userdata = st;
1810 st->l2.l2m.userint = 0;
1811 st->l2.l2m.printdebug = l2m_debug;
1812 strcpy(st->l2.debug_id, debug_id);
1813
1814 FsmInitTimer(&st->l2.l2m, &st->l2.t200);
1815 FsmInitTimer(&st->l2.l2m, &st->l2.t203);
1816}
1817
1818static void
1819transl2_l3l2(struct PStack *st, int pr, void *arg)
1820{
1821 switch (pr) {
1822 case (DL_DATA | REQUEST):
1823 case (DL_UNIT_DATA | REQUEST):
1824 st->l2.l2l1(st, PH_DATA | REQUEST, arg);
1825 break;
1826 case (DL_ESTABLISH | REQUEST):
1827 st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
1828 break;
1829 case (DL_RELEASE | REQUEST):
1830 st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
1831 break;
1832 }
1833}
1834
1835void
1836setstack_transl2(struct PStack *st)
1837{
1838 st->l3.l3l2 = transl2_l3l2;
1839}
1840
1841void
1842releasestack_transl2(struct PStack *st)
1843{
1844}
1845
1846int __init
1847Isdnl2New(void)
1848{
1849 l2fsm.state_count = L2_STATE_COUNT;
1850 l2fsm.event_count = L2_EVENT_COUNT;
1851 l2fsm.strEvent = strL2Event;
1852 l2fsm.strState = strL2State;
1853 return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);
1854}
1855
1856void
1857Isdnl2Free(void)
1858{
1859 FsmFree(&l2fsm);
1860}
diff --git a/drivers/isdn/hisax/isdnl2.h b/drivers/isdn/hisax/isdnl2.h
new file mode 100644
index 00000000000..0cdab1b73fa
--- /dev/null
+++ b/drivers/isdn/hisax/isdnl2.h
@@ -0,0 +1,26 @@
1/* $Id: isdnl2.h,v 1.3.6.2 2001/09/23 22:24:49 kai Exp $
2 *
3 * Layer 2 defines
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#define RR 0x01
11#define RNR 0x05
12#define REJ 0x09
13#define SABME 0x6f
14#define SABM 0x2f
15#define DM 0x0f
16#define UI 0x03
17#define DISC 0x43
18#define UA 0x63
19#define FRMR 0x87
20#define XID 0xaf
21
22#define CMD 0
23#define RSP 1
24
25#define LC_FLUSH_WAIT 1
26
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
new file mode 100644
index 00000000000..f571b5d18e9
--- /dev/null
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -0,0 +1,610 @@
1/* $Id: isdnl3.c,v 2.22.2.3 2004/01/13 14:31:25 keil Exp $
2 *
3 * Author Karsten Keil
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
12 *
13 * Thanks to Jan den Ouden
14 * Fritz Elfert
15 *
16 */
17
18#include <linux/init.h>
19#include "hisax.h"
20#include "isdnl3.h"
21#include <linux/config.h>
22
23const char *l3_revision = "$Revision: 2.22.2.3 $";
24
25static struct Fsm l3fsm;
26
27enum {
28 ST_L3_LC_REL,
29 ST_L3_LC_ESTAB_WAIT,
30 ST_L3_LC_REL_DELAY,
31 ST_L3_LC_REL_WAIT,
32 ST_L3_LC_ESTAB,
33};
34
35#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
36
37static char *strL3State[] =
38{
39 "ST_L3_LC_REL",
40 "ST_L3_LC_ESTAB_WAIT",
41 "ST_L3_LC_REL_DELAY",
42 "ST_L3_LC_REL_WAIT",
43 "ST_L3_LC_ESTAB",
44};
45
46enum {
47 EV_ESTABLISH_REQ,
48 EV_ESTABLISH_IND,
49 EV_ESTABLISH_CNF,
50 EV_RELEASE_REQ,
51 EV_RELEASE_CNF,
52 EV_RELEASE_IND,
53 EV_TIMEOUT,
54};
55
56#define L3_EVENT_COUNT (EV_TIMEOUT+1)
57
58static char *strL3Event[] =
59{
60 "EV_ESTABLISH_REQ",
61 "EV_ESTABLISH_IND",
62 "EV_ESTABLISH_CNF",
63 "EV_RELEASE_REQ",
64 "EV_RELEASE_CNF",
65 "EV_RELEASE_IND",
66 "EV_TIMEOUT",
67};
68
69static void
70l3m_debug(struct FsmInst *fi, char *fmt, ...)
71{
72 va_list args;
73 struct PStack *st = fi->userdata;
74
75 va_start(args, fmt);
76 VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
77 va_end(args);
78}
79
80u_char *
81findie(u_char * p, int size, u_char ie, int wanted_set)
82{
83 int l, codeset, maincodeset;
84 u_char *pend = p + size;
85
86 /* skip protocol discriminator, callref and message type */
87 p++;
88 l = (*p++) & 0xf;
89 p += l;
90 p++;
91 codeset = 0;
92 maincodeset = 0;
93 /* while there are bytes left... */
94 while (p < pend) {
95 if ((*p & 0xf0) == 0x90) {
96 codeset = *p & 0x07;
97 if (!(*p & 0x08))
98 maincodeset = codeset;
99 }
100 if (*p & 0x80)
101 p++;
102 else {
103 if (codeset == wanted_set) {
104 if (*p == ie)
105 { /* improved length check (Werner Cornelius) */
106 if ((pend - p) < 2)
107 return(NULL);
108 if (*(p+1) > (pend - (p+2)))
109 return(NULL);
110 return (p);
111 }
112
113 if (*p > ie)
114 return (NULL);
115 }
116 p++;
117 l = *p++;
118 p += l;
119 codeset = maincodeset;
120 }
121 }
122 return (NULL);
123}
124
125int
126getcallref(u_char * p)
127{
128 int l, cr = 0;
129
130 p++; /* prot discr */
131 if (*p & 0xfe) /* wrong callref BRI only 1 octet*/
132 return(-2);
133 l = 0xf & *p++; /* callref length */
134 if (!l) /* dummy CallRef */
135 return(-1);
136 cr = *p++;
137 return (cr);
138}
139
140static int OrigCallRef = 0;
141
142int
143newcallref(void)
144{
145 if (OrigCallRef == 127)
146 OrigCallRef = 1;
147 else
148 OrigCallRef++;
149 return (OrigCallRef);
150}
151
152void
153newl3state(struct l3_process *pc, int state)
154{
155 if (pc->debug & L3_DEB_STATE)
156 l3_debug(pc->st, "newstate cr %d %d --> %d",
157 pc->callref & 0x7F,
158 pc->state, state);
159 pc->state = state;
160}
161
162static void
163L3ExpireTimer(struct L3Timer *t)
164{
165 t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
166}
167
168void
169L3InitTimer(struct l3_process *pc, struct L3Timer *t)
170{
171 t->pc = pc;
172 t->tl.function = (void *) L3ExpireTimer;
173 t->tl.data = (long) t;
174 init_timer(&t->tl);
175}
176
177void
178L3DelTimer(struct L3Timer *t)
179{
180 del_timer(&t->tl);
181}
182
183int
184L3AddTimer(struct L3Timer *t,
185 int millisec, int event)
186{
187 if (timer_pending(&t->tl)) {
188 printk(KERN_WARNING "L3AddTimer: timer already active!\n");
189 return -1;
190 }
191 init_timer(&t->tl);
192 t->event = event;
193 t->tl.expires = jiffies + (millisec * HZ) / 1000;
194 add_timer(&t->tl);
195 return 0;
196}
197
198void
199StopAllL3Timer(struct l3_process *pc)
200{
201 L3DelTimer(&pc->timer);
202}
203
204struct sk_buff *
205l3_alloc_skb(int len)
206{
207 struct sk_buff *skb;
208
209 if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) {
210 printk(KERN_WARNING "HiSax: No skb for D-channel\n");
211 return (NULL);
212 }
213 skb_reserve(skb, MAX_HEADER_LEN);
214 return (skb);
215}
216
217static void
218no_l3_proto(struct PStack *st, int pr, void *arg)
219{
220 struct sk_buff *skb = arg;
221
222 HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
223 if (skb) {
224 dev_kfree_skb(skb);
225 }
226}
227
228static int
229no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
230{
231 printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
232 return(-1);
233}
234
235#ifdef CONFIG_HISAX_EURO
236extern void setstack_dss1(struct PStack *st);
237#endif
238
239#ifdef CONFIG_HISAX_NI1
240extern void setstack_ni1(struct PStack *st);
241#endif
242
243#ifdef CONFIG_HISAX_1TR6
244extern void setstack_1tr6(struct PStack *st);
245#endif
246
247struct l3_process
248*getl3proc(struct PStack *st, int cr)
249{
250 struct l3_process *p = st->l3.proc;
251
252 while (p)
253 if (p->callref == cr)
254 return (p);
255 else
256 p = p->next;
257 return (NULL);
258}
259
260struct l3_process
261*new_l3_process(struct PStack *st, int cr)
262{
263 struct l3_process *p, *np;
264
265 if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
266 printk(KERN_ERR "HiSax can't get memory for cr %d\n", cr);
267 return (NULL);
268 }
269 if (!st->l3.proc)
270 st->l3.proc = p;
271 else {
272 np = st->l3.proc;
273 while (np->next)
274 np = np->next;
275 np->next = p;
276 }
277 p->next = NULL;
278 p->debug = st->l3.debug;
279 p->callref = cr;
280 p->state = 0;
281 p->chan = NULL;
282 p->st = st;
283 p->N303 = st->l3.N303;
284 L3InitTimer(p, &p->timer);
285 return (p);
286};
287
288void
289release_l3_process(struct l3_process *p)
290{
291 struct l3_process *np, *pp = NULL;
292
293 if (!p)
294 return;
295 np = p->st->l3.proc;
296 while (np) {
297 if (np == p) {
298 StopAllL3Timer(p);
299 if (pp)
300 pp->next = np->next;
301 else if (!(p->st->l3.proc = np->next) &&
302 !test_bit(FLG_PTP, &p->st->l2.flag)) {
303 if (p->debug)
304 l3_debug(p->st, "release_l3_process: last process");
305 if (!skb_queue_len(&p->st->l3.squeue)) {
306 if (p->debug)
307 l3_debug(p->st, "release_l3_process: release link");
308 if (p->st->protocol != ISDN_PTYPE_NI1)
309 FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
310 else
311 FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL);
312 } else {
313 if (p->debug)
314 l3_debug(p->st, "release_l3_process: not release link");
315 }
316 }
317 kfree(p);
318 return;
319 }
320 pp = np;
321 np = np->next;
322 }
323 printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
324 l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
325};
326
327static void
328l3ml3p(struct PStack *st, int pr)
329{
330 struct l3_process *p = st->l3.proc;
331 struct l3_process *np;
332
333 while (p) {
334 /* p might be kfreed under us, so we need to save where we want to go on */
335 np = p->next;
336 st->l3.l3ml3(st, pr, p);
337 p = np;
338 }
339}
340
341void
342setstack_l3dc(struct PStack *st, struct Channel *chanp)
343{
344 char tmp[64];
345
346 st->l3.proc = NULL;
347 st->l3.global = NULL;
348 skb_queue_head_init(&st->l3.squeue);
349 st->l3.l3m.fsm = &l3fsm;
350 st->l3.l3m.state = ST_L3_LC_REL;
351 st->l3.l3m.debug = 1;
352 st->l3.l3m.userdata = st;
353 st->l3.l3m.userint = 0;
354 st->l3.l3m.printdebug = l3m_debug;
355 FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
356 strcpy(st->l3.debug_id, "L3DC ");
357 st->lli.l4l3_proto = no_l3_proto_spec;
358
359#ifdef CONFIG_HISAX_EURO
360 if (st->protocol == ISDN_PTYPE_EURO) {
361 setstack_dss1(st);
362 } else
363#endif
364#ifdef CONFIG_HISAX_NI1
365 if (st->protocol == ISDN_PTYPE_NI1) {
366 setstack_ni1(st);
367 } else
368#endif
369#ifdef CONFIG_HISAX_1TR6
370 if (st->protocol == ISDN_PTYPE_1TR6) {
371 setstack_1tr6(st);
372 } else
373#endif
374 if (st->protocol == ISDN_PTYPE_LEASED) {
375 st->lli.l4l3 = no_l3_proto;
376 st->l2.l2l3 = no_l3_proto;
377 st->l3.l3ml3 = no_l3_proto;
378 printk(KERN_INFO "HiSax: Leased line mode\n");
379 } else {
380 st->lli.l4l3 = no_l3_proto;
381 st->l2.l2l3 = no_l3_proto;
382 st->l3.l3ml3 = no_l3_proto;
383 sprintf(tmp, "protocol %s not supported",
384 (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
385 (st->protocol == ISDN_PTYPE_EURO) ? "euro" :
386 (st->protocol == ISDN_PTYPE_NI1) ? "ni1" :
387 "unknown");
388 printk(KERN_WARNING "HiSax: %s\n", tmp);
389 st->protocol = -1;
390 }
391}
392
393void
394isdnl3_trans(struct PStack *st, int pr, void *arg) {
395 st->l3.l3l2(st, pr, arg);
396}
397
398void
399releasestack_isdnl3(struct PStack *st)
400{
401 while (st->l3.proc)
402 release_l3_process(st->l3.proc);
403 if (st->l3.global) {
404 StopAllL3Timer(st->l3.global);
405 kfree(st->l3.global);
406 st->l3.global = NULL;
407 }
408 FsmDelTimer(&st->l3.l3m_timer, 54);
409 skb_queue_purge(&st->l3.squeue);
410}
411
412void
413setstack_l3bc(struct PStack *st, struct Channel *chanp)
414{
415
416 st->l3.proc = NULL;
417 st->l3.global = NULL;
418 skb_queue_head_init(&st->l3.squeue);
419 st->l3.l3m.fsm = &l3fsm;
420 st->l3.l3m.state = ST_L3_LC_REL;
421 st->l3.l3m.debug = 1;
422 st->l3.l3m.userdata = st;
423 st->l3.l3m.userint = 0;
424 st->l3.l3m.printdebug = l3m_debug;
425 strcpy(st->l3.debug_id, "L3BC ");
426 st->lli.l4l3 = isdnl3_trans;
427}
428
429#define DREL_TIMER_VALUE 40000
430
431static void
432lc_activate(struct FsmInst *fi, int event, void *arg)
433{
434 struct PStack *st = fi->userdata;
435
436 FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
437 st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
438}
439
440static void
441lc_connect(struct FsmInst *fi, int event, void *arg)
442{
443 struct PStack *st = fi->userdata;
444 struct sk_buff *skb = arg;
445 int dequeued = 0;
446
447 FsmChangeState(fi, ST_L3_LC_ESTAB);
448 while ((skb = skb_dequeue(&st->l3.squeue))) {
449 st->l3.l3l2(st, DL_DATA | REQUEST, skb);
450 dequeued++;
451 }
452 if ((!st->l3.proc) && dequeued) {
453 if (st->l3.debug)
454 l3_debug(st, "lc_connect: release link");
455 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
456 } else
457 l3ml3p(st, DL_ESTABLISH | INDICATION);
458}
459
460static void
461lc_connected(struct FsmInst *fi, int event, void *arg)
462{
463 struct PStack *st = fi->userdata;
464 struct sk_buff *skb = arg;
465 int dequeued = 0;
466
467 FsmDelTimer(&st->l3.l3m_timer, 51);
468 FsmChangeState(fi, ST_L3_LC_ESTAB);
469 while ((skb = skb_dequeue(&st->l3.squeue))) {
470 st->l3.l3l2(st, DL_DATA | REQUEST, skb);
471 dequeued++;
472 }
473 if ((!st->l3.proc) && dequeued) {
474 if (st->l3.debug)
475 l3_debug(st, "lc_connected: release link");
476 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
477 } else
478 l3ml3p(st, DL_ESTABLISH | CONFIRM);
479}
480
481static void
482lc_start_delay(struct FsmInst *fi, int event, void *arg)
483{
484 struct PStack *st = fi->userdata;
485
486 FsmChangeState(fi, ST_L3_LC_REL_DELAY);
487 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
488}
489
490static void
491lc_start_delay_check(struct FsmInst *fi, int event, void *arg)
492/* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */
493{
494 struct PStack *st = fi->userdata;
495
496 FsmChangeState(fi, ST_L3_LC_REL_DELAY);
497 /* 19/09/00 - GE timer not user for NI-1 */
498 if (st->protocol != ISDN_PTYPE_NI1)
499 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
500}
501
502static void
503lc_release_req(struct FsmInst *fi, int event, void *arg)
504{
505 struct PStack *st = fi->userdata;
506
507 if (test_bit(FLG_L2BLOCK, &st->l2.flag)) {
508 if (st->l3.debug)
509 l3_debug(st, "lc_release_req: l2 blocked");
510 /* restart release timer */
511 FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
512 } else {
513 FsmChangeState(fi, ST_L3_LC_REL_WAIT);
514 st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
515 }
516}
517
518static void
519lc_release_ind(struct FsmInst *fi, int event, void *arg)
520{
521 struct PStack *st = fi->userdata;
522
523 FsmDelTimer(&st->l3.l3m_timer, 52);
524 FsmChangeState(fi, ST_L3_LC_REL);
525 skb_queue_purge(&st->l3.squeue);
526 l3ml3p(st, DL_RELEASE | INDICATION);
527}
528
529static void
530lc_release_cnf(struct FsmInst *fi, int event, void *arg)
531{
532 struct PStack *st = fi->userdata;
533
534 FsmChangeState(fi, ST_L3_LC_REL);
535 skb_queue_purge(&st->l3.squeue);
536 l3ml3p(st, DL_RELEASE | CONFIRM);
537}
538
539
540/* *INDENT-OFF* */
541static struct FsmNode L3FnList[] __initdata =
542{
543 {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate},
544 {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect},
545 {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect},
546 {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected},
547 {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay},
548 {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind},
549 {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind},
550 {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check},
551 {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind},
552 {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected},
553 {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req},
554 {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf},
555 {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate},
556};
557/* *INDENT-ON* */
558
559#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
560
561void
562l3_msg(struct PStack *st, int pr, void *arg)
563{
564 switch (pr) {
565 case (DL_DATA | REQUEST):
566 if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
567 st->l3.l3l2(st, pr, arg);
568 } else {
569 struct sk_buff *skb = arg;
570
571 skb_queue_tail(&st->l3.squeue, skb);
572 FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
573 }
574 break;
575 case (DL_ESTABLISH | REQUEST):
576 FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
577 break;
578 case (DL_ESTABLISH | CONFIRM):
579 FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
580 break;
581 case (DL_ESTABLISH | INDICATION):
582 FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
583 break;
584 case (DL_RELEASE | INDICATION):
585 FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
586 break;
587 case (DL_RELEASE | CONFIRM):
588 FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
589 break;
590 case (DL_RELEASE | REQUEST):
591 FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
592 break;
593 }
594}
595
596int __init
597Isdnl3New(void)
598{
599 l3fsm.state_count = L3_STATE_COUNT;
600 l3fsm.event_count = L3_EVENT_COUNT;
601 l3fsm.strEvent = strL3Event;
602 l3fsm.strState = strL3State;
603 return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
604}
605
606void
607Isdnl3Free(void)
608{
609 FsmFree(&l3fsm);
610}
diff --git a/drivers/isdn/hisax/isdnl3.h b/drivers/isdn/hisax/isdnl3.h
new file mode 100644
index 00000000000..1dbe0297a50
--- /dev/null
+++ b/drivers/isdn/hisax/isdnl3.h
@@ -0,0 +1,37 @@
1/* $Id: isdnl3.h,v 2.6.6.2 2001/09/23 22:24:49 kai Exp $
2 *
3 * This software may be used and distributed according to the terms
4 * of the GNU General Public License, incorporated herein by reference.
5 *
6 */
7
8#define SBIT(state) (1<<state)
9#define ALL_STATES 0x03ffffff
10
11#define PROTO_DIS_EURO 0x08
12
13#define L3_DEB_WARN 0x01
14#define L3_DEB_PROTERR 0x02
15#define L3_DEB_STATE 0x04
16#define L3_DEB_CHARGE 0x08
17#define L3_DEB_CHECK 0x10
18#define L3_DEB_SI 0x20
19
20struct stateentry {
21 int state;
22 int primitive;
23 void (*rout) (struct l3_process *, u8, void *);
24};
25
26#define l3_debug(st, fmt, args...) HiSax_putstatus(st->l1.hardware, "l3 ", fmt, ## args)
27
28extern void newl3state(struct l3_process *pc, int state);
29extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
30extern void L3DelTimer(struct L3Timer *t);
31extern int L3AddTimer(struct L3Timer *t, int millisec, int event);
32extern void StopAllL3Timer(struct l3_process *pc);
33extern struct sk_buff *l3_alloc_skb(int len);
34extern struct l3_process *new_l3_process(struct PStack *st, int cr);
35extern void release_l3_process(struct l3_process *p);
36extern struct l3_process *getl3proc(struct PStack *st, int cr);
37extern void l3_msg(struct PStack *st, int pr, void *arg);
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
new file mode 100644
index 00000000000..af5171da734
--- /dev/null
+++ b/drivers/isdn/hisax/isurf.c
@@ -0,0 +1,306 @@
1/* $Id: isurf.c,v 1.12.2.4 2004/01/13 21:46:03 keil Exp $
2 *
3 * low level stuff for Siemens I-Surf/I-Talk cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "isac.h"
16#include "isar.h"
17#include "isdnl1.h"
18#include <linux/isapnp.h>
19
20extern const char *CardType[];
21
22static const char *ISurf_revision = "$Revision: 1.12.2.4 $";
23
24#define byteout(addr,val) outb(val,addr)
25#define bytein(addr) inb(addr)
26
27#define ISURF_ISAR_RESET 1
28#define ISURF_ISAC_RESET 2
29#define ISURF_ISAR_EA 4
30#define ISURF_ARCOFI_RESET 8
31#define ISURF_RESET (ISURF_ISAR_RESET | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET)
32
33#define ISURF_ISAR_OFFSET 0
34#define ISURF_ISAC_OFFSET 0x100
35#define ISURF_IOMEM_SIZE 0x400
36/* Interface functions */
37
38static u_char
39ReadISAC(struct IsdnCardState *cs, u_char offset)
40{
41 return (readb(cs->hw.isurf.isac + offset));
42}
43
44static void
45WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
46{
47 writeb(value, cs->hw.isurf.isac + offset); mb();
48}
49
50static void
51ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
52{
53 register int i;
54 for (i = 0; i < size; i++)
55 data[i] = readb(cs->hw.isurf.isac);
56}
57
58static void
59WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
60{
61 register int i;
62 for (i = 0; i < size; i++){
63 writeb(data[i], cs->hw.isurf.isac);mb();
64 }
65}
66
67/* ISAR access routines
68 * mode = 0 access with IRQ on
69 * mode = 1 access with IRQ off
70 * mode = 2 access with IRQ off and using last offset
71 */
72
73static u_char
74ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
75{
76 return(readb(cs->hw.isurf.isar + offset));
77}
78
79static void
80WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
81{
82 writeb(value, cs->hw.isurf.isar + offset);mb();
83}
84
85static irqreturn_t
86isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
87{
88 struct IsdnCardState *cs = dev_id;
89 u_char val;
90 int cnt = 5;
91 u_long flags;
92
93 spin_lock_irqsave(&cs->lock, flags);
94 val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
95 Start_ISAR:
96 if (val & ISAR_IRQSTA)
97 isar_int_main(cs);
98 val = readb(cs->hw.isurf.isac + ISAC_ISTA);
99 Start_ISAC:
100 if (val)
101 isac_interrupt(cs, val);
102 val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
103 if ((val & ISAR_IRQSTA) && --cnt) {
104 if (cs->debug & L1_DEB_HSCX)
105 debugl1(cs, "ISAR IntStat after IntRoutine");
106 goto Start_ISAR;
107 }
108 val = readb(cs->hw.isurf.isac + ISAC_ISTA);
109 if (val && --cnt) {
110 if (cs->debug & L1_DEB_ISAC)
111 debugl1(cs, "ISAC IntStat after IntRoutine");
112 goto Start_ISAC;
113 }
114 if (!cnt)
115 printk(KERN_WARNING "ISurf IRQ LOOP\n");
116
117 writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
118 writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
119 writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
120 writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
121 spin_unlock_irqrestore(&cs->lock, flags);
122 return IRQ_HANDLED;
123}
124
125void
126release_io_isurf(struct IsdnCardState *cs)
127{
128 release_region(cs->hw.isurf.reset, 1);
129 iounmap(cs->hw.isurf.isar);
130 release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
131}
132
133static void
134reset_isurf(struct IsdnCardState *cs, u_char chips)
135{
136 printk(KERN_INFO "ISurf: resetting card\n");
137
138 byteout(cs->hw.isurf.reset, chips); /* Reset On */
139 mdelay(10);
140 byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
141 mdelay(10);
142}
143
144static int
145ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
146{
147 u_long flags;
148
149 switch (mt) {
150 case CARD_RESET:
151 spin_lock_irqsave(&cs->lock, flags);
152 reset_isurf(cs, ISURF_RESET);
153 spin_unlock_irqrestore(&cs->lock, flags);
154 return(0);
155 case CARD_RELEASE:
156 release_io_isurf(cs);
157 return(0);
158 case CARD_INIT:
159 spin_lock_irqsave(&cs->lock, flags);
160 reset_isurf(cs, ISURF_RESET);
161 clear_pending_isac_ints(cs);
162 writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
163 initisac(cs);
164 initisar(cs);
165 /* Reenable ISAC IRQ */
166 cs->writeisac(cs, ISAC_MASK, 0);
167 /* RESET Receiver and Transmitter */
168 cs->writeisac(cs, ISAC_CMDR, 0x41);
169 spin_unlock_irqrestore(&cs->lock, flags);
170 return(0);
171 case CARD_TEST:
172 return(0);
173 }
174 return(0);
175}
176
177static int
178isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
179 int ret;
180 u_long flags;
181
182 if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) {
183 ret = isar_auxcmd(cs, ic);
184 spin_lock_irqsave(&cs->lock, flags);
185 if (!ret) {
186 reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
187 ISURF_ARCOFI_RESET);
188 initisac(cs);
189 cs->writeisac(cs, ISAC_MASK, 0);
190 cs->writeisac(cs, ISAC_CMDR, 0x41);
191 }
192 spin_unlock_irqrestore(&cs->lock, flags);
193 return(ret);
194 }
195 return(isar_auxcmd(cs, ic));
196}
197
198#ifdef __ISAPNP__
199static struct pnp_card *pnp_c __initdata = NULL;
200#endif
201
202int __init
203setup_isurf(struct IsdnCard *card)
204{
205 int ver;
206 struct IsdnCardState *cs = card->cs;
207 char tmp[64];
208
209 strcpy(tmp, ISurf_revision);
210 printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
211
212 if (cs->typ != ISDN_CTYPE_ISURF)
213 return(0);
214 if (card->para[1] && card->para[2]) {
215 cs->hw.isurf.reset = card->para[1];
216 cs->hw.isurf.phymem = card->para[2];
217 cs->irq = card->para[0];
218 } else {
219#ifdef __ISAPNP__
220 if (isapnp_present()) {
221 struct pnp_dev *pnp_d = NULL;
222 int err;
223
224 cs->subtyp = 0;
225 if ((pnp_c = pnp_find_card(
226 ISAPNP_VENDOR('S', 'I', 'E'),
227 ISAPNP_FUNCTION(0x0010), pnp_c))) {
228 if (!(pnp_d = pnp_find_dev(pnp_c,
229 ISAPNP_VENDOR('S', 'I', 'E'),
230 ISAPNP_FUNCTION(0x0010), pnp_d))) {
231 printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
232 return (0);
233 }
234 pnp_disable_dev(pnp_d);
235 err = pnp_activate_dev(pnp_d);
236 cs->hw.isurf.reset = pnp_port_start(pnp_d, 0);
237 cs->hw.isurf.phymem = pnp_mem_start(pnp_d, 1);
238 cs->irq = pnp_irq(pnp_d, 0);
239 if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
240 printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
241 cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
242 pnp_disable_dev(pnp_d);
243 return(0);
244 }
245 } else {
246 printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
247 return(0);
248 }
249 } else {
250 printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
251 return(0);
252 }
253#else
254 printk(KERN_WARNING "HiSax: %s port/mem not set\n",
255 CardType[card->typ]);
256 return (0);
257#endif
258 }
259 if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) {
260 printk(KERN_WARNING
261 "HiSax: %s config port %x already in use\n",
262 CardType[card->typ],
263 cs->hw.isurf.reset);
264 return (0);
265 }
266 if (!request_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, "isurf iomem")) {
267 printk(KERN_WARNING
268 "HiSax: %s memory region %lx-%lx already in use\n",
269 CardType[card->typ],
270 cs->hw.isurf.phymem,
271 cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
272 release_region(cs->hw.isurf.reset, 1);
273 return (0);
274 }
275 cs->hw.isurf.isar = ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
276 cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
277 printk(KERN_INFO
278 "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
279 cs->hw.isurf.reset,
280 cs->hw.isurf.phymem,
281 cs->irq);
282
283 setup_isac(cs);
284 cs->cardmsg = &ISurf_card_msg;
285 cs->irq_func = &isurf_interrupt;
286 cs->auxcmd = &isurf_auxcmd;
287 cs->readisac = &ReadISAC;
288 cs->writeisac = &WriteISAC;
289 cs->readisacfifo = &ReadISACfifo;
290 cs->writeisacfifo = &WriteISACfifo;
291 cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
292 cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
293 test_and_set_bit(HW_ISAR, &cs->HW_Flags);
294 ISACVersion(cs, "ISurf:");
295 cs->BC_Read_Reg = &ReadISAR;
296 cs->BC_Write_Reg = &WriteISAR;
297 cs->BC_Send_Data = &isar_fill_fifo;
298 ver = ISARVersion(cs, "ISurf:");
299 if (ver < 0) {
300 printk(KERN_WARNING
301 "ISurf: wrong ISAR version (ret = %d)\n", ver);
302 release_io_isurf(cs);
303 return (0);
304 }
305 return (1);
306}
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
new file mode 100644
index 00000000000..b843b7509ae
--- /dev/null
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -0,0 +1,318 @@
1/* $Id: ix1_micro.c,v 2.12.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for ITK ix1-micro Rev.2 isdn cards
4 * derived from the original file teles3.c from Karsten Keil
5 *
6 * Author Klaus-Peter Nischke
7 * Copyright by Klaus-Peter Nischke, ITK AG
8 * <klaus@nischke.do.eunet.de>
9 * by Karsten Keil <keil@isdn4linux.de>
10 *
11 * This software may be used and distributed according to the terms
12 * of the GNU General Public License, incorporated herein by reference.
13 *
14 * Klaus-Peter Nischke
15 * Deusener Str. 287
16 * 44369 Dortmund
17 * Germany
18 */
19
20#include <linux/init.h>
21#include <linux/isapnp.h>
22#include "hisax.h"
23#include "isac.h"
24#include "hscx.h"
25#include "isdnl1.h"
26
27extern const char *CardType[];
28const char *ix1_revision = "$Revision: 2.12.2.4 $";
29
30#define byteout(addr,val) outb(val,addr)
31#define bytein(addr) inb(addr)
32
33#define SPECIAL_PORT_OFFSET 3
34
35#define ISAC_COMMAND_OFFSET 2
36#define ISAC_DATA_OFFSET 0
37#define HSCX_COMMAND_OFFSET 2
38#define HSCX_DATA_OFFSET 1
39
40#define TIMEOUT 50
41
42static inline u_char
43readreg(unsigned int ale, unsigned int adr, u_char off)
44{
45 register u_char ret;
46
47 byteout(ale, off);
48 ret = bytein(adr);
49 return (ret);
50}
51
52static inline void
53readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
54{
55 byteout(ale, off);
56 insb(adr, data, size);
57}
58
59
60static inline void
61writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
62{
63 byteout(ale, off);
64 byteout(adr, data);
65}
66
67static inline void
68writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
69{
70 byteout(ale, off);
71 outsb(adr, data, size);
72}
73
74/* Interface functions */
75
76static u_char
77ReadISAC(struct IsdnCardState *cs, u_char offset)
78{
79 return (readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset));
80}
81
82static void
83WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
84{
85 writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset, value);
86}
87
88static void
89ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
90{
91 readfifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size);
92}
93
94static void
95WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
96{
97 writefifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size);
98}
99
100static u_char
101ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
102{
103 return (readreg(cs->hw.ix1.hscx_ale,
104 cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0)));
105}
106
107static void
108WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
109{
110 writereg(cs->hw.ix1.hscx_ale,
111 cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value);
112}
113
114#define READHSCX(cs, nr, reg) readreg(cs->hw.ix1.hscx_ale, \
115 cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0))
116#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ix1.hscx_ale, \
117 cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0), data)
118
119#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ix1.hscx_ale, \
120 cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt)
121
122#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ix1.hscx_ale, \
123 cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt)
124
125#include "hscx_irq.c"
126
127static irqreturn_t
128ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
129{
130 struct IsdnCardState *cs = dev_id;
131 u_char val;
132 u_long flags;
133
134 spin_lock_irqsave(&cs->lock, flags);
135 val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
136 Start_HSCX:
137 if (val)
138 hscx_int_main(cs, val);
139 val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA);
140 Start_ISAC:
141 if (val)
142 isac_interrupt(cs, val);
143 val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
144 if (val) {
145 if (cs->debug & L1_DEB_HSCX)
146 debugl1(cs, "HSCX IntStat after IntRoutine");
147 goto Start_HSCX;
148 }
149 val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA);
150 if (val) {
151 if (cs->debug & L1_DEB_ISAC)
152 debugl1(cs, "ISAC IntStat after IntRoutine");
153 goto Start_ISAC;
154 }
155 writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF);
156 writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF);
157 writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF);
158 writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
159 writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
160 writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
161 spin_unlock_irqrestore(&cs->lock, flags);
162 return IRQ_HANDLED;
163}
164
165void
166release_io_ix1micro(struct IsdnCardState *cs)
167{
168 if (cs->hw.ix1.cfg_reg)
169 release_region(cs->hw.ix1.cfg_reg, 4);
170}
171
172static void
173ix1_reset(struct IsdnCardState *cs)
174{
175 int cnt;
176
177 /* reset isac */
178 cnt = 3 * (HZ / 10) + 1;
179 while (cnt--) {
180 byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 1);
181 HZDELAY(1); /* wait >=10 ms */
182 }
183 byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 0);
184}
185
186static int
187ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
188{
189 u_long flags;
190
191 switch (mt) {
192 case CARD_RESET:
193 spin_lock_irqsave(&cs->lock, flags);
194 ix1_reset(cs);
195 spin_unlock_irqrestore(&cs->lock, flags);
196 return(0);
197 case CARD_RELEASE:
198 release_io_ix1micro(cs);
199 return(0);
200 case CARD_INIT:
201 spin_lock_irqsave(&cs->lock, flags);
202 ix1_reset(cs);
203 inithscxisac(cs, 3);
204 spin_unlock_irqrestore(&cs->lock, flags);
205 return(0);
206 case CARD_TEST:
207 return(0);
208 }
209 return(0);
210}
211
212#ifdef __ISAPNP__
213static struct isapnp_device_id itk_ids[] __initdata = {
214 { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
215 ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
216 (unsigned long) "ITK micro 2" },
217 { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
218 ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
219 (unsigned long) "ITK micro 2." },
220 { 0, }
221};
222
223static struct isapnp_device_id *ipid __initdata = &itk_ids[0];
224static struct pnp_card *pnp_c __devinitdata = NULL;
225#endif
226
227
228int __init
229setup_ix1micro(struct IsdnCard *card)
230{
231 struct IsdnCardState *cs = card->cs;
232 char tmp[64];
233
234 strcpy(tmp, ix1_revision);
235 printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
236 if (cs->typ != ISDN_CTYPE_IX1MICROR2)
237 return (0);
238
239#ifdef __ISAPNP__
240 if (!card->para[1] && isapnp_present()) {
241 struct pnp_dev *pnp_d;
242 while(ipid->card_vendor) {
243 if ((pnp_c = pnp_find_card(ipid->card_vendor,
244 ipid->card_device, pnp_c))) {
245 pnp_d = NULL;
246 if ((pnp_d = pnp_find_dev(pnp_c,
247 ipid->vendor, ipid->function, pnp_d))) {
248 int err;
249
250 printk(KERN_INFO "HiSax: %s detected\n",
251 (char *)ipid->driver_data);
252 pnp_disable_dev(pnp_d);
253 err = pnp_activate_dev(pnp_d);
254 if (err<0) {
255 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
256 __FUNCTION__, err);
257 return(0);
258 }
259 card->para[1] = pnp_port_start(pnp_d, 0);
260 card->para[0] = pnp_irq(pnp_d, 0);
261 if (!card->para[0] || !card->para[1]) {
262 printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n",
263 card->para[0], card->para[1]);
264 pnp_disable_dev(pnp_d);
265 return(0);
266 }
267 break;
268 } else {
269 printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
270 }
271 }
272 ipid++;
273 pnp_c = NULL;
274 }
275 if (!ipid->card_vendor) {
276 printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
277 return(0);
278 }
279 }
280#endif
281 /* IO-Ports */
282 cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
283 cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET;
284 cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
285 cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
286 cs->hw.ix1.cfg_reg = card->para[1];
287 cs->irq = card->para[0];
288 if (cs->hw.ix1.cfg_reg) {
289 if (!request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) {
290 printk(KERN_WARNING
291 "HiSax: %s config port %x-%x already in use\n",
292 CardType[card->typ],
293 cs->hw.ix1.cfg_reg,
294 cs->hw.ix1.cfg_reg + 4);
295 return (0);
296 }
297 }
298 printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
299 CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
300 setup_isac(cs);
301 cs->readisac = &ReadISAC;
302 cs->writeisac = &WriteISAC;
303 cs->readisacfifo = &ReadISACfifo;
304 cs->writeisacfifo = &WriteISACfifo;
305 cs->BC_Read_Reg = &ReadHSCX;
306 cs->BC_Write_Reg = &WriteHSCX;
307 cs->BC_Send_Data = &hscx_fill_fifo;
308 cs->cardmsg = &ix1_card_msg;
309 cs->irq_func = &ix1micro_interrupt;
310 ISACVersion(cs, "ix1-Micro:");
311 if (HscxVersion(cs, "ix1-Micro:")) {
312 printk(KERN_WARNING
313 "ix1-Micro: wrong HSCX versions check IO address\n");
314 release_io_ix1micro(cs);
315 return (0);
316 }
317 return (1);
318}
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
new file mode 100644
index 00000000000..f05d5275755
--- /dev/null
+++ b/drivers/isdn/hisax/jade.c
@@ -0,0 +1,318 @@
1/* $Id: jade.c,v 1.9.2.4 2004/01/14 16:04:48 keil Exp $
2 *
3 * JADE stuff (derived from original hscx.c)
4 *
5 * Author Roland Klabunde
6 * Copyright by Roland Klabunde <R.Klabunde@Berkom.de>
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
13
14#include <linux/init.h>
15#include "hisax.h"
16#include "hscx.h"
17#include "jade.h"
18#include "isdnl1.h"
19#include <linux/interrupt.h>
20
21
22int __init
23JadeVersion(struct IsdnCardState *cs, char *s)
24{
25 int ver,i;
26 int to = 50;
27 cs->BC_Write_Reg(cs, -1, 0x50, 0x19);
28 i=0;
29 while (to) {
30 udelay(1);
31 ver = cs->BC_Read_Reg(cs, -1, 0x60);
32 to--;
33 if (ver)
34 break;
35 if (!to) {
36 printk(KERN_INFO "%s JADE version not obtainable\n", s);
37 return (0);
38 }
39 }
40 /* Wait for the JADE */
41 udelay(10);
42 /* Read version */
43 ver = cs->BC_Read_Reg(cs, -1, 0x60);
44 printk(KERN_INFO "%s JADE version: %d\n", s, ver);
45 return (1);
46}
47
48/* Write to indirect accessible jade register set */
49static void
50jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
51{
52 int to = 50;
53 u_char ret;
54
55 /* Write the data */
56 cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value);
57 /* Say JADE we wanna write indirect reg 'reg' */
58 cs->BC_Write_Reg(cs, -1, COMM_JADE, reg);
59 to = 50;
60 /* Wait for RDY goes high */
61 while (to) {
62 udelay(1);
63 ret = cs->BC_Read_Reg(cs, -1, COMM_JADE);
64 to--;
65 if (ret & 1)
66 /* Got acknowledge */
67 break;
68 if (!to) {
69 printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value);
70 return;
71 }
72 }
73}
74
75
76
77void
78modejade(struct BCState *bcs, int mode, int bc)
79{
80 struct IsdnCardState *cs = bcs->cs;
81 int jade = bcs->hw.hscx.hscx;
82
83 if (cs->debug & L1_DEB_HSCX) {
84 char tmp[40];
85 sprintf(tmp, "jade %c mode %d ichan %d",
86 'A' + jade, mode, bc);
87 debugl1(cs, tmp);
88 }
89 bcs->mode = mode;
90 bcs->channel = bc;
91
92 cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00));
93 cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF));
94 cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00);
95
96 jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08);
97 jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08);
98 jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00);
99 jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00);
100
101 cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07);
102 cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07);
103
104 if (bc == 0) {
105 cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00);
106 cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00);
107 } else {
108 cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04);
109 cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04);
110 }
111 switch (mode) {
112 case (L1_MODE_NULL):
113 cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO);
114 break;
115 case (L1_MODE_TRANS):
116 cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC));
117 break;
118 case (L1_MODE_HDLC):
119 cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC));
120 break;
121 }
122 if (mode) {
123 cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC));
124 cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES);
125 /* Unmask ints */
126 cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8);
127 }
128 else
129 /* Mask ints */
130 cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00);
131}
132
133static void
134jade_l2l1(struct PStack *st, int pr, void *arg)
135{
136 struct BCState *bcs = st->l1.bcs;
137 struct sk_buff *skb = arg;
138 u_long flags;
139
140 switch (pr) {
141 case (PH_DATA | REQUEST):
142 spin_lock_irqsave(&bcs->cs->lock, flags);
143 if (bcs->tx_skb) {
144 skb_queue_tail(&bcs->squeue, skb);
145 } else {
146 bcs->tx_skb = skb;
147 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
148 bcs->hw.hscx.count = 0;
149 bcs->cs->BC_Send_Data(bcs);
150 }
151 spin_unlock_irqrestore(&bcs->cs->lock, flags);
152 break;
153 case (PH_PULL | INDICATION):
154 spin_lock_irqsave(&bcs->cs->lock, flags);
155 if (bcs->tx_skb) {
156 printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n");
157 } else {
158 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
159 bcs->tx_skb = skb;
160 bcs->hw.hscx.count = 0;
161 bcs->cs->BC_Send_Data(bcs);
162 }
163 spin_unlock_irqrestore(&bcs->cs->lock, flags);
164 break;
165 case (PH_PULL | REQUEST):
166 if (!bcs->tx_skb) {
167 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
168 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
169 } else
170 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
171 break;
172 case (PH_ACTIVATE | REQUEST):
173 spin_lock_irqsave(&bcs->cs->lock, flags);
174 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
175 modejade(bcs, st->l1.mode, st->l1.bc);
176 spin_unlock_irqrestore(&bcs->cs->lock, flags);
177 l1_msg_b(st, pr, arg);
178 break;
179 case (PH_DEACTIVATE | REQUEST):
180 l1_msg_b(st, pr, arg);
181 break;
182 case (PH_DEACTIVATE | CONFIRM):
183 spin_lock_irqsave(&bcs->cs->lock, flags);
184 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
185 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
186 modejade(bcs, 0, st->l1.bc);
187 spin_unlock_irqrestore(&bcs->cs->lock, flags);
188 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
189 break;
190 }
191}
192
193void
194close_jadestate(struct BCState *bcs)
195{
196 modejade(bcs, 0, bcs->channel);
197 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
198 if (bcs->hw.hscx.rcvbuf) {
199 kfree(bcs->hw.hscx.rcvbuf);
200 bcs->hw.hscx.rcvbuf = NULL;
201 }
202 if (bcs->blog) {
203 kfree(bcs->blog);
204 bcs->blog = NULL;
205 }
206 skb_queue_purge(&bcs->rqueue);
207 skb_queue_purge(&bcs->squeue);
208 if (bcs->tx_skb) {
209 dev_kfree_skb_any(bcs->tx_skb);
210 bcs->tx_skb = NULL;
211 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
212 }
213 }
214}
215
216static int
217open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
218{
219 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
220 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
221 printk(KERN_WARNING
222 "HiSax: No memory for hscx.rcvbuf\n");
223 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
224 return (1);
225 }
226 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
227 printk(KERN_WARNING
228 "HiSax: No memory for bcs->blog\n");
229 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
230 kfree(bcs->hw.hscx.rcvbuf);
231 bcs->hw.hscx.rcvbuf = NULL;
232 return (2);
233 }
234 skb_queue_head_init(&bcs->rqueue);
235 skb_queue_head_init(&bcs->squeue);
236 }
237 bcs->tx_skb = NULL;
238 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
239 bcs->event = 0;
240 bcs->hw.hscx.rcvidx = 0;
241 bcs->tx_cnt = 0;
242 return (0);
243}
244
245
246int
247setstack_jade(struct PStack *st, struct BCState *bcs)
248{
249 bcs->channel = st->l1.bc;
250 if (open_jadestate(st->l1.hardware, bcs))
251 return (-1);
252 st->l1.bcs = bcs;
253 st->l2.l2l1 = jade_l2l1;
254 setstack_manager(st);
255 bcs->st = st;
256 setstack_l1_B(st);
257 return (0);
258}
259
260void __init
261clear_pending_jade_ints(struct IsdnCardState *cs)
262{
263 int val;
264 char tmp[64];
265
266 cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
267 cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
268
269 val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
270 sprintf(tmp, "jade B ISTA %x", val);
271 debugl1(cs, tmp);
272 val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
273 sprintf(tmp, "jade A ISTA %x", val);
274 debugl1(cs, tmp);
275 val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
276 sprintf(tmp, "jade B STAR %x", val);
277 debugl1(cs, tmp);
278 val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
279 sprintf(tmp, "jade A STAR %x", val);
280 debugl1(cs, tmp);
281 /* Unmask ints */
282 cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
283 cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
284}
285
286void __init
287initjade(struct IsdnCardState *cs)
288{
289 cs->bcs[0].BC_SetStack = setstack_jade;
290 cs->bcs[1].BC_SetStack = setstack_jade;
291 cs->bcs[0].BC_Close = close_jadestate;
292 cs->bcs[1].BC_Close = close_jadestate;
293 cs->bcs[0].hw.hscx.hscx = 0;
294 cs->bcs[1].hw.hscx.hscx = 1;
295
296 /* Stop DSP audio tx/rx */
297 jade_write_indirect(cs, 0x11, 0x0f);
298 jade_write_indirect(cs, 0x17, 0x2f);
299
300 /* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */
301 cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO);
302 cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO);
303 /* Power down, 1-Idle, RxTx least significant bit first */
304 cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00);
305 cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00);
306 /* Mask all interrupts */
307 cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
308 cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
309 /* Setup host access to hdlc controller */
310 jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2));
311 /* Unmask HDLC int (don´t forget DSP int later on)*/
312 cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2));
313
314 /* once again TRANSPARENT */
315 modejade(cs->bcs, 0, 0);
316 modejade(cs->bcs + 1, 0, 0);
317}
318
diff --git a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h
new file mode 100644
index 00000000000..fa294448599
--- /dev/null
+++ b/drivers/isdn/hisax/jade.h
@@ -0,0 +1,135 @@
1/* $Id: jade.h,v 1.5.2.3 2004/01/14 16:04:48 keil Exp $
2 *
3 * JADE specific defines
4 *
5 * Author Roland Klabunde
6 * Copyright by Roland Klabunde <R.Klabunde@Berkom.de>
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
13/* All Registers original Siemens Spec */
14#ifndef __JADE_H__
15#define __JADE_H__
16
17/* Special registers for access to indirect accessible JADE regs */
18#define DIRECT_IO_JADE 0x0000 /* Jade direct io access area */
19#define COMM_JADE 0x0040 /* Jade communication area */
20
21/********************************************************************/
22/* JADE-HDLC registers */
23/********************************************************************/
24#define jade_HDLC_RFIFO 0x00 /* R */
25#define jade_HDLC_XFIFO 0x00 /* W */
26
27#define jade_HDLC_STAR 0x20 /* R */
28 #define jadeSTAR_XDOV 0x80
29 #define jadeSTAR_XFW 0x40 /* Does not work*/
30 #define jadeSTAR_XCEC 0x20
31 #define jadeSTAR_RCEC 0x10
32 #define jadeSTAR_BSY 0x08
33 #define jadeSTAR_RNA 0x04
34 #define jadeSTAR_STR 0x02
35 #define jadeSTAR_STX 0x01
36
37#define jade_HDLC_XCMD 0x20 /* W */
38 #define jadeXCMD_XF 0x80
39 #define jadeXCMD_XME 0x40
40 #define jadeXCMD_XRES 0x20
41 #define jadeXCMD_STX 0x01
42
43#define jade_HDLC_RSTA 0x21 /* R */
44 #define jadeRSTA_VFR 0x80
45 #define jadeRSTA_RDO 0x40
46 #define jadeRSTA_CRC 0x20
47 #define jadeRSTA_RAB 0x10
48 #define jadeRSTA_MASK 0xF0
49
50#define jade_HDLC_MODE 0x22 /* RW*/
51 #define jadeMODE_TMO 0x80
52 #define jadeMODE_RAC 0x40
53 #define jadeMODE_XAC 0x20
54 #define jadeMODE_TLP 0x10
55 #define jadeMODE_ERFS 0x02
56 #define jadeMODE_ETFS 0x01
57
58#define jade_HDLC_RBCH 0x24 /* R */
59
60#define jade_HDLC_RBCL 0x25 /* R */
61#define jade_HDLC_RCMD 0x25 /* W */
62 #define jadeRCMD_RMC 0x80
63 #define jadeRCMD_RRES 0x40
64 #define jadeRCMD_RMD 0x20
65 #define jadeRCMD_STR 0x02
66
67#define jade_HDLC_CCR0 0x26 /* RW*/
68 #define jadeCCR0_PU 0x80
69 #define jadeCCR0_ITF 0x40
70 #define jadeCCR0_C32 0x20
71 #define jadeCCR0_CRL 0x10
72 #define jadeCCR0_RCRC 0x08
73 #define jadeCCR0_XCRC 0x04
74 #define jadeCCR0_RMSB 0x02
75 #define jadeCCR0_XMSB 0x01
76
77#define jade_HDLC_CCR1 0x27 /* RW*/
78 #define jadeCCR1_RCS0 0x80
79 #define jadeCCR1_RCONT 0x40
80 #define jadeCCR1_RFDIS 0x20
81 #define jadeCCR1_XCS0 0x10
82 #define jadeCCR1_XCONT 0x08
83 #define jadeCCR1_XFDIS 0x04
84
85#define jade_HDLC_TSAR 0x28 /* RW*/
86#define jade_HDLC_TSAX 0x29 /* RW*/
87#define jade_HDLC_RCCR 0x2A /* RW*/
88#define jade_HDLC_XCCR 0x2B /* RW*/
89
90#define jade_HDLC_ISR 0x2C /* R */
91#define jade_HDLC_IMR 0x2C /* W */
92 #define jadeISR_RME 0x80
93 #define jadeISR_RPF 0x40
94 #define jadeISR_RFO 0x20
95 #define jadeISR_XPR 0x10
96 #define jadeISR_XDU 0x08
97 #define jadeISR_ALLS 0x04
98
99#define jade_INT 0x75
100 #define jadeINT_HDLC1 0x02
101 #define jadeINT_HDLC2 0x01
102 #define jadeINT_DSP 0x04
103#define jade_INTR 0x70
104
105/********************************************************************/
106/* Indirect accessible JADE registers of common interest */
107/********************************************************************/
108#define jade_CHIPVERSIONNR 0x00 /* Does not work*/
109
110#define jade_HDLCCNTRACCESS 0x10
111 #define jadeINDIRECT_HAH1 0x02
112 #define jadeINDIRECT_HAH2 0x01
113
114#define jade_HDLC1SERRXPATH 0x1D
115#define jade_HDLC1SERTXPATH 0x1E
116#define jade_HDLC2SERRXPATH 0x1F
117#define jade_HDLC2SERTXPATH 0x20
118 #define jadeINDIRECT_SLIN1 0x10
119 #define jadeINDIRECT_SLIN0 0x08
120 #define jadeINDIRECT_LMOD1 0x04
121 #define jadeINDIRECT_LMOD0 0x02
122 #define jadeINDIRECT_HHR 0x01
123 #define jadeINDIRECT_HHX 0x01
124
125#define jade_RXAUDIOCH1CFG 0x11
126#define jade_RXAUDIOCH2CFG 0x14
127#define jade_TXAUDIOCH1CFG 0x17
128#define jade_TXAUDIOCH2CFG 0x1A
129
130extern int JadeVersion(struct IsdnCardState *cs, char *s);
131extern void modejade(struct BCState *bcs, int mode, int bc);
132extern void clear_pending_jade_ints(struct IsdnCardState *cs);
133extern void initjade(struct IsdnCardState *cs);
134
135#endif /* __JADE_H__ */
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
new file mode 100644
index 00000000000..08563400e4f
--- /dev/null
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -0,0 +1,236 @@
1/* $Id: jade_irq.c,v 1.7.2.4 2004/02/11 13:21:34 keil Exp $
2 *
3 * Low level JADE IRQ stuff (derived from original hscx_irq.c)
4 *
5 * Author Roland Klabunde
6 * Copyright by Roland Klabunde <R.Klabunde@Berkom.de>
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
13static inline void
14waitforCEC(struct IsdnCardState *cs, int jade, int reg)
15{
16 int to = 50;
17 int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC);
18 while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) {
19 udelay(1);
20 to--;
21 }
22 if (!to)
23 printk(KERN_WARNING "HiSax: waitforCEC (jade) timeout\n");
24}
25
26
27static inline void
28waitforXFW(struct IsdnCardState *cs, int jade)
29{
30 /* Does not work on older jade versions, don't care */
31}
32
33static inline void
34WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data)
35{
36 waitforCEC(cs, jade, reg);
37 WRITEJADE(cs, jade, reg, data);
38}
39
40
41
42static void
43jade_empty_fifo(struct BCState *bcs, int count)
44{
45 u_char *ptr;
46 struct IsdnCardState *cs = bcs->cs;
47
48 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
49 debugl1(cs, "jade_empty_fifo");
50
51 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
52 if (cs->debug & L1_DEB_WARN)
53 debugl1(cs, "jade_empty_fifo: incoming packet too large");
54 WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
55 bcs->hw.hscx.rcvidx = 0;
56 return;
57 }
58 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
59 bcs->hw.hscx.rcvidx += count;
60 READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
61 WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
62 if (cs->debug & L1_DEB_HSCX_FIFO) {
63 char *t = bcs->blog;
64
65 t += sprintf(t, "jade_empty_fifo %c cnt %d",
66 bcs->hw.hscx.hscx ? 'B' : 'A', count);
67 QuickHex(t, ptr, count);
68 debugl1(cs, bcs->blog);
69 }
70}
71
72static void
73jade_fill_fifo(struct BCState *bcs)
74{
75 struct IsdnCardState *cs = bcs->cs;
76 int more, count;
77 int fifo_size = 32;
78 u_char *ptr;
79
80 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
81 debugl1(cs, "jade_fill_fifo");
82
83 if (!bcs->tx_skb)
84 return;
85 if (bcs->tx_skb->len <= 0)
86 return;
87
88 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
89 if (bcs->tx_skb->len > fifo_size) {
90 more = !0;
91 count = fifo_size;
92 } else
93 count = bcs->tx_skb->len;
94
95 waitforXFW(cs, bcs->hw.hscx.hscx);
96 ptr = bcs->tx_skb->data;
97 skb_pull(bcs->tx_skb, count);
98 bcs->tx_cnt -= count;
99 bcs->hw.hscx.count += count;
100 WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
101 WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
102 if (cs->debug & L1_DEB_HSCX_FIFO) {
103 char *t = bcs->blog;
104
105 t += sprintf(t, "jade_fill_fifo %c cnt %d",
106 bcs->hw.hscx.hscx ? 'B' : 'A', count);
107 QuickHex(t, ptr, count);
108 debugl1(cs, bcs->blog);
109 }
110}
111
112
113static inline void
114jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
115{
116 u_char r;
117 struct BCState *bcs = cs->bcs + jade;
118 struct sk_buff *skb;
119 int fifo_size = 32;
120 int count;
121 int i_jade = (int) jade; /* To satisfy the compiler */
122
123 if (!test_bit(BC_FLG_INIT, &bcs->Flag))
124 return;
125
126 if (val & 0x80) { /* RME */
127 r = READJADE(cs, i_jade, jade_HDLC_RSTA);
128 if ((r & 0xf0) != 0xa0) {
129 if (!(r & 0x80))
130 if (cs->debug & L1_DEB_WARN)
131 debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A"));
132 if ((r & 0x40) && bcs->mode)
133 if (cs->debug & L1_DEB_WARN)
134 debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode);
135 if (!(r & 0x20))
136 if (cs->debug & L1_DEB_WARN)
137 debugl1(cs, "JADE %c CRC error", 'A'+jade);
138 WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
139 } else {
140 count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
141 if (count == 0)
142 count = fifo_size;
143 jade_empty_fifo(bcs, count);
144 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
145 if (cs->debug & L1_DEB_HSCX_FIFO)
146 debugl1(cs, "HX Frame %d", count);
147 if (!(skb = dev_alloc_skb(count)))
148 printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
149 else {
150 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
151 skb_queue_tail(&bcs->rqueue, skb);
152 }
153 }
154 }
155 bcs->hw.hscx.rcvidx = 0;
156 schedule_event(bcs, B_RCVBUFREADY);
157 }
158 if (val & 0x40) { /* RPF */
159 jade_empty_fifo(bcs, fifo_size);
160 if (bcs->mode == L1_MODE_TRANS) {
161 /* receive audio data */
162 if (!(skb = dev_alloc_skb(fifo_size)))
163 printk(KERN_WARNING "HiSax: receive out of memory\n");
164 else {
165 memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
166 skb_queue_tail(&bcs->rqueue, skb);
167 }
168 bcs->hw.hscx.rcvidx = 0;
169 schedule_event(bcs, B_RCVBUFREADY);
170 }
171 }
172 if (val & 0x10) { /* XPR */
173 if (bcs->tx_skb) {
174 if (bcs->tx_skb->len) {
175 jade_fill_fifo(bcs);
176 return;
177 } else {
178 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
179 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
180 u_long flags;
181 spin_lock_irqsave(&bcs->aclock, flags);
182 bcs->ackcnt += bcs->hw.hscx.count;
183 spin_unlock_irqrestore(&bcs->aclock, flags);
184 schedule_event(bcs, B_ACKPENDING);
185 }
186 dev_kfree_skb_irq(bcs->tx_skb);
187 bcs->hw.hscx.count = 0;
188 bcs->tx_skb = NULL;
189 }
190 }
191 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
192 bcs->hw.hscx.count = 0;
193 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
194 jade_fill_fifo(bcs);
195 } else {
196 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
197 schedule_event(bcs, B_XMTBUFREADY);
198 }
199 }
200}
201
202static inline void
203jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
204{
205 struct BCState *bcs;
206 bcs = cs->bcs + jade;
207
208 if (val & jadeISR_RFO) {
209 /* handled with RDO */
210 val &= ~jadeISR_RFO;
211 }
212 if (val & jadeISR_XDU) {
213 /* relevant in HDLC mode only */
214 /* don't reset XPR here */
215 if (bcs->mode == 1)
216 jade_fill_fifo(bcs);
217 else {
218 /* Here we lost an TX interrupt, so
219 * restart transmitting the whole frame.
220 */
221 if (bcs->tx_skb) {
222 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
223 bcs->tx_cnt += bcs->hw.hscx.count;
224 bcs->hw.hscx.count = 0;
225 }
226 WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
227 if (cs->debug & L1_DEB_WARN)
228 debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val);
229 }
230 }
231 if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
232 if (cs->debug & L1_DEB_HSCX)
233 debugl1(cs, "JADE %c interrupt %x", 'A'+jade, val);
234 jade_interrupt(cs, val, jade);
235 }
236}
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
new file mode 100644
index 00000000000..d6c1c8f8329
--- /dev/null
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -0,0 +1,955 @@
1/* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $
2 *
3 * German 1TR6 D-channel protocol
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * For changes and modifications please read
12 * Documentation/isdn/HiSax.cert
13 *
14 */
15
16#include "hisax.h"
17#include "l3_1tr6.h"
18#include "isdnl3.h"
19#include <linux/ctype.h>
20
21extern char *HiSax_getrev(const char *revision);
22const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
23
24#define MsgHead(ptr, cref, mty, dis) \
25 *ptr++ = dis; \
26 *ptr++ = 0x1; \
27 *ptr++ = cref ^ 0x80; \
28 *ptr++ = mty
29
30static void
31l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd)
32{
33 struct sk_buff *skb;
34 u_char *p;
35
36 if (!(skb = l3_alloc_skb(4)))
37 return;
38 p = skb_put(skb, 4);
39 MsgHead(p, pc->callref, mt, pd);
40 l3_msg(pc->st, DL_DATA | REQUEST, skb);
41}
42
43static void
44l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
45{
46 StopAllL3Timer(pc);
47 newl3state(pc, 19);
48 l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
49 L3AddTimer(&pc->timer, T308, CC_T308_1);
50}
51
52static void
53l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
54{
55 struct sk_buff *skb = arg;
56
57 dev_kfree_skb(skb);
58 l3_1tr6_release_req(pc, 0, NULL);
59}
60
61static void
62l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
63{
64 dev_kfree_skb(skb);
65 if (pc->st->l3.debug & L3_DEB_WARN)
66 l3_debug(pc->st, msg);
67 l3_1tr6_release_req(pc, 0, NULL);
68}
69
70static void
71l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg)
72{
73 struct sk_buff *skb;
74 u_char tmp[128];
75 u_char *p = tmp;
76 u_char *teln;
77 u_char *eaz;
78 u_char channel = 0;
79 int l;
80
81 MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1);
82 teln = pc->para.setup.phone;
83 pc->para.spv = 0;
84 if (!isdigit(*teln)) {
85 switch (0x5f & *teln) {
86 case 'S':
87 pc->para.spv = 1;
88 break;
89 case 'C':
90 channel = 0x08;
91 case 'P':
92 channel |= 0x80;
93 teln++;
94 if (*teln == '1')
95 channel |= 0x01;
96 else
97 channel |= 0x02;
98 break;
99 default:
100 if (pc->st->l3.debug & L3_DEB_WARN)
101 l3_debug(pc->st, "Wrong MSN Code");
102 break;
103 }
104 teln++;
105 }
106 if (channel) {
107 *p++ = 0x18; /* channel indicator */
108 *p++ = 1;
109 *p++ = channel;
110 }
111 if (pc->para.spv) { /* SPV ? */
112 /* NSF SPV */
113 *p++ = WE0_netSpecFac;
114 *p++ = 4; /* Laenge */
115 *p++ = 0;
116 *p++ = FAC_SPV; /* SPV */
117 *p++ = pc->para.setup.si1; /* 0 for all Services */
118 *p++ = pc->para.setup.si2; /* 0 for all Services */
119 *p++ = WE0_netSpecFac;
120 *p++ = 4; /* Laenge */
121 *p++ = 0;
122 *p++ = FAC_Activate; /* aktiviere SPV (default) */
123 *p++ = pc->para.setup.si1; /* 0 for all Services */
124 *p++ = pc->para.setup.si2; /* 0 for all Services */
125 }
126 eaz = pc->para.setup.eazmsn;
127 if (*eaz) {
128 *p++ = WE0_origAddr;
129 *p++ = strlen(eaz) + 1;
130 /* Classify as AnyPref. */
131 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
132 while (*eaz)
133 *p++ = *eaz++ & 0x7f;
134 }
135 *p++ = WE0_destAddr;
136 *p++ = strlen(teln) + 1;
137 /* Classify as AnyPref. */
138 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
139 while (*teln)
140 *p++ = *teln++ & 0x7f;
141
142 *p++ = WE_Shift_F6;
143 /* Codesatz 6 fuer Service */
144 *p++ = WE6_serviceInd;
145 *p++ = 2; /* len=2 info,info2 */
146 *p++ = pc->para.setup.si1;
147 *p++ = pc->para.setup.si2;
148
149 l = p - tmp;
150 if (!(skb = l3_alloc_skb(l)))
151 return;
152 memcpy(skb_put(skb, l), tmp, l);
153 L3DelTimer(&pc->timer);
154 L3AddTimer(&pc->timer, T303, CC_T303);
155 newl3state(pc, 1);
156 l3_msg(pc->st, DL_DATA | REQUEST, skb);
157}
158
159static void
160l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
161{
162 u_char *p;
163 int bcfound = 0;
164 char tmp[80];
165 struct sk_buff *skb = arg;
166
167 p = skb->data;
168
169 /* Channel Identification */
170 p = skb->data;
171 if ((p = findie(p, skb->len, WE0_chanID, 0))) {
172 if (p[1] != 1) {
173 l3_1tr6_error(pc, "setup wrong chanID len", skb);
174 return;
175 }
176 if ((p[2] & 0xf4) != 0x80) {
177 l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
178 return;
179 }
180 if ((pc->para.bchannel = p[2] & 0x3))
181 bcfound++;
182 } else {
183 l3_1tr6_error(pc, "missing setup chanID", skb);
184 return;
185 }
186
187 p = skb->data;
188 if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
189 pc->para.setup.si1 = p[2];
190 pc->para.setup.si2 = p[3];
191 } else {
192 l3_1tr6_error(pc, "missing setup SI", skb);
193 return;
194 }
195
196 p = skb->data;
197 if ((p = findie(p, skb->len, WE0_destAddr, 0)))
198 iecpy(pc->para.setup.eazmsn, p, 1);
199 else
200 pc->para.setup.eazmsn[0] = 0;
201
202 p = skb->data;
203 if ((p = findie(p, skb->len, WE0_origAddr, 0))) {
204 iecpy(pc->para.setup.phone, p, 1);
205 } else
206 pc->para.setup.phone[0] = 0;
207
208 p = skb->data;
209 pc->para.spv = 0;
210 if ((p = findie(p, skb->len, WE0_netSpecFac, 0))) {
211 if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
212 pc->para.spv = 1;
213 }
214 dev_kfree_skb(skb);
215
216 /* Signal all services, linklevel takes care of Service-Indicator */
217 if (bcfound) {
218 if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) {
219 sprintf(tmp, "non-digital call: %s -> %s",
220 pc->para.setup.phone,
221 pc->para.setup.eazmsn);
222 l3_debug(pc->st, tmp);
223 }
224 newl3state(pc, 6);
225 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
226 } else
227 release_l3_process(pc);
228}
229
230static void
231l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
232{
233 u_char *p;
234 struct sk_buff *skb = arg;
235
236 L3DelTimer(&pc->timer);
237 p = skb->data;
238 newl3state(pc, 2);
239 if ((p = findie(p, skb->len, WE0_chanID, 0))) {
240 if (p[1] != 1) {
241 l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
242 return;
243 }
244 if ((p[2] & 0xf4) != 0x80) {
245 l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
246 return;
247 }
248 pc->para.bchannel = p[2] & 0x3;
249 } else {
250 l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
251 return;
252 }
253 dev_kfree_skb(skb);
254 L3AddTimer(&pc->timer, T304, CC_T304);
255 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
256}
257
258static void
259l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
260{
261 u_char *p;
262 struct sk_buff *skb = arg;
263
264 L3DelTimer(&pc->timer);
265 p = skb->data;
266 if ((p = findie(p, skb->len, WE0_chanID, 0))) {
267 if (p[1] != 1) {
268 l3_1tr6_error(pc, "call sent wrong chanID len", skb);
269 return;
270 }
271 if ((p[2] & 0xf4) != 0x80) {
272 l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
273 return;
274 }
275 if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
276 l3_1tr6_error(pc, "call sent wrong chanID value", skb);
277 return;
278 }
279 pc->para.bchannel = p[2] & 0x3;
280 } else {
281 l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
282 return;
283 }
284 dev_kfree_skb(skb);
285 L3AddTimer(&pc->timer, T310, CC_T310);
286 newl3state(pc, 3);
287 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
288}
289
290static void
291l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
292{
293 struct sk_buff *skb = arg;
294
295 dev_kfree_skb(skb);
296 L3DelTimer(&pc->timer); /* T304 */
297 newl3state(pc, 4);
298 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
299}
300
301static void
302l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
303{
304 u_char *p;
305 int i, tmpcharge = 0;
306 char a_charge[8], tmp[32];
307 struct sk_buff *skb = arg;
308
309 p = skb->data;
310 if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
311 iecpy(a_charge, p, 1);
312 for (i = 0; i < strlen(a_charge); i++) {
313 tmpcharge *= 10;
314 tmpcharge += a_charge[i] & 0xf;
315 }
316 if (tmpcharge > pc->para.chargeinfo) {
317 pc->para.chargeinfo = tmpcharge;
318 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
319 }
320 if (pc->st->l3.debug & L3_DEB_CHARGE) {
321 sprintf(tmp, "charging info %d", pc->para.chargeinfo);
322 l3_debug(pc->st, tmp);
323 }
324 } else if (pc->st->l3.debug & L3_DEB_CHARGE)
325 l3_debug(pc->st, "charging info not found");
326 dev_kfree_skb(skb);
327
328}
329
330static void
331l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg)
332{
333 struct sk_buff *skb = arg;
334
335 dev_kfree_skb(skb);
336}
337
338static void
339l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
340{
341 struct sk_buff *skb = arg;
342
343 L3DelTimer(&pc->timer); /* T310 */
344 if (!findie(skb->data, skb->len, WE6_date, 6)) {
345 l3_1tr6_error(pc, "missing connect date", skb);
346 return;
347 }
348 newl3state(pc, 10);
349 dev_kfree_skb(skb);
350 pc->para.chargeinfo = 0;
351 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
352}
353
354static void
355l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
356{
357 struct sk_buff *skb = arg;
358 u_char *p;
359
360 p = skb->data;
361 if ((p = findie(p, skb->len, WE0_cause, 0))) {
362 if (p[1] > 0) {
363 pc->para.cause = p[2];
364 if (p[1] > 1)
365 pc->para.loc = p[3];
366 else
367 pc->para.loc = 0;
368 } else {
369 pc->para.cause = 0;
370 pc->para.loc = 0;
371 }
372 } else {
373 pc->para.cause = NO_CAUSE;
374 l3_1tr6_error(pc, "missing REL cause", skb);
375 return;
376 }
377 dev_kfree_skb(skb);
378 StopAllL3Timer(pc);
379 newl3state(pc, 0);
380 l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
381 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
382 release_l3_process(pc);
383}
384
385static void
386l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
387{
388 struct sk_buff *skb = arg;
389
390 dev_kfree_skb(skb);
391 StopAllL3Timer(pc);
392 newl3state(pc, 0);
393 pc->para.cause = NO_CAUSE;
394 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
395 release_l3_process(pc);
396}
397
398static void
399l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
400{
401 struct sk_buff *skb = arg;
402 u_char *p;
403 int i, tmpcharge = 0;
404 char a_charge[8], tmp[32];
405
406 StopAllL3Timer(pc);
407 p = skb->data;
408 if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
409 iecpy(a_charge, p, 1);
410 for (i = 0; i < strlen(a_charge); i++) {
411 tmpcharge *= 10;
412 tmpcharge += a_charge[i] & 0xf;
413 }
414 if (tmpcharge > pc->para.chargeinfo) {
415 pc->para.chargeinfo = tmpcharge;
416 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
417 }
418 if (pc->st->l3.debug & L3_DEB_CHARGE) {
419 sprintf(tmp, "charging info %d", pc->para.chargeinfo);
420 l3_debug(pc->st, tmp);
421 }
422 } else if (pc->st->l3.debug & L3_DEB_CHARGE)
423 l3_debug(pc->st, "charging info not found");
424
425
426 p = skb->data;
427 if ((p = findie(p, skb->len, WE0_cause, 0))) {
428 if (p[1] > 0) {
429 pc->para.cause = p[2];
430 if (p[1] > 1)
431 pc->para.loc = p[3];
432 else
433 pc->para.loc = 0;
434 } else {
435 pc->para.cause = 0;
436 pc->para.loc = 0;
437 }
438 } else {
439 if (pc->st->l3.debug & L3_DEB_WARN)
440 l3_debug(pc->st, "cause not found");
441 pc->para.cause = NO_CAUSE;
442 }
443 if (!findie(skb->data, skb->len, WE6_date, 6)) {
444 l3_1tr6_error(pc, "missing connack date", skb);
445 return;
446 }
447 dev_kfree_skb(skb);
448 newl3state(pc, 12);
449 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
450}
451
452
453static void
454l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
455{
456 struct sk_buff *skb = arg;
457
458 if (!findie(skb->data, skb->len, WE6_date, 6)) {
459 l3_1tr6_error(pc, "missing connack date", skb);
460 return;
461 }
462 dev_kfree_skb(skb);
463 newl3state(pc, 10);
464 pc->para.chargeinfo = 0;
465 L3DelTimer(&pc->timer);
466 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
467}
468
469static void
470l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg)
471{
472 newl3state(pc, 7);
473 l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1);
474}
475
476static void
477l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg)
478{
479 struct sk_buff *skb;
480 u_char tmp[24];
481 u_char *p = tmp;
482 int l;
483
484 MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1);
485 if (pc->para.spv) { /* SPV ? */
486 /* NSF SPV */
487 *p++ = WE0_netSpecFac;
488 *p++ = 4; /* Laenge */
489 *p++ = 0;
490 *p++ = FAC_SPV; /* SPV */
491 *p++ = pc->para.setup.si1;
492 *p++ = pc->para.setup.si2;
493 *p++ = WE0_netSpecFac;
494 *p++ = 4; /* Laenge */
495 *p++ = 0;
496 *p++ = FAC_Activate; /* aktiviere SPV */
497 *p++ = pc->para.setup.si1;
498 *p++ = pc->para.setup.si2;
499 }
500 newl3state(pc, 8);
501 l = p - tmp;
502 if (!(skb = l3_alloc_skb(l)))
503 return;
504 memcpy(skb_put(skb, l), tmp, l);
505 l3_msg(pc->st, DL_DATA | REQUEST, skb);
506 L3DelTimer(&pc->timer);
507 L3AddTimer(&pc->timer, T313, CC_T313);
508}
509
510static void
511l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg)
512{
513 release_l3_process(pc);
514}
515
516static void
517l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
518{
519 struct sk_buff *skb;
520 u_char tmp[16];
521 u_char *p = tmp;
522 int l;
523 u_char cause = 0x10;
524 u_char clen = 1;
525
526 if (pc->para.cause > 0)
527 cause = pc->para.cause;
528 /* Map DSS1 causes */
529 switch (cause & 0x7f) {
530 case 0x10:
531 clen = 0;
532 break;
533 case 0x11:
534 cause = CAUSE_UserBusy;
535 break;
536 case 0x15:
537 cause = CAUSE_CallRejected;
538 break;
539 }
540 StopAllL3Timer(pc);
541 MsgHead(p, pc->callref, MT_N1_DISC, PROTO_DIS_N1);
542 *p++ = WE0_cause;
543 *p++ = clen; /* Laenge */
544 if (clen)
545 *p++ = cause | 0x80;
546 newl3state(pc, 11);
547 l = p - tmp;
548 if (!(skb = l3_alloc_skb(l)))
549 return;
550 memcpy(skb_put(skb, l), tmp, l);
551 l3_msg(pc->st, DL_DATA | REQUEST, skb);
552 L3AddTimer(&pc->timer, T305, CC_T305);
553}
554
555static void
556l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
557{
558 if (pc->N303 > 0) {
559 pc->N303--;
560 L3DelTimer(&pc->timer);
561 l3_1tr6_setup_req(pc, pr, arg);
562 } else {
563 L3DelTimer(&pc->timer);
564 pc->para.cause = 0;
565 l3_1tr6_disconnect_req(pc, 0, NULL);
566 }
567}
568
569static void
570l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg)
571{
572 L3DelTimer(&pc->timer);
573 pc->para.cause = 0xE6;
574 l3_1tr6_disconnect_req(pc, pr, NULL);
575 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
576}
577
578static void
579l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg)
580{
581 struct sk_buff *skb;
582 u_char tmp[16];
583 u_char *p = tmp;
584 int l;
585 u_char cause = 0x90;
586 u_char clen = 1;
587
588 L3DelTimer(&pc->timer);
589 if (pc->para.cause != NO_CAUSE)
590 cause = pc->para.cause;
591 /* Map DSS1 causes */
592 switch (cause & 0x7f) {
593 case 0x10:
594 clen = 0;
595 break;
596 case 0x15:
597 cause = CAUSE_CallRejected;
598 break;
599 }
600 MsgHead(p, pc->callref, MT_N1_REL, PROTO_DIS_N1);
601 *p++ = WE0_cause;
602 *p++ = clen; /* Laenge */
603 if (clen)
604 *p++ = cause;
605 newl3state(pc, 19);
606 l = p - tmp;
607 if (!(skb = l3_alloc_skb(l)))
608 return;
609 memcpy(skb_put(skb, l), tmp, l);
610 l3_msg(pc->st, DL_DATA | REQUEST, skb);
611 L3AddTimer(&pc->timer, T308, CC_T308_1);
612}
613
614static void
615l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg)
616{
617 L3DelTimer(&pc->timer);
618 pc->para.cause = 0xE6;
619 l3_1tr6_disconnect_req(pc, pr, NULL);
620 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
621}
622
623static void
624l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg)
625{
626 L3DelTimer(&pc->timer);
627 pc->para.cause = 0xE6;
628 l3_1tr6_disconnect_req(pc, pr, NULL);
629 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
630}
631
632static void
633l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg)
634{
635 L3DelTimer(&pc->timer);
636 l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
637 L3AddTimer(&pc->timer, T308, CC_T308_2);
638 newl3state(pc, 19);
639}
640
641static void
642l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
643{
644 L3DelTimer(&pc->timer);
645 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
646 release_l3_process(pc);
647}
648
649static void
650l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
651{
652 pc->para.cause = CAUSE_LocalProcErr;
653 l3_1tr6_disconnect_req(pc, pr, NULL);
654 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
655}
656
657static void
658l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
659{
660 newl3state(pc, 0);
661 pc->para.cause = 0x1b; /* Destination out of order */
662 pc->para.loc = 0;
663 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
664 release_l3_process(pc);
665}
666
667/* *INDENT-OFF* */
668static struct stateentry downstl[] =
669{
670 {SBIT(0),
671 CC_SETUP | REQUEST, l3_1tr6_setup_req},
672 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
673 SBIT(10),
674 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
675 {SBIT(12),
676 CC_RELEASE | REQUEST, l3_1tr6_release_req},
677 {SBIT(6),
678 CC_IGNORE | REQUEST, l3_1tr6_reset},
679 {SBIT(6),
680 CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
681 {SBIT(6),
682 CC_ALERTING | REQUEST, l3_1tr6_alert_req},
683 {SBIT(6) | SBIT(7),
684 CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
685 {SBIT(1),
686 CC_T303, l3_1tr6_t303},
687 {SBIT(2),
688 CC_T304, l3_1tr6_t304},
689 {SBIT(3),
690 CC_T310, l3_1tr6_t310},
691 {SBIT(8),
692 CC_T313, l3_1tr6_t313},
693 {SBIT(11),
694 CC_T305, l3_1tr6_t305},
695 {SBIT(19),
696 CC_T308_1, l3_1tr6_t308_1},
697 {SBIT(19),
698 CC_T308_2, l3_1tr6_t308_2},
699};
700
701#define DOWNSTL_LEN \
702 (sizeof(downstl) / sizeof(struct stateentry))
703
704static struct stateentry datastln1[] =
705{
706 {SBIT(0),
707 MT_N1_INVALID, l3_1tr6_invalid},
708 {SBIT(0),
709 MT_N1_SETUP, l3_1tr6_setup},
710 {SBIT(1),
711 MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
712 {SBIT(1) | SBIT(2),
713 MT_N1_CALL_SENT, l3_1tr6_call_sent},
714 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10),
715 MT_N1_DISC, l3_1tr6_disc},
716 {SBIT(2) | SBIT(3) | SBIT(4),
717 MT_N1_ALERT, l3_1tr6_alert},
718 {SBIT(2) | SBIT(3) | SBIT(4),
719 MT_N1_CONN, l3_1tr6_connect},
720 {SBIT(2),
721 MT_N1_INFO, l3_1tr6_info_s2},
722 {SBIT(8),
723 MT_N1_CONN_ACK, l3_1tr6_connect_ack},
724 {SBIT(10),
725 MT_N1_INFO, l3_1tr6_info},
726 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
727 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
728 MT_N1_REL, l3_1tr6_rel},
729 {SBIT(19),
730 MT_N1_REL, l3_1tr6_rel_ack},
731 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
732 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
733 MT_N1_REL_ACK, l3_1tr6_invalid},
734 {SBIT(19),
735 MT_N1_REL_ACK, l3_1tr6_rel_ack}
736};
737
738#define DATASTLN1_LEN \
739 (sizeof(datastln1) / sizeof(struct stateentry))
740
741static struct stateentry manstatelist[] =
742{
743 {SBIT(2),
744 DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset},
745 {ALL_STATES,
746 DL_RELEASE | INDICATION, l3_1tr6_dl_release},
747};
748
749#define MANSLLEN \
750 (sizeof(manstatelist) / sizeof(struct stateentry))
751/* *INDENT-ON* */
752
753static void
754up1tr6(struct PStack *st, int pr, void *arg)
755{
756 int i, mt, cr;
757 struct l3_process *proc;
758 struct sk_buff *skb = arg;
759 char tmp[80];
760
761 switch (pr) {
762 case (DL_DATA | INDICATION):
763 case (DL_UNIT_DATA | INDICATION):
764 break;
765 case (DL_ESTABLISH | CONFIRM):
766 case (DL_ESTABLISH | INDICATION):
767 case (DL_RELEASE | INDICATION):
768 case (DL_RELEASE | CONFIRM):
769 l3_msg(st, pr, arg);
770 return;
771 break;
772 }
773 if (skb->len < 4) {
774 if (st->l3.debug & L3_DEB_PROTERR) {
775 sprintf(tmp, "up1tr6 len only %d", skb->len);
776 l3_debug(st, tmp);
777 }
778 dev_kfree_skb(skb);
779 return;
780 }
781 if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
782 if (st->l3.debug & L3_DEB_PROTERR) {
783 sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
784 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
785 skb->data[0], skb->len);
786 l3_debug(st, tmp);
787 }
788 dev_kfree_skb(skb);
789 return;
790 }
791 if (skb->data[1] != 1) {
792 if (st->l3.debug & L3_DEB_PROTERR) {
793 sprintf(tmp, "up1tr6 CR len not 1");
794 l3_debug(st, tmp);
795 }
796 dev_kfree_skb(skb);
797 return;
798 }
799 cr = skb->data[2];
800 mt = skb->data[3];
801 if (skb->data[0] == PROTO_DIS_N0) {
802 dev_kfree_skb(skb);
803 if (st->l3.debug & L3_DEB_STATE) {
804 sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
805 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
806 l3_debug(st, tmp);
807 }
808 } else if (skb->data[0] == PROTO_DIS_N1) {
809 if (!(proc = getl3proc(st, cr))) {
810 if (mt == MT_N1_SETUP) {
811 if (cr < 128) {
812 if (!(proc = new_l3_process(st, cr))) {
813 if (st->l3.debug & L3_DEB_PROTERR) {
814 sprintf(tmp, "up1tr6 no roc mem");
815 l3_debug(st, tmp);
816 }
817 dev_kfree_skb(skb);
818 return;
819 }
820 } else {
821 dev_kfree_skb(skb);
822 return;
823 }
824 } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
825 (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
826 (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
827 (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
828 (mt == MT_N1_INFO)) {
829 dev_kfree_skb(skb);
830 return;
831 } else {
832 if (!(proc = new_l3_process(st, cr))) {
833 if (st->l3.debug & L3_DEB_PROTERR) {
834 sprintf(tmp, "up1tr6 no roc mem");
835 l3_debug(st, tmp);
836 }
837 dev_kfree_skb(skb);
838 return;
839 }
840 mt = MT_N1_INVALID;
841 }
842 }
843 for (i = 0; i < DATASTLN1_LEN; i++)
844 if ((mt == datastln1[i].primitive) &&
845 ((1 << proc->state) & datastln1[i].state))
846 break;
847 if (i == DATASTLN1_LEN) {
848 dev_kfree_skb(skb);
849 if (st->l3.debug & L3_DEB_STATE) {
850 sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
851 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
852 proc->state, mt);
853 l3_debug(st, tmp);
854 }
855 return;
856 } else {
857 if (st->l3.debug & L3_DEB_STATE) {
858 sprintf(tmp, "up1tr6%sstate %d mt %x",
859 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
860 proc->state, mt);
861 l3_debug(st, tmp);
862 }
863 datastln1[i].rout(proc, pr, skb);
864 }
865 }
866}
867
868static void
869down1tr6(struct PStack *st, int pr, void *arg)
870{
871 int i, cr;
872 struct l3_process *proc;
873 struct Channel *chan;
874 char tmp[80];
875
876 if ((DL_ESTABLISH | REQUEST)== pr) {
877 l3_msg(st, pr, NULL);
878 return;
879 } else if ((CC_SETUP | REQUEST) == pr) {
880 chan = arg;
881 cr = newcallref();
882 cr |= 0x80;
883 if (!(proc = new_l3_process(st, cr))) {
884 return;
885 } else {
886 proc->chan = chan;
887 chan->proc = proc;
888 memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
889 proc->callref = cr;
890 }
891 } else {
892 proc = arg;
893 }
894
895 for (i = 0; i < DOWNSTL_LEN; i++)
896 if ((pr == downstl[i].primitive) &&
897 ((1 << proc->state) & downstl[i].state))
898 break;
899 if (i == DOWNSTL_LEN) {
900 if (st->l3.debug & L3_DEB_STATE) {
901 sprintf(tmp, "down1tr6 state %d prim %d unhandled",
902 proc->state, pr);
903 l3_debug(st, tmp);
904 }
905 } else {
906 if (st->l3.debug & L3_DEB_STATE) {
907 sprintf(tmp, "down1tr6 state %d prim %d",
908 proc->state, pr);
909 l3_debug(st, tmp);
910 }
911 downstl[i].rout(proc, pr, arg);
912 }
913}
914
915static void
916man1tr6(struct PStack *st, int pr, void *arg)
917{
918 int i;
919 struct l3_process *proc = arg;
920
921 if (!proc) {
922 printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
923 return;
924 }
925 for (i = 0; i < MANSLLEN; i++)
926 if ((pr == manstatelist[i].primitive) &&
927 ((1 << proc->state) & manstatelist[i].state))
928 break;
929 if (i == MANSLLEN) {
930 if (st->l3.debug & L3_DEB_STATE) {
931 l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
932 proc->callref & 0x7f, proc->state, pr);
933 }
934 } else {
935 if (st->l3.debug & L3_DEB_STATE) {
936 l3_debug(st, "cr %d man1tr6 state %d prim %d",
937 proc->callref & 0x7f, proc->state, pr);
938 }
939 manstatelist[i].rout(proc, pr, arg);
940 }
941}
942
943void
944setstack_1tr6(struct PStack *st)
945{
946 char tmp[64];
947
948 st->lli.l4l3 = down1tr6;
949 st->l2.l2l3 = up1tr6;
950 st->l3.l3ml3 = man1tr6;
951 st->l3.N303 = 0;
952
953 strcpy(tmp, l3_1tr6_revision);
954 printk(KERN_INFO "HiSax: 1TR6 Rev. %s\n", HiSax_getrev(tmp));
955}
diff --git a/drivers/isdn/hisax/l3_1tr6.h b/drivers/isdn/hisax/l3_1tr6.h
new file mode 100644
index 00000000000..43215c00cad
--- /dev/null
+++ b/drivers/isdn/hisax/l3_1tr6.h
@@ -0,0 +1,164 @@
1/* $Id: l3_1tr6.h,v 2.2.6.2 2001/09/23 22:24:49 kai Exp $
2 *
3 * German 1TR6 D-channel protocol defines
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#ifndef l3_1tr6
11#define l3_1tr6
12
13#define PROTO_DIS_N0 0x40
14#define PROTO_DIS_N1 0x41
15
16/*
17 * MsgType N0
18 */
19#define MT_N0_REG_IND 0x61
20#define MT_N0_CANC_IND 0x62
21#define MT_N0_FAC_STA 0x63
22#define MT_N0_STA_ACK 0x64
23#define MT_N0_STA_REJ 0x65
24#define MT_N0_FAC_INF 0x66
25#define MT_N0_INF_ACK 0x67
26#define MT_N0_INF_REJ 0x68
27#define MT_N0_CLOSE 0x75
28#define MT_N0_CLO_ACK 0x77
29
30/*
31 * MsgType N1
32 */
33
34#define MT_N1_ESC 0x00
35#define MT_N1_ALERT 0x01
36#define MT_N1_CALL_SENT 0x02
37#define MT_N1_CONN 0x07
38#define MT_N1_CONN_ACK 0x0F
39#define MT_N1_SETUP 0x05
40#define MT_N1_SETUP_ACK 0x0D
41#define MT_N1_RES 0x26
42#define MT_N1_RES_ACK 0x2E
43#define MT_N1_RES_REJ 0x22
44#define MT_N1_SUSP 0x25
45#define MT_N1_SUSP_ACK 0x2D
46#define MT_N1_SUSP_REJ 0x21
47#define MT_N1_USER_INFO 0x20
48#define MT_N1_DET 0x40
49#define MT_N1_DISC 0x45
50#define MT_N1_REL 0x4D
51#define MT_N1_REL_ACK 0x5A
52#define MT_N1_CANC_ACK 0x6E
53#define MT_N1_CANC_REJ 0x67
54#define MT_N1_CON_CON 0x69
55#define MT_N1_FAC 0x60
56#define MT_N1_FAC_ACK 0x68
57#define MT_N1_FAC_CAN 0x66
58#define MT_N1_FAC_REG 0x64
59#define MT_N1_FAC_REJ 0x65
60#define MT_N1_INFO 0x6D
61#define MT_N1_REG_ACK 0x6C
62#define MT_N1_REG_REJ 0x6F
63#define MT_N1_STAT 0x63
64#define MT_N1_INVALID 0
65
66/*
67 * W Elemente
68 */
69
70#define WE_Shift_F0 0x90
71#define WE_Shift_F6 0x96
72#define WE_Shift_OF0 0x98
73#define WE_Shift_OF6 0x9E
74
75#define WE0_cause 0x08
76#define WE0_connAddr 0x0C
77#define WE0_callID 0x10
78#define WE0_chanID 0x18
79#define WE0_netSpecFac 0x20
80#define WE0_display 0x28
81#define WE0_keypad 0x2C
82#define WE0_origAddr 0x6C
83#define WE0_destAddr 0x70
84#define WE0_userInfo 0x7E
85
86#define WE0_moreData 0xA0
87#define WE0_congestLevel 0xB0
88
89#define WE6_serviceInd 0x01
90#define WE6_chargingInfo 0x02
91#define WE6_date 0x03
92#define WE6_facSelect 0x05
93#define WE6_facStatus 0x06
94#define WE6_statusCalled 0x07
95#define WE6_addTransAttr 0x08
96
97/*
98 * FacCodes
99 */
100#define FAC_Sperre 0x01
101#define FAC_Sperre_All 0x02
102#define FAC_Sperre_Fern 0x03
103#define FAC_Sperre_Intl 0x04
104#define FAC_Sperre_Interk 0x05
105
106#define FAC_Forward1 0x02
107#define FAC_Forward2 0x03
108#define FAC_Konferenz 0x06
109#define FAC_GrabBchan 0x0F
110#define FAC_Reactivate 0x10
111#define FAC_Konferenz3 0x11
112#define FAC_Dienstwechsel1 0x12
113#define FAC_Dienstwechsel2 0x13
114#define FAC_NummernIdent 0x14
115#define FAC_GBG 0x15
116#define FAC_DisplayUebergeben 0x17
117#define FAC_DisplayUmgeleitet 0x1A
118#define FAC_Unterdruecke 0x1B
119#define FAC_Deactivate 0x1E
120#define FAC_Activate 0x1D
121#define FAC_SPV 0x1F
122#define FAC_Rueckwechsel 0x23
123#define FAC_Umleitung 0x24
124
125/*
126 * Cause codes
127 */
128#define CAUSE_InvCRef 0x01
129#define CAUSE_BearerNotImpl 0x03
130#define CAUSE_CIDunknown 0x07
131#define CAUSE_CIDinUse 0x08
132#define CAUSE_NoChans 0x0A
133#define CAUSE_FacNotImpl 0x10
134#define CAUSE_FacNotSubscr 0x11
135#define CAUSE_OutgoingBarred 0x20
136#define CAUSE_UserAccessBusy 0x21
137#define CAUSE_NegativeGBG 0x22
138#define CAUSE_UnknownGBG 0x23
139#define CAUSE_NoSPVknown 0x25
140#define CAUSE_DestNotObtain 0x35
141#define CAUSE_NumberChanged 0x38
142#define CAUSE_OutOfOrder 0x39
143#define CAUSE_NoUserResponse 0x3A
144#define CAUSE_UserBusy 0x3B
145#define CAUSE_IncomingBarred 0x3D
146#define CAUSE_CallRejected 0x3E
147#define CAUSE_NetworkCongestion 0x59
148#define CAUSE_RemoteUser 0x5A
149#define CAUSE_LocalProcErr 0x70
150#define CAUSE_RemoteProcErr 0x71
151#define CAUSE_RemoteUserSuspend 0x72
152#define CAUSE_RemoteUserResumed 0x73
153#define CAUSE_UserInfoDiscarded 0x7F
154
155#define T303 4000
156#define T304 20000
157#define T305 4000
158#define T308 4000
159#define T310 120000
160#define T313 4000
161#define T318 4000
162#define T319 4000
163
164#endif
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
new file mode 100644
index 00000000000..ec92308c1ef
--- /dev/null
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -0,0 +1,3238 @@
1/* $Id: l3dss1.c,v 2.32.2.3 2004/01/13 14:31:25 keil Exp $
2 *
3 * EURO/DSS1 D-channel protocol
4 *
5 * German 1TR6 D-channel protocol
6 *
7 * Author Karsten Keil
8 * based on the teles driver from Jan den Ouden
9 * Copyright by Karsten Keil <keil@isdn4linux.de>
10 *
11 * This software may be used and distributed according to the terms
12 * of the GNU General Public License, incorporated herein by reference.
13 *
14 * For changes and modifications please read
15 * Documentation/isdn/HiSax.cert
16 *
17 * Thanks to Jan den Ouden
18 * Fritz Elfert
19 *
20 */
21
22#include "hisax.h"
23#include "isdnl3.h"
24#include "l3dss1.h"
25#include <linux/ctype.h>
26#include <linux/config.h>
27
28extern char *HiSax_getrev(const char *revision);
29const char *dss1_revision = "$Revision: 2.32.2.3 $";
30
31#define EXT_BEARER_CAPS 1
32
33#define MsgHead(ptr, cref, mty) \
34 *ptr++ = 0x8; \
35 if (cref == -1) { \
36 *ptr++ = 0x0; \
37 } else { \
38 *ptr++ = 0x1; \
39 *ptr++ = cref^0x80; \
40 } \
41 *ptr++ = mty
42
43
44/**********************************************/
45/* get a new invoke id for remote operations. */
46/* Only a return value != 0 is valid */
47/**********************************************/
48static unsigned char new_invoke_id(struct PStack *p)
49{
50 unsigned char retval;
51 int i;
52
53 i = 32; /* maximum search depth */
54
55 retval = p->prot.dss1.last_invoke_id + 1; /* try new id */
56 while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {
57 p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;
58 i--;
59 }
60 if (i) {
61 while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7)))
62 retval++;
63 } else
64 retval = 0;
65 p->prot.dss1.last_invoke_id = retval;
66 p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));
67 return(retval);
68} /* new_invoke_id */
69
70/*************************/
71/* free a used invoke id */
72/*************************/
73static void free_invoke_id(struct PStack *p, unsigned char id)
74{
75
76 if (!id) return; /* 0 = invalid value */
77
78 p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));
79} /* free_invoke_id */
80
81
82/**********************************************************/
83/* create a new l3 process and fill in dss1 specific data */
84/**********************************************************/
85static struct l3_process
86*dss1_new_l3_process(struct PStack *st, int cr)
87{ struct l3_process *proc;
88
89 if (!(proc = new_l3_process(st, cr)))
90 return(NULL);
91
92 proc->prot.dss1.invoke_id = 0;
93 proc->prot.dss1.remote_operation = 0;
94 proc->prot.dss1.uus1_data[0] = '\0';
95
96 return(proc);
97} /* dss1_new_l3_process */
98
99/************************************************/
100/* free a l3 process and all dss1 specific data */
101/************************************************/
102static void
103dss1_release_l3_process(struct l3_process *p)
104{
105 free_invoke_id(p->st,p->prot.dss1.invoke_id);
106 release_l3_process(p);
107} /* dss1_release_l3_process */
108
109/********************************************************/
110/* search a process with invoke id id and dummy callref */
111/********************************************************/
112static struct l3_process *
113l3dss1_search_dummy_proc(struct PStack *st, int id)
114{ struct l3_process *pc = st->l3.proc; /* start of processes */
115
116 if (!id) return(NULL);
117
118 while (pc)
119 { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id))
120 return(pc);
121 pc = pc->next;
122 }
123 return(NULL);
124} /* l3dss1_search_dummy_proc */
125
126/*******************************************************************/
127/* called when a facility message with a dummy callref is received */
128/* and a return result is delivered. id specifies the invoke id. */
129/*******************************************************************/
130static void
131l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
132{ isdn_ctrl ic;
133 struct IsdnCardState *cs;
134 struct l3_process *pc = NULL;
135
136 if ((pc = l3dss1_search_dummy_proc(st, id)))
137 { L3DelTimer(&pc->timer); /* remove timer */
138
139 cs = pc->st->l1.hardware;
140 ic.driver = cs->myid;
141 ic.command = ISDN_STAT_PROT;
142 ic.arg = DSS1_STAT_INVOKE_RES;
143 ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
144 ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
145 ic.parm.dss1_io.proc = pc->prot.dss1.proc;
146 ic.parm.dss1_io.timeout= 0;
147 ic.parm.dss1_io.datalen = nlen;
148 ic.parm.dss1_io.data = p;
149 free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
150 pc->prot.dss1.invoke_id = 0; /* reset id */
151
152 cs->iif.statcallb(&ic);
153 dss1_release_l3_process(pc);
154 }
155 else
156 l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
157} /* l3dss1_dummy_return_result */
158
159/*******************************************************************/
160/* called when a facility message with a dummy callref is received */
161/* and a return error is delivered. id specifies the invoke id. */
162/*******************************************************************/
163static void
164l3dss1_dummy_error_return(struct PStack *st, int id, ulong error)
165{ isdn_ctrl ic;
166 struct IsdnCardState *cs;
167 struct l3_process *pc = NULL;
168
169 if ((pc = l3dss1_search_dummy_proc(st, id)))
170 { L3DelTimer(&pc->timer); /* remove timer */
171
172 cs = pc->st->l1.hardware;
173 ic.driver = cs->myid;
174 ic.command = ISDN_STAT_PROT;
175 ic.arg = DSS1_STAT_INVOKE_ERR;
176 ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
177 ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
178 ic.parm.dss1_io.proc = pc->prot.dss1.proc;
179 ic.parm.dss1_io.timeout= error;
180 ic.parm.dss1_io.datalen = 0;
181 ic.parm.dss1_io.data = NULL;
182 free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
183 pc->prot.dss1.invoke_id = 0; /* reset id */
184
185 cs->iif.statcallb(&ic);
186 dss1_release_l3_process(pc);
187 }
188 else
189 l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
190} /* l3dss1_error_return */
191
192/*******************************************************************/
193/* called when a facility message with a dummy callref is received */
194/* and a invoke is delivered. id specifies the invoke id. */
195/*******************************************************************/
196static void
197l3dss1_dummy_invoke(struct PStack *st, int cr, int id,
198 int ident, u_char *p, u_char nlen)
199{ isdn_ctrl ic;
200 struct IsdnCardState *cs;
201
202 l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
203 (cr == -1) ? "local" : "broadcast",id,ident,nlen);
204 if (cr >= -1) return; /* ignore local data */
205
206 cs = st->l1.hardware;
207 ic.driver = cs->myid;
208 ic.command = ISDN_STAT_PROT;
209 ic.arg = DSS1_STAT_INVOKE_BRD;
210 ic.parm.dss1_io.hl_id = id;
211 ic.parm.dss1_io.ll_id = 0;
212 ic.parm.dss1_io.proc = ident;
213 ic.parm.dss1_io.timeout= 0;
214 ic.parm.dss1_io.datalen = nlen;
215 ic.parm.dss1_io.data = p;
216
217 cs->iif.statcallb(&ic);
218} /* l3dss1_dummy_invoke */
219
220static void
221l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
222 int cr, u_char * p)
223{
224 int qd_len = 0;
225 unsigned char nlen = 0, ilen, cp_tag;
226 int ident, id;
227 ulong err_ret;
228
229 if (pc)
230 st = pc->st; /* valid Stack */
231 else
232 if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
233
234 p++;
235 qd_len = *p++;
236 if (qd_len == 0) {
237 l3_debug(st, "qd_len == 0");
238 return;
239 }
240 if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
241 l3_debug(st, "supplementary service != 0x11");
242 return;
243 }
244 while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */
245 p++;
246 qd_len--;
247 }
248 if (qd_len < 2) {
249 l3_debug(st, "qd_len < 2");
250 return;
251 }
252 p++;
253 qd_len--;
254 if ((*p & 0xE0) != 0xA0) { /* class and form */
255 l3_debug(st, "class and form != 0xA0");
256 return;
257 }
258
259 cp_tag = *p & 0x1F; /* remember tag value */
260
261 p++;
262 qd_len--;
263 if (qd_len < 1)
264 { l3_debug(st, "qd_len < 1");
265 return;
266 }
267 if (*p & 0x80)
268 { /* length format indefinite or limited */
269 nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
270 if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
271 (nlen > 1))
272 { l3_debug(st, "length format error or not implemented");
273 return;
274 }
275 if (nlen == 1)
276 { nlen = *p++; /* complete length */
277 qd_len--;
278 }
279 else
280 { qd_len -= 2; /* trailing null bytes */
281 if ((*(p+qd_len)) || (*(p+qd_len+1)))
282 { l3_debug(st,"length format indefinite error");
283 return;
284 }
285 nlen = qd_len;
286 }
287 }
288 else
289 { nlen = *p++;
290 qd_len--;
291 }
292 if (qd_len < nlen)
293 { l3_debug(st, "qd_len < nlen");
294 return;
295 }
296 qd_len -= nlen;
297
298 if (nlen < 2)
299 { l3_debug(st, "nlen < 2");
300 return;
301 }
302 if (*p != 0x02)
303 { /* invoke identifier tag */
304 l3_debug(st, "invoke identifier tag !=0x02");
305 return;
306 }
307 p++;
308 nlen--;
309 if (*p & 0x80)
310 { /* length format */
311 l3_debug(st, "invoke id length format 2");
312 return;
313 }
314 ilen = *p++;
315 nlen--;
316 if (ilen > nlen || ilen == 0)
317 { l3_debug(st, "ilen > nlen || ilen == 0");
318 return;
319 }
320 nlen -= ilen;
321 id = 0;
322 while (ilen > 0)
323 { id = (id << 8) | (*p++ & 0xFF); /* invoke identifier */
324 ilen--;
325 }
326
327 switch (cp_tag) { /* component tag */
328 case 1: /* invoke */
329 if (nlen < 2) {
330 l3_debug(st, "nlen < 2 22");
331 return;
332 }
333 if (*p != 0x02) { /* operation value */
334 l3_debug(st, "operation value !=0x02");
335 return;
336 }
337 p++;
338 nlen--;
339 ilen = *p++;
340 nlen--;
341 if (ilen > nlen || ilen == 0) {
342 l3_debug(st, "ilen > nlen || ilen == 0 22");
343 return;
344 }
345 nlen -= ilen;
346 ident = 0;
347 while (ilen > 0) {
348 ident = (ident << 8) | (*p++ & 0xFF);
349 ilen--;
350 }
351
352 if (!pc)
353 { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
354 return;
355 }
356#if HISAX_DE_AOC
357 {
358
359#define FOO1(s,a,b) \
360 while(nlen > 1) { \
361 int ilen = p[1]; \
362 if(nlen < ilen+2) { \
363 l3_debug(st, "FOO1 nlen < ilen+2"); \
364 return; \
365 } \
366 nlen -= ilen+2; \
367 if((*p & 0xFF) == (a)) { \
368 int nlen = ilen; \
369 p += 2; \
370 b; \
371 } else { \
372 p += ilen+2; \
373 } \
374 }
375
376 switch (ident) {
377 case 0x22: /* during */
378 FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
379 ident = 0;
380 nlen = (nlen)?nlen:0; /* Make gcc happy */
381 while (ilen > 0) {
382 ident = (ident << 8) | *p++;
383 ilen--;
384 }
385 if (ident > pc->para.chargeinfo) {
386 pc->para.chargeinfo = ident;
387 st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
388 }
389 if (st->l3.debug & L3_DEB_CHARGE) {
390 if (*(p + 2) == 0) {
391 l3_debug(st, "charging info during %d", pc->para.chargeinfo);
392 }
393 else {
394 l3_debug(st, "charging info final %d", pc->para.chargeinfo);
395 }
396 }
397 }
398 )))))
399 break;
400 case 0x24: /* final */
401 FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
402 ident = 0;
403 nlen = (nlen)?nlen:0; /* Make gcc happy */
404 while (ilen > 0) {
405 ident = (ident << 8) | *p++;
406 ilen--;
407 }
408 if (ident > pc->para.chargeinfo) {
409 pc->para.chargeinfo = ident;
410 st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
411 }
412 if (st->l3.debug & L3_DEB_CHARGE) {
413 l3_debug(st, "charging info final %d", pc->para.chargeinfo);
414 }
415 }
416 ))))))
417 break;
418 default:
419 l3_debug(st, "invoke break invalid ident %02x",ident);
420 break;
421 }
422#undef FOO1
423
424 }
425#else /* not HISAX_DE_AOC */
426 l3_debug(st, "invoke break");
427#endif /* not HISAX_DE_AOC */
428 break;
429 case 2: /* return result */
430 /* if no process available handle separately */
431 if (!pc)
432 { if (cr == -1)
433 l3dss1_dummy_return_result(st, id, p, nlen);
434 return;
435 }
436 if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
437 { /* Diversion successful */
438 free_invoke_id(st,pc->prot.dss1.invoke_id);
439 pc->prot.dss1.remote_result = 0; /* success */
440 pc->prot.dss1.invoke_id = 0;
441 pc->redir_result = pc->prot.dss1.remote_result;
442 st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */
443 else
444 l3_debug(st,"return error unknown identifier");
445 break;
446 case 3: /* return error */
447 err_ret = 0;
448 if (nlen < 2)
449 { l3_debug(st, "return error nlen < 2");
450 return;
451 }
452 if (*p != 0x02)
453 { /* result tag */
454 l3_debug(st, "invoke error tag !=0x02");
455 return;
456 }
457 p++;
458 nlen--;
459 if (*p > 4)
460 { /* length format */
461 l3_debug(st, "invoke return errlen > 4 ");
462 return;
463 }
464 ilen = *p++;
465 nlen--;
466 if (ilen > nlen || ilen == 0)
467 { l3_debug(st, "error return ilen > nlen || ilen == 0");
468 return;
469 }
470 nlen -= ilen;
471 while (ilen > 0)
472 { err_ret = (err_ret << 8) | (*p++ & 0xFF); /* error value */
473 ilen--;
474 }
475 /* if no process available handle separately */
476 if (!pc)
477 { if (cr == -1)
478 l3dss1_dummy_error_return(st, id, err_ret);
479 return;
480 }
481 if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
482 { /* Deflection error */
483 free_invoke_id(st,pc->prot.dss1.invoke_id);
484 pc->prot.dss1.remote_result = err_ret; /* result */
485 pc->prot.dss1.invoke_id = 0;
486 pc->redir_result = pc->prot.dss1.remote_result;
487 st->l3.l3l4(st, CC_REDIR | INDICATION, pc);
488 } /* Deflection error */
489 else
490 l3_debug(st,"return result unknown identifier");
491 break;
492 default:
493 l3_debug(st, "facility default break tag=0x%02x",cp_tag);
494 break;
495 }
496}
497
498static void
499l3dss1_message(struct l3_process *pc, u_char mt)
500{
501 struct sk_buff *skb;
502 u_char *p;
503
504 if (!(skb = l3_alloc_skb(4)))
505 return;
506 p = skb_put(skb, 4);
507 MsgHead(p, pc->callref, mt);
508 l3_msg(pc->st, DL_DATA | REQUEST, skb);
509}
510
511static void
512l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
513{
514 struct sk_buff *skb;
515 u_char tmp[16];
516 u_char *p = tmp;
517 int l;
518
519 MsgHead(p, pc->callref, mt);
520 *p++ = IE_CAUSE;
521 *p++ = 0x2;
522 *p++ = 0x80;
523 *p++ = cause | 0x80;
524
525 l = p - tmp;
526 if (!(skb = l3_alloc_skb(l)))
527 return;
528 memcpy(skb_put(skb, l), tmp, l);
529 l3_msg(pc->st, DL_DATA | REQUEST, skb);
530}
531
532static void
533l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg)
534{
535 u_char tmp[16];
536 u_char *p = tmp;
537 int l;
538 struct sk_buff *skb;
539
540 MsgHead(p, pc->callref, MT_STATUS);
541
542 *p++ = IE_CAUSE;
543 *p++ = 0x2;
544 *p++ = 0x80;
545 *p++ = pc->para.cause | 0x80;
546
547 *p++ = IE_CALL_STATE;
548 *p++ = 0x1;
549 *p++ = pc->state & 0x3f;
550
551 l = p - tmp;
552 if (!(skb = l3_alloc_skb(l)))
553 return;
554 memcpy(skb_put(skb, l), tmp, l);
555 l3_msg(pc->st, DL_DATA | REQUEST, skb);
556}
557
558static void
559l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
560{
561 /* This routine is called if here was no SETUP made (checks in dss1up and in
562 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
563 * MT_STATUS_ENQUIRE in the NULL state is handled too
564 */
565 u_char tmp[16];
566 u_char *p = tmp;
567 int l;
568 struct sk_buff *skb;
569
570 switch (pc->para.cause) {
571 case 81: /* invalid callreference */
572 case 88: /* incomp destination */
573 case 96: /* mandory IE missing */
574 case 100: /* invalid IE contents */
575 case 101: /* incompatible Callstate */
576 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
577 *p++ = IE_CAUSE;
578 *p++ = 0x2;
579 *p++ = 0x80;
580 *p++ = pc->para.cause | 0x80;
581 break;
582 default:
583 printk(KERN_ERR "HiSax l3dss1_msg_without_setup wrong cause %d\n",
584 pc->para.cause);
585 return;
586 }
587 l = p - tmp;
588 if (!(skb = l3_alloc_skb(l)))
589 return;
590 memcpy(skb_put(skb, l), tmp, l);
591 l3_msg(pc->st, DL_DATA | REQUEST, skb);
592 dss1_release_l3_process(pc);
593}
594
595static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
596 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
597 IE_USER_USER, -1};
598static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
599 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
600static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
601 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
602 IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
603static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
604static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
605 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
606static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
607 IE_CALLED_PN, -1};
608static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
609static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
610 IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
611static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
612 IE_SIGNAL, IE_USER_USER, -1};
613/* a RELEASE_COMPLETE with errors don't require special actions
614static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
615*/
616static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
617 IE_DISPLAY, -1};
618static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
619static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY,
620 IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
621 IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
622 IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
623 IE_LLC, IE_HLC, IE_USER_USER, -1};
624static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
625 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
626static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
627 IE_MANDATORY, IE_DISPLAY, -1};
628static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
629static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
630static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
631/* not used
632 * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
633 * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
634 * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
635 * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
636 * IE_MANDATORY, -1};
637 */
638static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
639static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
640static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
641
642struct ie_len {
643 int ie;
644 int len;
645};
646
647static
648struct ie_len max_ie_len[] = {
649 {IE_SEGMENT, 4},
650 {IE_BEARER, 12},
651 {IE_CAUSE, 32},
652 {IE_CALL_ID, 10},
653 {IE_CALL_STATE, 3},
654 {IE_CHANNEL_ID, 34},
655 {IE_FACILITY, 255},
656 {IE_PROGRESS, 4},
657 {IE_NET_FAC, 255},
658 {IE_NOTIFY, 3},
659 {IE_DISPLAY, 82},
660 {IE_DATE, 8},
661 {IE_KEYPAD, 34},
662 {IE_SIGNAL, 3},
663 {IE_INFORATE, 6},
664 {IE_E2E_TDELAY, 11},
665 {IE_TDELAY_SEL, 5},
666 {IE_PACK_BINPARA, 3},
667 {IE_PACK_WINSIZE, 4},
668 {IE_PACK_SIZE, 4},
669 {IE_CUG, 7},
670 {IE_REV_CHARGE, 3},
671 {IE_CALLING_PN, 24},
672 {IE_CALLING_SUB, 23},
673 {IE_CALLED_PN, 24},
674 {IE_CALLED_SUB, 23},
675 {IE_REDIR_NR, 255},
676 {IE_TRANS_SEL, 255},
677 {IE_RESTART_IND, 3},
678 {IE_LLC, 18},
679 {IE_HLC, 5},
680 {IE_USER_USER, 131},
681 {-1,0},
682};
683
684static int
685getmax_ie_len(u_char ie) {
686 int i = 0;
687 while (max_ie_len[i].ie != -1) {
688 if (max_ie_len[i].ie == ie)
689 return(max_ie_len[i].len);
690 i++;
691 }
692 return(255);
693}
694
695static int
696ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
697 int ret = 1;
698
699 while (*checklist != -1) {
700 if ((*checklist & 0xff) == ie) {
701 if (ie & 0x80)
702 return(-ret);
703 else
704 return(ret);
705 }
706 ret++;
707 checklist++;
708 }
709 return(0);
710}
711
712static int
713check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
714{
715 int *cl = checklist;
716 u_char mt;
717 u_char *p, ie;
718 int l, newpos, oldpos;
719 int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
720 u_char codeset = 0;
721 u_char old_codeset = 0;
722 u_char codelock = 1;
723
724 p = skb->data;
725 /* skip cr */
726 p++;
727 l = (*p++) & 0xf;
728 p += l;
729 mt = *p++;
730 oldpos = 0;
731 while ((p - skb->data) < skb->len) {
732 if ((*p & 0xf0) == 0x90) { /* shift codeset */
733 old_codeset = codeset;
734 codeset = *p & 7;
735 if (*p & 0x08)
736 codelock = 0;
737 else
738 codelock = 1;
739 if (pc->debug & L3_DEB_CHECK)
740 l3_debug(pc->st, "check IE shift%scodeset %d->%d",
741 codelock ? " locking ": " ", old_codeset, codeset);
742 p++;
743 continue;
744 }
745 if (!codeset) { /* only codeset 0 */
746 if ((newpos = ie_in_set(pc, *p, cl))) {
747 if (newpos > 0) {
748 if (newpos < oldpos)
749 err_seq++;
750 else
751 oldpos = newpos;
752 }
753 } else {
754 if (ie_in_set(pc, *p, comp_required))
755 err_compr++;
756 else
757 err_ureg++;
758 }
759 }
760 ie = *p++;
761 if (ie & 0x80) {
762 l = 1;
763 } else {
764 l = *p++;
765 p += l;
766 l += 2;
767 }
768 if (!codeset && (l > getmax_ie_len(ie)))
769 err_len++;
770 if (!codelock) {
771 if (pc->debug & L3_DEB_CHECK)
772 l3_debug(pc->st, "check IE shift back codeset %d->%d",
773 codeset, old_codeset);
774 codeset = old_codeset;
775 codelock = 1;
776 }
777 }
778 if (err_compr | err_ureg | err_len | err_seq) {
779 if (pc->debug & L3_DEB_CHECK)
780 l3_debug(pc->st, "check IE MT(%x) %d/%d/%d/%d",
781 mt, err_compr, err_ureg, err_len, err_seq);
782 if (err_compr)
783 return(ERR_IE_COMPREHENSION);
784 if (err_ureg)
785 return(ERR_IE_UNRECOGNIZED);
786 if (err_len)
787 return(ERR_IE_LENGTH);
788 if (err_seq)
789 return(ERR_IE_SEQUENCE);
790 }
791 return(0);
792}
793
794/* verify if a message type exists and contain no IE error */
795static int
796l3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
797{
798 switch (mt) {
799 case MT_ALERTING:
800 case MT_CALL_PROCEEDING:
801 case MT_CONNECT:
802 case MT_CONNECT_ACKNOWLEDGE:
803 case MT_DISCONNECT:
804 case MT_INFORMATION:
805 case MT_FACILITY:
806 case MT_NOTIFY:
807 case MT_PROGRESS:
808 case MT_RELEASE:
809 case MT_RELEASE_COMPLETE:
810 case MT_SETUP:
811 case MT_SETUP_ACKNOWLEDGE:
812 case MT_RESUME_ACKNOWLEDGE:
813 case MT_RESUME_REJECT:
814 case MT_SUSPEND_ACKNOWLEDGE:
815 case MT_SUSPEND_REJECT:
816 case MT_USER_INFORMATION:
817 case MT_RESTART:
818 case MT_RESTART_ACKNOWLEDGE:
819 case MT_CONGESTION_CONTROL:
820 case MT_STATUS:
821 case MT_STATUS_ENQUIRY:
822 if (pc->debug & L3_DEB_CHECK)
823 l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
824 break;
825 case MT_RESUME: /* RESUME only in user->net */
826 case MT_SUSPEND: /* SUSPEND only in user->net */
827 default:
828 if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
829 l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
830 pc->para.cause = 97;
831 l3dss1_status_send(pc, 0, NULL);
832 return(1);
833 }
834 return(0);
835}
836
837static void
838l3dss1_std_ie_err(struct l3_process *pc, int ret) {
839
840 if (pc->debug & L3_DEB_CHECK)
841 l3_debug(pc->st, "check_infoelements ret %d", ret);
842 switch(ret) {
843 case 0:
844 break;
845 case ERR_IE_COMPREHENSION:
846 pc->para.cause = 96;
847 l3dss1_status_send(pc, 0, NULL);
848 break;
849 case ERR_IE_UNRECOGNIZED:
850 pc->para.cause = 99;
851 l3dss1_status_send(pc, 0, NULL);
852 break;
853 case ERR_IE_LENGTH:
854 pc->para.cause = 100;
855 l3dss1_status_send(pc, 0, NULL);
856 break;
857 case ERR_IE_SEQUENCE:
858 default:
859 break;
860 }
861}
862
863static int
864l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
865 u_char *p;
866
867 p = skb->data;
868 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
869 p++;
870 if (*p != 1) { /* len for BRI = 1 */
871 if (pc->debug & L3_DEB_WARN)
872 l3_debug(pc->st, "wrong chid len %d", *p);
873 return (-2);
874 }
875 p++;
876 if (*p & 0x60) { /* only base rate interface */
877 if (pc->debug & L3_DEB_WARN)
878 l3_debug(pc->st, "wrong chid %x", *p);
879 return (-3);
880 }
881 return(*p & 0x3);
882 } else
883 return(-1);
884}
885
886static int
887l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
888 u_char l, i=0;
889 u_char *p;
890
891 p = skb->data;
892 pc->para.cause = 31;
893 pc->para.loc = 0;
894 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
895 p++;
896 l = *p++;
897 if (l>30)
898 return(1);
899 if (l) {
900 pc->para.loc = *p++;
901 l--;
902 } else {
903 return(2);
904 }
905 if (l && !(pc->para.loc & 0x80)) {
906 l--;
907 p++; /* skip recommendation */
908 }
909 if (l) {
910 pc->para.cause = *p++;
911 l--;
912 if (!(pc->para.cause & 0x80))
913 return(3);
914 } else
915 return(4);
916 while (l && (i<6)) {
917 pc->para.diag[i++] = *p++;
918 l--;
919 }
920 } else
921 return(-1);
922 return(0);
923}
924
925static void
926l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd)
927{
928 struct sk_buff *skb;
929 u_char tmp[16+40];
930 u_char *p = tmp;
931 int l;
932
933 MsgHead(p, pc->callref, cmd);
934
935 if (pc->prot.dss1.uus1_data[0])
936 { *p++ = IE_USER_USER; /* UUS info element */
937 *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
938 *p++ = 0x04; /* IA5 chars */
939 strcpy(p,pc->prot.dss1.uus1_data);
940 p += strlen(pc->prot.dss1.uus1_data);
941 pc->prot.dss1.uus1_data[0] = '\0';
942 }
943
944 l = p - tmp;
945 if (!(skb = l3_alloc_skb(l)))
946 return;
947 memcpy(skb_put(skb, l), tmp, l);
948 l3_msg(pc->st, DL_DATA | REQUEST, skb);
949} /* l3dss1_msg_with_uus */
950
951static void
952l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
953{
954 StopAllL3Timer(pc);
955 newl3state(pc, 19);
956 if (!pc->prot.dss1.uus1_data[0])
957 l3dss1_message(pc, MT_RELEASE);
958 else
959 l3dss1_msg_with_uus(pc, MT_RELEASE);
960 L3AddTimer(&pc->timer, T308, CC_T308_1);
961}
962
963static void
964l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
965{
966 struct sk_buff *skb = arg;
967 int ret;
968
969 if ((ret = l3dss1_get_cause(pc, skb))>0) {
970 if (pc->debug & L3_DEB_WARN)
971 l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
972 } else if (ret < 0)
973 pc->para.cause = NO_CAUSE;
974 StopAllL3Timer(pc);
975 newl3state(pc, 0);
976 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
977 dss1_release_l3_process(pc);
978}
979
980#if EXT_BEARER_CAPS
981
982static u_char *
983EncodeASyncParams(u_char * p, u_char si2)
984{ // 7c 06 88 90 21 42 00 bb
985
986 p[0] = 0;
987 p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19
988 p[2] = 0x80;
989 if (si2 & 32) // 7 data bits
990
991 p[2] += 16;
992 else // 8 data bits
993
994 p[2] += 24;
995
996 if (si2 & 16) // 2 stop bits
997
998 p[2] += 96;
999 else // 1 stop bit
1000
1001 p[2] += 32;
1002
1003 if (si2 & 8) // even parity
1004
1005 p[2] += 2;
1006 else // no parity
1007
1008 p[2] += 3;
1009
1010 switch (si2 & 0x07) {
1011 case 0:
1012 p[0] = 66; // 1200 bit/s
1013
1014 break;
1015 case 1:
1016 p[0] = 88; // 1200/75 bit/s
1017
1018 break;
1019 case 2:
1020 p[0] = 87; // 75/1200 bit/s
1021
1022 break;
1023 case 3:
1024 p[0] = 67; // 2400 bit/s
1025
1026 break;
1027 case 4:
1028 p[0] = 69; // 4800 bit/s
1029
1030 break;
1031 case 5:
1032 p[0] = 72; // 9600 bit/s
1033
1034 break;
1035 case 6:
1036 p[0] = 73; // 14400 bit/s
1037
1038 break;
1039 case 7:
1040 p[0] = 75; // 19200 bit/s
1041
1042 break;
1043 }
1044 return p + 3;
1045}
1046
1047static u_char
1048EncodeSyncParams(u_char si2, u_char ai)
1049{
1050
1051 switch (si2) {
1052 case 0:
1053 return ai + 2; // 1200 bit/s
1054
1055 case 1:
1056 return ai + 24; // 1200/75 bit/s
1057
1058 case 2:
1059 return ai + 23; // 75/1200 bit/s
1060
1061 case 3:
1062 return ai + 3; // 2400 bit/s
1063
1064 case 4:
1065 return ai + 5; // 4800 bit/s
1066
1067 case 5:
1068 return ai + 8; // 9600 bit/s
1069
1070 case 6:
1071 return ai + 9; // 14400 bit/s
1072
1073 case 7:
1074 return ai + 11; // 19200 bit/s
1075
1076 case 8:
1077 return ai + 14; // 48000 bit/s
1078
1079 case 9:
1080 return ai + 15; // 56000 bit/s
1081
1082 case 15:
1083 return ai + 40; // negotiate bit/s
1084
1085 default:
1086 break;
1087 }
1088 return ai;
1089}
1090
1091
1092static u_char
1093DecodeASyncParams(u_char si2, u_char * p)
1094{
1095 u_char info;
1096
1097 switch (p[5]) {
1098 case 66: // 1200 bit/s
1099
1100 break; // si2 don't change
1101
1102 case 88: // 1200/75 bit/s
1103
1104 si2 += 1;
1105 break;
1106 case 87: // 75/1200 bit/s
1107
1108 si2 += 2;
1109 break;
1110 case 67: // 2400 bit/s
1111
1112 si2 += 3;
1113 break;
1114 case 69: // 4800 bit/s
1115
1116 si2 += 4;
1117 break;
1118 case 72: // 9600 bit/s
1119
1120 si2 += 5;
1121 break;
1122 case 73: // 14400 bit/s
1123
1124 si2 += 6;
1125 break;
1126 case 75: // 19200 bit/s
1127
1128 si2 += 7;
1129 break;
1130 }
1131
1132 info = p[7] & 0x7f;
1133 if ((info & 16) && (!(info & 8))) // 7 data bits
1134
1135 si2 += 32; // else 8 data bits
1136
1137 if ((info & 96) == 96) // 2 stop bits
1138
1139 si2 += 16; // else 1 stop bit
1140
1141 if ((info & 2) && (!(info & 1))) // even parity
1142
1143 si2 += 8; // else no parity
1144
1145 return si2;
1146}
1147
1148
1149static u_char
1150DecodeSyncParams(u_char si2, u_char info)
1151{
1152 info &= 0x7f;
1153 switch (info) {
1154 case 40: // bit/s negotiation failed ai := 165 not 175!
1155
1156 return si2 + 15;
1157 case 15: // 56000 bit/s failed, ai := 0 not 169 !
1158
1159 return si2 + 9;
1160 case 14: // 48000 bit/s
1161
1162 return si2 + 8;
1163 case 11: // 19200 bit/s
1164
1165 return si2 + 7;
1166 case 9: // 14400 bit/s
1167
1168 return si2 + 6;
1169 case 8: // 9600 bit/s
1170
1171 return si2 + 5;
1172 case 5: // 4800 bit/s
1173
1174 return si2 + 4;
1175 case 3: // 2400 bit/s
1176
1177 return si2 + 3;
1178 case 23: // 75/1200 bit/s
1179
1180 return si2 + 2;
1181 case 24: // 1200/75 bit/s
1182
1183 return si2 + 1;
1184 default: // 1200 bit/s
1185
1186 return si2;
1187 }
1188}
1189
1190static u_char
1191DecodeSI2(struct sk_buff *skb)
1192{
1193 u_char *p; //, *pend=skb->data + skb->len;
1194
1195 if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
1196 switch (p[4] & 0x0f) {
1197 case 0x01:
1198 if (p[1] == 0x04) // sync. Bitratenadaption
1199
1200 return DecodeSyncParams(160, p[5]); // V.110/X.30
1201
1202 else if (p[1] == 0x06) // async. Bitratenadaption
1203
1204 return DecodeASyncParams(192, p); // V.110/X.30
1205
1206 break;
1207 case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
1208 if (p[1] > 3)
1209 return DecodeSyncParams(176, p[5]); // V.120
1210 break;
1211 }
1212 }
1213 return 0;
1214}
1215
1216#endif
1217
1218
1219static void
1220l3dss1_setup_req(struct l3_process *pc, u_char pr,
1221 void *arg)
1222{
1223 struct sk_buff *skb;
1224 u_char tmp[128];
1225 u_char *p = tmp;
1226 u_char channel = 0;
1227
1228 u_char send_keypad;
1229 u_char screen = 0x80;
1230 u_char *teln;
1231 u_char *msn;
1232 u_char *sub;
1233 u_char *sp;
1234 int l;
1235
1236 MsgHead(p, pc->callref, MT_SETUP);
1237
1238 teln = pc->para.setup.phone;
1239#ifndef CONFIG_HISAX_NO_KEYPAD
1240 send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0;
1241#else
1242 send_keypad = 0;
1243#endif
1244#ifndef CONFIG_HISAX_NO_SENDCOMPLETE
1245 if (!send_keypad)
1246 *p++ = 0xa1; /* complete indicator */
1247#endif
1248 /*
1249 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
1250 */
1251 switch (pc->para.setup.si1) {
1252 case 1: /* Telephony */
1253 *p++ = IE_BEARER;
1254 *p++ = 0x3; /* Length */
1255 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1256 *p++ = 0x90; /* Circuit-Mode 64kbps */
1257 *p++ = 0xa3; /* A-Law Audio */
1258 break;
1259 case 5: /* Datatransmission 64k, BTX */
1260 case 7: /* Datatransmission 64k */
1261 default:
1262 *p++ = IE_BEARER;
1263 *p++ = 0x2; /* Length */
1264 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1265 *p++ = 0x90; /* Circuit-Mode 64kbps */
1266 break;
1267 }
1268
1269 if (send_keypad) {
1270 *p++ = IE_KEYPAD;
1271 *p++ = strlen(teln);
1272 while (*teln)
1273 *p++ = (*teln++) & 0x7F;
1274 }
1275
1276 /*
1277 * What about info2? Mapping to High-Layer-Compatibility?
1278 */
1279 if ((*teln) && (!send_keypad)) {
1280 /* parse number for special things */
1281 if (!isdigit(*teln)) {
1282 switch (0x5f & *teln) {
1283 case 'C':
1284 channel = 0x08;
1285 case 'P':
1286 channel |= 0x80;
1287 teln++;
1288 if (*teln == '1')
1289 channel |= 0x01;
1290 else
1291 channel |= 0x02;
1292 break;
1293 case 'R':
1294 screen = 0xA0;
1295 break;
1296 case 'D':
1297 screen = 0x80;
1298 break;
1299
1300 default:
1301 if (pc->debug & L3_DEB_WARN)
1302 l3_debug(pc->st, "Wrong MSN Code");
1303 break;
1304 }
1305 teln++;
1306 }
1307 }
1308 if (channel) {
1309 *p++ = IE_CHANNEL_ID;
1310 *p++ = 1;
1311 *p++ = channel;
1312 }
1313 msn = pc->para.setup.eazmsn;
1314 sub = NULL;
1315 sp = msn;
1316 while (*sp) {
1317 if ('.' == *sp) {
1318 sub = sp;
1319 *sp = 0;
1320 } else
1321 sp++;
1322 }
1323 if (*msn) {
1324 *p++ = IE_CALLING_PN;
1325 *p++ = strlen(msn) + (screen ? 2 : 1);
1326 /* Classify as AnyPref. */
1327 if (screen) {
1328 *p++ = 0x01; /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */
1329 *p++ = screen;
1330 } else
1331 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
1332 while (*msn)
1333 *p++ = *msn++ & 0x7f;
1334 }
1335 if (sub) {
1336 *sub++ = '.';
1337 *p++ = IE_CALLING_SUB;
1338 *p++ = strlen(sub) + 2;
1339 *p++ = 0x80; /* NSAP coded */
1340 *p++ = 0x50; /* local IDI format */
1341 while (*sub)
1342 *p++ = *sub++ & 0x7f;
1343 }
1344 sub = NULL;
1345 sp = teln;
1346 while (*sp) {
1347 if ('.' == *sp) {
1348 sub = sp;
1349 *sp = 0;
1350 } else
1351 sp++;
1352 }
1353
1354 if (!send_keypad) {
1355 *p++ = IE_CALLED_PN;
1356 *p++ = strlen(teln) + 1;
1357 /* Classify as AnyPref. */
1358 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
1359 while (*teln)
1360 *p++ = *teln++ & 0x7f;
1361
1362 if (sub) {
1363 *sub++ = '.';
1364 *p++ = IE_CALLED_SUB;
1365 *p++ = strlen(sub) + 2;
1366 *p++ = 0x80; /* NSAP coded */
1367 *p++ = 0x50; /* local IDI format */
1368 while (*sub)
1369 *p++ = *sub++ & 0x7f;
1370 }
1371 }
1372#if EXT_BEARER_CAPS
1373 if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
1374
1375 *p++ = IE_LLC;
1376 *p++ = 0x04;
1377 *p++ = 0x88;
1378 *p++ = 0x90;
1379 *p++ = 0x21;
1380 *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
1381 } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120
1382
1383 *p++ = IE_LLC;
1384 *p++ = 0x05;
1385 *p++ = 0x88;
1386 *p++ = 0x90;
1387 *p++ = 0x28;
1388 *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
1389 *p++ = 0x82;
1390 } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30
1391
1392 *p++ = IE_LLC;
1393 *p++ = 0x06;
1394 *p++ = 0x88;
1395 *p++ = 0x90;
1396 *p++ = 0x21;
1397 p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
1398#ifndef CONFIG_HISAX_NO_LLC
1399 } else {
1400 switch (pc->para.setup.si1) {
1401 case 1: /* Telephony */
1402 *p++ = IE_LLC;
1403 *p++ = 0x3; /* Length */
1404 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1405 *p++ = 0x90; /* Circuit-Mode 64kbps */
1406 *p++ = 0xa3; /* A-Law Audio */
1407 break;
1408 case 5: /* Datatransmission 64k, BTX */
1409 case 7: /* Datatransmission 64k */
1410 default:
1411 *p++ = IE_LLC;
1412 *p++ = 0x2; /* Length */
1413 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1414 *p++ = 0x90; /* Circuit-Mode 64kbps */
1415 break;
1416 }
1417#endif
1418 }
1419#endif
1420 l = p - tmp;
1421 if (!(skb = l3_alloc_skb(l)))
1422 return;
1423 memcpy(skb_put(skb, l), tmp, l);
1424 L3DelTimer(&pc->timer);
1425 L3AddTimer(&pc->timer, T303, CC_T303);
1426 newl3state(pc, 1);
1427 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1428}
1429
1430static void
1431l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
1432{
1433 struct sk_buff *skb = arg;
1434 int id, ret;
1435
1436 if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1437 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1438 if (pc->debug & L3_DEB_WARN)
1439 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1440 pc->para.cause = 100;
1441 l3dss1_status_send(pc, pr, NULL);
1442 return;
1443 }
1444 pc->para.bchannel = id;
1445 } else if (1 == pc->state) {
1446 if (pc->debug & L3_DEB_WARN)
1447 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1448 if (id == -1)
1449 pc->para.cause = 96;
1450 else
1451 pc->para.cause = 100;
1452 l3dss1_status_send(pc, pr, NULL);
1453 return;
1454 }
1455 /* Now we are on none mandatory IEs */
1456 ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
1457 if (ERR_IE_COMPREHENSION == ret) {
1458 l3dss1_std_ie_err(pc, ret);
1459 return;
1460 }
1461 L3DelTimer(&pc->timer);
1462 newl3state(pc, 3);
1463 L3AddTimer(&pc->timer, T310, CC_T310);
1464 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1465 l3dss1_std_ie_err(pc, ret);
1466 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
1467}
1468
1469static void
1470l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
1471{
1472 struct sk_buff *skb = arg;
1473 int id, ret;
1474
1475 if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1476 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1477 if (pc->debug & L3_DEB_WARN)
1478 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1479 pc->para.cause = 100;
1480 l3dss1_status_send(pc, pr, NULL);
1481 return;
1482 }
1483 pc->para.bchannel = id;
1484 } else {
1485 if (pc->debug & L3_DEB_WARN)
1486 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1487 if (id == -1)
1488 pc->para.cause = 96;
1489 else
1490 pc->para.cause = 100;
1491 l3dss1_status_send(pc, pr, NULL);
1492 return;
1493 }
1494 /* Now we are on none mandatory IEs */
1495 ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
1496 if (ERR_IE_COMPREHENSION == ret) {
1497 l3dss1_std_ie_err(pc, ret);
1498 return;
1499 }
1500 L3DelTimer(&pc->timer);
1501 newl3state(pc, 2);
1502 L3AddTimer(&pc->timer, T304, CC_T304);
1503 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1504 l3dss1_std_ie_err(pc, ret);
1505 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1506}
1507
1508static void
1509l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
1510{
1511 struct sk_buff *skb = arg;
1512 u_char *p;
1513 int ret;
1514 u_char cause = 0;
1515
1516 StopAllL3Timer(pc);
1517 if ((ret = l3dss1_get_cause(pc, skb))) {
1518 if (pc->debug & L3_DEB_WARN)
1519 l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
1520 if (ret < 0)
1521 cause = 96;
1522 else if (ret > 0)
1523 cause = 100;
1524 }
1525 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
1526 l3dss1_parse_facility(pc->st, pc, pc->callref, p);
1527 ret = check_infoelements(pc, skb, ie_DISCONNECT);
1528 if (ERR_IE_COMPREHENSION == ret)
1529 cause = 96;
1530 else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
1531 cause = 99;
1532 ret = pc->state;
1533 newl3state(pc, 12);
1534 if (cause)
1535 newl3state(pc, 19);
1536 if (11 != ret)
1537 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
1538 else if (!cause)
1539 l3dss1_release_req(pc, pr, NULL);
1540 if (cause) {
1541 l3dss1_message_cause(pc, MT_RELEASE, cause);
1542 L3AddTimer(&pc->timer, T308, CC_T308_1);
1543 }
1544}
1545
1546static void
1547l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
1548{
1549 struct sk_buff *skb = arg;
1550 int ret;
1551
1552 ret = check_infoelements(pc, skb, ie_CONNECT);
1553 if (ERR_IE_COMPREHENSION == ret) {
1554 l3dss1_std_ie_err(pc, ret);
1555 return;
1556 }
1557 L3DelTimer(&pc->timer); /* T310 */
1558 newl3state(pc, 10);
1559 pc->para.chargeinfo = 0;
1560 /* here should inserted COLP handling KKe */
1561 if (ret)
1562 l3dss1_std_ie_err(pc, ret);
1563 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
1564}
1565
1566static void
1567l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
1568{
1569 struct sk_buff *skb = arg;
1570 int ret;
1571
1572 ret = check_infoelements(pc, skb, ie_ALERTING);
1573 if (ERR_IE_COMPREHENSION == ret) {
1574 l3dss1_std_ie_err(pc, ret);
1575 return;
1576 }
1577 L3DelTimer(&pc->timer); /* T304 */
1578 newl3state(pc, 4);
1579 if (ret)
1580 l3dss1_std_ie_err(pc, ret);
1581 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
1582}
1583
1584static void
1585l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
1586{
1587 u_char *p;
1588 int bcfound = 0;
1589 char tmp[80];
1590 struct sk_buff *skb = arg;
1591 int id;
1592 int err = 0;
1593
1594 /*
1595 * Bearer Capabilities
1596 */
1597 p = skb->data;
1598 /* only the first occurence 'll be detected ! */
1599 if ((p = findie(p, skb->len, 0x04, 0))) {
1600 if ((p[1] < 2) || (p[1] > 11))
1601 err = 1;
1602 else {
1603 pc->para.setup.si2 = 0;
1604 switch (p[2] & 0x7f) {
1605 case 0x00: /* Speech */
1606 case 0x10: /* 3.1 Khz audio */
1607 pc->para.setup.si1 = 1;
1608 break;
1609 case 0x08: /* Unrestricted digital information */
1610 pc->para.setup.si1 = 7;
1611/* JIM, 05.11.97 I wanna set service indicator 2 */
1612#if EXT_BEARER_CAPS
1613 pc->para.setup.si2 = DecodeSI2(skb);
1614#endif
1615 break;
1616 case 0x09: /* Restricted digital information */
1617 pc->para.setup.si1 = 2;
1618 break;
1619 case 0x11:
1620 /* Unrestr. digital information with
1621 * tones/announcements ( or 7 kHz audio
1622 */
1623 pc->para.setup.si1 = 3;
1624 break;
1625 case 0x18: /* Video */
1626 pc->para.setup.si1 = 4;
1627 break;
1628 default:
1629 err = 2;
1630 break;
1631 }
1632 switch (p[3] & 0x7f) {
1633 case 0x40: /* packed mode */
1634 pc->para.setup.si1 = 8;
1635 break;
1636 case 0x10: /* 64 kbit */
1637 case 0x11: /* 2*64 kbit */
1638 case 0x13: /* 384 kbit */
1639 case 0x15: /* 1536 kbit */
1640 case 0x17: /* 1920 kbit */
1641 pc->para.moderate = p[3] & 0x7f;
1642 break;
1643 default:
1644 err = 3;
1645 break;
1646 }
1647 }
1648 if (pc->debug & L3_DEB_SI)
1649 l3_debug(pc->st, "SI=%d, AI=%d",
1650 pc->para.setup.si1, pc->para.setup.si2);
1651 if (err) {
1652 if (pc->debug & L3_DEB_WARN)
1653 l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
1654 p[1], p[2], p[3]);
1655 pc->para.cause = 100;
1656 l3dss1_msg_without_setup(pc, pr, NULL);
1657 return;
1658 }
1659 } else {
1660 if (pc->debug & L3_DEB_WARN)
1661 l3_debug(pc->st, "setup without bearer capabilities");
1662 /* ETS 300-104 1.3.3 */
1663 pc->para.cause = 96;
1664 l3dss1_msg_without_setup(pc, pr, NULL);
1665 return;
1666 }
1667 /*
1668 * Channel Identification
1669 */
1670 if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1671 if ((pc->para.bchannel = id)) {
1672 if ((3 == id) && (0x10 == pc->para.moderate)) {
1673 if (pc->debug & L3_DEB_WARN)
1674 l3_debug(pc->st, "setup with wrong chid %x",
1675 id);
1676 pc->para.cause = 100;
1677 l3dss1_msg_without_setup(pc, pr, NULL);
1678 return;
1679 }
1680 bcfound++;
1681 } else
1682 { if (pc->debug & L3_DEB_WARN)
1683 l3_debug(pc->st, "setup without bchannel, call waiting");
1684 bcfound++;
1685 }
1686 } else {
1687 if (pc->debug & L3_DEB_WARN)
1688 l3_debug(pc->st, "setup with wrong chid ret %d", id);
1689 if (id == -1)
1690 pc->para.cause = 96;
1691 else
1692 pc->para.cause = 100;
1693 l3dss1_msg_without_setup(pc, pr, NULL);
1694 return;
1695 }
1696 /* Now we are on none mandatory IEs */
1697 err = check_infoelements(pc, skb, ie_SETUP);
1698 if (ERR_IE_COMPREHENSION == err) {
1699 pc->para.cause = 96;
1700 l3dss1_msg_without_setup(pc, pr, NULL);
1701 return;
1702 }
1703 p = skb->data;
1704 if ((p = findie(p, skb->len, 0x70, 0)))
1705 iecpy(pc->para.setup.eazmsn, p, 1);
1706 else
1707 pc->para.setup.eazmsn[0] = 0;
1708
1709 p = skb->data;
1710 if ((p = findie(p, skb->len, 0x71, 0))) {
1711 /* Called party subaddress */
1712 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1713 tmp[0] = '.';
1714 iecpy(&tmp[1], p, 2);
1715 strcat(pc->para.setup.eazmsn, tmp);
1716 } else if (pc->debug & L3_DEB_WARN)
1717 l3_debug(pc->st, "wrong called subaddress");
1718 }
1719 p = skb->data;
1720 if ((p = findie(p, skb->len, 0x6c, 0))) {
1721 pc->para.setup.plan = p[2];
1722 if (p[2] & 0x80) {
1723 iecpy(pc->para.setup.phone, p, 1);
1724 pc->para.setup.screen = 0;
1725 } else {
1726 iecpy(pc->para.setup.phone, p, 2);
1727 pc->para.setup.screen = p[3];
1728 }
1729 } else {
1730 pc->para.setup.phone[0] = 0;
1731 pc->para.setup.plan = 0;
1732 pc->para.setup.screen = 0;
1733 }
1734 p = skb->data;
1735 if ((p = findie(p, skb->len, 0x6d, 0))) {
1736 /* Calling party subaddress */
1737 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1738 tmp[0] = '.';
1739 iecpy(&tmp[1], p, 2);
1740 strcat(pc->para.setup.phone, tmp);
1741 } else if (pc->debug & L3_DEB_WARN)
1742 l3_debug(pc->st, "wrong calling subaddress");
1743 }
1744 newl3state(pc, 6);
1745 if (err) /* STATUS for none mandatory IE errors after actions are taken */
1746 l3dss1_std_ie_err(pc, err);
1747 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1748}
1749
1750static void
1751l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
1752{
1753 dss1_release_l3_process(pc);
1754}
1755
1756static void
1757l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1758{
1759 struct sk_buff *skb;
1760 u_char tmp[16+40];
1761 u_char *p = tmp;
1762 int l;
1763 u_char cause = 16;
1764
1765 if (pc->para.cause != NO_CAUSE)
1766 cause = pc->para.cause;
1767
1768 StopAllL3Timer(pc);
1769
1770 MsgHead(p, pc->callref, MT_DISCONNECT);
1771
1772 *p++ = IE_CAUSE;
1773 *p++ = 0x2;
1774 *p++ = 0x80;
1775 *p++ = cause | 0x80;
1776
1777 if (pc->prot.dss1.uus1_data[0])
1778 { *p++ = IE_USER_USER; /* UUS info element */
1779 *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
1780 *p++ = 0x04; /* IA5 chars */
1781 strcpy(p,pc->prot.dss1.uus1_data);
1782 p += strlen(pc->prot.dss1.uus1_data);
1783 pc->prot.dss1.uus1_data[0] = '\0';
1784 }
1785
1786 l = p - tmp;
1787 if (!(skb = l3_alloc_skb(l)))
1788 return;
1789 memcpy(skb_put(skb, l), tmp, l);
1790 newl3state(pc, 11);
1791 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1792 L3AddTimer(&pc->timer, T305, CC_T305);
1793}
1794
1795static void
1796l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
1797 void *arg)
1798{
1799 if (!pc->para.bchannel)
1800 { if (pc->debug & L3_DEB_WARN)
1801 l3_debug(pc->st, "D-chan connect for waiting call");
1802 l3dss1_disconnect_req(pc, pr, arg);
1803 return;
1804 }
1805 newl3state(pc, 8);
1806 l3dss1_message(pc, MT_CONNECT);
1807 L3DelTimer(&pc->timer);
1808 L3AddTimer(&pc->timer, T313, CC_T313);
1809}
1810
1811static void
1812l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1813{
1814 struct sk_buff *skb = arg;
1815 int ret;
1816
1817 ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
1818 if (ERR_IE_COMPREHENSION == ret) {
1819 l3dss1_std_ie_err(pc, ret);
1820 return;
1821 }
1822 newl3state(pc, 10);
1823 L3DelTimer(&pc->timer);
1824 if (ret)
1825 l3dss1_std_ie_err(pc, ret);
1826 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1827}
1828
1829static void
1830l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1831{
1832 struct sk_buff *skb;
1833 u_char tmp[16];
1834 u_char *p = tmp;
1835 int l;
1836 u_char cause = 21;
1837
1838 if (pc->para.cause != NO_CAUSE)
1839 cause = pc->para.cause;
1840
1841 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1842
1843 *p++ = IE_CAUSE;
1844 *p++ = 0x2;
1845 *p++ = 0x80;
1846 *p++ = cause | 0x80;
1847
1848 l = p - tmp;
1849 if (!(skb = l3_alloc_skb(l)))
1850 return;
1851 memcpy(skb_put(skb, l), tmp, l);
1852 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1853 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1854 newl3state(pc, 0);
1855 dss1_release_l3_process(pc);
1856}
1857
1858static void
1859l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
1860{
1861 struct sk_buff *skb = arg;
1862 u_char *p;
1863 int ret, cause=0;
1864
1865 StopAllL3Timer(pc);
1866 if ((ret = l3dss1_get_cause(pc, skb))>0) {
1867 if (pc->debug & L3_DEB_WARN)
1868 l3_debug(pc->st, "REL get_cause ret(%d)", ret);
1869 } else if (ret<0)
1870 pc->para.cause = NO_CAUSE;
1871 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
1872 l3dss1_parse_facility(pc->st, pc, pc->callref, p);
1873 }
1874 if ((ret<0) && (pc->state != 11))
1875 cause = 96;
1876 else if (ret>0)
1877 cause = 100;
1878 ret = check_infoelements(pc, skb, ie_RELEASE);
1879 if (ERR_IE_COMPREHENSION == ret)
1880 cause = 96;
1881 else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
1882 cause = 99;
1883 if (cause)
1884 l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
1885 else
1886 l3dss1_message(pc, MT_RELEASE_COMPLETE);
1887 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1888 newl3state(pc, 0);
1889 dss1_release_l3_process(pc);
1890}
1891
1892static void
1893l3dss1_alert_req(struct l3_process *pc, u_char pr,
1894 void *arg)
1895{
1896 newl3state(pc, 7);
1897 if (!pc->prot.dss1.uus1_data[0])
1898 l3dss1_message(pc, MT_ALERTING);
1899 else
1900 l3dss1_msg_with_uus(pc, MT_ALERTING);
1901}
1902
1903static void
1904l3dss1_proceed_req(struct l3_process *pc, u_char pr,
1905 void *arg)
1906{
1907 newl3state(pc, 9);
1908 l3dss1_message(pc, MT_CALL_PROCEEDING);
1909 pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc);
1910}
1911
1912static void
1913l3dss1_setup_ack_req(struct l3_process *pc, u_char pr,
1914 void *arg)
1915{
1916 newl3state(pc, 25);
1917 L3DelTimer(&pc->timer);
1918 L3AddTimer(&pc->timer, T302, CC_T302);
1919 l3dss1_message(pc, MT_SETUP_ACKNOWLEDGE);
1920}
1921
1922/********************************************/
1923/* deliver a incoming display message to HL */
1924/********************************************/
1925static void
1926l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
1927{ u_char len;
1928 isdn_ctrl ic;
1929 struct IsdnCardState *cs;
1930 char *p;
1931
1932 if (*infp++ != IE_DISPLAY) return;
1933 if ((len = *infp++) > 80) return; /* total length <= 82 */
1934 if (!pc->chan) return;
1935
1936 p = ic.parm.display;
1937 while (len--)
1938 *p++ = *infp++;
1939 *p = '\0';
1940 ic.command = ISDN_STAT_DISPLAY;
1941 cs = pc->st->l1.hardware;
1942 ic.driver = cs->myid;
1943 ic.arg = pc->chan->chan;
1944 cs->iif.statcallb(&ic);
1945} /* l3dss1_deliver_display */
1946
1947
1948static void
1949l3dss1_progress(struct l3_process *pc, u_char pr, void *arg)
1950{
1951 struct sk_buff *skb = arg;
1952 int err = 0;
1953 u_char *p;
1954
1955 if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
1956 if (p[1] != 2) {
1957 err = 1;
1958 pc->para.cause = 100;
1959 } else if (!(p[2] & 0x70)) {
1960 switch (p[2]) {
1961 case 0x80:
1962 case 0x81:
1963 case 0x82:
1964 case 0x84:
1965 case 0x85:
1966 case 0x87:
1967 case 0x8a:
1968 switch (p[3]) {
1969 case 0x81:
1970 case 0x82:
1971 case 0x83:
1972 case 0x84:
1973 case 0x88:
1974 break;
1975 default:
1976 err = 2;
1977 pc->para.cause = 100;
1978 break;
1979 }
1980 break;
1981 default:
1982 err = 3;
1983 pc->para.cause = 100;
1984 break;
1985 }
1986 }
1987 } else {
1988 pc->para.cause = 96;
1989 err = 4;
1990 }
1991 if (err) {
1992 if (pc->debug & L3_DEB_WARN)
1993 l3_debug(pc->st, "progress error %d", err);
1994 l3dss1_status_send(pc, pr, NULL);
1995 return;
1996 }
1997 /* Now we are on none mandatory IEs */
1998 err = check_infoelements(pc, skb, ie_PROGRESS);
1999 if (err)
2000 l3dss1_std_ie_err(pc, err);
2001 if (ERR_IE_COMPREHENSION != err)
2002 pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
2003}
2004
2005static void
2006l3dss1_notify(struct l3_process *pc, u_char pr, void *arg)
2007{
2008 struct sk_buff *skb = arg;
2009 int err = 0;
2010 u_char *p;
2011
2012 if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
2013 if (p[1] != 1) {
2014 err = 1;
2015 pc->para.cause = 100;
2016 } else {
2017 switch (p[2]) {
2018 case 0x80:
2019 case 0x81:
2020 case 0x82:
2021 break;
2022 default:
2023 pc->para.cause = 100;
2024 err = 2;
2025 break;
2026 }
2027 }
2028 } else {
2029 pc->para.cause = 96;
2030 err = 3;
2031 }
2032 if (err) {
2033 if (pc->debug & L3_DEB_WARN)
2034 l3_debug(pc->st, "notify error %d", err);
2035 l3dss1_status_send(pc, pr, NULL);
2036 return;
2037 }
2038 /* Now we are on none mandatory IEs */
2039 err = check_infoelements(pc, skb, ie_NOTIFY);
2040 if (err)
2041 l3dss1_std_ie_err(pc, err);
2042 if (ERR_IE_COMPREHENSION != err)
2043 pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
2044}
2045
2046static void
2047l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
2048{
2049 int ret;
2050 struct sk_buff *skb = arg;
2051
2052 ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
2053 l3dss1_std_ie_err(pc, ret);
2054 pc->para.cause = 30; /* response to STATUS_ENQUIRY */
2055 l3dss1_status_send(pc, pr, NULL);
2056}
2057
2058static void
2059l3dss1_information(struct l3_process *pc, u_char pr, void *arg)
2060{
2061 int ret;
2062 struct sk_buff *skb = arg;
2063 u_char *p;
2064 char tmp[32];
2065
2066 ret = check_infoelements(pc, skb, ie_INFORMATION);
2067 if (ret)
2068 l3dss1_std_ie_err(pc, ret);
2069 if (pc->state == 25) { /* overlap receiving */
2070 L3DelTimer(&pc->timer);
2071 p = skb->data;
2072 if ((p = findie(p, skb->len, 0x70, 0))) {
2073 iecpy(tmp, p, 1);
2074 strcat(pc->para.setup.eazmsn, tmp);
2075 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
2076 }
2077 L3AddTimer(&pc->timer, T302, CC_T302);
2078 }
2079}
2080
2081/******************************/
2082/* handle deflection requests */
2083/******************************/
2084static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg)
2085{
2086 struct sk_buff *skb;
2087 u_char tmp[128];
2088 u_char *p = tmp;
2089 u_char *subp;
2090 u_char len_phone = 0;
2091 u_char len_sub = 0;
2092 int l;
2093
2094
2095 strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
2096 if (!pc->chan->setup.phone[0])
2097 { pc->para.cause = -1;
2098 l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */
2099 return;
2100 } /* only uus */
2101
2102 if (pc->prot.dss1.invoke_id)
2103 free_invoke_id(pc->st,pc->prot.dss1.invoke_id);
2104
2105 if (!(pc->prot.dss1.invoke_id = new_invoke_id(pc->st)))
2106 return;
2107
2108 MsgHead(p, pc->callref, MT_FACILITY);
2109
2110 for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
2111 if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subaddress element */
2112
2113 *p++ = 0x1c; /* Facility info element */
2114 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
2115 *p++ = 0x91; /* remote operations protocol */
2116 *p++ = 0xa1; /* invoke component */
2117
2118 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
2119 *p++ = 0x02; /* invoke id tag, integer */
2120 *p++ = 0x01; /* length */
2121 *p++ = pc->prot.dss1.invoke_id; /* invoke id */
2122 *p++ = 0x02; /* operation value tag, integer */
2123 *p++ = 0x01; /* length */
2124 *p++ = 0x0D; /* Call Deflect */
2125
2126 *p++ = 0x30; /* sequence phone number */
2127 *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
2128
2129 *p++ = 0x30; /* Deflected to UserNumber */
2130 *p++ = len_phone+2+len_sub; /* length */
2131 *p++ = 0x80; /* NumberDigits */
2132 *p++ = len_phone; /* length */
2133 for (l = 0; l < len_phone; l++)
2134 *p++ = pc->chan->setup.phone[l];
2135
2136 if (len_sub)
2137 { *p++ = 0x04; /* called party subaddress */
2138 *p++ = len_sub - 2;
2139 while (*subp) *p++ = *subp++;
2140 }
2141
2142 *p++ = 0x01; /* screening identifier */
2143 *p++ = 0x01;
2144 *p++ = pc->chan->setup.screen;
2145
2146 l = p - tmp;
2147 if (!(skb = l3_alloc_skb(l))) return;
2148 memcpy(skb_put(skb, l), tmp, l);
2149
2150 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2151} /* l3dss1_redir_req */
2152
2153/********************************************/
2154/* handle deflection request in early state */
2155/********************************************/
2156static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
2157{
2158 l3dss1_proceed_req(pc,pr,arg);
2159 l3dss1_redir_req(pc,pr,arg);
2160} /* l3dss1_redir_req_early */
2161
2162/***********************************************/
2163/* handle special commands for this protocol. */
2164/* Examples are call independant services like */
2165/* remote operations with dummy callref. */
2166/***********************************************/
2167static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
2168{ u_char id;
2169 u_char temp[265];
2170 u_char *p = temp;
2171 int i, l, proc_len;
2172 struct sk_buff *skb;
2173 struct l3_process *pc = NULL;
2174
2175 switch (ic->arg)
2176 { case DSS1_CMD_INVOKE:
2177 if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */
2178
2179 for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++)
2180 i = i >> 8; /* add one byte */
2181 l = ic->parm.dss1_io.datalen + proc_len + 8; /* length excluding ie header */
2182 if (l > 255)
2183 return(-2); /* too long */
2184
2185 if (!(id = new_invoke_id(st)))
2186 return(0); /* first get a invoke id -> return if no available */
2187
2188 i = -1;
2189 MsgHead(p, i, MT_FACILITY); /* build message head */
2190 *p++ = 0x1C; /* Facility IE */
2191 *p++ = l; /* length of ie */
2192 *p++ = 0x91; /* remote operations */
2193 *p++ = 0xA1; /* invoke */
2194 *p++ = l - 3; /* length of invoke */
2195 *p++ = 0x02; /* invoke id tag */
2196 *p++ = 0x01; /* length is 1 */
2197 *p++ = id; /* invoke id */
2198 *p++ = 0x02; /* operation */
2199 *p++ = proc_len; /* length of operation */
2200
2201 for (i = proc_len; i; i--)
2202 *p++ = (ic->parm.dss1_io.proc >> (i-1)) & 0xFF;
2203 memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */
2204 l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */
2205
2206 if (ic->parm.dss1_io.timeout > 0)
2207 if (!(pc = dss1_new_l3_process(st, -1)))
2208 { free_invoke_id(st, id);
2209 return(-2);
2210 }
2211 pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */
2212 pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */
2213
2214 if (!(skb = l3_alloc_skb(l)))
2215 { free_invoke_id(st, id);
2216 if (pc) dss1_release_l3_process(pc);
2217 return(-2);
2218 }
2219 memcpy(skb_put(skb, l), temp, l);
2220
2221 if (pc)
2222 { pc->prot.dss1.invoke_id = id; /* remember id */
2223 L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST);
2224 }
2225
2226 l3_msg(st, DL_DATA | REQUEST, skb);
2227 ic->parm.dss1_io.hl_id = id; /* return id */
2228 return(0);
2229
2230 case DSS1_CMD_INVOKE_ABORT:
2231 if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id)))
2232 { L3DelTimer(&pc->timer); /* remove timer */
2233 dss1_release_l3_process(pc);
2234 return(0);
2235 }
2236 else
2237 { l3_debug(st, "l3dss1_cmd_global abort unknown id");
2238 return(-2);
2239 }
2240 break;
2241
2242 default:
2243 l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg);
2244 return(-1);
2245 } /* switch ic-> arg */
2246 return(-1);
2247} /* l3dss1_cmd_global */
2248
2249static void
2250l3dss1_io_timer(struct l3_process *pc)
2251{ isdn_ctrl ic;
2252 struct IsdnCardState *cs = pc->st->l1.hardware;
2253
2254 L3DelTimer(&pc->timer); /* remove timer */
2255
2256 ic.driver = cs->myid;
2257 ic.command = ISDN_STAT_PROT;
2258 ic.arg = DSS1_STAT_INVOKE_ERR;
2259 ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
2260 ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
2261 ic.parm.dss1_io.proc = pc->prot.dss1.proc;
2262 ic.parm.dss1_io.timeout= -1;
2263 ic.parm.dss1_io.datalen = 0;
2264 ic.parm.dss1_io.data = NULL;
2265 free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
2266 pc->prot.dss1.invoke_id = 0; /* reset id */
2267
2268 cs->iif.statcallb(&ic);
2269
2270 dss1_release_l3_process(pc);
2271} /* l3dss1_io_timer */
2272
2273static void
2274l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
2275{
2276 u_char *p;
2277 struct sk_buff *skb = arg;
2278 int callState = 0;
2279 p = skb->data;
2280
2281 if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
2282 p++;
2283 if (1 == *p++)
2284 callState = *p;
2285 }
2286 if (callState == 0) {
2287 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
2288 * set down layer 3 without sending any message
2289 */
2290 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2291 newl3state(pc, 0);
2292 dss1_release_l3_process(pc);
2293 } else {
2294 pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
2295 }
2296}
2297
2298static void
2299l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg)
2300{
2301}
2302
2303static void
2304l3dss1_t302(struct l3_process *pc, u_char pr, void *arg)
2305{
2306 L3DelTimer(&pc->timer);
2307 pc->para.loc = 0;
2308 pc->para.cause = 28; /* invalid number */
2309 l3dss1_disconnect_req(pc, pr, NULL);
2310 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2311}
2312
2313static void
2314l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
2315{
2316 if (pc->N303 > 0) {
2317 pc->N303--;
2318 L3DelTimer(&pc->timer);
2319 l3dss1_setup_req(pc, pr, arg);
2320 } else {
2321 L3DelTimer(&pc->timer);
2322 l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
2323 pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
2324 dss1_release_l3_process(pc);
2325 }
2326}
2327
2328static void
2329l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
2330{
2331 L3DelTimer(&pc->timer);
2332 pc->para.loc = 0;
2333 pc->para.cause = 102;
2334 l3dss1_disconnect_req(pc, pr, NULL);
2335 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2336
2337}
2338
2339static void
2340l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
2341{
2342 u_char tmp[16];
2343 u_char *p = tmp;
2344 int l;
2345 struct sk_buff *skb;
2346 u_char cause = 16;
2347
2348 L3DelTimer(&pc->timer);
2349 if (pc->para.cause != NO_CAUSE)
2350 cause = pc->para.cause;
2351
2352 MsgHead(p, pc->callref, MT_RELEASE);
2353
2354 *p++ = IE_CAUSE;
2355 *p++ = 0x2;
2356 *p++ = 0x80;
2357 *p++ = cause | 0x80;
2358
2359 l = p - tmp;
2360 if (!(skb = l3_alloc_skb(l)))
2361 return;
2362 memcpy(skb_put(skb, l), tmp, l);
2363 newl3state(pc, 19);
2364 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2365 L3AddTimer(&pc->timer, T308, CC_T308_1);
2366}
2367
2368static void
2369l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
2370{
2371 L3DelTimer(&pc->timer);
2372 pc->para.loc = 0;
2373 pc->para.cause = 102;
2374 l3dss1_disconnect_req(pc, pr, NULL);
2375 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2376}
2377
2378static void
2379l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
2380{
2381 L3DelTimer(&pc->timer);
2382 pc->para.loc = 0;
2383 pc->para.cause = 102;
2384 l3dss1_disconnect_req(pc, pr, NULL);
2385 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
2386}
2387
2388static void
2389l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg)
2390{
2391 newl3state(pc, 19);
2392 L3DelTimer(&pc->timer);
2393 l3dss1_message(pc, MT_RELEASE);
2394 L3AddTimer(&pc->timer, T308, CC_T308_2);
2395}
2396
2397static void
2398l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
2399{
2400 L3DelTimer(&pc->timer);
2401 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
2402 dss1_release_l3_process(pc);
2403}
2404
2405static void
2406l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
2407{
2408 L3DelTimer(&pc->timer);
2409 pc->para.cause = 102; /* Timer expiry */
2410 pc->para.loc = 0; /* local */
2411 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2412 newl3state(pc, 19);
2413 l3dss1_message(pc, MT_RELEASE);
2414 L3AddTimer(&pc->timer, T308, CC_T308_1);
2415}
2416
2417static void
2418l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
2419{
2420 L3DelTimer(&pc->timer);
2421 pc->para.cause = 102; /* Timer expiry */
2422 pc->para.loc = 0; /* local */
2423 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2424 newl3state(pc, 10);
2425}
2426
2427static void
2428l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
2429{
2430 L3DelTimer(&pc->timer);
2431 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2432 dss1_release_l3_process(pc);
2433}
2434
2435static void
2436l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
2437{
2438 u_char *p;
2439 struct sk_buff *skb = arg;
2440 int ret;
2441 u_char cause = 0, callState = 0;
2442
2443 if ((ret = l3dss1_get_cause(pc, skb))) {
2444 if (pc->debug & L3_DEB_WARN)
2445 l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
2446 if (ret < 0)
2447 cause = 96;
2448 else if (ret > 0)
2449 cause = 100;
2450 }
2451 if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
2452 p++;
2453 if (1 == *p++) {
2454 callState = *p;
2455 if (!ie_in_set(pc, *p, l3_valid_states))
2456 cause = 100;
2457 } else
2458 cause = 100;
2459 } else
2460 cause = 96;
2461 if (!cause) { /* no error before */
2462 ret = check_infoelements(pc, skb, ie_STATUS);
2463 if (ERR_IE_COMPREHENSION == ret)
2464 cause = 96;
2465 else if (ERR_IE_UNRECOGNIZED == ret)
2466 cause = 99;
2467 }
2468 if (cause) {
2469 u_char tmp;
2470
2471 if (pc->debug & L3_DEB_WARN)
2472 l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
2473 tmp = pc->para.cause;
2474 pc->para.cause = cause;
2475 l3dss1_status_send(pc, 0, NULL);
2476 if (cause == 99)
2477 pc->para.cause = tmp;
2478 else
2479 return;
2480 }
2481 cause = pc->para.cause;
2482 if (((cause & 0x7f) == 111) && (callState == 0)) {
2483 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
2484 * if received MT_STATUS with cause == 111 and call
2485 * state == 0, then we must set down layer 3
2486 */
2487 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2488 newl3state(pc, 0);
2489 dss1_release_l3_process(pc);
2490 }
2491}
2492
2493static void
2494l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
2495{
2496 struct sk_buff *skb = arg;
2497 int ret;
2498
2499 ret = check_infoelements(pc, skb, ie_FACILITY);
2500 l3dss1_std_ie_err(pc, ret);
2501 {
2502 u_char *p;
2503 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
2504 l3dss1_parse_facility(pc->st, pc, pc->callref, p);
2505 }
2506}
2507
2508static void
2509l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
2510{
2511 struct sk_buff *skb;
2512 u_char tmp[32];
2513 u_char *p = tmp;
2514 u_char i, l;
2515 u_char *msg = pc->chan->setup.phone;
2516
2517 MsgHead(p, pc->callref, MT_SUSPEND);
2518 l = *msg++;
2519 if (l && (l <= 10)) { /* Max length 10 octets */
2520 *p++ = IE_CALL_ID;
2521 *p++ = l;
2522 for (i = 0; i < l; i++)
2523 *p++ = *msg++;
2524 } else if (l) {
2525 l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
2526 return;
2527 }
2528 l = p - tmp;
2529 if (!(skb = l3_alloc_skb(l)))
2530 return;
2531 memcpy(skb_put(skb, l), tmp, l);
2532 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2533 newl3state(pc, 15);
2534 L3AddTimer(&pc->timer, T319, CC_T319);
2535}
2536
2537static void
2538l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
2539{
2540 struct sk_buff *skb = arg;
2541 int ret;
2542
2543 L3DelTimer(&pc->timer);
2544 newl3state(pc, 0);
2545 pc->para.cause = NO_CAUSE;
2546 pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
2547 /* We don't handle suspend_ack for IE errors now */
2548 if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
2549 if (pc->debug & L3_DEB_WARN)
2550 l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
2551 dss1_release_l3_process(pc);
2552}
2553
2554static void
2555l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
2556{
2557 struct sk_buff *skb = arg;
2558 int ret;
2559
2560 if ((ret = l3dss1_get_cause(pc, skb))) {
2561 if (pc->debug & L3_DEB_WARN)
2562 l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
2563 if (ret < 0)
2564 pc->para.cause = 96;
2565 else
2566 pc->para.cause = 100;
2567 l3dss1_status_send(pc, pr, NULL);
2568 return;
2569 }
2570 ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
2571 if (ERR_IE_COMPREHENSION == ret) {
2572 l3dss1_std_ie_err(pc, ret);
2573 return;
2574 }
2575 L3DelTimer(&pc->timer);
2576 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2577 newl3state(pc, 10);
2578 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2579 l3dss1_std_ie_err(pc, ret);
2580}
2581
2582static void
2583l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
2584{
2585 struct sk_buff *skb;
2586 u_char tmp[32];
2587 u_char *p = tmp;
2588 u_char i, l;
2589 u_char *msg = pc->para.setup.phone;
2590
2591 MsgHead(p, pc->callref, MT_RESUME);
2592
2593 l = *msg++;
2594 if (l && (l <= 10)) { /* Max length 10 octets */
2595 *p++ = IE_CALL_ID;
2596 *p++ = l;
2597 for (i = 0; i < l; i++)
2598 *p++ = *msg++;
2599 } else if (l) {
2600 l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
2601 return;
2602 }
2603 l = p - tmp;
2604 if (!(skb = l3_alloc_skb(l)))
2605 return;
2606 memcpy(skb_put(skb, l), tmp, l);
2607 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2608 newl3state(pc, 17);
2609 L3AddTimer(&pc->timer, T318, CC_T318);
2610}
2611
2612static void
2613l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
2614{
2615 struct sk_buff *skb = arg;
2616 int id, ret;
2617
2618 if ((id = l3dss1_get_channel_id(pc, skb)) > 0) {
2619 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
2620 if (pc->debug & L3_DEB_WARN)
2621 l3_debug(pc->st, "resume ack with wrong chid %x", id);
2622 pc->para.cause = 100;
2623 l3dss1_status_send(pc, pr, NULL);
2624 return;
2625 }
2626 pc->para.bchannel = id;
2627 } else if (1 == pc->state) {
2628 if (pc->debug & L3_DEB_WARN)
2629 l3_debug(pc->st, "resume ack without chid (ret %d)", id);
2630 pc->para.cause = 96;
2631 l3dss1_status_send(pc, pr, NULL);
2632 return;
2633 }
2634 ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
2635 if (ERR_IE_COMPREHENSION == ret) {
2636 l3dss1_std_ie_err(pc, ret);
2637 return;
2638 }
2639 L3DelTimer(&pc->timer);
2640 pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
2641 newl3state(pc, 10);
2642 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2643 l3dss1_std_ie_err(pc, ret);
2644}
2645
2646static void
2647l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
2648{
2649 struct sk_buff *skb = arg;
2650 int ret;
2651
2652 if ((ret = l3dss1_get_cause(pc, skb))) {
2653 if (pc->debug & L3_DEB_WARN)
2654 l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
2655 if (ret < 0)
2656 pc->para.cause = 96;
2657 else
2658 pc->para.cause = 100;
2659 l3dss1_status_send(pc, pr, NULL);
2660 return;
2661 }
2662 ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
2663 if (ERR_IE_COMPREHENSION == ret) {
2664 l3dss1_std_ie_err(pc, ret);
2665 return;
2666 }
2667 L3DelTimer(&pc->timer);
2668 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2669 newl3state(pc, 0);
2670 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2671 l3dss1_std_ie_err(pc, ret);
2672 dss1_release_l3_process(pc);
2673}
2674
2675static void
2676l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
2677{
2678 u_char tmp[32];
2679 u_char *p;
2680 u_char ri, ch = 0, chan = 0;
2681 int l;
2682 struct sk_buff *skb = arg;
2683 struct l3_process *up;
2684
2685 newl3state(pc, 2);
2686 L3DelTimer(&pc->timer);
2687 p = skb->data;
2688 if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
2689 ri = p[2];
2690 l3_debug(pc->st, "Restart %x", ri);
2691 } else {
2692 l3_debug(pc->st, "Restart without restart IE");
2693 ri = 0x86;
2694 }
2695 p = skb->data;
2696 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
2697 chan = p[2] & 3;
2698 ch = p[2];
2699 if (pc->st->l3.debug)
2700 l3_debug(pc->st, "Restart for channel %d", chan);
2701 }
2702 newl3state(pc, 2);
2703 up = pc->st->l3.proc;
2704 while (up) {
2705 if ((ri & 7) == 7)
2706 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2707 else if (up->para.bchannel == chan)
2708 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2709 up = up->next;
2710 }
2711 p = tmp;
2712 MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
2713 if (chan) {
2714 *p++ = IE_CHANNEL_ID;
2715 *p++ = 1;
2716 *p++ = ch | 0x80;
2717 }
2718 *p++ = 0x79; /* RESTART Ind */
2719 *p++ = 1;
2720 *p++ = ri;
2721 l = p - tmp;
2722 if (!(skb = l3_alloc_skb(l)))
2723 return;
2724 memcpy(skb_put(skb, l), tmp, l);
2725 newl3state(pc, 0);
2726 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2727}
2728
2729static void
2730l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
2731{
2732 pc->para.cause = 0x29; /* Temporary failure */
2733 pc->para.loc = 0;
2734 l3dss1_disconnect_req(pc, pr, NULL);
2735 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2736}
2737
2738static void
2739l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg)
2740{
2741 newl3state(pc, 0);
2742 pc->para.cause = 0x1b; /* Destination out of order */
2743 pc->para.loc = 0;
2744 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2745 release_l3_process(pc);
2746}
2747
2748static void
2749l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
2750{
2751 L3DelTimer(&pc->timer);
2752 L3AddTimer(&pc->timer, T309, CC_T309);
2753 l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
2754}
2755
2756static void
2757l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
2758{
2759 L3DelTimer(&pc->timer);
2760
2761 pc->para.cause = 0x1F; /* normal, unspecified */
2762 l3dss1_status_send(pc, 0, NULL);
2763}
2764
2765/* *INDENT-OFF* */
2766static struct stateentry downstatelist[] =
2767{
2768 {SBIT(0),
2769 CC_SETUP | REQUEST, l3dss1_setup_req},
2770 {SBIT(0),
2771 CC_RESUME | REQUEST, l3dss1_resume_req},
2772 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
2773 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
2774 {SBIT(12),
2775 CC_RELEASE | REQUEST, l3dss1_release_req},
2776 {ALL_STATES,
2777 CC_RESTART | REQUEST, l3dss1_restart},
2778 {SBIT(6) | SBIT(25),
2779 CC_IGNORE | REQUEST, l3dss1_reset},
2780 {SBIT(6) | SBIT(25),
2781 CC_REJECT | REQUEST, l3dss1_reject_req},
2782 {SBIT(6) | SBIT(25),
2783 CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
2784 {SBIT(6),
2785 CC_MORE_INFO | REQUEST, l3dss1_setup_ack_req},
2786 {SBIT(25),
2787 CC_MORE_INFO | REQUEST, l3dss1_dummy},
2788 {SBIT(6) | SBIT(9) | SBIT(25),
2789 CC_ALERTING | REQUEST, l3dss1_alert_req},
2790 {SBIT(6) | SBIT(7) | SBIT(9) | SBIT(25),
2791 CC_SETUP | RESPONSE, l3dss1_setup_rsp},
2792 {SBIT(10),
2793 CC_SUSPEND | REQUEST, l3dss1_suspend_req},
2794 {SBIT(7) | SBIT(9) | SBIT(25),
2795 CC_REDIR | REQUEST, l3dss1_redir_req},
2796 {SBIT(6),
2797 CC_REDIR | REQUEST, l3dss1_redir_req_early},
2798 {SBIT(9) | SBIT(25),
2799 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
2800 {SBIT(25),
2801 CC_T302, l3dss1_t302},
2802 {SBIT(1),
2803 CC_T303, l3dss1_t303},
2804 {SBIT(2),
2805 CC_T304, l3dss1_t304},
2806 {SBIT(3),
2807 CC_T310, l3dss1_t310},
2808 {SBIT(8),
2809 CC_T313, l3dss1_t313},
2810 {SBIT(11),
2811 CC_T305, l3dss1_t305},
2812 {SBIT(15),
2813 CC_T319, l3dss1_t319},
2814 {SBIT(17),
2815 CC_T318, l3dss1_t318},
2816 {SBIT(19),
2817 CC_T308_1, l3dss1_t308_1},
2818 {SBIT(19),
2819 CC_T308_2, l3dss1_t308_2},
2820 {SBIT(10),
2821 CC_T309, l3dss1_dl_release},
2822};
2823
2824#define DOWNSLLEN \
2825 (sizeof(downstatelist) / sizeof(struct stateentry))
2826
2827static struct stateentry datastatelist[] =
2828{
2829 {ALL_STATES,
2830 MT_STATUS_ENQUIRY, l3dss1_status_enq},
2831 {ALL_STATES,
2832 MT_FACILITY, l3dss1_facility},
2833 {SBIT(19),
2834 MT_STATUS, l3dss1_release_ind},
2835 {ALL_STATES,
2836 MT_STATUS, l3dss1_status},
2837 {SBIT(0),
2838 MT_SETUP, l3dss1_setup},
2839 {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
2840 SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2841 MT_SETUP, l3dss1_dummy},
2842 {SBIT(1) | SBIT(2),
2843 MT_CALL_PROCEEDING, l3dss1_call_proc},
2844 {SBIT(1),
2845 MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
2846 {SBIT(2) | SBIT(3),
2847 MT_ALERTING, l3dss1_alerting},
2848 {SBIT(2) | SBIT(3),
2849 MT_PROGRESS, l3dss1_progress},
2850 {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
2851 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2852 MT_INFORMATION, l3dss1_information},
2853 {SBIT(10) | SBIT(11) | SBIT(15),
2854 MT_NOTIFY, l3dss1_notify},
2855 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
2856 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2857 MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
2858 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
2859 MT_RELEASE, l3dss1_release},
2860 {SBIT(19), MT_RELEASE, l3dss1_release_ind},
2861 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
2862 MT_DISCONNECT, l3dss1_disconnect},
2863 {SBIT(19),
2864 MT_DISCONNECT, l3dss1_dummy},
2865 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
2866 MT_CONNECT, l3dss1_connect},
2867 {SBIT(8),
2868 MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
2869 {SBIT(15),
2870 MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
2871 {SBIT(15),
2872 MT_SUSPEND_REJECT, l3dss1_suspend_rej},
2873 {SBIT(17),
2874 MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
2875 {SBIT(17),
2876 MT_RESUME_REJECT, l3dss1_resume_rej},
2877};
2878
2879#define DATASLLEN \
2880 (sizeof(datastatelist) / sizeof(struct stateentry))
2881
2882static struct stateentry globalmes_list[] =
2883{
2884 {ALL_STATES,
2885 MT_STATUS, l3dss1_status},
2886 {SBIT(0),
2887 MT_RESTART, l3dss1_global_restart},
2888/* {SBIT(1),
2889 MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
2890*/
2891};
2892#define GLOBALM_LEN \
2893 (sizeof(globalmes_list) / sizeof(struct stateentry))
2894
2895static struct stateentry manstatelist[] =
2896{
2897 {SBIT(2),
2898 DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
2899 {SBIT(10),
2900 DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
2901 {SBIT(10),
2902 DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
2903 {ALL_STATES,
2904 DL_RELEASE | INDICATION, l3dss1_dl_release},
2905};
2906
2907#define MANSLLEN \
2908 (sizeof(manstatelist) / sizeof(struct stateentry))
2909/* *INDENT-ON* */
2910
2911
2912static void
2913global_handler(struct PStack *st, int mt, struct sk_buff *skb)
2914{
2915 u_char tmp[16];
2916 u_char *p = tmp;
2917 int l;
2918 int i;
2919 struct l3_process *proc = st->l3.global;
2920
2921 proc->callref = skb->data[2]; /* cr flag */
2922 for (i = 0; i < GLOBALM_LEN; i++)
2923 if ((mt == globalmes_list[i].primitive) &&
2924 ((1 << proc->state) & globalmes_list[i].state))
2925 break;
2926 if (i == GLOBALM_LEN) {
2927 if (st->l3.debug & L3_DEB_STATE) {
2928 l3_debug(st, "dss1 global state %d mt %x unhandled",
2929 proc->state, mt);
2930 }
2931 MsgHead(p, proc->callref, MT_STATUS);
2932 *p++ = IE_CAUSE;
2933 *p++ = 0x2;
2934 *p++ = 0x80;
2935 *p++ = 81 |0x80; /* invalid cr */
2936 *p++ = 0x14; /* CallState */
2937 *p++ = 0x1;
2938 *p++ = proc->state & 0x3f;
2939 l = p - tmp;
2940 if (!(skb = l3_alloc_skb(l)))
2941 return;
2942 memcpy(skb_put(skb, l), tmp, l);
2943 l3_msg(proc->st, DL_DATA | REQUEST, skb);
2944 } else {
2945 if (st->l3.debug & L3_DEB_STATE) {
2946 l3_debug(st, "dss1 global %d mt %x",
2947 proc->state, mt);
2948 }
2949 globalmes_list[i].rout(proc, mt, skb);
2950 }
2951}
2952
2953static void
2954dss1up(struct PStack *st, int pr, void *arg)
2955{
2956 int i, mt, cr, cause, callState;
2957 char *ptr;
2958 u_char *p;
2959 struct sk_buff *skb = arg;
2960 struct l3_process *proc;
2961
2962 switch (pr) {
2963 case (DL_DATA | INDICATION):
2964 case (DL_UNIT_DATA | INDICATION):
2965 break;
2966 case (DL_ESTABLISH | CONFIRM):
2967 case (DL_ESTABLISH | INDICATION):
2968 case (DL_RELEASE | INDICATION):
2969 case (DL_RELEASE | CONFIRM):
2970 l3_msg(st, pr, arg);
2971 return;
2972 break;
2973 default:
2974 printk(KERN_ERR "HiSax dss1up unknown pr=%04x\n", pr);
2975 return;
2976 }
2977 if (skb->len < 3) {
2978 l3_debug(st, "dss1up frame too short(%d)", skb->len);
2979 dev_kfree_skb(skb);
2980 return;
2981 }
2982
2983 if (skb->data[0] != PROTO_DIS_EURO) {
2984 if (st->l3.debug & L3_DEB_PROTERR) {
2985 l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
2986 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
2987 skb->data[0], skb->len);
2988 }
2989 dev_kfree_skb(skb);
2990 return;
2991 }
2992 cr = getcallref(skb->data);
2993 if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
2994 l3_debug(st, "dss1up frame too short(%d)", skb->len);
2995 dev_kfree_skb(skb);
2996 return;
2997 }
2998 mt = skb->data[skb->data[1] + 2];
2999 if (st->l3.debug & L3_DEB_STATE)
3000 l3_debug(st, "dss1up cr %d", cr);
3001 if (cr == -2) { /* wrong Callref */
3002 if (st->l3.debug & L3_DEB_WARN)
3003 l3_debug(st, "dss1up wrong Callref");
3004 dev_kfree_skb(skb);
3005 return;
3006 } else if (cr == -1) { /* Dummy Callref */
3007 if (mt == MT_FACILITY)
3008 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
3009 l3dss1_parse_facility(st, NULL,
3010 (pr == (DL_DATA | INDICATION)) ? -1 : -2, p);
3011 dev_kfree_skb(skb);
3012 return;
3013 }
3014 if (st->l3.debug & L3_DEB_WARN)
3015 l3_debug(st, "dss1up dummy Callref (no facility msg or ie)");
3016 dev_kfree_skb(skb);
3017 return;
3018 } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
3019 (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */
3020 if (st->l3.debug & L3_DEB_STATE)
3021 l3_debug(st, "dss1up Global CallRef");
3022 global_handler(st, mt, skb);
3023 dev_kfree_skb(skb);
3024 return;
3025 } else if (!(proc = getl3proc(st, cr))) {
3026 /* No transaction process exist, that means no call with
3027 * this callreference is active
3028 */
3029 if (mt == MT_SETUP) {
3030 /* Setup creates a new transaction process */
3031 if (skb->data[2] & 0x80) {
3032 /* Setup with wrong CREF flag */
3033 if (st->l3.debug & L3_DEB_STATE)
3034 l3_debug(st, "dss1up wrong CRef flag");
3035 dev_kfree_skb(skb);
3036 return;
3037 }
3038 if (!(proc = dss1_new_l3_process(st, cr))) {
3039 /* May be to answer with RELEASE_COMPLETE and
3040 * CAUSE 0x2f "Resource unavailable", but this
3041 * need a new_l3_process too ... arghh
3042 */
3043 dev_kfree_skb(skb);
3044 return;
3045 }
3046 } else if (mt == MT_STATUS) {
3047 cause = 0;
3048 if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
3049 ptr++;
3050 if (*ptr++ == 2)
3051 ptr++;
3052 cause = *ptr & 0x7f;
3053 }
3054 callState = 0;
3055 if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
3056 ptr++;
3057 if (*ptr++ == 2)
3058 ptr++;
3059 callState = *ptr;
3060 }
3061 /* ETS 300-104 part 2.4.1
3062 * if setup has not been made and a message type
3063 * MT_STATUS is received with call state == 0,
3064 * we must send nothing
3065 */
3066 if (callState != 0) {
3067 /* ETS 300-104 part 2.4.2
3068 * if setup has not been made and a message type
3069 * MT_STATUS is received with call state != 0,
3070 * we must send MT_RELEASE_COMPLETE cause 101
3071 */
3072 if ((proc = dss1_new_l3_process(st, cr))) {
3073 proc->para.cause = 101;
3074 l3dss1_msg_without_setup(proc, 0, NULL);
3075 }
3076 }
3077 dev_kfree_skb(skb);
3078 return;
3079 } else if (mt == MT_RELEASE_COMPLETE) {
3080 dev_kfree_skb(skb);
3081 return;
3082 } else {
3083 /* ETS 300-104 part 2
3084 * if setup has not been made and a message type
3085 * (except MT_SETUP and RELEASE_COMPLETE) is received,
3086 * we must send MT_RELEASE_COMPLETE cause 81 */
3087 dev_kfree_skb(skb);
3088 if ((proc = dss1_new_l3_process(st, cr))) {
3089 proc->para.cause = 81;
3090 l3dss1_msg_without_setup(proc, 0, NULL);
3091 }
3092 return;
3093 }
3094 }
3095 if (l3dss1_check_messagetype_validity(proc, mt, skb)) {
3096 dev_kfree_skb(skb);
3097 return;
3098 }
3099 if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
3100 l3dss1_deliver_display(proc, pr, p); /* Display IE included */
3101 for (i = 0; i < DATASLLEN; i++)
3102 if ((mt == datastatelist[i].primitive) &&
3103 ((1 << proc->state) & datastatelist[i].state))
3104 break;
3105 if (i == DATASLLEN) {
3106 if (st->l3.debug & L3_DEB_STATE) {
3107 l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
3108 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3109 proc->state, mt);
3110 }
3111 if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
3112 proc->para.cause = 101;
3113 l3dss1_status_send(proc, pr, skb);
3114 }
3115 } else {
3116 if (st->l3.debug & L3_DEB_STATE) {
3117 l3_debug(st, "dss1up%sstate %d mt %x",
3118 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3119 proc->state, mt);
3120 }
3121 datastatelist[i].rout(proc, pr, skb);
3122 }
3123 dev_kfree_skb(skb);
3124 return;
3125}
3126
3127static void
3128dss1down(struct PStack *st, int pr, void *arg)
3129{
3130 int i, cr;
3131 struct l3_process *proc;
3132 struct Channel *chan;
3133
3134 if ((DL_ESTABLISH | REQUEST) == pr) {
3135 l3_msg(st, pr, NULL);
3136 return;
3137 } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
3138 chan = arg;
3139 cr = newcallref();
3140 cr |= 0x80;
3141 if ((proc = dss1_new_l3_process(st, cr))) {
3142 proc->chan = chan;
3143 chan->proc = proc;
3144 memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
3145 proc->callref = cr;
3146 }
3147 } else {
3148 proc = arg;
3149 }
3150 if (!proc) {
3151 printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
3152 return;
3153 }
3154
3155 if ( pr == (CC_TDSS1_IO | REQUEST)) {
3156 l3dss1_io_timer(proc); /* timer expires */
3157 return;
3158 }
3159
3160 for (i = 0; i < DOWNSLLEN; i++)
3161 if ((pr == downstatelist[i].primitive) &&
3162 ((1 << proc->state) & downstatelist[i].state))
3163 break;
3164 if (i == DOWNSLLEN) {
3165 if (st->l3.debug & L3_DEB_STATE) {
3166 l3_debug(st, "dss1down state %d prim %#x unhandled",
3167 proc->state, pr);
3168 }
3169 } else {
3170 if (st->l3.debug & L3_DEB_STATE) {
3171 l3_debug(st, "dss1down state %d prim %#x",
3172 proc->state, pr);
3173 }
3174 downstatelist[i].rout(proc, pr, arg);
3175 }
3176}
3177
3178static void
3179dss1man(struct PStack *st, int pr, void *arg)
3180{
3181 int i;
3182 struct l3_process *proc = arg;
3183
3184 if (!proc) {
3185 printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
3186 return;
3187 }
3188 for (i = 0; i < MANSLLEN; i++)
3189 if ((pr == manstatelist[i].primitive) &&
3190 ((1 << proc->state) & manstatelist[i].state))
3191 break;
3192 if (i == MANSLLEN) {
3193 if (st->l3.debug & L3_DEB_STATE) {
3194 l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
3195 proc->callref & 0x7f, proc->state, pr);
3196 }
3197 } else {
3198 if (st->l3.debug & L3_DEB_STATE) {
3199 l3_debug(st, "cr %d dss1man state %d prim %#x",
3200 proc->callref & 0x7f, proc->state, pr);
3201 }
3202 manstatelist[i].rout(proc, pr, arg);
3203 }
3204}
3205
3206void
3207setstack_dss1(struct PStack *st)
3208{
3209 char tmp[64];
3210 int i;
3211
3212 st->lli.l4l3 = dss1down;
3213 st->lli.l4l3_proto = l3dss1_cmd_global;
3214 st->l2.l2l3 = dss1up;
3215 st->l3.l3ml3 = dss1man;
3216 st->l3.N303 = 1;
3217 st->prot.dss1.last_invoke_id = 0;
3218 st->prot.dss1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
3219 i = 1;
3220 while (i < 32)
3221 st->prot.dss1.invoke_used[i++] = 0;
3222
3223 if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
3224 printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
3225 } else {
3226 st->l3.global->state = 0;
3227 st->l3.global->callref = 0;
3228 st->l3.global->next = NULL;
3229 st->l3.global->debug = L3_DEB_WARN;
3230 st->l3.global->st = st;
3231 st->l3.global->N303 = 1;
3232 st->l3.global->prot.dss1.invoke_id = 0;
3233
3234 L3InitTimer(st->l3.global, &st->l3.global->timer);
3235 }
3236 strcpy(tmp, dss1_revision);
3237 printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp));
3238}
diff --git a/drivers/isdn/hisax/l3dss1.h b/drivers/isdn/hisax/l3dss1.h
new file mode 100644
index 00000000000..6da47f05ef2
--- /dev/null
+++ b/drivers/isdn/hisax/l3dss1.h
@@ -0,0 +1,124 @@
1/* $Id: l3dss1.h,v 1.10.6.2 2001/09/23 22:24:50 kai Exp $
2 *
3 * DSS1 (Euro) D-channel protocol defines
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#ifndef l3dss1_process
11
12#define T302 15000
13#define T303 4000
14#define T304 30000
15#define T305 30000
16#define T308 4000
17/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
18/* This makes some tests easier and quicker */
19#define T309 40000
20#define T310 30000
21#define T313 4000
22#define T318 4000
23#define T319 4000
24
25/*
26 * Message-Types
27 */
28
29#define MT_ALERTING 0x01
30#define MT_CALL_PROCEEDING 0x02
31#define MT_CONNECT 0x07
32#define MT_CONNECT_ACKNOWLEDGE 0x0f
33#define MT_PROGRESS 0x03
34#define MT_SETUP 0x05
35#define MT_SETUP_ACKNOWLEDGE 0x0d
36#define MT_RESUME 0x26
37#define MT_RESUME_ACKNOWLEDGE 0x2e
38#define MT_RESUME_REJECT 0x22
39#define MT_SUSPEND 0x25
40#define MT_SUSPEND_ACKNOWLEDGE 0x2d
41#define MT_SUSPEND_REJECT 0x21
42#define MT_USER_INFORMATION 0x20
43#define MT_DISCONNECT 0x45
44#define MT_RELEASE 0x4d
45#define MT_RELEASE_COMPLETE 0x5a
46#define MT_RESTART 0x46
47#define MT_RESTART_ACKNOWLEDGE 0x4e
48#define MT_SEGMENT 0x60
49#define MT_CONGESTION_CONTROL 0x79
50#define MT_INFORMATION 0x7b
51#define MT_FACILITY 0x62
52#define MT_NOTIFY 0x6e
53#define MT_STATUS 0x7d
54#define MT_STATUS_ENQUIRY 0x75
55
56#define IE_SEGMENT 0x00
57#define IE_BEARER 0x04
58#define IE_CAUSE 0x08
59#define IE_CALL_ID 0x10
60#define IE_CALL_STATE 0x14
61#define IE_CHANNEL_ID 0x18
62#define IE_FACILITY 0x1c
63#define IE_PROGRESS 0x1e
64#define IE_NET_FAC 0x20
65#define IE_NOTIFY 0x27
66#define IE_DISPLAY 0x28
67#define IE_DATE 0x29
68#define IE_KEYPAD 0x2c
69#define IE_SIGNAL 0x34
70#define IE_INFORATE 0x40
71#define IE_E2E_TDELAY 0x42
72#define IE_TDELAY_SEL 0x43
73#define IE_PACK_BINPARA 0x44
74#define IE_PACK_WINSIZE 0x45
75#define IE_PACK_SIZE 0x46
76#define IE_CUG 0x47
77#define IE_REV_CHARGE 0x4a
78#define IE_CONNECT_PN 0x4c
79#define IE_CONNECT_SUB 0x4d
80#define IE_CALLING_PN 0x6c
81#define IE_CALLING_SUB 0x6d
82#define IE_CALLED_PN 0x70
83#define IE_CALLED_SUB 0x71
84#define IE_REDIR_NR 0x74
85#define IE_TRANS_SEL 0x78
86#define IE_RESTART_IND 0x79
87#define IE_LLC 0x7c
88#define IE_HLC 0x7d
89#define IE_USER_USER 0x7e
90#define IE_ESCAPE 0x7f
91#define IE_SHIFT 0x90
92#define IE_MORE_DATA 0xa0
93#define IE_COMPLETE 0xa1
94#define IE_CONGESTION 0xb0
95#define IE_REPEAT 0xd0
96
97#define IE_MANDATORY 0x0100
98/* mandatory not in every case */
99#define IE_MANDATORY_1 0x0200
100
101#define ERR_IE_COMPREHENSION 1
102#define ERR_IE_UNRECOGNIZED -1
103#define ERR_IE_LENGTH -2
104#define ERR_IE_SEQUENCE -3
105
106#else /* only l3dss1_process */
107
108/* l3dss1 specific data in l3 process */
109typedef struct
110 { unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */
111 ulong ll_id; /* remebered ll id */
112 u8 remote_operation; /* handled remote operation, 0 = not active */
113 int proc; /* rememered procedure */
114 ulong remote_result; /* result of remote operation for statcallb */
115 char uus1_data[35]; /* data send during alerting or disconnect */
116 } dss1_proc_priv;
117
118/* l3dss1 specific data in protocol stack */
119typedef struct
120 { unsigned char last_invoke_id; /* last used value for invoking */
121 unsigned char invoke_used[32]; /* 256 bits for 256 values */
122 } dss1_stk_priv;
123
124#endif /* only l3dss1_process */
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
new file mode 100644
index 00000000000..3ab3a54daac
--- /dev/null
+++ b/drivers/isdn/hisax/l3ni1.c
@@ -0,0 +1,3189 @@
1/* $Id: l3ni1.c,v 2.8.2.3 2004/01/13 14:31:25 keil Exp $
2 *
3 * NI1 D-channel protocol
4 *
5 * Author Matt Henderson & Guy Ellis
6 * Copyright by Traverse Technologies Pty Ltd, www.travers.com.au
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 * 2000.6.6 Initial implementation of routines for US NI1
12 * Layer 3 protocol based on the EURO/DSS1 D-channel protocol
13 * driver written by Karsten Keil et al.
14 * NI-1 Hall of Fame - Thanks to....
15 * Ragnar Paulson - for some handy code fragments
16 * Will Scales - beta tester extraordinaire
17 * Brett Whittacre - beta tester and remote devel system in Vegas
18 *
19 */
20
21#include "hisax.h"
22#include "isdnl3.h"
23#include "l3ni1.h"
24#include <linux/ctype.h>
25
26extern char *HiSax_getrev(const char *revision);
27const char *ni1_revision = "$Revision: 2.8.2.3 $";
28
29#define EXT_BEARER_CAPS 1
30
31#define MsgHead(ptr, cref, mty) \
32 *ptr++ = 0x8; \
33 if (cref == -1) { \
34 *ptr++ = 0x0; \
35 } else { \
36 *ptr++ = 0x1; \
37 *ptr++ = cref^0x80; \
38 } \
39 *ptr++ = mty
40
41
42/**********************************************/
43/* get a new invoke id for remote operations. */
44/* Only a return value != 0 is valid */
45/**********************************************/
46static unsigned char new_invoke_id(struct PStack *p)
47{
48 unsigned char retval;
49 int i;
50
51 i = 32; /* maximum search depth */
52
53 retval = p->prot.ni1.last_invoke_id + 1; /* try new id */
54 while ((i) && (p->prot.ni1.invoke_used[retval >> 3] == 0xFF)) {
55 p->prot.ni1.last_invoke_id = (retval & 0xF8) + 8;
56 i--;
57 }
58 if (i) {
59 while (p->prot.ni1.invoke_used[retval >> 3] & (1 << (retval & 7)))
60 retval++;
61 } else
62 retval = 0;
63 p->prot.ni1.last_invoke_id = retval;
64 p->prot.ni1.invoke_used[retval >> 3] |= (1 << (retval & 7));
65 return(retval);
66} /* new_invoke_id */
67
68/*************************/
69/* free a used invoke id */
70/*************************/
71static void free_invoke_id(struct PStack *p, unsigned char id)
72{
73
74 if (!id) return; /* 0 = invalid value */
75
76 p->prot.ni1.invoke_used[id >> 3] &= ~(1 << (id & 7));
77} /* free_invoke_id */
78
79
80/**********************************************************/
81/* create a new l3 process and fill in ni1 specific data */
82/**********************************************************/
83static struct l3_process
84*ni1_new_l3_process(struct PStack *st, int cr)
85{ struct l3_process *proc;
86
87 if (!(proc = new_l3_process(st, cr)))
88 return(NULL);
89
90 proc->prot.ni1.invoke_id = 0;
91 proc->prot.ni1.remote_operation = 0;
92 proc->prot.ni1.uus1_data[0] = '\0';
93
94 return(proc);
95} /* ni1_new_l3_process */
96
97/************************************************/
98/* free a l3 process and all ni1 specific data */
99/************************************************/
100static void
101ni1_release_l3_process(struct l3_process *p)
102{
103 free_invoke_id(p->st,p->prot.ni1.invoke_id);
104 release_l3_process(p);
105} /* ni1_release_l3_process */
106
107/********************************************************/
108/* search a process with invoke id id and dummy callref */
109/********************************************************/
110static struct l3_process *
111l3ni1_search_dummy_proc(struct PStack *st, int id)
112{ struct l3_process *pc = st->l3.proc; /* start of processes */
113
114 if (!id) return(NULL);
115
116 while (pc)
117 { if ((pc->callref == -1) && (pc->prot.ni1.invoke_id == id))
118 return(pc);
119 pc = pc->next;
120 }
121 return(NULL);
122} /* l3ni1_search_dummy_proc */
123
124/*******************************************************************/
125/* called when a facility message with a dummy callref is received */
126/* and a return result is delivered. id specifies the invoke id. */
127/*******************************************************************/
128static void
129l3ni1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
130{ isdn_ctrl ic;
131 struct IsdnCardState *cs;
132 struct l3_process *pc = NULL;
133
134 if ((pc = l3ni1_search_dummy_proc(st, id)))
135 { L3DelTimer(&pc->timer); /* remove timer */
136
137 cs = pc->st->l1.hardware;
138 ic.driver = cs->myid;
139 ic.command = ISDN_STAT_PROT;
140 ic.arg = NI1_STAT_INVOKE_RES;
141 ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id;
142 ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id;
143 ic.parm.ni1_io.proc = pc->prot.ni1.proc;
144 ic.parm.ni1_io.timeout= 0;
145 ic.parm.ni1_io.datalen = nlen;
146 ic.parm.ni1_io.data = p;
147 free_invoke_id(pc->st, pc->prot.ni1.invoke_id);
148 pc->prot.ni1.invoke_id = 0; /* reset id */
149
150 cs->iif.statcallb(&ic);
151 ni1_release_l3_process(pc);
152 }
153 else
154 l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
155} /* l3ni1_dummy_return_result */
156
157/*******************************************************************/
158/* called when a facility message with a dummy callref is received */
159/* and a return error is delivered. id specifies the invoke id. */
160/*******************************************************************/
161static void
162l3ni1_dummy_error_return(struct PStack *st, int id, ulong error)
163{ isdn_ctrl ic;
164 struct IsdnCardState *cs;
165 struct l3_process *pc = NULL;
166
167 if ((pc = l3ni1_search_dummy_proc(st, id)))
168 { L3DelTimer(&pc->timer); /* remove timer */
169
170 cs = pc->st->l1.hardware;
171 ic.driver = cs->myid;
172 ic.command = ISDN_STAT_PROT;
173 ic.arg = NI1_STAT_INVOKE_ERR;
174 ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id;
175 ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id;
176 ic.parm.ni1_io.proc = pc->prot.ni1.proc;
177 ic.parm.ni1_io.timeout= error;
178 ic.parm.ni1_io.datalen = 0;
179 ic.parm.ni1_io.data = NULL;
180 free_invoke_id(pc->st, pc->prot.ni1.invoke_id);
181 pc->prot.ni1.invoke_id = 0; /* reset id */
182
183 cs->iif.statcallb(&ic);
184 ni1_release_l3_process(pc);
185 }
186 else
187 l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
188} /* l3ni1_error_return */
189
190/*******************************************************************/
191/* called when a facility message with a dummy callref is received */
192/* and a invoke is delivered. id specifies the invoke id. */
193/*******************************************************************/
194static void
195l3ni1_dummy_invoke(struct PStack *st, int cr, int id,
196 int ident, u_char *p, u_char nlen)
197{ isdn_ctrl ic;
198 struct IsdnCardState *cs;
199
200 l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
201 (cr == -1) ? "local" : "broadcast",id,ident,nlen);
202 if (cr >= -1) return; /* ignore local data */
203
204 cs = st->l1.hardware;
205 ic.driver = cs->myid;
206 ic.command = ISDN_STAT_PROT;
207 ic.arg = NI1_STAT_INVOKE_BRD;
208 ic.parm.ni1_io.hl_id = id;
209 ic.parm.ni1_io.ll_id = 0;
210 ic.parm.ni1_io.proc = ident;
211 ic.parm.ni1_io.timeout= 0;
212 ic.parm.ni1_io.datalen = nlen;
213 ic.parm.ni1_io.data = p;
214
215 cs->iif.statcallb(&ic);
216} /* l3ni1_dummy_invoke */
217
218static void
219l3ni1_parse_facility(struct PStack *st, struct l3_process *pc,
220 int cr, u_char * p)
221{
222 int qd_len = 0;
223 unsigned char nlen = 0, ilen, cp_tag;
224 int ident, id;
225 ulong err_ret;
226
227 if (pc)
228 st = pc->st; /* valid Stack */
229 else
230 if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
231
232 p++;
233 qd_len = *p++;
234 if (qd_len == 0) {
235 l3_debug(st, "qd_len == 0");
236 return;
237 }
238 if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
239 l3_debug(st, "supplementary service != 0x11");
240 return;
241 }
242 while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */
243 p++;
244 qd_len--;
245 }
246 if (qd_len < 2) {
247 l3_debug(st, "qd_len < 2");
248 return;
249 }
250 p++;
251 qd_len--;
252 if ((*p & 0xE0) != 0xA0) { /* class and form */
253 l3_debug(st, "class and form != 0xA0");
254 return;
255 }
256
257 cp_tag = *p & 0x1F; /* remember tag value */
258
259 p++;
260 qd_len--;
261 if (qd_len < 1)
262 { l3_debug(st, "qd_len < 1");
263 return;
264 }
265 if (*p & 0x80)
266 { /* length format indefinite or limited */
267 nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
268 if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
269 (nlen > 1))
270 { l3_debug(st, "length format error or not implemented");
271 return;
272 }
273 if (nlen == 1)
274 { nlen = *p++; /* complete length */
275 qd_len--;
276 }
277 else
278 { qd_len -= 2; /* trailing null bytes */
279 if ((*(p+qd_len)) || (*(p+qd_len+1)))
280 { l3_debug(st,"length format indefinite error");
281 return;
282 }
283 nlen = qd_len;
284 }
285 }
286 else
287 { nlen = *p++;
288 qd_len--;
289 }
290 if (qd_len < nlen)
291 { l3_debug(st, "qd_len < nlen");
292 return;
293 }
294 qd_len -= nlen;
295
296 if (nlen < 2)
297 { l3_debug(st, "nlen < 2");
298 return;
299 }
300 if (*p != 0x02)
301 { /* invoke identifier tag */
302 l3_debug(st, "invoke identifier tag !=0x02");
303 return;
304 }
305 p++;
306 nlen--;
307 if (*p & 0x80)
308 { /* length format */
309 l3_debug(st, "invoke id length format 2");
310 return;
311 }
312 ilen = *p++;
313 nlen--;
314 if (ilen > nlen || ilen == 0)
315 { l3_debug(st, "ilen > nlen || ilen == 0");
316 return;
317 }
318 nlen -= ilen;
319 id = 0;
320 while (ilen > 0)
321 { id = (id << 8) | (*p++ & 0xFF); /* invoke identifier */
322 ilen--;
323 }
324
325 switch (cp_tag) { /* component tag */
326 case 1: /* invoke */
327 if (nlen < 2) {
328 l3_debug(st, "nlen < 2 22");
329 return;
330 }
331 if (*p != 0x02) { /* operation value */
332 l3_debug(st, "operation value !=0x02");
333 return;
334 }
335 p++;
336 nlen--;
337 ilen = *p++;
338 nlen--;
339 if (ilen > nlen || ilen == 0) {
340 l3_debug(st, "ilen > nlen || ilen == 0 22");
341 return;
342 }
343 nlen -= ilen;
344 ident = 0;
345 while (ilen > 0) {
346 ident = (ident << 8) | (*p++ & 0xFF);
347 ilen--;
348 }
349
350 if (!pc)
351 {
352 l3ni1_dummy_invoke(st, cr, id, ident, p, nlen);
353 return;
354 }
355 l3_debug(st, "invoke break");
356 break;
357 case 2: /* return result */
358 /* if no process available handle separately */
359 if (!pc)
360 { if (cr == -1)
361 l3ni1_dummy_return_result(st, id, p, nlen);
362 return;
363 }
364 if ((pc->prot.ni1.invoke_id) && (pc->prot.ni1.invoke_id == id))
365 { /* Diversion successful */
366 free_invoke_id(st,pc->prot.ni1.invoke_id);
367 pc->prot.ni1.remote_result = 0; /* success */
368 pc->prot.ni1.invoke_id = 0;
369 pc->redir_result = pc->prot.ni1.remote_result;
370 st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */
371 else
372 l3_debug(st,"return error unknown identifier");
373 break;
374 case 3: /* return error */
375 err_ret = 0;
376 if (nlen < 2)
377 { l3_debug(st, "return error nlen < 2");
378 return;
379 }
380 if (*p != 0x02)
381 { /* result tag */
382 l3_debug(st, "invoke error tag !=0x02");
383 return;
384 }
385 p++;
386 nlen--;
387 if (*p > 4)
388 { /* length format */
389 l3_debug(st, "invoke return errlen > 4 ");
390 return;
391 }
392 ilen = *p++;
393 nlen--;
394 if (ilen > nlen || ilen == 0)
395 { l3_debug(st, "error return ilen > nlen || ilen == 0");
396 return;
397 }
398 nlen -= ilen;
399 while (ilen > 0)
400 { err_ret = (err_ret << 8) | (*p++ & 0xFF); /* error value */
401 ilen--;
402 }
403 /* if no process available handle separately */
404 if (!pc)
405 { if (cr == -1)
406 l3ni1_dummy_error_return(st, id, err_ret);
407 return;
408 }
409 if ((pc->prot.ni1.invoke_id) && (pc->prot.ni1.invoke_id == id))
410 { /* Deflection error */
411 free_invoke_id(st,pc->prot.ni1.invoke_id);
412 pc->prot.ni1.remote_result = err_ret; /* result */
413 pc->prot.ni1.invoke_id = 0;
414 pc->redir_result = pc->prot.ni1.remote_result;
415 st->l3.l3l4(st, CC_REDIR | INDICATION, pc);
416 } /* Deflection error */
417 else
418 l3_debug(st,"return result unknown identifier");
419 break;
420 default:
421 l3_debug(st, "facility default break tag=0x%02x",cp_tag);
422 break;
423 }
424}
425
426static void
427l3ni1_message(struct l3_process *pc, u_char mt)
428{
429 struct sk_buff *skb;
430 u_char *p;
431
432 if (!(skb = l3_alloc_skb(4)))
433 return;
434 p = skb_put(skb, 4);
435 MsgHead(p, pc->callref, mt);
436 l3_msg(pc->st, DL_DATA | REQUEST, skb);
437}
438
439static void
440l3ni1_message_plus_chid(struct l3_process *pc, u_char mt)
441/* sends an l3 messages plus channel id - added GE 05/09/00 */
442{
443 struct sk_buff *skb;
444 u_char tmp[16];
445 u_char *p = tmp;
446 u_char chid;
447
448 chid = (u_char)(pc->para.bchannel & 0x03) | 0x88;
449 MsgHead(p, pc->callref, mt);
450 *p++ = IE_CHANNEL_ID;
451 *p++ = 0x01;
452 *p++ = chid;
453
454 if (!(skb = l3_alloc_skb(7)))
455 return;
456 memcpy(skb_put(skb, 7), tmp, 7);
457 l3_msg(pc->st, DL_DATA | REQUEST, skb);
458}
459
460static void
461l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
462{
463 struct sk_buff *skb;
464 u_char tmp[16];
465 u_char *p = tmp;
466 int l;
467
468 MsgHead(p, pc->callref, mt);
469 *p++ = IE_CAUSE;
470 *p++ = 0x2;
471 *p++ = 0x80;
472 *p++ = cause | 0x80;
473
474 l = p - tmp;
475 if (!(skb = l3_alloc_skb(l)))
476 return;
477 memcpy(skb_put(skb, l), tmp, l);
478 l3_msg(pc->st, DL_DATA | REQUEST, skb);
479}
480
481static void
482l3ni1_status_send(struct l3_process *pc, u_char pr, void *arg)
483{
484 u_char tmp[16];
485 u_char *p = tmp;
486 int l;
487 struct sk_buff *skb;
488
489 MsgHead(p, pc->callref, MT_STATUS);
490
491 *p++ = IE_CAUSE;
492 *p++ = 0x2;
493 *p++ = 0x80;
494 *p++ = pc->para.cause | 0x80;
495
496 *p++ = IE_CALL_STATE;
497 *p++ = 0x1;
498 *p++ = pc->state & 0x3f;
499
500 l = p - tmp;
501 if (!(skb = l3_alloc_skb(l)))
502 return;
503 memcpy(skb_put(skb, l), tmp, l);
504 l3_msg(pc->st, DL_DATA | REQUEST, skb);
505}
506
507static void
508l3ni1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
509{
510 /* This routine is called if here was no SETUP made (checks in ni1up and in
511 * l3ni1_setup) and a RELEASE_COMPLETE have to be sent with an error code
512 * MT_STATUS_ENQUIRE in the NULL state is handled too
513 */
514 u_char tmp[16];
515 u_char *p = tmp;
516 int l;
517 struct sk_buff *skb;
518
519 switch (pc->para.cause) {
520 case 81: /* invalid callreference */
521 case 88: /* incomp destination */
522 case 96: /* mandory IE missing */
523 case 100: /* invalid IE contents */
524 case 101: /* incompatible Callstate */
525 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
526 *p++ = IE_CAUSE;
527 *p++ = 0x2;
528 *p++ = 0x80;
529 *p++ = pc->para.cause | 0x80;
530 break;
531 default:
532 printk(KERN_ERR "HiSax l3ni1_msg_without_setup wrong cause %d\n",
533 pc->para.cause);
534 return;
535 }
536 l = p - tmp;
537 if (!(skb = l3_alloc_skb(l)))
538 return;
539 memcpy(skb_put(skb, l), tmp, l);
540 l3_msg(pc->st, DL_DATA | REQUEST, skb);
541 ni1_release_l3_process(pc);
542}
543
544static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
545 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
546 IE_USER_USER, -1};
547static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
548 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
549static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
550 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
551 IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
552static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
553static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
554 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
555static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
556 IE_CALLED_PN, -1};
557static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
558static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
559 IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
560static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
561 IE_SIGNAL, IE_USER_USER, -1};
562/* a RELEASE_COMPLETE with errors don't require special actions
563static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
564*/
565static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
566 IE_DISPLAY, -1};
567static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
568static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY,
569 IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
570 IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
571 IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
572 IE_LLC, IE_HLC, IE_USER_USER, -1};
573static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
574 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
575static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
576 IE_MANDATORY, IE_DISPLAY, -1};
577static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
578static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
579static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
580/* not used
581 * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
582 * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
583 * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
584 * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
585 * IE_MANDATORY, -1};
586 */
587static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
588static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
589static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
590
591struct ie_len {
592 int ie;
593 int len;
594};
595
596static
597struct ie_len max_ie_len[] = {
598 {IE_SEGMENT, 4},
599 {IE_BEARER, 12},
600 {IE_CAUSE, 32},
601 {IE_CALL_ID, 10},
602 {IE_CALL_STATE, 3},
603 {IE_CHANNEL_ID, 34},
604 {IE_FACILITY, 255},
605 {IE_PROGRESS, 4},
606 {IE_NET_FAC, 255},
607 {IE_NOTIFY, 3},
608 {IE_DISPLAY, 82},
609 {IE_DATE, 8},
610 {IE_KEYPAD, 34},
611 {IE_SIGNAL, 3},
612 {IE_INFORATE, 6},
613 {IE_E2E_TDELAY, 11},
614 {IE_TDELAY_SEL, 5},
615 {IE_PACK_BINPARA, 3},
616 {IE_PACK_WINSIZE, 4},
617 {IE_PACK_SIZE, 4},
618 {IE_CUG, 7},
619 {IE_REV_CHARGE, 3},
620 {IE_CALLING_PN, 24},
621 {IE_CALLING_SUB, 23},
622 {IE_CALLED_PN, 24},
623 {IE_CALLED_SUB, 23},
624 {IE_REDIR_NR, 255},
625 {IE_TRANS_SEL, 255},
626 {IE_RESTART_IND, 3},
627 {IE_LLC, 18},
628 {IE_HLC, 5},
629 {IE_USER_USER, 131},
630 {-1,0},
631};
632
633static int
634getmax_ie_len(u_char ie) {
635 int i = 0;
636 while (max_ie_len[i].ie != -1) {
637 if (max_ie_len[i].ie == ie)
638 return(max_ie_len[i].len);
639 i++;
640 }
641 return(255);
642}
643
644static int
645ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
646 int ret = 1;
647
648 while (*checklist != -1) {
649 if ((*checklist & 0xff) == ie) {
650 if (ie & 0x80)
651 return(-ret);
652 else
653 return(ret);
654 }
655 ret++;
656 checklist++;
657 }
658 return(0);
659}
660
661static int
662check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
663{
664 int *cl = checklist;
665 u_char mt;
666 u_char *p, ie;
667 int l, newpos, oldpos;
668 int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
669 u_char codeset = 0;
670 u_char old_codeset = 0;
671 u_char codelock = 1;
672
673 p = skb->data;
674 /* skip cr */
675 p++;
676 l = (*p++) & 0xf;
677 p += l;
678 mt = *p++;
679 oldpos = 0;
680 while ((p - skb->data) < skb->len) {
681 if ((*p & 0xf0) == 0x90) { /* shift codeset */
682 old_codeset = codeset;
683 codeset = *p & 7;
684 if (*p & 0x08)
685 codelock = 0;
686 else
687 codelock = 1;
688 if (pc->debug & L3_DEB_CHECK)
689 l3_debug(pc->st, "check IE shift%scodeset %d->%d",
690 codelock ? " locking ": " ", old_codeset, codeset);
691 p++;
692 continue;
693 }
694 if (!codeset) { /* only codeset 0 */
695 if ((newpos = ie_in_set(pc, *p, cl))) {
696 if (newpos > 0) {
697 if (newpos < oldpos)
698 err_seq++;
699 else
700 oldpos = newpos;
701 }
702 } else {
703 if (ie_in_set(pc, *p, comp_required))
704 err_compr++;
705 else
706 err_ureg++;
707 }
708 }
709 ie = *p++;
710 if (ie & 0x80) {
711 l = 1;
712 } else {
713 l = *p++;
714 p += l;
715 l += 2;
716 }
717 if (!codeset && (l > getmax_ie_len(ie)))
718 err_len++;
719 if (!codelock) {
720 if (pc->debug & L3_DEB_CHECK)
721 l3_debug(pc->st, "check IE shift back codeset %d->%d",
722 codeset, old_codeset);
723 codeset = old_codeset;
724 codelock = 1;
725 }
726 }
727 if (err_compr | err_ureg | err_len | err_seq) {
728 if (pc->debug & L3_DEB_CHECK)
729 l3_debug(pc->st, "check IE MT(%x) %d/%d/%d/%d",
730 mt, err_compr, err_ureg, err_len, err_seq);
731 if (err_compr)
732 return(ERR_IE_COMPREHENSION);
733 if (err_ureg)
734 return(ERR_IE_UNRECOGNIZED);
735 if (err_len)
736 return(ERR_IE_LENGTH);
737 if (err_seq)
738 return(ERR_IE_SEQUENCE);
739 }
740 return(0);
741}
742
743/* verify if a message type exists and contain no IE error */
744static int
745l3ni1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
746{
747 switch (mt) {
748 case MT_ALERTING:
749 case MT_CALL_PROCEEDING:
750 case MT_CONNECT:
751 case MT_CONNECT_ACKNOWLEDGE:
752 case MT_DISCONNECT:
753 case MT_INFORMATION:
754 case MT_FACILITY:
755 case MT_NOTIFY:
756 case MT_PROGRESS:
757 case MT_RELEASE:
758 case MT_RELEASE_COMPLETE:
759 case MT_SETUP:
760 case MT_SETUP_ACKNOWLEDGE:
761 case MT_RESUME_ACKNOWLEDGE:
762 case MT_RESUME_REJECT:
763 case MT_SUSPEND_ACKNOWLEDGE:
764 case MT_SUSPEND_REJECT:
765 case MT_USER_INFORMATION:
766 case MT_RESTART:
767 case MT_RESTART_ACKNOWLEDGE:
768 case MT_CONGESTION_CONTROL:
769 case MT_STATUS:
770 case MT_STATUS_ENQUIRY:
771 if (pc->debug & L3_DEB_CHECK)
772 l3_debug(pc->st, "l3ni1_check_messagetype_validity mt(%x) OK", mt);
773 break;
774 case MT_RESUME: /* RESUME only in user->net */
775 case MT_SUSPEND: /* SUSPEND only in user->net */
776 default:
777 if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
778 l3_debug(pc->st, "l3ni1_check_messagetype_validity mt(%x) fail", mt);
779 pc->para.cause = 97;
780 l3ni1_status_send(pc, 0, NULL);
781 return(1);
782 }
783 return(0);
784}
785
786static void
787l3ni1_std_ie_err(struct l3_process *pc, int ret) {
788
789 if (pc->debug & L3_DEB_CHECK)
790 l3_debug(pc->st, "check_infoelements ret %d", ret);
791 switch(ret) {
792 case 0:
793 break;
794 case ERR_IE_COMPREHENSION:
795 pc->para.cause = 96;
796 l3ni1_status_send(pc, 0, NULL);
797 break;
798 case ERR_IE_UNRECOGNIZED:
799 pc->para.cause = 99;
800 l3ni1_status_send(pc, 0, NULL);
801 break;
802 case ERR_IE_LENGTH:
803 pc->para.cause = 100;
804 l3ni1_status_send(pc, 0, NULL);
805 break;
806 case ERR_IE_SEQUENCE:
807 default:
808 break;
809 }
810}
811
812static int
813l3ni1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
814 u_char *p;
815
816 p = skb->data;
817 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
818 p++;
819 if (*p != 1) { /* len for BRI = 1 */
820 if (pc->debug & L3_DEB_WARN)
821 l3_debug(pc->st, "wrong chid len %d", *p);
822 return (-2);
823 }
824 p++;
825 if (*p & 0x60) { /* only base rate interface */
826 if (pc->debug & L3_DEB_WARN)
827 l3_debug(pc->st, "wrong chid %x", *p);
828 return (-3);
829 }
830 return(*p & 0x3);
831 } else
832 return(-1);
833}
834
835static int
836l3ni1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
837 u_char l, i=0;
838 u_char *p;
839
840 p = skb->data;
841 pc->para.cause = 31;
842 pc->para.loc = 0;
843 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
844 p++;
845 l = *p++;
846 if (l>30)
847 return(1);
848 if (l) {
849 pc->para.loc = *p++;
850 l--;
851 } else {
852 return(2);
853 }
854 if (l && !(pc->para.loc & 0x80)) {
855 l--;
856 p++; /* skip recommendation */
857 }
858 if (l) {
859 pc->para.cause = *p++;
860 l--;
861 if (!(pc->para.cause & 0x80))
862 return(3);
863 } else
864 return(4);
865 while (l && (i<6)) {
866 pc->para.diag[i++] = *p++;
867 l--;
868 }
869 } else
870 return(-1);
871 return(0);
872}
873
874static void
875l3ni1_msg_with_uus(struct l3_process *pc, u_char cmd)
876{
877 struct sk_buff *skb;
878 u_char tmp[16+40];
879 u_char *p = tmp;
880 int l;
881
882 MsgHead(p, pc->callref, cmd);
883
884 if (pc->prot.ni1.uus1_data[0])
885 { *p++ = IE_USER_USER; /* UUS info element */
886 *p++ = strlen(pc->prot.ni1.uus1_data) + 1;
887 *p++ = 0x04; /* IA5 chars */
888 strcpy(p,pc->prot.ni1.uus1_data);
889 p += strlen(pc->prot.ni1.uus1_data);
890 pc->prot.ni1.uus1_data[0] = '\0';
891 }
892
893 l = p - tmp;
894 if (!(skb = l3_alloc_skb(l)))
895 return;
896 memcpy(skb_put(skb, l), tmp, l);
897 l3_msg(pc->st, DL_DATA | REQUEST, skb);
898} /* l3ni1_msg_with_uus */
899
900static void
901l3ni1_release_req(struct l3_process *pc, u_char pr, void *arg)
902{
903 StopAllL3Timer(pc);
904 newl3state(pc, 19);
905 if (!pc->prot.ni1.uus1_data[0])
906 l3ni1_message(pc, MT_RELEASE);
907 else
908 l3ni1_msg_with_uus(pc, MT_RELEASE);
909 L3AddTimer(&pc->timer, T308, CC_T308_1);
910}
911
912static void
913l3ni1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
914{
915 struct sk_buff *skb = arg;
916 int ret;
917
918 if ((ret = l3ni1_get_cause(pc, skb))>0) {
919 if (pc->debug & L3_DEB_WARN)
920 l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
921 } else if (ret < 0)
922 pc->para.cause = NO_CAUSE;
923 StopAllL3Timer(pc);
924 newl3state(pc, 0);
925 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
926 ni1_release_l3_process(pc);
927}
928
929#if EXT_BEARER_CAPS
930
931static u_char *
932EncodeASyncParams(u_char * p, u_char si2)
933{ // 7c 06 88 90 21 42 00 bb
934
935 p[0] = 0;
936 p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19
937 p[2] = 0x80;
938 if (si2 & 32) // 7 data bits
939
940 p[2] += 16;
941 else // 8 data bits
942
943 p[2] += 24;
944
945 if (si2 & 16) // 2 stop bits
946
947 p[2] += 96;
948 else // 1 stop bit
949
950 p[2] += 32;
951
952 if (si2 & 8) // even parity
953
954 p[2] += 2;
955 else // no parity
956
957 p[2] += 3;
958
959 switch (si2 & 0x07) {
960 case 0:
961 p[0] = 66; // 1200 bit/s
962
963 break;
964 case 1:
965 p[0] = 88; // 1200/75 bit/s
966
967 break;
968 case 2:
969 p[0] = 87; // 75/1200 bit/s
970
971 break;
972 case 3:
973 p[0] = 67; // 2400 bit/s
974
975 break;
976 case 4:
977 p[0] = 69; // 4800 bit/s
978
979 break;
980 case 5:
981 p[0] = 72; // 9600 bit/s
982
983 break;
984 case 6:
985 p[0] = 73; // 14400 bit/s
986
987 break;
988 case 7:
989 p[0] = 75; // 19200 bit/s
990
991 break;
992 }
993 return p + 3;
994}
995
996static u_char
997EncodeSyncParams(u_char si2, u_char ai)
998{
999
1000 switch (si2) {
1001 case 0:
1002 return ai + 2; // 1200 bit/s
1003
1004 case 1:
1005 return ai + 24; // 1200/75 bit/s
1006
1007 case 2:
1008 return ai + 23; // 75/1200 bit/s
1009
1010 case 3:
1011 return ai + 3; // 2400 bit/s
1012
1013 case 4:
1014 return ai + 5; // 4800 bit/s
1015
1016 case 5:
1017 return ai + 8; // 9600 bit/s
1018
1019 case 6:
1020 return ai + 9; // 14400 bit/s
1021
1022 case 7:
1023 return ai + 11; // 19200 bit/s
1024
1025 case 8:
1026 return ai + 14; // 48000 bit/s
1027
1028 case 9:
1029 return ai + 15; // 56000 bit/s
1030
1031 case 15:
1032 return ai + 40; // negotiate bit/s
1033
1034 default:
1035 break;
1036 }
1037 return ai;
1038}
1039
1040
1041static u_char
1042DecodeASyncParams(u_char si2, u_char * p)
1043{
1044 u_char info;
1045
1046 switch (p[5]) {
1047 case 66: // 1200 bit/s
1048
1049 break; // si2 don't change
1050
1051 case 88: // 1200/75 bit/s
1052
1053 si2 += 1;
1054 break;
1055 case 87: // 75/1200 bit/s
1056
1057 si2 += 2;
1058 break;
1059 case 67: // 2400 bit/s
1060
1061 si2 += 3;
1062 break;
1063 case 69: // 4800 bit/s
1064
1065 si2 += 4;
1066 break;
1067 case 72: // 9600 bit/s
1068
1069 si2 += 5;
1070 break;
1071 case 73: // 14400 bit/s
1072
1073 si2 += 6;
1074 break;
1075 case 75: // 19200 bit/s
1076
1077 si2 += 7;
1078 break;
1079 }
1080
1081 info = p[7] & 0x7f;
1082 if ((info & 16) && (!(info & 8))) // 7 data bits
1083
1084 si2 += 32; // else 8 data bits
1085
1086 if ((info & 96) == 96) // 2 stop bits
1087
1088 si2 += 16; // else 1 stop bit
1089
1090 if ((info & 2) && (!(info & 1))) // even parity
1091
1092 si2 += 8; // else no parity
1093
1094 return si2;
1095}
1096
1097
1098static u_char
1099DecodeSyncParams(u_char si2, u_char info)
1100{
1101 info &= 0x7f;
1102 switch (info) {
1103 case 40: // bit/s negotiation failed ai := 165 not 175!
1104
1105 return si2 + 15;
1106 case 15: // 56000 bit/s failed, ai := 0 not 169 !
1107
1108 return si2 + 9;
1109 case 14: // 48000 bit/s
1110
1111 return si2 + 8;
1112 case 11: // 19200 bit/s
1113
1114 return si2 + 7;
1115 case 9: // 14400 bit/s
1116
1117 return si2 + 6;
1118 case 8: // 9600 bit/s
1119
1120 return si2 + 5;
1121 case 5: // 4800 bit/s
1122
1123 return si2 + 4;
1124 case 3: // 2400 bit/s
1125
1126 return si2 + 3;
1127 case 23: // 75/1200 bit/s
1128
1129 return si2 + 2;
1130 case 24: // 1200/75 bit/s
1131
1132 return si2 + 1;
1133 default: // 1200 bit/s
1134
1135 return si2;
1136 }
1137}
1138
1139static u_char
1140DecodeSI2(struct sk_buff *skb)
1141{
1142 u_char *p; //, *pend=skb->data + skb->len;
1143
1144 if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
1145 switch (p[4] & 0x0f) {
1146 case 0x01:
1147 if (p[1] == 0x04) // sync. Bitratenadaption
1148
1149 return DecodeSyncParams(160, p[5]); // V.110/X.30
1150
1151 else if (p[1] == 0x06) // async. Bitratenadaption
1152
1153 return DecodeASyncParams(192, p); // V.110/X.30
1154
1155 break;
1156 case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
1157 if (p[1] > 3)
1158 return DecodeSyncParams(176, p[5]); // V.120
1159 break;
1160 }
1161 }
1162 return 0;
1163}
1164
1165#endif
1166
1167
1168static void
1169l3ni1_setup_req(struct l3_process *pc, u_char pr,
1170 void *arg)
1171{
1172 struct sk_buff *skb;
1173 u_char tmp[128];
1174 u_char *p = tmp;
1175
1176 u_char *teln;
1177 u_char *sub;
1178 u_char *sp;
1179 int l;
1180
1181 MsgHead(p, pc->callref, MT_SETUP);
1182
1183 teln = pc->para.setup.phone;
1184
1185 *p++ = 0xa1; /* complete indicator */
1186 /*
1187 * Set Bearer Capability, Map info from 1TR6-convention to NI1
1188 */
1189 switch (pc->para.setup.si1) {
1190 case 1: /* Telephony */
1191 *p++ = IE_BEARER;
1192 *p++ = 0x3; /* Length */
1193 *p++ = 0x90; /* 3.1khz Audio */
1194 *p++ = 0x90; /* Circuit-Mode 64kbps */
1195 *p++ = 0xa2; /* u-Law Audio */
1196 break;
1197 case 5: /* Datatransmission 64k, BTX */
1198 case 7: /* Datatransmission 64k */
1199 default:
1200 *p++ = IE_BEARER;
1201 *p++ = 0x2; /* Length */
1202 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1203 *p++ = 0x90; /* Circuit-Mode 64kbps */
1204 break;
1205 }
1206
1207 sub = NULL;
1208 sp = teln;
1209 while (*sp) {
1210 if ('.' == *sp) {
1211 sub = sp;
1212 *sp = 0;
1213 } else
1214 sp++;
1215 }
1216
1217 *p++ = IE_KEYPAD;
1218 *p++ = strlen(teln);
1219 while (*teln)
1220 *p++ = (*teln++) & 0x7F;
1221
1222 if (sub)
1223 *sub++ = '.';
1224
1225#if EXT_BEARER_CAPS
1226 if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
1227
1228 *p++ = IE_LLC;
1229 *p++ = 0x04;
1230 *p++ = 0x88;
1231 *p++ = 0x90;
1232 *p++ = 0x21;
1233 *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
1234 } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120
1235
1236 *p++ = IE_LLC;
1237 *p++ = 0x05;
1238 *p++ = 0x88;
1239 *p++ = 0x90;
1240 *p++ = 0x28;
1241 *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
1242 *p++ = 0x82;
1243 } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30
1244
1245 *p++ = IE_LLC;
1246 *p++ = 0x06;
1247 *p++ = 0x88;
1248 *p++ = 0x90;
1249 *p++ = 0x21;
1250 p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
1251 } else {
1252 switch (pc->para.setup.si1) {
1253 case 1: /* Telephony */
1254 *p++ = IE_LLC;
1255 *p++ = 0x3; /* Length */
1256 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1257 *p++ = 0x90; /* Circuit-Mode 64kbps */
1258 *p++ = 0xa2; /* u-Law Audio */
1259 break;
1260 case 5: /* Datatransmission 64k, BTX */
1261 case 7: /* Datatransmission 64k */
1262 default:
1263 *p++ = IE_LLC;
1264 *p++ = 0x2; /* Length */
1265 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1266 *p++ = 0x90; /* Circuit-Mode 64kbps */
1267 break;
1268 }
1269 }
1270#endif
1271 l = p - tmp;
1272 if (!(skb = l3_alloc_skb(l)))
1273{
1274 return;
1275}
1276 memcpy(skb_put(skb, l), tmp, l);
1277 L3DelTimer(&pc->timer);
1278 L3AddTimer(&pc->timer, T303, CC_T303);
1279 newl3state(pc, 1);
1280 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1281}
1282
1283static void
1284l3ni1_call_proc(struct l3_process *pc, u_char pr, void *arg)
1285{
1286 struct sk_buff *skb = arg;
1287 int id, ret;
1288
1289 if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) {
1290 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1291 if (pc->debug & L3_DEB_WARN)
1292 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1293 pc->para.cause = 100;
1294 l3ni1_status_send(pc, pr, NULL);
1295 return;
1296 }
1297 pc->para.bchannel = id;
1298 } else if (1 == pc->state) {
1299 if (pc->debug & L3_DEB_WARN)
1300 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1301 if (id == -1)
1302 pc->para.cause = 96;
1303 else
1304 pc->para.cause = 100;
1305 l3ni1_status_send(pc, pr, NULL);
1306 return;
1307 }
1308 /* Now we are on none mandatory IEs */
1309 ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
1310 if (ERR_IE_COMPREHENSION == ret) {
1311 l3ni1_std_ie_err(pc, ret);
1312 return;
1313 }
1314 L3DelTimer(&pc->timer);
1315 newl3state(pc, 3);
1316 L3AddTimer(&pc->timer, T310, CC_T310);
1317 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1318 l3ni1_std_ie_err(pc, ret);
1319 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
1320}
1321
1322static void
1323l3ni1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
1324{
1325 struct sk_buff *skb = arg;
1326 int id, ret;
1327
1328 if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) {
1329 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1330 if (pc->debug & L3_DEB_WARN)
1331 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1332 pc->para.cause = 100;
1333 l3ni1_status_send(pc, pr, NULL);
1334 return;
1335 }
1336 pc->para.bchannel = id;
1337 } else {
1338 if (pc->debug & L3_DEB_WARN)
1339 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1340 if (id == -1)
1341 pc->para.cause = 96;
1342 else
1343 pc->para.cause = 100;
1344 l3ni1_status_send(pc, pr, NULL);
1345 return;
1346 }
1347 /* Now we are on none mandatory IEs */
1348 ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
1349 if (ERR_IE_COMPREHENSION == ret) {
1350 l3ni1_std_ie_err(pc, ret);
1351 return;
1352 }
1353 L3DelTimer(&pc->timer);
1354 newl3state(pc, 2);
1355 L3AddTimer(&pc->timer, T304, CC_T304);
1356 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1357 l3ni1_std_ie_err(pc, ret);
1358 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1359}
1360
1361static void
1362l3ni1_disconnect(struct l3_process *pc, u_char pr, void *arg)
1363{
1364 struct sk_buff *skb = arg;
1365 u_char *p;
1366 int ret;
1367 u_char cause = 0;
1368
1369 StopAllL3Timer(pc);
1370 if ((ret = l3ni1_get_cause(pc, skb))) {
1371 if (pc->debug & L3_DEB_WARN)
1372 l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
1373 if (ret < 0)
1374 cause = 96;
1375 else if (ret > 0)
1376 cause = 100;
1377 }
1378 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
1379 l3ni1_parse_facility(pc->st, pc, pc->callref, p);
1380 ret = check_infoelements(pc, skb, ie_DISCONNECT);
1381 if (ERR_IE_COMPREHENSION == ret)
1382 cause = 96;
1383 else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
1384 cause = 99;
1385 ret = pc->state;
1386 newl3state(pc, 12);
1387 if (cause)
1388 newl3state(pc, 19);
1389 if (11 != ret)
1390 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
1391 else if (!cause)
1392 l3ni1_release_req(pc, pr, NULL);
1393 if (cause) {
1394 l3ni1_message_cause(pc, MT_RELEASE, cause);
1395 L3AddTimer(&pc->timer, T308, CC_T308_1);
1396 }
1397}
1398
1399static void
1400l3ni1_connect(struct l3_process *pc, u_char pr, void *arg)
1401{
1402 struct sk_buff *skb = arg;
1403 int ret;
1404
1405 ret = check_infoelements(pc, skb, ie_CONNECT);
1406 if (ERR_IE_COMPREHENSION == ret) {
1407 l3ni1_std_ie_err(pc, ret);
1408 return;
1409 }
1410 L3DelTimer(&pc->timer); /* T310 */
1411 newl3state(pc, 10);
1412 pc->para.chargeinfo = 0;
1413 /* here should inserted COLP handling KKe */
1414 if (ret)
1415 l3ni1_std_ie_err(pc, ret);
1416 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
1417}
1418
1419static void
1420l3ni1_alerting(struct l3_process *pc, u_char pr, void *arg)
1421{
1422 struct sk_buff *skb = arg;
1423 int ret;
1424
1425 ret = check_infoelements(pc, skb, ie_ALERTING);
1426 if (ERR_IE_COMPREHENSION == ret) {
1427 l3ni1_std_ie_err(pc, ret);
1428 return;
1429 }
1430 L3DelTimer(&pc->timer); /* T304 */
1431 newl3state(pc, 4);
1432 if (ret)
1433 l3ni1_std_ie_err(pc, ret);
1434 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
1435}
1436
1437static void
1438l3ni1_setup(struct l3_process *pc, u_char pr, void *arg)
1439{
1440 u_char *p;
1441 int bcfound = 0;
1442 char tmp[80];
1443 struct sk_buff *skb = arg;
1444 int id;
1445 int err = 0;
1446
1447 /*
1448 * Bearer Capabilities
1449 */
1450 p = skb->data;
1451 /* only the first occurence 'll be detected ! */
1452 if ((p = findie(p, skb->len, 0x04, 0))) {
1453 if ((p[1] < 2) || (p[1] > 11))
1454 err = 1;
1455 else {
1456 pc->para.setup.si2 = 0;
1457 switch (p[2] & 0x7f) {
1458 case 0x00: /* Speech */
1459 case 0x10: /* 3.1 Khz audio */
1460 pc->para.setup.si1 = 1;
1461 break;
1462 case 0x08: /* Unrestricted digital information */
1463 pc->para.setup.si1 = 7;
1464/* JIM, 05.11.97 I wanna set service indicator 2 */
1465#if EXT_BEARER_CAPS
1466 pc->para.setup.si2 = DecodeSI2(skb);
1467#endif
1468 break;
1469 case 0x09: /* Restricted digital information */
1470 pc->para.setup.si1 = 2;
1471 break;
1472 case 0x11:
1473 /* Unrestr. digital information with
1474 * tones/announcements ( or 7 kHz audio
1475 */
1476 pc->para.setup.si1 = 3;
1477 break;
1478 case 0x18: /* Video */
1479 pc->para.setup.si1 = 4;
1480 break;
1481 default:
1482 err = 2;
1483 break;
1484 }
1485 switch (p[3] & 0x7f) {
1486 case 0x40: /* packed mode */
1487 pc->para.setup.si1 = 8;
1488 break;
1489 case 0x10: /* 64 kbit */
1490 case 0x11: /* 2*64 kbit */
1491 case 0x13: /* 384 kbit */
1492 case 0x15: /* 1536 kbit */
1493 case 0x17: /* 1920 kbit */
1494 pc->para.moderate = p[3] & 0x7f;
1495 break;
1496 default:
1497 err = 3;
1498 break;
1499 }
1500 }
1501 if (pc->debug & L3_DEB_SI)
1502 l3_debug(pc->st, "SI=%d, AI=%d",
1503 pc->para.setup.si1, pc->para.setup.si2);
1504 if (err) {
1505 if (pc->debug & L3_DEB_WARN)
1506 l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
1507 p[1], p[2], p[3]);
1508 pc->para.cause = 100;
1509 l3ni1_msg_without_setup(pc, pr, NULL);
1510 return;
1511 }
1512 } else {
1513 if (pc->debug & L3_DEB_WARN)
1514 l3_debug(pc->st, "setup without bearer capabilities");
1515 /* ETS 300-104 1.3.3 */
1516 pc->para.cause = 96;
1517 l3ni1_msg_without_setup(pc, pr, NULL);
1518 return;
1519 }
1520 /*
1521 * Channel Identification
1522 */
1523 if ((id = l3ni1_get_channel_id(pc, skb)) >= 0) {
1524 if ((pc->para.bchannel = id)) {
1525 if ((3 == id) && (0x10 == pc->para.moderate)) {
1526 if (pc->debug & L3_DEB_WARN)
1527 l3_debug(pc->st, "setup with wrong chid %x",
1528 id);
1529 pc->para.cause = 100;
1530 l3ni1_msg_without_setup(pc, pr, NULL);
1531 return;
1532 }
1533 bcfound++;
1534 } else
1535 { if (pc->debug & L3_DEB_WARN)
1536 l3_debug(pc->st, "setup without bchannel, call waiting");
1537 bcfound++;
1538 }
1539 } else {
1540 if (pc->debug & L3_DEB_WARN)
1541 l3_debug(pc->st, "setup with wrong chid ret %d", id);
1542 if (id == -1)
1543 pc->para.cause = 96;
1544 else
1545 pc->para.cause = 100;
1546 l3ni1_msg_without_setup(pc, pr, NULL);
1547 return;
1548 }
1549 /* Now we are on none mandatory IEs */
1550 err = check_infoelements(pc, skb, ie_SETUP);
1551 if (ERR_IE_COMPREHENSION == err) {
1552 pc->para.cause = 96;
1553 l3ni1_msg_without_setup(pc, pr, NULL);
1554 return;
1555 }
1556 p = skb->data;
1557 if ((p = findie(p, skb->len, 0x70, 0)))
1558 iecpy(pc->para.setup.eazmsn, p, 1);
1559 else
1560 pc->para.setup.eazmsn[0] = 0;
1561
1562 p = skb->data;
1563 if ((p = findie(p, skb->len, 0x71, 0))) {
1564 /* Called party subaddress */
1565 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1566 tmp[0] = '.';
1567 iecpy(&tmp[1], p, 2);
1568 strcat(pc->para.setup.eazmsn, tmp);
1569 } else if (pc->debug & L3_DEB_WARN)
1570 l3_debug(pc->st, "wrong called subaddress");
1571 }
1572 p = skb->data;
1573 if ((p = findie(p, skb->len, 0x6c, 0))) {
1574 pc->para.setup.plan = p[2];
1575 if (p[2] & 0x80) {
1576 iecpy(pc->para.setup.phone, p, 1);
1577 pc->para.setup.screen = 0;
1578 } else {
1579 iecpy(pc->para.setup.phone, p, 2);
1580 pc->para.setup.screen = p[3];
1581 }
1582 } else {
1583 pc->para.setup.phone[0] = 0;
1584 pc->para.setup.plan = 0;
1585 pc->para.setup.screen = 0;
1586 }
1587 p = skb->data;
1588 if ((p = findie(p, skb->len, 0x6d, 0))) {
1589 /* Calling party subaddress */
1590 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1591 tmp[0] = '.';
1592 iecpy(&tmp[1], p, 2);
1593 strcat(pc->para.setup.phone, tmp);
1594 } else if (pc->debug & L3_DEB_WARN)
1595 l3_debug(pc->st, "wrong calling subaddress");
1596 }
1597 newl3state(pc, 6);
1598 if (err) /* STATUS for none mandatory IE errors after actions are taken */
1599 l3ni1_std_ie_err(pc, err);
1600 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1601}
1602
1603static void
1604l3ni1_reset(struct l3_process *pc, u_char pr, void *arg)
1605{
1606 ni1_release_l3_process(pc);
1607}
1608
1609static void
1610l3ni1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1611{
1612 struct sk_buff *skb;
1613 u_char tmp[16+40];
1614 u_char *p = tmp;
1615 int l;
1616 u_char cause = 16;
1617
1618 if (pc->para.cause != NO_CAUSE)
1619 cause = pc->para.cause;
1620
1621 StopAllL3Timer(pc);
1622
1623 MsgHead(p, pc->callref, MT_DISCONNECT);
1624
1625 *p++ = IE_CAUSE;
1626 *p++ = 0x2;
1627 *p++ = 0x80;
1628 *p++ = cause | 0x80;
1629
1630 if (pc->prot.ni1.uus1_data[0])
1631 { *p++ = IE_USER_USER; /* UUS info element */
1632 *p++ = strlen(pc->prot.ni1.uus1_data) + 1;
1633 *p++ = 0x04; /* IA5 chars */
1634 strcpy(p,pc->prot.ni1.uus1_data);
1635 p += strlen(pc->prot.ni1.uus1_data);
1636 pc->prot.ni1.uus1_data[0] = '\0';
1637 }
1638
1639 l = p - tmp;
1640 if (!(skb = l3_alloc_skb(l)))
1641 return;
1642 memcpy(skb_put(skb, l), tmp, l);
1643 newl3state(pc, 11);
1644 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1645 L3AddTimer(&pc->timer, T305, CC_T305);
1646}
1647
1648static void
1649l3ni1_setup_rsp(struct l3_process *pc, u_char pr,
1650 void *arg)
1651{
1652 if (!pc->para.bchannel)
1653 { if (pc->debug & L3_DEB_WARN)
1654 l3_debug(pc->st, "D-chan connect for waiting call");
1655 l3ni1_disconnect_req(pc, pr, arg);
1656 return;
1657 }
1658 newl3state(pc, 8);
1659 if (pc->debug & L3_DEB_WARN)
1660 l3_debug(pc->st, "D-chan connect for waiting call");
1661 l3ni1_message_plus_chid(pc, MT_CONNECT); /* GE 05/09/00 */
1662 L3DelTimer(&pc->timer);
1663 L3AddTimer(&pc->timer, T313, CC_T313);
1664}
1665
1666static void
1667l3ni1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1668{
1669 struct sk_buff *skb = arg;
1670 int ret;
1671
1672 ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
1673 if (ERR_IE_COMPREHENSION == ret) {
1674 l3ni1_std_ie_err(pc, ret);
1675 return;
1676 }
1677 newl3state(pc, 10);
1678 L3DelTimer(&pc->timer);
1679 if (ret)
1680 l3ni1_std_ie_err(pc, ret);
1681 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1682}
1683
1684static void
1685l3ni1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1686{
1687 struct sk_buff *skb;
1688 u_char tmp[16];
1689 u_char *p = tmp;
1690 int l;
1691 u_char cause = 21;
1692
1693 if (pc->para.cause != NO_CAUSE)
1694 cause = pc->para.cause;
1695
1696 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1697
1698 *p++ = IE_CAUSE;
1699 *p++ = 0x2;
1700 *p++ = 0x80;
1701 *p++ = cause | 0x80;
1702
1703 l = p - tmp;
1704 if (!(skb = l3_alloc_skb(l)))
1705 return;
1706 memcpy(skb_put(skb, l), tmp, l);
1707 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1708 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1709 newl3state(pc, 0);
1710 ni1_release_l3_process(pc);
1711}
1712
1713static void
1714l3ni1_release(struct l3_process *pc, u_char pr, void *arg)
1715{
1716 struct sk_buff *skb = arg;
1717 u_char *p;
1718 int ret, cause=0;
1719
1720 StopAllL3Timer(pc);
1721 if ((ret = l3ni1_get_cause(pc, skb))>0) {
1722 if (pc->debug & L3_DEB_WARN)
1723 l3_debug(pc->st, "REL get_cause ret(%d)", ret);
1724 } else if (ret<0)
1725 pc->para.cause = NO_CAUSE;
1726 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
1727 l3ni1_parse_facility(pc->st, pc, pc->callref, p);
1728 }
1729 if ((ret<0) && (pc->state != 11))
1730 cause = 96;
1731 else if (ret>0)
1732 cause = 100;
1733 ret = check_infoelements(pc, skb, ie_RELEASE);
1734 if (ERR_IE_COMPREHENSION == ret)
1735 cause = 96;
1736 else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
1737 cause = 99;
1738 if (cause)
1739 l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
1740 else
1741 l3ni1_message(pc, MT_RELEASE_COMPLETE);
1742 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1743 newl3state(pc, 0);
1744 ni1_release_l3_process(pc);
1745}
1746
1747static void
1748l3ni1_alert_req(struct l3_process *pc, u_char pr,
1749 void *arg)
1750{
1751 newl3state(pc, 7);
1752 if (!pc->prot.ni1.uus1_data[0])
1753 l3ni1_message(pc, MT_ALERTING);
1754 else
1755 l3ni1_msg_with_uus(pc, MT_ALERTING);
1756}
1757
1758static void
1759l3ni1_proceed_req(struct l3_process *pc, u_char pr,
1760 void *arg)
1761{
1762 newl3state(pc, 9);
1763 l3ni1_message(pc, MT_CALL_PROCEEDING);
1764 pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc);
1765}
1766
1767static void
1768l3ni1_setup_ack_req(struct l3_process *pc, u_char pr,
1769 void *arg)
1770{
1771 newl3state(pc, 25);
1772 L3DelTimer(&pc->timer);
1773 L3AddTimer(&pc->timer, T302, CC_T302);
1774 l3ni1_message(pc, MT_SETUP_ACKNOWLEDGE);
1775}
1776
1777/********************************************/
1778/* deliver a incoming display message to HL */
1779/********************************************/
1780static void
1781l3ni1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
1782{ u_char len;
1783 isdn_ctrl ic;
1784 struct IsdnCardState *cs;
1785 char *p;
1786
1787 if (*infp++ != IE_DISPLAY) return;
1788 if ((len = *infp++) > 80) return; /* total length <= 82 */
1789 if (!pc->chan) return;
1790
1791 p = ic.parm.display;
1792 while (len--)
1793 *p++ = *infp++;
1794 *p = '\0';
1795 ic.command = ISDN_STAT_DISPLAY;
1796 cs = pc->st->l1.hardware;
1797 ic.driver = cs->myid;
1798 ic.arg = pc->chan->chan;
1799 cs->iif.statcallb(&ic);
1800} /* l3ni1_deliver_display */
1801
1802
1803static void
1804l3ni1_progress(struct l3_process *pc, u_char pr, void *arg)
1805{
1806 struct sk_buff *skb = arg;
1807 int err = 0;
1808 u_char *p;
1809
1810 if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
1811 if (p[1] != 2) {
1812 err = 1;
1813 pc->para.cause = 100;
1814 } else if (!(p[2] & 0x70)) {
1815 switch (p[2]) {
1816 case 0x80:
1817 case 0x81:
1818 case 0x82:
1819 case 0x84:
1820 case 0x85:
1821 case 0x87:
1822 case 0x8a:
1823 switch (p[3]) {
1824 case 0x81:
1825 case 0x82:
1826 case 0x83:
1827 case 0x84:
1828 case 0x88:
1829 break;
1830 default:
1831 err = 2;
1832 pc->para.cause = 100;
1833 break;
1834 }
1835 break;
1836 default:
1837 err = 3;
1838 pc->para.cause = 100;
1839 break;
1840 }
1841 }
1842 } else {
1843 pc->para.cause = 96;
1844 err = 4;
1845 }
1846 if (err) {
1847 if (pc->debug & L3_DEB_WARN)
1848 l3_debug(pc->st, "progress error %d", err);
1849 l3ni1_status_send(pc, pr, NULL);
1850 return;
1851 }
1852 /* Now we are on none mandatory IEs */
1853 err = check_infoelements(pc, skb, ie_PROGRESS);
1854 if (err)
1855 l3ni1_std_ie_err(pc, err);
1856 if (ERR_IE_COMPREHENSION != err)
1857 pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
1858}
1859
1860static void
1861l3ni1_notify(struct l3_process *pc, u_char pr, void *arg)
1862{
1863 struct sk_buff *skb = arg;
1864 int err = 0;
1865 u_char *p;
1866
1867 if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
1868 if (p[1] != 1) {
1869 err = 1;
1870 pc->para.cause = 100;
1871 } else {
1872 switch (p[2]) {
1873 case 0x80:
1874 case 0x81:
1875 case 0x82:
1876 break;
1877 default:
1878 pc->para.cause = 100;
1879 err = 2;
1880 break;
1881 }
1882 }
1883 } else {
1884 pc->para.cause = 96;
1885 err = 3;
1886 }
1887 if (err) {
1888 if (pc->debug & L3_DEB_WARN)
1889 l3_debug(pc->st, "notify error %d", err);
1890 l3ni1_status_send(pc, pr, NULL);
1891 return;
1892 }
1893 /* Now we are on none mandatory IEs */
1894 err = check_infoelements(pc, skb, ie_NOTIFY);
1895 if (err)
1896 l3ni1_std_ie_err(pc, err);
1897 if (ERR_IE_COMPREHENSION != err)
1898 pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
1899}
1900
1901static void
1902l3ni1_status_enq(struct l3_process *pc, u_char pr, void *arg)
1903{
1904 int ret;
1905 struct sk_buff *skb = arg;
1906
1907 ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
1908 l3ni1_std_ie_err(pc, ret);
1909 pc->para.cause = 30; /* response to STATUS_ENQUIRY */
1910 l3ni1_status_send(pc, pr, NULL);
1911}
1912
1913static void
1914l3ni1_information(struct l3_process *pc, u_char pr, void *arg)
1915{
1916 int ret;
1917 struct sk_buff *skb = arg;
1918 u_char *p;
1919 char tmp[32];
1920
1921 ret = check_infoelements(pc, skb, ie_INFORMATION);
1922 if (ret)
1923 l3ni1_std_ie_err(pc, ret);
1924 if (pc->state == 25) { /* overlap receiving */
1925 L3DelTimer(&pc->timer);
1926 p = skb->data;
1927 if ((p = findie(p, skb->len, 0x70, 0))) {
1928 iecpy(tmp, p, 1);
1929 strcat(pc->para.setup.eazmsn, tmp);
1930 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1931 }
1932 L3AddTimer(&pc->timer, T302, CC_T302);
1933 }
1934}
1935
1936/******************************/
1937/* handle deflection requests */
1938/******************************/
1939static void l3ni1_redir_req(struct l3_process *pc, u_char pr, void *arg)
1940{
1941 struct sk_buff *skb;
1942 u_char tmp[128];
1943 u_char *p = tmp;
1944 u_char *subp;
1945 u_char len_phone = 0;
1946 u_char len_sub = 0;
1947 int l;
1948
1949
1950 strcpy(pc->prot.ni1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
1951 if (!pc->chan->setup.phone[0])
1952 { pc->para.cause = -1;
1953 l3ni1_disconnect_req(pc,pr,arg); /* disconnect immediately */
1954 return;
1955 } /* only uus */
1956
1957 if (pc->prot.ni1.invoke_id)
1958 free_invoke_id(pc->st,pc->prot.ni1.invoke_id);
1959
1960 if (!(pc->prot.ni1.invoke_id = new_invoke_id(pc->st)))
1961 return;
1962
1963 MsgHead(p, pc->callref, MT_FACILITY);
1964
1965 for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
1966 if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subaddress element */
1967
1968 *p++ = 0x1c; /* Facility info element */
1969 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
1970 *p++ = 0x91; /* remote operations protocol */
1971 *p++ = 0xa1; /* invoke component */
1972
1973 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
1974 *p++ = 0x02; /* invoke id tag, integer */
1975 *p++ = 0x01; /* length */
1976 *p++ = pc->prot.ni1.invoke_id; /* invoke id */
1977 *p++ = 0x02; /* operation value tag, integer */
1978 *p++ = 0x01; /* length */
1979 *p++ = 0x0D; /* Call Deflect */
1980
1981 *p++ = 0x30; /* sequence phone number */
1982 *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
1983
1984 *p++ = 0x30; /* Deflected to UserNumber */
1985 *p++ = len_phone+2+len_sub; /* length */
1986 *p++ = 0x80; /* NumberDigits */
1987 *p++ = len_phone; /* length */
1988 for (l = 0; l < len_phone; l++)
1989 *p++ = pc->chan->setup.phone[l];
1990
1991 if (len_sub)
1992 { *p++ = 0x04; /* called party subaddress */
1993 *p++ = len_sub - 2;
1994 while (*subp) *p++ = *subp++;
1995 }
1996
1997 *p++ = 0x01; /* screening identifier */
1998 *p++ = 0x01;
1999 *p++ = pc->chan->setup.screen;
2000
2001 l = p - tmp;
2002 if (!(skb = l3_alloc_skb(l))) return;
2003 memcpy(skb_put(skb, l), tmp, l);
2004
2005 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2006} /* l3ni1_redir_req */
2007
2008/********************************************/
2009/* handle deflection request in early state */
2010/********************************************/
2011static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
2012{
2013 l3ni1_proceed_req(pc,pr,arg);
2014 l3ni1_redir_req(pc,pr,arg);
2015} /* l3ni1_redir_req_early */
2016
2017/***********************************************/
2018/* handle special commands for this protocol. */
2019/* Examples are call independant services like */
2020/* remote operations with dummy callref. */
2021/***********************************************/
2022static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic)
2023{ u_char id;
2024 u_char temp[265];
2025 u_char *p = temp;
2026 int i, l, proc_len;
2027 struct sk_buff *skb;
2028 struct l3_process *pc = NULL;
2029
2030 switch (ic->arg)
2031 { case NI1_CMD_INVOKE:
2032 if (ic->parm.ni1_io.datalen < 0) return(-2); /* invalid parameter */
2033
2034 for (proc_len = 1, i = ic->parm.ni1_io.proc >> 8; i; i++)
2035 i = i >> 8; /* add one byte */
2036 l = ic->parm.ni1_io.datalen + proc_len + 8; /* length excluding ie header */
2037 if (l > 255)
2038 return(-2); /* too long */
2039
2040 if (!(id = new_invoke_id(st)))
2041 return(0); /* first get a invoke id -> return if no available */
2042
2043 i = -1;
2044 MsgHead(p, i, MT_FACILITY); /* build message head */
2045 *p++ = 0x1C; /* Facility IE */
2046 *p++ = l; /* length of ie */
2047 *p++ = 0x91; /* remote operations */
2048 *p++ = 0xA1; /* invoke */
2049 *p++ = l - 3; /* length of invoke */
2050 *p++ = 0x02; /* invoke id tag */
2051 *p++ = 0x01; /* length is 1 */
2052 *p++ = id; /* invoke id */
2053 *p++ = 0x02; /* operation */
2054 *p++ = proc_len; /* length of operation */
2055
2056 for (i = proc_len; i; i--)
2057 *p++ = (ic->parm.ni1_io.proc >> (i-1)) & 0xFF;
2058 memcpy(p, ic->parm.ni1_io.data, ic->parm.ni1_io.datalen); /* copy data */
2059 l = (p - temp) + ic->parm.ni1_io.datalen; /* total length */
2060
2061 if (ic->parm.ni1_io.timeout > 0)
2062 if (!(pc = ni1_new_l3_process(st, -1)))
2063 { free_invoke_id(st, id);
2064 return(-2);
2065 }
2066 pc->prot.ni1.ll_id = ic->parm.ni1_io.ll_id; /* remember id */
2067 pc->prot.ni1.proc = ic->parm.ni1_io.proc; /* and procedure */
2068
2069 if (!(skb = l3_alloc_skb(l)))
2070 { free_invoke_id(st, id);
2071 if (pc) ni1_release_l3_process(pc);
2072 return(-2);
2073 }
2074 memcpy(skb_put(skb, l), temp, l);
2075
2076 if (pc)
2077 { pc->prot.ni1.invoke_id = id; /* remember id */
2078 L3AddTimer(&pc->timer, ic->parm.ni1_io.timeout, CC_TNI1_IO | REQUEST);
2079 }
2080
2081 l3_msg(st, DL_DATA | REQUEST, skb);
2082 ic->parm.ni1_io.hl_id = id; /* return id */
2083 return(0);
2084
2085 case NI1_CMD_INVOKE_ABORT:
2086 if ((pc = l3ni1_search_dummy_proc(st, ic->parm.ni1_io.hl_id)))
2087 { L3DelTimer(&pc->timer); /* remove timer */
2088 ni1_release_l3_process(pc);
2089 return(0);
2090 }
2091 else
2092 { l3_debug(st, "l3ni1_cmd_global abort unknown id");
2093 return(-2);
2094 }
2095 break;
2096
2097 default:
2098 l3_debug(st, "l3ni1_cmd_global unknown cmd 0x%lx", ic->arg);
2099 return(-1);
2100 } /* switch ic-> arg */
2101 return(-1);
2102} /* l3ni1_cmd_global */
2103
2104static void
2105l3ni1_io_timer(struct l3_process *pc)
2106{ isdn_ctrl ic;
2107 struct IsdnCardState *cs = pc->st->l1.hardware;
2108
2109 L3DelTimer(&pc->timer); /* remove timer */
2110
2111 ic.driver = cs->myid;
2112 ic.command = ISDN_STAT_PROT;
2113 ic.arg = NI1_STAT_INVOKE_ERR;
2114 ic.parm.ni1_io.hl_id = pc->prot.ni1.invoke_id;
2115 ic.parm.ni1_io.ll_id = pc->prot.ni1.ll_id;
2116 ic.parm.ni1_io.proc = pc->prot.ni1.proc;
2117 ic.parm.ni1_io.timeout= -1;
2118 ic.parm.ni1_io.datalen = 0;
2119 ic.parm.ni1_io.data = NULL;
2120 free_invoke_id(pc->st, pc->prot.ni1.invoke_id);
2121 pc->prot.ni1.invoke_id = 0; /* reset id */
2122
2123 cs->iif.statcallb(&ic);
2124
2125 ni1_release_l3_process(pc);
2126} /* l3ni1_io_timer */
2127
2128static void
2129l3ni1_release_ind(struct l3_process *pc, u_char pr, void *arg)
2130{
2131 u_char *p;
2132 struct sk_buff *skb = arg;
2133 int callState = 0;
2134 p = skb->data;
2135
2136 if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
2137 p++;
2138 if (1 == *p++)
2139 callState = *p;
2140 }
2141 if (callState == 0) {
2142 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
2143 * set down layer 3 without sending any message
2144 */
2145 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2146 newl3state(pc, 0);
2147 ni1_release_l3_process(pc);
2148 } else {
2149 pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
2150 }
2151}
2152
2153static void
2154l3ni1_dummy(struct l3_process *pc, u_char pr, void *arg)
2155{
2156}
2157
2158static void
2159l3ni1_t302(struct l3_process *pc, u_char pr, void *arg)
2160{
2161 L3DelTimer(&pc->timer);
2162 pc->para.loc = 0;
2163 pc->para.cause = 28; /* invalid number */
2164 l3ni1_disconnect_req(pc, pr, NULL);
2165 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2166}
2167
2168static void
2169l3ni1_t303(struct l3_process *pc, u_char pr, void *arg)
2170{
2171 if (pc->N303 > 0) {
2172 pc->N303--;
2173 L3DelTimer(&pc->timer);
2174 l3ni1_setup_req(pc, pr, arg);
2175 } else {
2176 L3DelTimer(&pc->timer);
2177 l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
2178 pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
2179 ni1_release_l3_process(pc);
2180 }
2181}
2182
2183static void
2184l3ni1_t304(struct l3_process *pc, u_char pr, void *arg)
2185{
2186 L3DelTimer(&pc->timer);
2187 pc->para.loc = 0;
2188 pc->para.cause = 102;
2189 l3ni1_disconnect_req(pc, pr, NULL);
2190 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2191
2192}
2193
2194static void
2195l3ni1_t305(struct l3_process *pc, u_char pr, void *arg)
2196{
2197 u_char tmp[16];
2198 u_char *p = tmp;
2199 int l;
2200 struct sk_buff *skb;
2201 u_char cause = 16;
2202
2203 L3DelTimer(&pc->timer);
2204 if (pc->para.cause != NO_CAUSE)
2205 cause = pc->para.cause;
2206
2207 MsgHead(p, pc->callref, MT_RELEASE);
2208
2209 *p++ = IE_CAUSE;
2210 *p++ = 0x2;
2211 *p++ = 0x80;
2212 *p++ = cause | 0x80;
2213
2214 l = p - tmp;
2215 if (!(skb = l3_alloc_skb(l)))
2216 return;
2217 memcpy(skb_put(skb, l), tmp, l);
2218 newl3state(pc, 19);
2219 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2220 L3AddTimer(&pc->timer, T308, CC_T308_1);
2221}
2222
2223static void
2224l3ni1_t310(struct l3_process *pc, u_char pr, void *arg)
2225{
2226 L3DelTimer(&pc->timer);
2227 pc->para.loc = 0;
2228 pc->para.cause = 102;
2229 l3ni1_disconnect_req(pc, pr, NULL);
2230 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2231}
2232
2233static void
2234l3ni1_t313(struct l3_process *pc, u_char pr, void *arg)
2235{
2236 L3DelTimer(&pc->timer);
2237 pc->para.loc = 0;
2238 pc->para.cause = 102;
2239 l3ni1_disconnect_req(pc, pr, NULL);
2240 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
2241}
2242
2243static void
2244l3ni1_t308_1(struct l3_process *pc, u_char pr, void *arg)
2245{
2246 newl3state(pc, 19);
2247 L3DelTimer(&pc->timer);
2248 l3ni1_message(pc, MT_RELEASE);
2249 L3AddTimer(&pc->timer, T308, CC_T308_2);
2250}
2251
2252static void
2253l3ni1_t308_2(struct l3_process *pc, u_char pr, void *arg)
2254{
2255 L3DelTimer(&pc->timer);
2256 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
2257 ni1_release_l3_process(pc);
2258}
2259
2260static void
2261l3ni1_t318(struct l3_process *pc, u_char pr, void *arg)
2262{
2263 L3DelTimer(&pc->timer);
2264 pc->para.cause = 102; /* Timer expiry */
2265 pc->para.loc = 0; /* local */
2266 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2267 newl3state(pc, 19);
2268 l3ni1_message(pc, MT_RELEASE);
2269 L3AddTimer(&pc->timer, T308, CC_T308_1);
2270}
2271
2272static void
2273l3ni1_t319(struct l3_process *pc, u_char pr, void *arg)
2274{
2275 L3DelTimer(&pc->timer);
2276 pc->para.cause = 102; /* Timer expiry */
2277 pc->para.loc = 0; /* local */
2278 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2279 newl3state(pc, 10);
2280}
2281
2282static void
2283l3ni1_restart(struct l3_process *pc, u_char pr, void *arg)
2284{
2285 L3DelTimer(&pc->timer);
2286 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2287 ni1_release_l3_process(pc);
2288}
2289
2290static void
2291l3ni1_status(struct l3_process *pc, u_char pr, void *arg)
2292{
2293 u_char *p;
2294 struct sk_buff *skb = arg;
2295 int ret;
2296 u_char cause = 0, callState = 0;
2297
2298 if ((ret = l3ni1_get_cause(pc, skb))) {
2299 if (pc->debug & L3_DEB_WARN)
2300 l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
2301 if (ret < 0)
2302 cause = 96;
2303 else if (ret > 0)
2304 cause = 100;
2305 }
2306 if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
2307 p++;
2308 if (1 == *p++) {
2309 callState = *p;
2310 if (!ie_in_set(pc, *p, l3_valid_states))
2311 cause = 100;
2312 } else
2313 cause = 100;
2314 } else
2315 cause = 96;
2316 if (!cause) { /* no error before */
2317 ret = check_infoelements(pc, skb, ie_STATUS);
2318 if (ERR_IE_COMPREHENSION == ret)
2319 cause = 96;
2320 else if (ERR_IE_UNRECOGNIZED == ret)
2321 cause = 99;
2322 }
2323 if (cause) {
2324 u_char tmp;
2325
2326 if (pc->debug & L3_DEB_WARN)
2327 l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
2328 tmp = pc->para.cause;
2329 pc->para.cause = cause;
2330 l3ni1_status_send(pc, 0, NULL);
2331 if (cause == 99)
2332 pc->para.cause = tmp;
2333 else
2334 return;
2335 }
2336 cause = pc->para.cause;
2337 if (((cause & 0x7f) == 111) && (callState == 0)) {
2338 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
2339 * if received MT_STATUS with cause == 111 and call
2340 * state == 0, then we must set down layer 3
2341 */
2342 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2343 newl3state(pc, 0);
2344 ni1_release_l3_process(pc);
2345 }
2346}
2347
2348static void
2349l3ni1_facility(struct l3_process *pc, u_char pr, void *arg)
2350{
2351 struct sk_buff *skb = arg;
2352 int ret;
2353
2354 ret = check_infoelements(pc, skb, ie_FACILITY);
2355 l3ni1_std_ie_err(pc, ret);
2356 {
2357 u_char *p;
2358 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
2359 l3ni1_parse_facility(pc->st, pc, pc->callref, p);
2360 }
2361}
2362
2363static void
2364l3ni1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
2365{
2366 struct sk_buff *skb;
2367 u_char tmp[32];
2368 u_char *p = tmp;
2369 u_char i, l;
2370 u_char *msg = pc->chan->setup.phone;
2371
2372 MsgHead(p, pc->callref, MT_SUSPEND);
2373 l = *msg++;
2374 if (l && (l <= 10)) { /* Max length 10 octets */
2375 *p++ = IE_CALL_ID;
2376 *p++ = l;
2377 for (i = 0; i < l; i++)
2378 *p++ = *msg++;
2379 } else if (l) {
2380 l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
2381 return;
2382 }
2383 l = p - tmp;
2384 if (!(skb = l3_alloc_skb(l)))
2385 return;
2386 memcpy(skb_put(skb, l), tmp, l);
2387 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2388 newl3state(pc, 15);
2389 L3AddTimer(&pc->timer, T319, CC_T319);
2390}
2391
2392static void
2393l3ni1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
2394{
2395 struct sk_buff *skb = arg;
2396 int ret;
2397
2398 L3DelTimer(&pc->timer);
2399 newl3state(pc, 0);
2400 pc->para.cause = NO_CAUSE;
2401 pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
2402 /* We don't handle suspend_ack for IE errors now */
2403 if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
2404 if (pc->debug & L3_DEB_WARN)
2405 l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
2406 ni1_release_l3_process(pc);
2407}
2408
2409static void
2410l3ni1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
2411{
2412 struct sk_buff *skb = arg;
2413 int ret;
2414
2415 if ((ret = l3ni1_get_cause(pc, skb))) {
2416 if (pc->debug & L3_DEB_WARN)
2417 l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
2418 if (ret < 0)
2419 pc->para.cause = 96;
2420 else
2421 pc->para.cause = 100;
2422 l3ni1_status_send(pc, pr, NULL);
2423 return;
2424 }
2425 ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
2426 if (ERR_IE_COMPREHENSION == ret) {
2427 l3ni1_std_ie_err(pc, ret);
2428 return;
2429 }
2430 L3DelTimer(&pc->timer);
2431 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2432 newl3state(pc, 10);
2433 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2434 l3ni1_std_ie_err(pc, ret);
2435}
2436
2437static void
2438l3ni1_resume_req(struct l3_process *pc, u_char pr, void *arg)
2439{
2440 struct sk_buff *skb;
2441 u_char tmp[32];
2442 u_char *p = tmp;
2443 u_char i, l;
2444 u_char *msg = pc->para.setup.phone;
2445
2446 MsgHead(p, pc->callref, MT_RESUME);
2447
2448 l = *msg++;
2449 if (l && (l <= 10)) { /* Max length 10 octets */
2450 *p++ = IE_CALL_ID;
2451 *p++ = l;
2452 for (i = 0; i < l; i++)
2453 *p++ = *msg++;
2454 } else if (l) {
2455 l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
2456 return;
2457 }
2458 l = p - tmp;
2459 if (!(skb = l3_alloc_skb(l)))
2460 return;
2461 memcpy(skb_put(skb, l), tmp, l);
2462 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2463 newl3state(pc, 17);
2464 L3AddTimer(&pc->timer, T318, CC_T318);
2465}
2466
2467static void
2468l3ni1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
2469{
2470 struct sk_buff *skb = arg;
2471 int id, ret;
2472
2473 if ((id = l3ni1_get_channel_id(pc, skb)) > 0) {
2474 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
2475 if (pc->debug & L3_DEB_WARN)
2476 l3_debug(pc->st, "resume ack with wrong chid %x", id);
2477 pc->para.cause = 100;
2478 l3ni1_status_send(pc, pr, NULL);
2479 return;
2480 }
2481 pc->para.bchannel = id;
2482 } else if (1 == pc->state) {
2483 if (pc->debug & L3_DEB_WARN)
2484 l3_debug(pc->st, "resume ack without chid (ret %d)", id);
2485 pc->para.cause = 96;
2486 l3ni1_status_send(pc, pr, NULL);
2487 return;
2488 }
2489 ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
2490 if (ERR_IE_COMPREHENSION == ret) {
2491 l3ni1_std_ie_err(pc, ret);
2492 return;
2493 }
2494 L3DelTimer(&pc->timer);
2495 pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
2496 newl3state(pc, 10);
2497 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2498 l3ni1_std_ie_err(pc, ret);
2499}
2500
2501static void
2502l3ni1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
2503{
2504 struct sk_buff *skb = arg;
2505 int ret;
2506
2507 if ((ret = l3ni1_get_cause(pc, skb))) {
2508 if (pc->debug & L3_DEB_WARN)
2509 l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
2510 if (ret < 0)
2511 pc->para.cause = 96;
2512 else
2513 pc->para.cause = 100;
2514 l3ni1_status_send(pc, pr, NULL);
2515 return;
2516 }
2517 ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
2518 if (ERR_IE_COMPREHENSION == ret) {
2519 l3ni1_std_ie_err(pc, ret);
2520 return;
2521 }
2522 L3DelTimer(&pc->timer);
2523 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2524 newl3state(pc, 0);
2525 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2526 l3ni1_std_ie_err(pc, ret);
2527 ni1_release_l3_process(pc);
2528}
2529
2530static void
2531l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg)
2532{
2533 u_char tmp[32];
2534 u_char *p;
2535 u_char ri, ch = 0, chan = 0;
2536 int l;
2537 struct sk_buff *skb = arg;
2538 struct l3_process *up;
2539
2540 newl3state(pc, 2);
2541 L3DelTimer(&pc->timer);
2542 p = skb->data;
2543 if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
2544 ri = p[2];
2545 l3_debug(pc->st, "Restart %x", ri);
2546 } else {
2547 l3_debug(pc->st, "Restart without restart IE");
2548 ri = 0x86;
2549 }
2550 p = skb->data;
2551 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
2552 chan = p[2] & 3;
2553 ch = p[2];
2554 if (pc->st->l3.debug)
2555 l3_debug(pc->st, "Restart for channel %d", chan);
2556 }
2557 newl3state(pc, 2);
2558 up = pc->st->l3.proc;
2559 while (up) {
2560 if ((ri & 7) == 7)
2561 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2562 else if (up->para.bchannel == chan)
2563 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2564
2565 up = up->next;
2566 }
2567 p = tmp;
2568 MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
2569 if (chan) {
2570 *p++ = IE_CHANNEL_ID;
2571 *p++ = 1;
2572 *p++ = ch | 0x80;
2573 }
2574 *p++ = 0x79; /* RESTART Ind */
2575 *p++ = 1;
2576 *p++ = ri;
2577 l = p - tmp;
2578 if (!(skb = l3_alloc_skb(l)))
2579 return;
2580 memcpy(skb_put(skb, l), tmp, l);
2581 newl3state(pc, 0);
2582 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2583}
2584
2585static void
2586l3ni1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
2587{
2588 pc->para.cause = 0x29; /* Temporary failure */
2589 pc->para.loc = 0;
2590 l3ni1_disconnect_req(pc, pr, NULL);
2591 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2592}
2593
2594static void
2595l3ni1_dl_release(struct l3_process *pc, u_char pr, void *arg)
2596{
2597 newl3state(pc, 0);
2598 pc->para.cause = 0x1b; /* Destination out of order */
2599 pc->para.loc = 0;
2600 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2601 release_l3_process(pc);
2602}
2603
2604static void
2605l3ni1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
2606{
2607 L3DelTimer(&pc->timer);
2608 L3AddTimer(&pc->timer, T309, CC_T309);
2609 l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
2610}
2611
2612static void
2613l3ni1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
2614{
2615 L3DelTimer(&pc->timer);
2616
2617 pc->para.cause = 0x1F; /* normal, unspecified */
2618 l3ni1_status_send(pc, 0, NULL);
2619}
2620
2621static void l3ni1_SendSpid( struct l3_process *pc, u_char pr, struct sk_buff *skb, int iNewState )
2622{
2623 u_char * p;
2624 char * pSPID;
2625 struct Channel * pChan = pc->st->lli.userdata;
2626 int l;
2627
2628 if ( skb )
2629 dev_kfree_skb( skb);
2630
2631 if ( !( pSPID = strchr( pChan->setup.eazmsn, ':' ) ) )
2632 {
2633 printk( KERN_ERR "SPID not supplied in EAZMSN %s\n", pChan->setup.eazmsn );
2634 newl3state( pc, 0 );
2635 pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL );
2636 return;
2637 }
2638
2639 l = strlen( ++pSPID );
2640 if ( !( skb = l3_alloc_skb( 5+l ) ) )
2641 {
2642 printk( KERN_ERR "HiSax can't get memory to send SPID\n" );
2643 return;
2644 }
2645
2646 p = skb_put( skb, 5 );
2647 *p++ = PROTO_DIS_EURO;
2648 *p++ = 0;
2649 *p++ = MT_INFORMATION;
2650 *p++ = IE_SPID;
2651 *p++ = l;
2652
2653 memcpy( skb_put( skb, l ), pSPID, l );
2654
2655 newl3state( pc, iNewState );
2656
2657 L3DelTimer( &pc->timer );
2658 L3AddTimer( &pc->timer, TSPID, CC_TSPID );
2659
2660 pc->st->l3.l3l2( pc->st, DL_DATA | REQUEST, skb );
2661}
2662
2663static void l3ni1_spid_send( struct l3_process *pc, u_char pr, void *arg )
2664{
2665 l3ni1_SendSpid( pc, pr, arg, 20 );
2666}
2667
2668void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
2669{
2670 struct sk_buff *skb = arg;
2671
2672 if ( skb->data[ 1 ] == 0 )
2673 if ( skb->data[ 3 ] == IE_ENDPOINT_ID )
2674 {
2675 L3DelTimer( &pc->timer );
2676 newl3state( pc, 0 );
2677 l3_msg( pc->st, DL_ESTABLISH | CONFIRM, NULL );
2678 }
2679 dev_kfree_skb( skb);
2680}
2681
2682static void l3ni1_spid_tout( struct l3_process *pc, u_char pr, void *arg )
2683{
2684 if ( pc->state < 22 )
2685 l3ni1_SendSpid( pc, pr, arg, pc->state+1 );
2686 else
2687 {
2688 L3DelTimer( &pc->timer );
2689 dev_kfree_skb( arg);
2690
2691 printk( KERN_ERR "SPID not accepted\n" );
2692 newl3state( pc, 0 );
2693 pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL );
2694 }
2695}
2696
2697/* *INDENT-OFF* */
2698static struct stateentry downstatelist[] =
2699{
2700 {SBIT(0),
2701 CC_SETUP | REQUEST, l3ni1_setup_req},
2702 {SBIT(0),
2703 CC_RESUME | REQUEST, l3ni1_resume_req},
2704 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
2705 CC_DISCONNECT | REQUEST, l3ni1_disconnect_req},
2706 {SBIT(12),
2707 CC_RELEASE | REQUEST, l3ni1_release_req},
2708 {ALL_STATES,
2709 CC_RESTART | REQUEST, l3ni1_restart},
2710 {SBIT(6) | SBIT(25),
2711 CC_IGNORE | REQUEST, l3ni1_reset},
2712 {SBIT(6) | SBIT(25),
2713 CC_REJECT | REQUEST, l3ni1_reject_req},
2714 {SBIT(6) | SBIT(25),
2715 CC_PROCEED_SEND | REQUEST, l3ni1_proceed_req},
2716 {SBIT(6),
2717 CC_MORE_INFO | REQUEST, l3ni1_setup_ack_req},
2718 {SBIT(25),
2719 CC_MORE_INFO | REQUEST, l3ni1_dummy},
2720 {SBIT(6) | SBIT(9) | SBIT(25),
2721 CC_ALERTING | REQUEST, l3ni1_alert_req},
2722 {SBIT(6) | SBIT(7) | SBIT(9) | SBIT(25),
2723 CC_SETUP | RESPONSE, l3ni1_setup_rsp},
2724 {SBIT(10),
2725 CC_SUSPEND | REQUEST, l3ni1_suspend_req},
2726 {SBIT(7) | SBIT(9) | SBIT(25),
2727 CC_REDIR | REQUEST, l3ni1_redir_req},
2728 {SBIT(6),
2729 CC_REDIR | REQUEST, l3ni1_redir_req_early},
2730 {SBIT(9) | SBIT(25),
2731 CC_DISCONNECT | REQUEST, l3ni1_disconnect_req},
2732 {SBIT(25),
2733 CC_T302, l3ni1_t302},
2734 {SBIT(1),
2735 CC_T303, l3ni1_t303},
2736 {SBIT(2),
2737 CC_T304, l3ni1_t304},
2738 {SBIT(3),
2739 CC_T310, l3ni1_t310},
2740 {SBIT(8),
2741 CC_T313, l3ni1_t313},
2742 {SBIT(11),
2743 CC_T305, l3ni1_t305},
2744 {SBIT(15),
2745 CC_T319, l3ni1_t319},
2746 {SBIT(17),
2747 CC_T318, l3ni1_t318},
2748 {SBIT(19),
2749 CC_T308_1, l3ni1_t308_1},
2750 {SBIT(19),
2751 CC_T308_2, l3ni1_t308_2},
2752 {SBIT(10),
2753 CC_T309, l3ni1_dl_release},
2754 { SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ),
2755 CC_TSPID, l3ni1_spid_tout },
2756};
2757
2758#define DOWNSLLEN \
2759 (sizeof(downstatelist) / sizeof(struct stateentry))
2760
2761static struct stateentry datastatelist[] =
2762{
2763 {ALL_STATES,
2764 MT_STATUS_ENQUIRY, l3ni1_status_enq},
2765 {ALL_STATES,
2766 MT_FACILITY, l3ni1_facility},
2767 {SBIT(19),
2768 MT_STATUS, l3ni1_release_ind},
2769 {ALL_STATES,
2770 MT_STATUS, l3ni1_status},
2771 {SBIT(0),
2772 MT_SETUP, l3ni1_setup},
2773 {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
2774 SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2775 MT_SETUP, l3ni1_dummy},
2776 {SBIT(1) | SBIT(2),
2777 MT_CALL_PROCEEDING, l3ni1_call_proc},
2778 {SBIT(1),
2779 MT_SETUP_ACKNOWLEDGE, l3ni1_setup_ack},
2780 {SBIT(2) | SBIT(3),
2781 MT_ALERTING, l3ni1_alerting},
2782 {SBIT(2) | SBIT(3),
2783 MT_PROGRESS, l3ni1_progress},
2784 {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
2785 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2786 MT_INFORMATION, l3ni1_information},
2787 {SBIT(10) | SBIT(11) | SBIT(15),
2788 MT_NOTIFY, l3ni1_notify},
2789 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
2790 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2791 MT_RELEASE_COMPLETE, l3ni1_release_cmpl},
2792 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
2793 MT_RELEASE, l3ni1_release},
2794 {SBIT(19), MT_RELEASE, l3ni1_release_ind},
2795 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
2796 MT_DISCONNECT, l3ni1_disconnect},
2797 {SBIT(19),
2798 MT_DISCONNECT, l3ni1_dummy},
2799 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
2800 MT_CONNECT, l3ni1_connect},
2801 {SBIT(8),
2802 MT_CONNECT_ACKNOWLEDGE, l3ni1_connect_ack},
2803 {SBIT(15),
2804 MT_SUSPEND_ACKNOWLEDGE, l3ni1_suspend_ack},
2805 {SBIT(15),
2806 MT_SUSPEND_REJECT, l3ni1_suspend_rej},
2807 {SBIT(17),
2808 MT_RESUME_ACKNOWLEDGE, l3ni1_resume_ack},
2809 {SBIT(17),
2810 MT_RESUME_REJECT, l3ni1_resume_rej},
2811};
2812
2813#define DATASLLEN \
2814 (sizeof(datastatelist) / sizeof(struct stateentry))
2815
2816static struct stateentry globalmes_list[] =
2817{
2818 {ALL_STATES,
2819 MT_STATUS, l3ni1_status},
2820 {SBIT(0),
2821 MT_RESTART, l3ni1_global_restart},
2822/* {SBIT(1),
2823 MT_RESTART_ACKNOWLEDGE, l3ni1_restart_ack},
2824*/
2825 { SBIT( 0 ), MT_DL_ESTABLISHED, l3ni1_spid_send },
2826 { SBIT( 20 ) | SBIT( 21 ) | SBIT( 22 ), MT_INFORMATION, l3ni1_spid_epid },
2827};
2828#define GLOBALM_LEN \
2829 (sizeof(globalmes_list) / sizeof(struct stateentry))
2830
2831static struct stateentry manstatelist[] =
2832{
2833 {SBIT(2),
2834 DL_ESTABLISH | INDICATION, l3ni1_dl_reset},
2835 {SBIT(10),
2836 DL_ESTABLISH | CONFIRM, l3ni1_dl_reest_status},
2837 {SBIT(10),
2838 DL_RELEASE | INDICATION, l3ni1_dl_reestablish},
2839 {ALL_STATES,
2840 DL_RELEASE | INDICATION, l3ni1_dl_release},
2841};
2842
2843#define MANSLLEN \
2844 (sizeof(manstatelist) / sizeof(struct stateentry))
2845/* *INDENT-ON* */
2846
2847
2848static void
2849global_handler(struct PStack *st, int mt, struct sk_buff *skb)
2850{
2851 u_char tmp[16];
2852 u_char *p = tmp;
2853 int l;
2854 int i;
2855 struct l3_process *proc = st->l3.global;
2856
2857 if ( skb )
2858 proc->callref = skb->data[2]; /* cr flag */
2859 else
2860 proc->callref = 0;
2861 for (i = 0; i < GLOBALM_LEN; i++)
2862 if ((mt == globalmes_list[i].primitive) &&
2863 ((1 << proc->state) & globalmes_list[i].state))
2864 break;
2865 if (i == GLOBALM_LEN) {
2866 if (st->l3.debug & L3_DEB_STATE) {
2867 l3_debug(st, "ni1 global state %d mt %x unhandled",
2868 proc->state, mt);
2869 }
2870 MsgHead(p, proc->callref, MT_STATUS);
2871 *p++ = IE_CAUSE;
2872 *p++ = 0x2;
2873 *p++ = 0x80;
2874 *p++ = 81 |0x80; /* invalid cr */
2875 *p++ = 0x14; /* CallState */
2876 *p++ = 0x1;
2877 *p++ = proc->state & 0x3f;
2878 l = p - tmp;
2879 if (!(skb = l3_alloc_skb(l)))
2880 return;
2881 memcpy(skb_put(skb, l), tmp, l);
2882 l3_msg(proc->st, DL_DATA | REQUEST, skb);
2883 } else {
2884 if (st->l3.debug & L3_DEB_STATE) {
2885 l3_debug(st, "ni1 global %d mt %x",
2886 proc->state, mt);
2887 }
2888 globalmes_list[i].rout(proc, mt, skb);
2889 }
2890}
2891
2892static void
2893ni1up(struct PStack *st, int pr, void *arg)
2894{
2895 int i, mt, cr, cause, callState;
2896 char *ptr;
2897 u_char *p;
2898 struct sk_buff *skb = arg;
2899 struct l3_process *proc;
2900
2901 switch (pr) {
2902 case (DL_DATA | INDICATION):
2903 case (DL_UNIT_DATA | INDICATION):
2904 break;
2905 case (DL_ESTABLISH | INDICATION):
2906 case (DL_RELEASE | INDICATION):
2907 case (DL_RELEASE | CONFIRM):
2908 l3_msg(st, pr, arg);
2909 return;
2910 break;
2911
2912 case (DL_ESTABLISH | CONFIRM):
2913 global_handler( st, MT_DL_ESTABLISHED, NULL );
2914 return;
2915
2916 default:
2917 printk(KERN_ERR "HiSax ni1up unknown pr=%04x\n", pr);
2918 return;
2919 }
2920 if (skb->len < 3) {
2921 l3_debug(st, "ni1up frame too short(%d)", skb->len);
2922 dev_kfree_skb(skb);
2923 return;
2924 }
2925
2926 if (skb->data[0] != PROTO_DIS_EURO) {
2927 if (st->l3.debug & L3_DEB_PROTERR) {
2928 l3_debug(st, "ni1up%sunexpected discriminator %x message len %d",
2929 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
2930 skb->data[0], skb->len);
2931 }
2932 dev_kfree_skb(skb);
2933 return;
2934 }
2935 cr = getcallref(skb->data);
2936 if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
2937 l3_debug(st, "ni1up frame too short(%d)", skb->len);
2938 dev_kfree_skb(skb);
2939 return;
2940 }
2941 mt = skb->data[skb->data[1] + 2];
2942 if (st->l3.debug & L3_DEB_STATE)
2943 l3_debug(st, "ni1up cr %d", cr);
2944 if (cr == -2) { /* wrong Callref */
2945 if (st->l3.debug & L3_DEB_WARN)
2946 l3_debug(st, "ni1up wrong Callref");
2947 dev_kfree_skb(skb);
2948 return;
2949 } else if (cr == -1) { /* Dummy Callref */
2950 if (mt == MT_FACILITY)
2951 {
2952 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
2953 l3ni1_parse_facility(st, NULL,
2954 (pr == (DL_DATA | INDICATION)) ? -1 : -2, p);
2955 dev_kfree_skb(skb);
2956 return;
2957 }
2958 }
2959 else
2960 {
2961 global_handler(st, mt, skb);
2962 return;
2963 }
2964
2965 if (st->l3.debug & L3_DEB_WARN)
2966 l3_debug(st, "ni1up dummy Callref (no facility msg or ie)");
2967 dev_kfree_skb(skb);
2968 return;
2969 } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
2970 (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */
2971 if (st->l3.debug & L3_DEB_STATE)
2972 l3_debug(st, "ni1up Global CallRef");
2973 global_handler(st, mt, skb);
2974 dev_kfree_skb(skb);
2975 return;
2976 } else if (!(proc = getl3proc(st, cr))) {
2977 /* No transaction process exist, that means no call with
2978 * this callreference is active
2979 */
2980 if (mt == MT_SETUP) {
2981 /* Setup creates a new transaction process */
2982 if (skb->data[2] & 0x80) {
2983 /* Setup with wrong CREF flag */
2984 if (st->l3.debug & L3_DEB_STATE)
2985 l3_debug(st, "ni1up wrong CRef flag");
2986 dev_kfree_skb(skb);
2987 return;
2988 }
2989 if (!(proc = ni1_new_l3_process(st, cr))) {
2990 /* May be to answer with RELEASE_COMPLETE and
2991 * CAUSE 0x2f "Resource unavailable", but this
2992 * need a new_l3_process too ... arghh
2993 */
2994 dev_kfree_skb(skb);
2995 return;
2996 }
2997 } else if (mt == MT_STATUS) {
2998 cause = 0;
2999 if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
3000 ptr++;
3001 if (*ptr++ == 2)
3002 ptr++;
3003 cause = *ptr & 0x7f;
3004 }
3005 callState = 0;
3006 if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
3007 ptr++;
3008 if (*ptr++ == 2)
3009 ptr++;
3010 callState = *ptr;
3011 }
3012 /* ETS 300-104 part 2.4.1
3013 * if setup has not been made and a message type
3014 * MT_STATUS is received with call state == 0,
3015 * we must send nothing
3016 */
3017 if (callState != 0) {
3018 /* ETS 300-104 part 2.4.2
3019 * if setup has not been made and a message type
3020 * MT_STATUS is received with call state != 0,
3021 * we must send MT_RELEASE_COMPLETE cause 101
3022 */
3023 if ((proc = ni1_new_l3_process(st, cr))) {
3024 proc->para.cause = 101;
3025 l3ni1_msg_without_setup(proc, 0, NULL);
3026 }
3027 }
3028 dev_kfree_skb(skb);
3029 return;
3030 } else if (mt == MT_RELEASE_COMPLETE) {
3031 dev_kfree_skb(skb);
3032 return;
3033 } else {
3034 /* ETS 300-104 part 2
3035 * if setup has not been made and a message type
3036 * (except MT_SETUP and RELEASE_COMPLETE) is received,
3037 * we must send MT_RELEASE_COMPLETE cause 81 */
3038 dev_kfree_skb(skb);
3039 if ((proc = ni1_new_l3_process(st, cr))) {
3040 proc->para.cause = 81;
3041 l3ni1_msg_without_setup(proc, 0, NULL);
3042 }
3043 return;
3044 }
3045 }
3046 if (l3ni1_check_messagetype_validity(proc, mt, skb)) {
3047 dev_kfree_skb(skb);
3048 return;
3049 }
3050 if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
3051 l3ni1_deliver_display(proc, pr, p); /* Display IE included */
3052 for (i = 0; i < DATASLLEN; i++)
3053 if ((mt == datastatelist[i].primitive) &&
3054 ((1 << proc->state) & datastatelist[i].state))
3055 break;
3056 if (i == DATASLLEN) {
3057 if (st->l3.debug & L3_DEB_STATE) {
3058 l3_debug(st, "ni1up%sstate %d mt %#x unhandled",
3059 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3060 proc->state, mt);
3061 }
3062 if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
3063 proc->para.cause = 101;
3064 l3ni1_status_send(proc, pr, skb);
3065 }
3066 } else {
3067 if (st->l3.debug & L3_DEB_STATE) {
3068 l3_debug(st, "ni1up%sstate %d mt %x",
3069 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3070 proc->state, mt);
3071 }
3072 datastatelist[i].rout(proc, pr, skb);
3073 }
3074 dev_kfree_skb(skb);
3075 return;
3076}
3077
3078static void
3079ni1down(struct PStack *st, int pr, void *arg)
3080{
3081 int i, cr;
3082 struct l3_process *proc;
3083 struct Channel *chan;
3084
3085 if ((DL_ESTABLISH | REQUEST) == pr) {
3086 l3_msg(st, pr, NULL);
3087 return;
3088 } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
3089 chan = arg;
3090 cr = newcallref();
3091 cr |= 0x80;
3092 if ((proc = ni1_new_l3_process(st, cr))) {
3093 proc->chan = chan;
3094 chan->proc = proc;
3095 memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
3096 proc->callref = cr;
3097 }
3098 } else {
3099 proc = arg;
3100 }
3101 if (!proc) {
3102 printk(KERN_ERR "HiSax ni1down without proc pr=%04x\n", pr);
3103 return;
3104 }
3105
3106 if ( pr == (CC_TNI1_IO | REQUEST)) {
3107 l3ni1_io_timer(proc); /* timer expires */
3108 return;
3109 }
3110
3111 for (i = 0; i < DOWNSLLEN; i++)
3112 if ((pr == downstatelist[i].primitive) &&
3113 ((1 << proc->state) & downstatelist[i].state))
3114 break;
3115 if (i == DOWNSLLEN) {
3116 if (st->l3.debug & L3_DEB_STATE) {
3117 l3_debug(st, "ni1down state %d prim %#x unhandled",
3118 proc->state, pr);
3119 }
3120 } else {
3121 if (st->l3.debug & L3_DEB_STATE) {
3122 l3_debug(st, "ni1down state %d prim %#x",
3123 proc->state, pr);
3124 }
3125 downstatelist[i].rout(proc, pr, arg);
3126 }
3127}
3128
3129static void
3130ni1man(struct PStack *st, int pr, void *arg)
3131{
3132 int i;
3133 struct l3_process *proc = arg;
3134
3135 if (!proc) {
3136 printk(KERN_ERR "HiSax ni1man without proc pr=%04x\n", pr);
3137 return;
3138 }
3139 for (i = 0; i < MANSLLEN; i++)
3140 if ((pr == manstatelist[i].primitive) &&
3141 ((1 << proc->state) & manstatelist[i].state))
3142 break;
3143 if (i == MANSLLEN) {
3144 if (st->l3.debug & L3_DEB_STATE) {
3145 l3_debug(st, "cr %d ni1man state %d prim %#x unhandled",
3146 proc->callref & 0x7f, proc->state, pr);
3147 }
3148 } else {
3149 if (st->l3.debug & L3_DEB_STATE) {
3150 l3_debug(st, "cr %d ni1man state %d prim %#x",
3151 proc->callref & 0x7f, proc->state, pr);
3152 }
3153 manstatelist[i].rout(proc, pr, arg);
3154 }
3155}
3156
3157void
3158setstack_ni1(struct PStack *st)
3159{
3160 char tmp[64];
3161 int i;
3162
3163 st->lli.l4l3 = ni1down;
3164 st->lli.l4l3_proto = l3ni1_cmd_global;
3165 st->l2.l2l3 = ni1up;
3166 st->l3.l3ml3 = ni1man;
3167 st->l3.N303 = 1;
3168 st->prot.ni1.last_invoke_id = 0;
3169 st->prot.ni1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
3170 i = 1;
3171 while (i < 32)
3172 st->prot.ni1.invoke_used[i++] = 0;
3173
3174 if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
3175 printk(KERN_ERR "HiSax can't get memory for ni1 global CR\n");
3176 } else {
3177 st->l3.global->state = 0;
3178 st->l3.global->callref = 0;
3179 st->l3.global->next = NULL;
3180 st->l3.global->debug = L3_DEB_WARN;
3181 st->l3.global->st = st;
3182 st->l3.global->N303 = 1;
3183 st->l3.global->prot.ni1.invoke_id = 0;
3184
3185 L3InitTimer(st->l3.global, &st->l3.global->timer);
3186 }
3187 strcpy(tmp, ni1_revision);
3188 printk(KERN_INFO "HiSax: National ISDN-1 Rev. %s\n", HiSax_getrev(tmp));
3189}
diff --git a/drivers/isdn/hisax/l3ni1.h b/drivers/isdn/hisax/l3ni1.h
new file mode 100644
index 00000000000..4066da2fe5a
--- /dev/null
+++ b/drivers/isdn/hisax/l3ni1.h
@@ -0,0 +1,136 @@
1/* $Id: l3ni1.h,v 2.3.6.2 2001/09/23 22:24:50 kai Exp $
2 *
3 * NI1 D-channel protocol
4 *
5 * Author Matt Henderson & Guy Ellis
6 * Copyright by Traverse Technologies Pty Ltd, www.travers.com.au
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 * 2000.6.6 Initial implementation of routines for US NI1
12 * Layer 3 protocol based on the EURO/DSS1 D-channel protocol
13 * driver written by Karsten Keil et al. Thanks also for the
14 * code provided by Ragnar Paulson.
15 *
16 */
17
18#ifndef l3ni1_process
19
20#define T302 15000
21#define T303 4000
22#define T304 30000
23#define T305 30000
24#define T308 4000
25/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
26/* This makes some tests easier and quicker */
27#define T309 40000
28#define T310 30000
29#define T313 4000
30#define T318 4000
31#define T319 4000
32#define TSPID 5000 /* was 2000 - Guy Ellis */
33
34/*
35 * Message-Types
36 */
37
38#define MT_ALERTING 0x01
39#define MT_CALL_PROCEEDING 0x02
40#define MT_CONNECT 0x07
41#define MT_CONNECT_ACKNOWLEDGE 0x0f
42#define MT_PROGRESS 0x03
43#define MT_SETUP 0x05
44#define MT_SETUP_ACKNOWLEDGE 0x0d
45#define MT_RESUME 0x26
46#define MT_RESUME_ACKNOWLEDGE 0x2e
47#define MT_RESUME_REJECT 0x22
48#define MT_SUSPEND 0x25
49#define MT_SUSPEND_ACKNOWLEDGE 0x2d
50#define MT_SUSPEND_REJECT 0x21
51#define MT_USER_INFORMATION 0x20
52#define MT_DISCONNECT 0x45
53#define MT_RELEASE 0x4d
54#define MT_RELEASE_COMPLETE 0x5a
55#define MT_RESTART 0x46
56#define MT_RESTART_ACKNOWLEDGE 0x4e
57#define MT_SEGMENT 0x60
58#define MT_CONGESTION_CONTROL 0x79
59#define MT_INFORMATION 0x7b
60#define MT_FACILITY 0x62
61#define MT_NOTIFY 0x6e
62#define MT_STATUS 0x7d
63#define MT_STATUS_ENQUIRY 0x75
64#define MT_DL_ESTABLISHED 0xfe
65
66#define IE_SEGMENT 0x00
67#define IE_BEARER 0x04
68#define IE_CAUSE 0x08
69#define IE_CALL_ID 0x10
70#define IE_CALL_STATE 0x14
71#define IE_CHANNEL_ID 0x18
72#define IE_FACILITY 0x1c
73#define IE_PROGRESS 0x1e
74#define IE_NET_FAC 0x20
75#define IE_NOTIFY 0x27
76#define IE_DISPLAY 0x28
77#define IE_DATE 0x29
78#define IE_KEYPAD 0x2c
79#define IE_SIGNAL 0x34
80#define IE_SPID 0x3a
81#define IE_ENDPOINT_ID 0x3b
82#define IE_INFORATE 0x40
83#define IE_E2E_TDELAY 0x42
84#define IE_TDELAY_SEL 0x43
85#define IE_PACK_BINPARA 0x44
86#define IE_PACK_WINSIZE 0x45
87#define IE_PACK_SIZE 0x46
88#define IE_CUG 0x47
89#define IE_REV_CHARGE 0x4a
90#define IE_CONNECT_PN 0x4c
91#define IE_CONNECT_SUB 0x4d
92#define IE_CALLING_PN 0x6c
93#define IE_CALLING_SUB 0x6d
94#define IE_CALLED_PN 0x70
95#define IE_CALLED_SUB 0x71
96#define IE_REDIR_NR 0x74
97#define IE_TRANS_SEL 0x78
98#define IE_RESTART_IND 0x79
99#define IE_LLC 0x7c
100#define IE_HLC 0x7d
101#define IE_USER_USER 0x7e
102#define IE_ESCAPE 0x7f
103#define IE_SHIFT 0x90
104#define IE_MORE_DATA 0xa0
105#define IE_COMPLETE 0xa1
106#define IE_CONGESTION 0xb0
107#define IE_REPEAT 0xd0
108
109#define IE_MANDATORY 0x0100
110/* mandatory not in every case */
111#define IE_MANDATORY_1 0x0200
112
113#define ERR_IE_COMPREHENSION 1
114#define ERR_IE_UNRECOGNIZED -1
115#define ERR_IE_LENGTH -2
116#define ERR_IE_SEQUENCE -3
117
118#else /* only l3ni1_process */
119
120/* l3ni1 specific data in l3 process */
121typedef struct
122 { unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */
123 ulong ll_id; /* remebered ll id */
124 u8 remote_operation; /* handled remote operation, 0 = not active */
125 int proc; /* rememered procedure */
126 ulong remote_result; /* result of remote operation for statcallb */
127 char uus1_data[35]; /* data send during alerting or disconnect */
128 } ni1_proc_priv;
129
130/* l3dni1 specific data in protocol stack */
131typedef struct
132 { unsigned char last_invoke_id; /* last used value for invoking */
133 unsigned char invoke_used[32]; /* 256 bits for 256 values */
134 } ni1_stk_priv;
135
136#endif /* only l3dni1_process */
diff --git a/drivers/isdn/hisax/lmgr.c b/drivers/isdn/hisax/lmgr.c
new file mode 100644
index 00000000000..d4f86d654de
--- /dev/null
+++ b/drivers/isdn/hisax/lmgr.c
@@ -0,0 +1,50 @@
1/* $Id: lmgr.c,v 1.7.6.2 2001/09/23 22:24:50 kai Exp $
2 *
3 * Layermanagement module
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include "hisax.h"
14
15static void
16error_handling_dchan(struct PStack *st, int Error)
17{
18 switch (Error) {
19 case 'C':
20 case 'D':
21 case 'G':
22 case 'H':
23 st->l2.l2tei(st, MDL_ERROR | REQUEST, NULL);
24 break;
25 }
26}
27
28static void
29hisax_manager(struct PStack *st, int pr, void *arg)
30{
31 long Code;
32
33 switch (pr) {
34 case (MDL_ERROR | INDICATION):
35 Code = (long) arg;
36 HiSax_putstatus(st->l1.hardware, "manager: MDL_ERROR",
37 " %c %s", (char)Code,
38 test_bit(FLG_LAPD, &st->l2.flag) ?
39 "D-channel" : "B-channel");
40 if (test_bit(FLG_LAPD, &st->l2.flag))
41 error_handling_dchan(st, Code);
42 break;
43 }
44}
45
46void
47setstack_manager(struct PStack *st)
48{
49 st->ma.layer = hisax_manager;
50}
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
new file mode 100644
index 00000000000..3ac4484a488
--- /dev/null
+++ b/drivers/isdn/hisax/mic.c
@@ -0,0 +1,239 @@
1/* $Id: mic.c,v 1.12.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for mic cards
4 *
5 * Author Stephan von Krawczynski
6 * Copyright by Stephan von Krawczynski <skraw@ithnet.com>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "isac.h"
16#include "hscx.h"
17#include "isdnl1.h"
18
19extern const char *CardType[];
20
21const char *mic_revision = "$Revision: 1.12.2.4 $";
22
23#define byteout(addr,val) outb(val,addr)
24#define bytein(addr) inb(addr)
25
26#define MIC_ISAC 2
27#define MIC_HSCX 1
28#define MIC_ADR 7
29
30/* CARD_ADR (Write) */
31#define MIC_RESET 0x3 /* same as DOS driver */
32
33static inline u_char
34readreg(unsigned int ale, unsigned int adr, u_char off)
35{
36 register u_char ret;
37
38 byteout(ale, off);
39 ret = bytein(adr);
40 return (ret);
41}
42
43static inline void
44readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
45{
46 byteout(ale, off);
47 insb(adr, data, size);
48}
49
50
51static inline void
52writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
53{
54 byteout(ale, off);
55 byteout(adr, data);
56}
57
58static inline void
59writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
60{
61 byteout(ale, off);
62 outsb(adr, data, size);
63}
64
65/* Interface functions */
66
67static u_char
68ReadISAC(struct IsdnCardState *cs, u_char offset)
69{
70 return (readreg(cs->hw.mic.adr, cs->hw.mic.isac, offset));
71}
72
73static void
74WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
75{
76 writereg(cs->hw.mic.adr, cs->hw.mic.isac, offset, value);
77}
78
79static void
80ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
81{
82 readfifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size);
83}
84
85static void
86WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
87{
88 writefifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size);
89}
90
91static u_char
92ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
93{
94 return (readreg(cs->hw.mic.adr,
95 cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0)));
96}
97
98static void
99WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
100{
101 writereg(cs->hw.mic.adr,
102 cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value);
103}
104
105/*
106 * fast interrupt HSCX stuff goes here
107 */
108
109#define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \
110 cs->hw.mic.hscx, reg + (nr ? 0x40 : 0))
111#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \
112 cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data)
113
114#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \
115 cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
116
117#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \
118 cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt)
119
120#include "hscx_irq.c"
121
122static irqreturn_t
123mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
124{
125 struct IsdnCardState *cs = dev_id;
126 u_char val;
127 u_long flags;
128
129 spin_lock_irqsave(&cs->lock, flags);
130 val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
131 Start_HSCX:
132 if (val)
133 hscx_int_main(cs, val);
134 val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
135 Start_ISAC:
136 if (val)
137 isac_interrupt(cs, val);
138 val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
139 if (val) {
140 if (cs->debug & L1_DEB_HSCX)
141 debugl1(cs, "HSCX IntStat after IntRoutine");
142 goto Start_HSCX;
143 }
144 val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
145 if (val) {
146 if (cs->debug & L1_DEB_ISAC)
147 debugl1(cs, "ISAC IntStat after IntRoutine");
148 goto Start_ISAC;
149 }
150 writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
151 writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
152 writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
153 writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
154 writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
155 writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
156 spin_unlock_irqrestore(&cs->lock, flags);
157 return IRQ_HANDLED;
158}
159
160void
161release_io_mic(struct IsdnCardState *cs)
162{
163 int bytecnt = 8;
164
165 if (cs->hw.mic.cfg_reg)
166 release_region(cs->hw.mic.cfg_reg, bytecnt);
167}
168
169static int
170mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
171{
172 u_long flags;
173
174 switch (mt) {
175 case CARD_RESET:
176 return(0);
177 case CARD_RELEASE:
178 release_io_mic(cs);
179 return(0);
180 case CARD_INIT:
181 spin_lock_irqsave(&cs->lock, flags);
182 inithscx(cs); /* /RTSA := ISAC RST */
183 inithscxisac(cs, 3);
184 spin_unlock_irqrestore(&cs->lock, flags);
185 return(0);
186 case CARD_TEST:
187 return(0);
188 }
189 return(0);
190}
191
192int __init
193setup_mic(struct IsdnCard *card)
194{
195 int bytecnt;
196 struct IsdnCardState *cs = card->cs;
197 char tmp[64];
198
199 strcpy(tmp, mic_revision);
200 printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
201 if (cs->typ != ISDN_CTYPE_MIC)
202 return (0);
203
204 bytecnt = 8;
205 cs->hw.mic.cfg_reg = card->para[1];
206 cs->irq = card->para[0];
207 cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
208 cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
209 cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
210
211 if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) {
212 printk(KERN_WARNING
213 "HiSax: %s config port %x-%x already in use\n",
214 CardType[card->typ],
215 cs->hw.mic.cfg_reg,
216 cs->hw.mic.cfg_reg + bytecnt);
217 return (0);
218 }
219 printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
220 cs->hw.mic.cfg_reg, cs->irq);
221 setup_isac(cs);
222 cs->readisac = &ReadISAC;
223 cs->writeisac = &WriteISAC;
224 cs->readisacfifo = &ReadISACfifo;
225 cs->writeisacfifo = &WriteISACfifo;
226 cs->BC_Read_Reg = &ReadHSCX;
227 cs->BC_Write_Reg = &WriteHSCX;
228 cs->BC_Send_Data = &hscx_fill_fifo;
229 cs->cardmsg = &mic_card_msg;
230 cs->irq_func = &mic_interrupt;
231 ISACVersion(cs, "mic:");
232 if (HscxVersion(cs, "mic:")) {
233 printk(KERN_WARNING
234 "mic: wrong HSCX versions check IO address\n");
235 release_io_mic(cs);
236 return (0);
237 }
238 return (1);
239}
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
new file mode 100644
index 00000000000..fe61d26365d
--- /dev/null
+++ b/drivers/isdn/hisax/netjet.c
@@ -0,0 +1,996 @@
1/* $Id: netjet.c,v 1.29.2.4 2004/02/11 13:21:34 keil Exp $
2 *
3 * low level stuff for Traverse Technologie NETJet ISDN cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * Thanks to Traverse Technologies Australia for documents and information
12 *
13 * 16-Apr-2002 - led code added - Guy Ellis (guy@traverse.com.au)
14 *
15 */
16
17#include <linux/init.h>
18#include "hisax.h"
19#include "isac.h"
20#include "hscx.h"
21#include "isdnl1.h"
22#include <linux/pci.h>
23#include <linux/interrupt.h>
24#include <linux/ppp_defs.h>
25#include <asm/io.h>
26#include "netjet.h"
27
28const char *NETjet_revision = "$Revision: 1.29.2.4 $";
29
30/* Interface functions */
31
32u_char
33NETjet_ReadIC(struct IsdnCardState *cs, u_char offset)
34{
35 u_char ret;
36
37 cs->hw.njet.auxd &= 0xfc;
38 cs->hw.njet.auxd |= (offset>>4) & 3;
39 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
40 ret = bytein(cs->hw.njet.isac + ((offset & 0xf)<<2));
41 return(ret);
42}
43
44void
45NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value)
46{
47 cs->hw.njet.auxd &= 0xfc;
48 cs->hw.njet.auxd |= (offset>>4) & 3;
49 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
50 byteout(cs->hw.njet.isac + ((offset & 0xf)<<2), value);
51}
52
53void
54NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size)
55{
56 cs->hw.njet.auxd &= 0xfc;
57 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
58 insb(cs->hw.njet.isac, data, size);
59}
60
61void
62NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size)
63{
64 cs->hw.njet.auxd &= 0xfc;
65 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
66 outsb(cs->hw.njet.isac, data, size);
67}
68
69void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
70{
71 u_int mask=0x000000ff, val = 0, *p=pos;
72 u_int i;
73
74 val |= fill;
75 if (chan) {
76 val <<= 8;
77 mask <<= 8;
78 }
79 mask ^= 0xffffffff;
80 for (i=0; i<cnt; i++) {
81 *p &= mask;
82 *p++ |= val;
83 if (p > bcs->hw.tiger.s_end)
84 p = bcs->hw.tiger.send;
85 }
86}
87
88void
89mode_tiger(struct BCState *bcs, int mode, int bc)
90{
91 struct IsdnCardState *cs = bcs->cs;
92 u_char led;
93
94 if (cs->debug & L1_DEB_HSCX)
95 debugl1(cs, "Tiger mode %d bchan %d/%d",
96 mode, bc, bcs->channel);
97 bcs->mode = mode;
98 bcs->channel = bc;
99 switch (mode) {
100 case (L1_MODE_NULL):
101 fill_mem(bcs, bcs->hw.tiger.send,
102 NETJET_DMA_TXSIZE, bc, 0xff);
103 if (cs->debug & L1_DEB_HSCX)
104 debugl1(cs, "Tiger stat rec %d/%d send %d",
105 bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err,
106 bcs->hw.tiger.s_tot);
107 if ((cs->bcs[0].mode == L1_MODE_NULL) &&
108 (cs->bcs[1].mode == L1_MODE_NULL)) {
109 cs->hw.njet.dmactrl = 0;
110 byteout(cs->hw.njet.base + NETJET_DMACTRL,
111 cs->hw.njet.dmactrl);
112 byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
113 }
114 if (cs->typ == ISDN_CTYPE_NETJET_S)
115 {
116 // led off
117 led = bc & 0x01;
118 led = 0x01 << (6 + led); // convert to mask
119 led = ~led;
120 cs->hw.njet.auxd &= led;
121 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
122 }
123 break;
124 case (L1_MODE_TRANS):
125 break;
126 case (L1_MODE_HDLC_56K):
127 case (L1_MODE_HDLC):
128 fill_mem(bcs, bcs->hw.tiger.send,
129 NETJET_DMA_TXSIZE, bc, 0xff);
130 bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH;
131 bcs->hw.tiger.r_tot = 0;
132 bcs->hw.tiger.r_bitcnt = 0;
133 bcs->hw.tiger.r_one = 0;
134 bcs->hw.tiger.r_err = 0;
135 bcs->hw.tiger.s_tot = 0;
136 if (! cs->hw.njet.dmactrl) {
137 fill_mem(bcs, bcs->hw.tiger.send,
138 NETJET_DMA_TXSIZE, !bc, 0xff);
139 cs->hw.njet.dmactrl = 1;
140 byteout(cs->hw.njet.base + NETJET_DMACTRL,
141 cs->hw.njet.dmactrl);
142 byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x0f);
143 /* was 0x3f now 0x0f for TJ300 and TJ320 GE 13/07/00 */
144 }
145 bcs->hw.tiger.sendp = bcs->hw.tiger.send;
146 bcs->hw.tiger.free = NETJET_DMA_TXSIZE;
147 test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
148 if (cs->typ == ISDN_CTYPE_NETJET_S)
149 {
150 // led on
151 led = bc & 0x01;
152 led = 0x01 << (6 + led); // convert to mask
153 cs->hw.njet.auxd |= led;
154 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
155 }
156 break;
157 }
158 if (cs->debug & L1_DEB_HSCX)
159 debugl1(cs, "tiger: set %x %x %x %x/%x pulse=%d",
160 bytein(cs->hw.njet.base + NETJET_DMACTRL),
161 bytein(cs->hw.njet.base + NETJET_IRQMASK0),
162 bytein(cs->hw.njet.base + NETJET_IRQSTAT0),
163 inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
164 inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
165 bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
166}
167
168static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s) {
169 char tmp[128];
170 char *t = tmp;
171 int i=count,j;
172 u_char *p = buf;
173
174 t += sprintf(t, "tiger %s(%4d)", s, count);
175 while (i>0) {
176 if (i>16)
177 j=16;
178 else
179 j=i;
180 QuickHex(t, p, j);
181 debugl1(cs, tmp);
182 p += j;
183 i -= j;
184 t = tmp;
185 t += sprintf(t, "tiger %s ", s);
186 }
187}
188
189// macro for 64k
190
191#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \
192 bitcnt++;\
193 s_val >>= 1;\
194 if (val & 1) {\
195 s_one++;\
196 s_val |= 0x80;\
197 } else {\
198 s_one = 0;\
199 s_val &= 0x7f;\
200 }\
201 if (bitcnt==8) {\
202 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
203 bitcnt = 0;\
204 }\
205 if (s_one == 5) {\
206 s_val >>= 1;\
207 s_val &= 0x7f;\
208 bitcnt++;\
209 s_one = 0;\
210 }\
211 if (bitcnt==8) {\
212 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
213 bitcnt = 0;\
214 }\
215 val >>= 1;\
216 }
217
218static int make_raw_data(struct BCState *bcs) {
219// this make_raw is for 64k
220 register u_int i,s_cnt=0;
221 register u_char j;
222 register u_char val;
223 register u_char s_one = 0;
224 register u_char s_val = 0;
225 register u_char bitcnt = 0;
226 u_int fcs;
227
228 if (!bcs->tx_skb) {
229 debugl1(bcs->cs, "tiger make_raw: NULL skb");
230 return(1);
231 }
232 bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE;
233 fcs = PPP_INITFCS;
234 for (i=0; i<bcs->tx_skb->len; i++) {
235 val = bcs->tx_skb->data[i];
236 fcs = PPP_FCS (fcs, val);
237 MAKE_RAW_BYTE;
238 }
239 fcs ^= 0xffff;
240 val = fcs & 0xff;
241 MAKE_RAW_BYTE;
242 val = (fcs>>8) & 0xff;
243 MAKE_RAW_BYTE;
244 val = HDLC_FLAG_VALUE;
245 for (j=0; j<8; j++) {
246 bitcnt++;
247 s_val >>= 1;
248 if (val & 1)
249 s_val |= 0x80;
250 else
251 s_val &= 0x7f;
252 if (bitcnt==8) {
253 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
254 bitcnt = 0;
255 }
256 val >>= 1;
257 }
258 if (bcs->cs->debug & L1_DEB_HSCX)
259 debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d",
260 bcs->tx_skb->len, s_cnt, bitcnt);
261 if (bitcnt) {
262 while (8>bitcnt++) {
263 s_val >>= 1;
264 s_val |= 0x80;
265 }
266 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
267 bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix
268 }
269 bcs->hw.tiger.sendcnt = s_cnt;
270 bcs->tx_cnt -= bcs->tx_skb->len;
271 bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
272 return(0);
273}
274
275// macro for 56k
276
277#define MAKE_RAW_BYTE_56K for (j=0; j<8; j++) { \
278 bitcnt++;\
279 s_val >>= 1;\
280 if (val & 1) {\
281 s_one++;\
282 s_val |= 0x80;\
283 } else {\
284 s_one = 0;\
285 s_val &= 0x7f;\
286 }\
287 if (bitcnt==7) {\
288 s_val >>= 1;\
289 s_val |= 0x80;\
290 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
291 bitcnt = 0;\
292 }\
293 if (s_one == 5) {\
294 s_val >>= 1;\
295 s_val &= 0x7f;\
296 bitcnt++;\
297 s_one = 0;\
298 }\
299 if (bitcnt==7) {\
300 s_val >>= 1;\
301 s_val |= 0x80;\
302 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
303 bitcnt = 0;\
304 }\
305 val >>= 1;\
306 }
307
308static int make_raw_data_56k(struct BCState *bcs) {
309// this make_raw is for 56k
310 register u_int i,s_cnt=0;
311 register u_char j;
312 register u_char val;
313 register u_char s_one = 0;
314 register u_char s_val = 0;
315 register u_char bitcnt = 0;
316 u_int fcs;
317
318 if (!bcs->tx_skb) {
319 debugl1(bcs->cs, "tiger make_raw_56k: NULL skb");
320 return(1);
321 }
322 val = HDLC_FLAG_VALUE;
323 for (j=0; j<8; j++) {
324 bitcnt++;
325 s_val >>= 1;
326 if (val & 1)
327 s_val |= 0x80;
328 else
329 s_val &= 0x7f;
330 if (bitcnt==7) {
331 s_val >>= 1;
332 s_val |= 0x80;
333 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
334 bitcnt = 0;
335 }
336 val >>= 1;
337 };
338 fcs = PPP_INITFCS;
339 for (i=0; i<bcs->tx_skb->len; i++) {
340 val = bcs->tx_skb->data[i];
341 fcs = PPP_FCS (fcs, val);
342 MAKE_RAW_BYTE_56K;
343 }
344 fcs ^= 0xffff;
345 val = fcs & 0xff;
346 MAKE_RAW_BYTE_56K;
347 val = (fcs>>8) & 0xff;
348 MAKE_RAW_BYTE_56K;
349 val = HDLC_FLAG_VALUE;
350 for (j=0; j<8; j++) {
351 bitcnt++;
352 s_val >>= 1;
353 if (val & 1)
354 s_val |= 0x80;
355 else
356 s_val &= 0x7f;
357 if (bitcnt==7) {
358 s_val >>= 1;
359 s_val |= 0x80;
360 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
361 bitcnt = 0;
362 }
363 val >>= 1;
364 }
365 if (bcs->cs->debug & L1_DEB_HSCX)
366 debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d",
367 bcs->tx_skb->len, s_cnt, bitcnt);
368 if (bitcnt) {
369 while (8>bitcnt++) {
370 s_val >>= 1;
371 s_val |= 0x80;
372 }
373 bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
374 bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix
375 }
376 bcs->hw.tiger.sendcnt = s_cnt;
377 bcs->tx_cnt -= bcs->tx_skb->len;
378 bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
379 return(0);
380}
381
382static void got_frame(struct BCState *bcs, int count) {
383 struct sk_buff *skb;
384
385 if (!(skb = dev_alloc_skb(count)))
386 printk(KERN_WARNING "TIGER: receive out of memory\n");
387 else {
388 memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count);
389 skb_queue_tail(&bcs->rqueue, skb);
390 }
391 test_and_set_bit(B_RCVBUFREADY, &bcs->event);
392 schedule_work(&bcs->tqueue);
393
394 if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME)
395 printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec");
396}
397
398
399
400static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
401 int i;
402 register u_char j;
403 register u_char val;
404 u_int *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1;
405 register u_char state = bcs->hw.tiger.r_state;
406 register u_char r_one = bcs->hw.tiger.r_one;
407 register u_char r_val = bcs->hw.tiger.r_val;
408 register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
409 u_int *p = buf;
410 int bits;
411 u_char mask;
412
413 if (bcs->mode == L1_MODE_HDLC) { // it's 64k
414 mask = 0xff;
415 bits = 8;
416 }
417 else { // it's 56K
418 mask = 0x7f;
419 bits = 7;
420 };
421 for (i=0;i<cnt;i++) {
422 val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff);
423 p++;
424 if (p > pend)
425 p = bcs->hw.tiger.rec;
426 if ((val & mask) == mask) {
427 state = HDLC_ZERO_SEARCH;
428 bcs->hw.tiger.r_tot++;
429 bitcnt = 0;
430 r_one = 0;
431 continue;
432 }
433 for (j=0;j<bits;j++) {
434 if (state == HDLC_ZERO_SEARCH) {
435 if (val & 1) {
436 r_one++;
437 } else {
438 r_one=0;
439 state= HDLC_FLAG_SEARCH;
440 if (bcs->cs->debug & L1_DEB_HSCX)
441 debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x",
442 bcs->hw.tiger.r_tot,i,j,val);
443 }
444 } else if (state == HDLC_FLAG_SEARCH) {
445 if (val & 1) {
446 r_one++;
447 if (r_one>6) {
448 state=HDLC_ZERO_SEARCH;
449 }
450 } else {
451 if (r_one==6) {
452 bitcnt=0;
453 r_val=0;
454 state=HDLC_FLAG_FOUND;
455 if (bcs->cs->debug & L1_DEB_HSCX)
456 debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x",
457 bcs->hw.tiger.r_tot,i,j,val);
458 }
459 r_one=0;
460 }
461 } else if (state == HDLC_FLAG_FOUND) {
462 if (val & 1) {
463 r_one++;
464 if (r_one>6) {
465 state=HDLC_ZERO_SEARCH;
466 } else {
467 r_val >>= 1;
468 r_val |= 0x80;
469 bitcnt++;
470 }
471 } else {
472 if (r_one==6) {
473 bitcnt=0;
474 r_val=0;
475 r_one=0;
476 val >>= 1;
477 continue;
478 } else if (r_one!=5) {
479 r_val >>= 1;
480 r_val &= 0x7f;
481 bitcnt++;
482 }
483 r_one=0;
484 }
485 if ((state != HDLC_ZERO_SEARCH) &&
486 !(bitcnt & 7)) {
487 state=HDLC_FRAME_FOUND;
488 bcs->hw.tiger.r_fcs = PPP_INITFCS;
489 bcs->hw.tiger.rcvbuf[0] = r_val;
490 bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
491 if (bcs->cs->debug & L1_DEB_HSCX)
492 debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
493 bcs->hw.tiger.r_tot,i,j,r_val,val,
494 bcs->cs->hw.njet.irqstat0);
495 }
496 } else if (state == HDLC_FRAME_FOUND) {
497 if (val & 1) {
498 r_one++;
499 if (r_one>6) {
500 state=HDLC_ZERO_SEARCH;
501 bitcnt=0;
502 } else {
503 r_val >>= 1;
504 r_val |= 0x80;
505 bitcnt++;
506 }
507 } else {
508 if (r_one==6) {
509 r_val=0;
510 r_one=0;
511 bitcnt++;
512 if (bitcnt & 7) {
513 debugl1(bcs->cs, "tiger: frame not byte aligned");
514 state=HDLC_FLAG_SEARCH;
515 bcs->hw.tiger.r_err++;
516#ifdef ERROR_STATISTIC
517 bcs->err_inv++;
518#endif
519 } else {
520 if (bcs->cs->debug & L1_DEB_HSCX)
521 debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x",
522 i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0);
523 if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) {
524 got_frame(bcs, (bitcnt>>3)-3);
525 } else {
526 if (bcs->cs->debug) {
527 debugl1(bcs->cs, "tiger FCS error");
528 printframe(bcs->cs, bcs->hw.tiger.rcvbuf,
529 (bitcnt>>3)-1, "rec");
530 bcs->hw.tiger.r_err++;
531 }
532#ifdef ERROR_STATISTIC
533 bcs->err_crc++;
534#endif
535 }
536 state=HDLC_FLAG_FOUND;
537 }
538 bitcnt=0;
539 } else if (r_one==5) {
540 val >>= 1;
541 r_one=0;
542 continue;
543 } else {
544 r_val >>= 1;
545 r_val &= 0x7f;
546 bitcnt++;
547 }
548 r_one=0;
549 }
550 if ((state == HDLC_FRAME_FOUND) &&
551 !(bitcnt & 7)) {
552 if ((bitcnt>>3)>=HSCX_BUFMAX) {
553 debugl1(bcs->cs, "tiger: frame too big");
554 r_val=0;
555 state=HDLC_FLAG_SEARCH;
556 bcs->hw.tiger.r_err++;
557#ifdef ERROR_STATISTIC
558 bcs->err_inv++;
559#endif
560 } else {
561 bcs->hw.tiger.rcvbuf[(bitcnt>>3)-1] = r_val;
562 bcs->hw.tiger.r_fcs =
563 PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
564 }
565 }
566 }
567 val >>= 1;
568 }
569 bcs->hw.tiger.r_tot++;
570 }
571 bcs->hw.tiger.r_state = state;
572 bcs->hw.tiger.r_one = r_one;
573 bcs->hw.tiger.r_val = r_val;
574 bcs->hw.tiger.r_bitcnt = bitcnt;
575}
576
577void read_tiger(struct IsdnCardState *cs) {
578 u_int *p;
579 int cnt = NETJET_DMA_RXSIZE/2;
580
581 if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
582 debugl1(cs,"tiger warn read double dma %x/%x",
583 cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
584#ifdef ERROR_STATISTIC
585 if (cs->bcs[0].mode)
586 cs->bcs[0].err_rdo++;
587 if (cs->bcs[1].mode)
588 cs->bcs[1].err_rdo++;
589#endif
590 return;
591 } else {
592 cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ;
593 cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ);
594 }
595 if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1)
596 p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1;
597 else
598 p = cs->bcs[0].hw.tiger.rec + cnt - 1;
599 if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K))
600 read_raw(cs->bcs, p, cnt);
601
602 if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K))
603 read_raw(cs->bcs + 1, p, cnt);
604 cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ;
605}
606
607static void write_raw(struct BCState *bcs, u_int *buf, int cnt);
608
609void netjet_fill_dma(struct BCState *bcs)
610{
611 register u_int *p, *sp;
612 register int cnt;
613
614 if (!bcs->tx_skb)
615 return;
616 if (bcs->cs->debug & L1_DEB_HSCX)
617 debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel,
618 bcs->Flag);
619 if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
620 return;
621 if (bcs->mode == L1_MODE_HDLC) { // it's 64k
622 if (make_raw_data(bcs))
623 return;
624 }
625 else { // it's 56k
626 if (make_raw_data_56k(bcs))
627 return;
628 };
629 if (bcs->cs->debug & L1_DEB_HSCX)
630 debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
631 bcs->Flag);
632 if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
633 write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
634 } else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
635 p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR));
636 sp = bcs->hw.tiger.sendp;
637 if (p == bcs->hw.tiger.s_end)
638 p = bcs->hw.tiger.send -1;
639 if (sp == bcs->hw.tiger.s_end)
640 sp = bcs->hw.tiger.send -1;
641 cnt = p - sp;
642 if (cnt <0) {
643 write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
644 } else {
645 p++;
646 cnt++;
647 if (p > bcs->hw.tiger.s_end)
648 p = bcs->hw.tiger.send;
649 p++;
650 cnt++;
651 if (p > bcs->hw.tiger.s_end)
652 p = bcs->hw.tiger.send;
653 write_raw(bcs, p, bcs->hw.tiger.free - cnt);
654 }
655 } else if (test_and_clear_bit(BC_FLG_EMPTY, &bcs->Flag)) {
656 p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR));
657 cnt = bcs->hw.tiger.s_end - p;
658 if (cnt < 2) {
659 p = bcs->hw.tiger.send + 1;
660 cnt = NETJET_DMA_TXSIZE/2 - 2;
661 } else {
662 p++;
663 p++;
664 if (cnt <= (NETJET_DMA_TXSIZE/2))
665 cnt += NETJET_DMA_TXSIZE/2;
666 cnt--;
667 cnt--;
668 }
669 write_raw(bcs, p, cnt);
670 }
671 if (bcs->cs->debug & L1_DEB_HSCX)
672 debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel,
673 bcs->Flag);
674}
675
676static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
677 u_int mask, val, *p=buf;
678 u_int i, s_cnt;
679
680 if (cnt <= 0)
681 return;
682 if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {
683 if (bcs->hw.tiger.sendcnt> cnt) {
684 s_cnt = cnt;
685 bcs->hw.tiger.sendcnt -= cnt;
686 } else {
687 s_cnt = bcs->hw.tiger.sendcnt;
688 bcs->hw.tiger.sendcnt = 0;
689 }
690 if (bcs->channel)
691 mask = 0xffff00ff;
692 else
693 mask = 0xffffff00;
694 for (i=0; i<s_cnt; i++) {
695 val = bcs->channel ? ((bcs->hw.tiger.sp[i] <<8) & 0xff00) :
696 (bcs->hw.tiger.sp[i]);
697 *p &= mask;
698 *p++ |= val;
699 if (p>bcs->hw.tiger.s_end)
700 p = bcs->hw.tiger.send;
701 }
702 bcs->hw.tiger.s_tot += s_cnt;
703 if (bcs->cs->debug & L1_DEB_HSCX)
704 debugl1(bcs->cs,"tiger write_raw: c%d %p-%p %d/%d %d %x", bcs->channel,
705 buf, p, s_cnt, cnt,
706 bcs->hw.tiger.sendcnt, bcs->cs->hw.njet.irqstat0);
707 if (bcs->cs->debug & L1_DEB_HSCX_FIFO)
708 printframe(bcs->cs, bcs->hw.tiger.sp, s_cnt, "snd");
709 bcs->hw.tiger.sp += s_cnt;
710 bcs->hw.tiger.sendp = p;
711 if (!bcs->hw.tiger.sendcnt) {
712 if (!bcs->tx_skb) {
713 debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
714 } else {
715 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
716 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
717 u_long flags;
718 spin_lock_irqsave(&bcs->aclock, flags);
719 bcs->ackcnt += bcs->tx_skb->len;
720 spin_unlock_irqrestore(&bcs->aclock, flags);
721 schedule_event(bcs, B_ACKPENDING);
722 }
723 dev_kfree_skb_any(bcs->tx_skb);
724 bcs->tx_skb = NULL;
725 }
726 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
727 bcs->hw.tiger.free = cnt - s_cnt;
728 if (bcs->hw.tiger.free > (NETJET_DMA_TXSIZE/2))
729 test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
730 else {
731 test_and_clear_bit(BC_FLG_HALF, &bcs->Flag);
732 test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag);
733 }
734 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
735 netjet_fill_dma(bcs);
736 } else {
737 mask ^= 0xffffffff;
738 if (s_cnt < cnt) {
739 for (i=s_cnt; i<cnt;i++) {
740 *p++ |= mask;
741 if (p>bcs->hw.tiger.s_end)
742 p = bcs->hw.tiger.send;
743 }
744 if (bcs->cs->debug & L1_DEB_HSCX)
745 debugl1(bcs->cs, "tiger write_raw: fill rest %d",
746 cnt - s_cnt);
747 }
748 test_and_set_bit(B_XMTBUFREADY, &bcs->event);
749 schedule_work(&bcs->tqueue);
750 }
751 }
752 } else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
753 test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
754 fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
755 bcs->hw.tiger.free += cnt;
756 if (bcs->cs->debug & L1_DEB_HSCX)
757 debugl1(bcs->cs,"tiger write_raw: fill half");
758 } else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
759 test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
760 fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
761 if (bcs->cs->debug & L1_DEB_HSCX)
762 debugl1(bcs->cs,"tiger write_raw: fill full");
763 }
764}
765
766void write_tiger(struct IsdnCardState *cs) {
767 u_int *p, cnt = NETJET_DMA_TXSIZE/2;
768
769 if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
770 debugl1(cs,"tiger warn write double dma %x/%x",
771 cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
772#ifdef ERROR_STATISTIC
773 if (cs->bcs[0].mode)
774 cs->bcs[0].err_tx++;
775 if (cs->bcs[1].mode)
776 cs->bcs[1].err_tx++;
777#endif
778 return;
779 } else {
780 cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE;
781 cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE);
782 }
783 if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE_1)
784 p = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
785 else
786 p = cs->bcs[0].hw.tiger.send + cnt - 1;
787 if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K))
788 write_raw(cs->bcs, p, cnt);
789 if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K))
790 write_raw(cs->bcs + 1, p, cnt);
791 cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE;
792}
793
794static void
795tiger_l2l1(struct PStack *st, int pr, void *arg)
796{
797 struct BCState *bcs = st->l1.bcs;
798 struct sk_buff *skb = arg;
799 u_long flags;
800
801 switch (pr) {
802 case (PH_DATA | REQUEST):
803 spin_lock_irqsave(&bcs->cs->lock, flags);
804 if (bcs->tx_skb) {
805 skb_queue_tail(&bcs->squeue, skb);
806 } else {
807 bcs->tx_skb = skb;
808 bcs->cs->BC_Send_Data(bcs);
809 }
810 spin_unlock_irqrestore(&bcs->cs->lock, flags);
811 break;
812 case (PH_PULL | INDICATION):
813 spin_lock_irqsave(&bcs->cs->lock, flags);
814 if (bcs->tx_skb) {
815 printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
816 } else {
817 bcs->tx_skb = skb;
818 bcs->cs->BC_Send_Data(bcs);
819 }
820 spin_unlock_irqrestore(&bcs->cs->lock, flags);
821 break;
822 case (PH_PULL | REQUEST):
823 if (!bcs->tx_skb) {
824 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
825 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
826 } else
827 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
828 break;
829 case (PH_ACTIVATE | REQUEST):
830 spin_lock_irqsave(&bcs->cs->lock, flags);
831 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
832 mode_tiger(bcs, st->l1.mode, st->l1.bc);
833 /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
834 spin_unlock_irqrestore(&bcs->cs->lock, flags);
835 bcs->cs->cardmsg(bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc));
836 l1_msg_b(st, pr, arg);
837 break;
838 case (PH_DEACTIVATE | REQUEST):
839 /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
840 bcs->cs->cardmsg(bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc));
841 l1_msg_b(st, pr, arg);
842 break;
843 case (PH_DEACTIVATE | CONFIRM):
844 spin_lock_irqsave(&bcs->cs->lock, flags);
845 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
846 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
847 mode_tiger(bcs, 0, st->l1.bc);
848 spin_unlock_irqrestore(&bcs->cs->lock, flags);
849 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
850 break;
851 }
852}
853
854
855void
856close_tigerstate(struct BCState *bcs)
857{
858 mode_tiger(bcs, 0, bcs->channel);
859 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
860 if (bcs->hw.tiger.rcvbuf) {
861 kfree(bcs->hw.tiger.rcvbuf);
862 bcs->hw.tiger.rcvbuf = NULL;
863 }
864 if (bcs->hw.tiger.sendbuf) {
865 kfree(bcs->hw.tiger.sendbuf);
866 bcs->hw.tiger.sendbuf = NULL;
867 }
868 skb_queue_purge(&bcs->rqueue);
869 skb_queue_purge(&bcs->squeue);
870 if (bcs->tx_skb) {
871 dev_kfree_skb_any(bcs->tx_skb);
872 bcs->tx_skb = NULL;
873 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
874 }
875 }
876}
877
878static int
879open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs)
880{
881 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
882 if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
883 printk(KERN_WARNING
884 "HiSax: No memory for tiger.rcvbuf\n");
885 return (1);
886 }
887 if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
888 printk(KERN_WARNING
889 "HiSax: No memory for tiger.sendbuf\n");
890 return (1);
891 }
892 skb_queue_head_init(&bcs->rqueue);
893 skb_queue_head_init(&bcs->squeue);
894 }
895 bcs->tx_skb = NULL;
896 bcs->hw.tiger.sendcnt = 0;
897 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
898 bcs->event = 0;
899 bcs->tx_cnt = 0;
900 return (0);
901}
902
903int
904setstack_tiger(struct PStack *st, struct BCState *bcs)
905{
906 bcs->channel = st->l1.bc;
907 if (open_tigerstate(st->l1.hardware, bcs))
908 return (-1);
909 st->l1.bcs = bcs;
910 st->l2.l2l1 = tiger_l2l1;
911 setstack_manager(st);
912 bcs->st = st;
913 setstack_l1_B(st);
914 return (0);
915}
916
917
918void __init
919inittiger(struct IsdnCardState *cs)
920{
921 if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
922 GFP_KERNEL | GFP_DMA))) {
923 printk(KERN_WARNING
924 "HiSax: No memory for tiger.send\n");
925 return;
926 }
927 cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE/2 - 1;
928 cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
929 cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send;
930 cs->bcs[1].hw.tiger.s_irq = cs->bcs[0].hw.tiger.s_irq;
931 cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
932
933 memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_TXSIZE * sizeof(unsigned int));
934 debugl1(cs, "tiger: send buf %p - %p", cs->bcs[0].hw.tiger.send,
935 cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1);
936 outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
937 cs->hw.njet.base + NETJET_DMA_READ_START);
938 outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
939 cs->hw.njet.base + NETJET_DMA_READ_IRQ);
940 outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end),
941 cs->hw.njet.base + NETJET_DMA_READ_END);
942 if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int),
943 GFP_KERNEL | GFP_DMA))) {
944 printk(KERN_WARNING
945 "HiSax: No memory for tiger.rec\n");
946 return;
947 }
948 debugl1(cs, "tiger: rec buf %p - %p", cs->bcs[0].hw.tiger.rec,
949 cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1);
950 cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
951 memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_RXSIZE * sizeof(unsigned int));
952 outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
953 cs->hw.njet.base + NETJET_DMA_WRITE_START);
954 outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE/2 - 1),
955 cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
956 outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1),
957 cs->hw.njet.base + NETJET_DMA_WRITE_END);
958 debugl1(cs, "tiger: dmacfg %x/%x pulse=%d",
959 inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
960 inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
961 bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
962 cs->hw.njet.last_is0 = 0;
963 cs->bcs[0].BC_SetStack = setstack_tiger;
964 cs->bcs[1].BC_SetStack = setstack_tiger;
965 cs->bcs[0].BC_Close = close_tigerstate;
966 cs->bcs[1].BC_Close = close_tigerstate;
967}
968
969void
970releasetiger(struct IsdnCardState *cs)
971{
972 if (cs->bcs[0].hw.tiger.send) {
973 kfree(cs->bcs[0].hw.tiger.send);
974 cs->bcs[0].hw.tiger.send = NULL;
975 }
976 if (cs->bcs[1].hw.tiger.send) {
977 cs->bcs[1].hw.tiger.send = NULL;
978 }
979 if (cs->bcs[0].hw.tiger.rec) {
980 kfree(cs->bcs[0].hw.tiger.rec);
981 cs->bcs[0].hw.tiger.rec = NULL;
982 }
983 if (cs->bcs[1].hw.tiger.rec) {
984 cs->bcs[1].hw.tiger.rec = NULL;
985 }
986}
987
988void
989release_io_netjet(struct IsdnCardState *cs)
990{
991 byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
992 byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0);
993 releasetiger(cs);
994 release_region(cs->hw.njet.base, 256);
995}
996
diff --git a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h
new file mode 100644
index 00000000000..1080508f3c6
--- /dev/null
+++ b/drivers/isdn/hisax/netjet.h
@@ -0,0 +1,72 @@
1/* $Id: netjet.h,v 2.8.2.2 2004/01/12 22:52:28 keil Exp $
2 *
3 * NETjet common header file
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 * by Matt Henderson,
8 * Traverse Technologies P/L www.traverse.com.au
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 */
14
15extern const char *CardType[];
16
17#define byteout(addr,val) outb(val,addr)
18#define bytein(addr) inb(addr)
19
20#define NETJET_CTRL 0x00
21#define NETJET_DMACTRL 0x01
22#define NETJET_AUXCTRL 0x02
23#define NETJET_AUXDATA 0x03
24#define NETJET_IRQMASK0 0x04
25#define NETJET_IRQMASK1 0x05
26#define NETJET_IRQSTAT0 0x06
27#define NETJET_IRQSTAT1 0x07
28#define NETJET_DMA_READ_START 0x08
29#define NETJET_DMA_READ_IRQ 0x0c
30#define NETJET_DMA_READ_END 0x10
31#define NETJET_DMA_READ_ADR 0x14
32#define NETJET_DMA_WRITE_START 0x18
33#define NETJET_DMA_WRITE_IRQ 0x1c
34#define NETJET_DMA_WRITE_END 0x20
35#define NETJET_DMA_WRITE_ADR 0x24
36#define NETJET_PULSE_CNT 0x28
37
38#define NETJET_ISAC_OFF 0xc0
39#define NETJET_ISACIRQ 0x10
40#define NETJET_IRQM0_READ 0x0c
41#define NETJET_IRQM0_READ_1 0x04
42#define NETJET_IRQM0_READ_2 0x08
43#define NETJET_IRQM0_WRITE 0x03
44#define NETJET_IRQM0_WRITE_1 0x01
45#define NETJET_IRQM0_WRITE_2 0x02
46
47#define NETJET_DMA_TXSIZE 512
48#define NETJET_DMA_RXSIZE 128
49
50#define HDLC_ZERO_SEARCH 0
51#define HDLC_FLAG_SEARCH 1
52#define HDLC_FLAG_FOUND 2
53#define HDLC_FRAME_FOUND 3
54#define HDLC_NULL 4
55#define HDLC_PART 5
56#define HDLC_FULL 6
57
58#define HDLC_FLAG_VALUE 0x7e
59
60u_char NETjet_ReadIC(struct IsdnCardState *cs, u_char offset);
61void NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value);
62void NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size);
63void NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size);
64
65void read_tiger(struct IsdnCardState *cs);
66void write_tiger(struct IsdnCardState *cs);
67
68void netjet_fill_dma(struct BCState *bcs);
69void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs);
70void inittiger(struct IsdnCardState *cs);
71void release_io_netjet(struct IsdnCardState *cs);
72
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
new file mode 100644
index 00000000000..cf77d836097
--- /dev/null
+++ b/drivers/isdn/hisax/niccy.c
@@ -0,0 +1,389 @@
1/* $Id: niccy.c,v 1.21.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
4 * compatible (SAGEM cybermodem)
5 *
6 * Author Karsten Keil
7 * Copyright by Karsten Keil <keil@isdn4linux.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 * Thanks to Dr. Neuhaus and SAGEM for information
13 *
14 */
15
16
17#include <linux/config.h>
18#include <linux/init.h>
19#include "hisax.h"
20#include "isac.h"
21#include "hscx.h"
22#include "isdnl1.h"
23#include <linux/pci.h>
24#include <linux/isapnp.h>
25
26extern const char *CardType[];
27const char *niccy_revision = "$Revision: 1.21.2.4 $";
28
29#define byteout(addr,val) outb(val,addr)
30#define bytein(addr) inb(addr)
31
32#define ISAC_PCI_DATA 0
33#define HSCX_PCI_DATA 1
34#define ISAC_PCI_ADDR 2
35#define HSCX_PCI_ADDR 3
36#define ISAC_PNP 0
37#define HSCX_PNP 1
38
39/* SUB Types */
40#define NICCY_PNP 1
41#define NICCY_PCI 2
42
43/* PCI stuff */
44#define PCI_IRQ_CTRL_REG 0x38
45#define PCI_IRQ_ENABLE 0x1f00
46#define PCI_IRQ_DISABLE 0xff0000
47#define PCI_IRQ_ASSERT 0x800000
48
49static inline u_char
50readreg(unsigned int ale, unsigned int adr, u_char off)
51{
52 register u_char ret;
53
54 byteout(ale, off);
55 ret = bytein(adr);
56 return (ret);
57}
58
59static inline void
60readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
61{
62 byteout(ale, off);
63 insb(adr, data, size);
64}
65
66
67static inline void
68writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
69{
70 byteout(ale, off);
71 byteout(adr, data);
72}
73
74static inline void
75writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
76{
77 byteout(ale, off);
78 outsb(adr, data, size);
79}
80
81/* Interface functions */
82
83static u_char
84ReadISAC(struct IsdnCardState *cs, u_char offset)
85{
86 return (readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset));
87}
88
89static void
90WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
91{
92 writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset, value);
93}
94
95static void
96ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
97{
98 readfifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size);
99}
100
101static void
102WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
103{
104 writefifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size);
105}
106
107static u_char
108ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
109{
110 return (readreg(cs->hw.niccy.hscx_ale,
111 cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0)));
112}
113
114static void
115WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
116{
117 writereg(cs->hw.niccy.hscx_ale,
118 cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0), value);
119}
120
121#define READHSCX(cs, nr, reg) readreg(cs->hw.niccy.hscx_ale, \
122 cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0))
123#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.niccy.hscx_ale, \
124 cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0), data)
125
126#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.niccy.hscx_ale, \
127 cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt)
128
129#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.niccy.hscx_ale, \
130 cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt)
131
132#include "hscx_irq.c"
133
134static irqreturn_t
135niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
136{
137 struct IsdnCardState *cs = dev_id;
138 u_char val;
139 u_long flags;
140
141 spin_lock_irqsave(&cs->lock, flags);
142 if (cs->subtyp == NICCY_PCI) {
143 int ival;
144 ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
145 if (!(ival & PCI_IRQ_ASSERT)) { /* IRQ not for us (shared) */
146 spin_unlock_irqrestore(&cs->lock, flags);
147 return IRQ_NONE;
148 }
149 outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
150 }
151 val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
152 Start_HSCX:
153 if (val)
154 hscx_int_main(cs, val);
155 val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
156 Start_ISAC:
157 if (val)
158 isac_interrupt(cs, val);
159 val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
160 if (val) {
161 if (cs->debug & L1_DEB_HSCX)
162 debugl1(cs, "HSCX IntStat after IntRoutine");
163 goto Start_HSCX;
164 }
165 val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
166 if (val) {
167 if (cs->debug & L1_DEB_ISAC)
168 debugl1(cs, "ISAC IntStat after IntRoutine");
169 goto Start_ISAC;
170 }
171 writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
172 writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
173 writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
174 writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
175 writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
176 writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
177 spin_unlock_irqrestore(&cs->lock, flags);
178 return IRQ_HANDLED;
179}
180
181void
182release_io_niccy(struct IsdnCardState *cs)
183{
184 if (cs->subtyp == NICCY_PCI) {
185 int val;
186
187 val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
188 val &= PCI_IRQ_DISABLE;
189 outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
190 release_region(cs->hw.niccy.cfg_reg, 0x40);
191 release_region(cs->hw.niccy.isac, 4);
192 } else {
193 release_region(cs->hw.niccy.isac, 2);
194 release_region(cs->hw.niccy.isac_ale, 2);
195 }
196}
197
198static void
199niccy_reset(struct IsdnCardState *cs)
200{
201 if (cs->subtyp == NICCY_PCI) {
202 int val;
203
204 val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
205 val |= PCI_IRQ_ENABLE;
206 outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
207 }
208 inithscxisac(cs, 3);
209}
210
211static int
212niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
213{
214 u_long flags;
215
216 switch (mt) {
217 case CARD_RESET:
218 spin_lock_irqsave(&cs->lock, flags);
219 niccy_reset(cs);
220 spin_unlock_irqrestore(&cs->lock, flags);
221 return(0);
222 case CARD_RELEASE:
223 release_io_niccy(cs);
224 return(0);
225 case CARD_INIT:
226 spin_lock_irqsave(&cs->lock, flags);
227 niccy_reset(cs);
228 spin_unlock_irqrestore(&cs->lock, flags);
229 return(0);
230 case CARD_TEST:
231 return(0);
232 }
233 return(0);
234}
235
236static struct pci_dev *niccy_dev __initdata = NULL;
237#ifdef __ISAPNP__
238static struct pnp_card *pnp_c __devinitdata = NULL;
239#endif
240
241int __init
242setup_niccy(struct IsdnCard *card)
243{
244 struct IsdnCardState *cs = card->cs;
245 char tmp[64];
246
247 strcpy(tmp, niccy_revision);
248 printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp));
249 if (cs->typ != ISDN_CTYPE_NICCY)
250 return (0);
251#ifdef __ISAPNP__
252 if (!card->para[1] && isapnp_present()) {
253 struct pnp_dev *pnp_d = NULL;
254 int err;
255
256 if ((pnp_c = pnp_find_card(
257 ISAPNP_VENDOR('S', 'D', 'A'),
258 ISAPNP_FUNCTION(0x0150), pnp_c))) {
259 if (!(pnp_d = pnp_find_dev(pnp_c,
260 ISAPNP_VENDOR('S', 'D', 'A'),
261 ISAPNP_FUNCTION(0x0150), pnp_d))) {
262 printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n");
263 return (0);
264 }
265 pnp_disable_dev(pnp_d);
266 err = pnp_activate_dev(pnp_d);
267 if (err<0) {
268 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
269 __FUNCTION__, err);
270 return(0);
271 }
272 card->para[1] = pnp_port_start(pnp_d, 0);
273 card->para[2] = pnp_port_start(pnp_d, 1);
274 card->para[0] = pnp_irq(pnp_d, 0);
275 if (!card->para[0] || !card->para[1] || !card->para[2]) {
276 printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n",
277 card->para[0], card->para[1], card->para[2]);
278 pnp_disable_dev(pnp_d);
279 return(0);
280 }
281 } else {
282 printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n");
283 }
284 }
285#endif
286 if (card->para[1]) {
287 cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
288 cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
289 cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
290 cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
291 cs->hw.niccy.cfg_reg = 0;
292 cs->subtyp = NICCY_PNP;
293 cs->irq = card->para[0];
294 if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) {
295 printk(KERN_WARNING
296 "HiSax: %s data port %x-%x already in use\n",
297 CardType[card->typ],
298 cs->hw.niccy.isac,
299 cs->hw.niccy.isac + 1);
300 return (0);
301 }
302 if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) {
303 printk(KERN_WARNING
304 "HiSax: %s address port %x-%x already in use\n",
305 CardType[card->typ],
306 cs->hw.niccy.isac_ale,
307 cs->hw.niccy.isac_ale + 1);
308 release_region(cs->hw.niccy.isac, 2);
309 return (0);
310 }
311 } else {
312#ifdef CONFIG_PCI
313 u_int pci_ioaddr;
314 cs->subtyp = 0;
315 if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
316 PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
317 if (pci_enable_device(niccy_dev))
318 return(0);
319 /* get IRQ */
320 if (!niccy_dev->irq) {
321 printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
322 return(0);
323 }
324 cs->irq = niccy_dev->irq;
325 cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
326 if (!cs->hw.niccy.cfg_reg) {
327 printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
328 return(0);
329 }
330 pci_ioaddr = pci_resource_start(niccy_dev, 1);
331 if (!pci_ioaddr) {
332 printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
333 return(0);
334 }
335 cs->subtyp = NICCY_PCI;
336 } else {
337 printk(KERN_WARNING "Niccy: No PCI card found\n");
338 return(0);
339 }
340 cs->irq_flags |= SA_SHIRQ;
341 cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
342 cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
343 cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
344 cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
345 if (!request_region(cs->hw.niccy.isac, 4, "niccy")) {
346 printk(KERN_WARNING
347 "HiSax: %s data port %x-%x already in use\n",
348 CardType[card->typ],
349 cs->hw.niccy.isac,
350 cs->hw.niccy.isac + 4);
351 return (0);
352 }
353 if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) {
354 printk(KERN_WARNING
355 "HiSax: %s pci port %x-%x already in use\n",
356 CardType[card->typ],
357 cs->hw.niccy.cfg_reg,
358 cs->hw.niccy.cfg_reg + 0x40);
359 release_region(cs->hw.niccy.isac, 4);
360 return (0);
361 }
362#else
363 printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
364 printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
365 return (0);
366#endif /* CONFIG_PCI */
367 }
368 printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
369 CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
370 cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
371 setup_isac(cs);
372 cs->readisac = &ReadISAC;
373 cs->writeisac = &WriteISAC;
374 cs->readisacfifo = &ReadISACfifo;
375 cs->writeisacfifo = &WriteISACfifo;
376 cs->BC_Read_Reg = &ReadHSCX;
377 cs->BC_Write_Reg = &WriteHSCX;
378 cs->BC_Send_Data = &hscx_fill_fifo;
379 cs->cardmsg = &niccy_card_msg;
380 cs->irq_func = &niccy_interrupt;
381 ISACVersion(cs, "Niccy:");
382 if (HscxVersion(cs, "Niccy:")) {
383 printk(KERN_WARNING
384 "Niccy: wrong HSCX versions check IO address\n");
385 release_io_niccy(cs);
386 return (0);
387 }
388 return (1);
389}
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
new file mode 100644
index 00000000000..fd664697f82
--- /dev/null
+++ b/drivers/isdn/hisax/nj_s.c
@@ -0,0 +1,278 @@
1/* $Id: nj_s.c,v 2.13.2.4 2004/01/16 01:53:48 keil Exp $
2 *
3 * This software may be used and distributed according to the terms
4 * of the GNU General Public License, incorporated herein by reference.
5 *
6 */
7
8#include <linux/config.h>
9#include <linux/init.h>
10#include "hisax.h"
11#include "isac.h"
12#include "isdnl1.h"
13#include <linux/pci.h>
14#include <linux/interrupt.h>
15#include <linux/ppp_defs.h>
16#include "netjet.h"
17
18const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
19
20static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
21{
22 return(5);
23}
24
25static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value)
26{
27}
28
29static irqreturn_t
30netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
31{
32 struct IsdnCardState *cs = dev_id;
33 u_char val, s1val, s0val;
34 u_long flags;
35
36 spin_lock_irqsave(&cs->lock, flags);
37 s1val = bytein(cs->hw.njet.base + NETJET_IRQSTAT1);
38 if (!(s1val & NETJET_ISACIRQ)) {
39 val = NETjet_ReadIC(cs, ISAC_ISTA);
40 if (cs->debug & L1_DEB_ISAC)
41 debugl1(cs, "tiger: i1 %x %x", s1val, val);
42 if (val) {
43 isac_interrupt(cs, val);
44 NETjet_WriteIC(cs, ISAC_MASK, 0xFF);
45 NETjet_WriteIC(cs, ISAC_MASK, 0x0);
46 }
47 s1val = 1;
48 } else
49 s1val = 0;
50 /*
51 * read/write stat0 is better, because lower IRQ rate
52 * Note the IRQ is on for 125 us if a condition match
53 * thats long on modern CPU and so the IRQ is reentered
54 * all the time.
55 */
56 s0val = bytein(cs->hw.njet.base + NETJET_IRQSTAT0);
57 if ((s0val | s1val)==0) { // shared IRQ
58 spin_unlock_irqrestore(&cs->lock, flags);
59 return IRQ_NONE;
60 }
61 if (s0val)
62 byteout(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
63 /* start new code 13/07/00 GE */
64 /* set bits in sval to indicate which page is free */
65 if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
66 inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
67 /* the 2nd write page is free */
68 s0val = 0x08;
69 else /* the 1st write page is free */
70 s0val = 0x04;
71 if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
72 inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
73 /* the 2nd read page is free */
74 s0val |= 0x02;
75 else /* the 1st read page is free */
76 s0val |= 0x01;
77 if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */
78 {
79 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
80 printk(KERN_WARNING "nj LOCK_ATOMIC s0val %x->%x\n",
81 cs->hw.njet.last_is0, s0val);
82 spin_unlock_irqrestore(&cs->lock, flags);
83 return IRQ_HANDLED;
84 }
85 cs->hw.njet.irqstat0 = s0val;
86 if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
87 (cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
88 /* we have a read dma int */
89 read_tiger(cs);
90 if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) !=
91 (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
92 /* we have a write dma int */
93 write_tiger(cs);
94 /* end new code 13/07/00 GE */
95 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
96 }
97 spin_unlock_irqrestore(&cs->lock, flags);
98 return IRQ_HANDLED;
99}
100
101static void
102reset_netjet_s(struct IsdnCardState *cs)
103{
104 cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
105 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
106 mdelay(10);
107 /* now edge triggered for TJ320 GE 13/07/00 */
108 /* see comment in IRQ function */
109 if (cs->subtyp) /* TJ320 */
110 cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */
111 else
112 cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
113 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
114 mdelay(10);
115 cs->hw.njet.auxd = 0;
116 cs->hw.njet.dmactrl = 0;
117 byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
118 byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
119 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
120}
121
122static int
123NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
124{
125 u_long flags;
126
127 switch (mt) {
128 case CARD_RESET:
129 spin_lock_irqsave(&cs->lock, flags);
130 reset_netjet_s(cs);
131 spin_unlock_irqrestore(&cs->lock, flags);
132 return(0);
133 case CARD_RELEASE:
134 release_io_netjet(cs);
135 return(0);
136 case CARD_INIT:
137 reset_netjet_s(cs);
138 inittiger(cs);
139 spin_lock_irqsave(&cs->lock, flags);
140 clear_pending_isac_ints(cs);
141 initisac(cs);
142 /* Reenable all IRQ */
143 cs->writeisac(cs, ISAC_MASK, 0);
144 spin_unlock_irqrestore(&cs->lock, flags);
145 return(0);
146 case CARD_TEST:
147 return(0);
148 }
149 return(0);
150}
151
152static struct pci_dev *dev_netjet __initdata = NULL;
153
154int __init
155setup_netjet_s(struct IsdnCard *card)
156{
157 int bytecnt,cfg;
158 struct IsdnCardState *cs = card->cs;
159 char tmp[64];
160
161#ifdef __BIG_ENDIAN
162#error "not running on big endian machines now"
163#endif
164 strcpy(tmp, NETjet_S_revision);
165 printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
166 if (cs->typ != ISDN_CTYPE_NETJET_S)
167 return(0);
168 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
169
170#ifdef CONFIG_PCI
171
172 for ( ;; )
173 {
174 if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
175 PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
176 if (pci_enable_device(dev_netjet))
177 return(0);
178 pci_set_master(dev_netjet);
179 cs->irq = dev_netjet->irq;
180 if (!cs->irq) {
181 printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
182 return(0);
183 }
184 cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
185 if (!cs->hw.njet.base) {
186 printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
187 return(0);
188 }
189 /* the TJ300 and TJ320 must be detected, the IRQ handling is different
190 * unfortunatly the chips use the same device ID, but the TJ320 has
191 * the bit20 in status PCI cfg register set
192 */
193 pci_read_config_dword(dev_netjet, 0x04, &cfg);
194 if (cfg & 0x00100000)
195 cs->subtyp = 1; /* TJ320 */
196 else
197 cs->subtyp = 0; /* TJ300 */
198 /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
199 if ((dev_netjet->subsystem_vendor == 0x55) &&
200 (dev_netjet->subsystem_device == 0x02)) {
201 printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
202 printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
203 return(0);
204 }
205 /* end new code */
206 } else {
207 printk(KERN_WARNING "NETjet-S: No PCI card found\n");
208 return(0);
209 }
210
211 cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
212 cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
213
214 cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
215 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
216 mdelay(10);
217
218 cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
219 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
220 mdelay(10);
221
222 cs->hw.njet.auxd = 0xC0;
223 cs->hw.njet.dmactrl = 0;
224
225 byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
226 byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
227 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
228
229 switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
230 {
231 case 0 :
232 break;
233
234 case 3 :
235 printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
236 continue;
237
238 default :
239 printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
240 return 0;
241 }
242 break;
243 }
244#else
245
246 printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n");
247 printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n");
248 return (0);
249
250#endif /* CONFIG_PCI */
251
252 bytecnt = 256;
253
254 printk(KERN_INFO
255 "NETjet-S: %s card configured at %#lx IRQ %d\n",
256 cs->subtyp ? "TJ320" : "TJ300", cs->hw.njet.base, cs->irq);
257 if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) {
258 printk(KERN_WARNING
259 "HiSax: %s config port %#lx-%#lx already in use\n",
260 CardType[card->typ],
261 cs->hw.njet.base,
262 cs->hw.njet.base + bytecnt);
263 return (0);
264 }
265 cs->readisac = &NETjet_ReadIC;
266 cs->writeisac = &NETjet_WriteIC;
267 cs->readisacfifo = &NETjet_ReadICfifo;
268 cs->writeisacfifo = &NETjet_WriteICfifo;
269 cs->BC_Read_Reg = &dummyrr;
270 cs->BC_Write_Reg = &dummywr;
271 cs->BC_Send_Data = &netjet_fill_dma;
272 setup_isac(cs);
273 cs->cardmsg = &NETjet_S_card_msg;
274 cs->irq_func = &netjet_s_interrupt;
275 cs->irq_flags |= SA_SHIRQ;
276 ISACVersion(cs, "NETjet-S:");
277 return (1);
278}
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
new file mode 100644
index 00000000000..3d6441e9633
--- /dev/null
+++ b/drivers/isdn/hisax/nj_u.c
@@ -0,0 +1,244 @@
1/* $Id: nj_u.c,v 2.14.2.3 2004/01/13 14:31:26 keil Exp $
2 *
3 * This software may be used and distributed according to the terms
4 * of the GNU General Public License, incorporated herein by reference.
5 *
6 */
7
8#include <linux/config.h>
9#include <linux/init.h>
10#include "hisax.h"
11#include "icc.h"
12#include "isdnl1.h"
13#include <linux/pci.h>
14#include <linux/interrupt.h>
15#include <linux/ppp_defs.h>
16#include "netjet.h"
17
18const char *NETjet_U_revision = "$Revision: 2.14.2.3 $";
19
20static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
21{
22 return(5);
23}
24
25static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value)
26{
27}
28
29static irqreturn_t
30netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
31{
32 struct IsdnCardState *cs = dev_id;
33 u_char val, sval;
34 u_long flags;
35
36 spin_lock_irqsave(&cs->lock, flags);
37 if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
38 NETJET_ISACIRQ)) {
39 val = NETjet_ReadIC(cs, ICC_ISTA);
40 if (cs->debug & L1_DEB_ISAC)
41 debugl1(cs, "tiger: i1 %x %x", sval, val);
42 if (val) {
43 icc_interrupt(cs, val);
44 NETjet_WriteIC(cs, ICC_MASK, 0xFF);
45 NETjet_WriteIC(cs, ICC_MASK, 0x0);
46 }
47 }
48 /* start new code 13/07/00 GE */
49 /* set bits in sval to indicate which page is free */
50 if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
51 inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
52 /* the 2nd write page is free */
53 sval = 0x08;
54 else /* the 1st write page is free */
55 sval = 0x04;
56 if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
57 inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
58 /* the 2nd read page is free */
59 sval = sval | 0x02;
60 else /* the 1st read page is free */
61 sval = sval | 0x01;
62 if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
63 {
64 if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
65 spin_unlock_irqrestore(&cs->lock, flags);
66 return IRQ_HANDLED;
67 }
68 cs->hw.njet.irqstat0 = sval;
69 if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
70 (cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
71 /* we have a read dma int */
72 read_tiger(cs);
73 if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) !=
74 (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
75 /* we have a write dma int */
76 write_tiger(cs);
77 /* end new code 13/07/00 GE */
78 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
79 }
80 spin_unlock_irqrestore(&cs->lock, flags);
81 return IRQ_HANDLED;
82}
83
84static void
85reset_netjet_u(struct IsdnCardState *cs)
86{
87 cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
88 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
89 mdelay(10);
90 cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */
91 /* now edge triggered for TJ320 GE 13/07/00 */
92 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
93 mdelay(10);
94 cs->hw.njet.auxd = 0xC0;
95 cs->hw.njet.dmactrl = 0;
96 byteout(cs->hw.njet.auxa, 0);
97 byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
98 byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
99 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
100}
101
102static int
103NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
104{
105 u_long flags;
106
107 switch (mt) {
108 case CARD_RESET:
109 spin_lock_irqsave(&cs->lock, flags);
110 reset_netjet_u(cs);
111 spin_unlock_irqrestore(&cs->lock, flags);
112 return(0);
113 case CARD_RELEASE:
114 release_io_netjet(cs);
115 return(0);
116 case CARD_INIT:
117 spin_lock_irqsave(&cs->lock, flags);
118 inittiger(cs);
119 reset_netjet_u(cs);
120 clear_pending_icc_ints(cs);
121 initicc(cs);
122 /* Reenable all IRQ */
123 cs->writeisac(cs, ICC_MASK, 0);
124 spin_unlock_irqrestore(&cs->lock, flags);
125 return(0);
126 case CARD_TEST:
127 return(0);
128 }
129 return(0);
130}
131
132static struct pci_dev *dev_netjet __initdata = NULL;
133
134int __init
135setup_netjet_u(struct IsdnCard *card)
136{
137 int bytecnt;
138 struct IsdnCardState *cs = card->cs;
139 char tmp[64];
140#ifdef CONFIG_PCI
141#endif
142#ifdef __BIG_ENDIAN
143#error "not running on big endian machines now"
144#endif
145 strcpy(tmp, NETjet_U_revision);
146 printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
147 if (cs->typ != ISDN_CTYPE_NETJET_U)
148 return(0);
149 test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
150
151#ifdef CONFIG_PCI
152
153 for ( ;; )
154 {
155 if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
156 PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
157 if (pci_enable_device(dev_netjet))
158 return(0);
159 pci_set_master(dev_netjet);
160 cs->irq = dev_netjet->irq;
161 if (!cs->irq) {
162 printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
163 return(0);
164 }
165 cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
166 if (!cs->hw.njet.base) {
167 printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
168 return(0);
169 }
170 } else {
171 printk(KERN_WARNING "NETspider-U: No PCI card found\n");
172 return(0);
173 }
174
175 cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
176 cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
177 mdelay(10);
178
179 cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
180 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
181 mdelay(10);
182
183 cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
184 byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
185 mdelay(10);
186
187 cs->hw.njet.auxd = 0xC0;
188 cs->hw.njet.dmactrl = 0;
189
190 byteout(cs->hw.njet.auxa, 0);
191 byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
192 byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
193 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
194
195 switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
196 {
197 case 3 :
198 break;
199
200 case 0 :
201 printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
202 continue;
203
204 default :
205 printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
206 return 0;
207 }
208 break;
209 }
210#else
211
212 printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n");
213 printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n");
214 return (0);
215
216#endif /* CONFIG_PCI */
217
218 bytecnt = 256;
219
220 printk(KERN_INFO
221 "NETspider-U: PCI card configured at %#lx IRQ %d\n",
222 cs->hw.njet.base, cs->irq);
223 if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) {
224 printk(KERN_WARNING
225 "HiSax: %s config port %#lx-%#lx already in use\n",
226 CardType[card->typ],
227 cs->hw.njet.base,
228 cs->hw.njet.base + bytecnt);
229 return (0);
230 }
231 setup_icc(cs);
232 cs->readisac = &NETjet_ReadIC;
233 cs->writeisac = &NETjet_WriteIC;
234 cs->readisacfifo = &NETjet_ReadICfifo;
235 cs->writeisacfifo = &NETjet_WriteICfifo;
236 cs->BC_Read_Reg = &dummyrr;
237 cs->BC_Write_Reg = &dummywr;
238 cs->BC_Send_Data = &netjet_fill_dma;
239 cs->cardmsg = &NETjet_U_card_msg;
240 cs->irq_func = &netjet_u_interrupt;
241 cs->irq_flags |= SA_SHIRQ;
242 ICCVersion(cs, "NETspider-U:");
243 return (1);
244}
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
new file mode 100644
index 00000000000..170fcd4a398
--- /dev/null
+++ b/drivers/isdn/hisax/q931.c
@@ -0,0 +1,1522 @@
1/* $Id: q931.c,v 1.12.2.3 2004/01/13 14:31:26 keil Exp $
2 *
3 * code to decode ITU Q.931 call control messages
4 *
5 * Author Jan den Ouden
6 * Copyright by Jan den Ouden
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 * Changelog:
12 *
13 * Pauline Middelink general improvements
14 * Beat Doebeli cause texts, display information element
15 * Karsten Keil cause texts, display information element for 1TR6
16 *
17 */
18
19
20#include "hisax.h"
21#include "l3_1tr6.h"
22
23void
24iecpy(u_char * dest, u_char * iestart, int ieoffset)
25{
26 u_char *p;
27 int l;
28
29 p = iestart + ieoffset + 2;
30 l = iestart[1] - ieoffset;
31 while (l--)
32 *dest++ = *p++;
33 *dest++ = '\0';
34}
35
36/*
37 * According to Table 4-2/Q.931
38 */
39static
40struct MessageType {
41 u_char nr;
42 char *descr;
43} mtlist[] = {
44
45 {
46 0x1, "ALERTING"
47 },
48 {
49 0x2, "CALL PROCEEDING"
50 },
51 {
52 0x7, "CONNECT"
53 },
54 {
55 0xf, "CONNECT ACKNOWLEDGE"
56 },
57 {
58 0x3, "PROGRESS"
59 },
60 {
61 0x5, "SETUP"
62 },
63 {
64 0xd, "SETUP ACKNOWLEDGE"
65 },
66 {
67 0x24, "HOLD"
68 },
69 {
70 0x28, "HOLD ACKNOWLEDGE"
71 },
72 {
73 0x30, "HOLD REJECT"
74 },
75 {
76 0x31, "RETRIEVE"
77 },
78 {
79 0x33, "RETRIEVE ACKNOWLEDGE"
80 },
81 {
82 0x37, "RETRIEVE REJECT"
83 },
84 {
85 0x26, "RESUME"
86 },
87 {
88 0x2e, "RESUME ACKNOWLEDGE"
89 },
90 {
91 0x22, "RESUME REJECT"
92 },
93 {
94 0x25, "SUSPEND"
95 },
96 {
97 0x2d, "SUSPEND ACKNOWLEDGE"
98 },
99 {
100 0x21, "SUSPEND REJECT"
101 },
102 {
103 0x20, "USER INFORMATION"
104 },
105 {
106 0x45, "DISCONNECT"
107 },
108 {
109 0x4d, "RELEASE"
110 },
111 {
112 0x5a, "RELEASE COMPLETE"
113 },
114 {
115 0x46, "RESTART"
116 },
117 {
118 0x4e, "RESTART ACKNOWLEDGE"
119 },
120 {
121 0x60, "SEGMENT"
122 },
123 {
124 0x79, "CONGESTION CONTROL"
125 },
126 {
127 0x7b, "INFORMATION"
128 },
129 {
130 0x62, "FACILITY"
131 },
132 {
133 0x6e, "NOTIFY"
134 },
135 {
136 0x7d, "STATUS"
137 },
138 {
139 0x75, "STATUS ENQUIRY"
140 }
141};
142
143#define MTSIZE sizeof(mtlist)/sizeof(struct MessageType)
144
145static
146struct MessageType mt_n0[] =
147{
148 {MT_N0_REG_IND, "REGister INDication"},
149 {MT_N0_CANC_IND, "CANCel INDication"},
150 {MT_N0_FAC_STA, "FACility STAtus"},
151 {MT_N0_STA_ACK, "STAtus ACKnowledge"},
152 {MT_N0_STA_REJ, "STAtus REJect"},
153 {MT_N0_FAC_INF, "FACility INFormation"},
154 {MT_N0_INF_ACK, "INFormation ACKnowledge"},
155 {MT_N0_INF_REJ, "INFormation REJect"},
156 {MT_N0_CLOSE, "CLOSE"},
157 {MT_N0_CLO_ACK, "CLOse ACKnowledge"}
158};
159
160#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
161
162static
163struct MessageType mt_n1[] =
164{
165 {MT_N1_ESC, "ESCape"},
166 {MT_N1_ALERT, "ALERT"},
167 {MT_N1_CALL_SENT, "CALL SENT"},
168 {MT_N1_CONN, "CONNect"},
169 {MT_N1_CONN_ACK, "CONNect ACKnowledge"},
170 {MT_N1_SETUP, "SETUP"},
171 {MT_N1_SETUP_ACK, "SETUP ACKnowledge"},
172 {MT_N1_RES, "RESume"},
173 {MT_N1_RES_ACK, "RESume ACKnowledge"},
174 {MT_N1_RES_REJ, "RESume REJect"},
175 {MT_N1_SUSP, "SUSPend"},
176 {MT_N1_SUSP_ACK, "SUSPend ACKnowledge"},
177 {MT_N1_SUSP_REJ, "SUSPend REJect"},
178 {MT_N1_USER_INFO, "USER INFO"},
179 {MT_N1_DET, "DETach"},
180 {MT_N1_DISC, "DISConnect"},
181 {MT_N1_REL, "RELease"},
182 {MT_N1_REL_ACK, "RELease ACKnowledge"},
183 {MT_N1_CANC_ACK, "CANCel ACKnowledge"},
184 {MT_N1_CANC_REJ, "CANCel REJect"},
185 {MT_N1_CON_CON, "CONgestion CONtrol"},
186 {MT_N1_FAC, "FACility"},
187 {MT_N1_FAC_ACK, "FACility ACKnowledge"},
188 {MT_N1_FAC_CAN, "FACility CANcel"},
189 {MT_N1_FAC_REG, "FACility REGister"},
190 {MT_N1_FAC_REJ, "FACility REJect"},
191 {MT_N1_INFO, "INFOrmation"},
192 {MT_N1_REG_ACK, "REGister ACKnowledge"},
193 {MT_N1_REG_REJ, "REGister REJect"},
194 {MT_N1_STAT, "STATus"}
195};
196
197#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
198
199
200static int
201prbits(char *dest, u_char b, int start, int len)
202{
203 char *dp = dest;
204
205 b = b << (8 - start);
206 while (len--) {
207 if (b & 0x80)
208 *dp++ = '1';
209 else
210 *dp++ = '0';
211 b = b << 1;
212 }
213 return (dp - dest);
214}
215
216static
217u_char *
218skipext(u_char * p)
219{
220 while (!(*p++ & 0x80));
221 return (p);
222}
223
224/*
225 * Cause Values According to Q.850
226 * edescr: English description
227 * ddescr: German description used by Swissnet II (Swiss Telecom
228 * not yet written...
229 */
230
231static
232struct CauseValue {
233 u_char nr;
234 char *edescr;
235 char *ddescr;
236} cvlist[] = {
237
238 {
239 0x01, "Unallocated (unassigned) number", "Nummer nicht zugeteilt"
240 },
241 {
242 0x02, "No route to specified transit network", ""
243 },
244 {
245 0x03, "No route to destination", ""
246 },
247 {
248 0x04, "Send special information tone", ""
249 },
250 {
251 0x05, "Misdialled trunk prefix", ""
252 },
253 {
254 0x06, "Channel unacceptable", "Kanal nicht akzeptierbar"
255 },
256 {
257 0x07, "Channel awarded and being delivered in an established channel", ""
258 },
259 {
260 0x08, "Preemption", ""
261 },
262 {
263 0x09, "Preemption - circuit reserved for reuse", ""
264 },
265 {
266 0x10, "Normal call clearing", "Normale Ausloesung"
267 },
268 {
269 0x11, "User busy", "TNB besetzt"
270 },
271 {
272 0x12, "No user responding", ""
273 },
274 {
275 0x13, "No answer from user (user alerted)", ""
276 },
277 {
278 0x14, "Subscriber absent", ""
279 },
280 {
281 0x15, "Call rejected", ""
282 },
283 {
284 0x16, "Number changed", ""
285 },
286 {
287 0x1a, "non-selected user clearing", ""
288 },
289 {
290 0x1b, "Destination out of order", ""
291 },
292 {
293 0x1c, "Invalid number format (address incomplete)", ""
294 },
295 {
296 0x1d, "Facility rejected", ""
297 },
298 {
299 0x1e, "Response to Status enquiry", ""
300 },
301 {
302 0x1f, "Normal, unspecified", ""
303 },
304 {
305 0x22, "No circuit/channel available", ""
306 },
307 {
308 0x26, "Network out of order", ""
309 },
310 {
311 0x27, "Permanent frame mode connection out-of-service", ""
312 },
313 {
314 0x28, "Permanent frame mode connection operational", ""
315 },
316 {
317 0x29, "Temporary failure", ""
318 },
319 {
320 0x2a, "Switching equipment congestion", ""
321 },
322 {
323 0x2b, "Access information discarded", ""
324 },
325 {
326 0x2c, "Requested circuit/channel not available", ""
327 },
328 {
329 0x2e, "Precedence call blocked", ""
330 },
331 {
332 0x2f, "Resource unavailable, unspecified", ""
333 },
334 {
335 0x31, "Quality of service unavailable", ""
336 },
337 {
338 0x32, "Requested facility not subscribed", ""
339 },
340 {
341 0x35, "Outgoing calls barred within CUG", ""
342 },
343 {
344 0x37, "Incoming calls barred within CUG", ""
345 },
346 {
347 0x39, "Bearer capability not authorized", ""
348 },
349 {
350 0x3a, "Bearer capability not presently available", ""
351 },
352 {
353 0x3e, "Inconsistency in designated outgoing access information and subscriber class ", " "
354 },
355 {
356 0x3f, "Service or option not available, unspecified", ""
357 },
358 {
359 0x41, "Bearer capability not implemented", ""
360 },
361 {
362 0x42, "Channel type not implemented", ""
363 },
364 {
365 0x43, "Requested facility not implemented", ""
366 },
367 {
368 0x44, "Only restricted digital information bearer capability is available", ""
369 },
370 {
371 0x4f, "Service or option not implemented", ""
372 },
373 {
374 0x51, "Invalid call reference value", ""
375 },
376 {
377 0x52, "Identified channel does not exist", ""
378 },
379 {
380 0x53, "A suspended call exists, but this call identity does not", ""
381 },
382 {
383 0x54, "Call identity in use", ""
384 },
385 {
386 0x55, "No call suspended", ""
387 },
388 {
389 0x56, "Call having the requested call identity has been cleared", ""
390 },
391 {
392 0x57, "User not member of CUG", ""
393 },
394 {
395 0x58, "Incompatible destination", ""
396 },
397 {
398 0x5a, "Non-existent CUG", ""
399 },
400 {
401 0x5b, "Invalid transit network selection", ""
402 },
403 {
404 0x5f, "Invalid message, unspecified", ""
405 },
406 {
407 0x60, "Mandatory information element is missing", ""
408 },
409 {
410 0x61, "Message type non-existent or not implemented", ""
411 },
412 {
413 0x62, "Message not compatible with call state or message type non-existent or not implemented ", " "
414 },
415 {
416 0x63, "Information element/parameter non-existent or not implemented", ""
417 },
418 {
419 0x64, "Invalid information element contents", ""
420 },
421 {
422 0x65, "Message not compatible with call state", ""
423 },
424 {
425 0x66, "Recovery on timer expiry", ""
426 },
427 {
428 0x67, "Parameter non-existent or not implemented - passed on", ""
429 },
430 {
431 0x6e, "Message with unrecognized parameter discarded", ""
432 },
433 {
434 0x6f, "Protocol error, unspecified", ""
435 },
436 {
437 0x7f, "Interworking, unspecified", ""
438 },
439};
440
441#define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue)
442
443static
444int
445prcause(char *dest, u_char * p)
446{
447 u_char *end;
448 char *dp = dest;
449 int i, cause;
450
451 end = p + p[1] + 1;
452 p += 2;
453 dp += sprintf(dp, " coding ");
454 dp += prbits(dp, *p, 7, 2);
455 dp += sprintf(dp, " location ");
456 dp += prbits(dp, *p, 4, 4);
457 *dp++ = '\n';
458 p = skipext(p);
459
460 cause = 0x7f & *p++;
461
462 /* locate cause value */
463 for (i = 0; i < CVSIZE; i++)
464 if (cvlist[i].nr == cause)
465 break;
466
467 /* display cause value if it exists */
468 if (i == CVSIZE)
469 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
470 else
471 dp += sprintf(dp, " cause value %x : %s \n", cause, cvlist[i].edescr);
472
473 while (!0) {
474 if (p > end)
475 break;
476 dp += sprintf(dp, " diag attribute %d ", *p++ & 0x7f);
477 dp += sprintf(dp, " rej %d ", *p & 0x7f);
478 if (*p & 0x80) {
479 *dp++ = '\n';
480 break;
481 } else
482 dp += sprintf(dp, " av %d\n", (*++p) & 0x7f);
483 }
484 return (dp - dest);
485
486}
487
488static
489struct MessageType cause_1tr6[] =
490{
491 {CAUSE_InvCRef, "Invalid Call Reference"},
492 {CAUSE_BearerNotImpl, "Bearer Service Not Implemented"},
493 {CAUSE_CIDunknown, "Caller Identity unknown"},
494 {CAUSE_CIDinUse, "Caller Identity in Use"},
495 {CAUSE_NoChans, "No Channels available"},
496 {CAUSE_FacNotImpl, "Facility Not Implemented"},
497 {CAUSE_FacNotSubscr, "Facility Not Subscribed"},
498 {CAUSE_OutgoingBarred, "Outgoing calls barred"},
499 {CAUSE_UserAccessBusy, "User Access Busy"},
500 {CAUSE_NegativeGBG, "Negative GBG"},
501 {CAUSE_UnknownGBG, "Unknown GBG"},
502 {CAUSE_NoSPVknown, "No SPV known"},
503 {CAUSE_DestNotObtain, "Destination not obtainable"},
504 {CAUSE_NumberChanged, "Number changed"},
505 {CAUSE_OutOfOrder, "Out Of Order"},
506 {CAUSE_NoUserResponse, "No User Response"},
507 {CAUSE_UserBusy, "User Busy"},
508 {CAUSE_IncomingBarred, "Incoming Barred"},
509 {CAUSE_CallRejected, "Call Rejected"},
510 {CAUSE_NetworkCongestion, "Network Congestion"},
511 {CAUSE_RemoteUser, "Remote User initiated"},
512 {CAUSE_LocalProcErr, "Local Procedure Error"},
513 {CAUSE_RemoteProcErr, "Remote Procedure Error"},
514 {CAUSE_RemoteUserSuspend, "Remote User Suspend"},
515 {CAUSE_RemoteUserResumed, "Remote User Resumed"},
516 {CAUSE_UserInfoDiscarded, "User Info Discarded"}
517};
518
519int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
520
521static int
522prcause_1tr6(char *dest, u_char * p)
523{
524 char *dp = dest;
525 int i, cause;
526
527 p++;
528 if (0 == *p) {
529 dp += sprintf(dp, " OK (cause length=0)\n");
530 return (dp - dest);
531 } else if (*p > 1) {
532 dp += sprintf(dp, " coding ");
533 dp += prbits(dp, p[2], 7, 2);
534 dp += sprintf(dp, " location ");
535 dp += prbits(dp, p[2], 4, 4);
536 *dp++ = '\n';
537 }
538 p++;
539 cause = 0x7f & *p;
540
541 /* locate cause value */
542 for (i = 0; i < cause_1tr6_len; i++)
543 if (cause_1tr6[i].nr == cause)
544 break;
545
546 /* display cause value if it exists */
547 if (i == cause_1tr6_len)
548 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
549 else
550 dp += sprintf(dp, " cause value %x : %s \n", cause, cause_1tr6[i].descr);
551
552 return (dp - dest);
553
554}
555
556static int
557prchident(char *dest, u_char * p)
558{
559 char *dp = dest;
560
561 p += 2;
562 dp += sprintf(dp, " octet 3 ");
563 dp += prbits(dp, *p, 8, 8);
564 *dp++ = '\n';
565 return (dp - dest);
566}
567
568static int
569prcalled(char *dest, u_char * p)
570{
571 int l;
572 char *dp = dest;
573
574 p++;
575 l = *p++ - 1;
576 dp += sprintf(dp, " octet 3 ");
577 dp += prbits(dp, *p++, 8, 8);
578 *dp++ = '\n';
579 dp += sprintf(dp, " number digits ");
580 while (l--)
581 *dp++ = *p++;
582 *dp++ = '\n';
583 return (dp - dest);
584}
585static int
586prcalling(char *dest, u_char * p)
587{
588 int l;
589 char *dp = dest;
590
591 p++;
592 l = *p++ - 1;
593 dp += sprintf(dp, " octet 3 ");
594 dp += prbits(dp, *p, 8, 8);
595 *dp++ = '\n';
596 if (!(*p & 0x80)) {
597 dp += sprintf(dp, " octet 3a ");
598 dp += prbits(dp, *++p, 8, 8);
599 *dp++ = '\n';
600 l--;
601 };
602 p++;
603
604 dp += sprintf(dp, " number digits ");
605 while (l--)
606 *dp++ = *p++;
607 *dp++ = '\n';
608 return (dp - dest);
609}
610
611static
612int
613prbearer(char *dest, u_char * p)
614{
615 char *dp = dest, ch;
616
617 p += 2;
618 dp += sprintf(dp, " octet 3 ");
619 dp += prbits(dp, *p++, 8, 8);
620 *dp++ = '\n';
621 dp += sprintf(dp, " octet 4 ");
622 dp += prbits(dp, *p, 8, 8);
623 *dp++ = '\n';
624 if ((*p++ & 0x1f) == 0x18) {
625 dp += sprintf(dp, " octet 4.1 ");
626 dp += prbits(dp, *p++, 8, 8);
627 *dp++ = '\n';
628 }
629 /* check for user information layer 1 */
630 if ((*p & 0x60) == 0x20) {
631 ch = ' ';
632 do {
633 dp += sprintf(dp, " octet 5%c ", ch);
634 dp += prbits(dp, *p, 8, 8);
635 *dp++ = '\n';
636 if (ch == ' ')
637 ch = 'a';
638 else
639 ch++;
640 }
641 while (!(*p++ & 0x80));
642 }
643 /* check for user information layer 2 */
644 if ((*p & 0x60) == 0x40) {
645 dp += sprintf(dp, " octet 6 ");
646 dp += prbits(dp, *p++, 8, 8);
647 *dp++ = '\n';
648 }
649 /* check for user information layer 3 */
650 if ((*p & 0x60) == 0x60) {
651 dp += sprintf(dp, " octet 7 ");
652 dp += prbits(dp, *p++, 8, 8);
653 *dp++ = '\n';
654 }
655 return (dp - dest);
656}
657
658
659static
660int
661prbearer_ni1(char *dest, u_char * p)
662{
663 char *dp = dest;
664 u_char len;
665
666 p++;
667 len = *p++;
668 dp += sprintf(dp, " octet 3 ");
669 dp += prbits(dp, *p, 8, 8);
670 switch (*p++) {
671 case 0x80:
672 dp += sprintf(dp, " Speech");
673 break;
674 case 0x88:
675 dp += sprintf(dp, " Unrestricted digital information");
676 break;
677 case 0x90:
678 dp += sprintf(dp, " 3.1 kHz audio");
679 break;
680 default:
681 dp += sprintf(dp, " Unknown information-transfer capability");
682 }
683 *dp++ = '\n';
684 dp += sprintf(dp, " octet 4 ");
685 dp += prbits(dp, *p, 8, 8);
686 switch (*p++) {
687 case 0x90:
688 dp += sprintf(dp, " 64 kbps, circuit mode");
689 break;
690 case 0xc0:
691 dp += sprintf(dp, " Packet mode");
692 break;
693 default:
694 dp += sprintf(dp, " Unknown transfer mode");
695 }
696 *dp++ = '\n';
697 if (len > 2) {
698 dp += sprintf(dp, " octet 5 ");
699 dp += prbits(dp, *p, 8, 8);
700 switch (*p++) {
701 case 0x21:
702 dp += sprintf(dp, " Rate adaption\n");
703 dp += sprintf(dp, " octet 5a ");
704 dp += prbits(dp, *p, 8, 8);
705 break;
706 case 0xa2:
707 dp += sprintf(dp, " u-law");
708 break;
709 default:
710 dp += sprintf(dp, " Unknown UI layer 1 protocol");
711 }
712 *dp++ = '\n';
713 }
714 return (dp - dest);
715}
716
717static int
718general(char *dest, u_char * p)
719{
720 char *dp = dest;
721 char ch = ' ';
722 int l, octet = 3;
723
724 p++;
725 l = *p++;
726 /* Iterate over all octets in the information element */
727 while (l--) {
728 dp += sprintf(dp, " octet %d%c ", octet, ch);
729 dp += prbits(dp, *p++, 8, 8);
730 *dp++ = '\n';
731
732 /* last octet in group? */
733 if (*p & 0x80) {
734 octet++;
735 ch = ' ';
736 } else if (ch == ' ')
737 ch = 'a';
738 else
739 ch++;
740 }
741 return (dp - dest);
742}
743
744static int
745general_ni1(char *dest, u_char * p)
746{
747 char *dp = dest;
748 char ch = ' ';
749 int l, octet = 3;
750
751 p++;
752 l = *p++;
753 /* Iterate over all octets in the information element */
754 while (l--) {
755 dp += sprintf(dp, " octet %d%c ", octet, ch);
756 dp += prbits(dp, *p, 8, 8);
757 *dp++ = '\n';
758
759 /* last octet in group? */
760 if (*p++ & 0x80) {
761 octet++;
762 ch = ' ';
763 } else if (ch == ' ')
764 ch = 'a';
765 else
766 ch++;
767 }
768 return (dp - dest);
769}
770
771static int
772prcharge(char *dest, u_char * p)
773{
774 char *dp = dest;
775 int l;
776
777 p++;
778 l = *p++ - 1;
779 dp += sprintf(dp, " GEA ");
780 dp += prbits(dp, *p++, 8, 8);
781 dp += sprintf(dp, " Anzahl: ");
782 /* Iterate over all octets in the * information element */
783 while (l--)
784 *dp++ = *p++;
785 *dp++ = '\n';
786 return (dp - dest);
787}
788static int
789prtext(char *dest, u_char * p)
790{
791 char *dp = dest;
792 int l;
793
794 p++;
795 l = *p++;
796 dp += sprintf(dp, " ");
797 /* Iterate over all octets in the * information element */
798 while (l--)
799 *dp++ = *p++;
800 *dp++ = '\n';
801 return (dp - dest);
802}
803
804static int
805prfeatureind(char *dest, u_char * p)
806{
807 char *dp = dest;
808
809 p += 2; /* skip id, len */
810 dp += sprintf(dp, " octet 3 ");
811 dp += prbits(dp, *p, 8, 8);
812 *dp++ = '\n';
813 if (!(*p++ & 80)) {
814 dp += sprintf(dp, " octet 4 ");
815 dp += prbits(dp, *p++, 8, 8);
816 *dp++ = '\n';
817 }
818 dp += sprintf(dp, " Status: ");
819 switch (*p) {
820 case 0:
821 dp += sprintf(dp, "Idle");
822 break;
823 case 1:
824 dp += sprintf(dp, "Active");
825 break;
826 case 2:
827 dp += sprintf(dp, "Prompt");
828 break;
829 case 3:
830 dp += sprintf(dp, "Pending");
831 break;
832 default:
833 dp += sprintf(dp, "(Reserved)");
834 break;
835 }
836 *dp++ = '\n';
837 return (dp - dest);
838}
839
840static
841struct DTag { /* Display tags */
842 u_char nr;
843 char *descr;
844} dtaglist[] = {
845 { 0x82, "Continuation" },
846 { 0x83, "Called address" },
847 { 0x84, "Cause" },
848 { 0x85, "Progress indicator" },
849 { 0x86, "Notification indicator" },
850 { 0x87, "Prompt" },
851 { 0x88, "Accumlated digits" },
852 { 0x89, "Status" },
853 { 0x8a, "Inband" },
854 { 0x8b, "Calling address" },
855 { 0x8c, "Reason" },
856 { 0x8d, "Calling party name" },
857 { 0x8e, "Called party name" },
858 { 0x8f, "Orignal called name" },
859 { 0x90, "Redirecting name" },
860 { 0x91, "Connected name" },
861 { 0x92, "Originating restrictions" },
862 { 0x93, "Date & time of day" },
863 { 0x94, "Call Appearance ID" },
864 { 0x95, "Feature address" },
865 { 0x96, "Redirection name" },
866 { 0x9e, "Text" },
867};
868#define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag)
869
870static int
871disptext_ni1(char *dest, u_char * p)
872{
873 char *dp = dest;
874 int l, tag, len, i;
875
876 p++;
877 l = *p++ - 1;
878 if (*p++ != 0x80) {
879 dp += sprintf(dp, " Unknown display type\n");
880 return (dp - dest);
881 }
882 /* Iterate over all tag,length,text fields */
883 while (l > 0) {
884 tag = *p++;
885 len = *p++;
886 l -= len + 2;
887 /* Don't space or skip */
888 if ((tag == 0x80) || (tag == 0x81)) p++;
889 else {
890 for (i = 0; i < DTAGSIZE; i++)
891 if (tag == dtaglist[i].nr)
892 break;
893
894 /* When not found, give appropriate msg */
895 if (i != DTAGSIZE) {
896 dp += sprintf(dp, " %s: ", dtaglist[i].descr);
897 while (len--)
898 *dp++ = *p++;
899 } else {
900 dp += sprintf(dp, " (unknown display tag %2x): ", tag);
901 while (len--)
902 *dp++ = *p++;
903 }
904 dp += sprintf(dp, "\n");
905 }
906 }
907 return (dp - dest);
908}
909static int
910display(char *dest, u_char * p)
911{
912 char *dp = dest;
913 char ch = ' ';
914 int l, octet = 3;
915
916 p++;
917 l = *p++;
918 /* Iterate over all octets in the * display-information element */
919 dp += sprintf(dp, " \"");
920 while (l--) {
921 dp += sprintf(dp, "%c", *p++);
922
923 /* last octet in group? */
924 if (*p & 0x80) {
925 octet++;
926 ch = ' ';
927 } else if (ch == ' ')
928 ch = 'a';
929
930 else
931 ch++;
932 }
933 *dp++ = '\"';
934 *dp++ = '\n';
935 return (dp - dest);
936}
937
938int
939prfacility(char *dest, u_char * p)
940{
941 char *dp = dest;
942 int l, l2;
943
944 p++;
945 l = *p++;
946 dp += sprintf(dp, " octet 3 ");
947 dp += prbits(dp, *p++, 8, 8);
948 dp += sprintf(dp, "\n");
949 l -= 1;
950
951 while (l > 0) {
952 dp += sprintf(dp, " octet 4 ");
953 dp += prbits(dp, *p++, 8, 8);
954 dp += sprintf(dp, "\n");
955 dp += sprintf(dp, " octet 5 %d\n", l2 = *p++ & 0x7f);
956 l -= 2;
957 dp += sprintf(dp, " contents ");
958 while (l2--) {
959 dp += sprintf(dp, "%2x ", *p++);
960 l--;
961 }
962 dp += sprintf(dp, "\n");
963 }
964
965 return (dp - dest);
966}
967
968static
969struct InformationElement {
970 u_char nr;
971 char *descr;
972 int (*f) (char *, u_char *);
973} ielist[] = {
974
975 {
976 0x00, "Segmented message", general
977 },
978 {
979 0x04, "Bearer capability", prbearer
980 },
981 {
982 0x08, "Cause", prcause
983 },
984 {
985 0x10, "Call identity", general
986 },
987 {
988 0x14, "Call state", general
989 },
990 {
991 0x18, "Channel identification", prchident
992 },
993 {
994 0x1c, "Facility", prfacility
995 },
996 {
997 0x1e, "Progress indicator", general
998 },
999 {
1000 0x20, "Network-specific facilities", general
1001 },
1002 {
1003 0x27, "Notification indicator", general
1004 },
1005 {
1006 0x28, "Display", display
1007 },
1008 {
1009 0x29, "Date/Time", general
1010 },
1011 {
1012 0x2c, "Keypad facility", general
1013 },
1014 {
1015 0x34, "Signal", general
1016 },
1017 {
1018 0x40, "Information rate", general
1019 },
1020 {
1021 0x42, "End-to-end delay", general
1022 },
1023 {
1024 0x43, "Transit delay selection and indication", general
1025 },
1026 {
1027 0x44, "Packet layer binary parameters", general
1028 },
1029 {
1030 0x45, "Packet layer window size", general
1031 },
1032 {
1033 0x46, "Packet size", general
1034 },
1035 {
1036 0x47, "Closed user group", general
1037 },
1038 {
1039 0x4a, "Reverse charge indication", general
1040 },
1041 {
1042 0x6c, "Calling party number", prcalling
1043 },
1044 {
1045 0x6d, "Calling party subaddress", general
1046 },
1047 {
1048 0x70, "Called party number", prcalled
1049 },
1050 {
1051 0x71, "Called party subaddress", general
1052 },
1053 {
1054 0x74, "Redirecting number", general
1055 },
1056 {
1057 0x78, "Transit network selection", general
1058 },
1059 {
1060 0x79, "Restart indicator", general
1061 },
1062 {
1063 0x7c, "Low layer compatibility", general
1064 },
1065 {
1066 0x7d, "High layer compatibility", general
1067 },
1068 {
1069 0x7e, "User-user", general
1070 },
1071 {
1072 0x7f, "Escape for extension", general
1073 },
1074};
1075
1076
1077#define IESIZE sizeof(ielist)/sizeof(struct InformationElement)
1078
1079static
1080struct InformationElement ielist_ni1[] = {
1081 { 0x04, "Bearer Capability", prbearer_ni1 },
1082 { 0x08, "Cause", prcause },
1083 { 0x14, "Call State", general_ni1 },
1084 { 0x18, "Channel Identification", prchident },
1085 { 0x1e, "Progress Indicator", general_ni1 },
1086 { 0x27, "Notification Indicator", general_ni1 },
1087 { 0x2c, "Keypad Facility", prtext },
1088 { 0x32, "Information Request", general_ni1 },
1089 { 0x34, "Signal", general_ni1 },
1090 { 0x38, "Feature Activation", general_ni1 },
1091 { 0x39, "Feature Indication", prfeatureind },
1092 { 0x3a, "Service Profile Identification (SPID)", prtext },
1093 { 0x3b, "Endpoint Identifier", general_ni1 },
1094 { 0x6c, "Calling Party Number", prcalling },
1095 { 0x6d, "Calling Party Subaddress", general_ni1 },
1096 { 0x70, "Called Party Number", prcalled },
1097 { 0x71, "Called Party Subaddress", general_ni1 },
1098 { 0x74, "Redirecting Number", general_ni1 },
1099 { 0x78, "Transit Network Selection", general_ni1 },
1100 { 0x7c, "Low Layer Compatibility", general_ni1 },
1101 { 0x7d, "High Layer Compatibility", general_ni1 },
1102};
1103
1104
1105#define IESIZE_NI1 sizeof(ielist_ni1)/sizeof(struct InformationElement)
1106
1107static
1108struct InformationElement ielist_ni1_cs5[] = {
1109 { 0x1d, "Operator system access", general_ni1 },
1110 { 0x2a, "Display text", disptext_ni1 },
1111};
1112
1113#define IESIZE_NI1_CS5 sizeof(ielist_ni1_cs5)/sizeof(struct InformationElement)
1114
1115static
1116struct InformationElement ielist_ni1_cs6[] = {
1117 { 0x7b, "Call appearance", general_ni1 },
1118};
1119
1120#define IESIZE_NI1_CS6 sizeof(ielist_ni1_cs6)/sizeof(struct InformationElement)
1121
1122static struct InformationElement we_0[] =
1123{
1124 {WE0_cause, "Cause", prcause_1tr6},
1125 {WE0_connAddr, "Connecting Address", prcalled},
1126 {WE0_callID, "Call IDentity", general},
1127 {WE0_chanID, "Channel IDentity", general},
1128 {WE0_netSpecFac, "Network Specific Facility", general},
1129 {WE0_display, "Display", general},
1130 {WE0_keypad, "Keypad", general},
1131 {WE0_origAddr, "Origination Address", prcalled},
1132 {WE0_destAddr, "Destination Address", prcalled},
1133 {WE0_userInfo, "User Info", general}
1134};
1135
1136#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
1137
1138static struct InformationElement we_6[] =
1139{
1140 {WE6_serviceInd, "Service Indicator", general},
1141 {WE6_chargingInfo, "Charging Information", prcharge},
1142 {WE6_date, "Date", prtext},
1143 {WE6_facSelect, "Facility Select", general},
1144 {WE6_facStatus, "Facility Status", general},
1145 {WE6_statusCalled, "Status Called", general},
1146 {WE6_addTransAttr, "Additional Transmission Attributes", general}
1147};
1148#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
1149
1150int
1151QuickHex(char *txt, u_char * p, int cnt)
1152{
1153 register int i;
1154 register char *t = txt;
1155 register u_char w;
1156
1157 for (i = 0; i < cnt; i++) {
1158 *t++ = ' ';
1159 w = (p[i] >> 4) & 0x0f;
1160 if (w < 10)
1161 *t++ = '0' + w;
1162 else
1163 *t++ = 'A' - 10 + w;
1164 w = p[i] & 0x0f;
1165 if (w < 10)
1166 *t++ = '0' + w;
1167 else
1168 *t++ = 'A' - 10 + w;
1169 }
1170 *t++ = 0;
1171 return (t - txt);
1172}
1173
1174void
1175LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
1176{
1177 char *dp;
1178
1179 if (size < 1)
1180 return;
1181 dp = cs->dlog;
1182 if (size < MAX_DLOG_SPACE / 3 - 10) {
1183 *dp++ = 'H';
1184 *dp++ = 'E';
1185 *dp++ = 'X';
1186 *dp++ = ':';
1187 dp += QuickHex(dp, buf, size);
1188 dp--;
1189 *dp++ = '\n';
1190 *dp = 0;
1191 HiSax_putstatus(cs, NULL, cs->dlog);
1192 } else
1193 HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
1194}
1195
1196void
1197dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
1198{
1199 u_char *bend, *buf;
1200 char *dp;
1201 unsigned char pd, cr_l, cr, mt;
1202 unsigned char sapi, tei, ftyp;
1203 int i, cset = 0, cs_old = 0, cs_fest = 0;
1204 int size, finish = 0;
1205
1206 if (skb->len < 3)
1207 return;
1208 /* display header */
1209 dp = cs->dlog;
1210 dp += jiftime(dp, jiffies);
1211 *dp++ = ' ';
1212 sapi = skb->data[0] >> 2;
1213 tei = skb->data[1] >> 1;
1214 ftyp = skb->data[2];
1215 buf = skb->data;
1216 dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
1217 size = skb->len;
1218
1219 if (tei == GROUP_TEI) {
1220 if (sapi == CTRL_SAPI) { /* sapi 0 */
1221 if (ftyp == 3) {
1222 dp += sprintf(dp, "broadcast\n");
1223 buf += 3;
1224 size -= 3;
1225 } else {
1226 dp += sprintf(dp, "no UI broadcast\n");
1227 finish = 1;
1228 }
1229 } else if (sapi == TEI_SAPI) {
1230 dp += sprintf(dp, "tei management\n");
1231 finish = 1;
1232 } else {
1233 dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi);
1234 finish = 1;
1235 }
1236 } else {
1237 if (sapi == CTRL_SAPI) {
1238 if (!(ftyp & 1)) { /* IFrame */
1239 dp += sprintf(dp, "with tei %d\n", tei);
1240 buf += 4;
1241 size -= 4;
1242 } else {
1243 dp += sprintf(dp, "SFrame with tei %d\n", tei);
1244 finish = 1;
1245 }
1246 } else {
1247 dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei);
1248 finish = 1;
1249 }
1250 }
1251 bend = skb->data + skb->len;
1252 if (buf >= bend) {
1253 dp += sprintf(dp, "frame too short\n");
1254 finish = 1;
1255 }
1256 if (finish) {
1257 *dp = 0;
1258 HiSax_putstatus(cs, NULL, cs->dlog);
1259 return;
1260 }
1261 if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */
1262 /* locate message type */
1263 pd = *buf++;
1264 cr_l = *buf++;
1265 if (cr_l)
1266 cr = *buf++;
1267 else
1268 cr = 0;
1269 mt = *buf++;
1270 if (pd == PROTO_DIS_N0) { /* N0 */
1271 for (i = 0; i < MT_N0_LEN; i++)
1272 if (mt_n0[i].nr == mt)
1273 break;
1274 /* display message type if it exists */
1275 if (i == MT_N0_LEN)
1276 dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n",
1277 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1278 size, mt);
1279 else
1280 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1281 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1282 size, mt_n0[i].descr);
1283 } else { /* N1 */
1284 for (i = 0; i < MT_N1_LEN; i++)
1285 if (mt_n1[i].nr == mt)
1286 break;
1287 /* display message type if it exists */
1288 if (i == MT_N1_LEN)
1289 dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n",
1290 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1291 size, mt);
1292 else
1293 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1294 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1295 size, mt_n1[i].descr);
1296 }
1297
1298 /* display each information element */
1299 while (buf < bend) {
1300 /* Is it a single octet information element? */
1301 if (*buf & 0x80) {
1302 switch ((*buf >> 4) & 7) {
1303 case 1:
1304 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1305 cs_old = cset;
1306 cset = *buf & 7;
1307 cs_fest = *buf & 8;
1308 break;
1309 case 3:
1310 dp += sprintf(dp, " Congestion level %x\n", *buf & 0xf);
1311 break;
1312 case 2:
1313 if (*buf == 0xa0) {
1314 dp += sprintf(dp, " More data\n");
1315 break;
1316 }
1317 if (*buf == 0xa1) {
1318 dp += sprintf(dp, " Sending complete\n");
1319 }
1320 break;
1321 /* fall through */
1322 default:
1323 dp += sprintf(dp, " Reserved %x\n", *buf);
1324 break;
1325 }
1326 buf++;
1327 continue;
1328 }
1329 /* No, locate it in the table */
1330 if (cset == 0) {
1331 for (i = 0; i < WE_0_LEN; i++)
1332 if (*buf == we_0[i].nr)
1333 break;
1334
1335 /* When found, give appropriate msg */
1336 if (i != WE_0_LEN) {
1337 dp += sprintf(dp, " %s\n", we_0[i].descr);
1338 dp += we_0[i].f(dp, buf);
1339 } else
1340 dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1341 } else if (cset == 6) {
1342 for (i = 0; i < WE_6_LEN; i++)
1343 if (*buf == we_6[i].nr)
1344 break;
1345
1346 /* When found, give appropriate msg */
1347 if (i != WE_6_LEN) {
1348 dp += sprintf(dp, " %s\n", we_6[i].descr);
1349 dp += we_6[i].f(dp, buf);
1350 } else
1351 dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1352 } else
1353 dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1354 /* Skip to next element */
1355 if (cs_fest == 8) {
1356 cset = cs_old;
1357 cs_old = 0;
1358 cs_fest = 0;
1359 }
1360 buf += buf[1] + 2;
1361 }
1362 } else if ((buf[0] == 8) && (cs->protocol == ISDN_PTYPE_NI1)) { /* NI-1 */
1363 /* locate message type */
1364 buf++;
1365 cr_l = *buf++;
1366 if (cr_l)
1367 cr = *buf++;
1368 else
1369 cr = 0;
1370 mt = *buf++;
1371 for (i = 0; i < MTSIZE; i++)
1372 if (mtlist[i].nr == mt)
1373 break;
1374
1375 /* display message type if it exists */
1376 if (i == MTSIZE)
1377 dp += sprintf(dp, "callref %d %s size %d unknown message type %x!\n",
1378 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1379 size, mt);
1380 else
1381 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1382 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1383 size, mtlist[i].descr);
1384
1385 /* display each information element */
1386 while (buf < bend) {
1387 /* Is it a single octet information element? */
1388 if (*buf & 0x80) {
1389 switch ((*buf >> 4) & 7) {
1390 case 1:
1391 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1392 cs_old = cset;
1393 cset = *buf & 7;
1394 cs_fest = *buf & 8;
1395 break;
1396 default:
1397 dp += sprintf(dp, " Unknown single-octet IE %x\n", *buf);
1398 break;
1399 }
1400 buf++;
1401 continue;
1402 }
1403 /* No, locate it in the table */
1404 if (cset == 0) {
1405 for (i = 0; i < IESIZE; i++)
1406 if (*buf == ielist_ni1[i].nr)
1407 break;
1408
1409 /* When not found, give appropriate msg */
1410 if (i != IESIZE) {
1411 dp += sprintf(dp, " %s\n", ielist_ni1[i].descr);
1412 dp += ielist_ni1[i].f(dp, buf);
1413 } else
1414 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1415 } else if (cset == 5) {
1416 for (i = 0; i < IESIZE_NI1_CS5; i++)
1417 if (*buf == ielist_ni1_cs5[i].nr)
1418 break;
1419
1420 /* When not found, give appropriate msg */
1421 if (i != IESIZE_NI1_CS5) {
1422 dp += sprintf(dp, " %s\n", ielist_ni1_cs5[i].descr);
1423 dp += ielist_ni1_cs5[i].f(dp, buf);
1424 } else
1425 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1426 } else if (cset == 6) {
1427 for (i = 0; i < IESIZE_NI1_CS6; i++)
1428 if (*buf == ielist_ni1_cs6[i].nr)
1429 break;
1430
1431 /* When not found, give appropriate msg */
1432 if (i != IESIZE_NI1_CS6) {
1433 dp += sprintf(dp, " %s\n", ielist_ni1_cs6[i].descr);
1434 dp += ielist_ni1_cs6[i].f(dp, buf);
1435 } else
1436 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1437 } else
1438 dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1439
1440 /* Skip to next element */
1441 if (cs_fest == 8) {
1442 cset = cs_old;
1443 cs_old = 0;
1444 cs_fest = 0;
1445 }
1446 buf += buf[1] + 2;
1447 }
1448 } else if ((buf[0] == 8) && (cs->protocol == ISDN_PTYPE_EURO)) { /* EURO */
1449 /* locate message type */
1450 buf++;
1451 cr_l = *buf++;
1452 if (cr_l)
1453 cr = *buf++;
1454 else
1455 cr = 0;
1456 mt = *buf++;
1457 for (i = 0; i < MTSIZE; i++)
1458 if (mtlist[i].nr == mt)
1459 break;
1460
1461 /* display message type if it exists */
1462 if (i == MTSIZE)
1463 dp += sprintf(dp, "callref %d %s size %d unknown message type %x!\n",
1464 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1465 size, mt);
1466 else
1467 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1468 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1469 size, mtlist[i].descr);
1470
1471 /* display each information element */
1472 while (buf < bend) {
1473 /* Is it a single octet information element? */
1474 if (*buf & 0x80) {
1475 switch ((*buf >> 4) & 7) {
1476 case 1:
1477 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1478 break;
1479 case 3:
1480 dp += sprintf(dp, " Congestion level %x\n", *buf & 0xf);
1481 break;
1482 case 5:
1483 dp += sprintf(dp, " Repeat indicator %x\n", *buf & 0xf);
1484 break;
1485 case 2:
1486 if (*buf == 0xa0) {
1487 dp += sprintf(dp, " More data\n");
1488 break;
1489 }
1490 if (*buf == 0xa1) {
1491 dp += sprintf(dp, " Sending complete\n");
1492 }
1493 break;
1494 /* fall through */
1495 default:
1496 dp += sprintf(dp, " Reserved %x\n", *buf);
1497 break;
1498 }
1499 buf++;
1500 continue;
1501 }
1502 /* No, locate it in the table */
1503 for (i = 0; i < IESIZE; i++)
1504 if (*buf == ielist[i].nr)
1505 break;
1506
1507 /* When not found, give appropriate msg */
1508 if (i != IESIZE) {
1509 dp += sprintf(dp, " %s\n", ielist[i].descr);
1510 dp += ielist[i].f(dp, buf);
1511 } else
1512 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1513
1514 /* Skip to next element */
1515 buf += buf[1] + 2;
1516 }
1517 } else {
1518 dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
1519 }
1520 *dp = 0;
1521 HiSax_putstatus(cs, NULL, cs->dlog);
1522}
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
new file mode 100644
index 00000000000..f3c481384a4
--- /dev/null
+++ b/drivers/isdn/hisax/s0box.c
@@ -0,0 +1,266 @@
1/* $Id: s0box.c,v 2.6.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for Creatix S0BOX
4 *
5 * Author Enrik Berkhan
6 * Copyright by Enrik Berkhan <enrik@starfleet.inka.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "isac.h"
16#include "hscx.h"
17#include "isdnl1.h"
18
19extern const char *CardType[];
20const char *s0box_revision = "$Revision: 2.6.2.4 $";
21
22static inline void
23writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
24 outb_p(0x1c,padr+2);
25 outb_p(0x14,padr+2);
26 outb_p((addr+off)&0x7f,padr);
27 outb_p(0x16,padr+2);
28 outb_p(val,padr);
29 outb_p(0x17,padr+2);
30 outb_p(0x14,padr+2);
31 outb_p(0x1c,padr+2);
32}
33
34static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
35 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ;
37
38static inline u_char
39readreg(unsigned int padr, signed int addr, u_char off) {
40 register u_char n1, n2;
41
42 outb_p(0x1c,padr+2);
43 outb_p(0x14,padr+2);
44 outb_p((addr+off)|0x80,padr);
45 outb_p(0x16,padr+2);
46 outb_p(0x17,padr+2);
47 n1 = (inb_p(padr+1) >> 3) & 0x17;
48 outb_p(0x16,padr+2);
49 n2 = (inb_p(padr+1) >> 3) & 0x17;
50 outb_p(0x14,padr+2);
51 outb_p(0x1c,padr+2);
52 return nibtab[n1] | (nibtab[n2] << 4);
53}
54
55static inline void
56read_fifo(unsigned int padr, signed int adr, u_char * data, int size)
57{
58 int i;
59 register u_char n1, n2;
60
61 outb_p(0x1c, padr+2);
62 outb_p(0x14, padr+2);
63 outb_p(adr|0x80, padr);
64 outb_p(0x16, padr+2);
65 for (i=0; i<size; i++) {
66 outb_p(0x17, padr+2);
67 n1 = (inb_p(padr+1) >> 3) & 0x17;
68 outb_p(0x16,padr+2);
69 n2 = (inb_p(padr+1) >> 3) & 0x17;
70 *(data++)=nibtab[n1] | (nibtab[n2] << 4);
71 }
72 outb_p(0x14,padr+2);
73 outb_p(0x1c,padr+2);
74 return;
75}
76
77static inline void
78write_fifo(unsigned int padr, signed int adr, u_char * data, int size)
79{
80 int i;
81 outb_p(0x1c, padr+2);
82 outb_p(0x14, padr+2);
83 outb_p(adr&0x7f, padr);
84 for (i=0; i<size; i++) {
85 outb_p(0x16, padr+2);
86 outb_p(*(data++), padr);
87 outb_p(0x17, padr+2);
88 }
89 outb_p(0x14,padr+2);
90 outb_p(0x1c,padr+2);
91 return;
92}
93
94/* Interface functions */
95
96static u_char
97ReadISAC(struct IsdnCardState *cs, u_char offset)
98{
99 return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset));
100}
101
102static void
103WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
104{
105 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value);
106}
107
108static void
109ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
110{
111 read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
112}
113
114static void
115WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
116{
117 write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
118}
119
120static u_char
121ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
122{
123 return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset));
124}
125
126static void
127WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
128{
129 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value);
130}
131
132/*
133 * fast interrupt HSCX stuff goes here
134 */
135
136#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg)
137#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data)
138#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
139#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
140
141#include "hscx_irq.c"
142
143static irqreturn_t
144s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
145{
146#define MAXCOUNT 5
147 struct IsdnCardState *cs = dev_id;
148 u_char val;
149 u_long flags;
150 int count = 0;
151
152 spin_lock_irqsave(&cs->lock, flags);
153 val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
154 Start_HSCX:
155 if (val)
156 hscx_int_main(cs, val);
157 val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
158 Start_ISAC:
159 if (val)
160 isac_interrupt(cs, val);
161 count++;
162 val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
163 if (val && count < MAXCOUNT) {
164 if (cs->debug & L1_DEB_HSCX)
165 debugl1(cs, "HSCX IntStat after IntRoutine");
166 goto Start_HSCX;
167 }
168 val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
169 if (val && count < MAXCOUNT) {
170 if (cs->debug & L1_DEB_ISAC)
171 debugl1(cs, "ISAC IntStat after IntRoutine");
172 goto Start_ISAC;
173 }
174 if (count >= MAXCOUNT)
175 printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
176 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
177 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
178 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
179 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
180 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
181 writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
182 spin_unlock_irqrestore(&cs->lock, flags);
183 return IRQ_HANDLED;
184}
185
186void
187release_io_s0box(struct IsdnCardState *cs)
188{
189 release_region(cs->hw.teles3.cfg_reg, 8);
190}
191
192static int
193S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
194{
195 u_long flags;
196
197 switch (mt) {
198 case CARD_RESET:
199 break;
200 case CARD_RELEASE:
201 release_io_s0box(cs);
202 break;
203 case CARD_INIT:
204 spin_lock_irqsave(&cs->lock, flags);
205 inithscxisac(cs, 3);
206 spin_unlock_irqrestore(&cs->lock, flags);
207 break;
208 case CARD_TEST:
209 break;
210 }
211 return(0);
212}
213
214int __init
215setup_s0box(struct IsdnCard *card)
216{
217 struct IsdnCardState *cs = card->cs;
218 char tmp[64];
219
220 strcpy(tmp, s0box_revision);
221 printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
222 if (cs->typ != ISDN_CTYPE_S0BOX)
223 return (0);
224
225 cs->hw.teles3.cfg_reg = card->para[1];
226 cs->hw.teles3.hscx[0] = -0x20;
227 cs->hw.teles3.hscx[1] = 0x0;
228 cs->hw.teles3.isac = 0x20;
229 cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
230 cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
231 cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
232 cs->irq = card->para[0];
233 if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
234 printk(KERN_WARNING
235 "HiSax: %s ports %x-%x already in use\n",
236 CardType[cs->typ],
237 cs->hw.teles3.cfg_reg,
238 cs->hw.teles3.cfg_reg + 7);
239 return 0;
240 }
241 printk(KERN_INFO
242 "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n",
243 CardType[cs->typ], cs->irq,
244 cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
245 printk(KERN_INFO
246 "HiSax: hscx A:0x%x hscx B:0x%x\n",
247 cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
248 setup_isac(cs);
249 cs->readisac = &ReadISAC;
250 cs->writeisac = &WriteISAC;
251 cs->readisacfifo = &ReadISACfifo;
252 cs->writeisacfifo = &WriteISACfifo;
253 cs->BC_Read_Reg = &ReadHSCX;
254 cs->BC_Write_Reg = &WriteHSCX;
255 cs->BC_Send_Data = &hscx_fill_fifo;
256 cs->cardmsg = &S0Box_card_msg;
257 cs->irq_func = &s0box_interrupt;
258 ISACVersion(cs, "S0Box:");
259 if (HscxVersion(cs, "S0Box:")) {
260 printk(KERN_WARNING
261 "S0Box: wrong HSCX versions check IO address\n");
262 release_io_s0box(cs);
263 return (0);
264 }
265 return (1);
266}
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
new file mode 100644
index 00000000000..9e6d3d686cc
--- /dev/null
+++ b/drivers/isdn/hisax/saphir.c
@@ -0,0 +1,300 @@
1/* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for HST Saphir 1
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * Thanks to HST High Soft Tech GmbH
12 *
13 */
14
15#include <linux/init.h>
16#include "hisax.h"
17#include "isac.h"
18#include "hscx.h"
19#include "isdnl1.h"
20
21extern const char *CardType[];
22static char *saphir_rev = "$Revision: 1.10.2.4 $";
23
24#define byteout(addr,val) outb(val,addr)
25#define bytein(addr) inb(addr)
26
27#define ISAC_DATA 0
28#define HSCX_DATA 1
29#define ADDRESS_REG 2
30#define IRQ_REG 3
31#define SPARE_REG 4
32#define RESET_REG 5
33
34static inline u_char
35readreg(unsigned int ale, unsigned int adr, u_char off)
36{
37 register u_char ret;
38
39 byteout(ale, off);
40 ret = bytein(adr);
41 return (ret);
42}
43
44static inline void
45readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
46{
47 byteout(ale, off);
48 insb(adr, data, size);
49}
50
51
52static inline void
53writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
54{
55 byteout(ale, off);
56 byteout(adr, data);
57}
58
59static inline void
60writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
61{
62 byteout(ale, off);
63 outsb(adr, data, size);
64}
65
66/* Interface functions */
67
68static u_char
69ReadISAC(struct IsdnCardState *cs, u_char offset)
70{
71 return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
72}
73
74static void
75WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
76{
77 writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
78}
79
80static void
81ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
82{
83 readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
84}
85
86static void
87WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
88{
89 writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
90}
91
92static u_char
93ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
94{
95 return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
96 offset + (hscx ? 0x40 : 0)));
97}
98
99static void
100WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
101{
102 writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
103 offset + (hscx ? 0x40 : 0), value);
104}
105
106#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
107 cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
108#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
109 cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
110
111#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
112 cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
113
114#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
115 cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
116
117#include "hscx_irq.c"
118
119static irqreturn_t
120saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
121{
122 struct IsdnCardState *cs = dev_id;
123 u_char val;
124 u_long flags;
125
126 spin_lock_irqsave(&cs->lock, flags);
127 val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
128 Start_HSCX:
129 if (val)
130 hscx_int_main(cs, val);
131 val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
132 Start_ISAC:
133 if (val)
134 isac_interrupt(cs, val);
135 val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
136 if (val) {
137 if (cs->debug & L1_DEB_HSCX)
138 debugl1(cs, "HSCX IntStat after IntRoutine");
139 goto Start_HSCX;
140 }
141 val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
142 if (val) {
143 if (cs->debug & L1_DEB_ISAC)
144 debugl1(cs, "ISAC IntStat after IntRoutine");
145 goto Start_ISAC;
146 }
147 /* Watchdog */
148 if (cs->hw.saphir.timer.function)
149 mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
150 else
151 printk(KERN_WARNING "saphir: Spurious timer!\n");
152 writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
153 writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
154 writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
155 writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
156 writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
157 writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
158 spin_unlock_irqrestore(&cs->lock, flags);
159 return IRQ_HANDLED;
160}
161
162static void
163SaphirWatchDog(struct IsdnCardState *cs)
164{
165 u_long flags;
166
167 spin_lock_irqsave(&cs->lock, flags);
168 /* 5 sec WatchDog, so read at least every 4 sec */
169 cs->readisac(cs, ISAC_RBCH);
170 spin_unlock_irqrestore(&cs->lock, flags);
171 mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
172}
173
174void
175release_io_saphir(struct IsdnCardState *cs)
176{
177 byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
178 del_timer(&cs->hw.saphir.timer);
179 cs->hw.saphir.timer.function = NULL;
180 if (cs->hw.saphir.cfg_reg)
181 release_region(cs->hw.saphir.cfg_reg, 6);
182}
183
184static int
185saphir_reset(struct IsdnCardState *cs)
186{
187 u_char irq_val;
188
189 switch(cs->irq) {
190 case 5: irq_val = 0;
191 break;
192 case 3: irq_val = 1;
193 break;
194 case 11:
195 irq_val = 2;
196 break;
197 case 12:
198 irq_val = 3;
199 break;
200 case 15:
201 irq_val = 4;
202 break;
203 default:
204 printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
205 cs->irq);
206 return (1);
207 }
208 byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
209 byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
210 mdelay(10);
211 byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
212 mdelay(10);
213 byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
214 byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
215 return (0);
216}
217
218static int
219saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
220{
221 u_long flags;
222
223 switch (mt) {
224 case CARD_RESET:
225 spin_lock_irqsave(&cs->lock, flags);
226 saphir_reset(cs);
227 spin_unlock_irqrestore(&cs->lock, flags);
228 return(0);
229 case CARD_RELEASE:
230 release_io_saphir(cs);
231 return(0);
232 case CARD_INIT:
233 spin_lock_irqsave(&cs->lock, flags);
234 inithscxisac(cs, 3);
235 spin_unlock_irqrestore(&cs->lock, flags);
236 return(0);
237 case CARD_TEST:
238 return(0);
239 }
240 return(0);
241}
242
243
244int __init
245setup_saphir(struct IsdnCard *card)
246{
247 struct IsdnCardState *cs = card->cs;
248 char tmp[64];
249
250 strcpy(tmp, saphir_rev);
251 printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
252 if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
253 return (0);
254
255 /* IO-Ports */
256 cs->hw.saphir.cfg_reg = card->para[1];
257 cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
258 cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
259 cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
260 cs->irq = card->para[0];
261 if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
262 printk(KERN_WARNING
263 "HiSax: %s config port %x-%x already in use\n",
264 CardType[card->typ],
265 cs->hw.saphir.cfg_reg,
266 cs->hw.saphir.cfg_reg + 5);
267 return (0);
268 }
269
270 printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
271 CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
272
273 setup_isac(cs);
274 cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
275 cs->hw.saphir.timer.data = (long) cs;
276 init_timer(&cs->hw.saphir.timer);
277 cs->hw.saphir.timer.expires = jiffies + 4*HZ;
278 add_timer(&cs->hw.saphir.timer);
279 if (saphir_reset(cs)) {
280 release_io_saphir(cs);
281 return (0);
282 }
283 cs->readisac = &ReadISAC;
284 cs->writeisac = &WriteISAC;
285 cs->readisacfifo = &ReadISACfifo;
286 cs->writeisacfifo = &WriteISACfifo;
287 cs->BC_Read_Reg = &ReadHSCX;
288 cs->BC_Write_Reg = &WriteHSCX;
289 cs->BC_Send_Data = &hscx_fill_fifo;
290 cs->cardmsg = &saphir_card_msg;
291 cs->irq_func = &saphir_interrupt;
292 ISACVersion(cs, "saphir:");
293 if (HscxVersion(cs, "saphir:")) {
294 printk(KERN_WARNING
295 "saphir: wrong HSCX versions check IO address\n");
296 release_io_saphir(cs);
297 return (0);
298 }
299 return (1);
300}
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
new file mode 100644
index 00000000000..8390f160685
--- /dev/null
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -0,0 +1,833 @@
1/* $Id: sedlbauer.c,v 1.34.2.6 2004/01/24 20:47:24 keil Exp $
2 *
3 * low level stuff for Sedlbauer cards
4 * includes support for the Sedlbauer speed star (speed star II),
5 * support for the Sedlbauer speed fax+,
6 * support for the Sedlbauer ISDN-Controller PC/104 and
7 * support for the Sedlbauer speed pci
8 * derived from the original file asuscom.c from Karsten Keil
9 *
10 * Author Marcus Niemann
11 * Copyright by Marcus Niemann <niemann@www-bib.fh-bielefeld.de>
12 *
13 * This software may be used and distributed according to the terms
14 * of the GNU General Public License, incorporated herein by reference.
15 *
16 * Thanks to Karsten Keil
17 * Sedlbauer AG for informations
18 * Edgar Toernig
19 *
20 */
21
22/* Supported cards:
23 * Card: Chip: Configuration: Comment:
24 * ---------------------------------------------------------------------
25 * Speed Card ISAC_HSCX DIP-SWITCH
26 * Speed Win ISAC_HSCX ISAPNP
27 * Speed Fax+ ISAC_ISAR ISAPNP Full analog support
28 * Speed Star ISAC_HSCX CARDMGR
29 * Speed Win2 IPAC ISAPNP
30 * ISDN PC/104 IPAC DIP-SWITCH
31 * Speed Star2 IPAC CARDMGR
32 * Speed PCI IPAC PCI PNP
33 * Speed Fax+ ISAC_ISAR PCI PNP Full analog support
34 *
35 * Important:
36 * For the sedlbauer speed fax+ to work properly you have to download
37 * the firmware onto the card.
38 * For example: hisaxctrl <DriverID> 9 ISAR.BIN
39*/
40
41#include <linux/init.h>
42#include <linux/config.h>
43#include "hisax.h"
44#include "isac.h"
45#include "ipac.h"
46#include "hscx.h"
47#include "isar.h"
48#include "isdnl1.h"
49#include <linux/pci.h>
50#include <linux/isapnp.h>
51
52extern const char *CardType[];
53
54const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $";
55
56const char *Sedlbauer_Types[] =
57 {"None", "speed card/win", "speed star", "speed fax+",
58 "speed win II / ISDN PC/104", "speed star II", "speed pci",
59 "speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
60
61#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
62#define PCI_SUBVENDOR_HST_SAPHIR3 0x52
63#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
64#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
65#define PCI_SUB_ID_SEDLBAUER 0x01
66
67#define SEDL_SPEED_CARD_WIN 1
68#define SEDL_SPEED_STAR 2
69#define SEDL_SPEED_FAX 3
70#define SEDL_SPEED_WIN2_PC104 4
71#define SEDL_SPEED_STAR2 5
72#define SEDL_SPEED_PCI 6
73#define SEDL_SPEEDFAX_PYRAMID 7
74#define SEDL_SPEEDFAX_PCI 8
75#define HST_SAPHIR3 9
76
77#define SEDL_CHIP_TEST 0
78#define SEDL_CHIP_ISAC_HSCX 1
79#define SEDL_CHIP_ISAC_ISAR 2
80#define SEDL_CHIP_IPAC 3
81
82#define SEDL_BUS_ISA 1
83#define SEDL_BUS_PCI 2
84#define SEDL_BUS_PCMCIA 3
85
86#define byteout(addr,val) outb(val,addr)
87#define bytein(addr) inb(addr)
88
89#define SEDL_HSCX_ISA_RESET_ON 0
90#define SEDL_HSCX_ISA_RESET_OFF 1
91#define SEDL_HSCX_ISA_ISAC 2
92#define SEDL_HSCX_ISA_HSCX 3
93#define SEDL_HSCX_ISA_ADR 4
94
95#define SEDL_HSCX_PCMCIA_RESET 0
96#define SEDL_HSCX_PCMCIA_ISAC 1
97#define SEDL_HSCX_PCMCIA_HSCX 2
98#define SEDL_HSCX_PCMCIA_ADR 4
99
100#define SEDL_ISAR_ISA_ISAC 4
101#define SEDL_ISAR_ISA_ISAR 6
102#define SEDL_ISAR_ISA_ADR 8
103#define SEDL_ISAR_ISA_ISAR_RESET_ON 10
104#define SEDL_ISAR_ISA_ISAR_RESET_OFF 12
105
106#define SEDL_IPAC_ANY_ADR 0
107#define SEDL_IPAC_ANY_IPAC 2
108
109#define SEDL_IPAC_PCI_BASE 0
110#define SEDL_IPAC_PCI_ADR 0xc0
111#define SEDL_IPAC_PCI_IPAC 0xc8
112#define SEDL_ISAR_PCI_ADR 0xc8
113#define SEDL_ISAR_PCI_ISAC 0xd0
114#define SEDL_ISAR_PCI_ISAR 0xe0
115#define SEDL_ISAR_PCI_ISAR_RESET_ON 0x01
116#define SEDL_ISAR_PCI_ISAR_RESET_OFF 0x18
117#define SEDL_ISAR_PCI_LED1 0x08
118#define SEDL_ISAR_PCI_LED2 0x10
119
120#define SEDL_RESET 0x3 /* same as DOS driver */
121
122static inline u_char
123readreg(unsigned int ale, unsigned int adr, u_char off)
124{
125 register u_char ret;
126
127 byteout(ale, off);
128 ret = bytein(adr);
129 return (ret);
130}
131
132static inline void
133readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
134{
135 byteout(ale, off);
136 insb(adr, data, size);
137}
138
139
140static inline void
141writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
142{
143 byteout(ale, off);
144 byteout(adr, data);
145}
146
147static inline void
148writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
149{
150 byteout(ale, off);
151 outsb(adr, data, size);
152}
153
154/* Interface functions */
155
156static u_char
157ReadISAC(struct IsdnCardState *cs, u_char offset)
158{
159 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset));
160}
161
162static void
163WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
164{
165 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value);
166}
167
168static void
169ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
170{
171 readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
172}
173
174static void
175WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
176{
177 writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size);
178}
179
180static u_char
181ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
182{
183 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));
184}
185
186static void
187WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
188{
189 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
190}
191
192static void
193ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
194{
195 readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
196}
197
198static void
199WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
200{
201 writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
202}
203
204static u_char
205ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
206{
207 return (readreg(cs->hw.sedl.adr,
208 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)));
209}
210
211static void
212WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
213{
214 writereg(cs->hw.sedl.adr,
215 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
216}
217
218/* ISAR access routines
219 * mode = 0 access with IRQ on
220 * mode = 1 access with IRQ off
221 * mode = 2 access with IRQ off and using last offset
222 */
223
224static u_char
225ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
226{
227 if (mode == 0)
228 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
229 else if (mode == 1)
230 byteout(cs->hw.sedl.adr, offset);
231 return(bytein(cs->hw.sedl.hscx));
232}
233
234static void
235WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
236{
237 if (mode == 0)
238 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
239 else {
240 if (mode == 1)
241 byteout(cs->hw.sedl.adr, offset);
242 byteout(cs->hw.sedl.hscx, value);
243 }
244}
245
246/*
247 * fast interrupt HSCX stuff goes here
248 */
249
250#define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \
251 cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0))
252#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \
253 cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data)
254
255#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \
256 cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
257
258#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \
259 cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt)
260
261#include "hscx_irq.c"
262
263static irqreturn_t
264sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
265{
266 struct IsdnCardState *cs = dev_id;
267 u_char val;
268 u_long flags;
269
270 spin_lock_irqsave(&cs->lock, flags);
271 if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
272 /* The card tends to generate interrupts while being removed
273 causing us to just crash the kernel. bad. */
274 spin_unlock_irqrestore(&cs->lock, flags);
275 printk(KERN_WARNING "Sedlbauer: card not available!\n");
276 return IRQ_NONE;
277 }
278
279 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
280 Start_HSCX:
281 if (val)
282 hscx_int_main(cs, val);
283 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
284 Start_ISAC:
285 if (val)
286 isac_interrupt(cs, val);
287 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
288 if (val) {
289 if (cs->debug & L1_DEB_HSCX)
290 debugl1(cs, "HSCX IntStat after IntRoutine");
291 goto Start_HSCX;
292 }
293 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
294 if (val) {
295 if (cs->debug & L1_DEB_ISAC)
296 debugl1(cs, "ISAC IntStat after IntRoutine");
297 goto Start_ISAC;
298 }
299 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
300 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
301 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
302 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
303 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
304 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
305 spin_unlock_irqrestore(&cs->lock, flags);
306 return IRQ_HANDLED;
307}
308
309static irqreturn_t
310sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
311{
312 struct IsdnCardState *cs = dev_id;
313 u_char ista, val, icnt = 5;
314 u_long flags;
315
316 spin_lock_irqsave(&cs->lock, flags);
317 ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
318Start_IPAC:
319 if (cs->debug & L1_DEB_IPAC)
320 debugl1(cs, "IPAC ISTA %02X", ista);
321 if (ista & 0x0f) {
322 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
323 if (ista & 0x01)
324 val |= 0x01;
325 if (ista & 0x04)
326 val |= 0x02;
327 if (ista & 0x08)
328 val |= 0x04;
329 if (val)
330 hscx_int_main(cs, val);
331 }
332 if (ista & 0x20) {
333 val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
334 if (val) {
335 isac_interrupt(cs, val);
336 }
337 }
338 if (ista & 0x10) {
339 val = 0x01;
340 isac_interrupt(cs, val);
341 }
342 ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
343 if ((ista & 0x3f) && icnt) {
344 icnt--;
345 goto Start_IPAC;
346 }
347 if (!icnt)
348 if (cs->debug & L1_DEB_ISAC)
349 debugl1(cs, "Sedlbauer IRQ LOOP");
350 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
351 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
352 spin_unlock_irqrestore(&cs->lock, flags);
353 return IRQ_HANDLED;
354}
355
356static irqreturn_t
357sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
358{
359 struct IsdnCardState *cs = dev_id;
360 u_char val;
361 int cnt = 5;
362 u_long flags;
363
364 spin_lock_irqsave(&cs->lock, flags);
365 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
366 Start_ISAR:
367 if (val & ISAR_IRQSTA)
368 isar_int_main(cs);
369 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
370 Start_ISAC:
371 if (val)
372 isac_interrupt(cs, val);
373 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
374 if ((val & ISAR_IRQSTA) && --cnt) {
375 if (cs->debug & L1_DEB_HSCX)
376 debugl1(cs, "ISAR IntStat after IntRoutine");
377 goto Start_ISAR;
378 }
379 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
380 if (val && --cnt) {
381 if (cs->debug & L1_DEB_ISAC)
382 debugl1(cs, "ISAC IntStat after IntRoutine");
383 goto Start_ISAC;
384 }
385 if (!cnt)
386 if (cs->debug & L1_DEB_ISAC)
387 debugl1(cs, "Sedlbauer IRQ LOOP");
388
389 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
390 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
391 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
392 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
393 spin_unlock_irqrestore(&cs->lock, flags);
394 return IRQ_HANDLED;
395}
396
397void
398release_io_sedlbauer(struct IsdnCardState *cs)
399{
400 int bytecnt = 8;
401
402 if (cs->subtyp == SEDL_SPEED_FAX) {
403 bytecnt = 16;
404 } else if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
405 bytecnt = 256;
406 }
407 if (cs->hw.sedl.cfg_reg)
408 release_region(cs->hw.sedl.cfg_reg, bytecnt);
409}
410
411static void
412reset_sedlbauer(struct IsdnCardState *cs)
413{
414 printk(KERN_INFO "Sedlbauer: resetting card\n");
415
416 if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
417 (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
418 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
419 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
420 mdelay(2);
421 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
422 mdelay(10);
423 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
424 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
425 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
426 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
427 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
428 } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) &&
429 (cs->hw.sedl.bus == SEDL_BUS_PCI)) {
430 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
431 mdelay(2);
432 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
433 mdelay(10);
434 } else {
435 byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
436 mdelay(2);
437 byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
438 mdelay(10);
439 }
440 }
441}
442
443static int
444Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
445{
446 u_long flags;
447
448 switch (mt) {
449 case CARD_RESET:
450 spin_lock_irqsave(&cs->lock, flags);
451 reset_sedlbauer(cs);
452 spin_unlock_irqrestore(&cs->lock, flags);
453 return(0);
454 case CARD_RELEASE:
455 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
456 spin_lock_irqsave(&cs->lock, flags);
457 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
458 ISAR_IRQBIT, 0);
459 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
460 ISAC_MASK, 0xFF);
461 reset_sedlbauer(cs);
462 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
463 ISAR_IRQBIT, 0);
464 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac,
465 ISAC_MASK, 0xFF);
466 spin_unlock_irqrestore(&cs->lock, flags);
467 }
468 release_io_sedlbauer(cs);
469 return(0);
470 case CARD_INIT:
471 spin_lock_irqsave(&cs->lock, flags);
472 reset_sedlbauer(cs);
473 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
474 clear_pending_isac_ints(cs);
475 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
476 ISAR_IRQBIT, 0);
477 initisac(cs);
478 initisar(cs);
479 /* Reenable all IRQ */
480 cs->writeisac(cs, ISAC_MASK, 0);
481 /* RESET Receiver and Transmitter */
482 cs->writeisac(cs, ISAC_CMDR, 0x41);
483 } else {
484 inithscxisac(cs, 3);
485 }
486 spin_unlock_irqrestore(&cs->lock, flags);
487 return(0);
488 case CARD_TEST:
489 return(0);
490 case MDL_INFO_CONN:
491 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
492 return(0);
493 spin_lock_irqsave(&cs->lock, flags);
494 if ((long) arg)
495 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2;
496 else
497 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1;
498 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
499 spin_unlock_irqrestore(&cs->lock, flags);
500 break;
501 case MDL_INFO_REL:
502 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID)
503 return(0);
504 spin_lock_irqsave(&cs->lock, flags);
505 if ((long) arg)
506 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2;
507 else
508 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1;
509 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
510 spin_unlock_irqrestore(&cs->lock, flags);
511 break;
512 }
513 return(0);
514}
515
516static struct pci_dev *dev_sedl __devinitdata = NULL;
517
518#ifdef __ISAPNP__
519static struct isapnp_device_id sedl_ids[] __devinitdata = {
520 { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
521 ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
522 (unsigned long) "Speed win" },
523 { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
524 ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
525 (unsigned long) "Speed Fax+" },
526 { 0, }
527};
528
529static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0];
530static struct pnp_card *pnp_c __devinitdata = NULL;
531#endif
532
533int __devinit
534setup_sedlbauer(struct IsdnCard *card)
535{
536 int bytecnt, ver, val;
537 struct IsdnCardState *cs = card->cs;
538 char tmp[64];
539 u16 sub_vendor_id, sub_id;
540
541 strcpy(tmp, Sedlbauer_revision);
542 printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
543
544 if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
545 cs->subtyp = SEDL_SPEED_CARD_WIN;
546 cs->hw.sedl.bus = SEDL_BUS_ISA;
547 cs->hw.sedl.chip = SEDL_CHIP_TEST;
548 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
549 cs->subtyp = SEDL_SPEED_STAR;
550 cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
551 cs->hw.sedl.chip = SEDL_CHIP_TEST;
552 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
553 cs->subtyp = SEDL_SPEED_FAX;
554 cs->hw.sedl.bus = SEDL_BUS_ISA;
555 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
556 } else
557 return (0);
558
559 bytecnt = 8;
560 if (card->para[1]) {
561 cs->hw.sedl.cfg_reg = card->para[1];
562 cs->irq = card->para[0];
563 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
564 bytecnt = 16;
565 }
566 } else {
567#ifdef __ISAPNP__
568 if (isapnp_present()) {
569 struct pnp_dev *pnp_d;
570 while(ipid->card_vendor) {
571 if ((pnp_c = pnp_find_card(ipid->card_vendor,
572 ipid->card_device, pnp_c))) {
573 pnp_d = NULL;
574 if ((pnp_d = pnp_find_dev(pnp_c,
575 ipid->vendor, ipid->function, pnp_d))) {
576 int err;
577
578 printk(KERN_INFO "HiSax: %s detected\n",
579 (char *)ipid->driver_data);
580 pnp_disable_dev(pnp_d);
581 err = pnp_activate_dev(pnp_d);
582 if (err<0) {
583 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
584 __FUNCTION__, err);
585 return(0);
586 }
587 card->para[1] = pnp_port_start(pnp_d, 0);
588 card->para[0] = pnp_irq(pnp_d, 0);
589
590 if (!card->para[0] || !card->para[1]) {
591 printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
592 card->para[0], card->para[1]);
593 pnp_disable_dev(pnp_d);
594 return(0);
595 }
596 cs->hw.sedl.cfg_reg = card->para[1];
597 cs->irq = card->para[0];
598 if (ipid->function == ISAPNP_FUNCTION(0x2)) {
599 cs->subtyp = SEDL_SPEED_FAX;
600 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
601 bytecnt = 16;
602 } else {
603 cs->subtyp = SEDL_SPEED_CARD_WIN;
604 cs->hw.sedl.chip = SEDL_CHIP_TEST;
605 }
606 goto ready;
607 } else {
608 printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
609 return(0);
610 }
611 }
612 ipid++;
613 pnp_c = NULL;
614 }
615 if (!ipid->card_vendor) {
616 printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
617 }
618 }
619#endif
620/* Probe for Sedlbauer speed pci */
621#ifdef CONFIG_PCI
622 if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
623 PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
624 if (pci_enable_device(dev_sedl))
625 return(0);
626 cs->irq = dev_sedl->irq;
627 if (!cs->irq) {
628 printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
629 return(0);
630 }
631 cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
632 } else {
633 printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
634 return(0);
635 }
636 cs->irq_flags |= SA_SHIRQ;
637 cs->hw.sedl.bus = SEDL_BUS_PCI;
638 sub_vendor_id = dev_sedl->subsystem_vendor;
639 sub_id = dev_sedl->subsystem_device;
640 printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
641 sub_vendor_id, sub_id);
642 printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
643 cs->hw.sedl.cfg_reg);
644 if (sub_id != PCI_SUB_ID_SEDLBAUER) {
645 printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
646 return(0);
647 }
648 if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
649 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
650 cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
651 } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
652 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
653 cs->subtyp = SEDL_SPEEDFAX_PCI;
654 } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
655 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
656 cs->subtyp = HST_SAPHIR3;
657 } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
658 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
659 cs->subtyp = SEDL_SPEED_PCI;
660 } else {
661 printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
662 sub_vendor_id);
663 return(0);
664 }
665 bytecnt = 256;
666 cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
667 cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
668 byteout(cs->hw.sedl.cfg_reg, 0xff);
669 byteout(cs->hw.sedl.cfg_reg, 0x00);
670 byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
671 byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
672 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
673 mdelay(2);
674 byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
675 mdelay(10);
676#else
677 printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
678 return (0);
679#endif /* CONFIG_PCI */
680 }
681ready:
682 /* In case of the sedlbauer pcmcia card, this region is in use,
683 * reserved for us by the card manager. So we do not check it
684 * here, it would fail.
685 */
686 if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
687 !request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) {
688 printk(KERN_WARNING
689 "HiSax: %s config port %x-%x already in use\n",
690 CardType[card->typ],
691 cs->hw.sedl.cfg_reg,
692 cs->hw.sedl.cfg_reg + bytecnt);
693 return (0);
694 }
695
696 printk(KERN_INFO
697 "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
698 cs->hw.sedl.cfg_reg,
699 cs->hw.sedl.cfg_reg + bytecnt,
700 cs->irq);
701
702 cs->BC_Read_Reg = &ReadHSCX;
703 cs->BC_Write_Reg = &WriteHSCX;
704 cs->BC_Send_Data = &hscx_fill_fifo;
705 cs->cardmsg = &Sedl_card_msg;
706
707/*
708 * testing ISA and PCMCIA Cards for IPAC, default is ISAC
709 * do not test for PCI card, because ports are different
710 * and PCI card uses only IPAC (for the moment)
711 */
712 if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
713 val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
714 cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
715 printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
716 if ((val == 1) || (val == 2)) {
717 /* IPAC */
718 cs->subtyp = SEDL_SPEED_WIN2_PC104;
719 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
720 cs->subtyp = SEDL_SPEED_STAR2;
721 }
722 cs->hw.sedl.chip = SEDL_CHIP_IPAC;
723 } else {
724 /* ISAC_HSCX oder ISAC_ISAR */
725 if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
726 cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
727 }
728 }
729 }
730
731/*
732 * hw.sedl.chip is now properly set
733 */
734 printk(KERN_INFO "Sedlbauer: %s detected\n",
735 Sedlbauer_Types[cs->subtyp]);
736
737 setup_isac(cs);
738 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
739 if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
740 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
741 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
742 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
743 } else {
744 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
745 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
746 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
747 }
748 test_and_set_bit(HW_IPAC, &cs->HW_Flags);
749 cs->readisac = &ReadISAC_IPAC;
750 cs->writeisac = &WriteISAC_IPAC;
751 cs->readisacfifo = &ReadISACfifo_IPAC;
752 cs->writeisacfifo = &WriteISACfifo_IPAC;
753 cs->irq_func = &sedlbauer_interrupt_ipac;
754 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID);
755 printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
756 } else {
757 /* ISAC_HSCX oder ISAC_ISAR */
758 cs->readisac = &ReadISAC;
759 cs->writeisac = &WriteISAC;
760 cs->readisacfifo = &ReadISACfifo;
761 cs->writeisacfifo = &WriteISACfifo;
762 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
763 if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
764 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
765 SEDL_ISAR_PCI_ADR;
766 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
767 SEDL_ISAR_PCI_ISAC;
768 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
769 SEDL_ISAR_PCI_ISAR;
770 } else {
771 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
772 SEDL_ISAR_ISA_ADR;
773 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
774 SEDL_ISAR_ISA_ISAC;
775 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
776 SEDL_ISAR_ISA_ISAR;
777 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
778 SEDL_ISAR_ISA_ISAR_RESET_ON;
779 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
780 SEDL_ISAR_ISA_ISAR_RESET_OFF;
781 }
782 cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
783 cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
784 test_and_set_bit(HW_ISAR, &cs->HW_Flags);
785 cs->irq_func = &sedlbauer_interrupt_isar;
786 cs->auxcmd = &isar_auxcmd;
787 ISACVersion(cs, "Sedlbauer:");
788 cs->BC_Read_Reg = &ReadISAR;
789 cs->BC_Write_Reg = &WriteISAR;
790 cs->BC_Send_Data = &isar_fill_fifo;
791 bytecnt = 3;
792 while (bytecnt) {
793 ver = ISARVersion(cs, "Sedlbauer:");
794 if (ver < 0)
795 printk(KERN_WARNING
796 "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
797 else
798 break;
799 reset_sedlbauer(cs);
800 bytecnt--;
801 }
802 if (!bytecnt) {
803 release_io_sedlbauer(cs);
804 return (0);
805 }
806 } else {
807 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
808 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
809 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
810 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
811 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
812 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
813 cs->irq_flags |= SA_SHIRQ;
814 } else {
815 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
816 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
817 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
818 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
819 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
820 }
821 cs->irq_func = &sedlbauer_interrupt;
822 ISACVersion(cs, "Sedlbauer:");
823
824 if (HscxVersion(cs, "Sedlbauer:")) {
825 printk(KERN_WARNING
826 "Sedlbauer: wrong HSCX versions check IO address\n");
827 release_io_sedlbauer(cs);
828 return (0);
829 }
830 }
831 }
832 return (1);
833}
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
new file mode 100644
index 00000000000..44965124147
--- /dev/null
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -0,0 +1,640 @@
1/*======================================================================
2
3 A Sedlbauer PCMCIA client driver
4
5 This driver is for the Sedlbauer Speed Star and Speed Star II,
6 which are ISDN PCMCIA Cards.
7
8 The contents of this file are subject to the Mozilla Public
9 License Version 1.1 (the "License"); you may not use this file
10 except in compliance with the License. You may obtain a copy of
11 the License at http://www.mozilla.org/MPL/
12
13 Software distributed under the License is distributed on an "AS
14 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 rights and limitations under the License.
17
18 The initial developer of the original code is David A. Hinds
19 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
20 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21
22 Modifications from dummy_cs.c are Copyright (C) 1999-2001 Marcus Niemann
23 <maniemann@users.sourceforge.net>. All Rights Reserved.
24
25 Alternatively, the contents of this file may be used under the
26 terms of the GNU General Public License version 2 (the "GPL"), in
27 which case the provisions of the GPL are applicable instead of the
28 above. If you wish to allow the use of your version of this file
29 only under the terms of the GPL and not to allow others to use
30 your version of this file under the MPL, indicate your decision
31 by deleting the provisions above and replace them with the notice
32 and other provisions required by the GPL. If you do not delete
33 the provisions above, a recipient may use your version of this
34 file under either the MPL or the GPL.
35
36======================================================================*/
37
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/init.h>
41#include <linux/sched.h>
42#include <linux/ptrace.h>
43#include <linux/slab.h>
44#include <linux/string.h>
45#include <linux/timer.h>
46#include <linux/ioport.h>
47#include <asm/io.h>
48#include <asm/system.h>
49
50#include <pcmcia/version.h>
51#include <pcmcia/cs_types.h>
52#include <pcmcia/cs.h>
53#include <pcmcia/cistpl.h>
54#include <pcmcia/cisreg.h>
55#include <pcmcia/ds.h>
56#include "hisax_cfg.h"
57
58MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards");
59MODULE_AUTHOR("Marcus Niemann");
60MODULE_LICENSE("Dual MPL/GPL");
61
62/*
63 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
64 you do not define PCMCIA_DEBUG at all, all the debug code will be
65 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
66 be present but disabled -- but it can then be enabled for specific
67 modules at load time with a 'pc_debug=#' option to insmod.
68*/
69
70#ifdef PCMCIA_DEBUG
71static int pc_debug = PCMCIA_DEBUG;
72module_param(pc_debug, int, 0);
73#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
74static char *version =
75"sedlbauer_cs.c 1.1a 2001/01/28 15:04:04 (M.Niemann)";
76#else
77#define DEBUG(n, args...)
78#endif
79
80
81/*====================================================================*/
82
83/* Parameters that can be set with 'insmod' */
84
85static int protocol = 2; /* EURO-ISDN Default */
86module_param(protocol, int, 0);
87
88/*====================================================================*/
89
90/*
91 The event() function is this driver's Card Services event handler.
92 It will be called by Card Services when an appropriate card status
93 event is received. The config() and release() entry points are
94 used to configure or release a socket, in response to card
95 insertion and ejection events. They are invoked from the sedlbauer
96 event handler.
97*/
98
99static void sedlbauer_config(dev_link_t *link);
100static void sedlbauer_release(dev_link_t *link);
101static int sedlbauer_event(event_t event, int priority,
102 event_callback_args_t *args);
103
104/*
105 The attach() and detach() entry points are used to create and destroy
106 "instances" of the driver, where each instance represents everything
107 needed to manage one actual PCMCIA card.
108*/
109
110static dev_link_t *sedlbauer_attach(void);
111static void sedlbauer_detach(dev_link_t *);
112
113/*
114 You'll also need to prototype all the functions that will actually
115 be used to talk to your device. See 'memory_cs' for a good example
116 of a fully self-sufficient driver; the other drivers rely more or
117 less on other parts of the kernel.
118*/
119
120/*
121 The dev_info variable is the "key" that is used to match up this
122 device driver with appropriate cards, through the card configuration
123 database.
124*/
125
126static dev_info_t dev_info = "sedlbauer_cs";
127
128/*
129 A linked list of "instances" of the sedlbauer device. Each actual
130 PCMCIA card corresponds to one device instance, and is described
131 by one dev_link_t structure (defined in ds.h).
132
133 You may not want to use a linked list for this -- for example, the
134 memory card driver uses an array of dev_link_t pointers, where minor
135 device numbers are used to derive the corresponding array index.
136*/
137
138static dev_link_t *dev_list = NULL;
139
140/*
141 A dev_link_t structure has fields for most things that are needed
142 to keep track of a socket, but there will usually be some device
143 specific information that also needs to be kept track of. The
144 'priv' pointer in a dev_link_t structure can be used to point to
145 a device-specific private data structure, like this.
146
147 To simplify the data structure handling, we actually include the
148 dev_link_t structure in the device's private data structure.
149
150 A driver needs to provide a dev_node_t structure for each device
151 on a card. In some cases, there is only one device per card (for
152 example, ethernet cards, modems). In other cases, there may be
153 many actual or logical devices (SCSI adapters, memory cards with
154 multiple partitions). The dev_node_t structures need to be kept
155 in a linked list starting at the 'dev' field of a dev_link_t
156 structure. We allocate them in the card's private data structure,
157 because they generally shouldn't be allocated dynamically.
158
159 In this case, we also provide a flag to indicate if a device is
160 "stopped" due to a power management event, or card ejection. The
161 device IO routines can use a flag like this to throttle IO to a
162 card that is not ready to accept it.
163*/
164
165typedef struct local_info_t {
166 dev_link_t link;
167 dev_node_t node;
168 int stop;
169 int cardnr;
170} local_info_t;
171
172/*======================================================================
173
174 sedlbauer_attach() creates an "instance" of the driver, allocating
175 local data structures for one device. The device is registered
176 with Card Services.
177
178 The dev_link structure is initialized, but we don't actually
179 configure the card at this point -- we wait until we receive a
180 card insertion event.
181
182======================================================================*/
183
184static dev_link_t *sedlbauer_attach(void)
185{
186 local_info_t *local;
187 dev_link_t *link;
188 client_reg_t client_reg;
189 int ret;
190
191 DEBUG(0, "sedlbauer_attach()\n");
192
193 /* Allocate space for private device-specific data */
194 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
195 if (!local) return NULL;
196 memset(local, 0, sizeof(local_info_t));
197 local->cardnr = -1;
198 link = &local->link; link->priv = local;
199
200 /* Interrupt setup */
201 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
202 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
203 link->irq.Handler = NULL;
204
205 /*
206 General socket configuration defaults can go here. In this
207 client, we assume very little, and rely on the CIS for almost
208 everything. In most clients, many details (i.e., number, sizes,
209 and attributes of IO windows) are fixed by the nature of the
210 device, and can be hard-wired here.
211 */
212
213 /* from old sedl_cs
214 */
215 /* The io structure describes IO port mapping */
216 link->io.NumPorts1 = 8;
217 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
218 link->io.IOAddrLines = 3;
219
220
221 link->conf.Attributes = 0;
222 link->conf.Vcc = 50;
223 link->conf.IntType = INT_MEMORY_AND_IO;
224
225 /* Register with Card Services */
226 link->next = dev_list;
227 dev_list = link;
228 client_reg.dev_info = &dev_info;
229 client_reg.EventMask =
230 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
231 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
232 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
233 client_reg.event_handler = &sedlbauer_event;
234 client_reg.Version = 0x0210;
235 client_reg.event_callback_args.client_data = link;
236 ret = pcmcia_register_client(&link->handle, &client_reg);
237 if (ret != CS_SUCCESS) {
238 cs_error(link->handle, RegisterClient, ret);
239 sedlbauer_detach(link);
240 return NULL;
241 }
242
243 return link;
244} /* sedlbauer_attach */
245
246/*======================================================================
247
248 This deletes a driver "instance". The device is de-registered
249 with Card Services. If it has been released, all local data
250 structures are freed. Otherwise, the structures will be freed
251 when the device is released.
252
253======================================================================*/
254
255static void sedlbauer_detach(dev_link_t *link)
256{
257 dev_link_t **linkp;
258
259 DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
260
261 /* Locate device structure */
262 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
263 if (*linkp == link) break;
264 if (*linkp == NULL)
265 return;
266
267 /*
268 If the device is currently configured and active, we won't
269 actually delete it yet. Instead, it is marked so that when
270 the release() function is called, that will trigger a proper
271 detach().
272 */
273 if (link->state & DEV_CONFIG) {
274#ifdef PCMCIA_DEBUG
275 printk(KERN_DEBUG "sedlbauer_cs: detach postponed, '%s' "
276 "still locked\n", link->dev->dev_name);
277#endif
278 link->state |= DEV_STALE_LINK;
279 return;
280 }
281
282 /* Break the link with Card Services */
283 if (link->handle)
284 pcmcia_deregister_client(link->handle);
285
286 /* Unlink device structure, and free it */
287 *linkp = link->next;
288 /* This points to the parent local_info_t struct */
289 kfree(link->priv);
290} /* sedlbauer_detach */
291
292/*======================================================================
293
294 sedlbauer_config() is scheduled to run after a CARD_INSERTION event
295 is received, to configure the PCMCIA socket, and to make the
296 device available to the system.
297
298======================================================================*/
299#define CS_CHECK(fn, ret) \
300do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
301
302static void sedlbauer_config(dev_link_t *link)
303{
304 client_handle_t handle = link->handle;
305 local_info_t *dev = link->priv;
306 tuple_t tuple;
307 cisparse_t parse;
308 int last_fn, last_ret;
309 u8 buf[64];
310 config_info_t conf;
311 win_req_t req;
312 memreq_t map;
313 IsdnCard_t icard;
314
315 DEBUG(0, "sedlbauer_config(0x%p)\n", link);
316
317 /*
318 This reads the card's CONFIG tuple to find its configuration
319 registers.
320 */
321 tuple.DesiredTuple = CISTPL_CONFIG;
322 tuple.Attributes = 0;
323 tuple.TupleData = buf;
324 tuple.TupleDataMax = sizeof(buf);
325 tuple.TupleOffset = 0;
326 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
327 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
328 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
329 link->conf.ConfigBase = parse.config.base;
330 link->conf.Present = parse.config.rmask[0];
331
332 /* Configure card */
333 link->state |= DEV_CONFIG;
334
335 /* Look up the current Vcc */
336 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
337 link->conf.Vcc = conf.Vcc;
338
339 /*
340 In this loop, we scan the CIS for configuration table entries,
341 each of which describes a valid card configuration, including
342 voltage, IO window, memory window, and interrupt settings.
343
344 We make no assumptions about the card to be configured: we use
345 just the information available in the CIS. In an ideal world,
346 this would work for any PCMCIA card, but it requires a complete
347 and accurate CIS. In practice, a driver usually "knows" most of
348 these things without consulting the CIS, and most client drivers
349 will only use the CIS to fill in implementation-defined details.
350 */
351 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
352 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
353 while (1) {
354 cistpl_cftable_entry_t dflt = { 0 };
355 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
356 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
357 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
358 goto next_entry;
359
360 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
361 if (cfg->index == 0) goto next_entry;
362 link->conf.ConfigIndex = cfg->index;
363
364 /* Does this card need audio output? */
365 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
366 link->conf.Attributes |= CONF_ENABLE_SPKR;
367 link->conf.Status = CCSR_AUDIO_ENA;
368 }
369
370 /* Use power settings for Vcc and Vpp if present */
371 /* Note that the CIS values need to be rescaled */
372 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
373 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
374 goto next_entry;
375 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
376 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
377 goto next_entry;
378 }
379
380 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
381 link->conf.Vpp1 = link->conf.Vpp2 =
382 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
383 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
384 link->conf.Vpp1 = link->conf.Vpp2 =
385 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
386
387 /* Do we need to allocate an interrupt? */
388 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
389 link->conf.Attributes |= CONF_ENABLE_IRQ;
390
391 /* IO window settings */
392 link->io.NumPorts1 = link->io.NumPorts2 = 0;
393 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
394 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
395 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
396 if (!(io->flags & CISTPL_IO_8BIT))
397 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
398 if (!(io->flags & CISTPL_IO_16BIT))
399 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
400/* new in dummy.cs 2001/01/28 MN
401 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
402*/
403 link->io.BasePort1 = io->win[0].base;
404 link->io.NumPorts1 = io->win[0].len;
405 if (io->nwin > 1) {
406 link->io.Attributes2 = link->io.Attributes1;
407 link->io.BasePort2 = io->win[1].base;
408 link->io.NumPorts2 = io->win[1].len;
409 }
410 /* This reserves IO space but doesn't actually enable it */
411 if (pcmcia_request_io(link->handle, &link->io) != 0)
412 goto next_entry;
413 }
414
415 /*
416 Now set up a common memory window, if needed. There is room
417 in the dev_link_t structure for one memory window handle,
418 but if the base addresses need to be saved, or if multiple
419 windows are needed, the info should go in the private data
420 structure for this device.
421
422 Note that the memory window base is a physical address, and
423 needs to be mapped to virtual space with ioremap() before it
424 is used.
425 */
426 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
427 cistpl_mem_t *mem =
428 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
429 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
430 req.Attributes |= WIN_ENABLE;
431 req.Base = mem->win[0].host_addr;
432 req.Size = mem->win[0].len;
433/* new in dummy.cs 2001/01/28 MN
434 if (req.Size < 0x1000)
435 req.Size = 0x1000;
436*/
437 req.AccessSpeed = 0;
438 if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
439 goto next_entry;
440 map.Page = 0; map.CardOffset = mem->win[0].card_addr;
441 if (pcmcia_map_mem_page(link->win, &map) != 0)
442 goto next_entry;
443 }
444 /* If we got this far, we're cool! */
445 break;
446
447 next_entry:
448/* new in dummy.cs 2001/01/28 MN
449 if (link->io.NumPorts1)
450 pcmcia_release_io(link->handle, &link->io);
451*/
452 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
453 }
454
455 /*
456 Allocate an interrupt line. Note that this does not assign a
457 handler to the interrupt, unless the 'Handler' member of the
458 irq structure is initialized.
459 */
460 if (link->conf.Attributes & CONF_ENABLE_IRQ)
461 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
462
463 /*
464 This actually configures the PCMCIA socket -- setting up
465 the I/O windows and the interrupt mapping, and putting the
466 card and host interface into "Memory and IO" mode.
467 */
468 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
469
470 /*
471 At this point, the dev_node_t structure(s) need to be
472 initialized and arranged in a linked list at link->dev.
473 */
474 sprintf(dev->node.dev_name, "sedlbauer");
475 dev->node.major = dev->node.minor = 0;
476 link->dev = &dev->node;
477
478 /* Finally, report what we've done */
479 printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
480 dev->node.dev_name, link->conf.ConfigIndex,
481 link->conf.Vcc/10, link->conf.Vcc%10);
482 if (link->conf.Vpp1)
483 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
484 if (link->conf.Attributes & CONF_ENABLE_IRQ)
485 printk(", irq %d", link->irq.AssignedIRQ);
486 if (link->io.NumPorts1)
487 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
488 link->io.BasePort1+link->io.NumPorts1-1);
489 if (link->io.NumPorts2)
490 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
491 link->io.BasePort2+link->io.NumPorts2-1);
492 if (link->win)
493 printk(", mem 0x%06lx-0x%06lx", req.Base,
494 req.Base+req.Size-1);
495 printk("\n");
496
497 link->state &= ~DEV_CONFIG_PENDING;
498
499 icard.para[0] = link->irq.AssignedIRQ;
500 icard.para[1] = link->io.BasePort1;
501 icard.protocol = protocol;
502 icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
503
504 last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard);
505 if (last_ret < 0) {
506 printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
507 last_ret, link->io.BasePort1);
508 sedlbauer_release(link);
509 } else
510 ((local_info_t*)link->priv)->cardnr = last_ret;
511
512 return;
513
514cs_failed:
515 cs_error(link->handle, last_fn, last_ret);
516 sedlbauer_release(link);
517
518} /* sedlbauer_config */
519
520/*======================================================================
521
522 After a card is removed, sedlbauer_release() will unregister the
523 device, and release the PCMCIA configuration. If the device is
524 still open, this will be postponed until it is closed.
525
526======================================================================*/
527
528static void sedlbauer_release(dev_link_t *link)
529{
530 local_info_t *local = link->priv;
531 DEBUG(0, "sedlbauer_release(0x%p)\n", link);
532
533 if (local) {
534 if (local->cardnr >= 0) {
535 /* no unregister function with hisax */
536 HiSax_closecard(local->cardnr);
537 }
538 }
539 /* Unlink the device chain */
540 link->dev = NULL;
541
542 /*
543 In a normal driver, additional code may be needed to release
544 other kernel data structures associated with this device.
545 */
546
547 /* Don't bother checking to see if these succeed or not */
548 if (link->win)
549 pcmcia_release_window(link->win);
550 pcmcia_release_configuration(link->handle);
551 if (link->io.NumPorts1)
552 pcmcia_release_io(link->handle, &link->io);
553 if (link->irq.AssignedIRQ)
554 pcmcia_release_irq(link->handle, &link->irq);
555 link->state &= ~DEV_CONFIG;
556
557 if (link->state & DEV_STALE_LINK)
558 sedlbauer_detach(link);
559
560} /* sedlbauer_release */
561
562/*======================================================================
563
564 The card status event handler. Mostly, this schedules other
565 stuff to run after an event is received.
566
567 When a CARD_REMOVAL event is received, we immediately set a
568 private flag to block future accesses to this device. All the
569 functions that actually access the device should check this flag
570 to make sure the card is still present.
571
572======================================================================*/
573
574static int sedlbauer_event(event_t event, int priority,
575 event_callback_args_t *args)
576{
577 dev_link_t *link = args->client_data;
578 local_info_t *dev = link->priv;
579
580 DEBUG(1, "sedlbauer_event(0x%06x)\n", event);
581
582 switch (event) {
583 case CS_EVENT_CARD_REMOVAL:
584 link->state &= ~DEV_PRESENT;
585 if (link->state & DEV_CONFIG) {
586 ((local_info_t *)link->priv)->stop = 1;
587 sedlbauer_release(link);
588 }
589 break;
590 case CS_EVENT_CARD_INSERTION:
591 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
592 sedlbauer_config(link);
593 break;
594 case CS_EVENT_PM_SUSPEND:
595 link->state |= DEV_SUSPEND;
596 /* Fall through... */
597 case CS_EVENT_RESET_PHYSICAL:
598 /* Mark the device as stopped, to block IO until later */
599 dev->stop = 1;
600 if (link->state & DEV_CONFIG)
601 pcmcia_release_configuration(link->handle);
602 break;
603 case CS_EVENT_PM_RESUME:
604 link->state &= ~DEV_SUSPEND;
605 /* Fall through... */
606 case CS_EVENT_CARD_RESET:
607 if (link->state & DEV_CONFIG)
608 pcmcia_request_configuration(link->handle, &link->conf);
609 dev->stop = 0;
610 /*
611 In a normal driver, additional code may go here to restore
612 the device state and restart IO.
613 */
614 break;
615 }
616 return 0;
617} /* sedlbauer_event */
618
619static struct pcmcia_driver sedlbauer_driver = {
620 .owner = THIS_MODULE,
621 .drv = {
622 .name = "sedlbauer_cs",
623 },
624 .attach = sedlbauer_attach,
625 .detach = sedlbauer_detach,
626};
627
628static int __init init_sedlbauer_cs(void)
629{
630 return pcmcia_register_driver(&sedlbauer_driver);
631}
632
633static void __exit exit_sedlbauer_cs(void)
634{
635 pcmcia_unregister_driver(&sedlbauer_driver);
636 BUG_ON(dev_list != NULL);
637}
638
639module_init(init_sedlbauer_cs);
640module_exit(exit_sedlbauer_cs);
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
new file mode 100644
index 00000000000..132840b750c
--- /dev/null
+++ b/drivers/isdn/hisax/sportster.c
@@ -0,0 +1,270 @@
1/* $Id: sportster.c,v 1.16.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for USR Sportster internal TA
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
12 *
13 *
14 */
15#include <linux/init.h>
16#include "hisax.h"
17#include "isac.h"
18#include "hscx.h"
19#include "isdnl1.h"
20
21extern const char *CardType[];
22const char *sportster_revision = "$Revision: 1.16.2.4 $";
23
24#define byteout(addr,val) outb(val,addr)
25#define bytein(addr) inb(addr)
26
27#define SPORTSTER_ISAC 0xC000
28#define SPORTSTER_HSCXA 0x0000
29#define SPORTSTER_HSCXB 0x4000
30#define SPORTSTER_RES_IRQ 0x8000
31#define SPORTSTER_RESET 0x80
32#define SPORTSTER_INTE 0x40
33
34static inline int
35calc_off(unsigned int base, unsigned int off)
36{
37 return(base + ((off & 0xfc)<<8) + ((off & 3)<<1));
38}
39
40static inline void
41read_fifo(unsigned int adr, u_char * data, int size)
42{
43 insb(adr, data, size);
44}
45
46static void
47write_fifo(unsigned int adr, u_char * data, int size)
48{
49 outsb(adr, data, size);
50}
51
52/* Interface functions */
53
54static u_char
55ReadISAC(struct IsdnCardState *cs, u_char offset)
56{
57 return (bytein(calc_off(cs->hw.spt.isac, offset)));
58}
59
60static void
61WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
62{
63 byteout(calc_off(cs->hw.spt.isac, offset), value);
64}
65
66static void
67ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
68{
69 read_fifo(cs->hw.spt.isac, data, size);
70}
71
72static void
73WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
74{
75 write_fifo(cs->hw.spt.isac, data, size);
76}
77
78static u_char
79ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
80{
81 return (bytein(calc_off(cs->hw.spt.hscx[hscx], offset)));
82}
83
84static void
85WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
86{
87 byteout(calc_off(cs->hw.spt.hscx[hscx], offset), value);
88}
89
90/*
91 * fast interrupt HSCX stuff goes here
92 */
93
94#define READHSCX(cs, nr, reg) bytein(calc_off(cs->hw.spt.hscx[nr], reg))
95#define WRITEHSCX(cs, nr, reg, data) byteout(calc_off(cs->hw.spt.hscx[nr], reg), data)
96#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.spt.hscx[nr], ptr, cnt)
97#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.spt.hscx[nr], ptr, cnt)
98
99#include "hscx_irq.c"
100
101static irqreturn_t
102sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs)
103{
104 struct IsdnCardState *cs = dev_id;
105 u_char val;
106 u_long flags;
107
108 spin_lock_irqsave(&cs->lock, flags);
109 val = READHSCX(cs, 1, HSCX_ISTA);
110 Start_HSCX:
111 if (val)
112 hscx_int_main(cs, val);
113 val = ReadISAC(cs, ISAC_ISTA);
114 Start_ISAC:
115 if (val)
116 isac_interrupt(cs, val);
117 val = READHSCX(cs, 1, HSCX_ISTA);
118 if (val) {
119 if (cs->debug & L1_DEB_HSCX)
120 debugl1(cs, "HSCX IntStat after IntRoutine");
121 goto Start_HSCX;
122 }
123 val = ReadISAC(cs, ISAC_ISTA);
124 if (val) {
125 if (cs->debug & L1_DEB_ISAC)
126 debugl1(cs, "ISAC IntStat after IntRoutine");
127 goto Start_ISAC;
128 }
129 /* get a new irq impulse if there any pending */
130 bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1);
131 spin_unlock_irqrestore(&cs->lock, flags);
132 return IRQ_HANDLED;
133}
134
135void
136release_io_sportster(struct IsdnCardState *cs)
137{
138 int i, adr;
139
140 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, 0);
141 for (i=0; i<64; i++) {
142 adr = cs->hw.spt.cfg_reg + i *1024;
143 release_region(adr, 8);
144 }
145}
146
147void
148reset_sportster(struct IsdnCardState *cs)
149{
150 cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */
151 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
152 mdelay(10);
153 cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */
154 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
155 mdelay(10);
156}
157
158static int
159Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
160{
161 u_long flags;
162
163 switch (mt) {
164 case CARD_RESET:
165 spin_lock_irqsave(&cs->lock, flags);
166 reset_sportster(cs);
167 spin_unlock_irqrestore(&cs->lock, flags);
168 return(0);
169 case CARD_RELEASE:
170 release_io_sportster(cs);
171 return(0);
172 case CARD_INIT:
173 spin_lock_irqsave(&cs->lock, flags);
174 reset_sportster(cs);
175 inithscxisac(cs, 1);
176 cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
177 byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
178 inithscxisac(cs, 2);
179 spin_unlock_irqrestore(&cs->lock, flags);
180 return(0);
181 case CARD_TEST:
182 return(0);
183 }
184 return(0);
185}
186
187static int __init
188get_io_range(struct IsdnCardState *cs)
189{
190 int i, j, adr;
191
192 for (i=0;i<64;i++) {
193 adr = cs->hw.spt.cfg_reg + i *1024;
194 if (!request_region(adr, 8, "sportster")) {
195 printk(KERN_WARNING
196 "HiSax: %s config port %x-%x already in use\n",
197 CardType[cs->typ], adr, adr + 8);
198 break;
199 }
200 }
201 if (i==64)
202 return(1);
203 else {
204 for (j=0; j<i; j++) {
205 adr = cs->hw.spt.cfg_reg + j *1024;
206 release_region(adr, 8);
207 }
208 return(0);
209 }
210}
211
212int __init
213setup_sportster(struct IsdnCard *card)
214{
215 struct IsdnCardState *cs = card->cs;
216 char tmp[64];
217
218 strcpy(tmp, sportster_revision);
219 printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
220 if (cs->typ != ISDN_CTYPE_SPORTSTER)
221 return (0);
222
223 cs->hw.spt.cfg_reg = card->para[1];
224 cs->irq = card->para[0];
225 if (!get_io_range(cs))
226 return (0);
227 cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
228 cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
229 cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
230
231 switch(cs->irq) {
232 case 5: cs->hw.spt.res_irq = 1;
233 break;
234 case 7: cs->hw.spt.res_irq = 2;
235 break;
236 case 10:cs->hw.spt.res_irq = 3;
237 break;
238 case 11:cs->hw.spt.res_irq = 4;
239 break;
240 case 12:cs->hw.spt.res_irq = 5;
241 break;
242 case 14:cs->hw.spt.res_irq = 6;
243 break;
244 case 15:cs->hw.spt.res_irq = 7;
245 break;
246 default:release_io_sportster(cs);
247 printk(KERN_WARNING "Sportster: wrong IRQ\n");
248 return(0);
249 }
250 printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
251 CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
252 setup_isac(cs);
253 cs->readisac = &ReadISAC;
254 cs->writeisac = &WriteISAC;
255 cs->readisacfifo = &ReadISACfifo;
256 cs->writeisacfifo = &WriteISACfifo;
257 cs->BC_Read_Reg = &ReadHSCX;
258 cs->BC_Write_Reg = &WriteHSCX;
259 cs->BC_Send_Data = &hscx_fill_fifo;
260 cs->cardmsg = &Sportster_card_msg;
261 cs->irq_func = &sportster_interrupt;
262 ISACVersion(cs, "Sportster:");
263 if (HscxVersion(cs, "Sportster:")) {
264 printk(KERN_WARNING
265 "Sportster: wrong HSCX versions check IO address\n");
266 release_io_sportster(cs);
267 return (0);
268 }
269 return (1);
270}
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
new file mode 100644
index 00000000000..e8177b017b1
--- /dev/null
+++ b/drivers/isdn/hisax/st5481.h
@@ -0,0 +1,535 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#ifndef _ST5481_H_
14#define _ST5481_H_
15
16#include <linux/config.h>
17
18// USB IDs, the Product Id is in the range 0x4810-0x481F
19
20#define ST_VENDOR_ID 0x0483
21#define ST5481_PRODUCT_ID 0x4810
22#define ST5481_PRODUCT_ID_MASK 0xFFF0
23
24// ST5481 endpoints when using alternative setting 3 (2B+D).
25// To get the endpoint address, OR with 0x80 for IN endpoints.
26
27#define EP_CTRL 0x00U /* Control endpoint */
28#define EP_INT 0x01U /* Interrupt endpoint */
29#define EP_B1_OUT 0x02U /* B1 channel out */
30#define EP_B1_IN 0x03U /* B1 channel in */
31#define EP_B2_OUT 0x04U /* B2 channel out */
32#define EP_B2_IN 0x05U /* B2 channel in */
33#define EP_D_OUT 0x06U /* D channel out */
34#define EP_D_IN 0x07U /* D channel in */
35
36// Number of isochronous packets. With 20 packets we get
37// 50 interrupts/sec for each endpoint.
38
39#define NUM_ISO_PACKETS_D 20
40#define NUM_ISO_PACKETS_B 20
41
42// Size of each isochronous packet.
43// In outgoing direction we need to match ISDN data rates:
44// D: 2 bytes / msec -> 16 kbit / s
45// B: 16 bytes / msec -> 64 kbit / s
46#define SIZE_ISO_PACKETS_D_IN 16
47#define SIZE_ISO_PACKETS_D_OUT 2
48#define SIZE_ISO_PACKETS_B_IN 32
49#define SIZE_ISO_PACKETS_B_OUT 8
50
51// If we overrun/underrun, we send one packet with +/- 2 bytes
52#define B_FLOW_ADJUST 2
53
54// Registers that are written using vendor specific device request
55// on endpoint 0.
56
57#define LBA 0x02 /* S loopback */
58#define SET_DEFAULT 0x06 /* Soft reset */
59#define LBB 0x1D /* S maintenance loopback */
60#define STT 0x1e /* S force transmission signals */
61#define SDA_MIN 0x20 /* SDA-sin minimal value */
62#define SDA_MAX 0x21 /* SDA-sin maximal value */
63#define SDELAY_VALUE 0x22 /* Delay between Tx and Rx clock */
64#define IN_D_COUNTER 0x36 /* D receive channel fifo counter */
65#define OUT_D_COUNTER 0x37 /* D transmit channel fifo counter */
66#define IN_B1_COUNTER 0x38 /* B1 receive channel fifo counter */
67#define OUT_B1_COUNTER 0x39 /* B1 transmit channel fifo counter */
68#define IN_B2_COUNTER 0x3a /* B2 receive channel fifo counter */
69#define OUT_B2_COUNTER 0x3b /* B2 transmit channel fifo counter */
70#define FFCTRL_IN_D 0x3C /* D receive channel fifo threshold low */
71#define FFCTRH_IN_D 0x3D /* D receive channel fifo threshold high */
72#define FFCTRL_OUT_D 0x3E /* D transmit channel fifo threshold low */
73#define FFCTRH_OUT_D 0x3F /* D transmit channel fifo threshold high */
74#define FFCTRL_IN_B1 0x40 /* B1 receive channel fifo threshold low */
75#define FFCTRH_IN_B1 0x41 /* B1 receive channel fifo threshold high */
76#define FFCTRL_OUT_B1 0x42 /* B1 transmit channel fifo threshold low */
77#define FFCTRH_OUT_B1 0x43 /* B1 transmit channel fifo threshold high */
78#define FFCTRL_IN_B2 0x44 /* B2 receive channel fifo threshold low */
79#define FFCTRH_IN_B2 0x45 /* B2 receive channel fifo threshold high */
80#define FFCTRL_OUT_B2 0x46 /* B2 transmit channel fifo threshold low */
81#define FFCTRH_OUT_B2 0x47 /* B2 transmit channel fifo threshold high */
82#define MPMSK 0x4A /* Multi purpose interrupt MASK register */
83#define FFMSK_D 0x4c /* D fifo interrupt MASK register */
84#define FFMSK_B1 0x4e /* B1 fifo interrupt MASK register */
85#define FFMSK_B2 0x50 /* B2 fifo interrupt MASK register */
86#define GPIO_DIR 0x52 /* GPIO pins direction registers */
87#define GPIO_OUT 0x53 /* GPIO pins output register */
88#define GPIO_IN 0x54 /* GPIO pins input register */
89#define TXCI 0x56 /* CI command to be transmitted */
90
91
92// Format of the interrupt packet received on endpoint 1:
93//
94// +--------+--------+--------+--------+--------+--------+
95// !MPINT !FFINT_D !FFINT_B1!FFINT_B2!CCIST !GPIO_INT!
96// +--------+--------+--------+--------+--------+--------+
97
98// Offsets in the interrupt packet
99
100#define MPINT 0
101#define FFINT_D 1
102#define FFINT_B1 2
103#define FFINT_B2 3
104#define CCIST 4
105#define GPIO_INT 5
106#define INT_PKT_SIZE 6
107
108// MPINT
109#define LSD_INT 0x80 /* S line activity detected */
110#define RXCI_INT 0x40 /* Indicate primitive arrived */
111#define DEN_INT 0x20 /* Signal enabling data out of D Tx fifo */
112#define DCOLL_INT 0x10 /* D channel collision */
113#define AMIVN_INT 0x04 /* AMI violation number reached 2 */
114#define INFOI_INT 0x04 /* INFOi changed */
115#define DRXON_INT 0x02 /* Reception channel active */
116#define GPCHG_INT 0x01 /* GPIO pin value changed */
117
118// FFINT_x
119#define IN_OVERRUN 0x80 /* In fifo overrun */
120#define OUT_UNDERRUN 0x40 /* Out fifo underrun */
121#define IN_UP 0x20 /* In fifo thresholdh up-crossed */
122#define IN_DOWN 0x10 /* In fifo thresholdl down-crossed */
123#define OUT_UP 0x08 /* Out fifo thresholdh up-crossed */
124#define OUT_DOWN 0x04 /* Out fifo thresholdl down-crossed */
125#define IN_COUNTER_ZEROED 0x02 /* In down-counter reached 0 */
126#define OUT_COUNTER_ZEROED 0x01 /* Out down-counter reached 0 */
127
128#define ANY_REC_INT (IN_OVERRUN+IN_UP+IN_DOWN+IN_COUNTER_ZEROED)
129#define ANY_XMIT_INT (OUT_UNDERRUN+OUT_UP+OUT_DOWN+OUT_COUNTER_ZEROED)
130
131
132// Level 1 commands that are sent using the TXCI device request
133#define ST5481_CMD_DR 0x0 /* Deactivation Request */
134#define ST5481_CMD_RES 0x1 /* state machine RESet */
135#define ST5481_CMD_TM1 0x2 /* Test Mode 1 */
136#define ST5481_CMD_TM2 0x3 /* Test Mode 2 */
137#define ST5481_CMD_PUP 0x7 /* Power UP */
138#define ST5481_CMD_AR8 0x8 /* Activation Request class 1 */
139#define ST5481_CMD_AR10 0x9 /* Activation Request class 2 */
140#define ST5481_CMD_ARL 0xA /* Activation Request Loopback */
141#define ST5481_CMD_PDN 0xF /* Power DoWn */
142
143// Turn on/off the LEDs using the GPIO device request.
144// To use the B LEDs, number_of_leds must be set to 4
145#define B1_LED 0x10U
146#define B2_LED 0x20U
147#define GREEN_LED 0x40U
148#define RED_LED 0x80U
149
150// D channel out states
151enum {
152 ST_DOUT_NONE,
153
154 ST_DOUT_SHORT_INIT,
155 ST_DOUT_SHORT_WAIT_DEN,
156
157 ST_DOUT_LONG_INIT,
158 ST_DOUT_LONG_WAIT_DEN,
159 ST_DOUT_NORMAL,
160
161 ST_DOUT_WAIT_FOR_UNDERRUN,
162 ST_DOUT_WAIT_FOR_NOT_BUSY,
163 ST_DOUT_WAIT_FOR_STOP,
164 ST_DOUT_WAIT_FOR_RESET,
165};
166
167#define DOUT_STATE_COUNT (ST_DOUT_WAIT_FOR_RESET + 1)
168
169// D channel out events
170enum {
171 EV_DOUT_START_XMIT,
172 EV_DOUT_COMPLETE,
173 EV_DOUT_DEN,
174 EV_DOUT_RESETED,
175 EV_DOUT_STOPPED,
176 EV_DOUT_COLL,
177 EV_DOUT_UNDERRUN,
178};
179
180#define DOUT_EVENT_COUNT (EV_DOUT_UNDERRUN + 1)
181
182// ----------------------------------------------------------------------
183
184enum {
185 ST_L1_F3,
186 ST_L1_F4,
187 ST_L1_F6,
188 ST_L1_F7,
189 ST_L1_F8,
190};
191
192#define L1_STATE_COUNT (ST_L1_F8+1)
193
194// The first 16 entries match the Level 1 indications that
195// are found at offset 4 (CCIST) in the interrupt packet
196
197enum {
198 EV_IND_DP, // 0000 Deactivation Pending
199 EV_IND_1, // 0001
200 EV_IND_2, // 0010
201 EV_IND_3, // 0011
202 EV_IND_RSY, // 0100 ReSYnchronizing
203 EV_IND_5, // 0101
204 EV_IND_6, // 0110
205 EV_IND_7, // 0111
206 EV_IND_AP, // 1000 Activation Pending
207 EV_IND_9, // 1001
208 EV_IND_10, // 1010
209 EV_IND_11, // 1011
210 EV_IND_AI8, // 1100 Activation Indication class 8
211 EV_IND_AI10,// 1101 Activation Indication class 10
212 EV_IND_AIL, // 1110 Activation Indication Loopback
213 EV_IND_DI, // 1111 Deactivation Indication
214 EV_PH_ACTIVATE_REQ,
215 EV_PH_DEACTIVATE_REQ,
216 EV_TIMER3,
217};
218
219#define L1_EVENT_COUNT (EV_TIMER3 + 1)
220
221#define ERR(format, arg...) \
222printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
223
224#define WARN(format, arg...) \
225printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
226
227#define INFO(format, arg...) \
228printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg)
229
230#include "isdnhdlc.h"
231#include "fsm.h"
232#include "hisax_if.h"
233#include <linux/skbuff.h>
234
235/* ======================================================================
236 * FIFO handling
237 */
238
239/* Generic FIFO structure */
240struct fifo {
241 u_char r,w,count,size;
242 spinlock_t lock;
243};
244
245/*
246 * Init an FIFO
247 */
248static inline void fifo_init(struct fifo *fifo, int size)
249{
250 fifo->r = fifo->w = fifo->count = 0;
251 fifo->size = size;
252 spin_lock_init(&fifo->lock);
253}
254
255/*
256 * Add an entry to the FIFO
257 */
258static inline int fifo_add(struct fifo *fifo)
259{
260 unsigned long flags;
261 int index;
262
263 if (!fifo) {
264 return -1;
265 }
266
267 spin_lock_irqsave(&fifo->lock, flags);
268 if (fifo->count == fifo->size) {
269 // FIFO full
270 index = -1;
271 } else {
272 // Return index where to get the next data to add to the FIFO
273 index = fifo->w++ & (fifo->size-1);
274 fifo->count++;
275 }
276 spin_unlock_irqrestore(&fifo->lock, flags);
277 return index;
278}
279
280/*
281 * Remove an entry from the FIFO with the index returned.
282 */
283static inline int fifo_remove(struct fifo *fifo)
284{
285 unsigned long flags;
286 int index;
287
288 if (!fifo) {
289 return -1;
290 }
291
292 spin_lock_irqsave(&fifo->lock, flags);
293 if (!fifo->count) {
294 // FIFO empty
295 index = -1;
296 } else {
297 // Return index where to get the next data from the FIFO
298 index = fifo->r++ & (fifo->size-1);
299 fifo->count--;
300 }
301 spin_unlock_irqrestore(&fifo->lock, flags);
302
303 return index;
304}
305
306/* ======================================================================
307 * control pipe
308 */
309typedef void (*ctrl_complete_t)(void *);
310
311typedef struct ctrl_msg {
312 struct usb_ctrlrequest dr;
313 ctrl_complete_t complete;
314 void *context;
315} ctrl_msg;
316
317/* FIFO of ctrl messages waiting to be sent */
318#define MAX_EP0_MSG 16
319struct ctrl_msg_fifo {
320 struct fifo f;
321 struct ctrl_msg data[MAX_EP0_MSG];
322};
323
324#define MAX_DFRAME_LEN_L1 300
325#define HSCX_BUFMAX 4096
326
327struct st5481_ctrl {
328 struct ctrl_msg_fifo msg_fifo;
329 unsigned long busy;
330 struct urb *urb;
331};
332
333struct st5481_intr {
334 // struct evt_fifo evt_fifo;
335 struct urb *urb;
336};
337
338struct st5481_d_out {
339 struct isdnhdlc_vars hdlc_state;
340 struct urb *urb[2]; /* double buffering */
341 unsigned long busy;
342 struct sk_buff *tx_skb;
343 struct FsmInst fsm;
344};
345
346struct st5481_b_out {
347 struct isdnhdlc_vars hdlc_state;
348 struct urb *urb[2]; /* double buffering */
349 u_char flow_event;
350 u_long busy;
351 struct sk_buff *tx_skb;
352};
353
354struct st5481_in {
355 struct isdnhdlc_vars hdlc_state;
356 struct urb *urb[2]; /* double buffering */
357 int mode;
358 int bufsize;
359 unsigned int num_packets;
360 unsigned int packet_size;
361 unsigned char ep, counter;
362 unsigned char *rcvbuf;
363 struct st5481_adapter *adapter;
364 struct hisax_if *hisax_if;
365};
366
367int st5481_setup_in(struct st5481_in *in);
368void st5481_release_in(struct st5481_in *in);
369void st5481_in_mode(struct st5481_in *in, int mode);
370
371struct st5481_bcs {
372 struct hisax_b_if b_if;
373 struct st5481_adapter *adapter;
374 struct st5481_in b_in;
375 struct st5481_b_out b_out;
376 int channel;
377 int mode;
378};
379
380struct st5481_adapter {
381 struct list_head list;
382 int number_of_leds;
383 struct usb_device *usb_dev;
384 struct hisax_d_if hisax_d_if;
385
386 struct st5481_ctrl ctrl;
387 struct st5481_intr intr;
388 struct st5481_in d_in;
389 struct st5481_d_out d_out;
390
391 unsigned char leds;
392 unsigned int led_counter;
393
394 unsigned long event;
395
396 struct FsmInst l1m;
397 struct FsmTimer timer;
398
399 struct st5481_bcs bcs[2];
400};
401
402#define TIMER3_VALUE 7000
403
404/* ======================================================================
405 *
406 */
407
408/*
409 * Submit an URB with error reporting. This is a macro so
410 * the __FUNCTION__ returns the caller function name.
411 */
412#define SUBMIT_URB(urb, mem_flags) \
413({ \
414 int status; \
415 if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \
416 WARN("usb_submit_urb failed,status=%d", status); \
417 } \
418 status; \
419})
420
421/*
422 * USB double buffering, return the URB index (0 or 1).
423 */
424static inline int get_buf_nr(struct urb *urbs[], struct urb *urb)
425{
426 return (urbs[0]==urb ? 0 : 1);
427}
428
429/* ---------------------------------------------------------------------- */
430
431/* B Channel */
432
433int st5481_setup_b(struct st5481_bcs *bcs);
434void st5481_release_b(struct st5481_bcs *bcs);
435void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
436
437/* D Channel */
438
439int st5481_setup_d(struct st5481_adapter *adapter);
440void st5481_release_d(struct st5481_adapter *adapter);
441void st5481_b_l2l1(struct hisax_if *b_if, int pr, void *arg);
442int st5481_d_init(void);
443void st5481_d_exit(void);
444
445/* USB */
446void st5481_ph_command(struct st5481_adapter *adapter, unsigned int command);
447int st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
448 unsigned int pipe, int num_packets,
449 int packet_size, int buf_size,
450 usb_complete_t complete, void *context);
451void st5481_release_isocpipes(struct urb* urb[2]);
452
453int st5481_isoc_flatten(struct urb *urb);
454void st5481_usb_pipe_reset(struct st5481_adapter *adapter,
455 u_char pipe, ctrl_complete_t complete, void *context);
456void st5481_usb_ctrl_msg(struct st5481_adapter *adapter,
457 u8 request, u8 requesttype, u16 value, u16 index,
458 ctrl_complete_t complete, void *context);
459void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter,
460 u8 request, u16 value,
461 ctrl_complete_t complete, void *context);
462int st5481_setup_usb(struct st5481_adapter *adapter);
463void st5481_release_usb(struct st5481_adapter *adapter);
464void st5481_start(struct st5481_adapter *adapter);
465void st5481_stop(struct st5481_adapter *adapter);
466
467// ----------------------------------------------------------------------
468// debugging macros
469
470#define __debug_variable st5481_debug
471#include "hisax_debug.h"
472
473#ifdef CONFIG_HISAX_DEBUG
474
475extern int st5481_debug;
476
477#define DBG_ISO_PACKET(level,urb) \
478 if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
479
480static void __attribute__((unused))
481dump_iso_packet(const char *name, struct urb *urb)
482{
483 int i,j;
484 int len,ofs;
485 u_char *data;
486
487 printk(KERN_DEBUG "%s: packets=%d,errors=%d\n",
488 name,urb->number_of_packets,urb->error_count);
489 for (i = 0; i < urb->number_of_packets; ++i) {
490 if (urb->pipe & USB_DIR_IN) {
491 len = urb->iso_frame_desc[i].actual_length;
492 } else {
493 len = urb->iso_frame_desc[i].length;
494 }
495 ofs = urb->iso_frame_desc[i].offset;
496 printk(KERN_DEBUG "len=%.2d,ofs=%.3d ",len,ofs);
497 if (len) {
498 data = urb->transfer_buffer+ofs;
499 for (j=0; j < len; j++) {
500 printk ("%.2x", data[j]);
501 }
502 }
503 printk("\n");
504 }
505}
506
507static inline const char *ST5481_CMD_string(int evt)
508{
509 static char s[16];
510
511 switch (evt) {
512 case ST5481_CMD_DR: return "DR";
513 case ST5481_CMD_RES: return "RES";
514 case ST5481_CMD_TM1: return "TM1";
515 case ST5481_CMD_TM2: return "TM2";
516 case ST5481_CMD_PUP: return "PUP";
517 case ST5481_CMD_AR8: return "AR8";
518 case ST5481_CMD_AR10: return "AR10";
519 case ST5481_CMD_ARL: return "ARL";
520 case ST5481_CMD_PDN: return "PDN";
521 };
522
523 sprintf(s,"0x%x",evt);
524 return s;
525}
526
527#else
528
529#define DBG_ISO_PACKET(level,urb) do {} while (0)
530
531#endif
532
533
534
535#endif
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
new file mode 100644
index 00000000000..2fcd093921d
--- /dev/null
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -0,0 +1,374 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#include <linux/init.h>
14#include <linux/usb.h>
15#include <linux/slab.h>
16#include <linux/netdevice.h>
17#include "st5481.h"
18
19static inline void B_L1L2(struct st5481_bcs *bcs, int pr, void *arg)
20{
21 struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
22
23 ifc->l1l2(ifc, pr, arg);
24}
25
26/*
27 * Encode and transmit next frame.
28 */
29static void usb_b_out(struct st5481_bcs *bcs,int buf_nr)
30{
31 struct st5481_b_out *b_out = &bcs->b_out;
32 struct st5481_adapter *adapter = bcs->adapter;
33 struct urb *urb;
34 unsigned int packet_size,offset;
35 int len,buf_size,bytes_sent;
36 int i;
37 struct sk_buff *skb;
38
39 if (test_and_set_bit(buf_nr, &b_out->busy)) {
40 DBG(4,"ep %d urb %d busy",(bcs->channel+1)*2,buf_nr);
41 return;
42 }
43 urb = b_out->urb[buf_nr];
44
45 // Adjust isoc buffer size according to flow state
46 if(b_out->flow_event & (OUT_DOWN | OUT_UNDERRUN)) {
47 buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST;
48 packet_size = SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST;
49 DBG(4,"B%d,adjust flow,add %d bytes",bcs->channel+1,B_FLOW_ADJUST);
50 } else if(b_out->flow_event & OUT_UP){
51 buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT - B_FLOW_ADJUST;
52 packet_size = SIZE_ISO_PACKETS_B_OUT - B_FLOW_ADJUST;
53 DBG(4,"B%d,adjust flow,remove %d bytes",bcs->channel+1,B_FLOW_ADJUST);
54 } else {
55 buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT;
56 packet_size = 8;
57 }
58 b_out->flow_event = 0;
59
60 len = 0;
61 while (len < buf_size) {
62 if ((skb = b_out->tx_skb)) {
63 DBG_SKB(0x100, skb);
64 DBG(4,"B%d,len=%d",bcs->channel+1,skb->len);
65
66 if (bcs->mode == L1_MODE_TRANS) {
67 bytes_sent = buf_size - len;
68 if (skb->len < bytes_sent)
69 bytes_sent = skb->len;
70 { /* swap tx bytes to get hearable audio data */
71 register unsigned char *src = skb->data;
72 register unsigned char *dest = urb->transfer_buffer+len;
73 register unsigned int count;
74 for (count = 0; count < bytes_sent; count++)
75 *dest++ = isdnhdlc_bit_rev_tab[*src++];
76 }
77 len += bytes_sent;
78 } else {
79 len += isdnhdlc_encode(&b_out->hdlc_state,
80 skb->data, skb->len, &bytes_sent,
81 urb->transfer_buffer+len, buf_size-len);
82 }
83
84 skb_pull(skb, bytes_sent);
85
86 if (!skb->len) {
87 // Frame sent
88 b_out->tx_skb = NULL;
89 B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
90 dev_kfree_skb_any(skb);
91
92/* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
93/* st5481B_sched_event(bcs, B_XMTBUFREADY); */
94/* } */
95 }
96 } else {
97 if (bcs->mode == L1_MODE_TRANS) {
98 memset(urb->transfer_buffer+len, 0xff, buf_size-len);
99 len = buf_size;
100 } else {
101 // Send flags
102 len += isdnhdlc_encode(&b_out->hdlc_state,
103 NULL, 0, &bytes_sent,
104 urb->transfer_buffer+len, buf_size-len);
105 }
106 }
107 }
108
109 // Prepare the URB
110 for (i = 0, offset = 0; offset < len; i++) {
111 urb->iso_frame_desc[i].offset = offset;
112 urb->iso_frame_desc[i].length = packet_size;
113 offset += packet_size;
114 packet_size = SIZE_ISO_PACKETS_B_OUT;
115 }
116 urb->transfer_buffer_length = len;
117 urb->number_of_packets = i;
118 urb->dev = adapter->usb_dev;
119
120 DBG_ISO_PACKET(0x200,urb);
121
122 SUBMIT_URB(urb, GFP_NOIO);
123}
124
125/*
126 * Start transfering (flags or data) on the B channel, since
127 * FIFO counters has been set to a non-zero value.
128 */
129static void st5481B_start_xfer(void *context)
130{
131 struct st5481_bcs *bcs = context;
132
133 DBG(4,"B%d",bcs->channel+1);
134
135 // Start transmitting (flags or data) on B channel
136
137 usb_b_out(bcs,0);
138 usb_b_out(bcs,1);
139}
140
141/*
142 * If the adapter has only 2 LEDs, the green
143 * LED will blink with a rate depending
144 * on the number of channels opened.
145 */
146static void led_blink(struct st5481_adapter *adapter)
147{
148 u_char leds = adapter->leds;
149
150 // 50 frames/sec for each channel
151 if (++adapter->led_counter % 50) {
152 return;
153 }
154
155 if (adapter->led_counter % 100) {
156 leds |= GREEN_LED;
157 } else {
158 leds &= ~GREEN_LED;
159 }
160
161 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, leds, NULL, NULL);
162}
163
164static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs)
165{
166 struct st5481_bcs *bcs = urb->context;
167 struct st5481_b_out *b_out = &bcs->b_out;
168 struct st5481_adapter *adapter = bcs->adapter;
169 int buf_nr;
170
171 buf_nr = get_buf_nr(b_out->urb, urb);
172 test_and_clear_bit(buf_nr, &b_out->busy);
173
174 if (unlikely(urb->status < 0)) {
175 if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
176 WARN("urb status %d",urb->status);
177 if (b_out->busy == 0) {
178 st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
179 }
180 } else {
181 DBG(1,"urb killed");
182 return; // Give up
183 }
184 }
185
186 usb_b_out(bcs,buf_nr);
187
188 if (adapter->number_of_leds == 2)
189 led_blink(adapter);
190}
191
192/*
193 * Start or stop the transfer on the B channel.
194 */
195static void st5481B_mode(struct st5481_bcs *bcs, int mode)
196{
197 struct st5481_b_out *b_out = &bcs->b_out;
198 struct st5481_adapter *adapter = bcs->adapter;
199
200 DBG(4,"B%d,mode=%d", bcs->channel + 1, mode);
201
202 if (bcs->mode == mode)
203 return;
204
205 bcs->mode = mode;
206
207 // Cancel all USB transfers on this B channel
208 usb_unlink_urb(b_out->urb[0]);
209 usb_unlink_urb(b_out->urb[1]);
210 b_out->busy = 0;
211
212 st5481_in_mode(&bcs->b_in, mode);
213 if (bcs->mode != L1_MODE_NULL) {
214 // Open the B channel
215 if (bcs->mode != L1_MODE_TRANS) {
216 isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
217 }
218 st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL);
219
220 // Enable B channel interrupts
221 st5481_usb_device_ctrl_msg(adapter, FFMSK_B1+(bcs->channel*2),
222 OUT_UP+OUT_DOWN+OUT_UNDERRUN, NULL, NULL);
223
224 // Enable B channel FIFOs
225 st5481_usb_device_ctrl_msg(adapter, OUT_B1_COUNTER+(bcs->channel*2), 32, st5481B_start_xfer, bcs);
226 if (adapter->number_of_leds == 4) {
227 if (bcs->channel == 0) {
228 adapter->leds |= B1_LED;
229 } else {
230 adapter->leds |= B2_LED;
231 }
232 }
233 } else {
234 // Disble B channel interrupts
235 st5481_usb_device_ctrl_msg(adapter, FFMSK_B1+(bcs->channel*2), 0, NULL, NULL);
236
237 // Disable B channel FIFOs
238 st5481_usb_device_ctrl_msg(adapter, OUT_B1_COUNTER+(bcs->channel*2), 0, NULL, NULL);
239
240 if (adapter->number_of_leds == 4) {
241 if (bcs->channel == 0) {
242 adapter->leds &= ~B1_LED;
243 } else {
244 adapter->leds &= ~B2_LED;
245 }
246 } else {
247 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
248 }
249 if (b_out->tx_skb) {
250 dev_kfree_skb_any(b_out->tx_skb);
251 b_out->tx_skb = NULL;
252 }
253
254 }
255}
256
257static int st5481_setup_b_out(struct st5481_bcs *bcs)
258{
259 struct usb_device *dev = bcs->adapter->usb_dev;
260 struct usb_interface *intf;
261 struct usb_host_interface *altsetting = NULL;
262 struct usb_host_endpoint *endpoint;
263 struct st5481_b_out *b_out = &bcs->b_out;
264
265 DBG(4,"");
266
267 intf = usb_ifnum_to_if(dev, 0);
268 if (intf)
269 altsetting = usb_altnum_to_altsetting(intf, 3);
270 if (!altsetting)
271 return -ENXIO;
272
273 // Allocate URBs and buffers for the B channel out
274 endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2];
275
276 DBG(4,"endpoint address=%02x,packet size=%d",
277 endpoint->desc.bEndpointAddress, le16_to_cpu(endpoint->desc.wMaxPacketSize));
278
279 // Allocate memory for 8000bytes/sec + extra bytes if underrun
280 return st5481_setup_isocpipes(b_out->urb, dev,
281 usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress),
282 NUM_ISO_PACKETS_B, SIZE_ISO_PACKETS_B_OUT,
283 NUM_ISO_PACKETS_B * SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST,
284 usb_b_out_complete, bcs);
285}
286
287static void st5481_release_b_out(struct st5481_bcs *bcs)
288{
289 struct st5481_b_out *b_out = &bcs->b_out;
290
291 DBG(4,"");
292
293 st5481_release_isocpipes(b_out->urb);
294}
295
296int st5481_setup_b(struct st5481_bcs *bcs)
297{
298 int retval;
299
300 DBG(4,"");
301
302 retval = st5481_setup_b_out(bcs);
303 if (retval)
304 goto err;
305 bcs->b_in.bufsize = HSCX_BUFMAX;
306 bcs->b_in.num_packets = NUM_ISO_PACKETS_B;
307 bcs->b_in.packet_size = SIZE_ISO_PACKETS_B_IN;
308 bcs->b_in.ep = (bcs->channel ? EP_B2_IN : EP_B1_IN) | USB_DIR_IN;
309 bcs->b_in.counter = bcs->channel ? IN_B2_COUNTER : IN_B1_COUNTER;
310 bcs->b_in.adapter = bcs->adapter;
311 bcs->b_in.hisax_if = &bcs->b_if.ifc;
312 retval = st5481_setup_in(&bcs->b_in);
313 if (retval)
314 goto err_b_out;
315
316
317 return 0;
318
319 err_b_out:
320 st5481_release_b_out(bcs);
321 err:
322 return retval;
323}
324
325/*
326 * Release buffers and URBs for the B channels
327 */
328void st5481_release_b(struct st5481_bcs *bcs)
329{
330 DBG(4,"");
331
332 st5481_release_in(&bcs->b_in);
333 st5481_release_b_out(bcs);
334}
335
336/*
337 * st5481_b_l2l1 is the entry point for upper layer routines that want to
338 * transmit on the B channel. PH_DATA | REQUEST is a normal packet that
339 * we either start transmitting (if idle) or queue (if busy).
340 * PH_PULL | REQUEST can be called to request a callback message
341 * (PH_PULL | CONFIRM)
342 * once the link is idle. After a "pull" callback, the upper layer
343 * routines can use PH_PULL | INDICATION to send data.
344 */
345void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
346{
347 struct st5481_bcs *bcs = ifc->priv;
348 struct sk_buff *skb = arg;
349 int mode;
350
351 DBG(4, "");
352
353 switch (pr) {
354 case PH_DATA | REQUEST:
355 if (bcs->b_out.tx_skb)
356 BUG();
357
358 bcs->b_out.tx_skb = skb;
359 break;
360 case PH_ACTIVATE | REQUEST:
361 mode = (int) arg;
362 DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
363 st5481B_mode(bcs, mode);
364 B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
365 break;
366 case PH_DEACTIVATE | REQUEST:
367 DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
368 st5481B_mode(bcs, L1_MODE_NULL);
369 B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
370 break;
371 default:
372 WARN("pr %#x\n", pr);
373 }
374}
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
new file mode 100644
index 00000000000..071b1d31999
--- /dev/null
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -0,0 +1,776 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#include <linux/init.h>
14#include <linux/usb.h>
15#include <linux/slab.h>
16#include <linux/netdevice.h>
17#include "st5481.h"
18
19static void ph_connect(struct st5481_adapter *adapter);
20static void ph_disconnect(struct st5481_adapter *adapter);
21
22static struct Fsm l1fsm;
23
24static char *strL1State[] =
25{
26 "ST_L1_F3",
27 "ST_L1_F4",
28 "ST_L1_F6",
29 "ST_L1_F7",
30 "ST_L1_F8",
31};
32
33static char *strL1Event[] =
34{
35 "EV_IND_DP",
36 "EV_IND_1",
37 "EV_IND_2",
38 "EV_IND_3",
39 "EV_IND_RSY",
40 "EV_IND_5",
41 "EV_IND_6",
42 "EV_IND_7",
43 "EV_IND_AP",
44 "EV_IND_9",
45 "EV_IND_10",
46 "EV_IND_11",
47 "EV_IND_AI8",
48 "EV_IND_AI10",
49 "EV_IND_AIL",
50 "EV_IND_DI",
51 "EV_PH_ACTIVATE_REQ",
52 "EV_PH_DEACTIVATE_REQ",
53 "EV_TIMER3",
54};
55
56static inline void D_L1L2(struct st5481_adapter *adapter, int pr, void *arg)
57{
58 struct hisax_if *ifc = (struct hisax_if *) &adapter->hisax_d_if;
59
60 ifc->l1l2(ifc, pr, arg);
61}
62
63static void
64l1_go_f3(struct FsmInst *fi, int event, void *arg)
65{
66 struct st5481_adapter *adapter = fi->userdata;
67
68 if (fi->state == ST_L1_F7)
69 ph_disconnect(adapter);
70
71 FsmChangeState(fi, ST_L1_F3);
72 D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
73}
74
75static void
76l1_go_f6(struct FsmInst *fi, int event, void *arg)
77{
78 struct st5481_adapter *adapter = fi->userdata;
79
80 if (fi->state == ST_L1_F7)
81 ph_disconnect(adapter);
82
83 FsmChangeState(fi, ST_L1_F6);
84}
85
86static void
87l1_go_f7(struct FsmInst *fi, int event, void *arg)
88{
89 struct st5481_adapter *adapter = fi->userdata;
90
91 FsmDelTimer(&adapter->timer, 0);
92 ph_connect(adapter);
93 FsmChangeState(fi, ST_L1_F7);
94 D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);
95}
96
97static void
98l1_go_f8(struct FsmInst *fi, int event, void *arg)
99{
100 struct st5481_adapter *adapter = fi->userdata;
101
102 if (fi->state == ST_L1_F7)
103 ph_disconnect(adapter);
104
105 FsmChangeState(fi, ST_L1_F8);
106}
107
108static void
109l1_timer3(struct FsmInst *fi, int event, void *arg)
110{
111 struct st5481_adapter *adapter = fi->userdata;
112
113 st5481_ph_command(adapter, ST5481_CMD_DR);
114 FsmChangeState(fi, ST_L1_F3);
115 D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
116}
117
118static void
119l1_ignore(struct FsmInst *fi, int event, void *arg)
120{
121}
122
123static void
124l1_activate(struct FsmInst *fi, int event, void *arg)
125{
126 struct st5481_adapter *adapter = fi->userdata;
127
128 st5481_ph_command(adapter, ST5481_CMD_DR);
129 st5481_ph_command(adapter, ST5481_CMD_PUP);
130 FsmRestartTimer(&adapter->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
131 st5481_ph_command(adapter, ST5481_CMD_AR8);
132 FsmChangeState(fi, ST_L1_F4);
133}
134
135static struct FsmNode L1FnList[] __initdata =
136{
137 {ST_L1_F3, EV_IND_DP, l1_ignore},
138 {ST_L1_F3, EV_IND_AP, l1_go_f6},
139 {ST_L1_F3, EV_IND_AI8, l1_go_f7},
140 {ST_L1_F3, EV_IND_AI10, l1_go_f7},
141 {ST_L1_F3, EV_PH_ACTIVATE_REQ, l1_activate},
142
143 {ST_L1_F4, EV_TIMER3, l1_timer3},
144 {ST_L1_F4, EV_IND_DP, l1_go_f3},
145 {ST_L1_F4, EV_IND_AP, l1_go_f6},
146 {ST_L1_F4, EV_IND_AI8, l1_go_f7},
147 {ST_L1_F4, EV_IND_AI10, l1_go_f7},
148
149 {ST_L1_F6, EV_TIMER3, l1_timer3},
150 {ST_L1_F6, EV_IND_DP, l1_go_f3},
151 {ST_L1_F6, EV_IND_AP, l1_ignore},
152 {ST_L1_F6, EV_IND_AI8, l1_go_f7},
153 {ST_L1_F6, EV_IND_AI10, l1_go_f7},
154 {ST_L1_F7, EV_IND_RSY, l1_go_f8},
155
156 {ST_L1_F7, EV_IND_DP, l1_go_f3},
157 {ST_L1_F7, EV_IND_AP, l1_go_f6},
158 {ST_L1_F7, EV_IND_AI8, l1_ignore},
159 {ST_L1_F7, EV_IND_AI10, l1_ignore},
160 {ST_L1_F7, EV_IND_RSY, l1_go_f8},
161
162 {ST_L1_F8, EV_TIMER3, l1_timer3},
163 {ST_L1_F8, EV_IND_DP, l1_go_f3},
164 {ST_L1_F8, EV_IND_AP, l1_go_f6},
165 {ST_L1_F8, EV_IND_AI8, l1_go_f8},
166 {ST_L1_F8, EV_IND_AI10, l1_go_f8},
167 {ST_L1_F8, EV_IND_RSY, l1_ignore},
168};
169
170static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
171{
172 va_list args;
173 char buf[256];
174
175 va_start(args, fmt);
176 vsprintf(buf, fmt, args);
177 DBG(8, "%s", buf);
178 va_end(args);
179}
180
181/* ======================================================================
182 * D-Channel out
183 */
184
185/*
186 D OUT state machine:
187 ====================
188
189 Transmit short frame (< 16 bytes of encoded data):
190
191 L1 FRAME D_OUT_STATE USB D CHANNEL
192 -------- ----------- --- ---------
193
194 FIXME
195
196 -> [xx..xx] SHORT_INIT -> [7Exx..xxC1C27EFF]
197 SHORT_WAIT_DEN <> OUT_D_COUNTER=16
198
199 END_OF_SHORT <- DEN_EVENT -> 7Exx
200 xxxx
201 xxxx
202 xxxx
203 xxxx
204 xxxx
205 C1C1
206 7EFF
207 WAIT_FOR_RESET_IDLE <- D_UNDERRUN <- (8ms)
208 IDLE <> Reset pipe
209
210
211
212 Transmit long frame (>= 16 bytes of encoded data):
213
214 L1 FRAME D_OUT_STATE USB D CHANNEL
215 -------- ----------- --- ---------
216
217 -> [xx...xx] IDLE
218 WAIT_FOR_STOP <> OUT_D_COUNTER=0
219 WAIT_FOR_RESET <> Reset pipe
220 STOP
221 INIT_LONG_FRAME -> [7Exx..xx]
222 WAIT_DEN <> OUT_D_COUNTER=16
223 OUT_NORMAL <- DEN_EVENT -> 7Exx
224 END_OF_FRAME_BUSY -> [xxxx] xxxx
225 END_OF_FRAME_NOT_BUSY -> [xxxx] xxxx
226 -> [xxxx] xxxx
227 -> [C1C2] xxxx
228 -> [7EFF] xxxx
229 xxxx
230 xxxx
231 ....
232 xxxx
233 C1C2
234 7EFF
235 <- D_UNDERRUN <- (> 8ms)
236 WAIT_FOR_STOP <> OUT_D_COUNTER=0
237 WAIT_FOR_RESET <> Reset pipe
238 STOP
239
240*/
241
242static struct Fsm dout_fsm;
243
244static char *strDoutState[] =
245{
246 "ST_DOUT_NONE",
247
248 "ST_DOUT_SHORT_INIT",
249 "ST_DOUT_SHORT_WAIT_DEN",
250
251 "ST_DOUT_LONG_INIT",
252 "ST_DOUT_LONG_WAIT_DEN",
253 "ST_DOUT_NORMAL",
254
255 "ST_DOUT_WAIT_FOR_UNDERRUN",
256 "ST_DOUT_WAIT_FOR_NOT_BUSY",
257 "ST_DOUT_WAIT_FOR_STOP",
258 "ST_DOUT_WAIT_FOR_RESET",
259};
260
261static char *strDoutEvent[] =
262{
263 "EV_DOUT_START_XMIT",
264 "EV_DOUT_COMPLETE",
265 "EV_DOUT_DEN",
266 "EV_DOUT_RESETED",
267 "EV_DOUT_STOPPED",
268 "EV_DOUT_COLL",
269 "EV_DOUT_UNDERRUN",
270};
271
272static void dout_debug(struct FsmInst *fi, char *fmt, ...)
273{
274 va_list args;
275 char buf[256];
276
277 va_start(args, fmt);
278 vsprintf(buf, fmt, args);
279 DBG(0x2, "%s", buf);
280 va_end(args);
281}
282
283static void dout_stop_event(void *context)
284{
285 struct st5481_adapter *adapter = context;
286
287 FsmEvent(&adapter->d_out.fsm, EV_DOUT_STOPPED, NULL);
288}
289
290/*
291 * Start the transfer of a D channel frame.
292 */
293static void usb_d_out(struct st5481_adapter *adapter, int buf_nr)
294{
295 struct st5481_d_out *d_out = &adapter->d_out;
296 struct urb *urb;
297 unsigned int num_packets, packet_offset;
298 int len, buf_size, bytes_sent;
299 struct sk_buff *skb;
300 struct usb_iso_packet_descriptor *desc;
301
302 if (d_out->fsm.state != ST_DOUT_NORMAL)
303 return;
304
305 if (test_and_set_bit(buf_nr, &d_out->busy)) {
306 DBG(2, "ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
307 return;
308 }
309 urb = d_out->urb[buf_nr];
310
311 skb = d_out->tx_skb;
312
313 buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;
314
315 if (skb) {
316 len = isdnhdlc_encode(&d_out->hdlc_state,
317 skb->data, skb->len, &bytes_sent,
318 urb->transfer_buffer, buf_size);
319 skb_pull(skb,bytes_sent);
320 } else {
321 // Send flags or idle
322 len = isdnhdlc_encode(&d_out->hdlc_state,
323 NULL, 0, &bytes_sent,
324 urb->transfer_buffer, buf_size);
325 }
326
327 if (len < buf_size) {
328 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);
329 }
330 if (skb && !skb->len) {
331 d_out->tx_skb = NULL;
332 D_L1L2(adapter, PH_DATA | CONFIRM, NULL);
333 dev_kfree_skb_any(skb);
334 }
335
336 // Prepare the URB
337 urb->transfer_buffer_length = len;
338 num_packets = 0;
339 packet_offset = 0;
340 while (packet_offset < len) {
341 desc = &urb->iso_frame_desc[num_packets];
342 desc->offset = packet_offset;
343 desc->length = SIZE_ISO_PACKETS_D_OUT;
344 if (len - packet_offset < desc->length)
345 desc->length = len - packet_offset;
346 num_packets++;
347 packet_offset += desc->length;
348 }
349 urb->number_of_packets = num_packets;
350
351 // Prepare the URB
352 urb->dev = adapter->usb_dev;
353 // Need to transmit the next buffer 2ms after the DEN_EVENT
354 urb->transfer_flags = 0;
355 urb->start_frame = usb_get_current_frame_number(adapter->usb_dev)+2;
356
357 DBG_ISO_PACKET(0x20,urb);
358
359 if (usb_submit_urb(urb, GFP_KERNEL) < 0) {
360 // There is another URB queued up
361 urb->transfer_flags = URB_ISO_ASAP;
362 SUBMIT_URB(urb, GFP_KERNEL);
363 }
364}
365
366static void fifo_reseted(void *context)
367{
368 struct st5481_adapter *adapter = context;
369
370 FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL);
371}
372
373static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs)
374{
375 struct st5481_adapter *adapter = urb->context;
376 struct st5481_d_out *d_out = &adapter->d_out;
377 int buf_nr;
378
379 DBG(2, "");
380
381 buf_nr = get_buf_nr(d_out->urb, urb);
382 test_and_clear_bit(buf_nr, &d_out->busy);
383
384 if (unlikely(urb->status < 0)) {
385 if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
386 WARN("urb status %d",urb->status);
387 if (d_out->busy == 0) {
388 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
389 }
390 return;
391 } else {
392 DBG(1,"urb killed");
393 return; // Give up
394 }
395 }
396
397 FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
398}
399
400/* ====================================================================== */
401
402static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
403{
404 // FIXME unify?
405 struct st5481_adapter *adapter = fsm->userdata;
406 struct st5481_d_out *d_out = &adapter->d_out;
407 struct urb *urb;
408 int len, bytes_sent;
409 struct sk_buff *skb;
410 int buf_nr = 0;
411
412 skb = d_out->tx_skb;
413
414 DBG(2,"len=%d",skb->len);
415
416 isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
417
418 if (test_and_set_bit(buf_nr, &d_out->busy)) {
419 WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
420 return;
421 }
422 urb = d_out->urb[buf_nr];
423
424 DBG_SKB(0x10, skb);
425 len = isdnhdlc_encode(&d_out->hdlc_state,
426 skb->data, skb->len, &bytes_sent,
427 urb->transfer_buffer, 16);
428 skb_pull(skb, bytes_sent);
429
430 if(len < 16)
431 FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_INIT);
432 else
433 FsmChangeState(&d_out->fsm, ST_DOUT_LONG_INIT);
434
435 if (skb->len == 0) {
436 d_out->tx_skb = NULL;
437 D_L1L2(adapter, PH_DATA | CONFIRM, NULL);
438 dev_kfree_skb_any(skb);
439 }
440
441// Prepare the URB
442 urb->transfer_buffer_length = len;
443
444 urb->iso_frame_desc[0].offset = 0;
445 urb->iso_frame_desc[0].length = len;
446 urb->number_of_packets = 1;
447
448 // Prepare the URB
449 urb->dev = adapter->usb_dev;
450 urb->transfer_flags = URB_ISO_ASAP;
451
452 DBG_ISO_PACKET(0x20,urb);
453 SUBMIT_URB(urb, GFP_KERNEL);
454}
455
456static void dout_short_fifo(struct FsmInst *fsm, int event, void *arg)
457{
458 struct st5481_adapter *adapter = fsm->userdata;
459 struct st5481_d_out *d_out = &adapter->d_out;
460
461 FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_WAIT_DEN);
462 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL);
463}
464
465static void dout_end_short_frame(struct FsmInst *fsm, int event, void *arg)
466{
467 struct st5481_adapter *adapter = fsm->userdata;
468 struct st5481_d_out *d_out = &adapter->d_out;
469
470 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);
471}
472
473static void dout_long_enable_fifo(struct FsmInst *fsm, int event, void *arg)
474{
475 struct st5481_adapter *adapter = fsm->userdata;
476 struct st5481_d_out *d_out = &adapter->d_out;
477
478 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL);
479 FsmChangeState(&d_out->fsm, ST_DOUT_LONG_WAIT_DEN);
480}
481
482static void dout_long_den(struct FsmInst *fsm, int event, void *arg)
483{
484 struct st5481_adapter *adapter = fsm->userdata;
485 struct st5481_d_out *d_out = &adapter->d_out;
486
487 FsmChangeState(&d_out->fsm, ST_DOUT_NORMAL);
488 usb_d_out(adapter, 0);
489 usb_d_out(adapter, 1);
490}
491
492static void dout_reset(struct FsmInst *fsm, int event, void *arg)
493{
494 struct st5481_adapter *adapter = fsm->userdata;
495 struct st5481_d_out *d_out = &adapter->d_out;
496
497 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_RESET);
498 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
499}
500
501static void dout_stop(struct FsmInst *fsm, int event, void *arg)
502{
503 struct st5481_adapter *adapter = fsm->userdata;
504 struct st5481_d_out *d_out = &adapter->d_out;
505
506 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_STOP);
507 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 0, dout_stop_event, adapter);
508}
509
510static void dout_underrun(struct FsmInst *fsm, int event, void *arg)
511{
512 struct st5481_adapter *adapter = fsm->userdata;
513 struct st5481_d_out *d_out = &adapter->d_out;
514
515 if (test_bit(0, &d_out->busy) || test_bit(1, &d_out->busy)) {
516 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_NOT_BUSY);
517 } else {
518 dout_stop(fsm, event, arg);
519 }
520}
521
522static void dout_check_busy(struct FsmInst *fsm, int event, void *arg)
523{
524 struct st5481_adapter *adapter = fsm->userdata;
525 struct st5481_d_out *d_out = &adapter->d_out;
526
527 if (!test_bit(0, &d_out->busy) && !test_bit(1, &d_out->busy))
528 dout_stop(fsm, event, arg);
529}
530
531static void dout_reseted(struct FsmInst *fsm, int event, void *arg)
532{
533 struct st5481_adapter *adapter = fsm->userdata;
534 struct st5481_d_out *d_out = &adapter->d_out;
535
536 FsmChangeState(&d_out->fsm, ST_DOUT_NONE);
537 // FIXME locking
538 if (d_out->tx_skb)
539 FsmEvent(&d_out->fsm, EV_DOUT_START_XMIT, NULL);
540}
541
542static void dout_complete(struct FsmInst *fsm, int event, void *arg)
543{
544 struct st5481_adapter *adapter = fsm->userdata;
545 int buf_nr = (int) arg;
546
547 usb_d_out(adapter, buf_nr);
548}
549
550static void dout_ignore(struct FsmInst *fsm, int event, void *arg)
551{
552}
553
554static struct FsmNode DoutFnList[] __initdata =
555{
556 {ST_DOUT_NONE, EV_DOUT_START_XMIT, dout_start_xmit},
557
558 {ST_DOUT_SHORT_INIT, EV_DOUT_COMPLETE, dout_short_fifo},
559
560 {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_DEN, dout_end_short_frame},
561 {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun},
562
563 {ST_DOUT_LONG_INIT, EV_DOUT_COMPLETE, dout_long_enable_fifo},
564
565 {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_DEN, dout_long_den},
566 {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun},
567
568 {ST_DOUT_NORMAL, EV_DOUT_UNDERRUN, dout_underrun},
569 {ST_DOUT_NORMAL, EV_DOUT_COMPLETE, dout_complete},
570
571 {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_UNDERRUN, dout_underrun},
572 {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_COMPLETE, dout_ignore},
573
574 {ST_DOUT_WAIT_FOR_NOT_BUSY, EV_DOUT_COMPLETE, dout_check_busy},
575
576 {ST_DOUT_WAIT_FOR_STOP, EV_DOUT_STOPPED, dout_reset},
577
578 {ST_DOUT_WAIT_FOR_RESET, EV_DOUT_RESETED, dout_reseted},
579};
580
581void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
582{
583 struct st5481_adapter *adapter = hisax_d_if->priv;
584 struct sk_buff *skb = arg;
585
586 switch (pr) {
587 case PH_ACTIVATE | REQUEST:
588 FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL);
589 break;
590 case PH_DEACTIVATE | REQUEST:
591 FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL);
592 break;
593 case PH_DATA | REQUEST:
594 DBG(2, "PH_DATA REQUEST len %d", skb->len);
595 if (adapter->d_out.tx_skb)
596 BUG();
597
598 adapter->d_out.tx_skb = skb;
599 FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL);
600 break;
601 default:
602 WARN("pr %#x\n", pr);
603 break;
604 }
605}
606
607/* ======================================================================
608 */
609
610/*
611 * Start receiving on the D channel since entered state F7.
612 */
613static void ph_connect(struct st5481_adapter *adapter)
614{
615 struct st5481_d_out *d_out = &adapter->d_out;
616 struct st5481_in *d_in = &adapter->d_in;
617
618 DBG(8,"");
619
620 FsmChangeState(&d_out->fsm, ST_DOUT_NONE);
621
622 // st5481_usb_device_ctrl_msg(adapter, FFMSK_D, OUT_UNDERRUN, NULL, NULL);
623 st5481_usb_device_ctrl_msg(adapter, FFMSK_D, 0xfc, NULL, NULL);
624 st5481_in_mode(d_in, L1_MODE_HDLC);
625
626#ifdef LOOPBACK
627 // Turn loopback on (data sent on B and D looped back)
628 st5481_usb_device_ctrl_msg(cs, LBB, 0x04, NULL, NULL);
629#endif
630
631 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, NULL, NULL);
632
633 // Turn on the green LED to tell that we are in state F7
634 adapter->leds |= GREEN_LED;
635 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
636}
637
638/*
639 * Stop receiving on the D channel since not in state F7.
640 */
641static void ph_disconnect(struct st5481_adapter *adapter)
642{
643 DBG(8,"");
644
645 st5481_in_mode(&adapter->d_in, L1_MODE_NULL);
646
647 // Turn off the green LED to tell that we left state F7
648 adapter->leds &= ~GREEN_LED;
649 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
650}
651
652static int st5481_setup_d_out(struct st5481_adapter *adapter)
653{
654 struct usb_device *dev = adapter->usb_dev;
655 struct usb_interface *intf;
656 struct usb_host_interface *altsetting = NULL;
657 struct usb_host_endpoint *endpoint;
658 struct st5481_d_out *d_out = &adapter->d_out;
659
660 DBG(2,"");
661
662 intf = usb_ifnum_to_if(dev, 0);
663 if (intf)
664 altsetting = usb_altnum_to_altsetting(intf, 3);
665 if (!altsetting)
666 return -ENXIO;
667
668 // Allocate URBs and buffers for the D channel out
669 endpoint = &altsetting->endpoint[EP_D_OUT-1];
670
671 DBG(2,"endpoint address=%02x,packet size=%d",
672 endpoint->desc.bEndpointAddress, le16_to_cpu(endpoint->desc.wMaxPacketSize));
673
674 return st5481_setup_isocpipes(d_out->urb, dev,
675 usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress),
676 NUM_ISO_PACKETS_D, SIZE_ISO_PACKETS_D_OUT,
677 NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT,
678 usb_d_out_complete, adapter);
679}
680
681static void st5481_release_d_out(struct st5481_adapter *adapter)
682{
683 struct st5481_d_out *d_out = &adapter->d_out;
684
685 DBG(2,"");
686
687 st5481_release_isocpipes(d_out->urb);
688}
689
690int st5481_setup_d(struct st5481_adapter *adapter)
691{
692 int retval;
693
694 DBG(2,"");
695
696 retval = st5481_setup_d_out(adapter);
697 if (retval)
698 goto err;
699 adapter->d_in.bufsize = MAX_DFRAME_LEN_L1;
700 adapter->d_in.num_packets = NUM_ISO_PACKETS_D;
701 adapter->d_in.packet_size = SIZE_ISO_PACKETS_D_IN;
702 adapter->d_in.ep = EP_D_IN | USB_DIR_IN;
703 adapter->d_in.counter = IN_D_COUNTER;
704 adapter->d_in.adapter = adapter;
705 adapter->d_in.hisax_if = &adapter->hisax_d_if.ifc;
706 retval = st5481_setup_in(&adapter->d_in);
707 if (retval)
708 goto err_d_out;
709
710 adapter->l1m.fsm = &l1fsm;
711 adapter->l1m.state = ST_L1_F3;
712 adapter->l1m.debug = 1;
713 adapter->l1m.userdata = adapter;
714 adapter->l1m.printdebug = l1m_debug;
715 FsmInitTimer(&adapter->l1m, &adapter->timer);
716
717 adapter->d_out.fsm.fsm = &dout_fsm;
718 adapter->d_out.fsm.state = ST_DOUT_NONE;
719 adapter->d_out.fsm.debug = 1;
720 adapter->d_out.fsm.userdata = adapter;
721 adapter->d_out.fsm.printdebug = dout_debug;
722
723 return 0;
724
725 err_d_out:
726 st5481_release_d_out(adapter);
727 err:
728 return retval;
729}
730
731void st5481_release_d(struct st5481_adapter *adapter)
732{
733 DBG(2,"");
734
735 st5481_release_in(&adapter->d_in);
736 st5481_release_d_out(adapter);
737}
738
739/* ======================================================================
740 * init / exit
741 */
742
743int __init st5481_d_init(void)
744{
745 int retval;
746
747 l1fsm.state_count = L1_STATE_COUNT;
748 l1fsm.event_count = L1_EVENT_COUNT;
749 l1fsm.strEvent = strL1Event;
750 l1fsm.strState = strL1State;
751 retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
752 if (retval)
753 goto err;
754
755 dout_fsm.state_count = DOUT_STATE_COUNT;
756 dout_fsm.event_count = DOUT_EVENT_COUNT;
757 dout_fsm.strEvent = strDoutEvent;
758 dout_fsm.strState = strDoutState;
759 retval = FsmNew(&dout_fsm, DoutFnList, ARRAY_SIZE(DoutFnList));
760 if (retval)
761 goto err_l1;
762
763 return 0;
764
765 err_l1:
766 FsmFree(&l1fsm);
767 err:
768 return retval;
769}
770
771// can't be __exit
772void st5481_d_exit(void)
773{
774 FsmFree(&l1fsm);
775 FsmFree(&dout_fsm);
776}
diff --git a/drivers/isdn/hisax/st5481_hdlc.c b/drivers/isdn/hisax/st5481_hdlc.c
new file mode 100644
index 00000000000..680f42e9a99
--- /dev/null
+++ b/drivers/isdn/hisax/st5481_hdlc.c
@@ -0,0 +1,580 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#include <linux/crc-ccitt.h>
14#include "st5481_hdlc.h"
15
16
17enum {
18 HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
19 HDLC_GET_DATA,HDLC_FAST_FLAG
20};
21
22enum {
23 HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
24 HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
25 HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
26 HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
27};
28
29void
30hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56)
31{
32 hdlc->bit_shift = 0;
33 hdlc->hdlc_bits1 = 0;
34 hdlc->data_bits = 0;
35 hdlc->ffbit_shift = 0;
36 hdlc->data_received = 0;
37 hdlc->state = HDLC_GET_DATA;
38 hdlc->do_adapt56 = do_adapt56;
39 hdlc->dchannel = 0;
40 hdlc->crc = 0;
41 hdlc->cbin = 0;
42 hdlc->shift_reg = 0;
43 hdlc->ffvalue = 0;
44 hdlc->dstpos = 0;
45}
46
47void
48hdlc_out_init(struct hdlc_vars *hdlc, int is_d_channel, int do_adapt56)
49{
50 hdlc->bit_shift = 0;
51 hdlc->hdlc_bits1 = 0;
52 hdlc->data_bits = 0;
53 hdlc->ffbit_shift = 0;
54 hdlc->data_received = 0;
55 hdlc->do_closing = 0;
56 hdlc->ffvalue = 0;
57 if (is_d_channel) {
58 hdlc->dchannel = 1;
59 hdlc->state = HDLC_SEND_FIRST_FLAG;
60 } else {
61 hdlc->dchannel = 0;
62 hdlc->state = HDLC_SEND_FAST_FLAG;
63 hdlc->ffvalue = 0x7e;
64 }
65 hdlc->cbin = 0x7e;
66 hdlc->bit_shift = 0;
67 if(do_adapt56){
68 hdlc->do_adapt56 = 1;
69 hdlc->data_bits = 0;
70 hdlc->state = HDLC_SENDFLAG_B0;
71 } else {
72 hdlc->do_adapt56 = 0;
73 hdlc->data_bits = 8;
74 }
75 hdlc->shift_reg = 0;
76}
77
78/*
79 hdlc_decode - decodes HDLC frames from a transparent bit stream.
80
81 The source buffer is scanned for valid HDLC frames looking for
82 flags (01111110) to indicate the start of a frame. If the start of
83 the frame is found, the bit stuffing is removed (0 after 5 1's).
84 When a new flag is found, the complete frame has been received
85 and the CRC is checked.
86 If a valid frame is found, the function returns the frame length
87 excluding the CRC with the bit HDLC_END_OF_FRAME set.
88 If the beginning of a valid frame is found, the function returns
89 the length.
90 If a framing error is found (too many 1s and not a flag) the function
91 returns the length with the bit HDLC_FRAMING_ERROR set.
92 If a CRC error is found the function returns the length with the
93 bit HDLC_CRC_ERROR set.
94 If the frame length exceeds the destination buffer size, the function
95 returns the length with the bit HDLC_LENGTH_ERROR set.
96
97 src - source buffer
98 slen - source buffer length
99 count - number of bytes removed (decoded) from the source buffer
100 dst _ destination buffer
101 dsize - destination buffer size
102 returns - number of decoded bytes in the destination buffer and status
103 flag.
104 */
105int hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src,
106 int slen, int *count, unsigned char *dst, int dsize)
107{
108 int status=0;
109
110 static const unsigned char fast_flag[]={
111 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
112 };
113
114 static const unsigned char fast_flag_value[]={
115 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
116 };
117
118 static const unsigned char fast_abort[]={
119 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
120 };
121
122 *count = slen;
123
124 while(slen > 0){
125 if(hdlc->bit_shift==0){
126 hdlc->cbin = *src++;
127 slen--;
128 hdlc->bit_shift = 8;
129 if(hdlc->do_adapt56){
130 hdlc->bit_shift --;
131 }
132 }
133
134 switch(hdlc->state){
135 case STOPPED:
136 return 0;
137 case HDLC_FAST_IDLE:
138 if(hdlc->cbin == 0xff){
139 hdlc->bit_shift = 0;
140 break;
141 }
142 hdlc->state = HDLC_GET_FLAG_B0;
143 hdlc->hdlc_bits1 = 0;
144 hdlc->bit_shift = 8;
145 break;
146 case HDLC_GET_FLAG_B0:
147 if(!(hdlc->cbin & 0x80)) {
148 hdlc->state = HDLC_GETFLAG_B1A6;
149 hdlc->hdlc_bits1 = 0;
150 } else {
151 if(!hdlc->do_adapt56){
152 if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
153 hdlc->state = HDLC_FAST_IDLE;
154 }
155 }
156 hdlc->cbin<<=1;
157 hdlc->bit_shift --;
158 break;
159 case HDLC_GETFLAG_B1A6:
160 if(hdlc->cbin & 0x80){
161 hdlc->hdlc_bits1++;
162 if(hdlc->hdlc_bits1==6){
163 hdlc->state = HDLC_GETFLAG_B7;
164 }
165 } else {
166 hdlc->hdlc_bits1 = 0;
167 }
168 hdlc->cbin<<=1;
169 hdlc->bit_shift --;
170 break;
171 case HDLC_GETFLAG_B7:
172 if(hdlc->cbin & 0x80) {
173 hdlc->state = HDLC_GET_FLAG_B0;
174 } else {
175 hdlc->state = HDLC_GET_DATA;
176 hdlc->crc = 0xffff;
177 hdlc->shift_reg = 0;
178 hdlc->hdlc_bits1 = 0;
179 hdlc->data_bits = 0;
180 hdlc->data_received = 0;
181 }
182 hdlc->cbin<<=1;
183 hdlc->bit_shift --;
184 break;
185 case HDLC_GET_DATA:
186 if(hdlc->cbin & 0x80){
187 hdlc->hdlc_bits1++;
188 switch(hdlc->hdlc_bits1){
189 case 6:
190 break;
191 case 7:
192 if(hdlc->data_received) {
193 // bad frame
194 status = -HDLC_FRAMING_ERROR;
195 }
196 if(!hdlc->do_adapt56){
197 if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
198 hdlc->state = HDLC_FAST_IDLE;
199 hdlc->bit_shift=1;
200 break;
201 }
202 } else {
203 hdlc->state = HDLC_GET_FLAG_B0;
204 }
205 break;
206 default:
207 hdlc->shift_reg>>=1;
208 hdlc->shift_reg |= 0x80;
209 hdlc->data_bits++;
210 break;
211 }
212 } else {
213 switch(hdlc->hdlc_bits1){
214 case 5:
215 break;
216 case 6:
217 if(hdlc->data_received){
218 if (hdlc->dstpos < 2) {
219 status = -HDLC_FRAMING_ERROR;
220 } else if (hdlc->crc != 0xf0b8){
221 // crc error
222 status = -HDLC_CRC_ERROR;
223 } else {
224 // remove CRC
225 hdlc->dstpos -= 2;
226 // good frame
227 status = hdlc->dstpos;
228 }
229 }
230 hdlc->crc = 0xffff;
231 hdlc->shift_reg = 0;
232 hdlc->data_bits = 0;
233 if(!hdlc->do_adapt56){
234 if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
235 hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
236 hdlc->state = HDLC_FAST_FLAG;
237 hdlc->ffbit_shift = hdlc->bit_shift;
238 hdlc->bit_shift = 1;
239 } else {
240 hdlc->state = HDLC_GET_DATA;
241 hdlc->data_received = 0;
242 }
243 } else {
244 hdlc->state = HDLC_GET_DATA;
245 hdlc->data_received = 0;
246 }
247 break;
248 default:
249 hdlc->shift_reg>>=1;
250 hdlc->data_bits++;
251 break;
252 }
253 hdlc->hdlc_bits1 = 0;
254 }
255 if (status) {
256 hdlc->dstpos = 0;
257 *count -= slen;
258 hdlc->cbin <<= 1;
259 hdlc->bit_shift--;
260 return status;
261 }
262 if(hdlc->data_bits==8){
263 hdlc->data_bits = 0;
264 hdlc->data_received = 1;
265 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
266
267 // good byte received
268 if (dsize--) {
269 dst[hdlc->dstpos++] = hdlc->shift_reg;
270 } else {
271 // frame too long
272 status = -HDLC_LENGTH_ERROR;
273 hdlc->dstpos = 0;
274 }
275 }
276 hdlc->cbin <<= 1;
277 hdlc->bit_shift--;
278 break;
279 case HDLC_FAST_FLAG:
280 if(hdlc->cbin==hdlc->ffvalue){
281 hdlc->bit_shift = 0;
282 break;
283 } else {
284 if(hdlc->cbin == 0xff){
285 hdlc->state = HDLC_FAST_IDLE;
286 hdlc->bit_shift=0;
287 } else if(hdlc->ffbit_shift==8){
288 hdlc->state = HDLC_GETFLAG_B7;
289 break;
290 } else {
291 hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
292 hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
293 if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
294 hdlc->data_bits = hdlc->ffbit_shift-1;
295 hdlc->state = HDLC_GET_DATA;
296 hdlc->data_received = 0;
297 }
298 }
299 break;
300 default:
301 break;
302 }
303 }
304 *count -= slen;
305 return 0;
306}
307
308/*
309 hdlc_encode - encodes HDLC frames to a transparent bit stream.
310
311 The bit stream starts with a beginning flag (01111110). After
312 that each byte is added to the bit stream with bit stuffing added
313 (0 after 5 1's).
314 When the last byte has been removed from the source buffer, the
315 CRC (2 bytes is added) and the frame terminates with the ending flag.
316 For the dchannel, the idle character (all 1's) is also added at the end.
317 If this function is called with empty source buffer (slen=0), flags or
318 idle character will be generated.
319
320 src - source buffer
321 slen - source buffer length
322 count - number of bytes removed (encoded) from source buffer
323 dst _ destination buffer
324 dsize - destination buffer size
325 returns - number of encoded bytes in the destination buffer
326*/
327int hdlc_encode(struct hdlc_vars *hdlc, const unsigned char *src,
328 unsigned short slen, int *count,
329 unsigned char *dst, int dsize)
330{
331 static const unsigned char xfast_flag_value[] = {
332 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
333 };
334
335 int len = 0;
336
337 *count = slen;
338
339 while (dsize > 0) {
340 if(hdlc->bit_shift==0){
341 if(slen && !hdlc->do_closing){
342 hdlc->shift_reg = *src++;
343 slen--;
344 if (slen == 0)
345 hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */
346 hdlc->bit_shift = 8;
347 } else {
348 if(hdlc->state == HDLC_SEND_DATA){
349 if(hdlc->data_received){
350 hdlc->state = HDLC_SEND_CRC1;
351 hdlc->crc ^= 0xffff;
352 hdlc->bit_shift = 8;
353 hdlc->shift_reg = hdlc->crc & 0xff;
354 } else if(!hdlc->do_adapt56){
355 hdlc->state = HDLC_SEND_FAST_FLAG;
356 } else {
357 hdlc->state = HDLC_SENDFLAG_B0;
358 }
359 }
360
361 }
362 }
363
364 switch(hdlc->state){
365 case STOPPED:
366 while (dsize--)
367 *dst++ = 0xff;
368
369 return dsize;
370 case HDLC_SEND_FAST_FLAG:
371 hdlc->do_closing = 0;
372 if(slen == 0){
373 *dst++ = hdlc->ffvalue;
374 len++;
375 dsize--;
376 break;
377 }
378 if(hdlc->bit_shift==8){
379 hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
380 hdlc->state = HDLC_SEND_DATA;
381 hdlc->crc = 0xffff;
382 hdlc->hdlc_bits1 = 0;
383 hdlc->data_received = 1;
384 }
385 break;
386 case HDLC_SENDFLAG_B0:
387 hdlc->do_closing = 0;
388 hdlc->cbin <<= 1;
389 hdlc->data_bits++;
390 hdlc->hdlc_bits1 = 0;
391 hdlc->state = HDLC_SENDFLAG_B1A6;
392 break;
393 case HDLC_SENDFLAG_B1A6:
394 hdlc->cbin <<= 1;
395 hdlc->data_bits++;
396 hdlc->cbin++;
397 if(++hdlc->hdlc_bits1 == 6)
398 hdlc->state = HDLC_SENDFLAG_B7;
399 break;
400 case HDLC_SENDFLAG_B7:
401 hdlc->cbin <<= 1;
402 hdlc->data_bits++;
403 if(slen == 0){
404 hdlc->state = HDLC_SENDFLAG_B0;
405 break;
406 }
407 if(hdlc->bit_shift==8){
408 hdlc->state = HDLC_SEND_DATA;
409 hdlc->crc = 0xffff;
410 hdlc->hdlc_bits1 = 0;
411 hdlc->data_received = 1;
412 }
413 break;
414 case HDLC_SEND_FIRST_FLAG:
415 hdlc->data_received = 1;
416 if(hdlc->data_bits==8){
417 hdlc->state = HDLC_SEND_DATA;
418 hdlc->crc = 0xffff;
419 hdlc->hdlc_bits1 = 0;
420 break;
421 }
422 hdlc->cbin <<= 1;
423 hdlc->data_bits++;
424 if(hdlc->shift_reg & 0x01)
425 hdlc->cbin++;
426 hdlc->shift_reg >>= 1;
427 hdlc->bit_shift--;
428 if(hdlc->bit_shift==0){
429 hdlc->state = HDLC_SEND_DATA;
430 hdlc->crc = 0xffff;
431 hdlc->hdlc_bits1 = 0;
432 }
433 break;
434 case HDLC_SEND_DATA:
435 hdlc->cbin <<= 1;
436 hdlc->data_bits++;
437 if(hdlc->hdlc_bits1 == 5){
438 hdlc->hdlc_bits1 = 0;
439 break;
440 }
441 if(hdlc->bit_shift==8){
442 hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
443 }
444 if(hdlc->shift_reg & 0x01){
445 hdlc->hdlc_bits1++;
446 hdlc->cbin++;
447 hdlc->shift_reg >>= 1;
448 hdlc->bit_shift--;
449 } else {
450 hdlc->hdlc_bits1 = 0;
451 hdlc->shift_reg >>= 1;
452 hdlc->bit_shift--;
453 }
454 break;
455 case HDLC_SEND_CRC1:
456 hdlc->cbin <<= 1;
457 hdlc->data_bits++;
458 if(hdlc->hdlc_bits1 == 5){
459 hdlc->hdlc_bits1 = 0;
460 break;
461 }
462 if(hdlc->shift_reg & 0x01){
463 hdlc->hdlc_bits1++;
464 hdlc->cbin++;
465 hdlc->shift_reg >>= 1;
466 hdlc->bit_shift--;
467 } else {
468 hdlc->hdlc_bits1 = 0;
469 hdlc->shift_reg >>= 1;
470 hdlc->bit_shift--;
471 }
472 if(hdlc->bit_shift==0){
473 hdlc->shift_reg = (hdlc->crc >> 8);
474 hdlc->state = HDLC_SEND_CRC2;
475 hdlc->bit_shift = 8;
476 }
477 break;
478 case HDLC_SEND_CRC2:
479 hdlc->cbin <<= 1;
480 hdlc->data_bits++;
481 if(hdlc->hdlc_bits1 == 5){
482 hdlc->hdlc_bits1 = 0;
483 break;
484 }
485 if(hdlc->shift_reg & 0x01){
486 hdlc->hdlc_bits1++;
487 hdlc->cbin++;
488 hdlc->shift_reg >>= 1;
489 hdlc->bit_shift--;
490 } else {
491 hdlc->hdlc_bits1 = 0;
492 hdlc->shift_reg >>= 1;
493 hdlc->bit_shift--;
494 }
495 if(hdlc->bit_shift==0){
496 hdlc->shift_reg = 0x7e;
497 hdlc->state = HDLC_SEND_CLOSING_FLAG;
498 hdlc->bit_shift = 8;
499 }
500 break;
501 case HDLC_SEND_CLOSING_FLAG:
502 hdlc->cbin <<= 1;
503 hdlc->data_bits++;
504 if(hdlc->hdlc_bits1 == 5){
505 hdlc->hdlc_bits1 = 0;
506 break;
507 }
508 if(hdlc->shift_reg & 0x01){
509 hdlc->cbin++;
510 }
511 hdlc->shift_reg >>= 1;
512 hdlc->bit_shift--;
513 if(hdlc->bit_shift==0){
514 hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
515 if(hdlc->dchannel){
516 hdlc->ffvalue = 0x7e;
517 hdlc->state = HDLC_SEND_IDLE1;
518 hdlc->bit_shift = 8-hdlc->data_bits;
519 if(hdlc->bit_shift==0)
520 hdlc->state = HDLC_SEND_FAST_IDLE;
521 } else {
522 if(!hdlc->do_adapt56){
523 hdlc->state = HDLC_SEND_FAST_FLAG;
524 hdlc->data_received = 0;
525 } else {
526 hdlc->state = HDLC_SENDFLAG_B0;
527 hdlc->data_received = 0;
528 }
529 // Finished with this frame, send flags
530 if (dsize > 1) dsize = 1;
531 }
532 }
533 break;
534 case HDLC_SEND_IDLE1:
535 hdlc->do_closing = 0;
536 hdlc->cbin <<= 1;
537 hdlc->cbin++;
538 hdlc->data_bits++;
539 hdlc->bit_shift--;
540 if(hdlc->bit_shift==0){
541 hdlc->state = HDLC_SEND_FAST_IDLE;
542 hdlc->bit_shift = 0;
543 }
544 break;
545 case HDLC_SEND_FAST_IDLE:
546 hdlc->do_closing = 0;
547 hdlc->cbin = 0xff;
548 hdlc->data_bits = 8;
549 if(hdlc->bit_shift == 8){
550 hdlc->cbin = 0x7e;
551 hdlc->state = HDLC_SEND_FIRST_FLAG;
552 } else {
553 *dst++ = hdlc->cbin;
554 hdlc->bit_shift = hdlc->data_bits = 0;
555 len++;
556 dsize = 0;
557 }
558 break;
559 default:
560 break;
561 }
562 if(hdlc->do_adapt56){
563 if(hdlc->data_bits==7){
564 hdlc->cbin <<= 1;
565 hdlc->cbin++;
566 hdlc->data_bits++;
567 }
568 }
569 if(hdlc->data_bits==8){
570 *dst++ = hdlc->cbin;
571 hdlc->data_bits = 0;
572 len++;
573 dsize--;
574 }
575 }
576 *count -= slen;
577
578 return len;
579}
580
diff --git a/drivers/isdn/hisax/st5481_hdlc.h b/drivers/isdn/hisax/st5481_hdlc.h
new file mode 100644
index 00000000000..495432f0f6b
--- /dev/null
+++ b/drivers/isdn/hisax/st5481_hdlc.h
@@ -0,0 +1,62 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#ifndef __ST5481_HDLC_H__
14#define __ST5481_HDLC_H__
15
16struct hdlc_vars {
17 int bit_shift;
18 int hdlc_bits1;
19 int data_bits;
20 int ffbit_shift; // encoding only
21 int state;
22 int dstpos;
23
24 int data_received:1; // set if transferring data
25 int dchannel:1; // set if D channel (send idle instead of flags)
26 int do_adapt56:1; // set if 56K adaptation
27 int do_closing:1; // set if in closing phase (need to send CRC + flag
28
29 unsigned short crc;
30
31 unsigned char cbin;
32 unsigned char shift_reg;
33 unsigned char ffvalue;
34
35};
36
37
38/*
39 The return value from hdlc_decode is
40 the frame length, 0 if no complete frame was decoded,
41 or a negative error number
42*/
43
44#define HDLC_FRAMING_ERROR 1
45#define HDLC_CRC_ERROR 2
46#define HDLC_LENGTH_ERROR 3
47
48void
49hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56);
50
51int
52hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
53 unsigned char *dst, int dsize);
54
55void
56hdlc_out_init(struct hdlc_vars *hdlc,int is_d_channel,int do_adapt56);
57
58int
59hdlc_encode(struct hdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
60 unsigned char *dst,int dsize);
61
62#endif
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
new file mode 100644
index 00000000000..7aa810d5d33
--- /dev/null
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -0,0 +1,224 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13/*
14 * TODO:
15 *
16 * b layer1 delay?
17 * hotplug / unregister issues
18 * mod_inc/dec_use_count
19 * unify parts of d/b channel usb handling
20 * file header
21 * avoid copy to isoc buffer?
22 * improve usb delay?
23 * merge l1 state machines?
24 * clean up debug
25 */
26
27#include <linux/config.h>
28#include <linux/version.h>
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/usb.h>
32#include <linux/slab.h>
33#include "st5481.h"
34
35MODULE_DESCRIPTION("ISDN4Linux: driver for ST5481 USB ISDN adapter");
36MODULE_AUTHOR("Frode Isaksen");
37MODULE_LICENSE("GPL");
38
39static int protocol = 2; /* EURO-ISDN Default */
40module_param(protocol, int, 0);
41
42static int number_of_leds = 2; /* 2 LEDs on the adpater default */
43module_param(number_of_leds, int, 0);
44
45#ifdef CONFIG_HISAX_DEBUG
46static int debug = 0x1;
47module_param(debug, int, 0);
48int st5481_debug;
49#endif
50
51static LIST_HEAD(adapter_list);
52
53/* ======================================================================
54 * registration/deregistration with the USB layer
55 */
56
57/*
58 * This function will be called when the adapter is plugged
59 * into the USB bus.
60 */
61static int probe_st5481(struct usb_interface *intf,
62 const struct usb_device_id *id)
63{
64 struct usb_device *dev = interface_to_usbdev(intf);
65 struct st5481_adapter *adapter;
66 struct hisax_b_if *b_if[2];
67 int retval, i;
68
69 printk(KERN_INFO "st541: found adapter VendorId %04x, ProductId %04x, LEDs %d\n",
70 le16_to_cpu(dev->descriptor.idVendor),
71 le16_to_cpu(dev->descriptor.idProduct),
72 number_of_leds);
73
74 adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL);
75 if (!adapter)
76 return -ENOMEM;
77
78 memset(adapter, 0, sizeof(struct st5481_adapter));
79
80 adapter->number_of_leds = number_of_leds;
81 adapter->usb_dev = dev;
82
83 adapter->hisax_d_if.owner = THIS_MODULE;
84 adapter->hisax_d_if.ifc.priv = adapter;
85 adapter->hisax_d_if.ifc.l2l1 = st5481_d_l2l1;
86
87 for (i = 0; i < 2; i++) {
88 adapter->bcs[i].adapter = adapter;
89 adapter->bcs[i].channel = i;
90 adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
91 adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1;
92 }
93 list_add(&adapter->list, &adapter_list);
94
95 retval = st5481_setup_usb(adapter);
96 if (retval < 0)
97 goto err;
98
99 retval = st5481_setup_d(adapter);
100 if (retval < 0)
101 goto err_usb;
102
103 retval = st5481_setup_b(&adapter->bcs[0]);
104 if (retval < 0)
105 goto err_d;
106
107 retval = st5481_setup_b(&adapter->bcs[1]);
108 if (retval < 0)
109 goto err_b;
110
111 for (i = 0; i < 2; i++)
112 b_if[i] = &adapter->bcs[i].b_if;
113
114 hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol);
115 st5481_start(adapter);
116
117 usb_set_intfdata(intf, adapter);
118 return 0;
119
120 err_b:
121 st5481_release_b(&adapter->bcs[0]);
122 err_d:
123 st5481_release_d(adapter);
124 err_usb:
125 st5481_release_usb(adapter);
126 err:
127 return -EIO;
128}
129
130/*
131 * This function will be called when the adapter is removed
132 * from the USB bus.
133 */
134static void disconnect_st5481(struct usb_interface *intf)
135{
136 struct st5481_adapter *adapter = usb_get_intfdata(intf);
137
138 DBG(1,"");
139
140 usb_set_intfdata(intf, NULL);
141 if (!adapter)
142 return;
143
144 list_del(&adapter->list);
145
146 st5481_stop(adapter);
147 st5481_release_b(&adapter->bcs[1]);
148 st5481_release_b(&adapter->bcs[0]);
149 st5481_release_d(adapter);
150 // we would actually better wait for completion of outstanding urbs
151 mdelay(2);
152 st5481_release_usb(adapter);
153
154 hisax_unregister(&adapter->hisax_d_if);
155
156 kfree(adapter);
157}
158
159/*
160 * The last 4 bits in the Product Id is set with 4 pins on the chip.
161 */
162static struct usb_device_id st5481_ids[] = {
163 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x0) },
164 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x1) },
165 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x2) },
166 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x3) },
167 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x4) },
168 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x5) },
169 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x6) },
170 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x7) },
171 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x8) },
172 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x9) },
173 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xA) },
174 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xB) },
175 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xC) },
176 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xD) },
177 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xE) },
178 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xF) },
179 { }
180};
181MODULE_DEVICE_TABLE (usb, st5481_ids);
182
183static struct usb_driver st5481_usb_driver = {
184 .owner = THIS_MODULE,
185 .name = "st5481_usb",
186 .probe = probe_st5481,
187 .disconnect = disconnect_st5481,
188 .id_table = st5481_ids,
189};
190
191static int __init st5481_usb_init(void)
192{
193 int retval;
194
195#ifdef CONFIG_HISAX_DEBUG
196 st5481_debug = debug;
197#endif
198
199 printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $\n");
200
201 retval = st5481_d_init();
202 if (retval < 0)
203 goto out;
204
205 retval = usb_register(&st5481_usb_driver);
206 if (retval < 0)
207 goto out_d_exit;
208
209 return 0;
210
211 out_d_exit:
212 st5481_d_exit();
213 out:
214 return retval;
215}
216
217static void __exit st5481_usb_exit(void)
218{
219 usb_deregister(&st5481_usb_driver);
220 st5481_d_exit();
221}
222
223module_init(st5481_usb_init);
224module_exit(st5481_usb_exit);
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
new file mode 100644
index 00000000000..2369180b1cb
--- /dev/null
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -0,0 +1,650 @@
1/*
2 * Driver for ST5481 USB ISDN modem
3 *
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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
13#include <linux/init.h>
14#include <linux/usb.h>
15#include <linux/slab.h>
16#include "st5481.h"
17
18/* ======================================================================
19 * control pipe
20 */
21
22/*
23 * Send the next endpoint 0 request stored in the FIFO.
24 * Called either by the completion or by usb_ctrl_msg.
25 */
26static void usb_next_ctrl_msg(struct urb *urb,
27 struct st5481_adapter *adapter)
28{
29 struct st5481_ctrl *ctrl = &adapter->ctrl;
30 int r_index;
31
32 if (test_and_set_bit(0, &ctrl->busy)) {
33 return;
34 }
35
36 if ((r_index = fifo_remove(&ctrl->msg_fifo.f)) < 0) {
37 test_and_clear_bit(0,&ctrl->busy);
38 return;
39 }
40 urb->setup_packet =
41 (unsigned char *)&ctrl->msg_fifo.data[r_index];
42
43 DBG(1,"request=0x%02x,value=0x%04x,index=%x",
44 ((struct ctrl_msg *)urb->setup_packet)->dr.bRequest,
45 ((struct ctrl_msg *)urb->setup_packet)->dr.wValue,
46 ((struct ctrl_msg *)urb->setup_packet)->dr.wIndex);
47
48 // Prepare the URB
49 urb->dev = adapter->usb_dev;
50
51 SUBMIT_URB(urb, GFP_ATOMIC);
52}
53
54/*
55 * Asynchronous endpoint 0 request (async version of usb_control_msg).
56 * The request will be queued up in a FIFO if the endpoint is busy.
57 */
58void usb_ctrl_msg(struct st5481_adapter *adapter,
59 u8 request, u8 requesttype, u16 value, u16 index,
60 ctrl_complete_t complete, void *context)
61{
62 struct st5481_ctrl *ctrl = &adapter->ctrl;
63 int w_index;
64 struct ctrl_msg *ctrl_msg;
65
66 if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) {
67 WARN("control msg FIFO full");
68 return;
69 }
70 ctrl_msg = &ctrl->msg_fifo.data[w_index];
71
72 ctrl_msg->dr.bRequestType = requesttype;
73 ctrl_msg->dr.bRequest = request;
74 ctrl_msg->dr.wValue = cpu_to_le16p(&value);
75 ctrl_msg->dr.wIndex = cpu_to_le16p(&index);
76 ctrl_msg->dr.wLength = 0;
77 ctrl_msg->complete = complete;
78 ctrl_msg->context = context;
79
80 usb_next_ctrl_msg(ctrl->urb, adapter);
81}
82
83/*
84 * Asynchronous endpoint 0 device request.
85 */
86void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter,
87 u8 request, u16 value,
88 ctrl_complete_t complete, void *context)
89{
90 usb_ctrl_msg(adapter, request,
91 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
92 value, 0, complete, context);
93}
94
95/*
96 * Asynchronous pipe reset (async version of usb_clear_halt).
97 */
98void st5481_usb_pipe_reset(struct st5481_adapter *adapter,
99 u_char pipe,
100 ctrl_complete_t complete, void *context)
101{
102 DBG(1,"pipe=%02x",pipe);
103
104 usb_ctrl_msg(adapter,
105 USB_REQ_CLEAR_FEATURE, USB_DIR_OUT | USB_RECIP_ENDPOINT,
106 0, pipe, complete, context);
107}
108
109
110/*
111 Physical level functions
112*/
113
114void st5481_ph_command(struct st5481_adapter *adapter, unsigned int command)
115{
116 DBG(8,"command=%s", ST5481_CMD_string(command));
117
118 st5481_usb_device_ctrl_msg(adapter, TXCI, command, NULL, NULL);
119}
120
121/*
122 * The request on endpoint 0 has completed.
123 * Call the user provided completion routine and try
124 * to send the next request.
125 */
126static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs)
127{
128 struct st5481_adapter *adapter = urb->context;
129 struct st5481_ctrl *ctrl = &adapter->ctrl;
130 struct ctrl_msg *ctrl_msg;
131
132 if (unlikely(urb->status < 0)) {
133 if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
134 WARN("urb status %d",urb->status);
135 } else {
136 DBG(1,"urb killed");
137 return; // Give up
138 }
139 }
140
141 ctrl_msg = (struct ctrl_msg *)urb->setup_packet;
142
143 if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
144 /* Special case handling for pipe reset */
145 le16_to_cpus(&ctrl_msg->dr.wIndex);
146
147 /* toggle is reset on clear */
148 usb_settoggle(adapter->usb_dev,
149 ctrl_msg->dr.wIndex & ~USB_DIR_IN,
150 (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0,
151 0);
152
153
154 }
155
156 if (ctrl_msg->complete)
157 ctrl_msg->complete(ctrl_msg->context);
158
159 clear_bit(0, &ctrl->busy);
160
161 // Try to send next control message
162 usb_next_ctrl_msg(urb, adapter);
163 return;
164}
165
166/* ======================================================================
167 * interrupt pipe
168 */
169
170/*
171 * The interrupt endpoint will be called when any
172 * of the 6 registers changes state (depending on masks).
173 * Decode the register values and schedule a private event.
174 * Called at interrupt.
175 */
176static void usb_int_complete(struct urb *urb, struct pt_regs *regs)
177{
178 u8 *data = urb->transfer_buffer;
179 u8 irqbyte;
180 struct st5481_adapter *adapter = urb->context;
181 int j;
182 int status;
183
184 switch (urb->status) {
185 case 0:
186 /* success */
187 break;
188 case -ECONNRESET:
189 case -ENOENT:
190 case -ESHUTDOWN:
191 /* this urb is terminated, clean up */
192 DBG(1, "urb shutting down with status: %d", urb->status);
193 return;
194 default:
195 WARN("nonzero urb status received: %d", urb->status);
196 goto exit;
197 }
198
199
200 DBG_PACKET(1, data, INT_PKT_SIZE);
201
202 if (urb->actual_length == 0) {
203 goto exit;
204 }
205
206 irqbyte = data[MPINT];
207 if (irqbyte & DEN_INT)
208 FsmEvent(&adapter->d_out.fsm, EV_DOUT_DEN, NULL);
209
210 if (irqbyte & DCOLL_INT)
211 FsmEvent(&adapter->d_out.fsm, EV_DOUT_COLL, NULL);
212
213 irqbyte = data[FFINT_D];
214 if (irqbyte & OUT_UNDERRUN)
215 FsmEvent(&adapter->d_out.fsm, EV_DOUT_UNDERRUN, NULL);
216
217 if (irqbyte & OUT_DOWN)
218;// printk("OUT_DOWN\n");
219
220 irqbyte = data[MPINT];
221 if (irqbyte & RXCI_INT)
222 FsmEvent(&adapter->l1m, data[CCIST] & 0x0f, NULL);
223
224 for (j = 0; j < 2; j++)
225 adapter->bcs[j].b_out.flow_event |= data[FFINT_B1 + j];
226
227 urb->actual_length = 0;
228
229exit:
230 status = usb_submit_urb (urb, GFP_ATOMIC);
231 if (status)
232 WARN("usb_submit_urb failed with result %d", status);
233}
234
235/* ======================================================================
236 * initialization
237 */
238
239int st5481_setup_usb(struct st5481_adapter *adapter)
240{
241 struct usb_device *dev = adapter->usb_dev;
242 struct st5481_ctrl *ctrl = &adapter->ctrl;
243 struct st5481_intr *intr = &adapter->intr;
244 struct usb_interface *intf;
245 struct usb_host_interface *altsetting = NULL;
246 struct usb_host_endpoint *endpoint;
247 int status;
248 struct urb *urb;
249 u8 *buf;
250
251 DBG(1,"");
252
253 if ((status = usb_reset_configuration (dev)) < 0) {
254 WARN("reset_configuration failed,status=%d",status);
255 return status;
256 }
257
258 intf = usb_ifnum_to_if(dev, 0);
259 if (intf)
260 altsetting = usb_altnum_to_altsetting(intf, 3);
261 if (!altsetting)
262 return -ENXIO;
263
264 // Check if the config is sane
265 if ( altsetting->desc.bNumEndpoints != 7 ) {
266 WARN("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints);
267 return -EINVAL;
268 }
269
270 // The descriptor is wrong for some early samples of the ST5481 chip
271 altsetting->endpoint[3].desc.wMaxPacketSize = __constant_cpu_to_le16(32);
272 altsetting->endpoint[4].desc.wMaxPacketSize = __constant_cpu_to_le16(32);
273
274 // Use alternative setting 3 on interface 0 to have 2B+D
275 if ((status = usb_set_interface (dev, 0, 3)) < 0) {
276 WARN("usb_set_interface failed,status=%d",status);
277 return status;
278 }
279
280 // Allocate URB for control endpoint
281 urb = usb_alloc_urb(0, GFP_KERNEL);
282 if (!urb) {
283 return -ENOMEM;
284 }
285 ctrl->urb = urb;
286
287 // Fill the control URB
288 usb_fill_control_urb (urb, dev,
289 usb_sndctrlpipe(dev, 0),
290 NULL, NULL, 0, usb_ctrl_complete, adapter);
291
292
293 fifo_init(&ctrl->msg_fifo.f, ARRAY_SIZE(ctrl->msg_fifo.data));
294
295 // Allocate URBs and buffers for interrupt endpoint
296 urb = usb_alloc_urb(0, GFP_KERNEL);
297 if (!urb) {
298 return -ENOMEM;
299 }
300 intr->urb = urb;
301
302 buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL);
303 if (!buf) {
304 return -ENOMEM;
305 }
306
307 endpoint = &altsetting->endpoint[EP_INT-1];
308
309 // Fill the interrupt URB
310 usb_fill_int_urb(urb, dev,
311 usb_rcvintpipe(dev, endpoint->desc.bEndpointAddress),
312 buf, INT_PKT_SIZE,
313 usb_int_complete, adapter,
314 endpoint->desc.bInterval);
315
316 return 0;
317}
318
319/*
320 * Release buffers and URBs for the interrupt and control
321 * endpoint.
322 */
323void st5481_release_usb(struct st5481_adapter *adapter)
324{
325 struct st5481_intr *intr = &adapter->intr;
326 struct st5481_ctrl *ctrl = &adapter->ctrl;
327
328 DBG(1,"");
329
330 // Stop and free Control and Interrupt URBs
331 usb_unlink_urb(ctrl->urb);
332 if (ctrl->urb->transfer_buffer)
333 kfree(ctrl->urb->transfer_buffer);
334 usb_free_urb(ctrl->urb);
335
336 usb_unlink_urb(intr->urb);
337 if (intr->urb->transfer_buffer)
338 kfree(intr->urb->transfer_buffer);
339 usb_free_urb(intr->urb);
340}
341
342/*
343 * Initialize the adapter.
344 */
345void st5481_start(struct st5481_adapter *adapter)
346{
347 static const u8 init_cmd_table[]={
348 SET_DEFAULT,0,
349 STT,0,
350 SDA_MIN,0x0d,
351 SDA_MAX,0x29,
352 SDELAY_VALUE,0x14,
353 GPIO_DIR,0x01,
354 GPIO_OUT,RED_LED,
355// FFCTRL_OUT_D,4,
356// FFCTRH_OUT_D,12,
357 FFCTRL_OUT_B1,6,
358 FFCTRH_OUT_B1,20,
359 FFCTRL_OUT_B2,6,
360 FFCTRH_OUT_B2,20,
361 MPMSK,RXCI_INT+DEN_INT+DCOLL_INT,
362 0
363 };
364 struct st5481_intr *intr = &adapter->intr;
365 int i = 0;
366 u8 request,value;
367
368 DBG(8,"");
369
370 adapter->leds = RED_LED;
371
372 // Start receiving on the interrupt endpoint
373 SUBMIT_URB(intr->urb, GFP_KERNEL);
374
375 while ((request = init_cmd_table[i++])) {
376 value = init_cmd_table[i++];
377 st5481_usb_device_ctrl_msg(adapter, request, value, NULL, NULL);
378 }
379 st5481_ph_command(adapter, ST5481_CMD_PUP);
380}
381
382/*
383 * Reset the adapter to default values.
384 */
385void st5481_stop(struct st5481_adapter *adapter)
386{
387 DBG(8,"");
388
389 st5481_usb_device_ctrl_msg(adapter, SET_DEFAULT, 0, NULL, NULL);
390}
391
392/* ======================================================================
393 * isochronous USB helpers
394 */
395
396static void
397fill_isoc_urb(struct urb *urb, struct usb_device *dev,
398 unsigned int pipe, void *buf, int num_packets,
399 int packet_size, usb_complete_t complete,
400 void *context)
401{
402 int k;
403
404 spin_lock_init(&urb->lock);
405 urb->dev=dev;
406 urb->pipe=pipe;
407 urb->transfer_buffer=buf;
408 urb->number_of_packets = num_packets;
409 urb->transfer_buffer_length=num_packets*packet_size;
410 urb->actual_length = 0;
411 urb->complete=complete;
412 urb->context=context;
413 urb->transfer_flags=URB_ISO_ASAP;
414 for (k = 0; k < num_packets; k++) {
415 urb->iso_frame_desc[k].offset = packet_size * k;
416 urb->iso_frame_desc[k].length = packet_size;
417 urb->iso_frame_desc[k].actual_length = 0;
418 }
419}
420
421int
422st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
423 unsigned int pipe, int num_packets,
424 int packet_size, int buf_size,
425 usb_complete_t complete, void *context)
426{
427 int j, retval;
428 unsigned char *buf;
429
430 for (j = 0; j < 2; j++) {
431 retval = -ENOMEM;
432 urb[j] = usb_alloc_urb(num_packets, GFP_KERNEL);
433 if (!urb[j])
434 goto err;
435
436 // Allocate memory for 2000bytes/sec (16Kb/s)
437 buf = kmalloc(buf_size, GFP_KERNEL);
438 if (!buf)
439 goto err;
440
441 // Fill the isochronous URB
442 fill_isoc_urb(urb[j], dev, pipe, buf,
443 num_packets, packet_size, complete,
444 context);
445 }
446 return 0;
447
448 err:
449 for (j = 0; j < 2; j++) {
450 if (urb[j]) {
451 if (urb[j]->transfer_buffer)
452 kfree(urb[j]->transfer_buffer);
453 usb_free_urb(urb[j]);
454 }
455 }
456 return retval;
457}
458
459void st5481_release_isocpipes(struct urb* urb[2])
460{
461 int j;
462
463 for (j = 0; j < 2; j++) {
464 usb_unlink_urb(urb[j]);
465 if (urb[j]->transfer_buffer)
466 kfree(urb[j]->transfer_buffer);
467 usb_free_urb(urb[j]);
468 }
469}
470
471/*
472 * Decode frames received on the B/D channel.
473 * Note that this function will be called continously
474 * with 64Kbit/s / 16Kbit/s of data and hence it will be
475 * called 50 times per second with 20 ISOC descriptors.
476 * Called at interrupt.
477 */
478static void usb_in_complete(struct urb *urb, struct pt_regs *regs)
479{
480 struct st5481_in *in = urb->context;
481 unsigned char *ptr;
482 struct sk_buff *skb;
483 int len, count, status;
484
485 if (unlikely(urb->status < 0)) {
486 if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
487 WARN("urb status %d",urb->status);
488 } else {
489 DBG(1,"urb killed");
490 return; // Give up
491 }
492 }
493
494 DBG_ISO_PACKET(0x80,urb);
495
496 len = st5481_isoc_flatten(urb);
497 ptr = urb->transfer_buffer;
498 while (len > 0) {
499 if (in->mode == L1_MODE_TRANS) {
500 memcpy(in->rcvbuf, ptr, len);
501 status = len;
502 len = 0;
503 } else {
504 status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count,
505 in->rcvbuf, in->bufsize);
506 ptr += count;
507 len -= count;
508 }
509
510 if (status > 0) {
511 // Good frame received
512 DBG(4,"count=%d",status);
513 DBG_PACKET(0x400, in->rcvbuf, status);
514 if (!(skb = dev_alloc_skb(status))) {
515 WARN("receive out of memory\n");
516 break;
517 }
518 memcpy(skb_put(skb, status), in->rcvbuf, status);
519 in->hisax_if->l1l2(in->hisax_if, PH_DATA | INDICATION, skb);
520 } else if (status == -HDLC_CRC_ERROR) {
521 INFO("CRC error");
522 } else if (status == -HDLC_FRAMING_ERROR) {
523 INFO("framing error");
524 } else if (status == -HDLC_LENGTH_ERROR) {
525 INFO("length error");
526 }
527 }
528
529 // Prepare URB for next transfer
530 urb->dev = in->adapter->usb_dev;
531 urb->actual_length = 0;
532
533 SUBMIT_URB(urb, GFP_ATOMIC);
534}
535
536int st5481_setup_in(struct st5481_in *in)
537{
538 struct usb_device *dev = in->adapter->usb_dev;
539 int retval;
540
541 DBG(4,"");
542
543 in->rcvbuf = kmalloc(in->bufsize, GFP_KERNEL);
544 retval = -ENOMEM;
545 if (!in->rcvbuf)
546 goto err;
547
548 retval = st5481_setup_isocpipes(in->urb, dev,
549 usb_rcvisocpipe(dev, in->ep),
550 in->num_packets, in->packet_size,
551 in->num_packets * in->packet_size,
552 usb_in_complete, in);
553 if (retval)
554 goto err_free;
555 return 0;
556
557 err_free:
558 kfree(in->rcvbuf);
559 err:
560 return retval;
561}
562
563void st5481_release_in(struct st5481_in *in)
564{
565 DBG(2,"");
566
567 st5481_release_isocpipes(in->urb);
568}
569
570/*
571 * Make the transfer_buffer contiguous by
572 * copying from the iso descriptors if necessary.
573 */
574int st5481_isoc_flatten(struct urb *urb)
575{
576 struct usb_iso_packet_descriptor *pipd,*pend;
577 unsigned char *src,*dst;
578 unsigned int len;
579
580 if (urb->status < 0) {
581 return urb->status;
582 }
583 for (pipd = &urb->iso_frame_desc[0],
584 pend = &urb->iso_frame_desc[urb->number_of_packets],
585 dst = urb->transfer_buffer;
586 pipd < pend;
587 pipd++) {
588
589 if (pipd->status < 0) {
590 return (pipd->status);
591 }
592
593 len = pipd->actual_length;
594 pipd->actual_length = 0;
595 src = urb->transfer_buffer+pipd->offset;
596
597 if (src != dst) {
598 // Need to copy since isoc buffers not full
599 while (len--) {
600 *dst++ = *src++;
601 }
602 } else {
603 // No need to copy, just update destination buffer
604 dst += len;
605 }
606 }
607 // Return size of flattened buffer
608 return (dst - (unsigned char *)urb->transfer_buffer);
609}
610
611static void st5481_start_rcv(void *context)
612{
613 struct st5481_in *in = context;
614 struct st5481_adapter *adapter = in->adapter;
615
616 DBG(4,"");
617
618 in->urb[0]->dev = adapter->usb_dev;
619 SUBMIT_URB(in->urb[0], GFP_KERNEL);
620
621 in->urb[1]->dev = adapter->usb_dev;
622 SUBMIT_URB(in->urb[1], GFP_KERNEL);
623}
624
625void st5481_in_mode(struct st5481_in *in, int mode)
626{
627 if (in->mode == mode)
628 return;
629
630 in->mode = mode;
631
632 usb_unlink_urb(in->urb[0]);
633 usb_unlink_urb(in->urb[1]);
634
635 if (in->mode != L1_MODE_NULL) {
636 if (in->mode != L1_MODE_TRANS)
637 isdnhdlc_rcv_init(&in->hdlc_state,
638 in->mode == L1_MODE_HDLC_56K);
639
640 st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL);
641 st5481_usb_device_ctrl_msg(in->adapter, in->counter,
642 in->packet_size,
643 NULL, NULL);
644 st5481_start_rcv(in);
645 } else {
646 st5481_usb_device_ctrl_msg(in->adapter, in->counter,
647 0, NULL, NULL);
648 }
649}
650
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
new file mode 100644
index 00000000000..082726db398
--- /dev/null
+++ b/drivers/isdn/hisax/tei.c
@@ -0,0 +1,466 @@
1/* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $
2 *
3 * Author Karsten Keil
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
12 *
13 * Thanks to Jan den Ouden
14 * Fritz Elfert
15 *
16 */
17
18#include "hisax.h"
19#include "isdnl2.h"
20#include <linux/init.h>
21#include <linux/random.h>
22
23const char *tei_revision = "$Revision: 2.20.2.3 $";
24
25#define ID_REQUEST 1
26#define ID_ASSIGNED 2
27#define ID_DENIED 3
28#define ID_CHK_REQ 4
29#define ID_CHK_RES 5
30#define ID_REMOVE 6
31#define ID_VERIFY 7
32
33#define TEI_ENTITY_ID 0xf
34
35static struct Fsm teifsm;
36
37void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
38
39enum {
40 ST_TEI_NOP,
41 ST_TEI_IDREQ,
42 ST_TEI_IDVERIFY,
43};
44
45#define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
46
47static char *strTeiState[] =
48{
49 "ST_TEI_NOP",
50 "ST_TEI_IDREQ",
51 "ST_TEI_IDVERIFY",
52};
53
54enum {
55 EV_IDREQ,
56 EV_ASSIGN,
57 EV_DENIED,
58 EV_CHKREQ,
59 EV_REMOVE,
60 EV_VERIFY,
61 EV_T202,
62};
63
64#define TEI_EVENT_COUNT (EV_T202+1)
65
66static char *strTeiEvent[] =
67{
68 "EV_IDREQ",
69 "EV_ASSIGN",
70 "EV_DENIED",
71 "EV_CHKREQ",
72 "EV_REMOVE",
73 "EV_VERIFY",
74 "EV_T202",
75};
76
77unsigned int
78random_ri(void)
79{
80 unsigned int x;
81
82 get_random_bytes(&x, sizeof(x));
83 return (x & 0xffff);
84}
85
86static struct PStack *
87findtei(struct PStack *st, int tei)
88{
89 struct PStack *ptr = *(st->l1.stlistp);
90
91 if (tei == 127)
92 return (NULL);
93
94 while (ptr)
95 if (ptr->l2.tei == tei)
96 return (ptr);
97 else
98 ptr = ptr->next;
99 return (NULL);
100}
101
102static void
103put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
104{
105 struct sk_buff *skb;
106 u_char *bp;
107
108 if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
109 printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
110 return;
111 }
112 bp = skb_put(skb, 3);
113 bp[0] = (TEI_SAPI << 2);
114 bp[1] = (GROUP_TEI << 1) | 0x1;
115 bp[2] = UI;
116 bp = skb_put(skb, 5);
117 bp[0] = TEI_ENTITY_ID;
118 bp[1] = ri >> 8;
119 bp[2] = ri & 0xff;
120 bp[3] = m_id;
121 bp[4] = (tei << 1) | 1;
122 st->l2.l2l1(st, PH_DATA | REQUEST, skb);
123}
124
125static void
126tei_id_request(struct FsmInst *fi, int event, void *arg)
127{
128 struct PStack *st = fi->userdata;
129
130 if (st->l2.tei != -1) {
131 st->ma.tei_m.printdebug(&st->ma.tei_m,
132 "assign request for allready asigned tei %d",
133 st->l2.tei);
134 return;
135 }
136 st->ma.ri = random_ri();
137 if (st->ma.debug)
138 st->ma.tei_m.printdebug(&st->ma.tei_m,
139 "assign request ri %d", st->ma.ri);
140 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
141 FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
142 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
143 st->ma.N202 = 3;
144}
145
146static void
147tei_id_assign(struct FsmInst *fi, int event, void *arg)
148{
149 struct PStack *ost, *st = fi->userdata;
150 struct sk_buff *skb = arg;
151 struct IsdnCardState *cs;
152 int ri, tei;
153
154 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
155 tei = skb->data[4] >> 1;
156 if (st->ma.debug)
157 st->ma.tei_m.printdebug(&st->ma.tei_m,
158 "identity assign ri %d tei %d", ri, tei);
159 if ((ost = findtei(st, tei))) { /* same tei is in use */
160 if (ri != ost->ma.ri) {
161 st->ma.tei_m.printdebug(&st->ma.tei_m,
162 "possible duplicate assignment tei %d", tei);
163 ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
164 }
165 } else if (ri == st->ma.ri) {
166 FsmDelTimer(&st->ma.t202, 1);
167 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
168 st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
169 cs = (struct IsdnCardState *) st->l1.hardware;
170 cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
171 }
172}
173
174static void
175tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
176{
177 struct PStack *ost, *st = fi->userdata;
178 struct sk_buff *skb = arg;
179 int tei, ri;
180
181 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
182 tei = skb->data[4] >> 1;
183 if (st->ma.debug)
184 st->ma.tei_m.printdebug(&st->ma.tei_m,
185 "foreign identity assign ri %d tei %d", ri, tei);
186 if ((ost = findtei(st, tei))) { /* same tei is in use */
187 if (ri != ost->ma.ri) { /* and it wasn't our request */
188 st->ma.tei_m.printdebug(&st->ma.tei_m,
189 "possible duplicate assignment tei %d", tei);
190 FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
191 }
192 }
193}
194
195static void
196tei_id_denied(struct FsmInst *fi, int event, void *arg)
197{
198 struct PStack *st = fi->userdata;
199 struct sk_buff *skb = arg;
200 int ri, tei;
201
202 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
203 tei = skb->data[4] >> 1;
204 if (st->ma.debug)
205 st->ma.tei_m.printdebug(&st->ma.tei_m,
206 "identity denied ri %d tei %d", ri, tei);
207}
208
209static void
210tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
211{
212 struct PStack *st = fi->userdata;
213 struct sk_buff *skb = arg;
214 int tei;
215
216 tei = skb->data[4] >> 1;
217 if (st->ma.debug)
218 st->ma.tei_m.printdebug(&st->ma.tei_m,
219 "identity check req tei %d", tei);
220 if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
221 FsmDelTimer(&st->ma.t202, 4);
222 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
223 put_tei_msg(st, ID_CHK_RES, random_ri(), st->l2.tei);
224 }
225}
226
227static void
228tei_id_remove(struct FsmInst *fi, int event, void *arg)
229{
230 struct PStack *st = fi->userdata;
231 struct sk_buff *skb = arg;
232 struct IsdnCardState *cs;
233 int tei;
234
235 tei = skb->data[4] >> 1;
236 if (st->ma.debug)
237 st->ma.tei_m.printdebug(&st->ma.tei_m,
238 "identity remove tei %d", tei);
239 if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
240 FsmDelTimer(&st->ma.t202, 5);
241 FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
242 st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
243 cs = (struct IsdnCardState *) st->l1.hardware;
244 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
245 }
246}
247
248static void
249tei_id_verify(struct FsmInst *fi, int event, void *arg)
250{
251 struct PStack *st = fi->userdata;
252
253 if (st->ma.debug)
254 st->ma.tei_m.printdebug(&st->ma.tei_m,
255 "id verify request for tei %d", st->l2.tei);
256 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
257 FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
258 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
259 st->ma.N202 = 2;
260}
261
262static void
263tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
264{
265 struct PStack *st = fi->userdata;
266 struct IsdnCardState *cs;
267
268 if (--st->ma.N202) {
269 st->ma.ri = random_ri();
270 if (st->ma.debug)
271 st->ma.tei_m.printdebug(&st->ma.tei_m,
272 "assign req(%d) ri %d", 4 - st->ma.N202,
273 st->ma.ri);
274 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
275 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
276 } else {
277 st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
278 st->l3.l3l2(st, MDL_ERROR | RESPONSE, NULL);
279 cs = (struct IsdnCardState *) st->l1.hardware;
280 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
281 FsmChangeState(fi, ST_TEI_NOP);
282 }
283}
284
285static void
286tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
287{
288 struct PStack *st = fi->userdata;
289 struct IsdnCardState *cs;
290
291 if (--st->ma.N202) {
292 if (st->ma.debug)
293 st->ma.tei_m.printdebug(&st->ma.tei_m,
294 "id verify req(%d) for tei %d",
295 3 - st->ma.N202, st->l2.tei);
296 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
297 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
298 } else {
299 st->ma.tei_m.printdebug(&st->ma.tei_m,
300 "verify req for tei %d failed", st->l2.tei);
301 st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
302 cs = (struct IsdnCardState *) st->l1.hardware;
303 cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
304 FsmChangeState(fi, ST_TEI_NOP);
305 }
306}
307
308static void
309tei_l1l2(struct PStack *st, int pr, void *arg)
310{
311 struct sk_buff *skb = arg;
312 int mt;
313
314 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
315 dev_kfree_skb(skb);
316 return;
317 }
318
319 if (pr == (PH_DATA | INDICATION)) {
320 if (skb->len < 3) {
321 st->ma.tei_m.printdebug(&st->ma.tei_m,
322 "short mgr frame %ld/3", skb->len);
323 } else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
324 (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
325 st->ma.tei_m.printdebug(&st->ma.tei_m,
326 "wrong mgr sapi/tei %x/%x",
327 skb->data[0], skb->data[1]);
328 } else if ((skb->data[2] & 0xef) != UI) {
329 st->ma.tei_m.printdebug(&st->ma.tei_m,
330 "mgr frame is not ui %x", skb->data[2]);
331 } else {
332 skb_pull(skb, 3);
333 if (skb->len < 5) {
334 st->ma.tei_m.printdebug(&st->ma.tei_m,
335 "short mgr frame %ld/5", skb->len);
336 } else if (skb->data[0] != TEI_ENTITY_ID) {
337 /* wrong management entity identifier, ignore */
338 st->ma.tei_m.printdebug(&st->ma.tei_m,
339 "tei handler wrong entity id %x",
340 skb->data[0]);
341 } else {
342 mt = skb->data[3];
343 if (mt == ID_ASSIGNED)
344 FsmEvent(&st->ma.tei_m, EV_ASSIGN, skb);
345 else if (mt == ID_DENIED)
346 FsmEvent(&st->ma.tei_m, EV_DENIED, skb);
347 else if (mt == ID_CHK_REQ)
348 FsmEvent(&st->ma.tei_m, EV_CHKREQ, skb);
349 else if (mt == ID_REMOVE)
350 FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
351 else {
352 st->ma.tei_m.printdebug(&st->ma.tei_m,
353 "tei handler wrong mt %x\n", mt);
354 }
355 }
356 }
357 } else {
358 st->ma.tei_m.printdebug(&st->ma.tei_m,
359 "tei handler wrong pr %x\n", pr);
360 }
361 dev_kfree_skb(skb);
362}
363
364static void
365tei_l2tei(struct PStack *st, int pr, void *arg)
366{
367 struct IsdnCardState *cs;
368
369 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
370 if (pr == (MDL_ASSIGN | INDICATION)) {
371 if (st->ma.debug)
372 st->ma.tei_m.printdebug(&st->ma.tei_m,
373 "fixed assign tei %d", st->l2.tei);
374 st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
375 cs = (struct IsdnCardState *) st->l1.hardware;
376 cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
377 }
378 return;
379 }
380 switch (pr) {
381 case (MDL_ASSIGN | INDICATION):
382 FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
383 break;
384 case (MDL_ERROR | REQUEST):
385 FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
386 break;
387 default:
388 break;
389 }
390}
391
392static void
393tei_debug(struct FsmInst *fi, char *fmt, ...)
394{
395 va_list args;
396 struct PStack *st = fi->userdata;
397
398 va_start(args, fmt);
399 VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
400 va_end(args);
401}
402
403void
404setstack_tei(struct PStack *st)
405{
406 st->l2.l2tei = tei_l2tei;
407 st->ma.T202 = 2000; /* T202 2000 milliseconds */
408 st->l1.l1tei = tei_l1l2;
409 st->ma.debug = 1;
410 st->ma.tei_m.fsm = &teifsm;
411 st->ma.tei_m.state = ST_TEI_NOP;
412 st->ma.tei_m.debug = 1;
413 st->ma.tei_m.userdata = st;
414 st->ma.tei_m.userint = 0;
415 st->ma.tei_m.printdebug = tei_debug;
416 FsmInitTimer(&st->ma.tei_m, &st->ma.t202);
417}
418
419void
420init_tei(struct IsdnCardState *cs, int protocol)
421{
422}
423
424void
425release_tei(struct IsdnCardState *cs)
426{
427 struct PStack *st = cs->stlist;
428
429 while (st) {
430 FsmDelTimer(&st->ma.t202, 1);
431 st = st->next;
432 }
433}
434
435static struct FsmNode TeiFnList[] __initdata =
436{
437 {ST_TEI_NOP, EV_IDREQ, tei_id_request},
438 {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
439 {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
440 {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
441 {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
442 {ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
443 {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
444 {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
445 {ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
446 {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
447 {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
448};
449
450#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
451
452int __init
453TeiNew(void)
454{
455 teifsm.state_count = TEI_STATE_COUNT;
456 teifsm.event_count = TEI_EVENT_COUNT;
457 teifsm.strEvent = strTeiEvent;
458 teifsm.strState = strTeiState;
459 return FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
460}
461
462void
463TeiFree(void)
464{
465 FsmFree(&teifsm);
466}
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
new file mode 100644
index 00000000000..ef8984c5f1f
--- /dev/null
+++ b/drivers/isdn/hisax/teleint.c
@@ -0,0 +1,339 @@
1/* $Id: teleint.c,v 1.16.2.5 2004/01/19 15:31:50 keil Exp $
2 *
3 * low level stuff for TeleInt isdn cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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
13#include <linux/init.h>
14#include "hisax.h"
15#include "isac.h"
16#include "hfc_2bs0.h"
17#include "isdnl1.h"
18
19extern const char *CardType[];
20
21const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
22
23#define byteout(addr,val) outb(val,addr)
24#define bytein(addr) inb(addr)
25
26static inline u_char
27readreg(unsigned int ale, unsigned int adr, u_char off)
28{
29 register u_char ret;
30 int max_delay = 2000;
31
32 byteout(ale, off);
33 ret = HFC_BUSY & bytein(ale);
34 while (ret && --max_delay)
35 ret = HFC_BUSY & bytein(ale);
36 if (!max_delay) {
37 printk(KERN_WARNING "TeleInt Busy not inactive\n");
38 return (0);
39 }
40 ret = bytein(adr);
41 return (ret);
42}
43
44static inline void
45readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
46{
47 register u_char ret;
48 register int max_delay = 20000;
49 register int i;
50
51 byteout(ale, off);
52 for (i = 0; i<size; i++) {
53 ret = HFC_BUSY & bytein(ale);
54 while (ret && --max_delay)
55 ret = HFC_BUSY & bytein(ale);
56 if (!max_delay) {
57 printk(KERN_WARNING "TeleInt Busy not inactive\n");
58 return;
59 }
60 data[i] = bytein(adr);
61 }
62}
63
64
65static inline void
66writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
67{
68 register u_char ret;
69 int max_delay = 2000;
70
71 byteout(ale, off);
72 ret = HFC_BUSY & bytein(ale);
73 while (ret && --max_delay)
74 ret = HFC_BUSY & bytein(ale);
75 if (!max_delay) {
76 printk(KERN_WARNING "TeleInt Busy not inactive\n");
77 return;
78 }
79 byteout(adr, data);
80}
81
82static inline void
83writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
84{
85 register u_char ret;
86 register int max_delay = 20000;
87 register int i;
88
89 byteout(ale, off);
90 for (i = 0; i<size; i++) {
91 ret = HFC_BUSY & bytein(ale);
92 while (ret && --max_delay)
93 ret = HFC_BUSY & bytein(ale);
94 if (!max_delay) {
95 printk(KERN_WARNING "TeleInt Busy not inactive\n");
96 return;
97 }
98 byteout(adr, data[i]);
99 }
100}
101
102/* Interface functions */
103
104static u_char
105ReadISAC(struct IsdnCardState *cs, u_char offset)
106{
107 cs->hw.hfc.cip = offset;
108 return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset));
109}
110
111static void
112WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
113{
114 cs->hw.hfc.cip = offset;
115 writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value);
116}
117
118static void
119ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
120{
121 cs->hw.hfc.cip = 0;
122 readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
123}
124
125static void
126WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
127{
128 cs->hw.hfc.cip = 0;
129 writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
130}
131
132static u_char
133ReadHFC(struct IsdnCardState *cs, int data, u_char reg)
134{
135 register u_char ret;
136
137 if (data) {
138 cs->hw.hfc.cip = reg;
139 byteout(cs->hw.hfc.addr | 1, reg);
140 ret = bytein(cs->hw.hfc.addr);
141 if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
142 debugl1(cs, "hfc RD %02x %02x", reg, ret);
143 } else
144 ret = bytein(cs->hw.hfc.addr | 1);
145 return (ret);
146}
147
148static void
149WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
150{
151 byteout(cs->hw.hfc.addr | 1, reg);
152 cs->hw.hfc.cip = reg;
153 if (data)
154 byteout(cs->hw.hfc.addr, value);
155 if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
156 debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
157}
158
159static irqreturn_t
160TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
161{
162 struct IsdnCardState *cs = dev_id;
163 u_char val;
164 u_long flags;
165
166 spin_lock_irqsave(&cs->lock, flags);
167 val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
168 Start_ISAC:
169 if (val)
170 isac_interrupt(cs, val);
171 val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
172 if (val) {
173 if (cs->debug & L1_DEB_ISAC)
174 debugl1(cs, "ISAC IntStat after IntRoutine");
175 goto Start_ISAC;
176 }
177 writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
178 writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
179 spin_unlock_irqrestore(&cs->lock, flags);
180 return IRQ_HANDLED;
181}
182
183static void
184TeleInt_Timer(struct IsdnCardState *cs)
185{
186 int stat = 0;
187 u_long flags;
188
189 spin_lock_irqsave(&cs->lock, flags);
190 if (cs->bcs[0].mode) {
191 stat |= 1;
192 main_irq_hfc(&cs->bcs[0]);
193 }
194 if (cs->bcs[1].mode) {
195 stat |= 2;
196 main_irq_hfc(&cs->bcs[1]);
197 }
198 spin_unlock_irqrestore(&cs->lock, flags);
199 stat = HZ/100;
200 if (!stat)
201 stat = 1;
202 cs->hw.hfc.timer.expires = jiffies + stat;
203 add_timer(&cs->hw.hfc.timer);
204}
205
206void
207release_io_TeleInt(struct IsdnCardState *cs)
208{
209 del_timer(&cs->hw.hfc.timer);
210 releasehfc(cs);
211 if (cs->hw.hfc.addr)
212 release_region(cs->hw.hfc.addr, 2);
213}
214
215static void
216reset_TeleInt(struct IsdnCardState *cs)
217{
218 printk(KERN_INFO "TeleInt: resetting card\n");
219 cs->hw.hfc.cirm |= HFC_RESET;
220 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */
221 mdelay(10);
222 cs->hw.hfc.cirm &= ~HFC_RESET;
223 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */
224 mdelay(10);
225}
226
227static int
228TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
229{
230 u_long flags;
231 int delay;
232
233 switch (mt) {
234 case CARD_RESET:
235 spin_lock_irqsave(&cs->lock, flags);
236 reset_TeleInt(cs);
237 spin_unlock_irqrestore(&cs->lock, flags);
238 return(0);
239 case CARD_RELEASE:
240 release_io_TeleInt(cs);
241 return(0);
242 case CARD_INIT:
243 spin_lock_irqsave(&cs->lock, flags);
244 reset_TeleInt(cs);
245 inithfc(cs);
246 clear_pending_isac_ints(cs);
247 initisac(cs);
248 /* Reenable all IRQ */
249 cs->writeisac(cs, ISAC_MASK, 0);
250 cs->writeisac(cs, ISAC_CMDR, 0x41);
251 spin_unlock_irqrestore(&cs->lock, flags);
252 delay = HZ/100;
253 if (!delay)
254 delay = 1;
255 cs->hw.hfc.timer.expires = jiffies + delay;
256 add_timer(&cs->hw.hfc.timer);
257 return(0);
258 case CARD_TEST:
259 return(0);
260 }
261 return(0);
262}
263
264int __init
265setup_TeleInt(struct IsdnCard *card)
266{
267 struct IsdnCardState *cs = card->cs;
268 char tmp[64];
269
270 strcpy(tmp, TeleInt_revision);
271 printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
272 if (cs->typ != ISDN_CTYPE_TELEINT)
273 return (0);
274
275 cs->hw.hfc.addr = card->para[1] & 0x3fe;
276 cs->irq = card->para[0];
277 cs->hw.hfc.cirm = HFC_CIRM;
278 cs->hw.hfc.isac_spcr = 0x00;
279 cs->hw.hfc.cip = 0;
280 cs->hw.hfc.ctmt = HFC_CTMT | HFC_CLTIMER;
281 cs->bcs[0].hw.hfc.send = NULL;
282 cs->bcs[1].hw.hfc.send = NULL;
283 cs->hw.hfc.fifosize = 7 * 1024 + 512;
284 cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
285 cs->hw.hfc.timer.data = (long) cs;
286 init_timer(&cs->hw.hfc.timer);
287 if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
288 printk(KERN_WARNING
289 "HiSax: %s config port %x-%x already in use\n",
290 CardType[card->typ],
291 cs->hw.hfc.addr,
292 cs->hw.hfc.addr + 2);
293 return (0);
294 }
295 /* HW IO = IO */
296 byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
297 byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
298 switch (cs->irq) {
299 case 3:
300 cs->hw.hfc.cirm |= HFC_INTA;
301 break;
302 case 4:
303 cs->hw.hfc.cirm |= HFC_INTB;
304 break;
305 case 5:
306 cs->hw.hfc.cirm |= HFC_INTC;
307 break;
308 case 7:
309 cs->hw.hfc.cirm |= HFC_INTD;
310 break;
311 case 10:
312 cs->hw.hfc.cirm |= HFC_INTE;
313 break;
314 case 11:
315 cs->hw.hfc.cirm |= HFC_INTF;
316 break;
317 default:
318 printk(KERN_WARNING "TeleInt: wrong IRQ\n");
319 release_io_TeleInt(cs);
320 return (0);
321 }
322 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
323 byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
324
325 printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
326 cs->hw.hfc.addr, cs->irq);
327
328 setup_isac(cs);
329 cs->readisac = &ReadISAC;
330 cs->writeisac = &WriteISAC;
331 cs->readisacfifo = &ReadISACfifo;
332 cs->writeisacfifo = &WriteISACfifo;
333 cs->BC_Read_Reg = &ReadHFC;
334 cs->BC_Write_Reg = &WriteHFC;
335 cs->cardmsg = &TeleInt_card_msg;
336 cs->irq_func = &TeleInt_interrupt;
337 ISACVersion(cs, "TeleInt:");
338 return (1);
339}
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
new file mode 100644
index 00000000000..5ec5ec3e1ea
--- /dev/null
+++ b/drivers/isdn/hisax/teles0.c
@@ -0,0 +1,367 @@
1/* $Id: teles0.c,v 2.15.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for Teles Memory IO isdn cards
4 *
5 * Author Karsten Keil
6 * based on the teles driver from Jan den Ouden
7 * Copyright by Karsten Keil <keil@isdn4linux.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 * Thanks to Jan den Ouden
13 * Fritz Elfert
14 * Beat Doebeli
15 *
16 */
17
18#include <linux/init.h>
19#include "hisax.h"
20#include "isdnl1.h"
21#include "isac.h"
22#include "hscx.h"
23
24extern const char *CardType[];
25
26const char *teles0_revision = "$Revision: 2.15.2.4 $";
27
28#define TELES_IOMEM_SIZE 0x400
29#define byteout(addr,val) outb(val,addr)
30#define bytein(addr) inb(addr)
31
32static inline u_char
33readisac(void __iomem *adr, u_char off)
34{
35 return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off);
36}
37
38static inline void
39writeisac(void __iomem *adr, u_char off, u_char data)
40{
41 writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
42}
43
44
45static inline u_char
46readhscx(void __iomem *adr, int hscx, u_char off)
47{
48 return readb(adr + (hscx ? 0x1c0 : 0x180) +
49 ((off & 1) ? 0x1ff : 0) + off);
50}
51
52static inline void
53writehscx(void __iomem *adr, int hscx, u_char off, u_char data)
54{
55 writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
56 ((off & 1) ? 0x1ff : 0) + off); mb();
57}
58
59static inline void
60read_fifo_isac(void __iomem *adr, u_char * data, int size)
61{
62 register int i;
63 register u_char __iomem *ad = adr + 0x100;
64 for (i = 0; i < size; i++)
65 data[i] = readb(ad);
66}
67
68static inline void
69write_fifo_isac(void __iomem *adr, u_char * data, int size)
70{
71 register int i;
72 register u_char __iomem *ad = adr + 0x100;
73 for (i = 0; i < size; i++) {
74 writeb(data[i], ad); mb();
75 }
76}
77
78static inline void
79read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
80{
81 register int i;
82 register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180);
83 for (i = 0; i < size; i++)
84 data[i] = readb(ad);
85}
86
87static inline void
88write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
89{
90 int i;
91 register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180);
92 for (i = 0; i < size; i++) {
93 writeb(data[i], ad); mb();
94 }
95}
96
97/* Interface functions */
98
99static u_char
100ReadISAC(struct IsdnCardState *cs, u_char offset)
101{
102 return (readisac(cs->hw.teles0.membase, offset));
103}
104
105static void
106WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
107{
108 writeisac(cs->hw.teles0.membase, offset, value);
109}
110
111static void
112ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
113{
114 read_fifo_isac(cs->hw.teles0.membase, data, size);
115}
116
117static void
118WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
119{
120 write_fifo_isac(cs->hw.teles0.membase, data, size);
121}
122
123static u_char
124ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
125{
126 return (readhscx(cs->hw.teles0.membase, hscx, offset));
127}
128
129static void
130WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
131{
132 writehscx(cs->hw.teles0.membase, hscx, offset, value);
133}
134
135/*
136 * fast interrupt HSCX stuff goes here
137 */
138
139#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
140#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
141#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
142#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
143
144#include "hscx_irq.c"
145
146static irqreturn_t
147teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
148{
149 struct IsdnCardState *cs = dev_id;
150 u_char val;
151 u_long flags;
152 int count = 0;
153
154 spin_lock_irqsave(&cs->lock, flags);
155 val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
156 Start_HSCX:
157 if (val)
158 hscx_int_main(cs, val);
159 val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
160 Start_ISAC:
161 if (val)
162 isac_interrupt(cs, val);
163 count++;
164 val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
165 if (val && count < 5) {
166 if (cs->debug & L1_DEB_HSCX)
167 debugl1(cs, "HSCX IntStat after IntRoutine");
168 goto Start_HSCX;
169 }
170 val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
171 if (val && count < 5) {
172 if (cs->debug & L1_DEB_ISAC)
173 debugl1(cs, "ISAC IntStat after IntRoutine");
174 goto Start_ISAC;
175 }
176 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
177 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
178 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
179 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
180 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
181 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
182 spin_unlock_irqrestore(&cs->lock, flags);
183 return IRQ_HANDLED;
184}
185
186void
187release_io_teles0(struct IsdnCardState *cs)
188{
189 if (cs->hw.teles0.cfg_reg)
190 release_region(cs->hw.teles0.cfg_reg, 8);
191 iounmap(cs->hw.teles0.membase);
192 release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
193}
194
195static int
196reset_teles0(struct IsdnCardState *cs)
197{
198 u_char cfval;
199
200 if (cs->hw.teles0.cfg_reg) {
201 switch (cs->irq) {
202 case 2:
203 case 9:
204 cfval = 0x00;
205 break;
206 case 3:
207 cfval = 0x02;
208 break;
209 case 4:
210 cfval = 0x04;
211 break;
212 case 5:
213 cfval = 0x06;
214 break;
215 case 10:
216 cfval = 0x08;
217 break;
218 case 11:
219 cfval = 0x0A;
220 break;
221 case 12:
222 cfval = 0x0C;
223 break;
224 case 15:
225 cfval = 0x0E;
226 break;
227 default:
228 return(1);
229 }
230 cfval |= ((cs->hw.teles0.phymem >> 9) & 0xF0);
231 byteout(cs->hw.teles0.cfg_reg + 4, cfval);
232 HZDELAY(HZ / 10 + 1);
233 byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
234 HZDELAY(HZ / 10 + 1);
235 }
236 writeb(0, cs->hw.teles0.membase + 0x80); mb();
237 HZDELAY(HZ / 5 + 1);
238 writeb(1, cs->hw.teles0.membase + 0x80); mb();
239 HZDELAY(HZ / 5 + 1);
240 return(0);
241}
242
243static int
244Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
245{
246 u_long flags;
247
248 switch (mt) {
249 case CARD_RESET:
250 spin_lock_irqsave(&cs->lock, flags);
251 reset_teles0(cs);
252 spin_unlock_irqrestore(&cs->lock, flags);
253 return(0);
254 case CARD_RELEASE:
255 release_io_teles0(cs);
256 return(0);
257 case CARD_INIT:
258 spin_lock_irqsave(&cs->lock, flags);
259 inithscxisac(cs, 3);
260 spin_unlock_irqrestore(&cs->lock, flags);
261 return(0);
262 case CARD_TEST:
263 return(0);
264 }
265 return(0);
266}
267
268int __init
269setup_teles0(struct IsdnCard *card)
270{
271 u_char val;
272 struct IsdnCardState *cs = card->cs;
273 char tmp[64];
274
275 strcpy(tmp, teles0_revision);
276 printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
277 if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0))
278 return (0);
279
280 if (cs->typ == ISDN_CTYPE_16_0)
281 cs->hw.teles0.cfg_reg = card->para[2];
282 else /* 8.0 */
283 cs->hw.teles0.cfg_reg = 0;
284
285 if (card->para[1] < 0x10000) {
286 card->para[1] <<= 4;
287 printk(KERN_INFO
288 "Teles0: membase configured DOSish, assuming 0x%lx\n",
289 (unsigned long) card->para[1]);
290 }
291 cs->irq = card->para[0];
292 if (cs->hw.teles0.cfg_reg) {
293 if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) {
294 printk(KERN_WARNING
295 "HiSax: %s config port %x-%x already in use\n",
296 CardType[card->typ],
297 cs->hw.teles0.cfg_reg,
298 cs->hw.teles0.cfg_reg + 8);
299 return (0);
300 }
301 }
302 if (cs->hw.teles0.cfg_reg) {
303 if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
304 printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
305 cs->hw.teles0.cfg_reg + 0, val);
306 release_region(cs->hw.teles0.cfg_reg, 8);
307 return (0);
308 }
309 if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
310 printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
311 cs->hw.teles0.cfg_reg + 1, val);
312 release_region(cs->hw.teles0.cfg_reg, 8);
313 return (0);
314 }
315 val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB
316 * 0x1f=with AB
317 * 0x1c 16.3 ???
318 */
319 if (val != 0x1e && val != 0x1f) {
320 printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
321 cs->hw.teles0.cfg_reg + 2, val);
322 release_region(cs->hw.teles0.cfg_reg, 8);
323 return (0);
324 }
325 }
326 /* 16.0 and 8.0 designed for IOM1 */
327 test_and_set_bit(HW_IOM1, &cs->HW_Flags);
328 cs->hw.teles0.phymem = card->para[1];
329 if (!request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem")) {
330 printk(KERN_WARNING
331 "HiSax: %s memory region %lx-%lx already in use\n",
332 CardType[card->typ],
333 cs->hw.teles0.phymem,
334 cs->hw.teles0.phymem + TELES_IOMEM_SIZE);
335 if (cs->hw.teles0.cfg_reg)
336 release_region(cs->hw.teles0.cfg_reg, 8);
337 return (0);
338 }
339 cs->hw.teles0.membase = ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
340 printk(KERN_INFO
341 "HiSax: %s config irq:%d mem:%p cfg:0x%X\n",
342 CardType[cs->typ], cs->irq,
343 cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
344 if (reset_teles0(cs)) {
345 printk(KERN_WARNING "Teles0: wrong IRQ\n");
346 release_io_teles0(cs);
347 return (0);
348 }
349 setup_isac(cs);
350 cs->readisac = &ReadISAC;
351 cs->writeisac = &WriteISAC;
352 cs->readisacfifo = &ReadISACfifo;
353 cs->writeisacfifo = &WriteISACfifo;
354 cs->BC_Read_Reg = &ReadHSCX;
355 cs->BC_Write_Reg = &WriteHSCX;
356 cs->BC_Send_Data = &hscx_fill_fifo;
357 cs->cardmsg = &Teles_card_msg;
358 cs->irq_func = &teles0_interrupt;
359 ISACVersion(cs, "Teles0:");
360 if (HscxVersion(cs, "Teles0:")) {
361 printk(KERN_WARNING
362 "Teles0: wrong HSCX versions check IO/MEM addresses\n");
363 release_io_teles0(cs);
364 return (0);
365 }
366 return (1);
367}
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
new file mode 100644
index 00000000000..c5b1f65f727
--- /dev/null
+++ b/drivers/isdn/hisax/teles3.c
@@ -0,0 +1,499 @@
1/* $Id: teles3.c,v 2.19.2.4 2004/01/13 23:48:39 keil Exp $
2 *
3 * low level stuff for Teles 16.3 & PNP isdn cards
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
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 * Thanks to Jan den Ouden
12 * Fritz Elfert
13 * Beat Doebeli
14 *
15 */
16#include <linux/init.h>
17#include <linux/isapnp.h>
18#include "hisax.h"
19#include "isac.h"
20#include "hscx.h"
21#include "isdnl1.h"
22
23extern const char *CardType[];
24const char *teles3_revision = "$Revision: 2.19.2.4 $";
25
26#define byteout(addr,val) outb(val,addr)
27#define bytein(addr) inb(addr)
28
29static inline u_char
30readreg(unsigned int adr, u_char off)
31{
32 return (bytein(adr + off));
33}
34
35static inline void
36writereg(unsigned int adr, u_char off, u_char data)
37{
38 byteout(adr + off, data);
39}
40
41
42static inline void
43read_fifo(unsigned int adr, u_char * data, int size)
44{
45 insb(adr, data, size);
46}
47
48static void
49write_fifo(unsigned int adr, u_char * data, int size)
50{
51 outsb(adr, data, size);
52}
53
54/* Interface functions */
55
56static u_char
57ReadISAC(struct IsdnCardState *cs, u_char offset)
58{
59 return (readreg(cs->hw.teles3.isac, offset));
60}
61
62static void
63WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
64{
65 writereg(cs->hw.teles3.isac, offset, value);
66}
67
68static void
69ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
70{
71 read_fifo(cs->hw.teles3.isacfifo, data, size);
72}
73
74static void
75WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
76{
77 write_fifo(cs->hw.teles3.isacfifo, data, size);
78}
79
80static u_char
81ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
82{
83 return (readreg(cs->hw.teles3.hscx[hscx], offset));
84}
85
86static void
87WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
88{
89 writereg(cs->hw.teles3.hscx[hscx], offset, value);
90}
91
92/*
93 * fast interrupt HSCX stuff goes here
94 */
95
96#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.hscx[nr], reg)
97#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.hscx[nr], reg, data)
98#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt)
99#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt)
100
101#include "hscx_irq.c"
102
103static irqreturn_t
104teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
105{
106#define MAXCOUNT 5
107 struct IsdnCardState *cs = dev_id;
108 u_char val;
109 u_long flags;
110 int count = 0;
111
112 spin_lock_irqsave(&cs->lock, flags);
113 val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
114 Start_HSCX:
115 if (val)
116 hscx_int_main(cs, val);
117 val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
118 Start_ISAC:
119 if (val)
120 isac_interrupt(cs, val);
121 count++;
122 val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
123 if (val && count < MAXCOUNT) {
124 if (cs->debug & L1_DEB_HSCX)
125 debugl1(cs, "HSCX IntStat after IntRoutine");
126 goto Start_HSCX;
127 }
128 val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
129 if (val && count < MAXCOUNT) {
130 if (cs->debug & L1_DEB_ISAC)
131 debugl1(cs, "ISAC IntStat after IntRoutine");
132 goto Start_ISAC;
133 }
134 if (count >= MAXCOUNT)
135 printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count);
136 writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
137 writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
138 writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
139 writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
140 writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
141 writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
142 spin_unlock_irqrestore(&cs->lock, flags);
143 return IRQ_HANDLED;
144}
145
146inline static void
147release_ioregs(struct IsdnCardState *cs, int mask)
148{
149 if (mask & 1)
150 release_region(cs->hw.teles3.isac + 32, 32);
151 if (mask & 2)
152 release_region(cs->hw.teles3.hscx[0] + 32, 32);
153 if (mask & 4)
154 release_region(cs->hw.teles3.hscx[1] + 32, 32);
155}
156
157void
158release_io_teles3(struct IsdnCardState *cs)
159{
160 if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
161 release_region(cs->hw.teles3.hscx[1], 96);
162 } else {
163 if (cs->hw.teles3.cfg_reg) {
164 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
165 release_region(cs->hw.teles3.cfg_reg, 1);
166 } else {
167 release_region(cs->hw.teles3.cfg_reg, 8);
168 }
169 }
170 release_ioregs(cs, 0x7);
171 }
172}
173
174static int
175reset_teles3(struct IsdnCardState *cs)
176{
177 u_char irqcfg;
178
179 if (cs->typ != ISDN_CTYPE_TELESPCMCIA) {
180 if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
181 switch (cs->irq) {
182 case 2:
183 case 9:
184 irqcfg = 0x00;
185 break;
186 case 3:
187 irqcfg = 0x02;
188 break;
189 case 4:
190 irqcfg = 0x04;
191 break;
192 case 5:
193 irqcfg = 0x06;
194 break;
195 case 10:
196 irqcfg = 0x08;
197 break;
198 case 11:
199 irqcfg = 0x0A;
200 break;
201 case 12:
202 irqcfg = 0x0C;
203 break;
204 case 15:
205 irqcfg = 0x0E;
206 break;
207 default:
208 return(1);
209 }
210 byteout(cs->hw.teles3.cfg_reg + 4, irqcfg);
211 HZDELAY(HZ / 10 + 1);
212 byteout(cs->hw.teles3.cfg_reg + 4, irqcfg | 1);
213 HZDELAY(HZ / 10 + 1);
214 } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
215 byteout(cs->hw.teles3.cfg_reg, 0xff);
216 HZDELAY(2);
217 byteout(cs->hw.teles3.cfg_reg, 0x00);
218 HZDELAY(2);
219 } else {
220 /* Reset off for 16.3 PnP , thanks to Georg Acher */
221 byteout(cs->hw.teles3.isac + 0x3c, 0);
222 HZDELAY(2);
223 byteout(cs->hw.teles3.isac + 0x3c, 1);
224 HZDELAY(2);
225 }
226 }
227 return(0);
228}
229
230static int
231Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
232{
233 u_long flags;
234
235 switch (mt) {
236 case CARD_RESET:
237 spin_lock_irqsave(&cs->lock, flags);
238 reset_teles3(cs);
239 spin_unlock_irqrestore(&cs->lock, flags);
240 return(0);
241 case CARD_RELEASE:
242 release_io_teles3(cs);
243 return(0);
244 case CARD_INIT:
245 spin_lock_irqsave(&cs->lock, flags);
246 inithscxisac(cs, 3);
247 spin_unlock_irqrestore(&cs->lock, flags);
248 return(0);
249 case CARD_TEST:
250 return(0);
251 }
252 return(0);
253}
254
255#ifdef __ISAPNP__
256
257static struct isapnp_device_id teles_ids[] __devinitdata = {
258 { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
259 ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
260 (unsigned long) "Teles 16.3 PnP" },
261 { ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
262 ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
263 (unsigned long) "Creatix 16.3 PnP" },
264 { ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
265 ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
266 (unsigned long) "Compaq ISDN S0" },
267 { 0, }
268};
269
270static struct isapnp_device_id *ipid __devinitdata = &teles_ids[0];
271static struct pnp_card *pnp_c __devinitdata = NULL;
272#endif
273
274int __devinit
275setup_teles3(struct IsdnCard *card)
276{
277 u_char val;
278 struct IsdnCardState *cs = card->cs;
279 char tmp[64];
280
281 strcpy(tmp, teles3_revision);
282 printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
283 if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
284 && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
285 return (0);
286
287#ifdef __ISAPNP__
288 if (!card->para[1] && isapnp_present()) {
289 struct pnp_dev *pnp_d;
290 while(ipid->card_vendor) {
291 if ((pnp_c = pnp_find_card(ipid->card_vendor,
292 ipid->card_device, pnp_c))) {
293 pnp_d = NULL;
294 if ((pnp_d = pnp_find_dev(pnp_c,
295 ipid->vendor, ipid->function, pnp_d))) {
296 int err;
297
298 printk(KERN_INFO "HiSax: %s detected\n",
299 (char *)ipid->driver_data);
300 pnp_disable_dev(pnp_d);
301 err = pnp_activate_dev(pnp_d);
302 if (err<0) {
303 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
304 __FUNCTION__, err);
305 return(0);
306 }
307 card->para[3] = pnp_port_start(pnp_d, 2);
308 card->para[2] = pnp_port_start(pnp_d, 1);
309 card->para[1] = pnp_port_start(pnp_d, 0);
310 card->para[0] = pnp_irq(pnp_d, 0);
311 if (!card->para[0] || !card->para[1] || !card->para[2]) {
312 printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
313 card->para[0], card->para[1], card->para[2]);
314 pnp_disable_dev(pnp_d);
315 return(0);
316 }
317 break;
318 } else {
319 printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
320 }
321 }
322 ipid++;
323 pnp_c = NULL;
324 }
325 if (!ipid->card_vendor) {
326 printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
327 return(0);
328 }
329 }
330#endif
331 if (cs->typ == ISDN_CTYPE_16_3) {
332 cs->hw.teles3.cfg_reg = card->para[1];
333 switch (cs->hw.teles3.cfg_reg) {
334 case 0x180:
335 case 0x280:
336 case 0x380:
337 cs->hw.teles3.cfg_reg |= 0xc00;
338 break;
339 }
340 cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
341 cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
342 cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
343 } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
344 cs->hw.teles3.cfg_reg = 0;
345 cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
346 cs->hw.teles3.hscx[1] = card->para[1];
347 cs->hw.teles3.isac = card->para[1] + 0x20;
348 } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
349 cs->hw.teles3.cfg_reg = card->para[3];
350 cs->hw.teles3.isac = card->para[2] - 32;
351 cs->hw.teles3.hscx[0] = card->para[1] - 32;
352 cs->hw.teles3.hscx[1] = card->para[1];
353 } else { /* PNP */
354 cs->hw.teles3.cfg_reg = 0;
355 cs->hw.teles3.isac = card->para[1] - 32;
356 cs->hw.teles3.hscx[0] = card->para[2] - 32;
357 cs->hw.teles3.hscx[1] = card->para[2];
358 }
359 cs->irq = card->para[0];
360 cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
361 cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
362 cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
363 if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
364 if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) {
365 printk(KERN_WARNING
366 "HiSax: %s ports %x-%x already in use\n",
367 CardType[cs->typ],
368 cs->hw.teles3.hscx[1],
369 cs->hw.teles3.hscx[1] + 96);
370 return (0);
371 }
372 } else {
373 if (cs->hw.teles3.cfg_reg) {
374 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
375 if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) {
376 printk(KERN_WARNING
377 "HiSax: %s config port %x already in use\n",
378 CardType[card->typ],
379 cs->hw.teles3.cfg_reg);
380 return (0);
381 }
382 } else {
383 if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) {
384 printk(KERN_WARNING
385 "HiSax: %s config port %x-%x already in use\n",
386 CardType[card->typ],
387 cs->hw.teles3.cfg_reg,
388 cs->hw.teles3.cfg_reg + 8);
389 return (0);
390 }
391 }
392 }
393 if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) {
394 printk(KERN_WARNING
395 "HiSax: %s isac ports %x-%x already in use\n",
396 CardType[cs->typ],
397 cs->hw.teles3.isac + 32,
398 cs->hw.teles3.isac + 64);
399 if (cs->hw.teles3.cfg_reg) {
400 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
401 release_region(cs->hw.teles3.cfg_reg, 1);
402 } else {
403 release_region(cs->hw.teles3.cfg_reg, 8);
404 }
405 }
406 return (0);
407 }
408 if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) {
409 printk(KERN_WARNING
410 "HiSax: %s hscx A ports %x-%x already in use\n",
411 CardType[cs->typ],
412 cs->hw.teles3.hscx[0] + 32,
413 cs->hw.teles3.hscx[0] + 64);
414 if (cs->hw.teles3.cfg_reg) {
415 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
416 release_region(cs->hw.teles3.cfg_reg, 1);
417 } else {
418 release_region(cs->hw.teles3.cfg_reg, 8);
419 }
420 }
421 release_ioregs(cs, 1);
422 return (0);
423 }
424 if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) {
425 printk(KERN_WARNING
426 "HiSax: %s hscx B ports %x-%x already in use\n",
427 CardType[cs->typ],
428 cs->hw.teles3.hscx[1] + 32,
429 cs->hw.teles3.hscx[1] + 64);
430 if (cs->hw.teles3.cfg_reg) {
431 if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
432 release_region(cs->hw.teles3.cfg_reg, 1);
433 } else {
434 release_region(cs->hw.teles3.cfg_reg, 8);
435 }
436 }
437 release_ioregs(cs, 3);
438 return (0);
439 }
440 }
441 if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
442 if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
443 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
444 cs->hw.teles3.cfg_reg + 0, val);
445 release_io_teles3(cs);
446 return (0);
447 }
448 if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
449 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
450 cs->hw.teles3.cfg_reg + 1, val);
451 release_io_teles3(cs);
452 return (0);
453 }
454 val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
455 * 0x1f=with AB
456 * 0x1c 16.3 ???
457 * 0x39 16.3 1.1
458 * 0x38 16.3 1.3
459 * 0x46 16.3 with AB + Video (Teles-Vision)
460 */
461 if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
462 printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
463 cs->hw.teles3.cfg_reg + 2, val);
464 release_io_teles3(cs);
465 return (0);
466 }
467 }
468 printk(KERN_INFO
469 "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n",
470 CardType[cs->typ], cs->irq,
471 cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
472 printk(KERN_INFO
473 "HiSax: hscx A:0x%X hscx B:0x%X\n",
474 cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
475
476 setup_isac(cs);
477 if (reset_teles3(cs)) {
478 printk(KERN_WARNING "Teles3: wrong IRQ\n");
479 release_io_teles3(cs);
480 return (0);
481 }
482 cs->readisac = &ReadISAC;
483 cs->writeisac = &WriteISAC;
484 cs->readisacfifo = &ReadISACfifo;
485 cs->writeisacfifo = &WriteISACfifo;
486 cs->BC_Read_Reg = &ReadHSCX;
487 cs->BC_Write_Reg = &WriteHSCX;
488 cs->BC_Send_Data = &hscx_fill_fifo;
489 cs->cardmsg = &Teles_card_msg;
490 cs->irq_func = &teles3_interrupt;
491 ISACVersion(cs, "Teles3:");
492 if (HscxVersion(cs, "Teles3:")) {
493 printk(KERN_WARNING
494 "Teles3: wrong HSCX versions check IO address\n");
495 release_io_teles3(cs);
496 return (0);
497 }
498 return (1);
499}
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
new file mode 100644
index 00000000000..63e8e20c17a
--- /dev/null
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -0,0 +1,513 @@
1/* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */
2/*======================================================================
3
4 A teles S0 PCMCIA client driver
5
6 Based on skeleton by David Hinds, dhinds@allegro.stanford.edu
7 Written by Christof Petig, christof.petig@wtal.de
8
9 Also inspired by ELSA PCMCIA driver
10 by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
11
12 Extentions to new hisax_pcmcia by Karsten Keil
13
14 minor changes to be compatible with kernel 2.4.x
15 by Jan.Schubert@GMX.li
16
17======================================================================*/
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/sched.h>
23#include <linux/ptrace.h>
24#include <linux/slab.h>
25#include <linux/string.h>
26#include <linux/timer.h>
27#include <linux/ioport.h>
28#include <asm/io.h>
29#include <asm/system.h>
30
31#include <pcmcia/version.h>
32#include <pcmcia/cs_types.h>
33#include <pcmcia/cs.h>
34#include <pcmcia/cistpl.h>
35#include <pcmcia/cisreg.h>
36#include <pcmcia/ds.h>
37#include "hisax_cfg.h"
38
39MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards");
40MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de");
41MODULE_LICENSE("GPL");
42
43/*
44 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
45 you do not define PCMCIA_DEBUG at all, all the debug code will be
46 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
47 be present but disabled -- but it can then be enabled for specific
48 modules at load time with a 'pc_debug=#' option to insmod.
49*/
50
51#ifdef PCMCIA_DEBUG
52static int pc_debug = PCMCIA_DEBUG;
53module_param(pc_debug, int, 0);
54#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
55static char *version =
56"teles_cs.c 2.10 2002/07/30 22:23:34 kkeil";
57#else
58#define DEBUG(n, args...)
59#endif
60
61/*====================================================================*/
62
63/* Parameters that can be set with 'insmod' */
64
65static int protocol = 2; /* EURO-ISDN Default */
66module_param(protocol, int, 0);
67
68/*====================================================================*/
69
70/*
71 The event() function is this driver's Card Services event handler.
72 It will be called by Card Services when an appropriate card status
73 event is received. The config() and release() entry points are
74 used to configure or release a socket, in response to card insertion
75 and ejection events. They are invoked from the teles_cs event
76 handler.
77*/
78
79static void teles_cs_config(dev_link_t *link);
80static void teles_cs_release(dev_link_t *link);
81static int teles_cs_event(event_t event, int priority,
82 event_callback_args_t *args);
83
84/*
85 The attach() and detach() entry points are used to create and destroy
86 "instances" of the driver, where each instance represents everything
87 needed to manage one actual PCMCIA card.
88*/
89
90static dev_link_t *teles_attach(void);
91static void teles_detach(dev_link_t *);
92
93/*
94 The dev_info variable is the "key" that is used to match up this
95 device driver with appropriate cards, through the card configuration
96 database.
97*/
98
99static dev_info_t dev_info = "teles_cs";
100
101/*
102 A linked list of "instances" of the teles_cs device. Each actual
103 PCMCIA card corresponds to one device instance, and is described
104 by one dev_link_t structure (defined in ds.h).
105
106 You may not want to use a linked list for this -- for example, the
107 memory card driver uses an array of dev_link_t pointers, where minor
108 device numbers are used to derive the corresponding array index.
109*/
110
111static dev_link_t *dev_list = NULL;
112
113/*
114 A dev_link_t structure has fields for most things that are needed
115 to keep track of a socket, but there will usually be some device
116 specific information that also needs to be kept track of. The
117 'priv' pointer in a dev_link_t structure can be used to point to
118 a device-specific private data structure, like this.
119
120 To simplify the data structure handling, we actually include the
121 dev_link_t structure in the device's private data structure.
122
123 A driver needs to provide a dev_node_t structure for each device
124 on a card. In some cases, there is only one device per card (for
125 example, ethernet cards, modems). In other cases, there may be
126 many actual or logical devices (SCSI adapters, memory cards with
127 multiple partitions). The dev_node_t structures need to be kept
128 in a linked list starting at the 'dev' field of a dev_link_t
129 structure. We allocate them in the card's private data structure,
130 because they generally shouldn't be allocated dynamically.
131 In this case, we also provide a flag to indicate if a device is
132 "stopped" due to a power management event, or card ejection. The
133 device IO routines can use a flag like this to throttle IO to a
134 card that is not ready to accept it.
135*/
136
137typedef struct local_info_t {
138 dev_link_t link;
139 dev_node_t node;
140 int busy;
141 int cardnr;
142} local_info_t;
143
144/*======================================================================
145
146 teles_attach() creates an "instance" of the driver, allocatingx
147 local data structures for one device. The device is registered
148 with Card Services.
149
150 The dev_link structure is initialized, but we don't actually
151 configure the card at this point -- we wait until we receive a
152 card insertion event.
153
154======================================================================*/
155
156static dev_link_t *teles_attach(void)
157{
158 client_reg_t client_reg;
159 dev_link_t *link;
160 local_info_t *local;
161 int ret;
162
163 DEBUG(0, "teles_attach()\n");
164
165 /* Allocate space for private device-specific data */
166 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
167 if (!local) return NULL;
168 memset(local, 0, sizeof(local_info_t));
169 local->cardnr = -1;
170 link = &local->link; link->priv = local;
171
172 /* Interrupt setup */
173 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
174 link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID;
175 link->irq.Handler = NULL;
176
177 /*
178 General socket configuration defaults can go here. In this
179 client, we assume very little, and rely on the CIS for almost
180 everything. In most clients, many details (i.e., number, sizes,
181 and attributes of IO windows) are fixed by the nature of the
182 device, and can be hard-wired here.
183 */
184 link->io.NumPorts1 = 96;
185 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
186 link->io.IOAddrLines = 5;
187
188 link->conf.Attributes = CONF_ENABLE_IRQ;
189 link->conf.Vcc = 50;
190 link->conf.IntType = INT_MEMORY_AND_IO;
191
192 /* Register with Card Services */
193 link->next = dev_list;
194 dev_list = link;
195 client_reg.dev_info = &dev_info;
196 client_reg.EventMask =
197 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
198 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
199 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
200 client_reg.event_handler = &teles_cs_event;
201 client_reg.Version = 0x0210;
202 client_reg.event_callback_args.client_data = link;
203 ret = pcmcia_register_client(&link->handle, &client_reg);
204 if (ret != CS_SUCCESS) {
205 cs_error(link->handle, RegisterClient, ret);
206 teles_detach(link);
207 return NULL;
208 }
209
210 return link;
211} /* teles_attach */
212
213/*======================================================================
214
215 This deletes a driver "instance". The device is de-registered
216 with Card Services. If it has been released, all local data
217 structures are freed. Otherwise, the structures will be freed
218 when the device is released.
219
220======================================================================*/
221
222static void teles_detach(dev_link_t *link)
223{
224 dev_link_t **linkp;
225 local_info_t *info = link->priv;
226 int ret;
227
228 DEBUG(0, "teles_detach(0x%p)\n", link);
229
230 /* Locate device structure */
231 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
232 if (*linkp == link) break;
233 if (*linkp == NULL)
234 return;
235
236 if (link->state & DEV_CONFIG)
237 teles_cs_release(link);
238
239 /* Break the link with Card Services */
240 if (link->handle) {
241 ret = pcmcia_deregister_client(link->handle);
242 if (ret != CS_SUCCESS)
243 cs_error(link->handle, DeregisterClient, ret);
244 }
245
246 /* Unlink device structure and free it */
247 *linkp = link->next;
248 kfree(info);
249
250} /* teles_detach */
251
252/*======================================================================
253
254 teles_cs_config() is scheduled to run after a CARD_INSERTION event
255 is received, to configure the PCMCIA socket, and to make the
256 device available to the system.
257
258======================================================================*/
259static int get_tuple(client_handle_t handle, tuple_t *tuple,
260 cisparse_t *parse)
261{
262 int i = pcmcia_get_tuple_data(handle, tuple);
263 if (i != CS_SUCCESS) return i;
264 return pcmcia_parse_tuple(handle, tuple, parse);
265}
266
267static int first_tuple(client_handle_t handle, tuple_t *tuple,
268 cisparse_t *parse)
269{
270 int i = pcmcia_get_first_tuple(handle, tuple);
271 if (i != CS_SUCCESS) return i;
272 return get_tuple(handle, tuple, parse);
273}
274
275static int next_tuple(client_handle_t handle, tuple_t *tuple,
276 cisparse_t *parse)
277{
278 int i = pcmcia_get_next_tuple(handle, tuple);
279 if (i != CS_SUCCESS) return i;
280 return get_tuple(handle, tuple, parse);
281}
282
283static void teles_cs_config(dev_link_t *link)
284{
285 client_handle_t handle;
286 tuple_t tuple;
287 cisparse_t parse;
288 local_info_t *dev;
289 int i, j, last_fn;
290 u_short buf[128];
291 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
292 IsdnCard_t icard;
293
294 DEBUG(0, "teles_config(0x%p)\n", link);
295 handle = link->handle;
296 dev = link->priv;
297
298 /*
299 This reads the card's CONFIG tuple to find its configuration
300 registers.
301 */
302 tuple.DesiredTuple = CISTPL_CONFIG;
303 tuple.TupleData = (cisdata_t *)buf;
304 tuple.TupleDataMax = 255;
305 tuple.TupleOffset = 0;
306 tuple.Attributes = 0;
307 i = first_tuple(handle, &tuple, &parse);
308 if (i != CS_SUCCESS) {
309 last_fn = ParseTuple;
310 goto cs_failed;
311 }
312 link->conf.ConfigBase = parse.config.base;
313 link->conf.Present = parse.config.rmask[0];
314
315 /* Configure card */
316 link->state |= DEV_CONFIG;
317
318 tuple.TupleData = (cisdata_t *)buf;
319 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
320 tuple.Attributes = 0;
321 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
322 i = first_tuple(handle, &tuple, &parse);
323 while (i == CS_SUCCESS) {
324 if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
325 printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
326 link->conf.ConfigIndex = cf->index;
327 link->io.BasePort1 = cf->io.win[0].base;
328 i = pcmcia_request_io(link->handle, &link->io);
329 if (i == CS_SUCCESS) break;
330 } else {
331 printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
332 link->conf.ConfigIndex = cf->index;
333 for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
334 link->io.BasePort1 = j;
335 i = pcmcia_request_io(link->handle, &link->io);
336 if (i == CS_SUCCESS) break;
337 }
338 break;
339 }
340 i = next_tuple(handle, &tuple, &parse);
341 }
342
343 if (i != CS_SUCCESS) {
344 last_fn = RequestIO;
345 goto cs_failed;
346 }
347
348 i = pcmcia_request_irq(link->handle, &link->irq);
349 if (i != CS_SUCCESS) {
350 link->irq.AssignedIRQ = 0;
351 last_fn = RequestIRQ;
352 goto cs_failed;
353 }
354
355 i = pcmcia_request_configuration(link->handle, &link->conf);
356 if (i != CS_SUCCESS) {
357 last_fn = RequestConfiguration;
358 goto cs_failed;
359 }
360
361 /* At this point, the dev_node_t structure(s) should be
362 initialized and arranged in a linked list at link->dev. *//* */
363 sprintf(dev->node.dev_name, "teles");
364 dev->node.major = dev->node.minor = 0x0;
365
366 link->dev = &dev->node;
367
368 /* Finally, report what we've done */
369 printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
370 dev->node.dev_name, link->conf.ConfigIndex,
371 link->conf.Vcc/10, link->conf.Vcc%10);
372 if (link->conf.Vpp1)
373 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
374 if (link->conf.Attributes & CONF_ENABLE_IRQ)
375 printk(", irq %d", link->irq.AssignedIRQ);
376 if (link->io.NumPorts1)
377 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
378 link->io.BasePort1+link->io.NumPorts1-1);
379 if (link->io.NumPorts2)
380 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
381 link->io.BasePort2+link->io.NumPorts2-1);
382 printk("\n");
383
384 link->state &= ~DEV_CONFIG_PENDING;
385
386 icard.para[0] = link->irq.AssignedIRQ;
387 icard.para[1] = link->io.BasePort1;
388 icard.protocol = protocol;
389 icard.typ = ISDN_CTYPE_TELESPCMCIA;
390
391 i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
392 if (i < 0) {
393 printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
394 i, link->io.BasePort1);
395 teles_cs_release(link);
396 } else
397 ((local_info_t*)link->priv)->cardnr = i;
398
399 return;
400cs_failed:
401 cs_error(link->handle, last_fn, i);
402 teles_cs_release(link);
403} /* teles_cs_config */
404
405/*======================================================================
406
407 After a card is removed, teles_cs_release() will unregister the net
408 device, and release the PCMCIA configuration. If the device is
409 still open, this will be postponed until it is closed.
410
411======================================================================*/
412
413static void teles_cs_release(dev_link_t *link)
414{
415 local_info_t *local = link->priv;
416
417 DEBUG(0, "teles_cs_release(0x%p)\n", link);
418
419 if (local) {
420 if (local->cardnr >= 0) {
421 /* no unregister function with hisax */
422 HiSax_closecard(local->cardnr);
423 }
424 }
425 /* Unlink the device chain */
426 link->dev = NULL;
427
428 /* Don't bother checking to see if these succeed or not */
429 if (link->win)
430 pcmcia_release_window(link->win);
431 pcmcia_release_configuration(link->handle);
432 pcmcia_release_io(link->handle, &link->io);
433 pcmcia_release_irq(link->handle, &link->irq);
434 link->state &= ~DEV_CONFIG;
435} /* teles_cs_release */
436
437/*======================================================================
438
439 The card status event handler. Mostly, this schedules other
440 stuff to run after an event is received. A CARD_REMOVAL event
441 also sets some flags to discourage the net drivers from trying
442 to talk to the card any more.
443
444 When a CARD_REMOVAL event is received, we immediately set a flag
445 to block future accesses to this device. All the functions that
446 actually access the device should check this flag to make sure
447 the card is still present.
448
449======================================================================*/
450
451static int teles_cs_event(event_t event, int priority,
452 event_callback_args_t *args)
453{
454 dev_link_t *link = args->client_data;
455 local_info_t *dev = link->priv;
456
457 DEBUG(1, "teles_cs_event(%d)\n", event);
458
459 switch (event) {
460 case CS_EVENT_CARD_REMOVAL:
461 link->state &= ~DEV_PRESENT;
462 if (link->state & DEV_CONFIG) {
463 ((local_info_t*)link->priv)->busy = 1;
464 teles_cs_release(link);
465 }
466 break;
467 case CS_EVENT_CARD_INSERTION:
468 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
469 teles_cs_config(link);
470 break;
471 case CS_EVENT_PM_SUSPEND:
472 link->state |= DEV_SUSPEND;
473 /* Fall through... */
474 case CS_EVENT_RESET_PHYSICAL:
475 /* Mark the device as stopped, to block IO until later */
476 dev->busy = 1;
477 if (link->state & DEV_CONFIG)
478 pcmcia_release_configuration(link->handle);
479 break;
480 case CS_EVENT_PM_RESUME:
481 link->state &= ~DEV_SUSPEND;
482 /* Fall through... */
483 case CS_EVENT_CARD_RESET:
484 if (link->state & DEV_CONFIG)
485 pcmcia_request_configuration(link->handle, &link->conf);
486 dev->busy = 0;
487 break;
488 }
489 return 0;
490} /* teles_cs_event */
491
492static struct pcmcia_driver teles_cs_driver = {
493 .owner = THIS_MODULE,
494 .drv = {
495 .name = "teles_cs",
496 },
497 .attach = teles_attach,
498 .detach = teles_detach,
499};
500
501static int __init init_teles_cs(void)
502{
503 return pcmcia_register_driver(&teles_cs_driver);
504}
505
506static void __exit exit_teles_cs(void)
507{
508 pcmcia_unregister_driver(&teles_cs_driver);
509 BUG_ON(dev_list != NULL);
510}
511
512module_init(init_teles_cs);
513module_exit(exit_teles_cs);
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
new file mode 100644
index 00000000000..0661c6c31ad
--- /dev/null
+++ b/drivers/isdn/hisax/telespci.c
@@ -0,0 +1,359 @@
1/* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $
2 *
3 * low level stuff for Teles PCI isdn cards
4 *
5 * Author Ton van Rosmalen
6 * Karsten Keil
7 * Copyright by Ton van Rosmalen
8 * by Karsten Keil <keil@isdn4linux.de>
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 */
14
15#include <linux/init.h>
16#include <linux/config.h>
17#include "hisax.h"
18#include "isac.h"
19#include "hscx.h"
20#include "isdnl1.h"
21#include <linux/pci.h>
22
23extern const char *CardType[];
24const char *telespci_revision = "$Revision: 2.23.2.3 $";
25
26#define ZORAN_PO_RQ_PEN 0x02000000
27#define ZORAN_PO_WR 0x00800000
28#define ZORAN_PO_GID0 0x00000000
29#define ZORAN_PO_GID1 0x00100000
30#define ZORAN_PO_GREG0 0x00000000
31#define ZORAN_PO_GREG1 0x00010000
32#define ZORAN_PO_DMASK 0xFF
33
34#define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
35#define READ_DATA_ISAC (ZORAN_PO_GID0 | ZORAN_PO_GREG1)
36#define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
37#define WRITE_ADDR_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
38#define READ_DATA_HSCX (ZORAN_PO_GID1 | ZORAN_PO_GREG1)
39#define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
40
41#define ZORAN_WAIT_NOBUSY do { \
42 portdata = readl(adr + 0x200); \
43 } while (portdata & ZORAN_PO_RQ_PEN)
44
45static inline u_char
46readisac(void __iomem *adr, u_char off)
47{
48 register unsigned int portdata;
49
50 ZORAN_WAIT_NOBUSY;
51
52 /* set address for ISAC */
53 writel(WRITE_ADDR_ISAC | off, adr + 0x200);
54 ZORAN_WAIT_NOBUSY;
55
56 /* read data from ISAC */
57 writel(READ_DATA_ISAC, adr + 0x200);
58 ZORAN_WAIT_NOBUSY;
59 return((u_char)(portdata & ZORAN_PO_DMASK));
60}
61
62static inline void
63writeisac(void __iomem *adr, u_char off, u_char data)
64{
65 register unsigned int portdata;
66
67 ZORAN_WAIT_NOBUSY;
68
69 /* set address for ISAC */
70 writel(WRITE_ADDR_ISAC | off, adr + 0x200);
71 ZORAN_WAIT_NOBUSY;
72
73 /* write data to ISAC */
74 writel(WRITE_DATA_ISAC | data, adr + 0x200);
75 ZORAN_WAIT_NOBUSY;
76}
77
78static inline u_char
79readhscx(void __iomem *adr, int hscx, u_char off)
80{
81 register unsigned int portdata;
82
83 ZORAN_WAIT_NOBUSY;
84 /* set address for HSCX */
85 writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
86 ZORAN_WAIT_NOBUSY;
87
88 /* read data from HSCX */
89 writel(READ_DATA_HSCX, adr + 0x200);
90 ZORAN_WAIT_NOBUSY;
91 return ((u_char)(portdata & ZORAN_PO_DMASK));
92}
93
94static inline void
95writehscx(void __iomem *adr, int hscx, u_char off, u_char data)
96{
97 register unsigned int portdata;
98
99 ZORAN_WAIT_NOBUSY;
100 /* set address for HSCX */
101 writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
102 ZORAN_WAIT_NOBUSY;
103
104 /* write data to HSCX */
105 writel(WRITE_DATA_HSCX | data, adr + 0x200);
106 ZORAN_WAIT_NOBUSY;
107}
108
109static inline void
110read_fifo_isac(void __iomem *adr, u_char * data, int size)
111{
112 register unsigned int portdata;
113 register int i;
114
115 ZORAN_WAIT_NOBUSY;
116 /* read data from ISAC */
117 for (i = 0; i < size; i++) {
118 /* set address for ISAC fifo */
119 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
120 ZORAN_WAIT_NOBUSY;
121 writel(READ_DATA_ISAC, adr + 0x200);
122 ZORAN_WAIT_NOBUSY;
123 data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
124 }
125}
126
127static void
128write_fifo_isac(void __iomem *adr, u_char * data, int size)
129{
130 register unsigned int portdata;
131 register int i;
132
133 ZORAN_WAIT_NOBUSY;
134 /* write data to ISAC */
135 for (i = 0; i < size; i++) {
136 /* set address for ISAC fifo */
137 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
138 ZORAN_WAIT_NOBUSY;
139 writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
140 ZORAN_WAIT_NOBUSY;
141 }
142}
143
144static inline void
145read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
146{
147 register unsigned int portdata;
148 register int i;
149
150 ZORAN_WAIT_NOBUSY;
151 /* read data from HSCX */
152 for (i = 0; i < size; i++) {
153 /* set address for HSCX fifo */
154 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
155 ZORAN_WAIT_NOBUSY;
156 writel(READ_DATA_HSCX, adr + 0x200);
157 ZORAN_WAIT_NOBUSY;
158 data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
159 }
160}
161
162static inline void
163write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
164{
165 unsigned int portdata;
166 register int i;
167
168 ZORAN_WAIT_NOBUSY;
169 /* write data to HSCX */
170 for (i = 0; i < size; i++) {
171 /* set address for HSCX fifo */
172 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
173 ZORAN_WAIT_NOBUSY;
174 writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
175 ZORAN_WAIT_NOBUSY;
176 udelay(10);
177 }
178}
179
180/* Interface functions */
181
182static u_char
183ReadISAC(struct IsdnCardState *cs, u_char offset)
184{
185 return (readisac(cs->hw.teles0.membase, offset));
186}
187
188static void
189WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
190{
191 writeisac(cs->hw.teles0.membase, offset, value);
192}
193
194static void
195ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
196{
197 read_fifo_isac(cs->hw.teles0.membase, data, size);
198}
199
200static void
201WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
202{
203 write_fifo_isac(cs->hw.teles0.membase, data, size);
204}
205
206static u_char
207ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
208{
209 return (readhscx(cs->hw.teles0.membase, hscx, offset));
210}
211
212static void
213WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
214{
215 writehscx(cs->hw.teles0.membase, hscx, offset, value);
216}
217
218/*
219 * fast interrupt HSCX stuff goes here
220 */
221
222#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
223#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
224#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
225#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
226
227#include "hscx_irq.c"
228
229static irqreturn_t
230telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
231{
232 struct IsdnCardState *cs = dev_id;
233 u_char hval, ival;
234 u_long flags;
235
236 spin_lock_irqsave(&cs->lock, flags);
237 hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
238 if (hval)
239 hscx_int_main(cs, hval);
240 ival = readisac(cs->hw.teles0.membase, ISAC_ISTA);
241 if ((hval | ival) == 0) {
242 spin_unlock_irqrestore(&cs->lock, flags);
243 return IRQ_NONE;
244 }
245 if (ival)
246 isac_interrupt(cs, ival);
247 /* Clear interrupt register for Zoran PCI controller */
248 writel(0x70000000, cs->hw.teles0.membase + 0x3C);
249
250 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
251 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
252 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
253 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
254 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
255 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
256 spin_unlock_irqrestore(&cs->lock, flags);
257 return IRQ_HANDLED;
258}
259
260void
261release_io_telespci(struct IsdnCardState *cs)
262{
263 iounmap(cs->hw.teles0.membase);
264}
265
266static int
267TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
268{
269 u_long flags;
270
271 switch (mt) {
272 case CARD_RESET:
273 return(0);
274 case CARD_RELEASE:
275 release_io_telespci(cs);
276 return(0);
277 case CARD_INIT:
278 spin_lock_irqsave(&cs->lock, flags);
279 inithscxisac(cs, 3);
280 spin_unlock_irqrestore(&cs->lock, flags);
281 return(0);
282 case CARD_TEST:
283 return(0);
284 }
285 return(0);
286}
287
288static struct pci_dev *dev_tel __initdata = NULL;
289
290int __init
291setup_telespci(struct IsdnCard *card)
292{
293 struct IsdnCardState *cs = card->cs;
294 char tmp[64];
295
296#ifdef __BIG_ENDIAN
297#error "not running on big endian machines now"
298#endif
299 strcpy(tmp, telespci_revision);
300 printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
301 if (cs->typ != ISDN_CTYPE_TELESPCI)
302 return (0);
303#ifdef CONFIG_PCI
304 if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
305 if (pci_enable_device(dev_tel))
306 return(0);
307 cs->irq = dev_tel->irq;
308 if (!cs->irq) {
309 printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
310 return(0);
311 }
312 cs->hw.teles0.membase = ioremap(pci_resource_start(dev_tel, 0),
313 PAGE_SIZE);
314 printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
315 pci_resource_start(dev_tel, 0), dev_tel->irq);
316 } else {
317 printk(KERN_WARNING "TelesPCI: No PCI card found\n");
318 return(0);
319 }
320#else
321 printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
322 printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
323 return (0);
324#endif /* CONFIG_PCI */
325
326 /* Initialize Zoran PCI controller */
327 writel(0x00000000, cs->hw.teles0.membase + 0x28);
328 writel(0x01000000, cs->hw.teles0.membase + 0x28);
329 writel(0x01000000, cs->hw.teles0.membase + 0x28);
330 writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
331 writel(0x70000000, cs->hw.teles0.membase + 0x3C);
332 writel(0x61000000, cs->hw.teles0.membase + 0x40);
333 /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
334
335 printk(KERN_INFO
336 "HiSax: %s config irq:%d mem:%p\n",
337 CardType[cs->typ], cs->irq,
338 cs->hw.teles0.membase);
339
340 setup_isac(cs);
341 cs->readisac = &ReadISAC;
342 cs->writeisac = &WriteISAC;
343 cs->readisacfifo = &ReadISACfifo;
344 cs->writeisacfifo = &WriteISACfifo;
345 cs->BC_Read_Reg = &ReadHSCX;
346 cs->BC_Write_Reg = &WriteHSCX;
347 cs->BC_Send_Data = &hscx_fill_fifo;
348 cs->cardmsg = &TelesPCI_card_msg;
349 cs->irq_func = &telespci_interrupt;
350 cs->irq_flags |= SA_SHIRQ;
351 ISACVersion(cs, "TelesPCI:");
352 if (HscxVersion(cs, "TelesPCI:")) {
353 printk(KERN_WARNING
354 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
355 release_io_telespci(cs);
356 return (0);
357 }
358 return (1);
359}
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
new file mode 100644
index 00000000000..d2b6b8e7298
--- /dev/null
+++ b/drivers/isdn/hisax/w6692.c
@@ -0,0 +1,1096 @@
1/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $
2 *
3 * Winbond W6692 specific routines
4 *
5 * Author Petr Novak
6 * Copyright by Petr Novak <petr.novak@i.cz>
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
13#include <linux/config.h>
14#include <linux/init.h>
15#include "hisax.h"
16#include "w6692.h"
17#include "isdnl1.h"
18#include <linux/interrupt.h>
19#include <linux/pci.h>
20
21/* table entry in the PCI devices list */
22typedef struct {
23 int vendor_id;
24 int device_id;
25 char *vendor_name;
26 char *card_name;
27} PCI_ENTRY;
28
29static const PCI_ENTRY id_list[] =
30{
31 {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
32 {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
33 {0, 0, "U.S.Robotics", "ISDN PCI Card TA"}
34};
35
36#define W6692_SV_USR 0x16ec
37#define W6692_SD_USR 0x3409
38#define W6692_WINBOND 0
39#define W6692_DYNALINK 1
40#define W6692_USR 2
41
42extern const char *CardType[];
43
44const char *w6692_revision = "$Revision: 1.18.2.4 $";
45
46#define DBUSY_TIMER_VALUE 80
47
48static char *W6692Ver[] __initdata =
49{"W6692 V00", "W6692 V01", "W6692 V10",
50 "W6692 V11"};
51
52static void __init
53W6692Version(struct IsdnCardState *cs, char *s)
54{
55 int val;
56
57 val = cs->readW6692(cs, W_D_RBCH);
58 printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
59}
60
61static void
62ph_command(struct IsdnCardState *cs, unsigned int command)
63{
64 if (cs->debug & L1_DEB_ISAC)
65 debugl1(cs, "ph_command %x", command);
66 cs->writeisac(cs, W_CIX, command);
67}
68
69
70static void
71W6692_new_ph(struct IsdnCardState *cs)
72{
73 switch (cs->dc.w6692.ph_state) {
74 case (W_L1CMD_RST):
75 ph_command(cs, W_L1CMD_DRC);
76 l1_msg(cs, HW_RESET | INDICATION, NULL);
77 /* fallthru */
78 case (W_L1IND_CD):
79 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
80 break;
81 case (W_L1IND_DRD):
82 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
83 break;
84 case (W_L1IND_CE):
85 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
86 break;
87 case (W_L1IND_LD):
88 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
89 break;
90 case (W_L1IND_ARD):
91 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
92 break;
93 case (W_L1IND_AI8):
94 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
95 break;
96 case (W_L1IND_AI10):
97 l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
98 break;
99 default:
100 break;
101 }
102}
103
104static void
105W6692_bh(struct IsdnCardState *cs)
106{
107 struct PStack *stptr;
108
109 if (!cs)
110 return;
111 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
112 if (cs->debug)
113 debugl1(cs, "D-Channel Busy cleared");
114 stptr = cs->stlist;
115 while (stptr != NULL) {
116 stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
117 stptr = stptr->next;
118 }
119 }
120 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
121 W6692_new_ph(cs);
122 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
123 DChannel_proc_rcv(cs);
124 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
125 DChannel_proc_xmt(cs);
126/*
127 if (test_and_clear_bit(D_RX_MON1, &cs->event))
128 arcofi_fsm(cs, ARCOFI_RX_END, NULL);
129 if (test_and_clear_bit(D_TX_MON1, &cs->event))
130 arcofi_fsm(cs, ARCOFI_TX_END, NULL);
131 */
132}
133
134static void
135W6692_empty_fifo(struct IsdnCardState *cs, int count)
136{
137 u_char *ptr;
138
139 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
140 debugl1(cs, "W6692_empty_fifo");
141
142 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
143 if (cs->debug & L1_DEB_WARN)
144 debugl1(cs, "W6692_empty_fifo overrun %d",
145 cs->rcvidx + count);
146 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
147 cs->rcvidx = 0;
148 return;
149 }
150 ptr = cs->rcvbuf + cs->rcvidx;
151 cs->rcvidx += count;
152 cs->readW6692fifo(cs, ptr, count);
153 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
154 if (cs->debug & L1_DEB_ISAC_FIFO) {
155 char *t = cs->dlog;
156
157 t += sprintf(t, "W6692_empty_fifo cnt %d", count);
158 QuickHex(t, ptr, count);
159 debugl1(cs, cs->dlog);
160 }
161}
162
163static void
164W6692_fill_fifo(struct IsdnCardState *cs)
165{
166 int count, more;
167 u_char *ptr;
168
169 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
170 debugl1(cs, "W6692_fill_fifo");
171
172 if (!cs->tx_skb)
173 return;
174
175 count = cs->tx_skb->len;
176 if (count <= 0)
177 return;
178
179 more = 0;
180 if (count > W_D_FIFO_THRESH) {
181 more = !0;
182 count = W_D_FIFO_THRESH;
183 }
184 ptr = cs->tx_skb->data;
185 skb_pull(cs->tx_skb, count);
186 cs->tx_cnt += count;
187 cs->writeW6692fifo(cs, ptr, count);
188 cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME));
189 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
190 debugl1(cs, "W6692_fill_fifo dbusytimer running");
191 del_timer(&cs->dbusytimer);
192 }
193 init_timer(&cs->dbusytimer);
194 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
195 add_timer(&cs->dbusytimer);
196 if (cs->debug & L1_DEB_ISAC_FIFO) {
197 char *t = cs->dlog;
198
199 t += sprintf(t, "W6692_fill_fifo cnt %d", count);
200 QuickHex(t, ptr, count);
201 debugl1(cs, cs->dlog);
202 }
203}
204
205static void
206W6692B_empty_fifo(struct BCState *bcs, int count)
207{
208 u_char *ptr;
209 struct IsdnCardState *cs = bcs->cs;
210
211 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
212 debugl1(cs, "W6692B_empty_fifo");
213
214 if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) {
215 if (cs->debug & L1_DEB_WARN)
216 debugl1(cs, "W6692B_empty_fifo: incoming packet too large");
217 cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
218 bcs->hw.w6692.rcvidx = 0;
219 return;
220 }
221 ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
222 bcs->hw.w6692.rcvidx += count;
223 READW6692BFIFO(cs, bcs->channel, ptr, count);
224 cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
225 if (cs->debug & L1_DEB_HSCX_FIFO) {
226 char *t = bcs->blog;
227
228 t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
229 bcs->channel + '1', count);
230 QuickHex(t, ptr, count);
231 debugl1(cs, bcs->blog);
232 }
233}
234
235static void
236W6692B_fill_fifo(struct BCState *bcs)
237{
238 struct IsdnCardState *cs = bcs->cs;
239 int more, count;
240 u_char *ptr;
241
242 if (!bcs->tx_skb)
243 return;
244 if (bcs->tx_skb->len <= 0)
245 return;
246
247 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
248 if (bcs->tx_skb->len > W_B_FIFO_THRESH) {
249 more = 1;
250 count = W_B_FIFO_THRESH;
251 } else
252 count = bcs->tx_skb->len;
253
254 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
255 debugl1(cs, "W6692B_fill_fifo%s%d", (more ? " ": " last "), count);
256
257 ptr = bcs->tx_skb->data;
258 skb_pull(bcs->tx_skb, count);
259 bcs->tx_cnt -= count;
260 bcs->hw.w6692.count += count;
261 WRITEW6692BFIFO(cs, bcs->channel, ptr, count);
262 cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME));
263 if (cs->debug & L1_DEB_HSCX_FIFO) {
264 char *t = bcs->blog;
265
266 t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
267 bcs->channel + '1', count);
268 QuickHex(t, ptr, count);
269 debugl1(cs, bcs->blog);
270 }
271}
272
273static void
274W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
275{
276 u_char val;
277 u_char r;
278 struct BCState *bcs;
279 struct sk_buff *skb;
280 int count;
281
282 bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1);
283 val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR);
284 debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val);
285
286 if (!test_bit(BC_FLG_INIT, &bcs->Flag)) {
287 debugl1(cs, "W6692B not INIT yet");
288 return;
289 }
290 if (val & W_B_EXI_RME) { /* RME */
291 r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
292 if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
293 if (cs->debug & L1_DEB_WARN)
294 debugl1(cs, "W6692 B STAR %x", r);
295 if ((r & W_B_STAR_RDOV) && bcs->mode)
296 if (cs->debug & L1_DEB_WARN)
297 debugl1(cs, "W6692 B RDOV mode=%d",
298 bcs->mode);
299 if (r & W_B_STAR_CRCE)
300 if (cs->debug & L1_DEB_WARN)
301 debugl1(cs, "W6692 B CRC error");
302 cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
303 } else {
304 count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
305 if (count == 0)
306 count = W_B_FIFO_THRESH;
307 W6692B_empty_fifo(bcs, count);
308 if ((count = bcs->hw.w6692.rcvidx) > 0) {
309 if (cs->debug & L1_DEB_HSCX_FIFO)
310 debugl1(cs, "W6692 Bchan Frame %d", count);
311 if (!(skb = dev_alloc_skb(count)))
312 printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
313 else {
314 memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count);
315 skb_queue_tail(&bcs->rqueue, skb);
316 }
317 }
318 }
319 bcs->hw.w6692.rcvidx = 0;
320 schedule_event(bcs, B_RCVBUFREADY);
321 }
322 if (val & W_B_EXI_RMR) { /* RMR */
323 W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
324 r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
325 if (r & W_B_STAR_RDOV) {
326 if (cs->debug & L1_DEB_WARN)
327 debugl1(cs, "W6692 B RDOV(RMR) mode=%d",bcs->mode);
328 cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
329 if (bcs->mode != L1_MODE_TRANS)
330 bcs->hw.w6692.rcvidx = 0;
331 }
332 if (bcs->mode == L1_MODE_TRANS) {
333 /* receive audio data */
334 if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
335 printk(KERN_WARNING "HiSax: receive out of memory\n");
336 else {
337 memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH);
338 skb_queue_tail(&bcs->rqueue, skb);
339 }
340 bcs->hw.w6692.rcvidx = 0;
341 schedule_event(bcs, B_RCVBUFREADY);
342 }
343 }
344 if (val & W_B_EXI_XDUN) { /* XDUN */
345 cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
346 if (cs->debug & L1_DEB_WARN)
347 debugl1(cs, "W6692 B EXIR %x Lost TX", val);
348 if (bcs->mode == 1)
349 W6692B_fill_fifo(bcs);
350 else {
351 /* Here we lost an TX interrupt, so
352 * restart transmitting the whole frame.
353 */
354 if (bcs->tx_skb) {
355 skb_push(bcs->tx_skb, bcs->hw.w6692.count);
356 bcs->tx_cnt += bcs->hw.w6692.count;
357 bcs->hw.w6692.count = 0;
358 }
359 }
360 return;
361 }
362 if (val & W_B_EXI_XFR) { /* XFR */
363 r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
364 if (r & W_B_STAR_XDOW) {
365 if (cs->debug & L1_DEB_WARN)
366 debugl1(cs, "W6692 B STAR %x XDOW", r);
367 cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
368 if (bcs->tx_skb && (bcs->mode != 1)) {
369 skb_push(bcs->tx_skb, bcs->hw.w6692.count);
370 bcs->tx_cnt += bcs->hw.w6692.count;
371 bcs->hw.w6692.count = 0;
372 }
373 }
374 if (bcs->tx_skb) {
375 if (bcs->tx_skb->len) {
376 W6692B_fill_fifo(bcs);
377 return;
378 } else {
379 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
380 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
381 u_long flags;
382 spin_lock_irqsave(&bcs->aclock, flags);
383 bcs->ackcnt += bcs->hw.w6692.count;
384 spin_unlock_irqrestore(&bcs->aclock, flags);
385 schedule_event(bcs, B_ACKPENDING);
386 }
387 dev_kfree_skb_irq(bcs->tx_skb);
388 bcs->hw.w6692.count = 0;
389 bcs->tx_skb = NULL;
390 }
391 }
392 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
393 bcs->hw.w6692.count = 0;
394 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
395 W6692B_fill_fifo(bcs);
396 } else {
397 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
398 schedule_event(bcs, B_XMTBUFREADY);
399 }
400 }
401}
402
403static irqreturn_t
404W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
405{
406 struct IsdnCardState *cs = dev_id;
407 u_char val, exval, v1;
408 struct sk_buff *skb;
409 u_int count;
410 u_long flags;
411 int icnt = 5;
412
413 spin_lock_irqsave(&cs->lock, flags);
414 val = cs->readW6692(cs, W_ISTA);
415 if (!val) {
416 spin_unlock_irqrestore(&cs->lock, flags);
417 return IRQ_NONE;
418 }
419 StartW6692:
420 if (cs->debug & L1_DEB_ISAC)
421 debugl1(cs, "W6692 ISTA %x", val);
422
423 if (val & W_INT_D_RME) { /* RME */
424 exval = cs->readW6692(cs, W_D_RSTA);
425 if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
426 if (exval & W_D_RSTA_RDOV)
427 if (cs->debug & L1_DEB_WARN)
428 debugl1(cs, "W6692 RDOV");
429 if (exval & W_D_RSTA_CRCE)
430 if (cs->debug & L1_DEB_WARN)
431 debugl1(cs, "W6692 D-channel CRC error");
432 if (exval & W_D_RSTA_RMB)
433 if (cs->debug & L1_DEB_WARN)
434 debugl1(cs, "W6692 D-channel ABORT");
435 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
436 } else {
437 count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
438 if (count == 0)
439 count = W_D_FIFO_THRESH;
440 W6692_empty_fifo(cs, count);
441 if ((count = cs->rcvidx) > 0) {
442 cs->rcvidx = 0;
443 if (!(skb = alloc_skb(count, GFP_ATOMIC)))
444 printk(KERN_WARNING "HiSax: D receive out of memory\n");
445 else {
446 memcpy(skb_put(skb, count), cs->rcvbuf, count);
447 skb_queue_tail(&cs->rq, skb);
448 }
449 }
450 }
451 cs->rcvidx = 0;
452 schedule_event(cs, D_RCVBUFREADY);
453 }
454 if (val & W_INT_D_RMR) { /* RMR */
455 W6692_empty_fifo(cs, W_D_FIFO_THRESH);
456 }
457 if (val & W_INT_D_XFR) { /* XFR */
458 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
459 del_timer(&cs->dbusytimer);
460 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
461 schedule_event(cs, D_CLEARBUSY);
462 if (cs->tx_skb) {
463 if (cs->tx_skb->len) {
464 W6692_fill_fifo(cs);
465 goto afterXFR;
466 } else {
467 dev_kfree_skb_irq(cs->tx_skb);
468 cs->tx_cnt = 0;
469 cs->tx_skb = NULL;
470 }
471 }
472 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
473 cs->tx_cnt = 0;
474 W6692_fill_fifo(cs);
475 } else
476 schedule_event(cs, D_XMTBUFREADY);
477 }
478 afterXFR:
479 if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */
480 if (cs->debug & L1_DEB_ISAC)
481 debugl1(cs, "W6692 spurious XINT!");
482 }
483 if (val & W_INT_D_EXI) { /* EXI */
484 exval = cs->readW6692(cs, W_D_EXIR);
485 if (cs->debug & L1_DEB_WARN)
486 debugl1(cs, "W6692 D_EXIR %02x", exval);
487 if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */
488 debugl1(cs, "W6692 D-chan underrun/collision");
489 printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n");
490 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
491 del_timer(&cs->dbusytimer);
492 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
493 schedule_event(cs, D_CLEARBUSY);
494 if (cs->tx_skb) { /* Restart frame */
495 skb_push(cs->tx_skb, cs->tx_cnt);
496 cs->tx_cnt = 0;
497 W6692_fill_fifo(cs);
498 } else {
499 printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n");
500 debugl1(cs, "W6692 XDUN/XCOL no skb");
501 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);
502 }
503 }
504 if (exval & W_D_EXI_RDOV) { /* RDOV */
505 debugl1(cs, "W6692 D-channel RDOV");
506 printk(KERN_WARNING "HiSax: W6692 D-RDOV\n");
507 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST);
508 }
509 if (exval & W_D_EXI_TIN2) { /* TIN2 - never */
510 debugl1(cs, "W6692 spurious TIN2 interrupt");
511 }
512 if (exval & W_D_EXI_MOC) { /* MOC - not supported */
513 debugl1(cs, "W6692 spurious MOC interrupt");
514 v1 = cs->readW6692(cs, W_MOSR);
515 debugl1(cs, "W6692 MOSR %02x", v1);
516 }
517 if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */
518 v1 = cs->readW6692(cs, W_CIR);
519 if (cs->debug & L1_DEB_ISAC)
520 debugl1(cs, "W6692 ISC CIR=0x%02X", v1);
521 if (v1 & W_CIR_ICC) {
522 cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK;
523 if (cs->debug & L1_DEB_ISAC)
524 debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state);
525 schedule_event(cs, D_L1STATECHANGE);
526 }
527 if (v1 & W_CIR_SCC) {
528 v1 = cs->readW6692(cs, W_SQR);
529 debugl1(cs, "W6692 SCC SQR=0x%02X", v1);
530 }
531 }
532 if (exval & W_D_EXI_WEXP) {
533 debugl1(cs, "W6692 spurious WEXP interrupt!");
534 }
535 if (exval & W_D_EXI_TEXP) {
536 debugl1(cs, "W6692 spurious TEXP interrupt!");
537 }
538 }
539 if (val & W_INT_B1_EXI) {
540 debugl1(cs, "W6692 B channel 1 interrupt");
541 W6692B_interrupt(cs, 0);
542 }
543 if (val & W_INT_B2_EXI) {
544 debugl1(cs, "W6692 B channel 2 interrupt");
545 W6692B_interrupt(cs, 1);
546 }
547 val = cs->readW6692(cs, W_ISTA);
548 if (val && icnt) {
549 icnt--;
550 goto StartW6692;
551 }
552 if (!icnt) {
553 printk(KERN_WARNING "W6692 IRQ LOOP\n");
554 cs->writeW6692(cs, W_IMASK, 0xff);
555 }
556 spin_unlock_irqrestore(&cs->lock, flags);
557 return IRQ_HANDLED;
558}
559
560static void
561W6692_l1hw(struct PStack *st, int pr, void *arg)
562{
563 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
564 struct sk_buff *skb = arg;
565 u_long flags;
566 int val;
567
568 switch (pr) {
569 case (PH_DATA | REQUEST):
570 if (cs->debug & DEB_DLOG_HEX)
571 LogFrame(cs, skb->data, skb->len);
572 if (cs->debug & DEB_DLOG_VERBOSE)
573 dlogframe(cs, skb, 0);
574 spin_lock_irqsave(&cs->lock, flags);
575 if (cs->tx_skb) {
576 skb_queue_tail(&cs->sq, skb);
577#ifdef L2FRAME_DEBUG /* psa */
578 if (cs->debug & L1_DEB_LAPD)
579 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
580#endif
581 } else {
582 cs->tx_skb = skb;
583 cs->tx_cnt = 0;
584#ifdef L2FRAME_DEBUG /* psa */
585 if (cs->debug & L1_DEB_LAPD)
586 Logl2Frame(cs, skb, "PH_DATA", 0);
587#endif
588 W6692_fill_fifo(cs);
589 }
590 spin_unlock_irqrestore(&cs->lock, flags);
591 break;
592 case (PH_PULL | INDICATION):
593 spin_lock_irqsave(&cs->lock, flags);
594 if (cs->tx_skb) {
595 if (cs->debug & L1_DEB_WARN)
596 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
597 skb_queue_tail(&cs->sq, skb);
598 spin_unlock_irqrestore(&cs->lock, flags);
599 break;
600 }
601 if (cs->debug & DEB_DLOG_HEX)
602 LogFrame(cs, skb->data, skb->len);
603 if (cs->debug & DEB_DLOG_VERBOSE)
604 dlogframe(cs, skb, 0);
605 cs->tx_skb = skb;
606 cs->tx_cnt = 0;
607#ifdef L2FRAME_DEBUG /* psa */
608 if (cs->debug & L1_DEB_LAPD)
609 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
610#endif
611 W6692_fill_fifo(cs);
612 spin_unlock_irqrestore(&cs->lock, flags);
613 break;
614 case (PH_PULL | REQUEST):
615#ifdef L2FRAME_DEBUG /* psa */
616 if (cs->debug & L1_DEB_LAPD)
617 debugl1(cs, "-> PH_REQUEST_PULL");
618#endif
619 if (!cs->tx_skb) {
620 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
621 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
622 } else
623 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
624 break;
625 case (HW_RESET | REQUEST):
626 spin_lock_irqsave(&cs->lock, flags);
627 if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) {
628 ph_command(cs, W_L1CMD_ECK);
629 spin_unlock_irqrestore(&cs->lock, flags);
630 } else {
631 ph_command(cs, W_L1CMD_RST);
632 cs->dc.w6692.ph_state = W_L1CMD_RST;
633 spin_unlock_irqrestore(&cs->lock, flags);
634 W6692_new_ph(cs);
635 }
636 break;
637 case (HW_ENABLE | REQUEST):
638 spin_lock_irqsave(&cs->lock, flags);
639 ph_command(cs, W_L1CMD_ECK);
640 spin_unlock_irqrestore(&cs->lock, flags);
641 break;
642 case (HW_INFO3 | REQUEST):
643 spin_lock_irqsave(&cs->lock, flags);
644 ph_command(cs, W_L1CMD_AR8);
645 spin_unlock_irqrestore(&cs->lock, flags);
646 break;
647 case (HW_TESTLOOP | REQUEST):
648 val = 0;
649 if (1 & (long) arg)
650 val |= 0x0c;
651 if (2 & (long) arg)
652 val |= 0x3;
653 /* !!! not implemented yet */
654 break;
655 case (HW_DEACTIVATE | RESPONSE):
656 skb_queue_purge(&cs->rq);
657 skb_queue_purge(&cs->sq);
658 if (cs->tx_skb) {
659 dev_kfree_skb_any(cs->tx_skb);
660 cs->tx_skb = NULL;
661 }
662 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
663 del_timer(&cs->dbusytimer);
664 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
665 schedule_event(cs, D_CLEARBUSY);
666 break;
667 default:
668 if (cs->debug & L1_DEB_WARN)
669 debugl1(cs, "W6692_l1hw unknown %04x", pr);
670 break;
671 }
672}
673
674static void
675setstack_W6692(struct PStack *st, struct IsdnCardState *cs)
676{
677 st->l1.l1hw = W6692_l1hw;
678}
679
680static void
681DC_Close_W6692(struct IsdnCardState *cs)
682{
683}
684
685static void
686dbusy_timer_handler(struct IsdnCardState *cs)
687{
688 struct PStack *stptr;
689 int rbch, star;
690 u_long flags;
691
692 spin_lock_irqsave(&cs->lock, flags);
693 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
694 rbch = cs->readW6692(cs, W_D_RBCH);
695 star = cs->readW6692(cs, W_D_STAR);
696 if (cs->debug)
697 debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x",
698 rbch, star);
699 if (star & W_D_STAR_XBZ) { /* D-Channel Busy */
700 test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
701 stptr = cs->stlist;
702 while (stptr != NULL) {
703 stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
704 stptr = stptr->next;
705 }
706 } else {
707 /* discard frame; reset transceiver */
708 test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
709 if (cs->tx_skb) {
710 dev_kfree_skb_any(cs->tx_skb);
711 cs->tx_cnt = 0;
712 cs->tx_skb = NULL;
713 } else {
714 printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n");
715 debugl1(cs, "D-Channel Busy no skb");
716 }
717 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */
718 spin_unlock_irqrestore(&cs->lock, flags);
719 cs->irq_func(cs->irq, cs, NULL);
720 return;
721 }
722 }
723 spin_unlock_irqrestore(&cs->lock, flags);
724}
725
726static void
727W6692Bmode(struct BCState *bcs, int mode, int bchan)
728{
729 struct IsdnCardState *cs = bcs->cs;
730
731 if (cs->debug & L1_DEB_HSCX)
732 debugl1(cs, "w6692 %c mode %d ichan %d",
733 '1' + bchan, mode, bchan);
734 bcs->mode = mode;
735 bcs->channel = bchan;
736 bcs->hw.w6692.bchan = bchan;
737
738 switch (mode) {
739 case (L1_MODE_NULL):
740 cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0);
741 break;
742 case (L1_MODE_TRANS):
743 cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS);
744 break;
745 case (L1_MODE_HDLC):
746 cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF);
747 cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff);
748 cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff);
749 break;
750 }
751 if (mode)
752 cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST |
753 W_B_CMDR_RACT | W_B_CMDR_XRST);
754 cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00);
755}
756
757static void
758W6692_l2l1(struct PStack *st, int pr, void *arg)
759{
760 struct sk_buff *skb = arg;
761 struct BCState *bcs = st->l1.bcs;
762 u_long flags;
763
764 switch (pr) {
765 case (PH_DATA | REQUEST):
766 spin_lock_irqsave(&bcs->cs->lock, flags);
767 if (bcs->tx_skb) {
768 skb_queue_tail(&bcs->squeue, skb);
769 } else {
770 bcs->tx_skb = skb;
771 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
772 bcs->hw.w6692.count = 0;
773 bcs->cs->BC_Send_Data(bcs);
774 }
775 spin_unlock_irqrestore(&bcs->cs->lock, flags);
776 break;
777 case (PH_PULL | INDICATION):
778 if (bcs->tx_skb) {
779 printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n");
780 break;
781 }
782 spin_lock_irqsave(&bcs->cs->lock, flags);
783 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
784 bcs->tx_skb = skb;
785 bcs->hw.w6692.count = 0;
786 bcs->cs->BC_Send_Data(bcs);
787 spin_unlock_irqrestore(&bcs->cs->lock, flags);
788 break;
789 case (PH_PULL | REQUEST):
790 if (!bcs->tx_skb) {
791 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
792 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
793 } else
794 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
795 break;
796 case (PH_ACTIVATE | REQUEST):
797 spin_lock_irqsave(&bcs->cs->lock, flags);
798 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
799 W6692Bmode(bcs, st->l1.mode, st->l1.bc);
800 spin_unlock_irqrestore(&bcs->cs->lock, flags);
801 l1_msg_b(st, pr, arg);
802 break;
803 case (PH_DEACTIVATE | REQUEST):
804 l1_msg_b(st, pr, arg);
805 break;
806 case (PH_DEACTIVATE | CONFIRM):
807 spin_lock_irqsave(&bcs->cs->lock, flags);
808 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
809 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
810 W6692Bmode(bcs, 0, st->l1.bc);
811 spin_unlock_irqrestore(&bcs->cs->lock, flags);
812 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
813 break;
814 }
815}
816
817static void
818close_w6692state(struct BCState *bcs)
819{
820 W6692Bmode(bcs, 0, bcs->channel);
821 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
822 if (bcs->hw.w6692.rcvbuf) {
823 kfree(bcs->hw.w6692.rcvbuf);
824 bcs->hw.w6692.rcvbuf = NULL;
825 }
826 if (bcs->blog) {
827 kfree(bcs->blog);
828 bcs->blog = NULL;
829 }
830 skb_queue_purge(&bcs->rqueue);
831 skb_queue_purge(&bcs->squeue);
832 if (bcs->tx_skb) {
833 dev_kfree_skb_any(bcs->tx_skb);
834 bcs->tx_skb = NULL;
835 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
836 }
837 }
838}
839
840static int
841open_w6692state(struct IsdnCardState *cs, struct BCState *bcs)
842{
843 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
844 if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
845 printk(KERN_WARNING
846 "HiSax: No memory for w6692.rcvbuf\n");
847 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
848 return (1);
849 }
850 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
851 printk(KERN_WARNING
852 "HiSax: No memory for bcs->blog\n");
853 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
854 kfree(bcs->hw.w6692.rcvbuf);
855 bcs->hw.w6692.rcvbuf = NULL;
856 return (2);
857 }
858 skb_queue_head_init(&bcs->rqueue);
859 skb_queue_head_init(&bcs->squeue);
860 }
861 bcs->tx_skb = NULL;
862 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
863 bcs->event = 0;
864 bcs->hw.w6692.rcvidx = 0;
865 bcs->tx_cnt = 0;
866 return (0);
867}
868
869static int
870setstack_w6692(struct PStack *st, struct BCState *bcs)
871{
872 bcs->channel = st->l1.bc;
873 if (open_w6692state(st->l1.hardware, bcs))
874 return (-1);
875 st->l1.bcs = bcs;
876 st->l2.l2l1 = W6692_l2l1;
877 setstack_manager(st);
878 bcs->st = st;
879 setstack_l1_B(st);
880 return (0);
881}
882
883void resetW6692(struct IsdnCardState *cs)
884{
885 cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
886 mdelay(10);
887 cs->writeW6692(cs, W_D_CTL, 0x00);
888 mdelay(10);
889 cs->writeW6692(cs, W_IMASK, 0xff);
890 cs->writeW6692(cs, W_D_SAM, 0xff);
891 cs->writeW6692(cs, W_D_TAM, 0xff);
892 cs->writeW6692(cs, W_D_EXIM, 0x00);
893 cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
894 cs->writeW6692(cs, W_IMASK, 0x18);
895 if (cs->subtyp == W6692_USR) {
896 /* seems that USR implemented some power control features
897 * Pin 79 is connected to the oscilator circuit so we
898 * have to handle it here
899 */
900 cs->writeW6692(cs, W_PCTL, 0x80);
901 cs->writeW6692(cs, W_XDATA, 0x00);
902 }
903}
904
905void __init initW6692(struct IsdnCardState *cs, int part)
906{
907 if (part & 1) {
908 cs->setstack_d = setstack_W6692;
909 cs->DC_Close = DC_Close_W6692;
910 cs->dbusytimer.function = (void *) dbusy_timer_handler;
911 cs->dbusytimer.data = (long) cs;
912 init_timer(&cs->dbusytimer);
913 resetW6692(cs);
914 ph_command(cs, W_L1CMD_RST);
915 cs->dc.w6692.ph_state = W_L1CMD_RST;
916 W6692_new_ph(cs);
917 ph_command(cs, W_L1CMD_ECK);
918
919 cs->bcs[0].BC_SetStack = setstack_w6692;
920 cs->bcs[1].BC_SetStack = setstack_w6692;
921 cs->bcs[0].BC_Close = close_w6692state;
922 cs->bcs[1].BC_Close = close_w6692state;
923 W6692Bmode(cs->bcs, 0, 0);
924 W6692Bmode(cs->bcs + 1, 0, 0);
925 }
926 if (part & 2) {
927 /* Reenable all IRQ */
928 cs->writeW6692(cs, W_IMASK, 0x18);
929 cs->writeW6692(cs, W_D_EXIM, 0x00);
930 cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00);
931 cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00);
932 /* Reset D-chan receiver and transmitter */
933 cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
934 }
935}
936
937/* Interface functions */
938
939static u_char
940ReadW6692(struct IsdnCardState *cs, u_char offset)
941{
942 return (inb(cs->hw.w6692.iobase + offset));
943}
944
945static void
946WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value)
947{
948 outb(value, cs->hw.w6692.iobase + offset);
949}
950
951static void
952ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
953{
954 insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
955}
956
957static void
958WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
959{
960 outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
961}
962
963static u_char
964ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset)
965{
966 return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset));
967}
968
969static void
970WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value)
971{
972 outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
973}
974
975static int
976w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
977{
978 switch (mt) {
979 case CARD_RESET:
980 resetW6692(cs);
981 return (0);
982 case CARD_RELEASE:
983 cs->writeW6692(cs, W_IMASK, 0xff);
984 release_region(cs->hw.w6692.iobase, 256);
985 if (cs->subtyp == W6692_USR) {
986 cs->writeW6692(cs, W_XDATA, 0x04);
987 }
988 return (0);
989 case CARD_INIT:
990 initW6692(cs, 3);
991 return (0);
992 case CARD_TEST:
993 return (0);
994 }
995 return (0);
996}
997
998static int id_idx ;
999
1000static struct pci_dev *dev_w6692 __initdata = NULL;
1001
1002int __init
1003setup_w6692(struct IsdnCard *card)
1004{
1005 struct IsdnCardState *cs = card->cs;
1006 char tmp[64];
1007 u_char found = 0;
1008 u_char pci_irq = 0;
1009 u_int pci_ioaddr = 0;
1010
1011 strcpy(tmp, w6692_revision);
1012 printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
1013 if (cs->typ != ISDN_CTYPE_W6692)
1014 return (0);
1015#ifdef CONFIG_PCI
1016 while (id_list[id_idx].vendor_id) {
1017 dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
1018 id_list[id_idx].device_id,
1019 dev_w6692);
1020 if (dev_w6692) {
1021 if (pci_enable_device(dev_w6692))
1022 continue;
1023 cs->subtyp = id_idx;
1024 break;
1025 }
1026 id_idx++;
1027 }
1028 if (dev_w6692) {
1029 found = 1;
1030 pci_irq = dev_w6692->irq;
1031 /* I think address 0 is allways the configuration area */
1032 /* and address 1 is the real IO space KKe 03.09.99 */
1033 pci_ioaddr = pci_resource_start(dev_w6692, 1);
1034 /* USR ISDN PCI card TA need some special handling */
1035 if (cs->subtyp == W6692_WINBOND) {
1036 if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
1037 (W6692_SD_USR == dev_w6692->subsystem_device)) {
1038 cs->subtyp = W6692_USR;
1039 }
1040 }
1041 }
1042 if (!found) {
1043 printk(KERN_WARNING "W6692: No PCI card found\n");
1044 return (0);
1045 }
1046 cs->irq = pci_irq;
1047 if (!cs->irq) {
1048 printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
1049 return (0);
1050 }
1051 if (!pci_ioaddr) {
1052 printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
1053 return (0);
1054 }
1055 cs->hw.w6692.iobase = pci_ioaddr;
1056 printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
1057 id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
1058 pci_ioaddr, pci_irq);
1059 if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) {
1060 printk(KERN_WARNING
1061 "HiSax: %s I/O ports %x-%x already in use\n",
1062 id_list[cs->subtyp].card_name,
1063 cs->hw.w6692.iobase,
1064 cs->hw.w6692.iobase + 255);
1065 return (0);
1066 }
1067#else
1068 printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
1069 printk(KERN_WARNING "HiSax: W6692 unable to config\n");
1070 return (0);
1071#endif /* CONFIG_PCI */
1072
1073 printk(KERN_INFO
1074 "HiSax: %s config irq:%d I/O:%x\n",
1075 id_list[cs->subtyp].card_name, cs->irq,
1076 cs->hw.w6692.iobase);
1077
1078 INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs);
1079 cs->readW6692 = &ReadW6692;
1080 cs->writeW6692 = &WriteW6692;
1081 cs->readisacfifo = &ReadISACfifo;
1082 cs->writeisacfifo = &WriteISACfifo;
1083 cs->BC_Read_Reg = &ReadW6692B;
1084 cs->BC_Write_Reg = &WriteW6692B;
1085 cs->BC_Send_Data = &W6692B_fill_fifo;
1086 cs->cardmsg = &w6692_card_msg;
1087 cs->irq_func = &W6692_interrupt;
1088 cs->irq_flags |= SA_SHIRQ;
1089 W6692Version(cs, "W6692:");
1090 printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA));
1091 printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK));
1092 printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR));
1093 printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM));
1094 printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA));
1095 return (1);
1096}
diff --git a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h
new file mode 100644
index 00000000000..c79c81e0401
--- /dev/null
+++ b/drivers/isdn/hisax/w6692.h
@@ -0,0 +1,184 @@
1/* $Id: w6692.h,v 1.4.2.2 2004/01/12 22:52:29 keil Exp $
2 *
3 * Winbond W6692 specific defines
4 *
5 * Author Petr Novak
6 * Copyright by Petr Novak <petr.novak@i.cz>
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
13/* map W6692 functions to ISAC functions */
14#define readW6692 readisac
15#define writeW6692 writeisac
16#define readW6692fifo readisacfifo
17#define writeW6692fifo writeisacfifo
18
19/* B-channel FIFO read/write routines */
20
21#define READW6692BFIFO(cs,bchan,ptr,count) \
22 insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count)
23
24#define WRITEW6692BFIFO(cs,bchan,ptr,count) \
25 outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count)
26
27/* Specifications of W6692 registers */
28
29#define W_D_RFIFO 0x00 /* R */
30#define W_D_XFIFO 0x04 /* W */
31#define W_D_CMDR 0x08 /* W */
32#define W_D_MODE 0x0c /* R/W */
33#define W_D_TIMR 0x10 /* R/W */
34#define W_ISTA 0x14 /* R_clr */
35#define W_IMASK 0x18 /* R/W */
36#define W_D_EXIR 0x1c /* R_clr */
37#define W_D_EXIM 0x20 /* R/W */
38#define W_D_STAR 0x24 /* R */
39#define W_D_RSTA 0x28 /* R */
40#define W_D_SAM 0x2c /* R/W */
41#define W_D_SAP1 0x30 /* R/W */
42#define W_D_SAP2 0x34 /* R/W */
43#define W_D_TAM 0x38 /* R/W */
44#define W_D_TEI1 0x3c /* R/W */
45#define W_D_TEI2 0x40 /* R/W */
46#define W_D_RBCH 0x44 /* R */
47#define W_D_RBCL 0x48 /* R */
48#define W_TIMR2 0x4c /* W */
49#define W_L1_RC 0x50 /* R/W */
50#define W_D_CTL 0x54 /* R/W */
51#define W_CIR 0x58 /* R */
52#define W_CIX 0x5c /* W */
53#define W_SQR 0x60 /* R */
54#define W_SQX 0x64 /* W */
55#define W_PCTL 0x68 /* R/W */
56#define W_MOR 0x6c /* R */
57#define W_MOX 0x70 /* R/W */
58#define W_MOSR 0x74 /* R_clr */
59#define W_MOCR 0x78 /* R/W */
60#define W_GCR 0x7c /* R/W */
61
62#define W_B_RFIFO 0x80 /* R */
63#define W_B_XFIFO 0x84 /* W */
64#define W_B_CMDR 0x88 /* W */
65#define W_B_MODE 0x8c /* R/W */
66#define W_B_EXIR 0x90 /* R_clr */
67#define W_B_EXIM 0x94 /* R/W */
68#define W_B_STAR 0x98 /* R */
69#define W_B_ADM1 0x9c /* R/W */
70#define W_B_ADM2 0xa0 /* R/W */
71#define W_B_ADR1 0xa4 /* R/W */
72#define W_B_ADR2 0xa8 /* R/W */
73#define W_B_RBCL 0xac /* R */
74#define W_B_RBCH 0xb0 /* R */
75
76#define W_XADDR 0xf4 /* R/W */
77#define W_XDATA 0xf8 /* R/W */
78#define W_EPCTL 0xfc /* W */
79
80/* W6692 register bits */
81
82#define W_D_CMDR_XRST 0x01
83#define W_D_CMDR_XME 0x02
84#define W_D_CMDR_XMS 0x08
85#define W_D_CMDR_STT 0x10
86#define W_D_CMDR_RRST 0x40
87#define W_D_CMDR_RACK 0x80
88
89#define W_D_MODE_RLP 0x01
90#define W_D_MODE_DLP 0x02
91#define W_D_MODE_MFD 0x04
92#define W_D_MODE_TEE 0x08
93#define W_D_MODE_TMS 0x10
94#define W_D_MODE_RACT 0x40
95#define W_D_MODE_MMS 0x80
96
97#define W_INT_B2_EXI 0x01
98#define W_INT_B1_EXI 0x02
99#define W_INT_D_EXI 0x04
100#define W_INT_XINT0 0x08
101#define W_INT_XINT1 0x10
102#define W_INT_D_XFR 0x20
103#define W_INT_D_RME 0x40
104#define W_INT_D_RMR 0x80
105
106#define W_D_EXI_WEXP 0x01
107#define W_D_EXI_TEXP 0x02
108#define W_D_EXI_ISC 0x04
109#define W_D_EXI_MOC 0x08
110#define W_D_EXI_TIN2 0x10
111#define W_D_EXI_XCOL 0x20
112#define W_D_EXI_XDUN 0x40
113#define W_D_EXI_RDOV 0x80
114
115#define W_D_STAR_DRDY 0x10
116#define W_D_STAR_XBZ 0x20
117#define W_D_STAR_XDOW 0x80
118
119#define W_D_RSTA_RMB 0x10
120#define W_D_RSTA_CRCE 0x20
121#define W_D_RSTA_RDOV 0x40
122
123#define W_D_CTL_SRST 0x20
124
125#define W_CIR_SCC 0x80
126#define W_CIR_ICC 0x40
127#define W_CIR_COD_MASK 0x0f
128
129#define W_B_CMDR_XRST 0x01
130#define W_B_CMDR_XME 0x02
131#define W_B_CMDR_XMS 0x04
132#define W_B_CMDR_RACT 0x20
133#define W_B_CMDR_RRST 0x40
134#define W_B_CMDR_RACK 0x80
135
136#define W_B_MODE_FTS0 0x01
137#define W_B_MODE_FTS1 0x02
138#define W_B_MODE_SW56 0x04
139#define W_B_MODE_BSW0 0x08
140#define W_B_MODE_BSW1 0x10
141#define W_B_MODE_EPCM 0x20
142#define W_B_MODE_ITF 0x40
143#define W_B_MODE_MMS 0x80
144
145#define W_B_EXI_XDUN 0x01
146#define W_B_EXI_XFR 0x02
147#define W_B_EXI_RDOV 0x10
148#define W_B_EXI_RME 0x20
149#define W_B_EXI_RMR 0x40
150
151#define W_B_STAR_XBZ 0x01
152#define W_B_STAR_XDOW 0x04
153#define W_B_STAR_RMB 0x10
154#define W_B_STAR_CRCE 0x20
155#define W_B_STAR_RDOV 0x40
156
157#define W_B_RBCH_LOV 0x20
158
159/* W6692 Layer1 commands */
160
161#define W_L1CMD_ECK 0x00
162#define W_L1CMD_RST 0x01
163#define W_L1CMD_SCP 0x04
164#define W_L1CMD_SSP 0x02
165#define W_L1CMD_AR8 0x08
166#define W_L1CMD_AR10 0x09
167#define W_L1CMD_EAL 0x0a
168#define W_L1CMD_DRC 0x0f
169
170/* W6692 Layer1 indications */
171
172#define W_L1IND_CE 0x07
173#define W_L1IND_DRD 0x00
174#define W_L1IND_LD 0x04
175#define W_L1IND_ARD 0x08
176#define W_L1IND_TI 0x0a
177#define W_L1IND_ATI 0x0b
178#define W_L1IND_AI8 0x0c
179#define W_L1IND_AI10 0x0d
180#define W_L1IND_CD 0x0f
181
182/* FIFO thresholds */
183#define W_D_FIFO_THRESH 64
184#define W_B_FIFO_THRESH 64