Compare commits
426 Commits
Author | SHA1 | Date |
---|---|---|
Martin Bachem | 3a24517201 | |
Martin Bachem | 4feee5174d | |
Martin Bachem | 818d806b82 | |
Martin Bachem | 687a87f360 | |
Detlef Wengorz | 215c508126 | |
Detlef Wengorz | d6bcb93acf | |
Karsten Keil | 3fcfc40d2e | |
Karsten Keil | 572178b99a | |
Detlef Wengorz | 3f1114644b | |
Karsten Keil | 68bcd010cf | |
Karsten Keil | f283a7e2c8 | |
Karsten Keil | 5188e85a9d | |
Karsten Keil | cab5bbc766 | |
Karsten Keil | 5bff970309 | |
Karsten Keil | 1703b79605 | |
Detlef Wengorz | b6f56b49af | |
Detlef Wengorz | 9b21ae7b60 | |
Armin Schindler | c052dac2f7 | |
Kai Germaschewski | 879c508ed1 | |
Kai Germaschewski | 6e79abd50f | |
Detlef Wengorz | 3a40e847c2 | |
Kai Germaschewski | c24ac62372 | |
Kai Germaschewski | c259549bc1 | |
Karsten Keil | c8ef9ea3f5 | |
Kai Germaschewski | 498f4da6ca | |
Kai Germaschewski | cdeb0a4c9f | |
Kai Germaschewski | a87ac24dee | |
Kai Germaschewski | e80660afb5 | |
Ulrich Albrecht | 89a11781cb | |
Kai Germaschewski | 276d17903c | |
Kai Germaschewski | a7c9cd8c7f | |
Kai Germaschewski | 132d6d83b7 | |
Karsten Keil | 5ad604bf7f | |
Kai Germaschewski | 625e9d8760 | |
Kai Germaschewski | 2b18963fc0 | |
Kai Germaschewski | 483673a6d3 | |
Kai Germaschewski | 5c71affd56 | |
Kai Germaschewski | 3f57fd5432 | |
Kai Germaschewski | b8115d4950 | |
Kai Germaschewski | fd1a3f457e | |
Kai Germaschewski | 028b0f5570 | |
Kai Germaschewski | 4c5152e3ed | |
Karsten Keil | e10f085bbb | |
Armin Schindler | b41cb5d65a | |
Armin Schindler | df75253118 | |
Detlef Wengorz | 7b418c2b90 | |
Kai Germaschewski | df921e6651 | |
Kai Germaschewski | de3b81cbce | |
Werner Cornelius | bf859c6ef7 | |
Werner Cornelius | ced29e47f1 | |
Karsten Keil | 042c4da0e9 | |
Karsten Keil | 5c7df9c077 | |
Kai Germaschewski | 6d2ddd8024 | |
Kai Germaschewski | f52026d482 | |
Kai Germaschewski | 271bd73c86 | |
Kai Germaschewski | 257850e38e | |
Kai Germaschewski | 6c0e8c43ea | |
Kai Germaschewski | 4483226493 | |
Kai Germaschewski | 2b5646effa | |
Kai Germaschewski | bf736af8fe | |
Werner Cornelius | 7201ec78cc | |
Werner Cornelius | 5affe803e1 | |
Werner Cornelius | d5d7b96910 | |
Werner Cornelius | 9917c4eab9 | |
Werner Cornelius | 8670d8c1b7 | |
Werner Cornelius | 6e243e06a1 | |
Werner Cornelius | 794b57c5b0 | |
Werner Cornelius | c59d09a54c | |
Werner Cornelius | feebdafb63 | |
Werner Cornelius | 0099cdbe13 | |
Kai Germaschewski | 8bbee59c21 | |
Kai Germaschewski | da09cee971 | |
Kai Germaschewski | c0fadb5f5e | |
Kai Germaschewski | 7bc01fd25c | |
Kai Germaschewski | ab87def0bb | |
Kai Germaschewski | b0f8f1dd42 | |
Kai Germaschewski | afe0d1ce83 | |
Kai Germaschewski | 18962b1891 | |
Kai Germaschewski | 6e91e47e5c | |
Kai Germaschewski | 3e9a5114aa | |
Carsten Paeth | 36c96b77ee | |
Carsten Paeth | 4280a7f6f9 | |
Carsten Paeth | e92e025c06 | |
Fritz Elfert | 8e8810e7ab | |
Carsten Paeth | 53c6c6b193 | |
Karsten Keil | 988052c6a4 | |
Karsten Keil | 304ed7995c | |
Karsten Keil | b79c3467b7 | |
Ulrich Albrecht | 334236da05 | |
Ulrich Albrecht | 3711c9f8c4 | |
Ulrich Albrecht | 813394f454 | |
Ulrich Albrecht | da280ff035 | |
Armin Schindler | 1018a97dc8 | |
Kai Germaschewski | 400bce700c | |
Kai Germaschewski | 4a982da022 | |
Carsten Paeth | d66c28295a | |
Detlef Wengorz | 91f3663b0e | |
Detlef Wengorz | d66fce0922 | |
Kai Germaschewski | 554d2014f3 | |
Kai Germaschewski | d2c067b2ba | |
Kai Germaschewski | 391f2b7758 | |
Kai Germaschewski | c977f66fab | |
Kai Germaschewski | 5a21f01636 | |
Kai Germaschewski | 03c561f5cc | |
Kai Germaschewski | 331c629e51 | |
Kai Germaschewski | 100bf42e08 | |
Ulrich Albrecht | 217e453e65 | |
Ulrich Albrecht | fd5c5d22d1 | |
Kai Germaschewski | 2b25ca2dd0 | |
Armin Schindler | 87a7ba0fa2 | |
Armin Schindler | 11baceac41 | |
Karsten Keil | 686c8687c9 | |
Armin Schindler | 5573cae6a9 | |
Armin Schindler | 95ad8107ba | |
Kai Germaschewski | 24a4a2538b | |
Carsten Paeth | 21e841aafa | |
Carsten Paeth | 3a95edaeec | |
Kai Germaschewski | 834d66319f | |
Kai Germaschewski | 5327184e9d | |
Kai Germaschewski | 841f2d9bf4 | |
Kai Germaschewski | 15696b18a0 | |
Carsten Paeth | 18a3ebaa1f | |
Armin Schindler | 016469efaa | |
Detlef Wengorz | 2f5d09601d | |
Werner Cornelius | 4662632e5b | |
Karsten Keil | 8774c83748 | |
Kai Germaschewski | 553df5cb4e | |
Werner Cornelius | a2d07d28b6 | |
Kai Germaschewski | 84da742773 | |
Kai Germaschewski | 92fedf78ea | |
Kai Germaschewski | 18d43861d0 | |
Armin Schindler | 6b5088dacc | |
Armin Schindler | 355e243418 | |
Kai Germaschewski | 57ac7b3275 | |
Kai Germaschewski | 658b751b34 | |
Kai Germaschewski | f120a52b93 | |
Kai Germaschewski | 8f5a6cd114 | |
Werner Cornelius | 18f63bdba9 | |
Armin Schindler | 5dafc5b63a | |
Kai Germaschewski | cddc0e23e1 | |
Werner Cornelius | 93d8811892 | |
Kai Germaschewski | c853347a04 | |
Kai Germaschewski | 457078cc3f | |
Kai Germaschewski | 4322c46164 | |
Kai Germaschewski | 0b414d1641 | |
Kai Germaschewski | ed8fcc4e6d | |
Kai Germaschewski | df0bf3c658 | |
Kai Germaschewski | b5accabbd3 | |
Kai Germaschewski | 464a93efad | |
Kai Germaschewski | 8c6c17493c | |
Kai Germaschewski | cfeb228cc5 | |
Werner Cornelius | 8ad67f8f6b | |
Kai Germaschewski | 3baa300757 | |
Kai Germaschewski | ac3689287b | |
Kai Germaschewski | 4a6fbad3ec | |
Kai Germaschewski | 8216b0d1ff | |
Kai Germaschewski | e372200e90 | |
Kai Germaschewski | 5289ece6e7 | |
Carsten Paeth | 0807f87ce6 | |
Kai Germaschewski | 323a78023d | |
Kai Germaschewski | c3b6ae8436 | |
Kai Germaschewski | 52afc6ea61 | |
Kai Germaschewski | d404264552 | |
Kai Germaschewski | 7dfb5916d0 | |
Kai Germaschewski | 05732ea78e | |
Kai Germaschewski | d68b25f279 | |
Kai Germaschewski | 75dd636457 | |
Kai Germaschewski | c63391e1ab | |
Kai Germaschewski | dfdcedb1af | |
Kai Germaschewski | 69e4e1b52a | |
Kai Germaschewski | d37916e1ae | |
Kai Germaschewski | d64f7e03d3 | |
Kai Germaschewski | 9f253b957c | |
Kai Germaschewski | 31432e7bd7 | |
Kai Germaschewski | 0c7ae2f941 | |
Kai Germaschewski | 9957cbef2c | |
Kai Germaschewski | 599511592d | |
Kai Germaschewski | cb12a3862b | |
Kai Germaschewski | a0f9eace40 | |
Kai Germaschewski | ca7c105d3f | |
Kai Germaschewski | 1a4d53db2f | |
Kai Germaschewski | a942b3cb0e | |
Kai Germaschewski | 974cd58b9a | |
Karsten Keil | 87fc7fb493 | |
Karsten Keil | 5164c2014e | |
Karsten Keil | de7ad8be4d | |
Karsten Keil | e0428a5d6b | |
Karsten Keil | 5f3afeeb32 | |
Karsten Keil | 5817d0d2e1 | |
Karsten Keil | 1b792b177e | |
Karsten Keil | bf71ea570a | |
Carsten Paeth | 134a3fcff2 | |
Kai Germaschewski | 8f9ff57a6d | |
Kai Germaschewski | 6cb6a3e3f9 | |
Kai Germaschewski | 45daefbcc7 | |
Kai Germaschewski | 464065fad2 | |
Kai Germaschewski | 354adc90f6 | |
Kai Germaschewski | f979c1535c | |
Kai Germaschewski | fa6653235e | |
Kai Germaschewski | 8c6a396304 | |
Detlef Wengorz | fb22ff5ceb | |
Detlef Wengorz | 059c34cf0c | |
Kai Germaschewski | a99a22cfac | |
Carsten Paeth | e89ba68f87 | |
Carsten Paeth | 974aabdb12 | |
Kai Germaschewski | cc3077b26e | |
Detlef Wengorz | fc10f79d69 | |
Carsten Paeth | e346262860 | |
Carsten Paeth | 02d57b89c8 | |
Olaf Stoyke | 19932ef38a | |
Olaf Stoyke | ddc1719fe9 | |
Olaf Stoyke | 3e10ab3581 | |
Carsten Paeth | c6835e540e | |
Kai Germaschewski | cce70b04bd | |
Detlef Wengorz | f5f22ceaae | |
Karsten Keil | 4c3304e07b | |
Paul Slootman | 0d448fd90b | |
Karsten Keil | 7ed89938e8 | |
Kai Germaschewski | 515f552555 | |
Armin Schindler | d92cee6b06 | |
Detlef Wengorz | ad87b5f637 | |
Werner Cornelius | 82cf44d24b | |
Werner Cornelius | 2bfd2e6d27 | |
Werner Cornelius | 332f0a167f | |
Armin Schindler | 5178acdda6 | |
Armin Schindler | fcb5c09a73 | |
Armin Schindler | be6159b8b4 | |
Armin Schindler | 87a64c35b9 | |
Armin Schindler | 2b10490472 | |
Armin Schindler | 06a0c7ce8d | |
Carsten Paeth | d469954416 | |
Karsten Keil | d6a3779566 | |
Karsten Keil | fc9cf85ef8 | |
Karsten Keil | 1abb46af72 | |
Karsten Keil | 5ba4067be9 | |
Karsten Keil | be992a3718 | |
Karsten Keil | 1586cc119e | |
Karsten Keil | 8d0bcedb83 | |
Karsten Keil | 7e40a07ed5 | |
Karsten Keil | e738bab3c4 | |
Armin Schindler | 9280a659cd | |
Armin Schindler | e485318794 | |
Armin Schindler | b89e76688e | |
Armin Schindler | 5affd1c32d | |
Armin Schindler | 22e38fe1bf | |
Kai Germaschewski | fdbd010ff3 | |
Kai Germaschewski | 755193f764 | |
Olaf Stoyke | 9b100d87ae | |
Olaf Stoyke | b0b55c3cf5 | |
Olaf Stoyke | 80886101d9 | |
Carsten Paeth | aeffee33b5 | |
Armin Schindler | 13600f5366 | |
Armin Schindler | 900701e406 | |
Carsten Paeth | d9e55b323a | |
Carsten Paeth | c16aca6071 | |
Carsten Paeth | 9b7acb5037 | |
Karsten Keil | 97d29143ae | |
Ulrich Albrecht | 8a5db16785 | |
Carsten Paeth | fba9a03d51 | |
Carsten Paeth | 9da5835515 | |
Carsten Paeth | a6c70f5202 | |
Carsten Paeth | 7da95bec2d | |
Carsten Paeth | 7f3246fe5b | |
Armin Schindler | 094b5f4603 | |
Armin Schindler | ab98e65b07 | |
Armin Schindler | 0c0f3bafe4 | |
Karsten Keil | f720acb42b | |
Carsten Paeth | 94f9feac24 | |
Carsten Paeth | a8fae58846 | |
Karsten Keil | d73a20a8da | |
Karsten Keil | c3ad1dd1cc | |
Karsten Keil | 843b1753b8 | |
Karsten Keil | c8b8c616a5 | |
Karsten Keil | 6e297bb8e6 | |
Karsten Keil | da97602862 | |
Karsten Keil | 393062192c | |
Karsten Keil | 5347736a35 | |
Armin Schindler | ad930e7ecb | |
Karsten Keil | 26dcbf70f4 | |
Karsten Keil | f1375b15ea | |
Karsten Keil | 74e0a50e2f | |
Karsten Keil | c51f9fc84b | |
Karsten Keil | 5a92d32d89 | |
Karsten Keil | 11fd40671f | |
Karsten Keil | 0fc55a091b | |
Karsten Keil | 406eb472b2 | |
Karsten Keil | 2ba264c176 | |
Karsten Keil | 1967246b7e | |
Karsten Keil | aadbf2fd78 | |
Karsten Keil | 8b2807c0c1 | |
Carsten Paeth | 398beb385c | |
Karsten Keil | b42db20c18 | |
Karsten Keil | ffbb12023e | |
Karsten Keil | 67115c4282 | |
Karsten Keil | 907df89fa6 | |
Karsten Keil | 7b312bc61b | |
Karsten Keil | fd1c87e173 | |
Karsten Keil | fe43d8cb58 | |
Armin Schindler | e36f65fb3c | |
Karsten Keil | 606d0ce2b3 | |
Karsten Keil | 5fec73fd33 | |
Karsten Keil | 80d4c78303 | |
Karsten Keil | b50a8d6c58 | |
Karsten Keil | 1e8aae60f0 | |
Karsten Keil | b4139fe973 | |
Karsten Keil | d9b4df592a | |
Karsten Keil | 2e37e520c3 | |
Karsten Keil | f38f18f38c | |
Karsten Keil | 8798cbd5af | |
Karsten Keil | 4acd613f9e | |
Karsten Keil | 954825b49b | |
Karsten Keil | 449fa25ed3 | |
Karsten Keil | 9605b12e8f | |
Ulrich Albrecht | a3447f58d2 | |
Ulrich Albrecht | 09f8e15696 | |
Ulrich Albrecht | 6684ed45e0 | |
Karsten Keil | 14da8b0ab1 | |
Armin Schindler | 3835fcfa6c | |
Armin Schindler | 06bbbc0e32 | |
Armin Schindler | 3b3c83c05f | |
Kai Germaschewski | 6c2f52aaed | |
Kai Germaschewski | 0e0046a758 | |
Kai Germaschewski | de0194bbc8 | |
Kai Germaschewski | 48cc1f988e | |
Armin Schindler | eae9986f04 | |
Kai Germaschewski | eeaba88443 | |
Armin Schindler | 444080450d | |
Armin Schindler | e681a3fc86 | |
Detlef Wengorz | 5aeb1161d6 | |
Detlef Wengorz | 80e1f22d93 | |
Karsten Keil | 35e0fdcb77 | |
Karsten Keil | 160599cc64 | |
Karsten Keil | 54fed61e91 | |
Karsten Keil | 4ff4b97416 | |
Karsten Keil | 08a8e0bd1c | |
Karsten Keil | 24a9866cf0 | |
Karsten Keil | 7e23ea5bee | |
Ulrich Albrecht | fc43e6389b | |
Ulrich Albrecht | 8921d2c7d9 | |
Ulrich Albrecht | fa1875145b | |
Armin Schindler | 74ed9373c9 | |
Karsten Keil | 7c6d5ae19a | |
Karsten Keil | 18db97b00a | |
Karsten Keil | 52f509f83b | |
Karsten Keil | 17b44ed7a1 | |
Carsten Paeth | f8231d1c15 | |
Karsten Keil | 465c72a343 | |
Carsten Paeth | b0e1f0019f | |
Ulrich Albrecht | 77d30ae3c3 | |
Ulrich Albrecht | f1bb4ec7f3 | |
Ulrich Albrecht | 19995602cf | |
Ulrich Albrecht | 65b90b66ff | |
Ulrich Albrecht | 50247a03fd | |
Karsten Keil | 4c8eeec66c | |
Karsten Keil | 0525ffa44d | |
Karsten Keil | d6da4a3374 | |
Karsten Keil | 3daf2bf3f6 | |
Kai Germaschewski | 3c40de9658 | |
Armin Schindler | b380e325dc | |
Kai Germaschewski | 7f5ba93f21 | |
Karsten Keil | 12bbd4eea8 | |
Karsten Keil | 08a5b82b93 | |
Armin Schindler | 9e2d2a82fa | |
Kai Germaschewski | 25fde20769 | |
Carsten Paeth | ac727efe2d | |
Carsten Paeth | 22eb62c099 | |
Carsten Paeth | 177623b836 | |
Karsten Keil | 4ca61103a2 | |
Karsten Keil | 37d344cc1d | |
Kai Germaschewski | a4c02dd38d | |
Karsten Keil | 71ce6b5be4 | |
Karsten Keil | 60f0764d01 | |
Karsten Keil | d58c8c0188 | |
Armin Schindler | cba7e6d378 | |
Carsten Paeth | 0a5aa29b11 | |
Carsten Paeth | 9cdecfcbcb | |
Carsten Paeth | fdc54378fe | |
Armin Schindler | 8b747f9b1f | |
Carsten Paeth | 5f8dd069ce | |
Detlef Wengorz | fafbf7d96f | |
Detlef Wengorz | ebdaa8c5b5 | |
Kai Germaschewski | 89ec768bf8 | |
Carsten Paeth | 714a4d6482 | |
Carsten Paeth | 64753ae814 | |
Carsten Paeth | ecc76e2349 | |
Armin Schindler | aafb2b7e76 | |
Armin Schindler | b1f8ecfea7 | |
Armin Schindler | 390db3a46d | |
Kai Germaschewski | c86c3637cb | |
Detlef Wengorz | 50c3eea967 | |
Kai Germaschewski | 2cf873e4a2 | |
Kai Germaschewski | 1ea93bb122 | |
Detlef Wengorz | de9aef0045 | |
Kai Germaschewski | 163a1f20d3 | |
Kai Germaschewski | 15e7682f1b | |
Carsten Paeth | 126be487cf | |
Kai Germaschewski | 0ac93e1484 | |
Kai Germaschewski | 20b601d4f2 | |
Kai Germaschewski | 76aa55904e | |
Kai Germaschewski | 0ae6bc1923 | |
Kai Germaschewski | 970c99e55b | |
Kai Germaschewski | eb9393dd8d | |
Kai Germaschewski | eb13d25d81 | |
Carsten Paeth | 10f9c57517 | |
Carsten Paeth | 06fe2c8d3c | |
Kai Germaschewski | 748d718685 | |
Kai Germaschewski | 6af1d2d4fe | |
Werner Cornelius | 5ee13e2749 | |
Werner Cornelius | d693b4790f | |
Kai Germaschewski | 93ae560439 | |
Kai Germaschewski | 76824fd61f | |
Kai Germaschewski | d4564c64a0 | |
Carsten Paeth | 7e3431614d | |
Carsten Paeth | e103e143d0 | |
Carsten Paeth | 3ea1695777 | |
Carsten Paeth | 1893040935 | |
Carsten Paeth | ba3d40acf1 | |
Carsten Paeth | 31c5aa1fcb | |
Armin Schindler | fc0a456c2b | |
Armin Schindler | c21c174ada | |
Carsten Paeth | 0402c2d424 | |
Armin Schindler | 0c335333cc | |
Detlef Wengorz | 00071128e4 | |
Carsten Paeth | 189065cec0 | |
Kai Germaschewski | ae7e6db007 | |
Carsten Paeth | 7fe092d9a5 |
|
@ -1,6 +1,6 @@
|
|||
--- Configure.help.orig Wed Dec 15 20:35:10 1999
|
||||
+++ Configure.help Wed Dec 15 20:35:33 1999
|
||||
@@ -11317,6 +11317,172 @@
|
||||
--- /usr/src/linux/Documentation/Configure.help Sat Mar 25 09:22:49 2000
|
||||
+++ Configure.help Sat Mar 25 09:29:13 2000
|
||||
@@ -12738,6 +12738,160 @@
|
||||
|
||||
Please read the file Documentation/isdn/README.diversion.
|
||||
|
||||
|
@ -141,18 +141,6 @@
|
|||
+ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
|
||||
+ for more Information
|
||||
+
|
||||
+Limit on the line frames to two
|
||||
+CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
|
||||
+
|
||||
+ This Option enables support for sending only 2 Pakets on
|
||||
+ the Fly to the ISDN Driver. It is very usefull when you
|
||||
+ will use the new RAW-IP Compression. Because of sending
|
||||
+ Only 2 Pakets on the Fly makes the risk of overflowing
|
||||
+ the ISDN Driver very smaller.
|
||||
+
|
||||
+ See "linux/Documentation/isdn/dw-abc-extension-howto.txt"
|
||||
+ for more Information
|
||||
+
|
||||
+Compression with RAWIP and X75I
|
||||
+CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
|
||||
+
|
||||
|
|
|
@ -31,7 +31,7 @@ README.act2000
|
|||
README.eicon
|
||||
- info on driver for Eicon active cards.
|
||||
README.concap
|
||||
- info on "CONCAP" ecapsulation protocol interface used for X.25.
|
||||
- info on "CONCAP" encapsulation protocol interface used for X.25.
|
||||
README.diversion
|
||||
- info on module for isdn diversion services.
|
||||
README.sc
|
||||
|
@ -40,4 +40,4 @@ README.x25
|
|||
_ info for running X.25 over ISDN.
|
||||
README.hysdn
|
||||
- info on driver for Hypercope active HYSDN cards
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,23 @@ The certification is only valid for the combination of the tested software
|
|||
version and the tested hardware. Any changes to the HiSax source code may
|
||||
therefore affect the certification.
|
||||
|
||||
Additional ITU approval tests have been carried out for all generic cards
|
||||
using Colognechip single chip solutions HFC-S PCI A for PCI cards as well
|
||||
as HFC-S USB based USB ISDN ta adapters.
|
||||
These tests included all layers 1-3 and as well all functional tests for
|
||||
the layer 1. Because all hardware based on these chips are complete ISDN
|
||||
solutions in one chip all cards and USB-TAs using these chips are to be
|
||||
regarded as approved for those tests. Some additional electrical tests
|
||||
of the layer 1 which are independant of the driver and related to a
|
||||
special hardware used will be regarded as approved if at least one
|
||||
solution has been tested including those electrical tests. So if cards
|
||||
or tas have been completely approved for any other os, the approval
|
||||
for those electrical tests is valid for linux, too.
|
||||
Please send any questions regarding this drivers or approval abouts to
|
||||
werner@isdn-development.de
|
||||
Additional information and the type approval documents will be found
|
||||
shortly on the Colognechip website www.colognechip.com
|
||||
|
||||
If you change the main files of the HiSax ISDN stack, the certification will
|
||||
become invalid. Because in most countries it is illegal to connect
|
||||
unapproved ISDN equipment to the public network, I have to guarantee that
|
||||
|
@ -50,6 +67,9 @@ drivers/isdn/hisax/l3_1tr6.c
|
|||
drivers/isdn/hisax/cert.c
|
||||
drivers/isdn/hisax/elsa.c
|
||||
drivers/isdn/hisax/diva.c
|
||||
drivers/isdn/hisax/hfc_pci.c
|
||||
drivers/isdn/hisax/hfc_usbr.c
|
||||
drivers/isdn/hisax/hfc_usb.c
|
||||
|
||||
Please send any changes, bugfixes and patches to me rather than implementing
|
||||
them directly into the HiSax sources.
|
||||
|
|
|
@ -399,7 +399,7 @@ Description of the Interface between Linklevel and Hardwarelevel
|
|||
protocol-Id is one of the constants ISDN_PROTO_L3...
|
||||
parm.fax = Pointer to T30_s fax struct. (fax usage only)
|
||||
|
||||
ISDN_CMD_GETL2: (currently unused)
|
||||
ISDN_CMD_GETL3: (currently unused)
|
||||
|
||||
With this command, the HL-driver is told to return the current
|
||||
setting of the Layer-3-protocol.
|
||||
|
@ -480,8 +480,8 @@ Description of the Interface between Linklevel and Hardwarelevel
|
|||
Parameter:
|
||||
driver = driver-Id
|
||||
command = ISDN_CMD_PROT_IO
|
||||
arg = The lower 8 Bits define the adressed protocol as defined
|
||||
in ISDN_PTYPE..., the upper bits are used to differenciate
|
||||
arg = The lower 8 Bits define the addressed protocol as defined
|
||||
in ISDN_PTYPE..., the upper bits are used to differentiate
|
||||
the protocol specific CMD.
|
||||
|
||||
para = protocol and function specific. See isdnif.h for detail.
|
||||
|
@ -734,7 +734,7 @@ Description of the Interface between Linklevel and Hardwarelevel
|
|||
Parameter:
|
||||
driver = driver-Id
|
||||
command = ISDN_STAT_PROT
|
||||
arg = The lower 8 Bits define the adressed protocol as defined
|
||||
arg = The lower 8 Bits define the addressed protocol as defined
|
||||
in ISDN_PTYPE..., the upper bits are used to differenciate
|
||||
the protocol specific STAT.
|
||||
|
||||
|
@ -748,7 +748,7 @@ Description of the Interface between Linklevel and Hardwarelevel
|
|||
loading the driver. The LL has to ignore a disabled channel when searching
|
||||
for free channels. The HL driver itself never delivers STAT callbacks for
|
||||
disabled channels.
|
||||
The LL returns a nonzero code if the operation was not successfull or the
|
||||
The LL returns a nonzero code if the operation was not successful or the
|
||||
selected channel is actually regarded as busy.
|
||||
|
||||
Parameter:
|
||||
|
@ -781,3 +781,22 @@ Description of the Interface between Linklevel and Hardwarelevel
|
|||
arg = channel-number, locally to the driver. (starting with 0)
|
||||
parm = unused.
|
||||
|
||||
ISDN_STAT_ALERT:
|
||||
|
||||
With this call, the HL-driver signals the receive of an ALERTING message to the LL.
|
||||
|
||||
Parameter:
|
||||
driver = driver-Id
|
||||
command = ISDN_STAT_ALERT
|
||||
arg = channel-number, locally to the driver. (starting with 0)
|
||||
|
||||
ISDN_STAT_PROCEED:
|
||||
|
||||
With this call, the HL-driver signals the receive of an CALL PROCEEDING message
|
||||
to the LL.
|
||||
|
||||
Parameter:
|
||||
driver = driver-Id
|
||||
command = ISDN_STAT_PROCEED
|
||||
arg = channel-number, locally to the driver. (starting with 0)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ $Id$
|
|||
Description of the fax-subinterface between linklevel and hardwarelevel of
|
||||
isdn4linux.
|
||||
|
||||
The communication between linklevel (LL) and harwarelevel (HL) for fax
|
||||
The communication between linklevel (LL) and hardwarelevel (HL) for fax
|
||||
is based on the struct T30_s (defined in isdnif.h).
|
||||
This struct is allocated in the LL.
|
||||
In order to use fax, the LL provides the pointer to this struct with the
|
||||
|
@ -60,7 +60,7 @@ Structure T30_s:
|
|||
depending on progress and type of connection.
|
||||
If the phase changes because of an AT command, the LL driver
|
||||
changes this value. Otherwise the HL-driver takes care of it, but
|
||||
only neccessary on call establishment (from IDLE to PHASE_A).
|
||||
only necessary on call establishment (from IDLE to PHASE_A).
|
||||
(one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E])
|
||||
|
||||
- direction
|
||||
|
|
|
@ -146,7 +146,7 @@ README for the ISDN-subsystem
|
|||
x = 38400: 198
|
||||
Note on value in Reg 19:
|
||||
There is _NO_ common convention for 38400 baud.
|
||||
The value 198 is choosen arbitrarily. Users
|
||||
The value 198 is chosen arbitrarily. Users
|
||||
_MUST_ negotiate this value before establishing
|
||||
a connection.
|
||||
AT&Sx Set window-size (x = 1..8) (not yet implemented)
|
||||
|
@ -242,7 +242,7 @@ README for the ISDN-subsystem
|
|||
0 = transparent
|
||||
1 = transparent with audio features (e.g. DSP)
|
||||
2 = Fax G3 Class 2 commands (S14 has to be set to 11)
|
||||
2 = Fax G3 Class 1 commands (S14 has to be set to 11)
|
||||
3 = Fax G3 Class 1 commands (S14 has to be set to 11)
|
||||
16 250 Send-Packet-size/16
|
||||
17 8 Window-size (not yet implemented)
|
||||
18 4 Bit coded register, Service-Octet-1 to accept,
|
||||
|
@ -276,6 +276,14 @@ README for the ISDN-subsystem
|
|||
1 = Add CPN to RING message on
|
||||
Bit 1: 0 = Add CPN to FCON message off
|
||||
1 = Add CPN to FCON message on
|
||||
Bit 2: 0 = Add CDN to RING/FCON message off
|
||||
1 = Add CDN to RING/FCON message on
|
||||
Bit 3: 0 = Do not signal RINGING
|
||||
1 = Signal RINGING if ALERT was received
|
||||
Bit 4: 0 = Do not signal PROCEEDING
|
||||
1 = Signal PROCEEDING if CALL PROCEEDING
|
||||
was received
|
||||
|
||||
|
||||
Last but not least a (at the moment fairly primitive) device to request
|
||||
the line-status (/dev/isdninfo) is made available.
|
||||
|
|
|
@ -53,7 +53,8 @@ Sedlbauer Speed Star/Speed Star2 (PCMCIA)
|
|||
Sedlbauer ISDN-Controller PC/104
|
||||
USR Sportster internal TA (compatible Stollmann tina-pp V3)
|
||||
ith Kommunikationstechnik GmbH MIC 16 ISA card
|
||||
Traverse Technologie NETjet PCI S0 card
|
||||
Traverse Technologie NETjet PCI S0 card and NETspider U card
|
||||
Ovislink ISDN sc100-p card (NETjet driver)
|
||||
Dr. Neuhaus Niccy PnP/PCI
|
||||
Siemens I-Surf 1.0
|
||||
Siemens I-Surf 2.0 (with IPAC, try type 12 asuscom)
|
||||
|
@ -65,19 +66,15 @@ Gazel ISDN cards
|
|||
HFC-PCI based cards
|
||||
Winbond W6692 based cards
|
||||
HFC-S+, HFC-SP/PCMCIA cards
|
||||
HFC-USB ISDN TAs
|
||||
|
||||
Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
|
||||
PCC-8: not tested yet
|
||||
Teles PCMCIA is EXPERIMENTAL
|
||||
Teles 16.3c is EXPERIMENTAL
|
||||
Teles PCI is EXPERIMENTAL
|
||||
Teles S0Box is EXPERIMENTAL
|
||||
Eicon.Diehl Diva U interface not tested
|
||||
HFC-S+, HFC-SP/PCMCIA are experimental
|
||||
|
||||
If you know other passive cards with the Siemens chipset, please let me know.
|
||||
To use the PNP cards you need the isapnptools.
|
||||
You can combine any card, if there is no conflict between the ressources
|
||||
You can combine any card, if there is no conflict between the resources
|
||||
(io, mem, irq).
|
||||
|
||||
|
||||
|
@ -134,7 +131,12 @@ mem=,0xd0000. See example 6 below.
|
|||
|
||||
The parameter for the D-Channel protocol may be omitted if you selected the
|
||||
correct one during kernel config. Valid values are "1" for German 1TR6,
|
||||
"2" for EDSS1 (Euro ISDN) and "3" for leased lines (no D-Channel).
|
||||
"2" for EDSS1 (Euro ISDN), "3" for leased lines (no D-Channel) and "4"
|
||||
for US NI1.
|
||||
With US NI1 you have to include your SPID into the MSN setting in the form
|
||||
<MSN>:<SPID> for example (your phonenumber is 1234 your SPID 5678):
|
||||
AT&E1234:5678 on ttyI interfaces
|
||||
isdnctrl eaz ippp0 1234:5678 on network devices
|
||||
|
||||
The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying
|
||||
the I/O addresses of the ISAC and HSCX chips, respectively.
|
||||
|
@ -186,8 +188,9 @@ Card types:
|
|||
34 Gazel ISDN cards (PCI) none
|
||||
35 HFC 2BDS0 PCI none
|
||||
36 W6692 based PCI cards none
|
||||
37 HFC 2BDS0 S+, SP/PCMCIA irq,io (pcmcia must be set with cardmgr)
|
||||
|
||||
37 HFC 2BDS0 S+, SP irq,io
|
||||
38 NETspider U PCI card none
|
||||
39 HFC 2BDS0 SP/PCMCIA irq,io (set with cardmgr)
|
||||
|
||||
At the moment IRQ sharing is only possible with PCI cards. Please make sure
|
||||
that your IRQ is free and enabled for ISA use.
|
||||
|
@ -291,7 +294,9 @@ type
|
|||
34 Gazel ISDN cards (PCI) no parameter
|
||||
35 HFC 2BDS0 PCI no parameter
|
||||
36 W6692 based PCI cards none
|
||||
37 HFC 2BDS0 S+,SP/PCMCIA pa=irq, pb=io
|
||||
37 HFC 2BDS0 S+,SP/PCMCIA ONLY WORKS AS A MODULE !
|
||||
38 NETspider U PCI card none
|
||||
|
||||
|
||||
Running the driver
|
||||
------------------
|
||||
|
@ -433,6 +438,7 @@ Special thanks to:
|
|||
Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff
|
||||
Ton van Rosmalen for Teles PCI
|
||||
Petr Novak <petr.novak@i.cz> for Winbond W6692 support
|
||||
Werner Cornelius <werner@isdn4linux.de> for HFC-PCI, HFC-S(+/P) and supplementary services support
|
||||
and more people who are hunting bugs. (If I forgot somebody, please
|
||||
send me a mail).
|
||||
|
||||
|
@ -532,7 +538,7 @@ to e.g. the Internet:
|
|||
/sbin/isdnctrl huptimeout isdn0 0
|
||||
/sbin/isdnctrl l2_prot isdn0 hdlc
|
||||
# Attention you must not set an outgoing number !!! This won't work !!!
|
||||
# The incomming number is LEASED0 for the first card, LEASED1 for the
|
||||
# The incoming number is LEASED0 for the first card, LEASED1 for the
|
||||
# second and so on.
|
||||
/sbin/isdnctrl addphone isdn0 in LEASED0
|
||||
# Here is no need to bind the channel.
|
||||
|
@ -551,7 +557,7 @@ a) Use state of the art isdn4k-utils
|
|||
|
||||
Here an example script:
|
||||
#!/bin/sh
|
||||
# Start/Stop ISDN lesaed line connection
|
||||
# Start/Stop ISDN leased line connection
|
||||
|
||||
I4L_AS_MODULE=yes
|
||||
I4L_REMOTE_IS_CISCO=no
|
||||
|
|
|
@ -7,7 +7,7 @@ There are 3 Types of this card available. A ISA-, MCA-, and PCMCIA-Bus
|
|||
Version. Currently, only the ISA-Bus version of the card is supported.
|
||||
However MCA and PCMCIA will follow soon.
|
||||
|
||||
The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set
|
||||
The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
|
||||
manually using the DIP switches.
|
||||
|
||||
Setting up the DIP switches for the IBM Active 2000 ISDN card:
|
||||
|
|
|
@ -175,7 +175,7 @@ a mail to majordomo@calle.in-berlin.de with
|
|||
subscribe linux-avmb1
|
||||
in the body.
|
||||
|
||||
German documentaion and several scripts can be found at
|
||||
German documentation and several scripts can be found at
|
||||
ftp://ftp.avm.de/cardware/b1/linux/
|
||||
|
||||
Bugs
|
||||
|
|
|
@ -68,7 +68,7 @@ increased.
|
|||
Likewise, a similar encapsulation protocol will frequently be needed by
|
||||
several different interfaces of even different hardware type, e.g. the
|
||||
synchronous ppp implementation used by the isdn driver and the
|
||||
asyncronous ppp implementation used by the ppp driver have a lot of
|
||||
asynchronous ppp implementation used by the ppp driver have a lot of
|
||||
similar code in them. By cleanly separating the encapsulation protocol
|
||||
from the hardware specific interface stuff such code could be shared
|
||||
better in future.
|
||||
|
|
|
@ -6,7 +6,7 @@ document. The diversion services may be used with all cards supported by
|
|||
the HiSax driver.
|
||||
The diversion kernel interface and controlling tool divertctrl were written
|
||||
by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) under the
|
||||
GNU Public License.
|
||||
GNU General Public License.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -57,7 +57,7 @@ Table of contents
|
|||
compared to the mechanism of ipfwadm or ipchains. If a given rule matches
|
||||
the checking process is finished and the rule matching will be applied
|
||||
to the call.
|
||||
The rules include primary and secondary service indentifiers, called
|
||||
The rules include primary and secondary service identifiers, called
|
||||
number and subaddress, callers number and subaddress and whether the rule
|
||||
matches to all filtered calls or only those when all B-channel resources
|
||||
are exhausted.
|
||||
|
@ -82,7 +82,7 @@ Table of contents
|
|||
available in some countries (for example germany). Countries requiring the
|
||||
keypad protocol for activating static diversions (like the netherlands) are
|
||||
not supported but may use the tty devices for this purpose.
|
||||
The dynamic diversion servives may be used in all countries if the provider
|
||||
The dynamic diversion services may be used in all countries if the provider
|
||||
enables the feature CF (call forwarding). This should work on both MSN- and
|
||||
point-to-point lines.
|
||||
To add and delete rules the additional divertctrl program is needed. This
|
||||
|
|
|
@ -40,6 +40,7 @@ DIVA Server family
|
|||
------------------
|
||||
- DIVA Server BRI/PCI 2M
|
||||
- DIVA Server PRI/PCI 2M (9M 23M 30M)
|
||||
- DIVA Server 4BRI/PCI
|
||||
supported functions of onboard DSPs:
|
||||
- analog modem
|
||||
- fax group 2/3 (Fax Class 2 commands)
|
||||
|
@ -78,6 +79,10 @@ Example for loading and starting a BRI card with E-DSS1 Protocol.
|
|||
|
||||
eiconctrl [-d DriverId] load etsi
|
||||
|
||||
Example for a BRI card with E-DSS1 Protocol with PtP configuration.
|
||||
|
||||
eiconctrl [-d DriverId] load etsi -n -t1 -s1
|
||||
|
||||
|
||||
Example for loading and starting a PRI card with E-DSS1 Protocol.
|
||||
|
||||
|
@ -95,6 +100,7 @@ Just use "eiconctrl isdnlog on" and the driver will generate
|
|||
the necessary D-Channel traces for isdnlog.
|
||||
|
||||
|
||||
|
||||
Thanks to
|
||||
Deutsche Mailbox Saar-Lor-Lux GmbH
|
||||
for sponsoring and testing fax
|
||||
|
@ -109,3 +115,4 @@ Have fun !
|
|||
Armin Schindler
|
||||
mac@melware.de
|
||||
http://www.melware.de
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@ Supported ISDN-Cards
|
|||
Eicon DIVA Server BRI/PCI
|
||||
- full support with both B-channels.
|
||||
|
||||
Eicon DIVA Server 4BRI/PCI
|
||||
- full support with all B-channels.
|
||||
|
||||
Eicon DIVA Server PRI/PCI
|
||||
- full support on amount of B-channels
|
||||
depending on DSPs on board.
|
||||
|
|
|
@ -35,7 +35,7 @@ If the io parameter is used the io addresses of all used cards should be
|
|||
supplied else the parameter is assumed 0 and a auto search for a free card is
|
||||
invoked which may not give the wanted result.
|
||||
|
||||
Comments and reports to werner@isdn4linux.de or werner@titro.de .
|
||||
Comments and reports to werner@isdn4linux.de or werner@isdn-development.de
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@ $Id$
|
|||
The hysdn driver has been written by
|
||||
by Werner Cornelius (werner@isdn4linux.de or werner@titro.de)
|
||||
for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver
|
||||
under the GNU Public License.
|
||||
under the GNU General Public License.
|
||||
|
||||
The CAPI 2.0-support was added by Ulrich Albrecht (ualbrecht@hypercope.de)
|
||||
for Hypercope GmbH Aachen, Germany.
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -41,15 +45,19 @@ Table of contents
|
|||
enable ISDN support in the kernel config and support for HYSDN cards in
|
||||
the active cards submenu. The driver may only be compiled and used if
|
||||
support for loadable modules and the process filesystem have been enabled.
|
||||
No other ISDN options need to be enabled for these cards.
|
||||
|
||||
Up to now these cards do not use or require the standard isdn interface
|
||||
module (isdn.o), but registers itself as an ethernet card. All necessary
|
||||
These cards provide two different interfaces to the kernel. Without the
|
||||
optional CAPI 2.0 support, they register as ethernet card. IP-routing
|
||||
to a ISDN-destination is performed on the card itself. All necessary
|
||||
handlers for various protocols like ppp and others as well as config info
|
||||
and firmware may be fetched from Hypercopes WWW-Site www.hypercope.de.
|
||||
The driver has been included in the i4l tree as a CAPI compliant module
|
||||
is under development and will be connected to the standard i4l modules
|
||||
additionally.
|
||||
|
||||
With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0
|
||||
compliant devices with either CAPI 2.0 applications
|
||||
(check isdn4k-utils) or -using the capidrv module- as a regular
|
||||
isdn4linux device. This is done via the same mechanism as with the
|
||||
active AVM cards and in fact uses the same module.
|
||||
|
||||
|
||||
2. Loading/Unloading the driver
|
||||
|
||||
|
@ -58,7 +66,14 @@ Table of contents
|
|||
If a loaded driver shall be unloaded all open files in the /proc/net/hysdn
|
||||
subdir need to be closed and all ethernet interfaces allocated by this
|
||||
driver must be shut down. Otherwise the module counter will avoid a module
|
||||
unload.
|
||||
unload.
|
||||
|
||||
If you are using the CAPI 2.0-interface, make sure to load/modprobe the
|
||||
kernelcapi-module first.
|
||||
|
||||
If you plan to use the capidrv-link to isdn4linux, make sure to load
|
||||
capidrv.o after all modules using this driver (i.e. after hysdn and
|
||||
any avm-specific modules).
|
||||
|
||||
3. Entries in the /proc filesystem
|
||||
|
||||
|
@ -92,7 +107,7 @@ Table of contents
|
|||
3 -> card is booted and active
|
||||
|
||||
And the last field (device) shows the name of the ethernet device assigned
|
||||
to this card. Up to the first successfull boot this field only shows a -
|
||||
to this card. Up to the first successful boot this field only shows a -
|
||||
to tell that no net device has been allocated up to now. Once a net device
|
||||
has been allocated it remains assigned to this card, even if a card is
|
||||
rebooted and an boot error occurs.
|
||||
|
@ -128,12 +143,12 @@ Table of contents
|
|||
get the cards and drivers log data. Card messages always start with the
|
||||
keyword LOG. All other lines are output from the driver.
|
||||
The driver log data may be redirected to the syslog by selecting the
|
||||
approriate bitmask. The cards log messages will always be send to this
|
||||
appropriate bitmask. The cards log messages will always be send to this
|
||||
interface but never to the syslog.
|
||||
|
||||
A root user may write a decimal or hex (with 0x) value t this file to select
|
||||
desired output options. As mentioned above the cards log dat is always
|
||||
written to the cardlog file independant of the following options only used
|
||||
written to the cardlog file independent of the following options only used
|
||||
to check and debug the driver itself:
|
||||
|
||||
For example:
|
||||
|
@ -160,8 +175,11 @@ Table of contents
|
|||
6. Where to get additional info and help
|
||||
|
||||
If you have any problems concerning the driver or configuration contact
|
||||
the Hypercope support team (www.hypercope.de) and or the author
|
||||
Werner Cornelius (werner@isdn4linux or cornelius@titro.de)
|
||||
the Hypercope support team (support@hypercope.de) and or the authors
|
||||
Werner Cornelius (werner@isdn4linux or cornelius@titro.de) or
|
||||
Ulrich Albrecht (ualbrecht@hypercope.de).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ Loading the firmware into the card:
|
|||
To load a 4B-card, the same command is used, except a second firmware
|
||||
file is appended to the commandline of icnctrl.
|
||||
|
||||
-> After dowloading firmware, the two LEDs at the back cover of the card
|
||||
-> After downloading firmware, the two LEDs at the back cover of the card
|
||||
(ICN-4B: 4 LEDs) must be blinking intermittently now. If a connection
|
||||
is up, the corresponding led is lit continuously.
|
||||
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
#!/bin/sh
|
||||
|
||||
KERNELDIR=/usr/src/Linux-Kernel/v2.2.18-pre9
|
||||
KERNELDIR=/usr/src/Linux-Kernel/v2.2.17-pre5
|
||||
KERNELDIR=/usr/src/Linux-Kernel/v2.2.15
|
||||
KERNELDIR=/usr/src/linux
|
||||
DOCP=docpd
|
||||
PREPARSER="./preparser"
|
||||
UNIQUE=false
|
||||
VERBOSE=false
|
||||
NOTEST=true
|
||||
|
||||
docpd() {
|
||||
if ! cmp -s $1 $2 ; then
|
||||
if $NOTEST ; then
|
||||
echo Copying $1 ...
|
||||
mkdir -p `dirname $2`
|
||||
cp $1 $2
|
||||
else
|
||||
echo $1 was changed
|
||||
fi
|
||||
else
|
||||
if $VERBOSE ; then
|
||||
echo $2 is up to date, NOT converted
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
docp() {
|
||||
if [ $1 -nt $2 -o ! -f $2 ] ; then
|
||||
if $NOTEST ; then
|
||||
echo Copying $1 ...
|
||||
mkdir -p `dirname $2`
|
||||
cp $1 $2
|
||||
else
|
||||
echo $1 was changed
|
||||
fi
|
||||
else
|
||||
if $VERBOSE ; then
|
||||
echo $2 is up to date, NOT converted
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
docpuni() {
|
||||
if $VERBOSE ; then
|
||||
echo -n "Processing $1 ... "
|
||||
fi
|
||||
TMPNAME=/tmp/`basename $1`.$$
|
||||
$PREPARSER -c $CTRLNAME $1 $TMPNAME
|
||||
RES=$?
|
||||
if [ "$RES" -eq "0" ] ; then
|
||||
if ! cmp -s $1 $2 ; then
|
||||
if $NOTEST ; then
|
||||
if $VERBOSE ; then
|
||||
echo copying original
|
||||
else
|
||||
echo "Processing $1 ... copying original"
|
||||
fi
|
||||
mkdir -p `dirname $2`
|
||||
cp $1 $2
|
||||
else
|
||||
if $VERBOSE ; then
|
||||
echo original was changed
|
||||
else
|
||||
echo "Processing $1 ... original was changed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if $VERBOSE ; then
|
||||
echo original file is up to date
|
||||
fi
|
||||
fi
|
||||
rm $TMPNAME
|
||||
return 0
|
||||
fi
|
||||
if [ "$RES" -eq "2" ] ; then
|
||||
if ! cmp -s $TMPNAME $2 ; then
|
||||
if $NOTEST ; then
|
||||
if $VERBOSE ; then
|
||||
echo copying modified
|
||||
else
|
||||
echo "Processing $1 ... copying modified"
|
||||
fi
|
||||
mkdir -p `dirname $2`
|
||||
cp $TMPNAME $2
|
||||
else
|
||||
if $VERBOSE ; then
|
||||
echo modified was changed
|
||||
else
|
||||
echo "Processing $1 ... modified was changed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if $VERBOSE ; then
|
||||
echo modified file is up to date
|
||||
fi
|
||||
fi
|
||||
rm $TMPNAME
|
||||
return 0
|
||||
fi
|
||||
echo
|
||||
echo "problem with $PREPARSER retcode $RES"
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Print usage and exit
|
||||
#
|
||||
usage() {
|
||||
cat<<EOM
|
||||
|
||||
std2kern is used for updating your kernel-tree from within
|
||||
this directory.
|
||||
|
||||
std2kern [-d] [-h] [-k DIR] [-v] [-u] [-c FILE] [files ...]
|
||||
|
||||
Options:
|
||||
|
||||
-h This Text.
|
||||
-d Copy depends on modification date instead of file-compare.
|
||||
-k DIR Kerneltree is in DIR instead of /usr/src/linux
|
||||
-v More mesages about processing
|
||||
-u Make a diff for a unique kernel-tree
|
||||
(preprocessing with $PREPARSER)
|
||||
-c FILE Use FILE as control file for $PREPARSER (only with -u)
|
||||
-t Test, don't really copy files
|
||||
|
||||
Without any files given, within the whole tree, the "right"
|
||||
files are copied. When any files are given in the commandline,
|
||||
only those are copied.
|
||||
|
||||
EOM
|
||||
exit
|
||||
}
|
||||
|
||||
#
|
||||
# Check, if argument is a linux kernel dir
|
||||
#
|
||||
checkkernel() {
|
||||
if [ -f $1/Makefile ] ; then
|
||||
if [ "`grep ^vmlinux: $1/Makefile | grep vmlinux`" != "" ] ; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
echo "The given argument does not look like a kernel dir"
|
||||
exit 1
|
||||
}
|
||||
|
||||
#
|
||||
# Determine a control file name
|
||||
#
|
||||
calc_ctrl_file() {
|
||||
eval `sed -n 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' $KERNELDIR/Makefile`
|
||||
echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL"
|
||||
if [ -z "$CTRLNAME" ] ; then
|
||||
CTRLNAME=v$VERSION.$PATCHLEVEL.$SUBLEVEL.ctrl
|
||||
if [ -f $CTRLNAME ] ; then
|
||||
return 0
|
||||
fi
|
||||
CTRLNAME=v$VERSION.$PATCHLEVEL.ctrl
|
||||
if [ -f $CTRLNAME ] ; then
|
||||
return 0
|
||||
fi
|
||||
CTRLNAME=default.ctrl
|
||||
fi
|
||||
if [ -f $CTRLNAME ] ; then
|
||||
return 0
|
||||
fi
|
||||
echo "No control file found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while getopts :dhk:uc:vt a ; do
|
||||
case $a in
|
||||
\?) case $OPTARG in
|
||||
k) echo "-k requires Kernel directory parameter"
|
||||
;;
|
||||
*) echo "Unknown option: -$OPTARG"
|
||||
echo "Try std2kern -h"
|
||||
;;
|
||||
esac
|
||||
exit 1
|
||||
;;
|
||||
k) checkkernel $OPTARG
|
||||
KERNELDIR=$OPTARG
|
||||
;;
|
||||
c) CTRLNAME=$OPTARG
|
||||
;;
|
||||
u) UNIQUE=true
|
||||
;;
|
||||
v) VERBOSE=true
|
||||
;;
|
||||
t) NOTEST=false
|
||||
;;
|
||||
d) DOCP=docp
|
||||
;;
|
||||
h) usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1`
|
||||
|
||||
if $UNIQUE ; then
|
||||
DOCP=docpuni
|
||||
calc_ctrl_file
|
||||
fi
|
||||
|
||||
echo -n "Using $DOCP"
|
||||
|
||||
if $UNIQUE ; then
|
||||
echo " with controlfile $CTRLNAME"
|
||||
else
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ $# != 0 ]; then
|
||||
for i in $* ; do
|
||||
$DOCP $i $KERNELDIR/$i
|
||||
done
|
||||
else
|
||||
for i in drivers/isdn/avmb1/*.[ch] ; do
|
||||
$DOCP $i $KERNELDIR/$i
|
||||
done
|
||||
for i in \
|
||||
include/linux/kernelcapi.h \
|
||||
include/linux/capi.h \
|
||||
include/linux/b1lli.h \
|
||||
include/linux/b1pcmcia.h \
|
||||
; do
|
||||
$DOCP $i $KERNELDIR/$i
|
||||
done
|
||||
for i in drivers/isdn/avmb1/Makefile; do
|
||||
if [ -f $i.kernel ] ; then
|
||||
if $UNIQUE ; then
|
||||
docpd $i.kernel $KERNELDIR/$i
|
||||
else
|
||||
$DOCP $i.kernel $KERNELDIR/$i
|
||||
fi
|
||||
else
|
||||
if $UNIQUE ; then
|
||||
docpd $i $KERNELDIR/$i
|
||||
else
|
||||
$DOCP $i $KERNELDIR/$i
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
|
@ -0,0 +1,170 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
KERNELDIR=/usr/src/linux
|
||||
KERNFIRST=false
|
||||
PREPARSER="./preparser"
|
||||
DODIFF=dodiff
|
||||
UNIQUE=false
|
||||
|
||||
dodiff() {
|
||||
if $KERNFIRST ; then
|
||||
diff -u -bB $EXTRAOPT $2 $1
|
||||
else
|
||||
diff -u -bB $EXTRAOPT $1 $2
|
||||
fi
|
||||
}
|
||||
|
||||
dodiffuni() {
|
||||
echo -n "Processing $1 ... "
|
||||
TMPNAME=/tmp/`basename $1`.$$
|
||||
$PREPARSER -c $CTRLNAME $1 $TMPNAME
|
||||
RES=$?
|
||||
if [ "$RES" -eq "0" ] ; then
|
||||
echo diff original
|
||||
dodiff $1 $2
|
||||
rm $TMPNAME
|
||||
return 0
|
||||
fi
|
||||
if [ "$RES" -eq "2" ] ; then
|
||||
echo diff modified
|
||||
dodiff $TMPNAME $2
|
||||
rm $TMPNAME
|
||||
return 0
|
||||
fi
|
||||
echo "problem with $PREPARSER retcode $RES"
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Print usage and exit
|
||||
#
|
||||
usage() {
|
||||
cat<<EOM
|
||||
|
||||
stddiff is used for generating diffs of the cvs-tree
|
||||
versus the kernel-tree.
|
||||
|
||||
stddiff [-r] [-h] [-k DIR] [-u] [-c FILE] [-w] [files ...]
|
||||
|
||||
Options:
|
||||
|
||||
-h This Text.
|
||||
-r Reverse direction (kernel versus cvs).
|
||||
-k DIR Kerneltree is in DIR instead of /usr/src/linux
|
||||
-u Make a diff for a unique kernel-tree
|
||||
(preprocessing with $PREPARSER)
|
||||
-c FILE Use FILE as control file for $PREPARSER (only with -u)
|
||||
-w Ignore white space when comparing lines
|
||||
|
||||
Without any files given, within the whole tree, the "right"
|
||||
files are diffed. When any files are given in the commandline,
|
||||
only those are diffed.
|
||||
|
||||
EOM
|
||||
exit
|
||||
}
|
||||
|
||||
#
|
||||
# Check, if argument is a linux kernel dir
|
||||
#
|
||||
checkkernel() {
|
||||
if [ -f $1/Makefile ] ; then
|
||||
if [ "`grep ^vmlinux: $1/Makefile | grep vmlinux`" != "" ] ; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
echo "The given argument does not look like a kernel dir"
|
||||
exit 1
|
||||
}
|
||||
|
||||
#
|
||||
# Determine a control file name
|
||||
#
|
||||
calc_ctrl_file() {
|
||||
eval `sed -n 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' $KERNELDIR/Makefile`
|
||||
echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL"
|
||||
if [ -z "$CTRLNAME" ] ; then
|
||||
CTRLNAME=v$VERSION.$PATCHLEVEL.$SUBLEVEL.ctrl
|
||||
if [ -f $CTRLNAME ] ; then
|
||||
return 0
|
||||
fi
|
||||
CTRLNAME=v$VERSION.$PATCHLEVEL.ctrl
|
||||
if [ -f $CTRLNAME ] ; then
|
||||
return 0
|
||||
fi
|
||||
CTRLNAME=default.ctrl
|
||||
fi
|
||||
if [ -f $CTRLNAME ] ; then
|
||||
return 0
|
||||
fi
|
||||
echo "No control file found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while getopts :rhk:uc:w a ; do
|
||||
case $a in
|
||||
\?) case $OPTARG in
|
||||
k) echo "-k requires Kernel directory parameter"
|
||||
;;
|
||||
*) echo "Unknown option: -$OPTARG"
|
||||
echo "Try stddiff -h"
|
||||
;;
|
||||
esac
|
||||
exit 1
|
||||
;;
|
||||
k) checkkernel $OPTARG
|
||||
KERNELDIR=$OPTARG
|
||||
;;
|
||||
c) CTRLNAME=$OPTARG
|
||||
;;
|
||||
u) UNIQUE=true
|
||||
;;
|
||||
r) KERNFIRST=true
|
||||
;;
|
||||
w) EXTRAOPT=-w
|
||||
;;
|
||||
h) usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift `expr $OPTIND - 1`
|
||||
|
||||
if $UNIQUE ; then
|
||||
DODIFF=dodiffuni
|
||||
calc_ctrl_file
|
||||
fi
|
||||
|
||||
echo -n "Using $DODIFF $EXTRAOPT"
|
||||
|
||||
if $UNIQUE ; then
|
||||
echo " with controlfile $CTRLNAME"
|
||||
else
|
||||
echo
|
||||
fi
|
||||
|
||||
if [ $# != 0 ]; then
|
||||
for i in $* ; do
|
||||
$DODIFF $i $KERNELDIR/$i
|
||||
done
|
||||
else
|
||||
for i in drivers/isdn/avmb1/*.[ch] ; do
|
||||
$DODIFF $i $KERNELDIR/$i
|
||||
done
|
||||
for i in \
|
||||
include/linux/kernelcapi.h \
|
||||
include/linux/capi.h \
|
||||
include/linux/b1lli.h \
|
||||
include/linux/b1pcmcia.h \
|
||||
; do
|
||||
$DODIFF $i $KERNELDIR/$i
|
||||
done
|
||||
for i in drivers/isdn/avmb1/Makefile ; do
|
||||
if [ -f $i.kernel ] ; then
|
||||
dodiff $i.kernel $KERNELDIR/$i
|
||||
else
|
||||
dodiff $i $KERNELDIR/$i
|
||||
fi
|
||||
done
|
||||
fi
|
|
@ -1,56 +1,53 @@
|
|||
#
|
||||
# ISDN device configuration
|
||||
#
|
||||
|
||||
# only included if CONFIG_ISDN != n
|
||||
|
||||
if [ "$CONFIG_INET" != "n" ]; then
|
||||
bool ' Support synchronous PPP' CONFIG_ISDN_PPP
|
||||
if [ "$CONFIG_ISDN_PPP" != "n" ]; then
|
||||
bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
|
||||
bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
|
||||
bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
|
||||
bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
|
||||
dep_tristate ' Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN
|
||||
fi
|
||||
fi
|
||||
bool ' Support audio via ISDN' CONFIG_ISDN_AUDIO
|
||||
if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then
|
||||
bool ' Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
|
||||
bool ' Support AT-Fax Class 1 and 2 commands' CONFIG_ISDN_TTY_FAX
|
||||
fi
|
||||
if [ "$CONFIG_X25" != "n" ]; then
|
||||
bool ' X.25 PLP on top of ISDN' CONFIG_ISDN_X25
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
mainmenu_option next_comment
|
||||
comment 'ISDN abc-dw-extension'
|
||||
bool 'Enable isdn-abc-dw-extension' CONFIG_ISDN_WITH_ABC
|
||||
if [ "$CONFIG_ISDN_WITH_ABC" != "n" ]; then
|
||||
bool ' Use D-Channel-Callback with Channel in use check' CONFIG_ISDN_WITH_ABC_CALLB
|
||||
bool ' Enable Outgoing-EAZ-Support' CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
|
||||
bool ' Enable LCR-Support (need isdnlog)' CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
|
||||
bool ' TCP keepalive detect and response (ip4 only)' CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE
|
||||
bool ' Drop frames s_addr != iface_addr (ip4 only)' CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
|
||||
if [ "$CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR" != "n" ]; then
|
||||
bool ' Rewrite socket and frame saddr-field (tcp-ip4 only and very experimental)' CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR
|
||||
bool ' Rewrite socket and frame saddr-field (udp-ip4 only and very experimental)' CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR
|
||||
fi
|
||||
bool ' RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
|
||||
bool ' Support (device-channel)<->(bind-groups)' CONFIG_ISDN_WITH_ABC_ICALL_BIND
|
||||
bool ' Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
|
||||
bool ' Support interface-auto-disble if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR
|
||||
mainmenu_option next_comment
|
||||
comment 'ISDN abc-dw-extension'
|
||||
bool 'Enable isdn-abc-dw-extension' CONFIG_ISDN_WITH_ABC
|
||||
if [ "$CONFIG_ISDN_WITH_ABC" != "n" ]; then
|
||||
bool ' Use D-Channel-Callback with Channel in use check' CONFIG_ISDN_WITH_ABC_CALLB
|
||||
bool ' Enable Outgoing-EAZ-Support' CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
|
||||
bool ' Enable LCR-Support (need isdnlog)' CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
|
||||
bool ' RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
bool ' Enable UDP-Info-Support' CONFIG_ISDN_WITH_ABC_UDP_CHECK
|
||||
if [ "$CONFIG_ISDN_WITH_ABC_UDP_CHECK" != "n" ]; then
|
||||
bool ' Enable Hangup-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
|
||||
bool ' Enable Dial-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
|
||||
fi
|
||||
bool ' Limit on the line frames to 2' CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
|
||||
if [ "$CONFIG_ISDN_PPP" != "n" ]; then
|
||||
bool ' Enable Compression with rawip and x75i' CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
|
||||
bool ' Enable Hangup-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
|
||||
bool ' Enable Dial-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
|
||||
fi
|
||||
fi
|
||||
endmenu
|
||||
|
||||
bool ' Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
|
||||
bool ' Support interface-auto-disable if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR
|
||||
if [ "$CONFIG_ISDN_PPP" != "n" ]; then
|
||||
bool ' Enable Compression with rawip and x75i' CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
|
||||
fi
|
||||
fi
|
||||
endmenu
|
||||
|
||||
mainmenu_option next_comment
|
||||
comment 'ISDN feature submodules'
|
||||
dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
|
||||
bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
|
||||
dep_tristate 'Support isdn diversion services' CONFIG_ISDN_DIVERSION $CONFIG_ISDN
|
||||
endmenu
|
||||
|
||||
comment 'low-level hardware drivers'
|
||||
|
@ -68,6 +65,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
|
|||
bool ' Disable keypad protocol option' CONFIG_HISAX_NO_KEYPAD
|
||||
fi
|
||||
bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
|
||||
bool ' HiSax Support for US NI1' CONFIG_HISAX_NI1
|
||||
comment ' HiSax supported cards'
|
||||
bool ' Teles 16.0/8.0' CONFIG_HISAX_16_0
|
||||
bool ' Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
|
||||
|
@ -86,6 +84,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
|
|||
bool ' USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
|
||||
bool ' MIC card' CONFIG_HISAX_MIC
|
||||
bool ' NETjet card' CONFIG_HISAX_NETJET
|
||||
bool ' NETspider U card' CONFIG_HISAX_NETJET_U
|
||||
bool ' Niccy PnP/PCI card' CONFIG_HISAX_NICCY
|
||||
bool ' Siemens I-Surf card' CONFIG_HISAX_ISURF
|
||||
bool ' HST Saphir card' CONFIG_HISAX_HSTSAPHIR
|
||||
|
@ -94,48 +93,93 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
|
|||
bool ' Gazel cards' CONFIG_HISAX_GAZEL
|
||||
bool ' HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
|
||||
bool ' Winbond W6692 based cards' CONFIG_HISAX_W6692
|
||||
bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
|
||||
# bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
|
||||
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
|
||||
bool ' Am7930' CONFIG_HISAX_AMD7930
|
||||
fi
|
||||
fi
|
||||
bool ' HiSax debugging' CONFIG_HISAX_DEBUG
|
||||
|
||||
dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
|
||||
dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
|
||||
dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
|
||||
dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
|
||||
|
||||
if [ "$CONFIG_HISAX_SEDLBAUER_CS" != "n" ]; then
|
||||
define_bool CONFIG_HISAX_SEDLBAUER y
|
||||
fi
|
||||
if [ "$CONFIG_HISAX_ELSA_CS" != "n" ]; then
|
||||
define_bool CONFIG_HISAX_ELSA y
|
||||
fi
|
||||
if [ "$CONFIG_HISAX_HFC_USB_CS" != "n" ]; then
|
||||
define_bool CONFIG_HISAX_HFC_USB y
|
||||
fi
|
||||
fi
|
||||
endmenu
|
||||
|
||||
### Active ISDN cards
|
||||
|
||||
mainmenu_option next_comment
|
||||
comment 'Active ISDN cards'
|
||||
dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
|
||||
dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
|
||||
dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
|
||||
fi
|
||||
dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
|
||||
|
||||
dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
|
||||
dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
|
||||
dep_tristate 'Spellcaster support' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
|
||||
dep_tristate 'IBM Active 2000 support' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
|
||||
|
||||
bool 'Eicon active card support' CONFIG_ISDN_DRV_EICON
|
||||
if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
|
||||
bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
|
||||
fi
|
||||
dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
|
||||
if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
|
||||
bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
|
||||
bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
|
||||
if [ "$CONFIG_ISDN_DRV_AVMB1_B1PCI" != "n" ]; then
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
bool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "y" ]; then
|
||||
dep_tristate ' Build Eicon driver type standalone' CONFIG_ISDN_DRV_EICON_DIVAS $CONFIG_ISDN $CONFIG_PCI
|
||||
fi
|
||||
if [ "$CONFIG_ISDN_DRV_EICON_DIVAS" != "y" ]; then
|
||||
dep_tristate ' Legacy Eicon driver' CONFIG_ISDN_DRV_EICON_OLD $CONFIG_ISDN
|
||||
if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "n" ]; then
|
||||
dep_bool ' Eicon PCI DIVA Server BRI/PRI/4BRI support' CONFIG_ISDN_DRV_EICON_PCI $CONFIG_PCI
|
||||
bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
|
||||
fi
|
||||
fi
|
||||
bool ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
|
||||
bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
|
||||
bool ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
bool ' AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
|
||||
dep_tristate 'Auvertech TurboPAM support' CONFIG_ISDN_DRV_TPAM $CONFIG_ISDN $CONFIG_PCI
|
||||
fi
|
||||
|
||||
# CAPI subsystem
|
||||
|
||||
tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI
|
||||
if [ "$CONFIG_ISDN_CAPI" != "n" ]; then
|
||||
bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
|
||||
dep_bool ' CAPI2.0 Middleware support (EXPERIMENTAL)' CONFIG_ISDN_CAPI_MIDDLEWARE $CONFIG_EXPERIMENTAL
|
||||
dep_tristate ' CAPI2.0 /dev/capi support' CONFIG_ISDN_CAPI_CAPI20 $CONFIG_ISDN_CAPI
|
||||
if [ "$CONFIG_ISDN_CAPI_MIDDLEWARE" = "y" ]; then
|
||||
dep_mbool ' CAPI2.0 filesystem support' CONFIG_ISDN_CAPI_CAPIFS_BOOL $CONFIG_ISDN_CAPI_CAPI20
|
||||
if [ "$CONFIG_ISDN_CAPI_CAPIFS_BOOL" = "y" ]; then
|
||||
define_tristate CONFIG_ISDN_CAPI_CAPIFS $CONFIG_ISDN_CAPI_CAPI20
|
||||
else
|
||||
define_tristate CONFIG_ISDN_CAPI_CAPIFS n
|
||||
fi
|
||||
fi
|
||||
bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
|
||||
fi
|
||||
if [ "$CONFIG_PROC_FS" != "n" ]; then
|
||||
if [ "$CONFIG_MODULES" != "n" ]; then
|
||||
bool 'Hypercope HYSDN cards (Champ, Ergo, Metro) support (module)' CONFIG_HYSDN
|
||||
dep_tristate ' CAPI2.0 capidrv interface support' CONFIG_ISDN_CAPI_CAPIDRV $CONFIG_ISDN_CAPI $CONFIG_ISDN
|
||||
fi
|
||||
|
||||
# CAPI drivers
|
||||
|
||||
if [ "$CONFIG_ISDN_CAPI" != "n" ]; then
|
||||
dep_tristate ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA $CONFIG_ISDN_CAPI
|
||||
dep_tristate ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI
|
||||
dep_mbool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4 $CONFIG_ISDN_DRV_AVMB1_B1PCI
|
||||
dep_tristate ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA $CONFIG_ISDN_CAPI
|
||||
dep_tristate ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_ISDN_CAPI
|
||||
dep_tristate ' AVM B1/M1/M2 PCMCIA cs module' CONFIG_ISDN_DRV_AVMB1_AVM_CS $CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_PCMCIA
|
||||
dep_tristate ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI
|
||||
dep_tristate ' AVM C4/C2 support' CONFIG_ISDN_DRV_AVMB1_C4 $CONFIG_ISDN_CAPI $CONFIG_PCI
|
||||
fi
|
||||
|
||||
# HYSDN
|
||||
|
||||
dep_tristate ' Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)' CONFIG_HYSDN m $CONFIG_PROC_FS
|
||||
dep_mbool ' HYSDN CAPI 2.0 support' CONFIG_HYSDN_CAPI $CONFIG_HYSDN $CONFIG_ISDN_CAPI
|
||||
endmenu
|
||||
|
|
|
@ -1,151 +1,57 @@
|
|||
SUB_DIRS :=
|
||||
MOD_SUB_DIRS :=
|
||||
ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert hysdn
|
||||
# Makefile for the kernel ISDN subsystem and device drivers.
|
||||
|
||||
L_OBJS :=
|
||||
LX_OBJS :=
|
||||
M_OBJS :=
|
||||
MX_OBJS :=
|
||||
O_OBJS :=
|
||||
OX_OBJS :=
|
||||
L_TARGET :=
|
||||
O_TARGET :=
|
||||
# The target object and module list name.
|
||||
|
||||
ifeq ($(CONFIG_ISDN),y)
|
||||
L_TARGET := isdn.a
|
||||
L_OBJS += isdn_net.o isdn_tty.o isdn_cards.o isdn_v110.o
|
||||
LX_OBJS += isdn_common.o
|
||||
ifdef CONFIG_ISDN_PPP
|
||||
L_OBJS += isdn_ppp.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_X25
|
||||
L_OBJS += isdn_x25iface.o
|
||||
L_OBJS += isdn_concap.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_AUDIO
|
||||
L_OBJS += isdn_audio.o
|
||||
ifdef CONFIG_ISDN_TTY_FAX
|
||||
L_OBJS += isdn_ttyfax.o
|
||||
endif
|
||||
endif
|
||||
ifdef CONFIG_ISDN_WITH_ABC
|
||||
L_OBJS += isdn_dwabc.o
|
||||
endif
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN),m)
|
||||
M_OBJS += isdn.o
|
||||
O_TARGET += isdn.o
|
||||
O_OBJS += isdn_net.o isdn_tty.o isdn_v110.o
|
||||
OX_OBJS += isdn_common.o
|
||||
ifdef CONFIG_ISDN_PPP
|
||||
O_OBJS += isdn_ppp.o
|
||||
M_OBJS += isdn_bsdcomp.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_X25
|
||||
O_OBJS += isdn_x25iface.o
|
||||
O_OBJS += isdn_concap.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_AUDIO
|
||||
O_OBJS += isdn_audio.o
|
||||
ifdef CONFIG_ISDN_TTY_FAX
|
||||
O_OBJS += isdn_ttyfax.o
|
||||
endif
|
||||
endif
|
||||
ifdef CONFIG_ISDN_WITH_ABC
|
||||
O_OBJS += isdn_dwabc.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
O_TARGET := isdn.a
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DIVERSION),y)
|
||||
ifeq ($(CONFIG_MODULES),y)
|
||||
MOD_SUB_DIRS += divert
|
||||
endif
|
||||
endif
|
||||
# Objects that export symbols.
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_HISAX),y)
|
||||
L_OBJS += hisax/hisax.o
|
||||
SUB_DIRS += hisax
|
||||
MOD_SUB_DIRS += hisax
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_HISAX),m)
|
||||
MOD_SUB_DIRS += hisax
|
||||
endif
|
||||
endif
|
||||
export-objs := isdn_common.o
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_ICN),y)
|
||||
L_OBJS += icn/icn_obj.o
|
||||
SUB_DIRS += icn
|
||||
MOD_SUB_DIRS += icn
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_ICN),m)
|
||||
MOD_SUB_DIRS += icn
|
||||
endif
|
||||
endif
|
||||
# Multipart objects.
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_PCBIT),y)
|
||||
L_OBJS += pcbit/pcbit.o
|
||||
SUB_DIRS += pcbit
|
||||
MOD_SUB_DIRS += pcbit
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_PCBIT),m)
|
||||
MOD_SUB_DIRS += pcbit
|
||||
endif
|
||||
endif
|
||||
list-multi := isdn.o
|
||||
isdn-objs := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_SC),y)
|
||||
L_OBJS += sc/sc.o
|
||||
SUB_DIRS += sc
|
||||
MOD_SUB_DIRS += sc
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_SC),m)
|
||||
MOD_SUB_DIRS += sc
|
||||
endif
|
||||
endif
|
||||
# Optional parts of multipart objects.
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_AVMB1),y)
|
||||
L_OBJS += avmb1/avmb1.o
|
||||
SUB_DIRS += avmb1
|
||||
MOD_SUB_DIRS += avmb1
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
|
||||
MOD_SUB_DIRS += avmb1
|
||||
endif
|
||||
endif
|
||||
isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o
|
||||
isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o
|
||||
isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o
|
||||
isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o
|
||||
isdn-objs-$(CONFIG_ISDN_WITH_ABC) += isdn_dwabc.o
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_LOOP),y)
|
||||
L_OBJS += isdnloop/isdnloop.o
|
||||
SUB_DIRS += isdnloop
|
||||
MOD_SUB_DIRS += isdnloop
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_LOOP),m)
|
||||
MOD_SUB_DIRS += isdnloop
|
||||
endif
|
||||
endif
|
||||
isdn-objs += $(isdn-objs-y)
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_ACT2000),y)
|
||||
L_OBJS += act2000/act2000.o
|
||||
SUB_DIRS += act2000
|
||||
MOD_SUB_DIRS += act2000
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_ACT2000),m)
|
||||
MOD_SUB_DIRS += act2000
|
||||
endif
|
||||
endif
|
||||
# Ordering constraints: isdn.o first, rest doesn't matter
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_EICON),y)
|
||||
L_OBJS += eicon/eicon.o
|
||||
SUB_DIRS += eicon
|
||||
MOD_SUB_DIRS += eicon
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_EICON),m)
|
||||
MOD_SUB_DIRS += eicon
|
||||
endif
|
||||
endif
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
ifeq ($(CONFIG_HYSDN),y)
|
||||
MOD_SUB_DIRS += hysdn
|
||||
endif
|
||||
obj-$(CONFIG_ISDN) += isdn.o
|
||||
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
# Object files in subdirectories
|
||||
|
||||
mod-subdirs := avmb1 eicon
|
||||
subdir-$(CONFIG_ISDN_DIVERSION) += divert
|
||||
subdir-$(CONFIG_ISDN_DRV_HISAX) += hisax
|
||||
subdir-$(CONFIG_ISDN_DRV_ICN) += icn
|
||||
subdir-$(CONFIG_ISDN_DRV_PCBIT) += pcbit
|
||||
subdir-$(CONFIG_ISDN_DRV_SC) += sc
|
||||
subdir-$(CONFIG_ISDN_CAPI) += avmb1
|
||||
subdir-$(CONFIG_ISDN_DRV_LOOP) += isdnloop
|
||||
subdir-$(CONFIG_ISDN_DRV_ACT2000) += act2000
|
||||
subdir-$(CONFIG_ISDN_DRV_EICON) += eicon
|
||||
subdir-$(CONFIG_HYSDN) += hysdn
|
||||
subdir-$(CONFIG_ISDN_DRV_TPAM) += tpam
|
||||
|
||||
obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y))
|
||||
|
||||
# The global Rules.make.
|
||||
|
||||
include $(TOPDIR)/drivers/isdn/Rules.make
|
||||
|
||||
# Link rules for multi-part drivers.
|
||||
|
||||
isdn.o: $(isdn-objs)
|
||||
$(LD) -r -o $@ $(isdn-objs)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# Extract lists of the multi-part drivers.
|
||||
# The 'int-*' lists are the intermediate files used to build the multi's.
|
||||
|
||||
multi-y := $(filter $(list-multi), $(obj-y))
|
||||
multi-m := $(filter $(list-multi), $(obj-m))
|
||||
int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
|
||||
int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
|
||||
|
||||
# Files that are both resident and modular: remove from modular.
|
||||
|
||||
obj-m := $(filter-out $(obj-y), $(obj-m))
|
||||
int-m := $(filter-out $(int-y), $(int-m))
|
||||
|
||||
# Take multi-part drivers out of obj-y and put components in.
|
||||
|
||||
obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
|
||||
|
||||
# Translate to Rules.make lists.
|
||||
|
||||
O_OBJS := $(sort $(filter-out $(export-objs), $(obj-y)))
|
||||
OX_OBJS := $(sort $(filter $(export-objs), $(obj-y)))
|
||||
M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
|
||||
MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
|
||||
MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
|
||||
MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
|
||||
|
||||
both-m := $(filter $(mod-subdirs), $(subdir-y))
|
||||
SUB_DIRS := $(subdir-y)
|
||||
MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m))
|
||||
ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
|
@ -1,15 +1,21 @@
|
|||
L_OBJS :=
|
||||
M_OBJS :=
|
||||
O_OBJS := module.o capi.o act2000_isa.o
|
||||
# Makefile for the act2000 ISDN device driver
|
||||
|
||||
O_TARGET :=
|
||||
ifeq ($(CONFIG_ISDN_DRV_ACT2000),y)
|
||||
O_TARGET += act2000.o
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_ACT2000),m)
|
||||
O_TARGET += act2000.o
|
||||
M_OBJS = act2000.o
|
||||
endif
|
||||
endif
|
||||
# The target object and module list name.
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
O_TARGET := vmlinux-obj.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
list-multi := act2000.o
|
||||
act2000-objs := module.o capi.o act2000_isa.o
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000.o
|
||||
|
||||
include $(TOPDIR)/drivers/isdn/Rules.make
|
||||
|
||||
# Link rules for multi-part drivers.
|
||||
|
||||
act2000.o: $(act2000-objs)
|
||||
$(LD) -r -o $@ $(act2000-objs)
|
||||
|
|
|
@ -2,57 +2,19 @@
|
|||
*
|
||||
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Author Fritz Elfert
|
||||
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Thanks to Friedemann Baitinger and IBM Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.6 1998/11/05 22:12:38 fritz
|
||||
* Changed mail-address.
|
||||
*
|
||||
* Revision 1.5 1997/10/09 22:22:59 fritz
|
||||
* New HL<->LL interface:
|
||||
* New BSENT callback with nr. of bytes included.
|
||||
* Sending without ACK.
|
||||
*
|
||||
* Revision 1.4 1997/09/25 17:25:37 fritz
|
||||
* Support for adding cards at runtime.
|
||||
* Support for new Firmware.
|
||||
*
|
||||
* Revision 1.3 1997/09/24 23:11:43 fritz
|
||||
* Optimized IRQ load and polling-mode.
|
||||
*
|
||||
* Revision 1.2 1997/09/24 19:44:12 fritz
|
||||
* Added MSN mapping support, some cleanup.
|
||||
*
|
||||
* Revision 1.1 1997/09/23 18:00:05 fritz
|
||||
* New driver for IBM Active 2000.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef act2000_h
|
||||
#define act2000_h
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/* Kernel includes */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#define ACT2000_IOCTL_SETPORT 1
|
||||
#define ACT2000_IOCTL_GETPORT 2
|
||||
#define ACT2000_IOCTL_SETIRQ 3
|
||||
|
@ -110,7 +72,7 @@ typedef struct act2000_fwid {
|
|||
#include <asm/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/ioport.h>
|
||||
|
|
|
@ -2,56 +2,14 @@
|
|||
*
|
||||
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Author Fritz Elfert
|
||||
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Thanks to Friedemann Baitinger and IBM Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 1999/09/04 06:20:04 keil
|
||||
* Changes from kernel set_current_state()
|
||||
*
|
||||
* Revision 1.8 1999/01/05 18:29:25 he
|
||||
* merged remaining schedule_timeout() changes from 2.1.127
|
||||
*
|
||||
* Revision 1.7 1998/11/05 22:12:41 fritz
|
||||
* Changed mail-address.
|
||||
*
|
||||
* Revision 1.6 1998/06/17 19:51:09 he
|
||||
* merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
|
||||
* brute force fix to avoid Ugh's in isdn_tty_write()
|
||||
* cleaned up some dead code
|
||||
*
|
||||
* Revision 1.5 1998/02/12 23:06:47 keil
|
||||
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
|
||||
*
|
||||
* Revision 1.4 1997/10/09 22:23:00 fritz
|
||||
* New HL<->LL interface:
|
||||
* New BSENT callback with nr. of bytes included.
|
||||
* Sending without ACK.
|
||||
*
|
||||
* Revision 1.3 1997/09/25 17:25:38 fritz
|
||||
* Support for adding cards at runtime.
|
||||
* Support for new Firmware.
|
||||
*
|
||||
* Revision 1.2 1997/09/24 23:11:44 fritz
|
||||
* Optimized IRQ load and polling-mode.
|
||||
*
|
||||
* Revision 1.1 1997/09/23 18:00:05 fritz
|
||||
* New driver for IBM Active 2000.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
@ -59,16 +17,7 @@
|
|||
#include "act2000_isa.h"
|
||||
#include "capi.h"
|
||||
|
||||
static act2000_card *irq2card_map[16] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static int act2000_isa_irqs[] =
|
||||
{
|
||||
3, 5, 7, 10, 11, 12, 15
|
||||
};
|
||||
#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int))
|
||||
static act2000_card *irq2card_map[16];
|
||||
|
||||
static void
|
||||
act2000_isa_delay(long t)
|
||||
|
@ -115,13 +64,9 @@ int
|
|||
act2000_isa_detect(unsigned short portbase)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if (!check_region(portbase, ISA_REGION))
|
||||
ret = act2000_isa_reset(portbase);
|
||||
restore_flags(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -200,9 +145,6 @@ act2000_isa_enable_irq(act2000_card * card)
|
|||
int
|
||||
act2000_isa_config_irq(act2000_card * card, short irq)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (card->flags & ACT2000_FLAGS_IVALID) {
|
||||
free_irq(card->irq, NULL);
|
||||
irq2card_map[card->irq] = NULL;
|
||||
|
@ -211,30 +153,13 @@ act2000_isa_config_irq(act2000_card * card, short irq)
|
|||
outb(ISA_COR_IRQOFF, ISA_PORT_COR);
|
||||
if (!irq)
|
||||
return 0;
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if (irq == -1) {
|
||||
/* Auto select */
|
||||
for (i = 0; i < ISA_NRIRQS; i++) {
|
||||
if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) {
|
||||
card->irq = act2000_isa_irqs[i];
|
||||
irq2card_map[card->irq] = card;
|
||||
card->flags |= ACT2000_FLAGS_IVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Fixed irq */
|
||||
if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
|
||||
card->irq = irq;
|
||||
irq2card_map[card->irq] = card;
|
||||
card->flags |= ACT2000_FLAGS_IVALID;
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
if (!card->flags & ACT2000_FLAGS_IVALID) {
|
||||
|
||||
if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
|
||||
card->irq = irq;
|
||||
irq2card_map[card->irq] = card;
|
||||
card->flags |= ACT2000_FLAGS_IVALID;
|
||||
printk(KERN_WARNING
|
||||
"act2000: Could not request irq\n");
|
||||
"act2000: Could not request irq %d\n",irq);
|
||||
return -EBUSY;
|
||||
} else {
|
||||
act2000_isa_select_irq(card);
|
||||
|
@ -490,7 +415,7 @@ act2000_isa_getid(act2000_card * card)
|
|||
int
|
||||
act2000_isa_download(act2000_card * card, act2000_ddef * cb)
|
||||
{
|
||||
int length;
|
||||
unsigned int length;
|
||||
int ret;
|
||||
int l;
|
||||
int c;
|
||||
|
@ -503,9 +428,8 @@ act2000_isa_download(act2000_card * card, act2000_ddef * cb)
|
|||
if (!act2000_isa_reset(card->port))
|
||||
return -ENXIO;
|
||||
act2000_isa_delay(HZ / 2);
|
||||
if ((ret = verify_area(VERIFY_READ, (void *) cb, sizeof(cblock))))
|
||||
return ret;
|
||||
copy_from_user(&cblock, (char *) cb, sizeof(cblock));
|
||||
if(copy_from_user(&cblock, (char *) cb, sizeof(cblock)))
|
||||
return -EFAULT;
|
||||
length = cblock.length;
|
||||
p = cblock.buffer;
|
||||
if ((ret = verify_area(VERIFY_READ, (void *) p, length)))
|
||||
|
|
|
@ -2,30 +2,14 @@
|
|||
*
|
||||
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Author Fritz Elfert
|
||||
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Thanks to Friedemann Baitinger and IBM Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.2 1998/11/05 22:12:43 fritz
|
||||
* Changed mail-address.
|
||||
*
|
||||
* Revision 1.1 1997/09/23 18:00:07 fritz
|
||||
* New driver for IBM Active 2000.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef act2000_isa_h
|
||||
|
|
|
@ -1,50 +1,16 @@
|
|||
/* $Id$
|
||||
*
|
||||
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
|
||||
* CAPI encoder/decoder
|
||||
* CAPI encoder/decoder
|
||||
*
|
||||
* Author Fritz Elfert
|
||||
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Thanks to Friedemann Baitinger and IBM Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.7 1998/02/23 23:35:41 fritz
|
||||
* Eliminated some compiler warnings.
|
||||
*
|
||||
* Revision 1.6 1998/02/12 23:06:50 keil
|
||||
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
|
||||
*
|
||||
* Revision 1.5 1997/10/09 22:23:02 fritz
|
||||
* New HL<->LL interface:
|
||||
* New BSENT callback with nr. of bytes included.
|
||||
* Sending without ACK.
|
||||
*
|
||||
* Revision 1.4 1997/09/25 17:25:39 fritz
|
||||
* Support for adding cards at runtime.
|
||||
* Support for new Firmware.
|
||||
*
|
||||
* Revision 1.3 1997/09/24 19:44:14 fritz
|
||||
* Added MSN mapping support, some cleanup.
|
||||
*
|
||||
* Revision 1.2 1997/09/23 19:41:24 fritz
|
||||
* Disabled Logging of DATA_B3_IND/RESP/REQ/CONF Messages.
|
||||
*
|
||||
* Revision 1.1 1997/09/23 18:00:08 fritz
|
||||
* New driver for IBM Active 2000.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
|
@ -153,7 +119,7 @@ actcapi_chkhdr(act2000_card * card, actcapi_msghdr *hdr)
|
|||
m->hdr.cmd.cmd = c; \
|
||||
m->hdr.cmd.subcmd = s; \
|
||||
m->hdr.msgnum = actcapi_nextsmsg(card); \
|
||||
} \
|
||||
} else m = NULL;\
|
||||
}
|
||||
|
||||
#define ACTCAPI_CHKSKB if (!skb) { \
|
||||
|
|
|
@ -2,39 +2,14 @@
|
|||
*
|
||||
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Author Fritz Elfert
|
||||
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Thanks to Friedemann Baitinger and IBM Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.4 1997/10/01 09:21:04 fritz
|
||||
* Removed old compatibility stuff for 2.0.X kernels.
|
||||
* From now on, this code is for 2.1.X ONLY!
|
||||
* Old stuff is still in the separate branch.
|
||||
*
|
||||
* Revision 1.3 1997/09/25 17:25:41 fritz
|
||||
* Support for adding cards at runtime.
|
||||
* Support for new Firmware.
|
||||
*
|
||||
* Revision 1.2 1997/09/24 19:44:15 fritz
|
||||
* Added MSN mapping support, some cleanup.
|
||||
*
|
||||
* Revision 1.1 1997/09/23 18:00:10 fritz
|
||||
* New driver for IBM Active 2000.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CAPI_H
|
||||
|
@ -60,7 +35,7 @@ typedef struct actcapi_msgdsc {
|
|||
char *description;
|
||||
} actcapi_msgdsc;
|
||||
|
||||
/* CAPI Adress */
|
||||
/* CAPI Address */
|
||||
typedef struct actcapi_addr {
|
||||
__u8 len; /* Length of element */
|
||||
__u8 tnp; /* Type/Numbering Plan */
|
||||
|
|
|
@ -2,63 +2,21 @@
|
|||
*
|
||||
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Author Fritz Elfert
|
||||
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Thanks to Friedemann Baitinger and IBM Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.10 1999/10/24 18:46:05 fritz
|
||||
* Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest
|
||||
* kernels.
|
||||
*
|
||||
* Revision 1.9 1999/04/12 13:13:56 fritz
|
||||
* Made cards pointer static to avoid name-clash.
|
||||
*
|
||||
* Revision 1.8 1998/11/05 22:12:51 fritz
|
||||
* Changed mail-address.
|
||||
*
|
||||
* Revision 1.7 1998/02/12 23:06:52 keil
|
||||
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
|
||||
*
|
||||
* Revision 1.6 1998/01/31 22:10:42 keil
|
||||
* changes for 2.1.82
|
||||
*
|
||||
* Revision 1.5 1997/10/09 22:23:04 fritz
|
||||
* New HL<->LL interface:
|
||||
* New BSENT callback with nr. of bytes included.
|
||||
* Sending without ACK.
|
||||
*
|
||||
* Revision 1.4 1997/09/25 17:25:43 fritz
|
||||
* Support for adding cards at runtime.
|
||||
* Support for new Firmware.
|
||||
*
|
||||
* Revision 1.3 1997/09/24 23:11:45 fritz
|
||||
* Optimized IRQ load and polling-mode.
|
||||
*
|
||||
* Revision 1.2 1997/09/24 19:44:17 fritz
|
||||
* Added MSN mapping support, some cleanup.
|
||||
*
|
||||
* Revision 1.1 1997/09/23 18:00:13 fritz
|
||||
* New driver for IBM Active 2000.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "act2000.h"
|
||||
#include "act2000_isa.h"
|
||||
#include "capi.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
static unsigned short act2000_isa_ports[] =
|
||||
{
|
||||
|
@ -72,15 +30,15 @@ static act2000_card *cards = (act2000_card *) NULL;
|
|||
/* Parameters to be set by insmod */
|
||||
static int act_bus = 0;
|
||||
static int act_port = -1; /* -1 = Autoprobe */
|
||||
static int act_irq = -1; /* -1 = Autoselect */
|
||||
static int act_irq = -1;
|
||||
static char *act_id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
MODULE_DESCRIPTION( "Driver for IBM Active 2000 ISDN card");
|
||||
MODULE_DESCRIPTION( "ISDN4Linux: Driver for IBM Active 2000 ISDN card");
|
||||
MODULE_AUTHOR( "Fritz Elfert");
|
||||
MODULE_SUPPORTED_DEVICE( "ISDN subsystem");
|
||||
MODULE_LICENSE( "GPL");
|
||||
MODULE_PARM_DESC(act_bus, "BusType of first card, 1=ISA, 2=MCA, 3=PCMCIA, currently only ISA");
|
||||
MODULE_PARM_DESC(membase, "Base port address of first card");
|
||||
MODULE_PARM_DESC(act_irq, "IRQ of first card (-1 = grab next free IRQ)");
|
||||
MODULE_PARM_DESC(act_irq, "IRQ of first card");
|
||||
MODULE_PARM_DESC(act_id, "ID-String of first card");
|
||||
MODULE_PARM(act_bus, "i");
|
||||
MODULE_PARM(act_port, "i");
|
||||
|
@ -276,9 +234,7 @@ act2000_poll(unsigned long data)
|
|||
act2000_receive(card);
|
||||
save_flags(flags);
|
||||
cli();
|
||||
del_timer(&card->ptimer);
|
||||
card->ptimer.expires = jiffies + 3;
|
||||
add_timer(&card->ptimer);
|
||||
mod_timer(&card->ptimer, jiffies+3);
|
||||
restore_flags(flags);
|
||||
}
|
||||
|
||||
|
@ -562,37 +518,6 @@ act2000_readstatus(u_char * buf, int len, int user, act2000_card * card)
|
|||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
act2000_putmsg(act2000_card *card, char c)
|
||||
{
|
||||
ulong flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
*card->status_buf_write++ = c;
|
||||
if (card->status_buf_write == card->status_buf_read) {
|
||||
if (++card->status_buf_read > card->status_buf_end)
|
||||
card->status_buf_read = card->status_buf;
|
||||
}
|
||||
if (card->status_buf_write > card->status_buf_end)
|
||||
card->status_buf_write = card->status_buf;
|
||||
restore_flags(flags);
|
||||
}
|
||||
|
||||
static void
|
||||
act2000_logstat(struct act2000_card *card, char *str)
|
||||
{
|
||||
char *p = str;
|
||||
isdn_ctrl c;
|
||||
|
||||
while (*p)
|
||||
act2000_putmsg(card, *p++);
|
||||
c.command = ISDN_STAT_STAVAIL;
|
||||
c.driver = card->myid;
|
||||
c.arg = strlen(str);
|
||||
card->interface.statcallb(&c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find card with given driverId
|
||||
*/
|
||||
|
@ -892,12 +817,7 @@ act2000_addcard(int bus, int port, int irq, char *id)
|
|||
|
||||
#define DRIVERNAME "IBM Active 2000 ISDN driver"
|
||||
|
||||
#ifdef MODULE
|
||||
#define act2000_init init_module
|
||||
#endif
|
||||
|
||||
int
|
||||
act2000_init(void)
|
||||
static int __init act2000_init(void)
|
||||
{
|
||||
printk(KERN_INFO "%s\n", DRIVERNAME);
|
||||
if (!cards)
|
||||
|
@ -909,9 +829,7 @@ act2000_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void
|
||||
cleanup_module(void)
|
||||
static void __exit act2000_exit(void)
|
||||
{
|
||||
act2000_card *card = cards;
|
||||
act2000_card *last;
|
||||
|
@ -929,8 +847,8 @@ cleanup_module(void)
|
|||
}
|
||||
printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
|
||||
}
|
||||
|
||||
#else
|
||||
#if 0
|
||||
#ifndef MODULE
|
||||
void
|
||||
act2000_setup(char *str, int *ints)
|
||||
{
|
||||
|
@ -961,3 +879,7 @@ act2000_setup(char *str, int *ints)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
module_init(act2000_init);
|
||||
module_exit(act2000_exit);
|
||||
|
|
|
@ -1,130 +1,40 @@
|
|||
#
|
||||
# $Id$
|
||||
#
|
||||
# Makefile for the CAPI and AVM-B1 device drivers.
|
||||
#
|
||||
# Note! Dependencies are done automagically by 'make dep', which also
|
||||
# removes any old dependencies. DON'T put your own dependencies here
|
||||
# unless it's something special (ie not a .c file).
|
||||
#
|
||||
# Note 2! The CFLAGS definitions are now inherited from the
|
||||
# parent makes..
|
||||
#
|
||||
# $Log$
|
||||
# Revision 1.7 1999/09/15 08:16:03 calle
|
||||
# Implementation of 64Bit extention complete.
|
||||
#
|
||||
# Revision 1.6 1999/07/20 06:41:44 calle
|
||||
# Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
|
||||
# compile, if not selected as modules.
|
||||
#
|
||||
# Revision 1.5 1999/07/01 15:26:20 calle
|
||||
# complete new version (I love it):
|
||||
# + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
# - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
# - write a CAPI-2.0 for the passive cards
|
||||
# - support serial link CAPI-2.0 boxes.
|
||||
# + wrote "capi_driver" for all supported cards.
|
||||
# + "capi_driver" (supported cards) now have to be configured with
|
||||
# make menuconfig, in the past all supported cards where included
|
||||
# at once.
|
||||
# + new and better informations in /proc/capi/
|
||||
# + new ioctl to switch trace of capi messages per controller
|
||||
# using "avmcapictrl trace [contr] on|off|...."
|
||||
# + complete testcircle with all supported cards and also the
|
||||
# PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
#
|
||||
# Revision 1.4 1997/03/30 17:10:40 calle
|
||||
# added support for AVM-B1-PCI card.
|
||||
#
|
||||
# Revision 1.3 1997/03/22 02:00:57 fritz
|
||||
# -Reworked toplevel Makefile. From now on, no different Makefiles
|
||||
# for standalone- and in-kernel-compilation are needed any more.
|
||||
# -Added local Rules.make for above reason.
|
||||
# -Experimental changes in teles3.c for enhanced IRQ-checking with
|
||||
# 2.1.X and SMP kernels.
|
||||
# -Removed diffstd-script, same functionality is in stddiff -r.
|
||||
# -Enhanced scripts std2kern and stddiff.
|
||||
#
|
||||
# Revision 1.1 1997/03/05 21:26:14 fritz
|
||||
# Renamed, according naming conventions in CVS tree.
|
||||
#
|
||||
# Revision 1.1 1997/03/04 21:50:26 calle
|
||||
# Frirst version in isdn4linux
|
||||
#
|
||||
# Revision 2.2 1997/02/12 09:31:39 calle
|
||||
#
|
||||
# Revision 1.1 1997/01/31 10:32:20 calle
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# Makefile for the AVM ISDN device drivers and CAPI subsystem.
|
||||
|
||||
#
|
||||
# Objects that don't export a symtab
|
||||
#
|
||||
L_OBJS := # used as component of an L_TARGET
|
||||
O_OBJS := # used as component of an O_TARGET
|
||||
M_OBJS := # used as module
|
||||
#
|
||||
# Objects that do export a symtab
|
||||
#
|
||||
LX_OBJS := # used as component of an L_TARGET
|
||||
OX_OBJS := # used as component of an O_TARGET
|
||||
MX_OBJS := # used as module
|
||||
#
|
||||
# Targets, created by linking others
|
||||
#
|
||||
O_TARGET := # used for .o targets (from O and OX objects)
|
||||
L_TARGET := # used for .a targets (from L and LX objects)
|
||||
# The target object and module list name.
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_AVMB1),y)
|
||||
O_TARGET += avmb1.o
|
||||
OX_OBJS += kcapi.o
|
||||
O_OBJS += capi.o
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
|
||||
O_OBJS += b1isa.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
|
||||
O_OBJS += b1pci.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
|
||||
O_OBJS += t1isa.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
|
||||
OX_OBJS += b1pcmcia.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
|
||||
O_OBJS += t1pci.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_C4
|
||||
O_OBJS += c4.o
|
||||
endif
|
||||
OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
|
||||
O_TARGET += kernelcapi.o
|
||||
OX_OBJS += kcapi.o
|
||||
M_OBJS += capi.o kernelcapi.o
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
|
||||
M_OBJS += b1isa.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
|
||||
M_OBJS += b1pci.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
|
||||
M_OBJS += t1isa.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
|
||||
MX_OBJS += b1pcmcia.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
|
||||
M_OBJS += t1pci.o
|
||||
endif
|
||||
ifdef CONFIG_ISDN_DRV_AVMB1_C4
|
||||
M_OBJS += c4.o
|
||||
endif
|
||||
MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
|
||||
endif
|
||||
endif
|
||||
O_TARGET := vmlinux-obj.o
|
||||
|
||||
# Objects that export symbols.
|
||||
|
||||
export-objs := kcapi.o capiutil.o b1dma.o b1pcmcia.o b1.o capifs.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
list-multi := kernelcapi.o
|
||||
kernelcapi-objs := kcapi.o
|
||||
|
||||
# Ordering constraints: kernelcapi.o first
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o capiutil.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIFS) += capifs.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o
|
||||
obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o
|
||||
|
||||
# The global Rules.make.
|
||||
|
||||
include $(TOPDIR)/drivers/isdn/Rules.make
|
||||
|
||||
# Link rules for multi-part drivers.
|
||||
|
||||
kernelcapi.o: $(kernelcapi-objs)
|
||||
$(LD) -r -o $@ $(kernelcapi-objs)
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
|
|
@ -0,0 +1,543 @@
|
|||
/* $Id$
|
||||
*
|
||||
* A PCMCIA client driver for AVM B1/M1/M2
|
||||
*
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/major.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
#include <pcmcia/ds.h>
|
||||
#include <pcmcia/cisreg.h>
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/b1lli.h>
|
||||
#include <linux/b1pcmcia.h>
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Parameters that can be set with 'insmod' */
|
||||
|
||||
/* This means pick from 15, 12, 11, 10, 9, 7, 5, 4, and 3 */
|
||||
static int default_irq_list[10] = { 15, 12, 11, 10, 9, 7, 5, 4, 3, -1 };
|
||||
static int irq_list[10] = { -1 };
|
||||
|
||||
MODULE_PARM(irq_list, "1-10i");
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/*
|
||||
The event() function is this driver's Card Services event handler.
|
||||
It will be called by Card Services when an appropriate card status
|
||||
event is received. The config() and release() entry points are
|
||||
used to configure or release a socket, in response to card insertion
|
||||
and ejection events. They are invoked from the skeleton event
|
||||
handler.
|
||||
*/
|
||||
|
||||
static void avmcs_config(dev_link_t *link);
|
||||
static void avmcs_release(u_long arg);
|
||||
static int avmcs_event(event_t event, int priority,
|
||||
event_callback_args_t *args);
|
||||
|
||||
/*
|
||||
The attach() and detach() entry points are used to create and destroy
|
||||
"instances" of the driver, where each instance represents everything
|
||||
needed to manage one actual PCMCIA card.
|
||||
*/
|
||||
|
||||
static dev_link_t *avmcs_attach(void);
|
||||
static void avmcs_detach(dev_link_t *);
|
||||
|
||||
/*
|
||||
The dev_info variable is the "key" that is used to match up this
|
||||
device driver with appropriate cards, through the card configuration
|
||||
database.
|
||||
*/
|
||||
|
||||
static dev_info_t dev_info = "avm_cs";
|
||||
|
||||
/*
|
||||
A linked list of "instances" of the skeleton device. Each actual
|
||||
PCMCIA card corresponds to one device instance, and is described
|
||||
by one dev_link_t structure (defined in ds.h).
|
||||
|
||||
You may not want to use a linked list for this -- for example, the
|
||||
memory card driver uses an array of dev_link_t pointers, where minor
|
||||
device numbers are used to derive the corresponding array index.
|
||||
*/
|
||||
|
||||
static dev_link_t *dev_list = NULL;
|
||||
|
||||
/*
|
||||
A dev_link_t structure has fields for most things that are needed
|
||||
to keep track of a socket, but there will usually be some device
|
||||
specific information that also needs to be kept track of. The
|
||||
'priv' pointer in a dev_link_t structure can be used to point to
|
||||
a device-specific private data structure, like this.
|
||||
|
||||
A driver needs to provide a dev_node_t structure for each device
|
||||
on a card. In some cases, there is only one device per card (for
|
||||
example, ethernet cards, modems). In other cases, there may be
|
||||
many actual or logical devices (SCSI adapters, memory cards with
|
||||
multiple partitions). The dev_node_t structures need to be kept
|
||||
in a linked list starting at the 'dev' field of a dev_link_t
|
||||
structure. We allocate them in the card's private data structure,
|
||||
because they generally can't be allocated dynamically.
|
||||
*/
|
||||
|
||||
typedef struct local_info_t {
|
||||
dev_node_t node;
|
||||
} local_info_t;
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void cs_error(client_handle_t handle, int func, int ret)
|
||||
{
|
||||
error_info_t err = { func, ret };
|
||||
CardServices(ReportError, handle, &err);
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
avmcs_attach() creates an "instance" of the driver, allocating
|
||||
local data structures for one device. The device is registered
|
||||
with Card Services.
|
||||
|
||||
The dev_link structure is initialized, but we don't actually
|
||||
configure the card at this point -- we wait until we receive a
|
||||
card insertion event.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static dev_link_t *avmcs_attach(void)
|
||||
{
|
||||
client_reg_t client_reg;
|
||||
dev_link_t *link;
|
||||
local_info_t *local;
|
||||
int ret, i;
|
||||
|
||||
/* Initialize the dev_link_t structure */
|
||||
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
|
||||
if (!link)
|
||||
return NULL;
|
||||
memset(link, 0, sizeof(struct dev_link_t));
|
||||
link->release.function = &avmcs_release;
|
||||
link->release.data = (u_long)link;
|
||||
|
||||
/* The io structure describes IO port mapping */
|
||||
link->io.NumPorts1 = 16;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts2 = 0;
|
||||
|
||||
/* Interrupt setup */
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
|
||||
|
||||
link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
|
||||
if (irq_list[0] != -1) {
|
||||
for (i = 0; i < 10 && irq_list[i] > 0; i++)
|
||||
link->irq.IRQInfo2 |= 1 << irq_list[i];
|
||||
} else {
|
||||
for (i = 0; i < 10 && default_irq_list[i] > 0; i++)
|
||||
link->irq.IRQInfo2 |= 1 << default_irq_list[i];
|
||||
}
|
||||
|
||||
/* General socket configuration */
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.Vcc = 50;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
link->conf.ConfigIndex = 1;
|
||||
link->conf.Present = PRESENT_OPTION;
|
||||
|
||||
/* Allocate space for private device-specific data */
|
||||
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
|
||||
if (!local)
|
||||
return NULL;
|
||||
memset(local, 0, sizeof(local_info_t));
|
||||
link->priv = local;
|
||||
|
||||
/* Register with Card Services */
|
||||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &avmcs_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
ret = CardServices(RegisterClient, &link->handle, &client_reg);
|
||||
if (ret != 0) {
|
||||
cs_error(link->handle, RegisterClient, ret);
|
||||
avmcs_detach(link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link;
|
||||
} /* avmcs_attach */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
This deletes a driver "instance". The device is de-registered
|
||||
with Card Services. If it has been released, all local data
|
||||
structures are freed. Otherwise, the structures will be freed
|
||||
when the device is released.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void avmcs_detach(dev_link_t *link)
|
||||
{
|
||||
dev_link_t **linkp;
|
||||
|
||||
/* Locate device structure */
|
||||
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
|
||||
if (*linkp == link) break;
|
||||
if (*linkp == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
If the device is currently configured and active, we won't
|
||||
actually delete it yet. Instead, it is marked so that when
|
||||
the release() function is called, that will trigger a proper
|
||||
detach().
|
||||
*/
|
||||
if (link->state & DEV_CONFIG) {
|
||||
link->state |= DEV_STALE_LINK;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Break the link with Card Services */
|
||||
if (link->handle)
|
||||
CardServices(DeregisterClient, link->handle);
|
||||
|
||||
/* Unlink device structure, free pieces */
|
||||
*linkp = link->next;
|
||||
if (link->priv) {
|
||||
kfree(link->priv);
|
||||
}
|
||||
kfree(link);
|
||||
|
||||
} /* avmcs_detach */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
avmcs_config() is scheduled to run after a CARD_INSERTION event
|
||||
is received, to configure the PCMCIA socket, and to make the
|
||||
ethernet device available to the system.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
|
||||
cisparse_t *parse)
|
||||
{
|
||||
int i;
|
||||
i = CardServices(fn, handle, tuple);
|
||||
if (i != CS_SUCCESS) return i;
|
||||
i = CardServices(GetTupleData, handle, tuple);
|
||||
if (i != CS_SUCCESS) return i;
|
||||
return CardServices(ParseTuple, handle, tuple, parse);
|
||||
}
|
||||
|
||||
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
|
||||
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
|
||||
|
||||
static void avmcs_config(dev_link_t *link)
|
||||
{
|
||||
client_handle_t handle;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
|
||||
local_info_t *dev;
|
||||
int i;
|
||||
u_char buf[64];
|
||||
char devname[128];
|
||||
int cardtype;
|
||||
int (*addcard)(unsigned int port, unsigned irq);
|
||||
|
||||
handle = link->handle;
|
||||
dev = link->priv;
|
||||
|
||||
/*
|
||||
This reads the card's CONFIG tuple to find its configuration
|
||||
registers.
|
||||
*/
|
||||
do {
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
i = CardServices(GetFirstTuple, handle, &tuple);
|
||||
if (i != CS_SUCCESS) break;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = 64;
|
||||
tuple.TupleOffset = 0;
|
||||
i = CardServices(GetTupleData, handle, &tuple);
|
||||
if (i != CS_SUCCESS) break;
|
||||
i = CardServices(ParseTuple, handle, &tuple, &parse);
|
||||
if (i != CS_SUCCESS) break;
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
} while (0);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, ParseTuple, i);
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure card */
|
||||
link->state |= DEV_CONFIG;
|
||||
|
||||
do {
|
||||
|
||||
tuple.Attributes = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = 254;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.DesiredTuple = CISTPL_VERS_1;
|
||||
|
||||
devname[0] = 0;
|
||||
if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
|
||||
strncpy(devname,parse.version_1.str + parse.version_1.ofs[1],
|
||||
sizeof(devname));
|
||||
}
|
||||
/*
|
||||
* find IO port
|
||||
*/
|
||||
tuple.TupleData = (cisdata_t *)buf;
|
||||
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
|
||||
tuple.Attributes = 0;
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
while (i == CS_SUCCESS) {
|
||||
if (cf->io.nwin > 0) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
link->io.BasePort1 = cf->io.win[0].base;
|
||||
link->io.NumPorts1 = cf->io.win[0].len;
|
||||
link->io.NumPorts2 = 0;
|
||||
printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
|
||||
link->io.BasePort1,
|
||||
link->io.BasePort1+link->io.NumPorts1-1);
|
||||
i = CardServices(RequestIO, link->handle, &link->io);
|
||||
if (i == CS_SUCCESS) goto found_port;
|
||||
}
|
||||
i = next_tuple(handle, &tuple, &parse);
|
||||
}
|
||||
|
||||
found_port:
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestIO, i);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate an interrupt line
|
||||
*/
|
||||
i = CardServices(RequestIRQ, link->handle, &link->irq);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestIRQ, i);
|
||||
CardServices(ReleaseIO, link->handle, &link->io);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* configure the PCMCIA socket
|
||||
*/
|
||||
i = CardServices(RequestConfiguration, link->handle, &link->conf);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestConfiguration, i);
|
||||
CardServices(ReleaseIO, link->handle, &link->io);
|
||||
CardServices(ReleaseIRQ, link->handle, &link->irq);
|
||||
break;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
/* At this point, the dev_node_t structure(s) should be
|
||||
initialized and arranged in a linked list at link->dev. */
|
||||
|
||||
if (devname[0]) {
|
||||
char *s = strrchr(devname, ' ');
|
||||
if (!s)
|
||||
s = devname;
|
||||
else s++;
|
||||
strcpy(dev->node.dev_name, s);
|
||||
if (strcmp("M1", s) == 0) {
|
||||
cardtype = AVM_CARDTYPE_M1;
|
||||
} else if (strcmp("M2", s) == 0) {
|
||||
cardtype = AVM_CARDTYPE_M2;
|
||||
} else {
|
||||
cardtype = AVM_CARDTYPE_B1;
|
||||
}
|
||||
} else {
|
||||
strcpy(dev->node.dev_name, "b1");
|
||||
cardtype = AVM_CARDTYPE_B1;
|
||||
}
|
||||
|
||||
dev->node.major = 64;
|
||||
dev->node.minor = 0;
|
||||
link->dev = &dev->node;
|
||||
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
/* If any step failed, release any partially configured state */
|
||||
if (i != 0) {
|
||||
avmcs_release((u_long)link);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (cardtype) {
|
||||
case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
|
||||
case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
|
||||
default:
|
||||
case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
|
||||
}
|
||||
if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
|
||||
printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
|
||||
dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
avmcs_release((u_long)link);
|
||||
return;
|
||||
}
|
||||
dev->node.minor = i;
|
||||
|
||||
} /* avmcs_config */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
After a card is removed, avmcs_release() will unregister the net
|
||||
device, and release the PCMCIA configuration. If the device is
|
||||
still open, this will be postponed until it is closed.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void avmcs_release(u_long arg)
|
||||
{
|
||||
dev_link_t *link = (dev_link_t *)arg;
|
||||
|
||||
/*
|
||||
If the device is currently in use, we won't release until it
|
||||
is actually closed.
|
||||
*/
|
||||
if (link->open) {
|
||||
link->state |= DEV_STALE_CONFIG;
|
||||
return;
|
||||
}
|
||||
|
||||
b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
|
||||
/* Unlink the device chain */
|
||||
link->dev = NULL;
|
||||
|
||||
/* Don't bother checking to see if these succeed or not */
|
||||
CardServices(ReleaseConfiguration, link->handle);
|
||||
CardServices(ReleaseIO, link->handle, &link->io);
|
||||
CardServices(ReleaseIRQ, link->handle, &link->irq);
|
||||
link->state &= ~DEV_CONFIG;
|
||||
|
||||
if (link->state & DEV_STALE_LINK)
|
||||
avmcs_detach(link);
|
||||
|
||||
} /* avmcs_release */
|
||||
|
||||
/*======================================================================
|
||||
|
||||
The card status event handler. Mostly, this schedules other
|
||||
stuff to run after an event is received. A CARD_REMOVAL event
|
||||
also sets some flags to discourage the net drivers from trying
|
||||
to talk to the card any more.
|
||||
|
||||
When a CARD_REMOVAL event is received, we immediately set a flag
|
||||
to block future accesses to this device. All the functions that
|
||||
actually access the device should check this flag to make sure
|
||||
the card is still present.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int avmcs_event(event_t event, int priority,
|
||||
event_callback_args_t *args)
|
||||
{
|
||||
dev_link_t *link = args->client_data;
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
link->state &= ~DEV_PRESENT;
|
||||
if (link->state & DEV_CONFIG) {
|
||||
link->release.expires = jiffies + (HZ/20);
|
||||
add_timer(&link->release);
|
||||
}
|
||||
break;
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||
avmcs_config(link);
|
||||
break;
|
||||
case CS_EVENT_PM_SUSPEND:
|
||||
link->state |= DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
if (link->state & DEV_CONFIG)
|
||||
CardServices(ReleaseConfiguration, link->handle);
|
||||
break;
|
||||
case CS_EVENT_PM_RESUME:
|
||||
link->state &= ~DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_CARD_RESET:
|
||||
if (link->state & DEV_CONFIG)
|
||||
CardServices(RequestConfiguration, link->handle, &link->conf);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
} /* avmcs_event */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int __init avmcs_init(void)
|
||||
{
|
||||
servinfo_t serv;
|
||||
CardServices(GetCardServicesInfo, &serv);
|
||||
if (serv.Revision != CS_RELEASE_CODE) {
|
||||
printk(KERN_NOTICE "avm_cs: Card Services release "
|
||||
"does not match!\n");
|
||||
return -1;
|
||||
}
|
||||
register_pccard_driver(&dev_info, &avmcs_attach, &avmcs_detach);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit avmcs_exit(void)
|
||||
{
|
||||
unregister_pccard_driver(&dev_info);
|
||||
while (dev_list != NULL) {
|
||||
if (dev_list->state & DEV_CONFIG)
|
||||
avmcs_release((u_long)dev_list);
|
||||
avmcs_detach(dev_list);
|
||||
}
|
||||
}
|
||||
|
||||
module_init(avmcs_init);
|
||||
module_exit(avmcs_exit);
|
|
@ -1,48 +1,9 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.6 1999/11/05 16:38:01 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.5 1999/09/07 09:02:53 calle
|
||||
* SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
|
||||
* DATA_B3_IND is always directly after the CAPI message. The "Data" member
|
||||
* ist never used inside the kernel.
|
||||
*
|
||||
* Revision 1.4 1999/08/04 10:10:08 calle
|
||||
* Bugfix: corrected /proc functions, added structure for new AVM cards.
|
||||
*
|
||||
* Revision 1.3 1999/07/23 08:41:47 calle
|
||||
* prepared for new AVM cards.
|
||||
*
|
||||
* Revision 1.2 1999/07/05 15:09:45 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.1 1999/07/01 15:26:22 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -51,7 +12,6 @@
|
|||
|
||||
#define AVMB1_PORTLEN 0x1f
|
||||
#define AVM_MAXVERSION 8
|
||||
#define AVM_NAPPS 30
|
||||
#define AVM_NCCI_PER_CHANNEL 4
|
||||
|
||||
/*
|
||||
|
@ -75,7 +35,8 @@ enum avmcardtype {
|
|||
avm_m2,
|
||||
avm_t1isa,
|
||||
avm_t1pci,
|
||||
avm_c4
|
||||
avm_c4,
|
||||
avm_c2
|
||||
};
|
||||
|
||||
typedef struct avmcard_dmainfo {
|
||||
|
@ -342,13 +303,13 @@ static inline unsigned int b1_rd_reg(unsigned int base,
|
|||
static inline void b1_reset(unsigned int base)
|
||||
{
|
||||
b1outp(base, B1_RESET, 0);
|
||||
udelay(55 * 2 * 1000); /* 2 TIC's */
|
||||
mdelay(55 * 2); /* 2 TIC's */
|
||||
|
||||
b1outp(base, B1_RESET, 1);
|
||||
udelay(55 * 2 * 1000); /* 2 TIC's */
|
||||
mdelay(55 * 2); /* 2 TIC's */
|
||||
|
||||
b1outp(base, B1_RESET, 0);
|
||||
udelay(55 * 2 * 1000); /* 2 TIC's */
|
||||
mdelay(55 * 2); /* 2 TIC's */
|
||||
}
|
||||
|
||||
static inline unsigned char b1_disable_irq(unsigned int base)
|
||||
|
|
|
@ -1,73 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Common module for AVM B1 cards.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.12 1999/11/05 16:38:01 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.11 1999/10/11 22:04:12 keil
|
||||
* COMPAT_NEED_UACCESS (no include in isdn_compat.h)
|
||||
*
|
||||
* Revision 1.10 1999/09/15 08:16:03 calle
|
||||
* Implementation of 64Bit extention complete.
|
||||
*
|
||||
* Revision 1.9 1999/09/07 09:02:53 calle
|
||||
* SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
|
||||
* DATA_B3_IND is always directly after the CAPI message. The "Data" member
|
||||
* ist never used inside the kernel.
|
||||
*
|
||||
* Revision 1.8 1999/08/22 20:26:22 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.7 1999/08/04 10:10:09 calle
|
||||
* Bugfix: corrected /proc functions, added structure for new AVM cards.
|
||||
*
|
||||
* Revision 1.6 1999/07/23 08:51:04 calle
|
||||
* small fix and typo in checkin before.
|
||||
*
|
||||
* Revision 1.5 1999/07/23 08:41:48 calle
|
||||
* prepared for new AVM cards.
|
||||
*
|
||||
* Revision 1.4 1999/07/09 15:05:38 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.3 1999/07/06 07:41:59 calle
|
||||
* - changes in /proc interface
|
||||
* - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
|
||||
*
|
||||
* Revision 1.2 1999/07/05 15:09:47 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.1 1999/07/01 15:26:23 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -79,11 +17,12 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#ifdef COMPAT_NEED_UACCESS
|
||||
#include <asm/uaccess.h>
|
||||
#endif
|
||||
#include <linux/netdevice.h>
|
||||
#include "capilli.h"
|
||||
#include "avmcard.h"
|
||||
#include "capicmd.h"
|
||||
|
@ -93,7 +32,9 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -334,7 +275,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
|
|||
cli();
|
||||
b1_setinterrupt(port, card->irq, card->cardtype);
|
||||
b1_put_byte(port, SEND_INIT);
|
||||
b1_put_word(port, AVM_NAPPS);
|
||||
b1_put_word(port, CAPI_MAXAPPL);
|
||||
b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
|
||||
b1_put_word(port, ctrl->cnr - 1);
|
||||
restore_flags(flags);
|
||||
|
@ -418,7 +359,7 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
|
|||
b1_put_slice(port, skb->data, len);
|
||||
}
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -591,25 +532,29 @@ void b1_handle_interrupt(avmcard * card)
|
|||
ctrl->ready(ctrl);
|
||||
break;
|
||||
|
||||
case RECEIVE_TASK_READY:
|
||||
case RECEIVE_TASK_READY:
|
||||
ApplId = (unsigned) b1_get_word(card->port);
|
||||
MsgLen = b1_get_slice(card->port, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
|
||||
card->name, ApplId, card->msgbuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_DEBUGMSG:
|
||||
case RECEIVE_DEBUGMSG:
|
||||
MsgLen = b1_get_slice(card->port, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
|
||||
break;
|
||||
|
||||
|
@ -645,6 +590,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
|
|||
case avm_t1isa: s = "T1 ISA (HEMA)"; break;
|
||||
case avm_t1pci: s = "T1 PCI"; break;
|
||||
case avm_c4: s = "C4"; break;
|
||||
case avm_c2: s = "C2"; break;
|
||||
default: s = "???"; break;
|
||||
}
|
||||
len += sprintf(page+len, "%-16s %s\n", "type", s);
|
||||
|
@ -712,20 +658,16 @@ EXPORT_SYMBOL(b1_handle_interrupt);
|
|||
|
||||
EXPORT_SYMBOL(b1ctl_read_proc);
|
||||
|
||||
#ifdef MODULE
|
||||
#define b1_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
int b1_init(void)
|
||||
static int __init b1_init(void)
|
||||
{
|
||||
char *p;
|
||||
char rev[10];
|
||||
char rev[32];
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(rev, p + 1, sizeof(rev));
|
||||
p = strchr(rev, '$');
|
||||
*p = 0;
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(rev, p + 2, sizeof(rev));
|
||||
rev[sizeof(rev)-1] = 0;
|
||||
if ((p = strchr(rev, '$')) != 0 && p > rev)
|
||||
*(p-1) = 0;
|
||||
} else
|
||||
strcpy(rev, "1.0");
|
||||
|
||||
|
@ -734,8 +676,9 @@ int b1_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit b1_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(b1_init);
|
||||
module_exit(b1_exit);
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Common module for AVM B1 cards that support dma with AMCC
|
||||
*
|
||||
* (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.2 2000/01/25 14:44:47 calle
|
||||
* typo in b1pciv4_detect().
|
||||
*
|
||||
* Revision 1.1 2000/01/25 14:36:43 calle
|
||||
* common function for T1 PCI and B1 PCI V4.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -24,23 +18,30 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#ifdef COMPAT_NEED_UACCESS
|
||||
#include <asm/uaccess.h>
|
||||
#endif
|
||||
#include <linux/netdevice.h>
|
||||
#include "capilli.h"
|
||||
#include "avmcard.h"
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
|
||||
#if BITS_PER_LONG != 32
|
||||
#error FIXME: driver requires 32-bit platform
|
||||
#endif
|
||||
|
||||
static char *revision = "$Revision$";
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
int suppress_pollack = 0;
|
||||
static int suppress_pollack = 0;
|
||||
MODULE_PARM(suppress_pollack, "0-1i");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -230,14 +231,14 @@ void b1dma_reset(avmcard *card)
|
|||
restore_flags(flags);
|
||||
|
||||
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
|
||||
if (card->cardtype == avm_t1pci)
|
||||
udelay(42 * 1000);
|
||||
mdelay(42);
|
||||
else
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -245,11 +246,11 @@ void b1dma_reset(avmcard *card)
|
|||
int b1dma_detect(avmcard *card)
|
||||
{
|
||||
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
|
||||
udelay(42 * 1000);
|
||||
mdelay(42);
|
||||
|
||||
b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0);
|
||||
b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0);
|
||||
|
@ -427,7 +428,7 @@ static void b1dma_dispatch_tx(avmcard *card)
|
|||
b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
|
||||
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -551,22 +552,26 @@ static void b1dma_handle_rx(avmcard *card)
|
|||
case RECEIVE_TASK_READY:
|
||||
ApplId = (unsigned) _get_word(&p);
|
||||
MsgLen = _get_slice(&p, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
|
||||
card->name, ApplId, card->msgbuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_DEBUGMSG:
|
||||
MsgLen = _get_slice(&p, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
|
||||
break;
|
||||
|
||||
|
@ -612,13 +617,6 @@ static void b1dma_handle_interrupt(avmcard *card)
|
|||
if ((status & TX_TC_INT) != 0) {
|
||||
card->csr &= ~EN_TX_TC_INT;
|
||||
b1dma_dispatch_tx(card);
|
||||
#if 1
|
||||
} else if (card->csr & EN_TX_TC_INT) {
|
||||
if (b1dmainmeml(card->mbase+AMCC_TXLEN) == 0) {
|
||||
card->csr &= ~EN_TX_TC_INT;
|
||||
b1dma_dispatch_tx(card);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
|
||||
}
|
||||
|
@ -694,7 +692,7 @@ static void b1dma_send_init(avmcard *card)
|
|||
_put_byte(&p, 0);
|
||||
_put_byte(&p, 0);
|
||||
_put_byte(&p, SEND_INIT);
|
||||
_put_word(&p, AVM_NAPPS);
|
||||
_put_word(&p, CAPI_MAXAPPL);
|
||||
_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
|
||||
_put_word(&p, card->cardnr - 1);
|
||||
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
|
||||
|
@ -873,6 +871,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
|
|||
case avm_t1isa: s = "T1 ISA (HEMA)"; break;
|
||||
case avm_t1pci: s = "T1 PCI"; break;
|
||||
case avm_c4: s = "C4"; break;
|
||||
case avm_c2: s = "C2"; break;
|
||||
default: s = "???"; break;
|
||||
}
|
||||
len += sprintf(page+len, "%-16s %s\n", "type", s);
|
||||
|
@ -960,20 +959,16 @@ EXPORT_SYMBOL(b1dma_release_appl);
|
|||
EXPORT_SYMBOL(b1dma_send_message);
|
||||
EXPORT_SYMBOL(b1dmactl_read_proc);
|
||||
|
||||
#ifdef MODULE
|
||||
#define b1dma_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
int b1dma_init(void)
|
||||
{
|
||||
char *p;
|
||||
char rev[10];
|
||||
char rev[32];
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(rev, p + 1, sizeof(rev));
|
||||
p = strchr(rev, '$');
|
||||
*p = 0;
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(rev, p + 2, sizeof(rev));
|
||||
rev[sizeof(rev)-1] = 0;
|
||||
if ((p = strchr(rev, '$')) != 0 && p > rev)
|
||||
*(p-1) = 0;
|
||||
} else
|
||||
strcpy(rev, "1.0");
|
||||
|
||||
|
@ -982,8 +977,9 @@ int b1dma_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
void b1dma_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(b1dma_init);
|
||||
module_exit(b1dma_exit);
|
||||
|
|
|
@ -1,53 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Module for AVM B1 ISA-card.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.6 2000/01/25 14:37:39 calle
|
||||
* new message after successfull detection including card revision and
|
||||
* used resources.
|
||||
*
|
||||
* Revision 1.5 1999/11/05 16:38:01 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.4 1999/08/22 20:26:24 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.3 1999/07/09 15:05:40 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.2 1999/07/05 15:09:49 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.1 1999/07/01 15:26:27 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -59,6 +17,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include "capicmd.h"
|
||||
|
@ -70,7 +29,9 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -237,37 +198,36 @@ static char *b1isa_procinfo(struct capi_ctr *ctrl)
|
|||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_driver b1isa_driver = {
|
||||
"b1isa",
|
||||
"0.0",
|
||||
b1_load_firmware,
|
||||
b1_reset_ctr,
|
||||
b1isa_remove_ctr,
|
||||
b1_register_appl,
|
||||
b1_release_appl,
|
||||
b1_send_message,
|
||||
name: "b1isa",
|
||||
revision: "0.0",
|
||||
load_firmware: b1_load_firmware,
|
||||
reset_ctr: b1_reset_ctr,
|
||||
remove_ctr: b1isa_remove_ctr,
|
||||
register_appl: b1_register_appl,
|
||||
release_appl: b1_release_appl,
|
||||
send_message: b1_send_message,
|
||||
|
||||
b1isa_procinfo,
|
||||
b1ctl_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: b1isa_procinfo,
|
||||
ctr_read_proc: b1ctl_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
b1isa_add_card,
|
||||
add_card: b1isa_add_card,
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
#define b1isa_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
int b1isa_init(void)
|
||||
static int __init b1isa_init(void)
|
||||
{
|
||||
struct capi_driver *driver = &b1isa_driver;
|
||||
char *p;
|
||||
int retval = 0;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(driver->revision, p + 1, sizeof(driver->revision));
|
||||
p = strchr(driver->revision, '$');
|
||||
*p = 0;
|
||||
}
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driver->revision, p + 2, sizeof(driver->revision));
|
||||
driver->revision[sizeof(driver->revision)-1] = 0;
|
||||
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
|
||||
|
||||
|
@ -276,14 +236,16 @@ int b1isa_init(void)
|
|||
if (!di) {
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driver->name);
|
||||
return -EIO;
|
||||
retval = -EIO;
|
||||
}
|
||||
return 0;
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit b1isa_exit(void)
|
||||
{
|
||||
detach_capi_driver(&b1isa_driver);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(b1isa_init);
|
||||
module_exit(b1isa_exit);
|
||||
|
|
|
@ -1,57 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Module for AVM B1 PCI-card.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.19 2000/01/25 14:33:38 calle
|
||||
* - Added Support AVM B1 PCI V4.0 (tested with prototype)
|
||||
* - splitted up t1pci.c into b1dma.c for common function with b1pciv4
|
||||
* - support for revision register
|
||||
*
|
||||
* Revision 1.18 1999/11/05 16:38:01 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.17 1999/10/05 06:50:07 calle
|
||||
* Forgot SA_SHIRQ as argument to request_irq.
|
||||
*
|
||||
* Revision 1.16 1999/08/11 21:01:07 keil
|
||||
* new PCI codefix
|
||||
*
|
||||
* Revision 1.15 1999/08/10 16:02:27 calle
|
||||
* struct pci_dev changed in 2.3.13. Made the necessary changes.
|
||||
*
|
||||
* Revision 1.14 1999/07/09 15:05:41 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.13 1999/07/05 15:09:50 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.12 1999/07/01 15:26:29 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -66,6 +20,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/capi.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
|
@ -76,17 +31,17 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#ifndef PCI_VENDOR_ID_AVM
|
||||
#define PCI_VENDOR_ID_AVM 0x1244
|
||||
#ifndef COMPAT_HAS_2_2_PCI
|
||||
static struct pci_device_id b1pci_pci_tbl[] __initdata = {
|
||||
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_AVM_B1
|
||||
#define PCI_DEVICE_ID_AVM_B1 0x700
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -249,20 +204,20 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_driver b1pci_driver = {
|
||||
"b1pci",
|
||||
"0.0",
|
||||
b1_load_firmware,
|
||||
b1_reset_ctr,
|
||||
b1pci_remove_ctr,
|
||||
b1_register_appl,
|
||||
b1_release_appl,
|
||||
b1_send_message,
|
||||
name: "b1pci",
|
||||
revision: "0.0",
|
||||
load_firmware: b1_load_firmware,
|
||||
reset_ctr: b1_reset_ctr,
|
||||
remove_ctr: b1pci_remove_ctr,
|
||||
register_appl: b1_register_appl,
|
||||
release_appl: b1_release_appl,
|
||||
send_message: b1_send_message,
|
||||
|
||||
b1pci_procinfo,
|
||||
b1ctl_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: b1pci_procinfo,
|
||||
ctr_read_proc: b1ctl_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
0, /* no add_card function */
|
||||
add_card: 0, /* no add_card function */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
|
@ -281,7 +236,7 @@ static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
|
|||
|
||||
div4->detach_ctr(ctrl);
|
||||
free_irq(card->irq, card);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
ctrl->driverdata = 0;
|
||||
kfree(card->ctrlinfo);
|
||||
|
@ -312,15 +267,17 @@ static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
|
|||
|
||||
static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
||||
{
|
||||
unsigned long base, page_offset;
|
||||
avmcard *card;
|
||||
avmctrl_info *cinfo;
|
||||
int retval;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
|
||||
|
||||
if (!card) {
|
||||
printk(KERN_WARNING "%s: no memory.\n", driver->name);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(card, 0, sizeof(avmcard));
|
||||
|
@ -328,6 +285,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
if (!card->dma) {
|
||||
printk(KERN_WARNING "%s: no memory.\n", driver->name);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(card->dma, 0, sizeof(avmcard_dmainfo));
|
||||
|
@ -336,6 +294,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
printk(KERN_WARNING "%s: no memory.\n", driver->name);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(cinfo, 0, sizeof(avmctrl_info));
|
||||
|
@ -354,20 +313,18 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
base = card->membase & PAGE_MASK;
|
||||
page_offset = card->membase - base;
|
||||
card->mbase = ioremap_nocache(base, page_offset + 64);
|
||||
if (card->mbase) {
|
||||
card->mbase += page_offset;
|
||||
} else {
|
||||
card->mbase = ioremap_nocache(card->membase, 64);
|
||||
if (!card->mbase) {
|
||||
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
|
||||
driver->name, card->membase);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -376,10 +333,11 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
if ((retval = b1pciv4_detect(card)) != 0) {
|
||||
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
|
||||
driver->name, card->port, retval);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EIO;
|
||||
}
|
||||
b1dma_reset(card);
|
||||
|
@ -391,23 +349,25 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
if (retval) {
|
||||
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
|
||||
driver->name, card->irq);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
cinfo->capi_ctrl = div4->attach_ctr(driver, card->name, cinfo);
|
||||
if (!cinfo->capi_ctrl) {
|
||||
printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
free_irq(card->irq, card);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EBUSY;
|
||||
}
|
||||
card->cardnr = cinfo->capi_ctrl->cnr;
|
||||
|
@ -419,8 +379,6 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
driver->name, card->port, card->irq,
|
||||
card->membase, card->revision);
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -428,29 +386,24 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
|
|||
|
||||
|
||||
static struct capi_driver b1pciv4_driver = {
|
||||
"b1pciv4",
|
||||
"0.0",
|
||||
b1dma_load_firmware,
|
||||
b1dma_reset_ctr,
|
||||
b1pciv4_remove_ctr,
|
||||
b1dma_register_appl,
|
||||
b1dma_release_appl,
|
||||
b1dma_send_message,
|
||||
name: "b1pciv4",
|
||||
revision: "0.0",
|
||||
load_firmware: b1dma_load_firmware,
|
||||
reset_ctr: b1dma_reset_ctr,
|
||||
remove_ctr: b1pciv4_remove_ctr,
|
||||
register_appl: b1dma_register_appl,
|
||||
release_appl: b1dma_release_appl,
|
||||
send_message: b1dma_send_message,
|
||||
|
||||
b1pciv4_procinfo,
|
||||
b1dmactl_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: b1pciv4_procinfo,
|
||||
ctr_read_proc: b1dmactl_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
0, /* no add_card function */
|
||||
add_card: 0, /* no add_card function */
|
||||
};
|
||||
|
||||
#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
|
||||
|
||||
#ifdef MODULE
|
||||
#define b1pci_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
static int ncards = 0;
|
||||
|
||||
static int add_card(struct pci_dev *dev)
|
||||
|
@ -459,13 +412,22 @@ static int add_card(struct pci_dev *dev)
|
|||
struct capicardparams param;
|
||||
int retval;
|
||||
|
||||
if (get_pcibase(dev, 2) & PCI_BASE_ADDRESS_IO_MASK) { /* B1 PCI V4 */
|
||||
if (pci_enable_device(dev) < 0) {
|
||||
printk(KERN_ERR "%s: failed to enable AVM-B1\n",
|
||||
driver->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
param.irq = dev->irq;
|
||||
|
||||
if (pci_resource_start_io(dev, 2)) { /* B1 PCI V4 */
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
driver = &b1pciv4_driver;
|
||||
|
||||
pci_set_master(dev);
|
||||
#endif
|
||||
param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
param.port = get_pcibase(dev, 2) & PCI_BASE_ADDRESS_IO_MASK;
|
||||
param.irq = dev->irq;
|
||||
param.membase = pci_resource_start_mem(dev, 0);
|
||||
param.port = pci_resource_start_io(dev, 2);
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
|
||||
driver->name, param.port, param.irq, param.membase);
|
||||
|
@ -481,8 +443,8 @@ static int add_card(struct pci_dev *dev)
|
|||
}
|
||||
} else {
|
||||
param.membase = 0;
|
||||
param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
|
||||
param.irq = dev->irq;
|
||||
param.port = pci_resource_start_io(dev, 1);
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
|
||||
driver->name, param.port, param.irq);
|
||||
|
@ -496,7 +458,7 @@ static int add_card(struct pci_dev *dev)
|
|||
return retval;
|
||||
}
|
||||
|
||||
int b1pci_init(void)
|
||||
static int __init b1pci_init(void)
|
||||
{
|
||||
struct capi_driver *driver = &b1pci_driver;
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
|
@ -504,76 +466,73 @@ int b1pci_init(void)
|
|||
#endif
|
||||
struct pci_dev *dev = NULL;
|
||||
char *p;
|
||||
int retval;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(driver->revision, p + 1, sizeof(driver->revision));
|
||||
p = strchr(driver->revision, '$');
|
||||
*p = 0;
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driver->revision, p + 2, sizeof(driver->revision));
|
||||
driver->revision[sizeof(driver->revision)-1] = 0;
|
||||
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driverv4->revision, p + 2, sizeof(driverv4->revision));
|
||||
driverv4->revision[sizeof(driverv4->revision)-1] = 0;
|
||||
if ((p = strchr(driverv4->revision, '$')) != 0 && p > driverv4->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
|
||||
|
||||
di = attach_capi_driver(driver);
|
||||
|
||||
if (!di) {
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driver->name);
|
||||
return -EIO;
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
printk(KERN_INFO "%s: revision %s\n", driverv4->name, driverv4->revision);
|
||||
|
||||
div4 = attach_capi_driver(driverv4);
|
||||
|
||||
if (!div4) {
|
||||
detach_capi_driver(driver);
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driverv4->name);
|
||||
return -EIO;
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (!pci_present()) {
|
||||
printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
|
||||
detach_capi_driver(driver);
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
detach_capi_driver(driverv4);
|
||||
#endif
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) {
|
||||
retval = add_card(dev);
|
||||
if (retval != 0) {
|
||||
#ifdef MODULE
|
||||
cleanup_module();
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
ncards++;
|
||||
if (add_card(dev) == 0)
|
||||
ncards++;
|
||||
}
|
||||
if (ncards) {
|
||||
printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n",
|
||||
driver->name, ncards);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name);
|
||||
return -ESRCH;
|
||||
#else
|
||||
printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
|
||||
return -EIO;
|
||||
detach_capi_driver(driver);
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
detach_capi_driver(driverv4);
|
||||
#endif
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit b1pci_exit(void)
|
||||
{
|
||||
detach_capi_driver(&b1pci_driver);
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
|
||||
detach_capi_driver(&b1pciv4_driver);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(b1pci_init);
|
||||
module_exit(b1pci_exit);
|
||||
|
|
|
@ -1,53 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Module for AVM B1/M1/M2 PCMCIA-card.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.6 2000/01/25 14:37:39 calle
|
||||
* new message after successfull detection including card revision and
|
||||
* used resources.
|
||||
*
|
||||
* Revision 1.5 1999/11/05 16:38:01 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.4 1999/08/22 20:26:26 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.3 1999/07/09 15:05:41 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.2 1999/07/05 15:09:51 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.1 1999/07/01 15:26:30 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -58,10 +16,10 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/b1pcmcia.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
#include "capilli.h"
|
||||
|
@ -71,7 +29,9 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -229,20 +189,20 @@ static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
|
|||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_driver b1pcmcia_driver = {
|
||||
"b1pcmcia",
|
||||
"0.0",
|
||||
b1_load_firmware,
|
||||
b1_reset_ctr,
|
||||
b1pcmcia_remove_ctr,
|
||||
b1_register_appl,
|
||||
b1_release_appl,
|
||||
b1_send_message,
|
||||
name: "b1pcmcia",
|
||||
revision: "0.0",
|
||||
load_firmware: b1_load_firmware,
|
||||
reset_ctr: b1_reset_ctr,
|
||||
remove_ctr: b1pcmcia_remove_ctr,
|
||||
register_appl: b1_register_appl,
|
||||
release_appl: b1_release_appl,
|
||||
send_message: b1_send_message,
|
||||
|
||||
b1pcmcia_procinfo,
|
||||
b1ctl_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: b1pcmcia_procinfo,
|
||||
ctr_read_proc: b1ctl_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
0,
|
||||
add_card: 0,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -284,20 +244,19 @@ EXPORT_SYMBOL(b1pcmcia_delcard);
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#ifdef MODULE
|
||||
#define b1pcmcia_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
int b1pcmcia_init(void)
|
||||
static int __init b1pcmcia_init(void)
|
||||
{
|
||||
struct capi_driver *driver = &b1pcmcia_driver;
|
||||
char *p;
|
||||
int retval = 0;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(driver->revision, p + 1, sizeof(driver->revision));
|
||||
p = strchr(driver->revision, '$');
|
||||
*p = 0;
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driver->revision, p + 2, sizeof(driver->revision));
|
||||
driver->revision[sizeof(driver->revision)-1] = 0;
|
||||
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
|
||||
|
@ -307,14 +266,16 @@ int b1pcmcia_init(void)
|
|||
if (!di) {
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driver->name);
|
||||
return -EIO;
|
||||
retval = -EIO;
|
||||
}
|
||||
return 0;
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit b1pcmcia_exit(void)
|
||||
{
|
||||
detach_capi_driver(&b1pcmcia_driver);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(b1pcmcia_init);
|
||||
module_exit(b1pcmcia_exit);
|
||||
|
|
|
@ -1,21 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Module for AVM C4 card.
|
||||
* Module for AVM C4 & C2 card.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 2000/01/25 14:37:39 calle
|
||||
* new message after successfull detection including card revision and
|
||||
* used resources.
|
||||
*
|
||||
* Revision 1.2 2000/01/21 20:52:58 keil
|
||||
* pci_find_subsys as local function for 2.2.X kernel
|
||||
*
|
||||
* Revision 1.1 2000/01/20 10:51:37 calle
|
||||
* Added driver for C4.
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -28,9 +18,13 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
#include "capilli.h"
|
||||
|
@ -43,28 +37,20 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#ifndef PCI_VENDOR_ID_DEC
|
||||
#define PCI_VENDOR_ID_DEC 0x1011
|
||||
static int suppress_pollack;
|
||||
|
||||
#ifndef COMPAT_HAS_2_2_PCI
|
||||
static struct pci_device_id c4_pci_tbl[] __initdata = {
|
||||
{ PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4 },
|
||||
{ PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2 },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_DEC_21285
|
||||
#define PCI_DEVICE_ID_DEC_21285 0x1065
|
||||
#endif
|
||||
|
||||
#ifndef PCI_VENDOR_ID_AVM
|
||||
#define PCI_VENDOR_ID_AVM 0x1244
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_AVM_C4
|
||||
#define PCI_DEVICE_ID_AVM_C4 0x0800
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
int suppress_pollack = 0;
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_PARM(suppress_pollack, "0-1i");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -366,7 +352,7 @@ static int c4_detect(avmcard *card)
|
|||
return 8;
|
||||
if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;
|
||||
|
||||
udelay(1000);
|
||||
mdelay(1);
|
||||
|
||||
if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;
|
||||
if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;
|
||||
|
@ -378,7 +364,7 @@ static int c4_detect(avmcard *card)
|
|||
if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16;
|
||||
if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17;
|
||||
|
||||
udelay(1000);
|
||||
mdelay(1);
|
||||
|
||||
if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))
|
||||
return 18;
|
||||
|
@ -493,7 +479,7 @@ static void c4_dispatch_tx(avmcard *card)
|
|||
c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
|
||||
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -545,7 +531,7 @@ static void c4_handle_rx(avmcard *card)
|
|||
MsgLen = _get_slice(&p, card->msgbuf);
|
||||
DataB3Len = _get_slice(&p, card->databuf);
|
||||
cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
|
||||
if (cidx > 3) cidx = 0;
|
||||
if (cidx >= card->nlogcontr) cidx = 0;
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
|
||||
if (MsgLen < 30) { /* not CAPI 64Bit */
|
||||
|
@ -568,7 +554,7 @@ static void c4_handle_rx(avmcard *card)
|
|||
ApplId = (unsigned) _get_word(&p);
|
||||
MsgLen = _get_slice(&p, card->msgbuf);
|
||||
cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
|
||||
if (cidx > 3) cidx = 0;
|
||||
if (cidx >= card->nlogcontr) cidx = 0;
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
|
||||
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
|
||||
|
@ -586,7 +572,7 @@ static void c4_handle_rx(avmcard *card)
|
|||
NCCI = _get_word(&p);
|
||||
WindowSize = _get_word(&p);
|
||||
cidx = (NCCI&0x7f) - card->cardnr;
|
||||
if (cidx > 3) cidx = 0;
|
||||
if (cidx >= card->nlogcontr) cidx = 0;
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
|
||||
ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
|
||||
|
@ -600,13 +586,15 @@ static void c4_handle_rx(avmcard *card)
|
|||
|
||||
if (NCCI != 0xffffffff) {
|
||||
cidx = (NCCI&0x7f) - card->cardnr;
|
||||
if (cidx > 3) cidx = 0;
|
||||
if (cidx >= card->nlogcontr) cidx = 0;
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
ctrl->free_ncci(ctrl, ApplId, NCCI);
|
||||
if (ctrl)
|
||||
ctrl->free_ncci(ctrl, ApplId, NCCI);
|
||||
} else {
|
||||
for (cidx=0; cidx < 4; cidx++) {
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
ctrl->appl_released(ctrl, ApplId);
|
||||
if (ctrl)
|
||||
ctrl->appl_released(ctrl, ApplId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -619,20 +607,28 @@ static void c4_handle_rx(avmcard *card)
|
|||
queue_pollack(card);
|
||||
for (cidx=0; cidx < 4; cidx++) {
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
ctrl->resume_output(ctrl);
|
||||
if (ctrl)
|
||||
ctrl->resume_output(ctrl);
|
||||
}
|
||||
break;
|
||||
|
||||
case RECEIVE_STOP:
|
||||
for (cidx=0; cidx < 4; cidx++) {
|
||||
ctrl = card->ctrlinfo[cidx].capi_ctrl;
|
||||
ctrl->suspend_output(ctrl);
|
||||
if (ctrl)
|
||||
ctrl->suspend_output(ctrl);
|
||||
}
|
||||
break;
|
||||
|
||||
case RECEIVE_INIT:
|
||||
|
||||
cidx = card->nlogcontr++;
|
||||
cidx = card->nlogcontr;
|
||||
if (cidx >= 4 || !card->ctrlinfo[cidx].capi_ctrl) {
|
||||
printk(KERN_ERR "%s: card with %d controllers ??\n",
|
||||
card->name, cidx+1);
|
||||
break;
|
||||
}
|
||||
card->nlogcontr++;
|
||||
cinfo = &card->ctrlinfo[cidx];
|
||||
ctrl = cinfo->capi_ctrl;
|
||||
cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
|
||||
|
@ -647,22 +643,26 @@ static void c4_handle_rx(avmcard *card)
|
|||
case RECEIVE_TASK_READY:
|
||||
ApplId = (unsigned) _get_word(&p);
|
||||
MsgLen = _get_slice(&p, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
|
||||
card->name, ApplId, card->msgbuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_DEBUGMSG:
|
||||
MsgLen = _get_slice(&p, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
|
||||
break;
|
||||
|
||||
|
@ -682,6 +682,8 @@ static void c4_handle_interrupt(avmcard *card)
|
|||
if (status & DBELL_RESET_HOST) {
|
||||
int i;
|
||||
c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
|
||||
if (card->nlogcontr == 0)
|
||||
return;
|
||||
printk(KERN_ERR "%s: unexpected reset\n", card->name);
|
||||
for (i=0; i < 4; i++) {
|
||||
avmctrl_info *cinfo = &card->ctrlinfo[i];
|
||||
|
@ -689,6 +691,7 @@ static void c4_handle_interrupt(avmcard *card)
|
|||
if (cinfo->capi_ctrl)
|
||||
cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
|
||||
}
|
||||
card->nlogcontr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -757,7 +760,7 @@ static void c4_send_init(avmcard *card)
|
|||
_put_byte(&p, 0);
|
||||
_put_byte(&p, 0);
|
||||
_put_byte(&p, SEND_INIT);
|
||||
_put_word(&p, AVM_NAPPS);
|
||||
_put_word(&p, CAPI_MAXAPPL);
|
||||
_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
|
||||
_put_word(&p, card->cardnr - 1);
|
||||
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
|
||||
|
@ -766,45 +769,78 @@ static void c4_send_init(avmcard *card)
|
|||
c4_dispatch_tx(card);
|
||||
}
|
||||
|
||||
static int c4_send_config(avmcard *card, capiloaddatapart * config)
|
||||
static int queue_sendconfigword(avmcard *card, __u32 val)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
__u8 val[sizeof(__u32)];
|
||||
void *p;
|
||||
unsigned char *dp;
|
||||
int left, retval;
|
||||
|
||||
skb = alloc_skb(12 + ((config->len+3)/4)*5, GFP_ATOMIC);
|
||||
|
||||
skb = alloc_skb(3+4, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
printk(KERN_CRIT "%s: no memory, can't send config.\n",
|
||||
printk(KERN_CRIT "%s: no memory, send config\n",
|
||||
card->name);
|
||||
return -ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
p = skb->data;
|
||||
_put_byte(&p, 0);
|
||||
_put_byte(&p, 0);
|
||||
_put_byte(&p, SEND_CONFIG);
|
||||
_put_word(&p, 1);
|
||||
_put_word(&p, val);
|
||||
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
|
||||
|
||||
skb_queue_tail(&card->dma->send_queue, skb);
|
||||
c4_dispatch_tx(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int queue_sendconfig(avmcard *card, char cval[4])
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
void *p;
|
||||
|
||||
skb = alloc_skb(3+4, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
printk(KERN_CRIT "%s: no memory, send config\n",
|
||||
card->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
p = skb->data;
|
||||
_put_byte(&p, 0);
|
||||
_put_byte(&p, 0);
|
||||
_put_byte(&p, SEND_CONFIG);
|
||||
_put_word(&p, config->len); /* 12 */
|
||||
_put_byte(&p, cval[0]);
|
||||
_put_byte(&p, cval[1]);
|
||||
_put_byte(&p, cval[2]);
|
||||
_put_byte(&p, cval[3]);
|
||||
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
|
||||
|
||||
skb_queue_tail(&card->dma->send_queue, skb);
|
||||
c4_dispatch_tx(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int c4_send_config(avmcard *card, capiloaddatapart * config)
|
||||
{
|
||||
__u8 val[4];
|
||||
unsigned char *dp;
|
||||
int left, retval;
|
||||
|
||||
if ((retval = queue_sendconfigword(card, 1)) != 0)
|
||||
return retval;
|
||||
if ((retval = queue_sendconfigword(card, config->len)) != 0)
|
||||
return retval;
|
||||
|
||||
dp = config->data;
|
||||
left = config->len;
|
||||
while (left >= sizeof(__u32)) {
|
||||
if (config->user) {
|
||||
retval = copy_from_user(val, dp, sizeof(val));
|
||||
if (retval) {
|
||||
dev_kfree_skb(skb);
|
||||
if (retval)
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
memcpy(val, dp, sizeof(val));
|
||||
}
|
||||
_put_byte(&p, SEND_CONFIG);
|
||||
_put_byte(&p, val[0]);
|
||||
_put_byte(&p, val[1]);
|
||||
_put_byte(&p, val[2]);
|
||||
_put_byte(&p, val[3]);
|
||||
if ((retval = queue_sendconfig(card, val)) != 0)
|
||||
return retval;
|
||||
left -= sizeof(val);
|
||||
dp += sizeof(val);
|
||||
}
|
||||
|
@ -812,25 +848,15 @@ static int c4_send_config(avmcard *card, capiloaddatapart * config)
|
|||
memset(val, 0, sizeof(val));
|
||||
if (config->user) {
|
||||
retval = copy_from_user(&val, dp, left);
|
||||
if (retval) {
|
||||
dev_kfree_skb(skb);
|
||||
if (retval)
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
memcpy(&val, dp, left);
|
||||
}
|
||||
_put_byte(&p, SEND_CONFIG);
|
||||
_put_byte(&p, val[0]);
|
||||
_put_byte(&p, val[1]);
|
||||
_put_byte(&p, val[2]);
|
||||
_put_byte(&p, val[3]);
|
||||
if ((retval = queue_sendconfig(card, val)) != 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
|
||||
|
||||
skb_queue_tail(&card->dma->send_queue, skb);
|
||||
c4_dispatch_tx(card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -855,7 +881,7 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
|
|||
c4outmeml(card->mbase+MBOX_UP_LEN, 0);
|
||||
c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
|
||||
c4outmeml(card->mbase+DOORBELL, DBELL_INIT);
|
||||
udelay(1000);
|
||||
mdelay(1);
|
||||
c4outmeml(card->mbase+DOORBELL,
|
||||
DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST);
|
||||
|
||||
|
@ -867,8 +893,15 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
|
|||
c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
|
||||
restore_flags(flags);
|
||||
|
||||
if (data->configuration.len > 0 && data->configuration.data)
|
||||
c4_send_config(card, &data->configuration);
|
||||
if (data->configuration.len > 0 && data->configuration.data) {
|
||||
retval = c4_send_config(card, &data->configuration);
|
||||
if (retval) {
|
||||
printk(KERN_ERR "%s: failed to set config!!\n",
|
||||
card->name);
|
||||
c4_reset(card);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
c4_send_init(card);
|
||||
|
||||
|
@ -890,6 +923,7 @@ void c4_reset_ctr(struct capi_ctr *ctrl)
|
|||
if (cinfo->capi_ctrl)
|
||||
cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
|
||||
}
|
||||
card->nlogcontr = 0;
|
||||
}
|
||||
|
||||
static void c4_remove_ctr(struct capi_ctr *ctrl)
|
||||
|
@ -900,14 +934,16 @@ static void c4_remove_ctr(struct capi_ctr *ctrl)
|
|||
|
||||
c4_reset(card);
|
||||
|
||||
for (i=0; i <= 4; i++) {
|
||||
for (i=0; i < 4; i++) {
|
||||
cinfo = &card->ctrlinfo[i];
|
||||
if (cinfo->capi_ctrl)
|
||||
if (cinfo->capi_ctrl) {
|
||||
di->detach_ctr(cinfo->capi_ctrl);
|
||||
cinfo->capi_ctrl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free_irq(card->irq, card);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
ctrl->driverdata = 0;
|
||||
kfree(card->ctrlinfo);
|
||||
|
@ -1040,6 +1076,7 @@ static int c4_read_proc(char *page, char **start, off_t off,
|
|||
case avm_t1isa: s = "T1 ISA (HEMA)"; break;
|
||||
case avm_t1pci: s = "T1 PCI"; break;
|
||||
case avm_c4: s = "C4"; break;
|
||||
case avm_c2: s = "C2"; break;
|
||||
default: s = "???"; break;
|
||||
}
|
||||
len += sprintf(page+len, "%-16s %s\n", "type", s);
|
||||
|
@ -1087,9 +1124,10 @@ static int c4_read_proc(char *page, char **start, off_t off,
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
||||
static int c4_add_card(struct capi_driver *driver,
|
||||
struct capicardparams *p,
|
||||
int nr)
|
||||
{
|
||||
unsigned long base, page_offset;
|
||||
avmctrl_info *cinfo;
|
||||
avmcard *card;
|
||||
int retval;
|
||||
|
@ -1116,7 +1154,6 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
|
||||
if (!cinfo) {
|
||||
printk(KERN_WARNING "%s: no memory.\n", driver->name);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
|
@ -1128,11 +1165,11 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
cinfo = &card->ctrlinfo[i];
|
||||
cinfo->card = card;
|
||||
}
|
||||
sprintf(card->name, "c4-%x", p->port);
|
||||
sprintf(card->name, "%s-%x", driver->name, p->port);
|
||||
card->port = p->port;
|
||||
card->irq = p->irq;
|
||||
card->membase = p->membase;
|
||||
card->cardtype = avm_c4;
|
||||
card->cardtype = nr == 4 ? avm_c4 : avm_c2;
|
||||
|
||||
if (check_region(card->port, AVMB1_PORTLEN)) {
|
||||
printk(KERN_WARNING
|
||||
|
@ -1145,12 +1182,8 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
base = card->membase & PAGE_MASK;
|
||||
page_offset = card->membase - base;
|
||||
card->mbase = ioremap_nocache(base, page_offset + 128);
|
||||
if (card->mbase) {
|
||||
card->mbase += page_offset;
|
||||
} else {
|
||||
card->mbase = ioremap_nocache(card->membase, 128);
|
||||
if (card->mbase == 0) {
|
||||
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
|
||||
driver->name, card->membase);
|
||||
kfree(card->ctrlinfo);
|
||||
|
@ -1163,7 +1196,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
if ((retval = c4_detect(card)) != 0) {
|
||||
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
|
||||
driver->name, card->port, retval);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
|
@ -1178,7 +1211,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
if (retval) {
|
||||
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
|
||||
driver->name, card->irq);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
|
@ -1187,7 +1220,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
for (i=0; i < 4; i++) {
|
||||
for (i=0; i < nr ; i++) {
|
||||
cinfo = &card->ctrlinfo[i];
|
||||
cinfo->card = card;
|
||||
cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
|
||||
|
@ -1198,7 +1231,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
cinfo = &card->ctrlinfo[i];
|
||||
di->detach_ctr(cinfo->capi_ctrl);
|
||||
}
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
free_irq(card->irq, card);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
kfree(card->dma);
|
||||
|
@ -1214,131 +1247,160 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
skb_queue_head_init(&card->dma->send_queue);
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: AVM C4 at i/o %#x, irq %d, mem %#lx\n",
|
||||
driver->name, card->port, card->irq, card->membase);
|
||||
"%s: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
|
||||
driver->name, nr, card->port, card->irq, card->membase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_driver c4_driver = {
|
||||
"c4",
|
||||
"0.0",
|
||||
c4_load_firmware,
|
||||
c4_reset_ctr,
|
||||
c4_remove_ctr,
|
||||
c4_register_appl,
|
||||
c4_release_appl,
|
||||
c4_send_message,
|
||||
static struct capi_driver c2_driver = {
|
||||
name: "c2",
|
||||
revision: "0.0",
|
||||
load_firmware: c4_load_firmware,
|
||||
reset_ctr: c4_reset_ctr,
|
||||
remove_ctr: c4_remove_ctr,
|
||||
register_appl: c4_register_appl,
|
||||
release_appl: c4_release_appl,
|
||||
send_message: c4_send_message,
|
||||
|
||||
c4_procinfo,
|
||||
c4_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: c4_procinfo,
|
||||
ctr_read_proc: c4_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
0, /* no add_card function */
|
||||
add_card: 0, /* no add_card function */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
#define c4_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
static struct capi_driver c4_driver = {
|
||||
name: "c4",
|
||||
revision: "0.0",
|
||||
load_firmware: c4_load_firmware,
|
||||
reset_ctr: c4_reset_ctr,
|
||||
remove_ctr: c4_remove_ctr,
|
||||
register_appl: c4_register_appl,
|
||||
release_appl: c4_release_appl,
|
||||
send_message: c4_send_message,
|
||||
|
||||
#ifndef COMPAT_HAS_pci_find_subsys
|
||||
#ifndef PCI_ANY_ID
|
||||
#define PCI_ANY_ID (~0)
|
||||
#endif
|
||||
procinfo: c4_procinfo,
|
||||
ctr_read_proc: c4_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
static struct pci_dev *
|
||||
pci_find_subsys(unsigned int vendor, unsigned int device,
|
||||
unsigned int ss_vendor, unsigned int ss_device,
|
||||
struct pci_dev *from)
|
||||
{
|
||||
unsigned short subsystem_vendor, subsystem_device;
|
||||
|
||||
while ((from = pci_find_device(vendor, device, from))) {
|
||||
pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
|
||||
pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device);
|
||||
if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) &&
|
||||
(ss_device == PCI_ANY_ID || subsystem_device == ss_device))
|
||||
return from;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
add_card: 0, /* no add_card function */
|
||||
};
|
||||
|
||||
static int ncards = 0;
|
||||
|
||||
int c4_init(void)
|
||||
static int c4_attach_driver (struct capi_driver * driver)
|
||||
{
|
||||
struct capi_driver *driver = &c4_driver;
|
||||
struct pci_dev *dev = NULL;
|
||||
char *p;
|
||||
int retval;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(driver->revision, p + 1, sizeof(driver->revision));
|
||||
p = strchr(driver->revision, '$');
|
||||
*p = 0;
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driver->revision, p + 2, sizeof(driver->revision));
|
||||
driver->revision[sizeof(driver->revision)-1] = 0;
|
||||
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
|
||||
|
||||
di = attach_capi_driver(driver);
|
||||
|
||||
if (!di) {
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driver->name);
|
||||
return -EIO;
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (!pci_present()) {
|
||||
printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
|
||||
detach_capi_driver(driver);
|
||||
return -EIO;
|
||||
}
|
||||
static int __init search_cards(struct capi_driver * driver,
|
||||
int pci_id, int nr)
|
||||
{
|
||||
struct pci_dev * dev = NULL;
|
||||
int retval = 0;
|
||||
|
||||
while ((dev = pci_find_subsys(
|
||||
PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
|
||||
PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) {
|
||||
PCI_VENDOR_ID_AVM, pci_id, dev))) {
|
||||
struct capicardparams param;
|
||||
|
||||
param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
|
||||
param.irq = dev->irq;
|
||||
param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
if (pci_enable_device(dev) < 0) {
|
||||
printk(KERN_ERR "%s: failed to enable AVM-C%d\n",
|
||||
driver->name, nr);
|
||||
continue;
|
||||
}
|
||||
pci_set_master(dev);
|
||||
|
||||
param.port = pci_resource_start_io(dev, 1);
|
||||
param.irq = dev->irq;
|
||||
param.membase = pci_resource_start_mem(dev, 0);
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: PCI BIOS reports AVM-C4 at i/o %#x, irq %d, mem %#x\n",
|
||||
driver->name, param.port, param.irq, param.membase);
|
||||
retval = c4_add_card(driver, ¶m);
|
||||
"%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
|
||||
driver->name, nr, param.port, param.irq, param.membase);
|
||||
retval = c4_add_card(driver, ¶m, nr);
|
||||
if (retval != 0) {
|
||||
printk(KERN_ERR
|
||||
"%s: no AVM-C4 at i/o %#x, irq %d detected, mem %#x\n",
|
||||
driver->name, param.port, param.irq, param.membase);
|
||||
#ifdef MODULE
|
||||
cleanup_module();
|
||||
#endif
|
||||
return retval;
|
||||
"%s: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
|
||||
driver->name, nr, param.port, param.irq, param.membase);
|
||||
continue;
|
||||
}
|
||||
ncards++;
|
||||
}
|
||||
if (ncards) {
|
||||
printk(KERN_INFO "%s: %d C4 card(s) detected\n",
|
||||
driver->name, ncards);
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_ERR "%s: NO C4 card detected\n", driver->name);
|
||||
return -ESRCH;
|
||||
#else
|
||||
printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
|
||||
return -EIO;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static int __init c4_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
retval = c4_attach_driver (&c4_driver);
|
||||
if (retval) {
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = c4_attach_driver (&c2_driver);
|
||||
if (retval) {
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = search_cards(&c4_driver, PCI_DEVICE_ID_AVM_C4, 4);
|
||||
if (retval && ncards == 0) {
|
||||
detach_capi_driver(&c2_driver);
|
||||
detach_capi_driver(&c4_driver);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
retval = search_cards(&c2_driver, PCI_DEVICE_ID_AVM_C2, 2);
|
||||
if (retval && ncards == 0) {
|
||||
detach_capi_driver(&c2_driver);
|
||||
detach_capi_driver(&c4_driver);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (ncards) {
|
||||
printk(KERN_INFO "%s: %d C4/C2 card(s) detected\n",
|
||||
c4_driver.name, ncards);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_ERR "%s: NO C4/C2 card detected\n", c4_driver.name);
|
||||
detach_capi_driver(&c4_driver);
|
||||
detach_capi_driver(&c2_driver);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit c4_exit(void)
|
||||
{
|
||||
detach_capi_driver(&c2_driver);
|
||||
detach_capi_driver(&c4_driver);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(c4_init);
|
||||
module_exit(c4_exit);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,21 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* CAPI 2.0 Interface for Linux
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1997 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CAPICMD_H__
|
||||
#define __CAPICMD_H__
|
||||
|
||||
#define CAPI_MSG_BASELEN 8
|
||||
#define CAPI_DATA_B3_REQ_LEN (CAPI_MSG_BASELEN+4+4+2+2+2)
|
||||
#define CAPI_DATA_B3_RESP_LEN (CAPI_MSG_BASELEN+4+2)
|
||||
|
||||
/*----- CAPI commands -----*/
|
||||
#define CAPI_ALERT 0x01
|
||||
#define CAPI_CONNECT 0x02
|
||||
|
|
|
@ -1,45 +1,27 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* CAPI 2.0 Interface for Linux
|
||||
*
|
||||
* (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1996 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1999/07/01 08:22:58 keil
|
||||
* compatibility macros now in <linux/isdn_compat.h>
|
||||
*
|
||||
* Revision 1.2 1999/06/21 15:24:13 calle
|
||||
* extend information in /proc.
|
||||
*
|
||||
* Revision 1.1 1997/03/04 21:50:30 calle
|
||||
* Frirst version in isdn4linux
|
||||
*
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
struct capidev {
|
||||
int is_open;
|
||||
int is_registered;
|
||||
__u16 applid;
|
||||
struct sk_buff_head recv_queue;
|
||||
#ifdef COMPAT_HAS_NEW_WAITQ
|
||||
wait_queue_head_t recv_wait;
|
||||
#else
|
||||
struct wait_queue *recv_wait;
|
||||
#endif
|
||||
__u16 errcode;
|
||||
/* Statistic */
|
||||
unsigned long nopen;
|
||||
unsigned long nrecvctlpkt;
|
||||
unsigned long nrecvdatapkt;
|
||||
unsigned long nsentctlpkt;
|
||||
unsigned long nsentdatapkt;
|
||||
};
|
||||
struct capidev *next;
|
||||
struct file *file;
|
||||
__u16 applid;
|
||||
__u16 errcode;
|
||||
unsigned int minor;
|
||||
|
||||
#define CAPI_MAXMINOR CAPI_MAXAPPL
|
||||
struct sk_buff_head recv_queue;
|
||||
wait_queue_head_t recv_wait;
|
||||
|
||||
/* Statistic */
|
||||
unsigned long nrecvctlpkt;
|
||||
unsigned long nrecvdatapkt;
|
||||
unsigned long nsentctlpkt;
|
||||
unsigned long nsentdatapkt;
|
||||
};
|
||||
|
|
|
@ -1,145 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1997 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.28 1999/11/05 16:22:37 calle
|
||||
* Bugfix: Missing break in switch on ISDN_CMD_HANGUP.
|
||||
*
|
||||
* Revision 1.27 1999/09/16 15:13:04 calle
|
||||
* forgot to change paramter type of contr for lower_callback ...
|
||||
*
|
||||
* Revision 1.26 1999/08/06 07:41:16 calle
|
||||
* Added the "vbox patch". if (si1 == 1) si2 = 0;
|
||||
*
|
||||
* Revision 1.25 1999/08/04 10:10:11 calle
|
||||
* Bugfix: corrected /proc functions, added structure for new AVM cards.
|
||||
*
|
||||
* Revision 1.24 1999/07/20 06:48:02 calle
|
||||
* Bugfix: firmware version check for D2 trace was too restrictiv.
|
||||
*
|
||||
* Revision 1.23 1999/07/09 15:05:44 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.22 1999/07/06 07:24:14 calle
|
||||
* Bugfix: call to kfree_skb in capidrv_signal was too early,
|
||||
* thanks to Lars Heete <hel@admin.de>.
|
||||
*
|
||||
* Revision 1.21 1999/07/01 15:26:34 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
*
|
||||
* Revision 1.20 1999/07/01 08:22:59 keil
|
||||
* compatibility macros now in <linux/isdn_compat.h>
|
||||
*
|
||||
* Revision 1.19 1999/06/29 16:16:54 calle
|
||||
* Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
|
||||
* Also right unlocking (ISDN_CMD_UNLOCK) is done now.
|
||||
* isdnlog should check returncode of read(2) calls.
|
||||
*
|
||||
* Revision 1.18 1999/06/21 15:24:15 calle
|
||||
* extend information in /proc.
|
||||
*
|
||||
* Revision 1.17 1999/06/10 16:53:55 calle
|
||||
* Removing of module b1pci will now remove card from lower level.
|
||||
*
|
||||
* Revision 1.16 1999/05/31 11:50:33 calle
|
||||
* Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed
|
||||
* on failure, result in data block with DATA_B3 header transmitted
|
||||
*
|
||||
* Revision 1.15 1999/05/25 21:26:16 calle
|
||||
* Include CAPI-Channelallocation (leased lines) from the 2.0 tree.
|
||||
*
|
||||
* Revision 1.14 1999/05/22 07:55:06 calle
|
||||
* Added *V110* to AVM B1 driver.
|
||||
*
|
||||
* Revision 1.13 1998/06/26 15:12:55 fritz
|
||||
* Added handling of STAT_ICALL with incomplete CPN.
|
||||
* Added AT&L for ttyI emulator.
|
||||
* Added more locking stuff in tty_write.
|
||||
*
|
||||
* Revision 1.12 1998/03/29 16:06:03 calle
|
||||
* changes from 2.0 tree merged.
|
||||
*
|
||||
* Revision 1.3.2.10 1998/03/20 14:38:24 calle
|
||||
* capidrv: prepared state machines for suspend/resume/hold
|
||||
* capidrv: fix bug in state machine if B1/T1 is out of nccis
|
||||
* b1capi: changed some errno returns.
|
||||
* b1capi: detect if you try to add same T1 to different io address.
|
||||
* b1capi: change number of nccis depending on number of channels.
|
||||
* b1lli: cosmetics
|
||||
*
|
||||
* Revision 1.3.2.9 1998/03/20 09:01:12 calle
|
||||
* Changes capi_register handling to get full support for 30 bchannels.
|
||||
*
|
||||
* Revision 1.3.2.8 1998/03/18 17:51:28 calle
|
||||
* added controller number to error messages
|
||||
*
|
||||
* Revision 1.3.2.7 1998/02/27 15:40:47 calle
|
||||
* T1 running with slow link. bugfix in capi_release.
|
||||
*
|
||||
* Revision 1.11 1998/02/13 07:09:15 calle
|
||||
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
|
||||
*
|
||||
* Revision 1.10 1998/02/02 19:52:23 calle
|
||||
* Fixed vbox (audio) acceptb.
|
||||
*
|
||||
* Revision 1.9 1998/01/31 11:14:45 calle
|
||||
* merged changes to 2.0 tree, prepare 2.1.82 to work.
|
||||
*
|
||||
* Revision 1.8 1997/11/04 06:12:09 calle
|
||||
* capi.c: new read/write in file_ops since 2.1.60
|
||||
* capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
|
||||
* capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
|
||||
* compat.h: added #define LinuxVersionCode
|
||||
*
|
||||
* Revision 1.7 1997/10/11 10:36:34 calle
|
||||
* Added isdnlog support. patch to isdnlog needed.
|
||||
*
|
||||
* Revision 1.6 1997/10/11 10:25:55 calle
|
||||
* New interface for lowlevel drivers. BSENT with nr. of bytes sent,
|
||||
* allow sending without ACK.
|
||||
*
|
||||
* Revision 1.5 1997/10/01 09:21:16 fritz
|
||||
* Removed old compatibility stuff for 2.0.X kernels.
|
||||
* From now on, this code is for 2.1.X ONLY!
|
||||
* Old stuff is still in the separate branch.
|
||||
*
|
||||
* Revision 1.4 1997/07/13 12:22:43 calle
|
||||
* bug fix for more than one controller in connect_req.
|
||||
* debugoutput now with contrnr.
|
||||
*
|
||||
* Revision 1.3 1997/05/18 09:24:15 calle
|
||||
* added verbose disconnect reason reporting to avmb1.
|
||||
* some fixes in capi20 interface.
|
||||
* changed info messages for B1-PCI
|
||||
*
|
||||
* Revision 1.2 1997/03/05 21:19:59 fritz
|
||||
* Removed include of config.h (mkdep stated this is unneded).
|
||||
*
|
||||
* Revision 1.1 1997/03/04 21:50:31 calle
|
||||
* Frirst version in isdn4linux
|
||||
*
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -148,7 +14,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/signal.h>
|
||||
|
@ -162,17 +28,19 @@
|
|||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
#include <linux/isdn_compat.h>
|
||||
#include "capiutil.h"
|
||||
#include "capicmd.h"
|
||||
#include "capidrv.h"
|
||||
|
||||
static char *revision = "$Revision$";
|
||||
int debugmode = 0;
|
||||
static int debugmode = 0;
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_PARM(debugmode, "i");
|
||||
|
||||
/* -------- type definitions ----------------------------------------- */
|
||||
|
@ -278,6 +146,7 @@ typedef struct capidrv_bchan capidrv_bchan;
|
|||
/* -------- data definitions ----------------------------------------- */
|
||||
|
||||
static capidrv_data global;
|
||||
static spinlock_t global_lock = SPIN_LOCK_UNLOCKED;
|
||||
static struct capi_interface *capifuncs;
|
||||
|
||||
static void handle_dtrace_data(capidrv_contr *card,
|
||||
|
@ -303,6 +172,8 @@ static inline __u32 b1prot(int l2, int l3)
|
|||
return 2;
|
||||
case ISDN_PROTO_L2_FAX:
|
||||
return 4;
|
||||
case ISDN_PROTO_L2_MODEM:
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,6 +190,7 @@ static inline __u32 b2prot(int l2, int l3)
|
|||
case ISDN_PROTO_L2_V11096:
|
||||
case ISDN_PROTO_L2_V11019:
|
||||
case ISDN_PROTO_L2_V11038:
|
||||
case ISDN_PROTO_L2_MODEM:
|
||||
return 1;
|
||||
case ISDN_PROTO_L2_FAX:
|
||||
return 4;
|
||||
|
@ -336,6 +208,7 @@ static inline __u32 b3prot(int l2, int l3)
|
|||
case ISDN_PROTO_L2_V11096:
|
||||
case ISDN_PROTO_L2_V11019:
|
||||
case ISDN_PROTO_L2_V11038:
|
||||
case ISDN_PROTO_L2_MODEM:
|
||||
default:
|
||||
return 0;
|
||||
case ISDN_PROTO_L2_FAX:
|
||||
|
@ -343,16 +216,16 @@ static inline __u32 b3prot(int l2, int l3)
|
|||
}
|
||||
}
|
||||
|
||||
static _cstruct b1config_sync_v110(__u16 rate)
|
||||
static _cstruct b1config_async_v110(__u16 rate)
|
||||
{
|
||||
/* CAPI-Spec "B1 Configuration" */
|
||||
static unsigned char buf[9];
|
||||
buf[0] = 8; /* len */
|
||||
/* maximum bitrate */
|
||||
buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
|
||||
buf[3] = buf[4] = 0; /* reserved, bits per character */
|
||||
buf[5] = buf[6] = 0; /* reserved, parity */
|
||||
buf[7] = buf[9] = 0; /* reserved, stop bits */
|
||||
buf[3] = 8; buf[4] = 0; /* 8 bits per character */
|
||||
buf[5] = 0; buf[6] = 0; /* parity none */
|
||||
buf[7] = 0; buf[8] = 0; /* 1 stop bit */
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -367,11 +240,11 @@ static _cstruct b1config(int l2, int l3)
|
|||
default:
|
||||
return 0;
|
||||
case ISDN_PROTO_L2_V11096:
|
||||
return b1config_sync_v110(9600);
|
||||
return b1config_async_v110(9600);
|
||||
case ISDN_PROTO_L2_V11019:
|
||||
return b1config_sync_v110(19200);
|
||||
return b1config_async_v110(19200);
|
||||
case ISDN_PROTO_L2_V11038:
|
||||
return b1config_sync_v110(38400);
|
||||
return b1config_async_v110(38400);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,30 +306,32 @@ static inline __u8 cip2si2(__u16 cipval)
|
|||
}
|
||||
|
||||
|
||||
/* -------- controller managment ------------------------------------- */
|
||||
/* -------- controller management ------------------------------------- */
|
||||
|
||||
static inline capidrv_contr *findcontrbydriverid(int driverid)
|
||||
{
|
||||
capidrv_contr *p = global.contr_list;
|
||||
unsigned long flags;
|
||||
capidrv_contr *p;
|
||||
|
||||
while (p) {
|
||||
spin_lock_irqsave(&global_lock, flags);
|
||||
for (p = global.contr_list; p; p = p->next)
|
||||
if (p->myid == driverid)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
return (capidrv_contr *) 0;
|
||||
break;
|
||||
spin_unlock_irqrestore(&global_lock, flags);
|
||||
return p;
|
||||
}
|
||||
|
||||
static capidrv_contr *findcontrbynumber(__u32 contr)
|
||||
{
|
||||
unsigned long flags;
|
||||
capidrv_contr *p = global.contr_list;
|
||||
|
||||
while (p) {
|
||||
spin_lock_irqsave(&global_lock, flags);
|
||||
for (p = global.contr_list; p; p = p->next)
|
||||
if (p->contrnr == contr)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
return (capidrv_contr *) 0;
|
||||
break;
|
||||
spin_unlock_irqrestore(&global_lock, flags);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1499,7 +1374,7 @@ static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
|
|||
|
||||
static _cmsg s_cmsg;
|
||||
|
||||
static void capidrv_signal(__u16 applid, __u32 dummy)
|
||||
static void capidrv_signal(__u16 applid, void *dummy)
|
||||
{
|
||||
struct sk_buff *skb = 0;
|
||||
|
||||
|
@ -1543,47 +1418,41 @@ static void capidrv_signal(__u16 applid, __u32 dummy)
|
|||
static void handle_dtrace_data(capidrv_contr *card,
|
||||
int send, int level2, __u8 *data, __u16 len)
|
||||
{
|
||||
long flags;
|
||||
__u8 *p, *end;
|
||||
isdn_ctrl cmd;
|
||||
__u8 *p, *end;
|
||||
isdn_ctrl cmd;
|
||||
|
||||
if (!len) {
|
||||
printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
|
||||
if (!len) {
|
||||
printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
|
||||
card->contrnr, len);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if (level2) {
|
||||
PUTBYTE_TO_STATUS(card, 'D');
|
||||
PUTBYTE_TO_STATUS(card, '2');
|
||||
PUTBYTE_TO_STATUS(card, send ? '>' : '<');
|
||||
PUTBYTE_TO_STATUS(card, ':');
|
||||
} else {
|
||||
PUTBYTE_TO_STATUS(card, 'D');
|
||||
PUTBYTE_TO_STATUS(card, '3');
|
||||
PUTBYTE_TO_STATUS(card, send ? '>' : '<');
|
||||
PUTBYTE_TO_STATUS(card, ':');
|
||||
}
|
||||
|
||||
if (level2) {
|
||||
PUTBYTE_TO_STATUS(card, 'D');
|
||||
PUTBYTE_TO_STATUS(card, '2');
|
||||
PUTBYTE_TO_STATUS(card, send ? '>' : '<');
|
||||
PUTBYTE_TO_STATUS(card, ':');
|
||||
} else {
|
||||
PUTBYTE_TO_STATUS(card, 'D');
|
||||
PUTBYTE_TO_STATUS(card, '3');
|
||||
PUTBYTE_TO_STATUS(card, send ? '>' : '<');
|
||||
PUTBYTE_TO_STATUS(card, ':');
|
||||
}
|
||||
for (p = data, end = data+len; p < end; p++) {
|
||||
__u8 w;
|
||||
PUTBYTE_TO_STATUS(card, ' ');
|
||||
w = (*p >> 4) & 0xf;
|
||||
PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
|
||||
w = *p & 0xf;
|
||||
PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
|
||||
}
|
||||
PUTBYTE_TO_STATUS(card, '\n');
|
||||
|
||||
for (p = data, end = data+len; p < end; p++) {
|
||||
__u8 w;
|
||||
PUTBYTE_TO_STATUS(card, ' ');
|
||||
w = (*p >> 4) & 0xf;
|
||||
PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
|
||||
w = *p & 0xf;
|
||||
PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
|
||||
}
|
||||
PUTBYTE_TO_STATUS(card, '\n');
|
||||
|
||||
restore_flags(flags);
|
||||
|
||||
cmd.command = ISDN_STAT_STAVAIL;
|
||||
cmd.driver = card->myid;
|
||||
cmd.arg = len*3+5;
|
||||
card->interface.statcallb(&cmd);
|
||||
cmd.command = ISDN_STAT_STAVAIL;
|
||||
cmd.driver = card->myid;
|
||||
cmd.arg = len*3+5;
|
||||
card->interface.statcallb(&cmd);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
@ -1988,8 +1857,8 @@ static int if_command(isdn_ctrl * c)
|
|||
return capidrv_command(c, card);
|
||||
|
||||
printk(KERN_ERR
|
||||
"capidrv-%d: if_command %d called with invalid driverId %d!\n",
|
||||
card->contrnr, c->command, c->driver);
|
||||
"capidrv: if_command %d called with invalid driverId %d!\n",
|
||||
c->command, c->driver);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -2006,8 +1875,8 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
|
|||
__u16 datahandle;
|
||||
|
||||
if (!card) {
|
||||
printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
|
||||
card->contrnr, id);
|
||||
printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
|
||||
id);
|
||||
return 0;
|
||||
}
|
||||
if (debugmode > 1)
|
||||
|
@ -2078,8 +1947,8 @@ static int if_readstat(__u8 *buf, int len, int user, int id, int channel)
|
|||
__u8 *p;
|
||||
|
||||
if (!card) {
|
||||
printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",
|
||||
card->contrnr, id);
|
||||
printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
|
||||
id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -2147,6 +2016,7 @@ static void enable_dchannel_trace(capidrv_contr *card)
|
|||
send_message(card, &cmdcmsg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void disable_dchannel_trace(capidrv_contr *card)
|
||||
{
|
||||
__u8 manufacturer[CAPI_MANUFACTURER_LEN];
|
||||
|
@ -2191,6 +2061,7 @@ static void disable_dchannel_trace(capidrv_contr *card)
|
|||
(_cstruct)"\004\000\000\000\000");
|
||||
send_message(card, &cmdcmsg);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void send_listen(capidrv_contr *card)
|
||||
{
|
||||
|
@ -2218,14 +2089,18 @@ static void listentimerfunc(unsigned long x)
|
|||
static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
|
||||
{
|
||||
capidrv_contr *card;
|
||||
long flags;
|
||||
isdn_ctrl cmd;
|
||||
char id[20];
|
||||
int i;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
sprintf(id, "capidrv-%d", contr);
|
||||
if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"capidrv: (%s) Could not allocate contr-struct.\n", id);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -1;
|
||||
}
|
||||
memset(card, 0, sizeof(capidrv_contr));
|
||||
|
@ -2238,6 +2113,7 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
|
|||
printk(KERN_WARNING
|
||||
"capidrv: (%s) Could not allocate bchan-structs.\n", id);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -1;
|
||||
}
|
||||
card->interface.channels = profp->nbchannel;
|
||||
|
@ -2246,45 +2122,49 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
|
|||
card->interface.writebuf_skb = if_sendbuf;
|
||||
card->interface.writecmd = 0;
|
||||
card->interface.readstat = if_readstat;
|
||||
card->interface.features = ISDN_FEATURE_L2_X75I |
|
||||
ISDN_FEATURE_L2_X75UI |
|
||||
ISDN_FEATURE_L2_X75BUI |
|
||||
ISDN_FEATURE_L2_HDLC |
|
||||
ISDN_FEATURE_L2_TRANS |
|
||||
ISDN_FEATURE_L3_TRANS |
|
||||
ISDN_FEATURE_L2_V11096 |
|
||||
ISDN_FEATURE_L2_V11019 |
|
||||
ISDN_FEATURE_L2_V11038 |
|
||||
#if 0
|
||||
ISDN_FEATURE_L2_FAX |
|
||||
ISDN_FEATURE_L3_FAX |
|
||||
#endif
|
||||
ISDN_FEATURE_P_UNKNOWN;
|
||||
card->interface.features = ISDN_FEATURE_L2_HDLC |
|
||||
ISDN_FEATURE_L2_TRANS |
|
||||
ISDN_FEATURE_L3_TRANS |
|
||||
ISDN_FEATURE_P_UNKNOWN |
|
||||
ISDN_FEATURE_L2_X75I |
|
||||
ISDN_FEATURE_L2_X75UI |
|
||||
ISDN_FEATURE_L2_X75BUI;
|
||||
if (profp->support1 & (1<<2))
|
||||
card->interface.features |= ISDN_FEATURE_L2_V11096 |
|
||||
ISDN_FEATURE_L2_V11019 |
|
||||
ISDN_FEATURE_L2_V11038;
|
||||
if (profp->support1 & (1<<8))
|
||||
card->interface.features |= ISDN_FEATURE_L2_MODEM;
|
||||
card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
|
||||
strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
|
||||
card->next = global.contr_list;
|
||||
global.contr_list = card;
|
||||
global.ncontr++;
|
||||
|
||||
|
||||
card->q931_read = card->q931_buf;
|
||||
card->q931_write = card->q931_buf;
|
||||
card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
|
||||
|
||||
if (!register_isdn(&card->interface)) {
|
||||
global.contr_list = global.contr_list->next;
|
||||
printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);
|
||||
kfree(card->bchans);
|
||||
kfree(card);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -1;
|
||||
}
|
||||
card->myid = card->interface.channels;
|
||||
|
||||
spin_lock_irqsave(&global_lock, flags);
|
||||
card->next = global.contr_list;
|
||||
global.contr_list = card;
|
||||
global.ncontr++;
|
||||
spin_unlock_irqrestore(&global_lock, flags);
|
||||
|
||||
memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
|
||||
for (i = 0; i < card->nbchan; i++) {
|
||||
card->bchans[i].contr = card;
|
||||
}
|
||||
|
||||
cmd.driver = card->myid;
|
||||
cmd.command = ISDN_STAT_RUN;
|
||||
cmd.driver = card->myid;
|
||||
card->interface.statcallb(&cmd);
|
||||
|
||||
card->cipmask = 0x1FFF03FF; /* any */
|
||||
|
@ -2307,45 +2187,82 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
|
|||
static int capidrv_delcontr(__u16 contr)
|
||||
{
|
||||
capidrv_contr **pp, *card;
|
||||
unsigned long flags;
|
||||
isdn_ctrl cmd;
|
||||
int i;
|
||||
|
||||
for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
|
||||
if ((*pp)->contrnr == contr)
|
||||
spin_lock_irqsave(&global_lock, flags);
|
||||
for (card = global.contr_list; card; card = card->next) {
|
||||
if (card->contrnr == contr)
|
||||
break;
|
||||
}
|
||||
if (!*pp) {
|
||||
if (!card) {
|
||||
spin_unlock_irqrestore(&global_lock, flags);
|
||||
printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
|
||||
return -1;
|
||||
}
|
||||
card = *pp;
|
||||
spin_unlock_irqrestore(&global_lock, flags);
|
||||
|
||||
del_timer(&card->listentimer);
|
||||
|
||||
if (debugmode)
|
||||
printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
|
||||
card->contrnr, card->myid);
|
||||
|
||||
cmd.command = ISDN_STAT_STOP;
|
||||
cmd.driver = card->myid;
|
||||
card->interface.statcallb(&cmd);
|
||||
|
||||
while (card->nbchan) {
|
||||
|
||||
cmd.command = ISDN_STAT_DISCH;
|
||||
cmd.driver = card->myid;
|
||||
cmd.arg = card->nbchan-1;
|
||||
cmd.parm.num[0] = 0;
|
||||
if (debugmode)
|
||||
printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ld\n",
|
||||
card->contrnr, card->myid, cmd.arg);
|
||||
card->interface.statcallb(&cmd);
|
||||
|
||||
if (card->bchans[card->nbchan-1].nccip)
|
||||
free_ncci(card, card->bchans[card->nbchan-1].nccip);
|
||||
if (card->bchans[card->nbchan-1].plcip)
|
||||
free_plci(card, card->bchans[card->nbchan-1].plcip);
|
||||
if (card->plci_list)
|
||||
printk(KERN_ERR "capidrv: bug in free_plci()\n");
|
||||
card->nbchan--;
|
||||
}
|
||||
kfree(card->bchans);
|
||||
card->bchans = 0;
|
||||
|
||||
if (debugmode)
|
||||
printk(KERN_DEBUG "capidrv-%d: id=%d isdn unload\n",
|
||||
card->contrnr, card->myid);
|
||||
|
||||
cmd.command = ISDN_STAT_UNLOAD;
|
||||
cmd.driver = card->myid;
|
||||
card->interface.statcallb(&cmd);
|
||||
|
||||
*pp = (*pp)->next;
|
||||
global.ncontr--;
|
||||
if (debugmode)
|
||||
printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from list\n",
|
||||
card->contrnr, card->myid);
|
||||
|
||||
for (i = 0; i < card->nbchan; i++) {
|
||||
if (card->bchans[i].nccip)
|
||||
free_ncci(card, card->bchans[i].nccip);
|
||||
if (card->bchans[i].plcip)
|
||||
free_plci(card, card->bchans[i].plcip);
|
||||
if (card->plci_list)
|
||||
printk(KERN_ERR "capidrv: bug in free_plci()\n");
|
||||
spin_lock_irqsave(&global_lock, flags);
|
||||
for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
|
||||
if (*pp == card) {
|
||||
*pp = (*pp)->next;
|
||||
card->next = 0;
|
||||
global.ncontr--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kfree(card->bchans);
|
||||
del_timer(&card->listentimer);
|
||||
spin_unlock_irqrestore(&global_lock, flags);
|
||||
|
||||
printk(KERN_INFO "%s: now down.\n", card->name);
|
||||
|
||||
kfree(card);
|
||||
|
||||
MOD_DEC_USE_COUNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2398,7 +2315,7 @@ static struct procfsentries {
|
|||
{ "capi/capidrv", 0 , proc_capidrv_read_proc },
|
||||
};
|
||||
|
||||
static void proc_init(void)
|
||||
static void __init proc_init(void)
|
||||
{
|
||||
int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
|
||||
int i;
|
||||
|
@ -2410,7 +2327,7 @@ static void proc_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void proc_exit(void)
|
||||
static void __exit proc_exit(void)
|
||||
{
|
||||
int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
|
||||
int i;
|
||||
|
@ -2425,34 +2342,35 @@ static void proc_exit(void)
|
|||
}
|
||||
|
||||
static struct capi_interface_user cuser = {
|
||||
"capidrv",
|
||||
lower_callback
|
||||
name: "capidrv",
|
||||
callback: lower_callback
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
#define capidrv_init init_module
|
||||
#endif
|
||||
|
||||
int capidrv_init(void)
|
||||
static int __init capidrv_init(void)
|
||||
{
|
||||
struct capi_register_params rparam;
|
||||
capi_profile profile;
|
||||
char rev[10];
|
||||
char rev[32];
|
||||
char *p;
|
||||
__u32 ncontr, contr;
|
||||
__u16 errcode;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
capifuncs = attach_capi_interface(&cuser);
|
||||
|
||||
if (!capifuncs)
|
||||
if (!capifuncs) {
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strcpy(rev, p + 1);
|
||||
p = strchr(rev, '$');
|
||||
*p = 0;
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(rev, p + 2, sizeof(rev));
|
||||
rev[sizeof(rev)-1] = 0;
|
||||
if ((p = strchr(rev, '$')) != 0 && p > rev)
|
||||
*(p-1) = 0;
|
||||
} else
|
||||
strcpy(rev, " ??? ");
|
||||
strcpy(rev, "1.0");
|
||||
|
||||
rparam.level3cnt = -2; /* number of bchannels twice */
|
||||
rparam.datablkcnt = 16;
|
||||
|
@ -2460,6 +2378,7 @@ int capidrv_init(void)
|
|||
errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
|
||||
if (errcode) {
|
||||
detach_capi_interface(&cuser);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -2467,6 +2386,7 @@ int capidrv_init(void)
|
|||
if (errcode != CAPI_NOERROR) {
|
||||
(void) (*capifuncs->capi_release) (global.appid);
|
||||
detach_capi_interface(&cuser);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -2481,17 +2401,18 @@ int capidrv_init(void)
|
|||
}
|
||||
proc_init();
|
||||
|
||||
printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev);
|
||||
MOD_DEC_USE_COUNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit capidrv_exit(void)
|
||||
{
|
||||
capidrv_contr *card, *next;
|
||||
char rev[10];
|
||||
char *p;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
if ((p = strchr(revision, ':')) != 0) {
|
||||
strcpy(rev, p + 1);
|
||||
p = strchr(rev, '$');
|
||||
*p = 0;
|
||||
|
@ -2499,17 +2420,14 @@ void cleanup_module(void)
|
|||
strcpy(rev, " ??? ");
|
||||
}
|
||||
|
||||
for (card = global.contr_list; card; card = next) {
|
||||
next = card->next;
|
||||
disable_dchannel_trace(card);
|
||||
capidrv_delcontr(card->contrnr);
|
||||
}
|
||||
|
||||
(void) (*capifuncs->capi_release) (global.appid);
|
||||
|
||||
detach_capi_interface(&cuser);
|
||||
|
||||
proc_exit();
|
||||
|
||||
printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
|
||||
}
|
||||
|
||||
#endif
|
||||
module_init(capidrv_init);
|
||||
module_exit(capidrv_exit);
|
||||
|
|
|
@ -1,29 +1,14 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1997 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.1.2.1 1998/03/20 14:38:28 calle
|
||||
* capidrv: prepared state machines for suspend/resume/hold
|
||||
* capidrv: fix bug in state machine if B1/T1 is out of nccis
|
||||
* b1capi: changed some errno returns.
|
||||
* b1capi: detect if you try to add same T1 to different io address.
|
||||
* b1capi: change number of nccis depending on number of channels.
|
||||
* b1lli: cosmetics
|
||||
*
|
||||
* Revision 1.1 1997/03/04 21:50:33 calle
|
||||
* Frirst version in isdn4linux
|
||||
*
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CAPIDRV_H__
|
||||
#define __CAPIDRV_H__
|
||||
|
||||
|
|
|
@ -0,0 +1,619 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* Heavily based on devpts filesystem from H. Peter Anvin
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/locks.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static char *revision = "$Revision$";
|
||||
|
||||
struct capifs_ncci {
|
||||
struct inode *inode;
|
||||
char used;
|
||||
char type;
|
||||
unsigned int num;
|
||||
kdev_t kdev;
|
||||
};
|
||||
|
||||
struct capifs_sb_info {
|
||||
u32 magic;
|
||||
struct super_block *next;
|
||||
struct super_block **back;
|
||||
int setuid;
|
||||
int setgid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
umode_t mode;
|
||||
|
||||
unsigned int max_ncci;
|
||||
struct capifs_ncci *nccis;
|
||||
};
|
||||
|
||||
#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
|
||||
#define CAPIFS_SBI_MAGIC (('C'<<24)|('A'<<16)|('P'<<8)|'I')
|
||||
|
||||
static inline struct capifs_sb_info *SBI(struct super_block *sb)
|
||||
{
|
||||
return (struct capifs_sb_info *)(sb->u.generic_sbp);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int capifs_root_readdir(struct file *,void *,filldir_t);
|
||||
static struct dentry *capifs_root_lookup(struct inode *,struct dentry *);
|
||||
static int capifs_revalidate(struct dentry *, int);
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
static struct inode *capifs_new_inode(struct super_block *sb);
|
||||
#endif
|
||||
|
||||
static struct file_operations capifs_root_operations = {
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
read: generic_read_dir,
|
||||
#endif
|
||||
readdir: capifs_root_readdir,
|
||||
};
|
||||
|
||||
struct inode_operations capifs_root_inode_operations = {
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
default_file_ops: &capifs_root_operations, /* file operations */
|
||||
#endif
|
||||
lookup: capifs_root_lookup,
|
||||
};
|
||||
|
||||
static struct dentry_operations capifs_dentry_operations = {
|
||||
d_revalidate: capifs_revalidate,
|
||||
};
|
||||
|
||||
/*
|
||||
* /dev/capi/%d
|
||||
* /dev/capi/r%d
|
||||
*/
|
||||
|
||||
static int capifs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
{
|
||||
struct inode * inode = filp->f_dentry->d_inode;
|
||||
struct capifs_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
|
||||
off_t nr;
|
||||
char numbuf[32];
|
||||
|
||||
nr = filp->f_pos;
|
||||
|
||||
switch(nr)
|
||||
{
|
||||
case 0:
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
|
||||
#else
|
||||
if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
|
||||
#endif
|
||||
return 0;
|
||||
filp->f_pos = ++nr;
|
||||
/* fall through */
|
||||
case 1:
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
|
||||
#else
|
||||
if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
|
||||
#endif
|
||||
return 0;
|
||||
filp->f_pos = ++nr;
|
||||
/* fall through */
|
||||
default:
|
||||
while (nr < sbi->max_ncci) {
|
||||
int n = nr - 2;
|
||||
struct capifs_ncci *np = &sbi->nccis[n];
|
||||
if (np->inode && np->used) {
|
||||
char *p = numbuf;
|
||||
if (np->type) *p++ = np->type;
|
||||
sprintf(p, "%u", np->num);
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_UNKNOWN) < 0 )
|
||||
#else
|
||||
if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
filp->f_pos = ++nr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Revalidate is called on every cache lookup. We use it to check that
|
||||
* the ncci really does still exist. Never revalidate negative dentries;
|
||||
* for simplicity (fix later?)
|
||||
*/
|
||||
static int capifs_revalidate(struct dentry * dentry, int flags)
|
||||
{
|
||||
struct capifs_sb_info *sbi;
|
||||
|
||||
if ( !dentry->d_inode )
|
||||
return 0;
|
||||
|
||||
sbi = SBI(dentry->d_inode->i_sb);
|
||||
|
||||
return ( sbi->nccis[dentry->d_inode->i_ino - 2].inode == dentry->d_inode );
|
||||
}
|
||||
|
||||
static struct dentry *capifs_root_lookup(struct inode * dir, struct dentry * dentry)
|
||||
{
|
||||
struct capifs_sb_info *sbi = SBI(dir->i_sb);
|
||||
struct capifs_ncci *np;
|
||||
unsigned int i;
|
||||
char numbuf[32];
|
||||
char *p, *tmp;
|
||||
unsigned int num;
|
||||
char type = 0;
|
||||
|
||||
dentry->d_inode = NULL; /* Assume failure */
|
||||
dentry->d_op = &capifs_dentry_operations;
|
||||
|
||||
if (dentry->d_name.len >= sizeof(numbuf) )
|
||||
return NULL;
|
||||
strncpy(numbuf, dentry->d_name.name, dentry->d_name.len);
|
||||
numbuf[dentry->d_name.len] = 0;
|
||||
p = numbuf;
|
||||
if (!isdigit(*p)) type = *p++;
|
||||
tmp = p;
|
||||
num = (unsigned int)simple_strtoul(p, &tmp, 10);
|
||||
if (tmp == p || *tmp)
|
||||
return NULL;
|
||||
|
||||
for (i = 0, np = sbi->nccis ; i < sbi->max_ncci; i++, np++) {
|
||||
if (np->used && np->num == num && np->type == type)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i >= sbi->max_ncci )
|
||||
return NULL;
|
||||
|
||||
dentry->d_inode = np->inode;
|
||||
if ( dentry->d_inode )
|
||||
i_count_inc(dentry->d_inode->i_count);
|
||||
|
||||
d_add(dentry, dentry->d_inode);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static struct super_block *mounts = NULL;
|
||||
|
||||
static void capifs_put_super(struct super_block *sb)
|
||||
{
|
||||
struct capifs_sb_info *sbi = SBI(sb);
|
||||
struct inode *inode;
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < sbi->max_ncci ; i++ ) {
|
||||
if ( (inode = sbi->nccis[i].inode) ) {
|
||||
if (i_count_read(inode->i_count) != 1 )
|
||||
printk("capifs_put_super: badness: entry %d count %d\n",
|
||||
i, (unsigned)i_count_read(inode->i_count));
|
||||
inode->i_nlink--;
|
||||
iput(inode);
|
||||
}
|
||||
}
|
||||
|
||||
*sbi->back = sbi->next;
|
||||
if ( sbi->next )
|
||||
SBI(sbi->next)->back = sbi->back;
|
||||
|
||||
kfree(sbi->nccis);
|
||||
kfree(sbi);
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
static int capifs_statfs(struct super_block *sb, struct statfs *buf);
|
||||
#else
|
||||
static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
|
||||
static void capifs_write_inode(struct inode *inode) { };
|
||||
static void capifs_read_inode(struct inode *inode);
|
||||
#endif
|
||||
|
||||
static struct super_operations capifs_sops = {
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
read_inode: capifs_read_inode,
|
||||
write_inode: capifs_write_inode,
|
||||
#endif
|
||||
put_super: capifs_put_super,
|
||||
statfs: capifs_statfs,
|
||||
};
|
||||
|
||||
static int capifs_parse_options(char *options, struct capifs_sb_info *sbi)
|
||||
{
|
||||
int setuid = 0;
|
||||
int setgid = 0;
|
||||
uid_t uid = 0;
|
||||
gid_t gid = 0;
|
||||
umode_t mode = 0600;
|
||||
unsigned int maxncci = 512;
|
||||
char *this_char, *value;
|
||||
|
||||
this_char = NULL;
|
||||
if ( options )
|
||||
this_char = strtok(options,",");
|
||||
for ( ; this_char; this_char = strtok(NULL,",")) {
|
||||
if ((value = strchr(this_char,'=')) != NULL)
|
||||
*value++ = 0;
|
||||
if (!strcmp(this_char,"uid")) {
|
||||
if (!value || !*value)
|
||||
return 1;
|
||||
uid = simple_strtoul(value,&value,0);
|
||||
if (*value)
|
||||
return 1;
|
||||
setuid = 1;
|
||||
}
|
||||
else if (!strcmp(this_char,"gid")) {
|
||||
if (!value || !*value)
|
||||
return 1;
|
||||
gid = simple_strtoul(value,&value,0);
|
||||
if (*value)
|
||||
return 1;
|
||||
setgid = 1;
|
||||
}
|
||||
else if (!strcmp(this_char,"mode")) {
|
||||
if (!value || !*value)
|
||||
return 1;
|
||||
mode = simple_strtoul(value,&value,8);
|
||||
if (*value)
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(this_char,"maxncci")) {
|
||||
if (!value || !*value)
|
||||
return 1;
|
||||
maxncci = simple_strtoul(value,&value,8);
|
||||
if (*value)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
sbi->setuid = setuid;
|
||||
sbi->setgid = setgid;
|
||||
sbi->uid = uid;
|
||||
sbi->gid = gid;
|
||||
sbi->mode = mode & ~S_IFMT;
|
||||
sbi->max_ncci = maxncci;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct super_block *capifs_read_super(struct super_block *s, void *data,
|
||||
int silent)
|
||||
{
|
||||
struct inode * root_inode;
|
||||
struct dentry * root;
|
||||
struct capifs_sb_info *sbi;
|
||||
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
MOD_INC_USE_COUNT;
|
||||
lock_super(s);
|
||||
#endif
|
||||
/* Super block already completed? */
|
||||
if (s->s_root)
|
||||
goto out;
|
||||
|
||||
sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
|
||||
if ( !sbi )
|
||||
goto fail;
|
||||
|
||||
memset(sbi, 0, sizeof(struct capifs_sb_info));
|
||||
sbi->magic = CAPIFS_SBI_MAGIC;
|
||||
|
||||
if ( capifs_parse_options(data,sbi) ) {
|
||||
kfree(sbi);
|
||||
printk("capifs: called with bogus options\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL);
|
||||
if ( !sbi->nccis ) {
|
||||
kfree(sbi);
|
||||
goto fail;
|
||||
}
|
||||
memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci);
|
||||
|
||||
s->u.generic_sbp = (void *) sbi;
|
||||
s->s_blocksize = 1024;
|
||||
s->s_blocksize_bits = 10;
|
||||
s->s_magic = CAPIFS_SUPER_MAGIC;
|
||||
s->s_op = &capifs_sops;
|
||||
s->s_root = NULL;
|
||||
|
||||
/*
|
||||
* Get the root inode and dentry, but defer checking for errors.
|
||||
*/
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
root_inode = capifs_new_inode(s);
|
||||
if (root_inode) {
|
||||
root_inode->i_ino = 1;
|
||||
root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
|
||||
root_inode->i_op = &capifs_root_inode_operations;
|
||||
root_inode->i_fop = &capifs_root_operations;
|
||||
root_inode->i_nlink = 2;
|
||||
}
|
||||
root = d_alloc_root(root_inode);
|
||||
#else
|
||||
root_inode = iget(s, 1); /* inode 1 == root directory */
|
||||
root = d_alloc_root(root_inode, NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check whether somebody else completed the super block.
|
||||
*/
|
||||
if (s->s_root) {
|
||||
if (root) dput(root);
|
||||
else iput(root_inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
printk("capifs: get root dentry failed\n");
|
||||
/*
|
||||
* iput() can block, so we clear the super block first.
|
||||
*/
|
||||
iput(root_inode);
|
||||
kfree(sbi->nccis);
|
||||
kfree(sbi);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether somebody else completed the super block.
|
||||
*/
|
||||
if (s->s_root)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Success! Install the root dentry now to indicate completion.
|
||||
*/
|
||||
s->s_root = root;
|
||||
|
||||
sbi->next = mounts;
|
||||
if ( sbi->next )
|
||||
SBI(sbi->next)->back = &(sbi->next);
|
||||
sbi->back = &mounts;
|
||||
mounts = s;
|
||||
|
||||
out: /* Success ... somebody else completed the super block for us. */
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
unlock_super(s);
|
||||
#endif
|
||||
return s;
|
||||
fail:
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
unlock_super(s);
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
|
||||
{
|
||||
struct statfs tmp;
|
||||
|
||||
tmp.f_type = CAPIFS_SUPER_MAGIC;
|
||||
tmp.f_bsize = 1024;
|
||||
tmp.f_blocks = 0;
|
||||
tmp.f_bfree = 0;
|
||||
tmp.f_bavail = 0;
|
||||
tmp.f_files = 0;
|
||||
tmp.f_ffree = 0;
|
||||
tmp.f_namelen = NAME_MAX;
|
||||
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
|
||||
}
|
||||
#else
|
||||
static int capifs_statfs(struct super_block *sb, struct statfs *buf)
|
||||
{
|
||||
buf->f_type = CAPIFS_SUPER_MAGIC;
|
||||
buf->f_bsize = 1024;
|
||||
buf->f_blocks = 0;
|
||||
buf->f_bfree = 0;
|
||||
buf->f_bavail = 0;
|
||||
buf->f_files = 0;
|
||||
buf->f_ffree = 0;
|
||||
buf->f_namelen = NAME_MAX;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
static struct inode *capifs_new_inode(struct super_block *sb)
|
||||
{
|
||||
struct inode *inode = new_inode(sb);
|
||||
if (inode) {
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
inode->i_blocks = 0;
|
||||
inode->i_blksize = 1024;
|
||||
inode->i_uid = inode->i_gid = 0;
|
||||
}
|
||||
return inode;
|
||||
}
|
||||
#else
|
||||
static void capifs_read_inode(struct inode *inode)
|
||||
{
|
||||
ino_t ino = inode->i_ino;
|
||||
struct capifs_sb_info *sbi = SBI(inode->i_sb);
|
||||
|
||||
inode->i_mode = 0;
|
||||
inode->i_nlink = 0;
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
inode->i_blocks = 0;
|
||||
inode->i_blksize = 1024;
|
||||
inode->i_uid = inode->i_gid = 0;
|
||||
|
||||
if ( ino == 1 ) {
|
||||
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
|
||||
inode->i_op = &capifs_root_inode_operations;
|
||||
inode->i_nlink = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
ino -= 2;
|
||||
if ( ino >= sbi->max_ncci )
|
||||
return; /* Bogus */
|
||||
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
init_special_inode(inode, S_IFCHR, 0);
|
||||
#else
|
||||
inode->i_mode = S_IFCHR;
|
||||
inode->i_op = &chrdev_inode_operations;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef COMPAT_VFS_2_4
|
||||
static struct file_system_type capifs_fs_type = {
|
||||
"capifs",
|
||||
0,
|
||||
capifs_read_super,
|
||||
NULL
|
||||
};
|
||||
#else
|
||||
static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
|
||||
#endif
|
||||
|
||||
void capifs_new_ncci(char type, unsigned int num, kdev_t device)
|
||||
{
|
||||
struct super_block *sb;
|
||||
struct capifs_sb_info *sbi;
|
||||
struct capifs_ncci *np;
|
||||
ino_t ino;
|
||||
|
||||
for ( sb = mounts ; sb ; sb = sbi->next ) {
|
||||
sbi = SBI(sb);
|
||||
|
||||
for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) {
|
||||
if (np->used == 0) {
|
||||
np->used = 1;
|
||||
np->type = type;
|
||||
np->num = num;
|
||||
np->kdev = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
if ( ino >= sbi->max_ncci )
|
||||
continue;
|
||||
|
||||
if ((np->inode = capifs_new_inode(sb)) != NULL) {
|
||||
#else
|
||||
if ((np->inode = iget(sb, ino+2)) != NULL) {
|
||||
#endif
|
||||
struct inode *inode = np->inode;
|
||||
inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
|
||||
inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
|
||||
#ifdef COMPAT_VFS_2_4
|
||||
inode->i_nlink = 1;
|
||||
inode->i_ino = ino + 2;
|
||||
init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
|
||||
#else
|
||||
inode->i_mode = sbi->mode | S_IFCHR;
|
||||
inode->i_rdev = np->kdev;
|
||||
inode->i_nlink++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void capifs_free_ncci(char type, unsigned int num)
|
||||
{
|
||||
struct super_block *sb;
|
||||
struct capifs_sb_info *sbi;
|
||||
struct inode *inode;
|
||||
struct capifs_ncci *np;
|
||||
ino_t ino;
|
||||
|
||||
for ( sb = mounts ; sb ; sb = sbi->next ) {
|
||||
sbi = SBI(sb);
|
||||
|
||||
for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) {
|
||||
if (!np->used || np->type != type || np->num != num)
|
||||
continue;
|
||||
if (np->inode) {
|
||||
inode = np->inode;
|
||||
np->inode = 0;
|
||||
np->used = 0;
|
||||
inode->i_nlink--;
|
||||
iput(inode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __init capifs_init(void)
|
||||
{
|
||||
char rev[32];
|
||||
char *p;
|
||||
int err;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(rev, p + 2, sizeof(rev));
|
||||
rev[sizeof(rev)-1] = 0;
|
||||
if ((p = strchr(rev, '$')) != 0 && p > rev)
|
||||
*(p-1) = 0;
|
||||
} else
|
||||
strcpy(rev, "1.0");
|
||||
|
||||
err = register_filesystem(&capifs_fs_type);
|
||||
if (err) {
|
||||
MOD_DEC_USE_COUNT;
|
||||
return err;
|
||||
}
|
||||
printk(KERN_NOTICE "capifs: Rev %s\n", rev);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit capifs_exit(void)
|
||||
{
|
||||
unregister_filesystem(&capifs_fs_type);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capifs_new_ncci);
|
||||
EXPORT_SYMBOL(capifs_free_ncci);
|
||||
|
||||
module_init(capifs_init);
|
||||
module_exit(capifs_exit);
|
|
@ -0,0 +1,11 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
void capifs_new_ncci(char type, unsigned int num, kdev_t device);
|
||||
void capifs_free_ncci(char type, unsigned int num);
|
|
@ -1,11 +1,14 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Kernel CAPI 2.0 Driver Interface for Linux
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CAPILLI_H__
|
||||
#define __CAPILLI_H__
|
||||
|
||||
|
|
|
@ -1,78 +1,31 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* CAPI 2.0 convert capi message to capi message struct
|
||||
*
|
||||
* From CAPI 2.0 Development Kit AVM 1995 (msg.c)
|
||||
* Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 1999/07/09 15:05:46 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.8 1999/07/01 15:26:37 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
*
|
||||
* Revision 1.7 1999/07/01 08:23:01 keil
|
||||
* compatibility macros now in <linux/isdn_compat.h>
|
||||
*
|
||||
* Revision 1.6 1997/11/04 06:12:12 calle
|
||||
* capi.c: new read/write in file_ops since 2.1.60
|
||||
* capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
|
||||
* capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
|
||||
* compat.h: added #define LinuxVersionCode
|
||||
*
|
||||
* Revision 1.5 1997/10/01 09:21:19 fritz
|
||||
* Removed old compatibility stuff for 2.0.X kernels.
|
||||
* From now on, this code is for 2.1.X ONLY!
|
||||
* Old stuff is still in the separate branch.
|
||||
*
|
||||
* Revision 1.4 1997/08/10 07:43:55 calle
|
||||
* forgot to export symbol capi_info2str for 2.1.x
|
||||
*
|
||||
* Revision 1.3 1997/05/18 09:24:18 calle
|
||||
* added verbose disconnect reason reporting to avmb1.
|
||||
* some fixes in capi20 interface.
|
||||
* changed info messages for B1-PCI
|
||||
*
|
||||
* Revision 1.2 1997/03/05 21:22:13 fritz
|
||||
* Fix: Symbols have to be exported unconditionally.
|
||||
*
|
||||
* Revision 1.1 1997/03/04 21:50:34 calle
|
||||
* Frirst version in isdn4linux
|
||||
*
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/segment.h>
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/isdn_compat.h>
|
||||
#include "capiutil.h"
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: CAPI message conversion support");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* from CAPI2.0 DDK AVM Berlin GmbH */
|
||||
|
||||
#ifndef CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
|
||||
|
@ -792,7 +745,7 @@ static char *pnames[] =
|
|||
/*15 */ "Class",
|
||||
/*16 */ "ConnectedNumber",
|
||||
/*17 */ "ConnectedSubaddress",
|
||||
/*18 */ "Data",
|
||||
/*18 */ "Data32",
|
||||
/*19 */ "DataHandle",
|
||||
/*1a */ "DataLength",
|
||||
/*1b */ "FacilityConfirmationParameter",
|
||||
|
@ -890,13 +843,7 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level)
|
|||
cmsg->l += 2;
|
||||
break;
|
||||
case _CDWORD:
|
||||
if (strcmp(NAME, "Data") == 0) {
|
||||
bufprint("%-*s = ", slen, NAME);
|
||||
printstructlen((__u8 *) * (__u32 *) (cmsg->m + cmsg->l),
|
||||
*(__u16 *) (cmsg->m + cmsg->l + sizeof(__u32)));
|
||||
bufprint("\n");
|
||||
} else
|
||||
bufprint("%-*s = 0x%lx\n", slen, NAME, *(__u32 *) (cmsg->m + cmsg->l));
|
||||
bufprint("%-*s = 0x%lx\n", slen, NAME, *(__u32 *) (cmsg->m + cmsg->l));
|
||||
cmsg->l += 4;
|
||||
break;
|
||||
case _CSTRUCT:
|
||||
|
@ -971,7 +918,6 @@ char *capi_cmsg2str(_cmsg * cmsg)
|
|||
return buf;
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(capi_cmsg2message);
|
||||
EXPORT_SYMBOL(capi_message2cmsg);
|
||||
EXPORT_SYMBOL(capi_cmsg_header);
|
||||
|
@ -980,15 +926,14 @@ EXPORT_SYMBOL(capi_cmsg2str);
|
|||
EXPORT_SYMBOL(capi_message2str);
|
||||
EXPORT_SYMBOL(capi_info2str);
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return 0;
|
||||
static int __init capiutil_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
static void __exit capiutil_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
module_init(capiutil_init);
|
||||
module_exit(capiutil_exit);
|
||||
|
|
|
@ -1,60 +1,61 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
/* $Id$
|
||||
*
|
||||
* CAPI 2.0 defines & types
|
||||
*
|
||||
* From CAPI 2.0 Development Kit AVM 1995 (capi20.h)
|
||||
* Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1999/09/07 09:02:53 calle
|
||||
* SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
|
||||
* DATA_B3_IND is always directly after the CAPI message. The "Data" member
|
||||
* ist never used inside the kernel.
|
||||
*
|
||||
* Revision 1.2 1997/05/18 09:24:19 calle
|
||||
* added verbose disconnect reason reporting to avmb1.
|
||||
* some fixes in capi20 interface.
|
||||
* changed info messages for B1-PCI
|
||||
* From CAPI 2.0 Development Kit AVM 1995 (msg.c)
|
||||
* Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* Revision 1.1 1997/03/04 21:50:35 calle
|
||||
* Frirst version in isdn4linux
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Revision 2.2 1997/02/12 09:31:39 calle
|
||||
* new version
|
||||
*
|
||||
* Revision 1.1 1997/01/31 10:32:20 calle
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CAPIUTIL_H__
|
||||
#define __CAPIUTIL_H__
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
#define CAPIMSG_LEN(m) (m[0] | (m[1] << 8))
|
||||
#define CAPIMSG_APPID(m) (m[2] | (m[3] << 8))
|
||||
#define CAPIMSG_COMMAND(m) (m[4])
|
||||
#define CAPIMSG_SUBCOMMAND(m) (m[5])
|
||||
#define CAPIMSG_MSGID(m) (m[6] | (m[7] << 8))
|
||||
#define CAPIMSG_BASELEN 8
|
||||
#define CAPIMSG_U8(m, off) (m[off])
|
||||
#define CAPIMSG_U16(m, off) (m[off]|(m[(off)+1]<<8))
|
||||
#define CAPIMSG_U32(m, off) (m[off]|(m[(off)+1]<<8)|(m[(off)+2]<<16)|(m[(off)+3]<<24))
|
||||
#define CAPIMSG_LEN(m) CAPIMSG_U16(m,0)
|
||||
#define CAPIMSG_APPID(m) CAPIMSG_U16(m,2)
|
||||
#define CAPIMSG_COMMAND(m) CAPIMSG_U8(m,4)
|
||||
#define CAPIMSG_SUBCOMMAND(m) CAPIMSG_U8(m,5)
|
||||
#define CAPIMSG_CMD(m) (((m[4])<<8)|(m[5]))
|
||||
#define CAPIMSG_MSGID(m) CAPIMSG_U16(m,6)
|
||||
#define CAPIMSG_CONTROLLER(m) (m[8] & 0x7f)
|
||||
#define CAPIMSG_CONTROL(m) (m[8]|(m[9]<<8)|(m[10]<<16)|(m[11]<<24))
|
||||
#define CAPIMSG_CONTROL(m) CAPIMSG_U32(m, 8)
|
||||
#define CAPIMSG_NCCI(m) CAPIMSG_CONTROL(m)
|
||||
#define CAPIMSG_DATA(m) (m[12]|(m[13]<<8)|(m[14]<<16)|(m[15]<<24))
|
||||
#define CAPIMSG_DATALEN(m) (m[16] | (m[17]<<8))
|
||||
#define CAPIMSG_DATALEN(m) CAPIMSG_U16(m,16) /* DATA_B3_REQ */
|
||||
|
||||
#define CAPIMSG_SETAPPID(m, applid) \
|
||||
do { \
|
||||
((__u8 *)m)[2] = (__u16)(applid) & 0xff; \
|
||||
((__u8 *)m)[3] = ((__u16)(applid) >> 8) & 0xff; \
|
||||
} while (0)
|
||||
static inline void capimsg_setu8(void *m, int off, __u8 val)
|
||||
{
|
||||
((__u8 *)m)[off] = val;
|
||||
}
|
||||
|
||||
#define CAPIMSG_SETLEN(m, len) \
|
||||
do { \
|
||||
((__u8 *)m)[0] = (__u16)(len) & 0xff; \
|
||||
((__u8 *)m)[1] = ((__u16)(len) >> 8) & 0xff; \
|
||||
} while (0)
|
||||
static inline void capimsg_setu16(void *m, int off, __u16 val)
|
||||
{
|
||||
((__u8 *)m)[off] = val & 0xff;
|
||||
((__u8 *)m)[off+1] = (val >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline void capimsg_setu32(void *m, int off, __u32 val)
|
||||
{
|
||||
((__u8 *)m)[off] = val & 0xff;
|
||||
((__u8 *)m)[off+1] = (val >> 8) & 0xff;
|
||||
((__u8 *)m)[off+2] = (val >> 16) & 0xff;
|
||||
((__u8 *)m)[off+3] = (val >> 24) & 0xff;
|
||||
}
|
||||
|
||||
#define CAPIMSG_SETLEN(m, len) capimsg_setu16(m, 0, len)
|
||||
#define CAPIMSG_SETAPPID(m, applid) capimsg_setu16(m, 2, applid)
|
||||
#define CAPIMSG_SETCOMMAND(m,cmd) capimsg_setu8(m, 4, cmd)
|
||||
#define CAPIMSG_SETSUBCOMMAND(m, cmd) capimsg_setu8(m, 5, cmd)
|
||||
#define CAPIMSG_SETMSGID(m, msgid) capimsg_setu16(m, 6, msgid)
|
||||
#define CAPIMSG_SETCONTROL(m, contr) capimsg_setu32(m, 8, contr)
|
||||
#define CAPIMSG_SETDATALEN(m, len) capimsg_setu16(m, 16, len)
|
||||
|
||||
/*----- basic-type definitions -----*/
|
||||
|
||||
|
|
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
* Copyright (C) 2000 AVM GmbH. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY, without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, and WITHOUT
|
||||
* ANY LIABILITY FOR ANY DAMAGES arising out of or in connection
|
||||
* with the use or performance of this software. See the
|
||||
* GNU General Public License for further details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
*
|
||||
* Based on Carsten Paeth's PCMCIA client driver for AVM B1/M1/M2
|
||||
*
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <pcmcia/config.h>
|
||||
#include <pcmcia/k_compat.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/capi.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do
|
||||
* not define PCMCIA_DEBUG at all, all the debug code will be left out. If
|
||||
* you compile with PCMCIA_DEBUG=0, the debug code will be present but
|
||||
* disabled -- but it can then be enabled for specific modules at load time
|
||||
* with a 'pc_debug=#' option to insmod.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef PCMCIA_DEBUG
|
||||
static int pc_debug = PCMCIA_DEBUG;
|
||||
MODULE_PARM(pc_debug, "i");
|
||||
#define DEBUG(n, args...) if (pc_debug>(n)) \
|
||||
printk(KERN_DEBUG "fcpcmcia_cs: " args);
|
||||
#else
|
||||
#define DEBUG(n, args...)
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Parameters that can be set with 'insmod' */
|
||||
/* This means pick from 15, 12, 11, 10, 9, 7, 5, 4, and 3 */
|
||||
|
||||
static int default_irq_list[10] = { 15, 12, 11, 10, 9, 7, 5, 4, 3, -1 };
|
||||
static int irq_list[10] = { -1 };
|
||||
|
||||
MODULE_PARM(irq_list, "1-10i");
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* The event() function is this driver's Card Services event handler. It will
|
||||
* be called by Card Services when an appropriate card status event is
|
||||
* received. The config() and release() entry points are used to configure
|
||||
* or release a socket, in response to card insertion and ejection events.
|
||||
* They are invoked from the skeleton event handler.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static void fcpcmcia_config (dev_link_t * link);
|
||||
static void fcpcmcia_release (u_long arg);
|
||||
static int fcpcmcia_event (event_t event, int priority,
|
||||
event_callback_args_t * args);
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* The attach() and detach() entry points are used to create and destroy
|
||||
* "instances" of the driver, where each instance represents everything
|
||||
* needed to manage one actual PCMCIA card.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static dev_link_t * fcpcmcia_attach (void);
|
||||
static void fcpcmcia_detach (dev_link_t *);
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* The dev_info variable is the "key" that is used to match up this device
|
||||
* driver with appropriate cards, through the card configuration database.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static dev_info_t dev_info = "fcpcmcia_cs";
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* A linked list of "instances" of the skeleton device. Each actual PCMCIA
|
||||
* card corresponds to one device instance, and is described by one dev_link_t
|
||||
* structure (defined in ds.h).
|
||||
*
|
||||
* You may not want to use a linked list for this -- for example, the memory
|
||||
* card driver uses an array of dev_link_t pointers, where minor device
|
||||
* numbers are used to derive the corresponding array index.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static dev_link_t * dev_list = NULL;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* A dev_link_t structure has fields for most things that are needed to keep
|
||||
* track of a socket, but there will usually be some device specific
|
||||
* information that also needs to be kept track of. The 'priv' pointer in a
|
||||
* dev_link_t structure can be used to point to a device-specific private data
|
||||
* structure, like this.
|
||||
*
|
||||
* A driver needs to provide a dev_node_t structure for each device on a
|
||||
* card. In some cases, there is only one device per card (for example,
|
||||
* ethernet cards, modems). In other cases, there may be many actual or
|
||||
* logical devices (SCSI adapters, memory cards with multiple partitions).
|
||||
* The dev_node_t structures need to be kept in a linked list starting at the
|
||||
* 'dev' field of a dev_link_t structure. We allocate them in the card's
|
||||
* private data structure, because they generally can't be allocated
|
||||
* dynamically.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
typedef struct local_info_t {
|
||||
|
||||
dev_node_t node;
|
||||
} local_info_t;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static void cs_error(client_handle_t handle, int func, int ret) {
|
||||
error_info_t err = { func, ret };
|
||||
|
||||
CardServices (ReportError, handle, &err);
|
||||
} /* cs_error */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* fcpcmcia_attach() creates an "instance" of the driver, allocating local
|
||||
* data structures for one device. The device is registered with Card
|
||||
* Services.
|
||||
*
|
||||
* The dev_link structure is initialized, but we don't actually configure the
|
||||
* card at this point -- we wait until we receive a card insertion event.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static dev_link_t * fcpcmcia_attach(void) {
|
||||
client_reg_t client_reg;
|
||||
dev_link_t * link;
|
||||
local_info_t * local;
|
||||
int ret, i;
|
||||
|
||||
DEBUG (0, "fcpcmcia_attach()\n");
|
||||
|
||||
/* Initialize the dev_link_t structure */
|
||||
link = kmalloc (sizeof (struct dev_link_t), GFP_KERNEL);
|
||||
memset (link, 0, sizeof (struct dev_link_t));
|
||||
link->release.function = &fcpcmcia_release;
|
||||
link->release.data = (u_long) link;
|
||||
|
||||
/* The io structure describes IO port mapping */
|
||||
link->io.NumPorts1 = 16;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts2 = 16;
|
||||
link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
|
||||
link->io.IOAddrLines = 5;
|
||||
|
||||
/* Interrupt setup */
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED;
|
||||
|
||||
link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
|
||||
if (irq_list[0] != -1) {
|
||||
for (i = 0; i < 10 && irq_list[i] > 0; i++) {
|
||||
link->irq.IRQInfo2 |= 1 << irq_list[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 10 && default_irq_list[i] > 0; i++) {
|
||||
link->irq.IRQInfo2 |= 1 << default_irq_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* General socket configuration */
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.Vcc = 50;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
link->conf.ConfigIndex = 1;
|
||||
link->conf.Present = PRESENT_OPTION;
|
||||
|
||||
/* Allocate space for private device-specific data */
|
||||
local = kmalloc (sizeof (local_info_t), GFP_KERNEL);
|
||||
memset (local, 0, sizeof (local_info_t));
|
||||
link->priv = local;
|
||||
|
||||
/* Register with Card Services */
|
||||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &fcpcmcia_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
ret = CardServices (RegisterClient, &link->handle, &client_reg);
|
||||
if (ret != 0) {
|
||||
cs_error (link->handle, RegisterClient, ret);
|
||||
fcpcmcia_detach (link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link;
|
||||
} /* fcpcmcia_attach */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* This deletes a driver "instance". The device is de-registered with Card
|
||||
* Services. If it has been released, all local data structures are freed.
|
||||
* Otherwise, the structures will be freed when the device is released.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static void fcpcmcia_detach (dev_link_t * link)
|
||||
{
|
||||
dev_link_t ** linkp;
|
||||
|
||||
DEBUG (0, "fcpcmcia_detach(0x%p)\n", link);
|
||||
|
||||
/* Locate device structure */
|
||||
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
|
||||
if (*linkp == link) break;
|
||||
}
|
||||
if (*linkp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*\
|
||||
* If the device is currently configured and active, we won't actually
|
||||
* delete it yet. Instead, it is marked so that when the release()
|
||||
* function is called, that will trigger a proper detach().
|
||||
\*-----------------------------------------------------------------------*/
|
||||
if (link->state & DEV_CONFIG) {
|
||||
#ifdef PCMCIA_DEBUG
|
||||
printk (KERN_DEBUG "fcpcmcia_cs: detach postponed, '%s' "
|
||||
"still locked\n", link->dev->dev_name);
|
||||
#endif
|
||||
link->state |= DEV_STALE_LINK;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Break the link with Card Services */
|
||||
if (link->handle) {
|
||||
CardServices (DeregisterClient, link->handle);
|
||||
}
|
||||
|
||||
/* Unlink device structure, free pieces */
|
||||
*linkp = link->next;
|
||||
if (link->priv) {
|
||||
kfree_s (link->priv, sizeof(local_info_t));
|
||||
}
|
||||
kfree_s (link, sizeof(struct dev_link_t));
|
||||
|
||||
} /* fcpcmcia_detach */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static int get_tuple (int fn, client_handle_t handle, tuple_t * tuple,
|
||||
cisparse_t *parse)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = CardServices (fn, handle, tuple);
|
||||
if (i != CS_SUCCESS) {
|
||||
return i;
|
||||
}
|
||||
i = CardServices (GetTupleData, handle, tuple);
|
||||
if (i != CS_SUCCESS) {
|
||||
return i;
|
||||
}
|
||||
return CardServices (ParseTuple, handle, tuple, parse);
|
||||
} /* get_tuple */
|
||||
|
||||
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
|
||||
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* fcpcmcia_config() is scheduled to run after a CARD_INSERTION event is
|
||||
* received, to configure the PCMCIA socket, and to make the ISDN controller
|
||||
* available to the system.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static void fcpcmcia_config (dev_link_t * link) {
|
||||
client_handle_t handle;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
cistpl_cftable_entry_t * cf = &parse.cftable_entry;
|
||||
local_info_t * dev;
|
||||
int i;
|
||||
u_char buf[64];
|
||||
char devname[128];
|
||||
int cardtype;
|
||||
|
||||
handle = link->handle;
|
||||
dev = link->priv;
|
||||
|
||||
DEBUG (0, "fcpcmcia_config(0x%p)\n", link);
|
||||
|
||||
/*-----------------------------------------------------------------------*\
|
||||
* Read the card's CONFIG tuple to find its configuration registers.
|
||||
\*-----------------------------------------------------------------------*/
|
||||
do {
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
i = CardServices (GetFirstTuple, handle, &tuple);
|
||||
if (i != CS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = 64;
|
||||
tuple.TupleOffset = 0;
|
||||
i = CardServices (GetTupleData, handle, &tuple);
|
||||
if (i != CS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
i = CardServices (ParseTuple, handle, &tuple, &parse);
|
||||
if (i != CS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
} while (0);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error (link->handle, ParseTuple, i);
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure card */
|
||||
link->state |= DEV_CONFIG;
|
||||
|
||||
do {
|
||||
tuple.Attributes = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = 254;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.DesiredTuple = CISTPL_VERS_1;
|
||||
|
||||
devname[0] = 0;
|
||||
if (!first_tuple (handle, &tuple, &parse) && (parse.version_1.ns > 1)) {
|
||||
strncpy (devname, parse.version_1.str + parse.version_1.ofs[1],
|
||||
sizeof(devname));
|
||||
}
|
||||
|
||||
/* find IO port */
|
||||
tuple.TupleData = (cisdata_t *) buf;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.TupleDataMax = 255;
|
||||
tuple.Attributes = 0;
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
i = first_tuple (handle, &tuple, &parse);
|
||||
while (i == CS_SUCCESS) {
|
||||
if (cf->io.nwin > 0) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
link->io.BasePort1 = cf->io.win[0].base;
|
||||
link->io.NumPorts1 = cf->io.win[0].len;
|
||||
printk (KERN_INFO "fcpcmcia_cs: testing i/o %#x-%#x\n",
|
||||
link->io.BasePort1,
|
||||
link->io.BasePort1 + link->io.NumPorts1);
|
||||
i = CardServices (RequestIO, link->handle, &link->io);
|
||||
if (i == CS_SUCCESS) {
|
||||
goto found_port;
|
||||
}
|
||||
}
|
||||
i = next_tuple (handle, &tuple, &parse);
|
||||
}
|
||||
|
||||
found_port:
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error (link->handle, RequestIO, i);
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate an interrupt line */
|
||||
i = CardServices (RequestIRQ, link->handle, &link->irq);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error (link->handle, RequestIRQ, i);
|
||||
CardServices (ReleaseIO, link->handle, &link->io);
|
||||
break;
|
||||
}
|
||||
|
||||
/* configure the PCMCIA socket */
|
||||
i = CardServices (RequestConfiguration, link->handle, &link->conf);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error (link->handle, RequestConfiguration, i);
|
||||
CardServices (ReleaseIO, link->handle, &link->io);
|
||||
CardServices (ReleaseIRQ, link->handle, &link->irq);
|
||||
break;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
/*-----------------------------------------------------------------------*\
|
||||
* At this point, the dev_node_t structure(s) should be initialized and
|
||||
* arranged in a linked list at link->dev.
|
||||
\*-----------------------------------------------------------------------*/
|
||||
strcpy (dev->node.dev_name, "A1");
|
||||
dev->node.major = 45; /* <<<< */
|
||||
dev->node.minor = 0; /* <<<< */
|
||||
link->dev = &dev->node;
|
||||
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
/* If any step failed, release any partially configured state */
|
||||
if (i != 0) {
|
||||
fcpcmcia_release ((u_long) link);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i = avm_a1pcmcia_addcard (link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
|
||||
printk (KERN_ERR "fcpcmcia_cs: failed to add AVM-%s-Controller at"
|
||||
" i/o %#x, irq %d\n",
|
||||
dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
fcpcmcia_release ((u_long) link);
|
||||
return;
|
||||
}
|
||||
dev->node.minor = i;
|
||||
|
||||
printk (KERN_DEBUG "fcpcmcia_cs device loaded\n");
|
||||
} /* fcpcmcia_config */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* After a card is removed, fcpcmcia_release() will unregister the net device,
|
||||
* and release the PCMCIA configuration. If the device is still open, this
|
||||
* will be postponed until it is closed.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
static void fcpcmcia_release (u_long arg) {
|
||||
dev_link_t * link = (dev_link_t *) arg;
|
||||
|
||||
DEBUG (0, "fcpcmcia_release(0x%p)\n", link);
|
||||
|
||||
/*-----------------------------------------------------------------------*\
|
||||
* If the device is currently in use, we won't release until it is
|
||||
* actually closed.
|
||||
\*-----------------------------------------------------------------------*/
|
||||
if (link->open) {
|
||||
DEBUG (1, "fcpcmcia_cs: release postponed, '%s' still open\n",
|
||||
link->dev->dev_name);
|
||||
link->state |= DEV_STALE_CONFIG;
|
||||
return;
|
||||
}
|
||||
|
||||
avm_a1pcmcia_delcard (link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
|
||||
/* Unlink the device chain */
|
||||
link->dev = NULL;
|
||||
|
||||
/* Don't bother checking to see if these succeed or not */
|
||||
(void) CardServices (ReleaseConfiguration, link->handle);
|
||||
(void) CardServices (ReleaseIO, link->handle, &link->io);
|
||||
(void) CardServices (ReleaseIRQ, link->handle, &link->irq);
|
||||
link->state &= ~DEV_CONFIG;
|
||||
|
||||
if (link->state & DEV_STALE_LINK)
|
||||
fcpcmcia_detach (link);
|
||||
|
||||
} /* fcpcmcia_release */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* The card status event handler. Mostly, this schedules other stuff to run
|
||||
* after an event is received. A CARD_REMOVAL event also sets some flags to
|
||||
* discourage the net drivers from trying to talk to the card any more.
|
||||
*
|
||||
* When a CARD_REMOVAL event is received, we immediately set a flag to block
|
||||
* future accesses to this device. All the functions that actually access
|
||||
* the device should check this flag to make sure the card is still present.
|
||||
\*---------------------------------------------------------------------------*/
|
||||
static int fcpcmcia_event (event_t event, int priority,
|
||||
event_callback_args_t * args)
|
||||
{
|
||||
dev_link_t * link = args->client_data;
|
||||
|
||||
DEBUG (1, "fcpcmcia_event(0x%06x)\n", event);
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
link->state &= ~DEV_PRESENT;
|
||||
if (link->state & DEV_CONFIG) {
|
||||
link->release.expires = RUN_AT (HZ/20);
|
||||
add_timer (&link->release);
|
||||
}
|
||||
break;
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||
fcpcmcia_config (link);
|
||||
break;
|
||||
case CS_EVENT_PM_SUSPEND:
|
||||
link->state |= DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
if (link->state & DEV_CONFIG) {
|
||||
CardServices (ReleaseConfiguration, link->handle);
|
||||
}
|
||||
break;
|
||||
case CS_EVENT_PM_RESUME:
|
||||
link->state &= ~DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_CARD_RESET:
|
||||
if (link->state & DEV_CONFIG) {
|
||||
CardServices (RequestConfiguration, link->handle, &link->conf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
} /* fcpcmcia_event */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
\*---------------------------------------------------------------------------*/
|
||||
int init_module (void) {
|
||||
servinfo_t serv;
|
||||
|
||||
DEBUG (0, "%s\n", version);
|
||||
CardServices (GetCardServicesInfo, &serv);
|
||||
if (serv.Revision != CS_RELEASE_CODE) {
|
||||
printk (KERN_NOTICE "fcpcmcia_cs: Card Services release "
|
||||
"does not match!\n");
|
||||
return -1;
|
||||
}
|
||||
register_pcmcia_driver (&dev_info, &fcpcmcia_attach, &fcpcmcia_detach);
|
||||
return 0;
|
||||
} /* init_module */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
\*---------------------------------------------------------------------------*/
|
||||
void cleanup_module (void) {
|
||||
|
||||
DEBUG (0, "fcpcmcia_cs: unloading\n");
|
||||
unregister_pcmcia_driver (&dev_info);
|
||||
while (dev_list != NULL) {
|
||||
if (dev_list->state & DEV_CONFIG) {
|
||||
fcpcmcia_release ((u_long) dev_list);
|
||||
}
|
||||
fcpcmcia_detach (dev_list);
|
||||
}
|
||||
} /* cleanup_module */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
|
@ -1,65 +1,14 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Kernel CAPI 2.0 Module
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.11 1999/11/23 13:29:29 calle
|
||||
* Bugfix: incoming capi message were never traced.
|
||||
*
|
||||
* Revision 1.10 1999/10/26 15:30:32 calle
|
||||
* Generate error message if user want to add card, but driver module is
|
||||
* not loaded.
|
||||
*
|
||||
* Revision 1.9 1999/10/11 22:04:12 keil
|
||||
* COMPAT_NEED_UACCESS (no include in isdn_compat.h)
|
||||
*
|
||||
* Revision 1.8 1999/09/10 17:24:18 calle
|
||||
* Changes for proposed standard for CAPI2.0:
|
||||
* - AK148 "Linux Exention"
|
||||
*
|
||||
* Revision 1.7 1999/09/04 06:20:05 keil
|
||||
* Changes from kernel set_current_state()
|
||||
*
|
||||
* Revision 1.6 1999/07/20 06:41:49 calle
|
||||
* Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
|
||||
* compile, if not selected as modules.
|
||||
*
|
||||
* Revision 1.5 1999/07/09 15:05:48 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.4 1999/07/08 14:15:17 calle
|
||||
* Forgot to count down ncards in drivercb_detach_ctr.
|
||||
*
|
||||
* Revision 1.3 1999/07/06 07:42:02 calle
|
||||
* - changes in /proc interface
|
||||
* - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
|
||||
*
|
||||
* Revision 1.2 1999/07/05 15:09:52 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.1 1999/07/01 15:26:42 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#define CONFIG_AVMB1_COMPAT
|
||||
|
||||
#include <linux/config.h>
|
||||
|
@ -72,12 +21,12 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/tqueue.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#ifdef COMPAT_NEED_UACCESS
|
||||
#include <linux/locks.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/uaccess.h>
|
||||
#endif
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
#include "capilli.h"
|
||||
|
@ -96,10 +45,12 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
int showcapimsgs = 0;
|
||||
static int showcapimsgs = 0;
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_PARM(showcapimsgs, "0-4i");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_PARM(showcapimsgs, "i");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -124,8 +75,8 @@ struct capi_appl {
|
|||
__u16 applid;
|
||||
capi_register_params rparam;
|
||||
int releasing;
|
||||
__u32 param;
|
||||
void (*signal) (__u16 applid, __u32 param);
|
||||
void *param;
|
||||
void (*signal) (__u16 applid, void *param);
|
||||
struct sk_buff_head recv_queue;
|
||||
int nncci;
|
||||
struct capi_ncci *nccilist;
|
||||
|
@ -136,6 +87,14 @@ struct capi_appl {
|
|||
unsigned long nsentdatapkt;
|
||||
};
|
||||
|
||||
struct capi_notifier {
|
||||
struct capi_notifier *next;
|
||||
unsigned int cmd;
|
||||
__u32 controller;
|
||||
__u16 applid;
|
||||
__u32 ncci;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_version driver_version = {2, 0, 1, 1<<4};
|
||||
|
@ -159,9 +118,9 @@ static struct capi_ctr cards[CAPI_MAXCONTR];
|
|||
static int ncards = 0;
|
||||
static struct sk_buff_head recv_queue;
|
||||
static struct capi_interface_user *capi_users = 0;
|
||||
static spinlock_t capi_users_lock = SPIN_LOCK_UNLOCKED;
|
||||
static struct capi_driver *drivers;
|
||||
static long notify_up_set = 0;
|
||||
static long notify_down_set = 0;
|
||||
static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static struct tq_struct tq_state_notify;
|
||||
static struct tq_struct tq_recv_notify;
|
||||
|
@ -225,7 +184,6 @@ static int proc_applications_read_proc(char *page, char **start, off_t off,
|
|||
struct capi_appl *ap;
|
||||
int i;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
for (i=0; i < CAPI_MAXAPPL; i++) {
|
||||
ap = &applications[i];
|
||||
|
@ -237,20 +195,21 @@ static int proc_applications_read_proc(char *page, char **start, off_t off,
|
|||
ap->rparam.datablklen,
|
||||
ap->nncci,
|
||||
skb_queue_len(&ap->recv_queue));
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (i >= CAPI_MAXAPPL)
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -264,7 +223,6 @@ static int proc_ncci_read_proc(char *page, char **start, off_t off,
|
|||
struct capi_ncci *np;
|
||||
int i;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
for (i=0; i < CAPI_MAXAPPL; i++) {
|
||||
ap = &applications[i];
|
||||
|
@ -275,21 +233,22 @@ static int proc_ncci_read_proc(char *page, char **start, off_t off,
|
|||
np->ncci,
|
||||
np->winsize,
|
||||
np->nmsg);
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (i >= CAPI_MAXAPPL)
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -301,27 +260,29 @@ static int proc_driver_read_proc(char *page, char **start, off_t off,
|
|||
{
|
||||
struct capi_driver *driver;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
spin_lock(&drivers_lock);
|
||||
for (driver = drivers; driver; driver = driver->next) {
|
||||
len += sprintf(page+len, "%-32s %d %s\n",
|
||||
driver->name,
|
||||
driver->ncontroller,
|
||||
driver->revision);
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (!driver)
|
||||
spin_unlock(&drivers_lock);
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -333,24 +294,26 @@ static int proc_users_read_proc(char *page, char **start, off_t off,
|
|||
{
|
||||
struct capi_interface_user *cp;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
spin_lock(&capi_users_lock);
|
||||
for (cp = capi_users; cp ; cp = cp->next) {
|
||||
len += sprintf(page+len, "%s\n", cp->name);
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (cp == 0)
|
||||
spin_unlock(&capi_users_lock);
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -363,7 +326,6 @@ static int proc_controller_read_proc(char *page, char **start, off_t off,
|
|||
struct capi_ctr *cp;
|
||||
int i;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
for (i=0; i < CAPI_MAXCONTR; i++) {
|
||||
cp = &cards[i];
|
||||
|
@ -374,20 +336,21 @@ static int proc_controller_read_proc(char *page, char **start, off_t off,
|
|||
cp->name,
|
||||
cp->driver->procinfo ? cp->driver->procinfo(cp) : ""
|
||||
);
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (i >= CAPI_MAXCONTR)
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -400,7 +363,6 @@ static int proc_applstats_read_proc(char *page, char **start, off_t off,
|
|||
struct capi_appl *ap;
|
||||
int i;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
for (i=0; i < CAPI_MAXAPPL; i++) {
|
||||
ap = &applications[i];
|
||||
|
@ -411,20 +373,21 @@ static int proc_applstats_read_proc(char *page, char **start, off_t off,
|
|||
ap->nrecvdatapkt,
|
||||
ap->nsentctlpkt,
|
||||
ap->nsentdatapkt);
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (i >= CAPI_MAXAPPL)
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -437,7 +400,6 @@ static int proc_contrstats_read_proc(char *page, char **start, off_t off,
|
|||
struct capi_ctr *cp;
|
||||
int i;
|
||||
int len = 0;
|
||||
off_t begin = 0;
|
||||
|
||||
for (i=0; i < CAPI_MAXCONTR; i++) {
|
||||
cp = &cards[i];
|
||||
|
@ -448,20 +410,21 @@ static int proc_contrstats_read_proc(char *page, char **start, off_t off,
|
|||
cp->nrecvdatapkt,
|
||||
cp->nsentctlpkt,
|
||||
cp->nsentdatapkt);
|
||||
if (len+begin > off+count)
|
||||
goto endloop;
|
||||
if (len+begin < off) {
|
||||
begin += len;
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
} else {
|
||||
if (len-off > count)
|
||||
goto endloop;
|
||||
}
|
||||
}
|
||||
endloop:
|
||||
if (i >= CAPI_MAXCONTR)
|
||||
*start = page+off;
|
||||
if (len < count)
|
||||
*eof = 1;
|
||||
if (off >= len+begin)
|
||||
return 0;
|
||||
*start = page + (begin-off);
|
||||
return ((count < begin+len-off) ? count : begin+len-off);
|
||||
if (len>count) len = count;
|
||||
if (len<0) len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct procfsentries {
|
||||
|
@ -509,6 +472,176 @@ static void proc_capi_exit(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* -------- Notifier handling --------------------------------- */
|
||||
|
||||
static struct capi_notifier_list{
|
||||
struct capi_notifier *head;
|
||||
struct capi_notifier *tail;
|
||||
} notifier_list;
|
||||
|
||||
static spinlock_t notifier_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static inline void notify_enqueue(struct capi_notifier *np)
|
||||
{
|
||||
struct capi_notifier_list *q = ¬ifier_list;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(¬ifier_lock, flags);
|
||||
if (q->tail) {
|
||||
q->tail->next = np;
|
||||
q->tail = np;
|
||||
} else {
|
||||
q->head = q->tail = np;
|
||||
}
|
||||
spin_unlock_irqrestore(¬ifier_lock, flags);
|
||||
}
|
||||
|
||||
static inline struct capi_notifier *notify_dequeue(void)
|
||||
{
|
||||
struct capi_notifier_list *q = ¬ifier_list;
|
||||
struct capi_notifier *np = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(¬ifier_lock, flags);
|
||||
if (q->head) {
|
||||
np = q->head;
|
||||
if ((q->head = np->next) == 0)
|
||||
q->tail = 0;
|
||||
np->next = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(¬ifier_lock, flags);
|
||||
return np;
|
||||
}
|
||||
|
||||
static int notify_push(unsigned int cmd, __u32 controller,
|
||||
__u16 applid, __u32 ncci)
|
||||
{
|
||||
struct capi_notifier *np;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);
|
||||
if (!np) {
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -1;
|
||||
}
|
||||
memset(np, 0, sizeof(struct capi_notifier));
|
||||
np->cmd = cmd;
|
||||
np->controller = controller;
|
||||
np->applid = applid;
|
||||
np->ncci = ncci;
|
||||
notify_enqueue(np);
|
||||
/*
|
||||
* The notifier will result in adding/deleteing
|
||||
* of devices. Devices can only removed in
|
||||
* user process, not in bh.
|
||||
*/
|
||||
#ifdef COMPAT_HAS_SCHEDULE_TASK
|
||||
MOD_INC_USE_COUNT;
|
||||
if (schedule_task(&tq_state_notify) == 0)
|
||||
MOD_DEC_USE_COUNT;
|
||||
#else
|
||||
queue_task(&tq_state_notify, &tq_scheduler);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------- KCI_CONTRUP --------------------------------------- */
|
||||
|
||||
static void notify_up(__u32 contr)
|
||||
{
|
||||
struct capi_interface_user *p;
|
||||
|
||||
printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
|
||||
spin_lock(&capi_users_lock);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (!p->callback) continue;
|
||||
(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);
|
||||
}
|
||||
spin_unlock(&capi_users_lock);
|
||||
}
|
||||
|
||||
/* -------- KCI_CONTRDOWN ------------------------------------- */
|
||||
|
||||
static void notify_down(__u32 contr)
|
||||
{
|
||||
struct capi_interface_user *p;
|
||||
printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
|
||||
spin_lock(&capi_users_lock);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (!p->callback) continue;
|
||||
(*p->callback) (KCI_CONTRDOWN, contr, 0);
|
||||
}
|
||||
spin_unlock(&capi_users_lock);
|
||||
}
|
||||
|
||||
/* -------- KCI_NCCIUP ---------------------------------------- */
|
||||
|
||||
static void notify_ncciup(__u32 contr, __u16 applid, __u32 ncci)
|
||||
{
|
||||
struct capi_interface_user *p;
|
||||
struct capi_ncciinfo n;
|
||||
n.applid = applid;
|
||||
n.ncci = ncci;
|
||||
/*printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);*/
|
||||
spin_lock(&capi_users_lock);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (!p->callback) continue;
|
||||
(*p->callback) (KCI_NCCIUP, contr, &n);
|
||||
}
|
||||
spin_unlock(&capi_users_lock);
|
||||
};
|
||||
|
||||
/* -------- KCI_NCCIDOWN -------------------------------------- */
|
||||
|
||||
static void notify_nccidown(__u32 contr, __u16 applid, __u32 ncci)
|
||||
{
|
||||
struct capi_interface_user *p;
|
||||
struct capi_ncciinfo n;
|
||||
n.applid = applid;
|
||||
n.ncci = ncci;
|
||||
/*printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);*/
|
||||
spin_lock(&capi_users_lock);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (!p->callback) continue;
|
||||
(*p->callback) (KCI_NCCIDOWN, contr, &n);
|
||||
}
|
||||
spin_unlock(&capi_users_lock);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
static void inline notify_doit(struct capi_notifier *np)
|
||||
{
|
||||
switch (np->cmd) {
|
||||
case KCI_CONTRUP:
|
||||
notify_up(np->controller);
|
||||
break;
|
||||
case KCI_CONTRDOWN:
|
||||
notify_down(np->controller);
|
||||
break;
|
||||
case KCI_NCCIUP:
|
||||
notify_ncciup(np->controller, np->applid, np->ncci);
|
||||
break;
|
||||
case KCI_NCCIDOWN:
|
||||
notify_nccidown(np->controller, np->applid, np->ncci);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_handler(void *dummy)
|
||||
{
|
||||
struct capi_notifier *np;
|
||||
|
||||
while ((np = notify_dequeue()) != 0) {
|
||||
notify_doit(np);
|
||||
kfree(np);
|
||||
MOD_DEC_USE_COUNT;
|
||||
}
|
||||
#ifdef COMPAT_HAS_SCHEDULE_TASK
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -------- NCCI Handling ------------------------------------- */
|
||||
|
||||
static inline void mq_init(struct capi_ncci * np)
|
||||
|
@ -587,7 +720,7 @@ static void controllercb_appl_released(struct capi_ctr * card, __u16 appl)
|
|||
}
|
||||
}
|
||||
/*
|
||||
* ncci managment
|
||||
* ncci management
|
||||
*/
|
||||
|
||||
static void controllercb_new_ncci(struct capi_ctr * card,
|
||||
|
@ -616,6 +749,7 @@ static void controllercb_new_ncci(struct capi_ctr * card,
|
|||
APPL(appl)->nncci++;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
|
||||
|
||||
notify_push(KCI_NCCIUP, CARDNR(card), appl, ncci);
|
||||
}
|
||||
|
||||
static void controllercb_free_ncci(struct capi_ctr * card,
|
||||
|
@ -633,6 +767,7 @@ static void controllercb_free_ncci(struct capi_ctr * card,
|
|||
kfree(np);
|
||||
APPL(appl)->nncci--;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
|
||||
notify_push(KCI_NCCIDOWN, CARDNR(card), appl, ncci);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -733,42 +868,6 @@ error:
|
|||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* -------- Notifier ------------------------------------------ */
|
||||
|
||||
static void notify_up(__u32 contr)
|
||||
{
|
||||
struct capi_interface_user *p;
|
||||
|
||||
printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (!p->callback) continue;
|
||||
(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_down(__u32 contr)
|
||||
{
|
||||
struct capi_interface_user *p;
|
||||
printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (!p->callback) continue;
|
||||
(*p->callback) (KCI_CONTRDOWN, contr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_handler(void *dummy)
|
||||
{
|
||||
__u32 contr;
|
||||
|
||||
for (contr=1; VALID_CARD(contr); contr++)
|
||||
if (test_and_clear_bit(contr, ¬ify_up_set))
|
||||
notify_up(contr);
|
||||
for (contr=1; VALID_CARD(contr); contr++)
|
||||
if (test_and_clear_bit(contr, ¬ify_down_set))
|
||||
notify_down(contr);
|
||||
}
|
||||
|
||||
|
||||
static void controllercb_ready(struct capi_ctr * card)
|
||||
{
|
||||
__u16 appl;
|
||||
|
@ -781,11 +880,10 @@ static void controllercb_ready(struct capi_ctr * card)
|
|||
card->driver->register_appl(card, appl, &APPL(appl)->rparam);
|
||||
}
|
||||
|
||||
set_bit(CARDNR(card), ¬ify_up_set);
|
||||
queue_task(&tq_state_notify, &tq_scheduler);
|
||||
|
||||
printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
|
||||
CARDNR(card), card->name);
|
||||
|
||||
notify_push(KCI_CONTRUP, CARDNR(card), 0, 0);
|
||||
}
|
||||
|
||||
static void controllercb_reseted(struct capi_ctr * card)
|
||||
|
@ -811,6 +909,7 @@ static void controllercb_reseted(struct capi_ctr * card)
|
|||
struct capi_ncci *np = *pp;
|
||||
*pp = np->next;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
|
||||
notify_push(KCI_NCCIDOWN, CARDNR(card), appl, np->ncci);
|
||||
kfree(np);
|
||||
nextpp = pp;
|
||||
} else {
|
||||
|
@ -818,9 +917,10 @@ static void controllercb_reseted(struct capi_ctr * card)
|
|||
}
|
||||
}
|
||||
}
|
||||
set_bit(CARDNR(card), ¬ify_down_set);
|
||||
queue_task(&tq_state_notify, &tq_scheduler);
|
||||
|
||||
printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card));
|
||||
|
||||
notify_push(KCI_CONTRDOWN, CARDNR(card), 0, 0);
|
||||
}
|
||||
|
||||
static void controllercb_suspend_output(struct capi_ctr *card)
|
||||
|
@ -936,7 +1036,7 @@ static int driver_read_proc(char *page, char **start, off_t off,
|
|||
if (len < off)
|
||||
return 0;
|
||||
*eof = 1;
|
||||
*start = page - off;
|
||||
*start = page + off;
|
||||
return ((count < len-off) ? count : len-off);
|
||||
}
|
||||
|
||||
|
@ -951,9 +1051,12 @@ struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
|
|||
{
|
||||
struct capi_driver **pp;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
spin_lock(&drivers_lock);
|
||||
for (pp = &drivers; *pp; pp = &(*pp)->next) ;
|
||||
driver->next = 0;
|
||||
*pp = driver;
|
||||
spin_unlock(&drivers_lock);
|
||||
printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);
|
||||
sprintf(driver->procfn, "capi/drivers/%s", driver->name);
|
||||
driver->procent = create_proc_entry(driver->procfn, 0, 0);
|
||||
|
@ -973,6 +1076,7 @@ struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
|
|||
void detach_capi_driver(struct capi_driver *driver)
|
||||
{
|
||||
struct capi_driver **pp;
|
||||
spin_lock(&drivers_lock);
|
||||
for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
|
||||
if (*pp) {
|
||||
*pp = (*pp)->next;
|
||||
|
@ -980,10 +1084,12 @@ void detach_capi_driver(struct capi_driver *driver)
|
|||
} else {
|
||||
printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);
|
||||
}
|
||||
spin_unlock(&drivers_lock);
|
||||
if (driver->procent) {
|
||||
remove_proc_entry(driver->procfn, 0);
|
||||
driver->procent = 0;
|
||||
}
|
||||
MOD_DEC_USE_COUNT;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
@ -1035,19 +1141,19 @@ static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
|
|||
|
||||
static __u16 capi_release(__u16 applid)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int i;
|
||||
|
||||
if (!VALID_APPLID(applid) || APPL(applid)->releasing)
|
||||
return CAPI_ILLAPPNR;
|
||||
while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
|
||||
kfree_skb(skb);
|
||||
APPL(applid)->releasing++;
|
||||
skb_queue_purge(&APPL(applid)->recv_queue);
|
||||
for (i = 0; i < CAPI_MAXCONTR; i++) {
|
||||
if (cards[i].cardstate != CARD_RUNNING)
|
||||
continue;
|
||||
APPL(applid)->releasing++;
|
||||
cards[i].driver->release_appl(&cards[i], applid);
|
||||
}
|
||||
APPL(applid)->releasing--;
|
||||
if (APPL(applid)->releasing <= 0) {
|
||||
APPL(applid)->signal = 0;
|
||||
APPL_MARK_FREE(applid);
|
||||
|
@ -1127,8 +1233,8 @@ static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
|
|||
}
|
||||
|
||||
static __u16 capi_set_signal(__u16 applid,
|
||||
void (*signal) (__u16 applid, __u32 param),
|
||||
__u32 param)
|
||||
void (*signal) (__u16 applid, void *param),
|
||||
void *param)
|
||||
{
|
||||
if (!VALID_APPLID(applid))
|
||||
return CAPI_ILLAPPNR;
|
||||
|
@ -1193,10 +1299,12 @@ static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp)
|
|||
static struct capi_driver *find_driver(char *name)
|
||||
{
|
||||
struct capi_driver *dp;
|
||||
spin_lock(&drivers_lock);
|
||||
for (dp = drivers; dp; dp = dp->next)
|
||||
if (strcmp(dp->name, name) == 0)
|
||||
return dp;
|
||||
return 0;
|
||||
break;
|
||||
spin_unlock(&drivers_lock);
|
||||
return dp;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AVMB1_COMPAT
|
||||
|
@ -1271,6 +1379,10 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
|
|||
card = CARD(ldef.contr);
|
||||
if (card->cardstate == CARD_FREE)
|
||||
return -ESRCH;
|
||||
if (card->driver->load_firmware == 0) {
|
||||
printk(KERN_DEBUG "kcapi: load: driver \%s\" has no load function\n", card->driver->name);
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
if (ldef.t4file.len <= 0) {
|
||||
printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
|
||||
|
@ -1489,16 +1601,20 @@ struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
|
|||
{
|
||||
struct capi_interface_user *p;
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
spin_lock(&capi_users_lock);
|
||||
for (p = capi_users; p; p = p->next) {
|
||||
if (p == userp) {
|
||||
spin_unlock(&capi_users_lock);
|
||||
printk(KERN_ERR "kcapi: double attach from %s\n",
|
||||
userp->name);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
userp->next = capi_users;
|
||||
capi_users = userp;
|
||||
MOD_INC_USE_COUNT;
|
||||
spin_unlock(&capi_users_lock);
|
||||
printk(KERN_NOTICE "kcapi: %s attached\n", userp->name);
|
||||
|
||||
return &avmb1_interface;
|
||||
|
@ -1508,15 +1624,18 @@ int detach_capi_interface(struct capi_interface_user *userp)
|
|||
{
|
||||
struct capi_interface_user **pp;
|
||||
|
||||
spin_lock(&capi_users_lock);
|
||||
for (pp = &capi_users; *pp; pp = &(*pp)->next) {
|
||||
if (*pp == userp) {
|
||||
*pp = userp->next;
|
||||
spin_unlock(&capi_users_lock);
|
||||
userp->next = 0;
|
||||
MOD_DEC_USE_COUNT;
|
||||
printk(KERN_NOTICE "kcapi: %s detached\n", userp->name);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
spin_unlock(&capi_users_lock);
|
||||
printk(KERN_ERR "kcapi: double detach from %s\n", userp->name);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1530,42 +1649,18 @@ EXPORT_SYMBOL(detach_capi_interface);
|
|||
EXPORT_SYMBOL(attach_capi_driver);
|
||||
EXPORT_SYMBOL(detach_capi_driver);
|
||||
|
||||
#ifndef MODULE
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
|
||||
extern int b1isa_init(void);
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
|
||||
extern int b1pci_init(void);
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
|
||||
extern int t1isa_init(void);
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
|
||||
extern int b1pcmcia_init(void);
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
|
||||
extern int t1pci_init(void);
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_C4
|
||||
extern int c4_init(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* init / exit functions
|
||||
*/
|
||||
|
||||
#ifdef MODULE
|
||||
#define kcapi_init init_module
|
||||
#endif
|
||||
|
||||
int kcapi_init(void)
|
||||
static int __init kcapi_init(void)
|
||||
{
|
||||
char *p;
|
||||
char rev[10];
|
||||
char rev[32];
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
skb_queue_head_init(&recv_queue);
|
||||
/* init_bh(CAPI_BH, do_capi_bh); */
|
||||
|
||||
tq_state_notify.routine = notify_handler;
|
||||
tq_state_notify.data = 0;
|
||||
|
@ -1575,41 +1670,24 @@ int kcapi_init(void)
|
|||
|
||||
proc_capi_init();
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strcpy(rev, p + 1);
|
||||
p = strchr(rev, '$');
|
||||
*p = 0;
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(rev, p + 2, sizeof(rev));
|
||||
rev[sizeof(rev)-1] = 0;
|
||||
if ((p = strchr(rev, '$')) != 0 && p > rev)
|
||||
*(p-1) = 0;
|
||||
} else
|
||||
strcpy(rev, "1.0");
|
||||
|
||||
#ifdef MODULE
|
||||
printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev);
|
||||
printk(KERN_NOTICE "CAPI-driver Rev %s: loaded\n", rev);
|
||||
#else
|
||||
printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev);
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
|
||||
(void)b1isa_init();
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
|
||||
(void)b1pci_init();
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
|
||||
(void)t1isa_init();
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
|
||||
(void)b1pcmcia_init();
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
|
||||
(void)t1pci_init();
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_AVMB1_C4
|
||||
(void)c4_init();
|
||||
#endif
|
||||
printk(KERN_NOTICE "CAPI-driver Rev %s: started\n", rev);
|
||||
#endif
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit kcapi_exit(void)
|
||||
{
|
||||
char rev[10];
|
||||
char *p;
|
||||
|
@ -1622,8 +1700,9 @@ void cleanup_module(void)
|
|||
strcpy(rev, "1.0");
|
||||
}
|
||||
|
||||
schedule(); /* execute queued tasks .... */
|
||||
proc_capi_exit();
|
||||
printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(kcapi_init);
|
||||
module_exit(kcapi_exit);
|
||||
|
|
|
@ -1,65 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Module for AVM T1 HEMA-card.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 2000/01/25 14:37:39 calle
|
||||
* new message after successfull detection including card revision and
|
||||
* used resources.
|
||||
*
|
||||
* Revision 1.8 1999/11/05 16:38:01 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.7 1999/09/15 08:16:03 calle
|
||||
* Implementation of 64Bit extention complete.
|
||||
*
|
||||
* Revision 1.6 1999/09/07 09:02:53 calle
|
||||
* SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
|
||||
* DATA_B3_IND is always directly after the CAPI message. The "Data" member
|
||||
* ist never used inside the kernel.
|
||||
*
|
||||
* Revision 1.5 1999/08/22 20:26:28 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.4 1999/07/09 15:05:50 keil
|
||||
* compat.h is now isdn_compat.h
|
||||
*
|
||||
* Revision 1.3 1999/07/06 07:42:04 calle
|
||||
* - changes in /proc interface
|
||||
* - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
|
||||
*
|
||||
* Revision 1.2 1999/07/05 15:09:54 calle
|
||||
* - renamed "appl_release" to "appl_released".
|
||||
* - version und profile data now cleared on controller reset
|
||||
* - extended /proc interface, to allow driver and controller specific
|
||||
* informations to include by driver hackers.
|
||||
*
|
||||
* Revision 1.1 1999/07/01 15:26:44 calle
|
||||
* complete new version (I love it):
|
||||
* + new hardware independed "capi_driver" interface that will make it easy to:
|
||||
* - support other controllers with CAPI-2.0 (i.e. USB Controller)
|
||||
* - write a CAPI-2.0 for the passive cards
|
||||
* - support serial link CAPI-2.0 boxes.
|
||||
* + wrote "capi_driver" for all supported cards.
|
||||
* + "capi_driver" (supported cards) now have to be configured with
|
||||
* make menuconfig, in the past all supported cards where included
|
||||
* at once.
|
||||
* + new and better informations in /proc/capi/
|
||||
* + new ioctl to switch trace of capi messages per controller
|
||||
* using "avmcapictrl trace [contr] on|off|...."
|
||||
* + complete testcircle with all supported cards and also the
|
||||
* PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -71,8 +17,10 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/capi.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include <asm/io.h>
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
#include "capilli.h"
|
||||
|
@ -82,7 +30,9 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -132,7 +82,7 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
|
|||
cli();
|
||||
/* board reset */
|
||||
t1outp(base, T1_RESETBOARD, 0xf);
|
||||
udelay(100 * 1000);
|
||||
mdelay(100);
|
||||
dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
|
||||
|
||||
/* write config */
|
||||
|
@ -144,18 +94,18 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
|
|||
t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
|
||||
restore_flags(flags);
|
||||
|
||||
udelay(100 * 1000);
|
||||
mdelay(100);
|
||||
t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
|
||||
t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
|
||||
t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
|
||||
udelay(100 * 1000);
|
||||
mdelay(100);
|
||||
t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
|
||||
t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
|
||||
udelay(10 * 1000);
|
||||
mdelay(10);
|
||||
t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
|
||||
udelay(5 * 1000);
|
||||
mdelay(5);
|
||||
t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
|
||||
|
||||
if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
|
||||
|
@ -275,25 +225,30 @@ static void t1_handle_interrupt(avmcard * card)
|
|||
case RECEIVE_TASK_READY:
|
||||
ApplId = (unsigned) b1_get_word(card->port);
|
||||
MsgLen = t1_get_slice(card->port, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
|
||||
card->name, ApplId, card->msgbuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_DEBUGMSG:
|
||||
MsgLen = t1_get_slice(card->port, card->msgbuf);
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
while ( MsgLen >= 0
|
||||
&& ( card->msgbuf[MsgLen] == '\n'
|
||||
|| card->msgbuf[MsgLen] == '\r'))
|
||||
card->msgbuf[MsgLen--] = 0;
|
||||
card->msgbuf[MsgLen] = 0;
|
||||
while ( MsgLen > 0
|
||||
&& ( card->msgbuf[MsgLen-1] == '\n'
|
||||
|| card->msgbuf[MsgLen-1] == '\r')) {
|
||||
card->msgbuf[MsgLen-1] = 0;
|
||||
MsgLen--;
|
||||
}
|
||||
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
|
||||
break;
|
||||
|
||||
|
||||
case 0xff:
|
||||
printk(KERN_ERR "%s: card reseted ?\n", card->name);
|
||||
return;
|
||||
|
@ -367,7 +322,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
|
|||
cli();
|
||||
b1_setinterrupt(port, card->irq, card->cardtype);
|
||||
b1_put_byte(port, SEND_INIT);
|
||||
b1_put_word(port, AVM_NAPPS);
|
||||
b1_put_word(port, CAPI_MAXAPPL);
|
||||
b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
|
||||
b1_put_word(port, ctrl->cnr - 1);
|
||||
restore_flags(flags);
|
||||
|
@ -570,36 +525,35 @@ static char *t1isa_procinfo(struct capi_ctr *ctrl)
|
|||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_driver t1isa_driver = {
|
||||
"t1isa",
|
||||
"0.0",
|
||||
t1isa_load_firmware,
|
||||
t1isa_reset_ctr,
|
||||
t1isa_remove_ctr,
|
||||
b1_register_appl,
|
||||
b1_release_appl,
|
||||
t1isa_send_message,
|
||||
name: "t1isa",
|
||||
revision: "0.0",
|
||||
load_firmware: t1isa_load_firmware,
|
||||
reset_ctr: t1isa_reset_ctr,
|
||||
remove_ctr: t1isa_remove_ctr,
|
||||
register_appl: b1_register_appl,
|
||||
release_appl: b1_release_appl,
|
||||
send_message: t1isa_send_message,
|
||||
|
||||
t1isa_procinfo,
|
||||
b1ctl_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: t1isa_procinfo,
|
||||
ctr_read_proc: b1ctl_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
t1isa_add_card,
|
||||
add_card: t1isa_add_card,
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
#define t1isa_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
int t1isa_init(void)
|
||||
static int __init t1isa_init(void)
|
||||
{
|
||||
struct capi_driver *driver = &t1isa_driver;
|
||||
char *p;
|
||||
int retval = 0;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(driver->revision, p + 1, sizeof(driver->revision));
|
||||
p = strchr(driver->revision, '$');
|
||||
*p = 0;
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driver->revision, p + 2, sizeof(driver->revision));
|
||||
driver->revision[sizeof(driver->revision)-1] = 0;
|
||||
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
|
||||
|
@ -609,14 +563,17 @@ int t1isa_init(void)
|
|||
if (!di) {
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driver->name);
|
||||
return -EIO;
|
||||
retval = -EIO;
|
||||
}
|
||||
return 0;
|
||||
|
||||
MOD_DEC_USE_COUNT;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit t1isa_exit(void)
|
||||
{
|
||||
detach_capi_driver(&t1isa_driver);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(t1isa_init);
|
||||
module_exit(t1isa_exit);
|
||||
|
|
|
@ -1,29 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Module for AVM T1 PCI-card.
|
||||
*
|
||||
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.4 2000/01/25 14:33:38 calle
|
||||
* - Added Support AVM B1 PCI V4.0 (tested with prototype)
|
||||
* - splitted up t1pci.c into b1dma.c for common function with b1pciv4
|
||||
* - support for revision register
|
||||
*
|
||||
* Revision 1.3 1999/11/13 21:27:16 keil
|
||||
* remove KERNELVERSION
|
||||
*
|
||||
* Revision 1.2 1999/11/05 16:38:02 calle
|
||||
* Cleanups before kernel 2.4:
|
||||
* - Changed all messages to use card->name or driver->name instead of
|
||||
* constant string.
|
||||
* - Moved some data from struct avmcard into new struct avmctrl_info.
|
||||
* Changed all lowlevel capi driver to match the new structur.
|
||||
*
|
||||
* Revision 1.1 1999/10/26 15:31:42 calle
|
||||
* Added driver for T1-PCI card.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -36,9 +18,10 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/capi.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
#include "capicmd.h"
|
||||
#include "capiutil.h"
|
||||
#include "capilli.h"
|
||||
|
@ -51,17 +34,17 @@ static char *revision = "$Revision$";
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#ifndef PCI_VENDOR_ID_AVM
|
||||
#define PCI_VENDOR_ID_AVM 0x1244
|
||||
#ifndef COMPAT_HAS_2_2_PCI
|
||||
static struct pci_device_id t1pci_pci_tbl[] __initdata = {
|
||||
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_AVM_T1
|
||||
#define PCI_DEVICE_ID_AVM_T1 0x1200
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -78,7 +61,7 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
|
|||
|
||||
di->detach_ctr(ctrl);
|
||||
free_irq(card->irq, card);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
ctrl->driverdata = 0;
|
||||
kfree(card->ctrlinfo);
|
||||
|
@ -92,7 +75,6 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
|
|||
|
||||
static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
|
||||
{
|
||||
unsigned long base, page_offset;
|
||||
avmcard *card;
|
||||
avmctrl_info *cinfo;
|
||||
int retval;
|
||||
|
@ -143,12 +125,8 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
base = card->membase & PAGE_MASK;
|
||||
page_offset = card->membase - base;
|
||||
card->mbase = ioremap_nocache(base, page_offset + 64);
|
||||
if (card->mbase) {
|
||||
card->mbase += page_offset;
|
||||
} else {
|
||||
card->mbase = ioremap_nocache(card->membase, 64);
|
||||
if (!card->mbase) {
|
||||
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
|
||||
driver->name, card->membase);
|
||||
kfree(card->ctrlinfo);
|
||||
|
@ -161,9 +139,13 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
b1dma_reset(card);
|
||||
|
||||
if ((retval = t1pci_detect(card)) != 0) {
|
||||
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
|
||||
if (retval < 6)
|
||||
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
|
||||
driver->name, card->port, retval);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
else
|
||||
printk(KERN_NOTICE "%s: card at 0x%x, but cabel not connected or T1 has no power (%d)\n",
|
||||
driver->name, card->port, retval);
|
||||
iounmap(card->mbase);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
kfree(card);
|
||||
|
@ -178,7 +160,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
if (retval) {
|
||||
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
|
||||
driver->name, card->irq);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
kfree(card->ctrlinfo);
|
||||
kfree(card->dma);
|
||||
|
@ -190,7 +172,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
|
|||
cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
|
||||
if (!cinfo->capi_ctrl) {
|
||||
printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
|
||||
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
|
||||
iounmap(card->mbase);
|
||||
free_irq(card->irq, card);
|
||||
release_region(card->port, AVMB1_PORTLEN);
|
||||
kfree(card->ctrlinfo);
|
||||
|
@ -231,65 +213,63 @@ static char *t1pci_procinfo(struct capi_ctr *ctrl)
|
|||
/* ------------------------------------------------------------- */
|
||||
|
||||
static struct capi_driver t1pci_driver = {
|
||||
"t1pci",
|
||||
"0.0",
|
||||
b1dma_load_firmware,
|
||||
b1dma_reset_ctr,
|
||||
t1pci_remove_ctr,
|
||||
b1dma_register_appl,
|
||||
b1dma_release_appl,
|
||||
b1dma_send_message,
|
||||
name: "t1pci",
|
||||
revision: "0.0",
|
||||
load_firmware: b1dma_load_firmware,
|
||||
reset_ctr: b1dma_reset_ctr,
|
||||
remove_ctr: t1pci_remove_ctr,
|
||||
register_appl: b1dma_register_appl,
|
||||
release_appl: b1dma_release_appl,
|
||||
send_message: b1dma_send_message,
|
||||
|
||||
t1pci_procinfo,
|
||||
b1dmactl_read_proc,
|
||||
0, /* use standard driver_read_proc */
|
||||
procinfo: t1pci_procinfo,
|
||||
ctr_read_proc: b1dmactl_read_proc,
|
||||
driver_read_proc: 0, /* use standard driver_read_proc */
|
||||
|
||||
0, /* no add_card function */
|
||||
add_card: 0, /* no add_card function */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
#define t1pci_init init_module
|
||||
void cleanup_module(void);
|
||||
#endif
|
||||
|
||||
static int ncards = 0;
|
||||
|
||||
int t1pci_init(void)
|
||||
static int __init t1pci_init(void)
|
||||
{
|
||||
struct capi_driver *driver = &t1pci_driver;
|
||||
struct pci_dev *dev = NULL;
|
||||
char *p;
|
||||
int retval;
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strncpy(driver->revision, p + 1, sizeof(driver->revision));
|
||||
p = strchr(driver->revision, '$');
|
||||
*p = 0;
|
||||
MOD_INC_USE_COUNT;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strncpy(driver->revision, p + 2, sizeof(driver->revision));
|
||||
driver->revision[sizeof(driver->revision)-1] = 0;
|
||||
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
|
||||
*(p-1) = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
|
||||
|
||||
di = attach_capi_driver(driver);
|
||||
|
||||
if (!di) {
|
||||
printk(KERN_ERR "%s: failed to attach capi_driver\n",
|
||||
driver->name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (!pci_present()) {
|
||||
printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
|
||||
detach_capi_driver(driver);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) {
|
||||
struct capicardparams param;
|
||||
|
||||
param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
|
||||
param.irq = dev->irq;
|
||||
param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
if (pci_enable_device(dev) < 0) {
|
||||
printk(KERN_ERR "%s: failed to enable AVM-T1-PCI\n",
|
||||
driver->name);
|
||||
continue;
|
||||
}
|
||||
pci_set_master(dev);
|
||||
|
||||
param.port = pci_resource_start_io(dev, 1);
|
||||
param.irq = dev->irq;
|
||||
param.membase = pci_resource_start_mem(dev, 0);
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
|
||||
|
@ -299,29 +279,26 @@ int t1pci_init(void)
|
|||
printk(KERN_ERR
|
||||
"%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
|
||||
driver->name, param.port, param.irq, param.membase);
|
||||
#ifdef MODULE
|
||||
cleanup_module();
|
||||
#endif
|
||||
return retval;
|
||||
continue;
|
||||
}
|
||||
ncards++;
|
||||
}
|
||||
if (ncards) {
|
||||
printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n",
|
||||
driver->name, ncards);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name);
|
||||
return -ESRCH;
|
||||
#else
|
||||
printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
|
||||
return -EIO;
|
||||
#endif
|
||||
detach_capi_driver(&t1pci_driver);
|
||||
MOD_DEC_USE_COUNT;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
static void __exit t1pci_exit(void)
|
||||
{
|
||||
detach_capi_driver(&t1pci_driver);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(t1pci_init);
|
||||
module_exit(t1pci_exit);
|
||||
|
|
|
@ -1,328 +0,0 @@
|
|||
/* $Id$
|
||||
|
||||
* Variable-debugging for isdn4linux.
|
||||
*
|
||||
* Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Copyright 1995 Thinking Objects Software GmbH Wuerzburg
|
||||
*
|
||||
* This file is part of Isdn4Linux.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.6 1999/04/12 12:33:07 fritz
|
||||
* Changes from 2.0 tree.
|
||||
*
|
||||
* Revision 1.5 1997/02/03 23:34:51 fritz
|
||||
* Reformatted
|
||||
*
|
||||
* Revision 1.4 1996/04/30 07:55:50 fritz
|
||||
* Disabled mmap.
|
||||
*
|
||||
* Revision 1.3 1996/04/28 15:19:23 fritz
|
||||
* adapted to new ioctl names.
|
||||
*
|
||||
* Revision 1.2 1996/01/04 02:46:16 fritz
|
||||
* Changed copying policy to GPL.
|
||||
*
|
||||
* Revision 1.1 1995/12/18 18:22:52 fritz
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/fcntl.h>
|
||||
/* #include <sys/mman.h> */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/isdn.h>
|
||||
#include <linux/isdnif.h>
|
||||
|
||||
typedef unsigned char uchar;
|
||||
int mem_fd;
|
||||
|
||||
#if 0 /* Weiss der Teufel, warum das nicht mit mmap geht */
|
||||
uchar
|
||||
* mapmem(ulong location, long size)
|
||||
{
|
||||
ulong mmseg;
|
||||
ulong mmsize;
|
||||
ulong addr;
|
||||
ulong offset;
|
||||
|
||||
mmseg = location & 0xffffe000L;
|
||||
mmsize = (location - mmseg + size) + 0x1000;
|
||||
offset = location - mmseg;
|
||||
addr = (ulong) mmap(0, mmsize, PROT_READ, MAP_SHARED, mem_fd, mmseg);
|
||||
if ((int) addr == -1) {
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
printf("mmap: loc=%08lx siz=%08lx mseg=%08lx msiz=%08lx ofs=%08lx adr=%08lx\n", location, size, mmseg, mmsize, offset, addr);
|
||||
return ((uchar *) (addr + offset));
|
||||
}
|
||||
#else
|
||||
uchar
|
||||
* mapmem(ulong location, long size)
|
||||
{
|
||||
uchar *buffer;
|
||||
|
||||
if ((buffer = malloc(size))) {
|
||||
lseek(mem_fd, location, SEEK_SET);
|
||||
read(mem_fd, buffer, size);
|
||||
} else {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
dumpIntArray(int *arr, int count)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *p = buf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
p += sprintf(p, "%d%s", arr[i], (i < (count - 1)) ? ", " : "\0");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
char *
|
||||
dumpCharArray(char *arr, int count)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *p = buf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
p += sprintf(p, "%02x%s", (uchar) arr[i], (i < (count - 1)) ? ", " : "\0");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
char *
|
||||
dumpStringArray(char *arr, int count, int len)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *p = buf;
|
||||
char *s = arr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; s += len, i++)
|
||||
p += sprintf(p, "\"%s\"%s", s, (i < (count - 1)) ? ", " : "\0");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
void
|
||||
dumpDriver(ulong drvaddr)
|
||||
{
|
||||
driver *drv = (driver *) mapmem(drvaddr, sizeof(driver));
|
||||
isdn_if *ifc = (isdn_if *) mapmem((ulong) drv->interface, sizeof(isdn_if));
|
||||
|
||||
printf(" online = %08lx\n", drv->online);
|
||||
printf(" channels = %d\n", drv->channels);
|
||||
printf(" locks = %d\n", drv->locks);
|
||||
printf(" reject_bus = %d\n", drv->flags & DRV_FLAG_REJBUS);
|
||||
printf(" running = %d\n", drv->flags & DRV_FLAG_RUNNING);
|
||||
printf(" loaded = %d\n", drv->flags & DRV_FLAG_LOADED);
|
||||
printf(" maxbufsize = %d\n", drv->maxbufsize);
|
||||
printf(" pktcount = %ld\n", drv->pktcount);
|
||||
printf(" stavail = %d\n", drv->stavail);
|
||||
printf(" Interface @%08lx:\n", (ulong) drv->interface);
|
||||
printf(" Id(ch) = %d\n", ifc->channels);
|
||||
printf(" maxbufsize = %d\n", ifc->maxbufsize);
|
||||
printf(" features = %08lx\n", ifc->features);
|
||||
}
|
||||
|
||||
void
|
||||
dumpModem(modem mdm)
|
||||
{
|
||||
int i;
|
||||
atemu *atm;
|
||||
modem_info *info;
|
||||
|
||||
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
|
||||
printf("mdm [%02d]\n", i);
|
||||
printf(" msr = %08x\n", mdm.msr[i]);
|
||||
printf(" mlr = %08x\n", mdm.mlr[i]);
|
||||
printf(" refcount = %d\n", mdm.refcount);
|
||||
printf(" online = %d\n", mdm.online[i]);
|
||||
printf(" dialing = %d\n", mdm.dialing[i]);
|
||||
printf(" rcvsched = %d\n", mdm.rcvsched[i]);
|
||||
printf(" ncarrier = %d\n", mdm.ncarrier[i]);
|
||||
printf(" atmodem:\n");
|
||||
atm = &mdm.atmodem[i];
|
||||
printf(" profile = \n %s\n", dumpCharArray(atm->mdmreg, ISDN_MODEM_NUMREG));
|
||||
printf(" mdmreg = \n %s\n", dumpCharArray(atm->mdmreg, ISDN_MODEM_NUMREG));
|
||||
printf(" msn = \"%s\"\n", atm->msn);
|
||||
printf(" mdmcmdl = %d\n", atm->mdmcmdl);
|
||||
printf(" pluscount = %d\n", atm->pluscount);
|
||||
printf(" lastplus = %08x\n", atm->lastplus);
|
||||
printf(" mdmcmd = \"%s\"\n", atm->mdmcmd);
|
||||
printf(" info:\n");
|
||||
info = &mdm.info[i];
|
||||
printf(" magic = %08x\n", info->magic);
|
||||
printf(" flags = %08x\n", info->flags);
|
||||
printf(" type = %d\n", info->type);
|
||||
printf(" x_char = %02x\n", info->x_char);
|
||||
printf(" close_delay = %d\n", info->close_delay);
|
||||
printf(" MCR = %08x\n", info->MCR);
|
||||
printf(" line = %d\n", info->line);
|
||||
printf(" count = %d\n", info->count);
|
||||
printf(" blocked_open = %d\n", info->blocked_open);
|
||||
printf(" session = %08lx\n", info->session);
|
||||
printf(" pgrp = %08lx\n", info->pgrp);
|
||||
printf(" isdn_driver = %d\n", info->isdn_driver);
|
||||
printf(" isdn_channel = %d\n", info->isdn_channel);
|
||||
printf(" drv_index = %d\n", info->drv_index);
|
||||
printf(" xmit_size = %d\n", info->xmit_size);
|
||||
printf(" xmit_count = %d\n", info->xmit_count);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpNetPhone(ulong paddr)
|
||||
{
|
||||
ulong pa = paddr;
|
||||
isdn_net_phone *phone;
|
||||
|
||||
while (pa) {
|
||||
phone = (isdn_net_phone *) mapmem(pa, sizeof(isdn_net_phone));
|
||||
printf(" @%08lx: \"%s\"\n", pa, phone->num);
|
||||
pa = (ulong) (phone->next);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpNetDev(ulong devaddr)
|
||||
{
|
||||
ulong nda = devaddr;
|
||||
isdn_net_dev *ndev;
|
||||
|
||||
while (nda) {
|
||||
ndev = (isdn_net_dev *) mapmem(nda, sizeof(isdn_net_dev));
|
||||
printf("Net-Device @%08lx:\n", nda);
|
||||
printf("dev. :\n");
|
||||
printf(" start = %d\n", ndev->dev.start);
|
||||
printf(" tbusy = %ld\n", ndev->dev.tbusy);
|
||||
printf(" interrupt = %d\n", ndev->dev.interrupt);
|
||||
printf("local. :\n");
|
||||
printf(" name = \"%s\"\n", ndev->local.name);
|
||||
printf(" isdn_device = %d\n", ndev->local.isdn_device);
|
||||
printf(" isdn_channel = %d\n", ndev->local.isdn_channel);
|
||||
printf(" ppp_minor = %d\n", ndev->local.ppp_minor);
|
||||
printf(" pre_device = %d\n", ndev->local.pre_device);
|
||||
printf(" pre_channel = %d\n", ndev->local.pre_channel);
|
||||
printf(" exclusive = %d\n", ndev->local.exclusive);
|
||||
printf(" flags = %d\n", ndev->local.flags);
|
||||
printf(" dialstate = %d\n", ndev->local.dialstate);
|
||||
printf(" dialretry = %d\n", ndev->local.dialretry);
|
||||
printf(" dialmax = %d\n", ndev->local.dialmax);
|
||||
printf(" msn = \"%s\"\n", ndev->local.msn);
|
||||
printf(" dtimer = %d\n", ndev->local.dtimer);
|
||||
printf(" p_encap = %d\n", ndev->local.p_encap);
|
||||
printf(" l2_proto = %d\n", ndev->local.l2_proto);
|
||||
printf(" l3_proto = %d\n", ndev->local.l3_proto);
|
||||
printf(" huptimer = %d\n", ndev->local.huptimer);
|
||||
printf(" charge = %d\n", ndev->local.charge);
|
||||
printf(" chargetime = %08x\n", ndev->local.chargetime);
|
||||
printf(" hupflags = %d\n", ndev->local.hupflags);
|
||||
printf(" outgoing = %d\n", ndev->local.outgoing);
|
||||
printf(" onhtime = %d\n", ndev->local.onhtime);
|
||||
printf(" chargeint = %d\n", ndev->local.chargeint);
|
||||
printf(" onum = %d\n", ndev->local.onum);
|
||||
printf(" sqfull = %08x\n", ndev->local.sqfull);
|
||||
printf(" sqfull_stamp = %08lx\n", ndev->local.sqfull_stamp);
|
||||
printf(" master = -> %08x\n", (unsigned int) ndev->local.master);
|
||||
printf(" slave = -> %08x\n", (unsigned int) ndev->local.slave);
|
||||
if (ndev->local.phone[0]) {
|
||||
printf(" phone[in]:\n");
|
||||
dumpNetPhone((ulong) ndev->local.phone[0]);
|
||||
} else
|
||||
printf(" phone[in] = NULL\n");
|
||||
if (ndev->local.phone[1]) {
|
||||
printf(" phone[out]:\n");
|
||||
dumpNetPhone((ulong) ndev->local.phone[1]);
|
||||
} else
|
||||
printf(" phone[out] = NULL\n");
|
||||
printf(" dial = @%08lx\n", (ulong) ndev->local.dial);
|
||||
nda = (ulong) (ndev->next);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
int f;
|
||||
int i;
|
||||
static isdn_dev *my_isdndev;
|
||||
ulong kaddr;
|
||||
|
||||
printf("\nDebugger for isdn and icn Modules\n");
|
||||
f = open("/dev/isdnctrl", O_RDONLY);
|
||||
if (ioctl(f, IIOCDBGVAR, &kaddr)) {
|
||||
perror("ioctl IIOCDBGVAR");
|
||||
exit(-1);
|
||||
}
|
||||
close(f);
|
||||
if ((mem_fd = open("/dev/kmem", O_RDWR)) < 0) {
|
||||
perror("open /dev/kmem");
|
||||
exit(1);
|
||||
}
|
||||
printf("isdn-main-struct at %08lx (%d):\n", kaddr, sizeof(isdn_dev));
|
||||
my_isdndev = (isdn_dev *) mapmem(kaddr, sizeof(isdn_dev));
|
||||
printf("isdndev.flags = %d\n", my_isdndev->flags);
|
||||
printf("isdndev.drivers = %d\n", my_isdndev->drivers);
|
||||
printf("isdndev.channels = %d\n", my_isdndev->channels);
|
||||
printf("isdndev.net_verbose = %d\n", my_isdndev->net_verbose);
|
||||
printf("isdndev.modempoll = %d\n", my_isdndev->modempoll);
|
||||
printf("isdndev.tflags = %d\n", my_isdndev->tflags);
|
||||
printf("isdndev.global_flags = %d\n", my_isdndev->global_flags);
|
||||
if (my_isdndev->infochain) {
|
||||
printf("isdndev.infochain = @%08lx:\n", (ulong) my_isdndev->infochain);
|
||||
} else
|
||||
printf("isdndev.infochain = NULL\n");
|
||||
if (my_isdndev->info_waitq) {
|
||||
printf("isdndev.info_waitq = @%08lx:\n", (ulong) my_isdndev->info_waitq);
|
||||
} else
|
||||
printf("isdndev.info_waitq = NULL\n");
|
||||
printf("isdndev.chanmap = %s\n",
|
||||
dumpIntArray(my_isdndev->chanmap, ISDN_MAX_CHANNELS));
|
||||
printf("isdndev.drvmap = %s\n",
|
||||
dumpIntArray(my_isdndev->drvmap, ISDN_MAX_CHANNELS));
|
||||
printf("isdndev.usage = %s\n",
|
||||
dumpIntArray(my_isdndev->usage, ISDN_MAX_CHANNELS));
|
||||
printf("isdndev.num = %s\n",
|
||||
dumpStringArray(my_isdndev->num[0], ISDN_MAX_CHANNELS, 20));
|
||||
printf("isdndev.m_idx = %s\n",
|
||||
dumpIntArray(my_isdndev->m_idx, ISDN_MAX_CHANNELS));
|
||||
dumpModem(my_isdndev->mdm);
|
||||
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
|
||||
if (my_isdndev->drv[i]) {
|
||||
printf("isdndev.drv[%02d] = @%08lx:\n", i, (ulong) my_isdndev->drv[i]);
|
||||
dumpDriver((ulong) (my_isdndev->drv[i]));
|
||||
}
|
||||
if (my_isdndev->netdev) {
|
||||
printf("isdndev.netdev = @%08lx:\n", (ulong) my_isdndev->netdev);
|
||||
dumpNetDev((ulong) my_isdndev->netdev);
|
||||
} else
|
||||
printf("isdndev.netdev = NULL\n");
|
||||
close(mem_fd);
|
||||
}
|
|
@ -1,18 +1,26 @@
|
|||
L_OBJS :=
|
||||
LX_OBJS :=
|
||||
M_OBJS :=
|
||||
MX_OBJS :=
|
||||
O_OBJS :=
|
||||
OX_OBJS :=
|
||||
L_TARGET :=
|
||||
O_TARGET :=
|
||||
#
|
||||
# Makefile for the dss1_divert ISDN module
|
||||
#
|
||||
|
||||
O_OBJS += isdn_divert.o divert_procfs.o
|
||||
O_TARGET := dss1_divert.o
|
||||
M_OBJS += dss1_divert.o
|
||||
OX_OBJS += divert_init.o
|
||||
# The target object and module list name.
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
O_TARGET := vmlinux-obj.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
list-multi := dss1_divert.o
|
||||
dss1_divert-objs := isdn_divert.o divert_procfs.o divert_init.o
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_ISDN_DIVERSION) += dss1_divert.o
|
||||
|
||||
include $(TOPDIR)/drivers/isdn/Rules.make
|
||||
|
||||
# Link rules for multi-part drivers.
|
||||
|
||||
dss1_divert.o: $(dss1_divert-objs)
|
||||
$(LD) -r -o $@ $(dss1_divert-objs)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,40 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id divert_init.c,v 1.5.6.2 2001/01/24 22:18:17 kai Exp $
|
||||
*
|
||||
* Module init for DSS1 diversion services for i4l.
|
||||
*
|
||||
* Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1999/07/05 20:21:39 werner
|
||||
* changes to use diversion sources for all kernel versions.
|
||||
* removed static device, only proc filesystem used
|
||||
*
|
||||
* Revision 1.2 1999/07/04 21:37:30 werner
|
||||
* Ported from kernel version 2.0
|
||||
*
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include "isdn_divert.h"
|
||||
|
||||
MODULE_DESCRIPTION("ISDN4Linux: Call diversion support");
|
||||
MODULE_AUTHOR("Werner Cornelius");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/********************/
|
||||
/* needed externals */
|
||||
/********************/
|
||||
|
@ -56,7 +39,7 @@ isdn_divert_if divert_if =
|
|||
/* Module interface code */
|
||||
/* no cmd line parms */
|
||||
/*************************/
|
||||
int init_module(void)
|
||||
static int __init divert_init(void)
|
||||
{ int i;
|
||||
|
||||
if (divert_dev_init())
|
||||
|
@ -73,13 +56,13 @@ int init_module(void)
|
|||
#endif
|
||||
printk(KERN_INFO "dss1_divert module successfully installed\n");
|
||||
return(0);
|
||||
} /* init_module */
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Module deinit code */
|
||||
/**********************/
|
||||
void cleanup_module(void)
|
||||
{ int flags;
|
||||
static void __exit divert_exit(void)
|
||||
{ unsigned long flags;
|
||||
int i;
|
||||
|
||||
save_flags(flags);
|
||||
|
@ -99,6 +82,8 @@ void cleanup_module(void)
|
|||
deleterule(-1); /* delete all rules and free mem */
|
||||
deleteprocs();
|
||||
printk(KERN_INFO "dss1_divert module successfully removed \n");
|
||||
} /* cleanup_module */
|
||||
}
|
||||
|
||||
module_init(divert_init);
|
||||
module_exit(divert_exit);
|
||||
|
||||
|
|
|
@ -1,44 +1,11 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Filesystem handling for the diversion supplementary services.
|
||||
*
|
||||
* Copyright 1998 by Werner Cornelius (werner@isdn4linux.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.6 2000/02/14 19:23:03 werner
|
||||
*
|
||||
* Changed handling of proc filesystem tables to a more portable version
|
||||
*
|
||||
* Revision 1.5 1999/09/14 20:31:01 werner
|
||||
*
|
||||
* Removed obsoleted functions for proc fs and synced with new ones.
|
||||
*
|
||||
* Revision 1.4 1999/08/06 07:42:48 calle
|
||||
* Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels.
|
||||
*
|
||||
* Revision 1.3 1999/07/05 20:21:41 werner
|
||||
* changes to use diversion sources for all kernel versions.
|
||||
* removed static device, only proc filesystem used
|
||||
*
|
||||
* Revision 1.2 1999/07/04 21:37:31 werner
|
||||
* Ported from kernel version 2.0
|
||||
*
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -47,6 +14,9 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/poll.h>
|
||||
#ifndef COMPAT_USE_MODCOUNT_LOCK
|
||||
#include <linux/smp_lock.h>
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
#else
|
||||
|
@ -62,11 +32,7 @@
|
|||
ulong if_used = 0; /* number of interface users */
|
||||
static struct divert_info *divert_info_head = NULL; /* head of queue */
|
||||
static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
|
||||
#ifdef COMPAT_HAS_NEW_WAITQ
|
||||
static wait_queue_head_t rd_queue;
|
||||
#else
|
||||
static struct wait_queue *rd_queue = 0; /* Queue IO */
|
||||
#endif
|
||||
|
||||
/*********************************/
|
||||
/* put an info buffer into queue */
|
||||
|
@ -75,7 +41,7 @@ void
|
|||
put_info_buffer(char *cp)
|
||||
{
|
||||
struct divert_info *ib;
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
|
||||
if (if_used <= 0)
|
||||
return;
|
||||
|
@ -170,9 +136,13 @@ isdn_divert_poll(struct file *file, poll_table * wait)
|
|||
static int
|
||||
isdn_divert_open(struct inode *ino, struct file *filep)
|
||||
{
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef COMPAT_USE_MODCOUNT_LOCK
|
||||
MOD_INC_USE_COUNT;
|
||||
#else
|
||||
lock_kernel();
|
||||
#endif
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if_used++;
|
||||
|
@ -182,6 +152,9 @@ isdn_divert_open(struct inode *ino, struct file *filep)
|
|||
(struct divert_info **) filep->private_data = &divert_info_head;
|
||||
restore_flags(flags);
|
||||
/* start_divert(); */
|
||||
#ifndef COMPAT_USE_MODCOUNT_LOCK
|
||||
unlock_kernel();
|
||||
#endif
|
||||
return (0);
|
||||
} /* isdn_divert_open */
|
||||
|
||||
|
@ -192,8 +165,11 @@ static int
|
|||
isdn_divert_close(struct inode *ino, struct file *filep)
|
||||
{
|
||||
struct divert_info *inf;
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
|
||||
#ifndef COMPAT_USE_MODCOUNT_LOCK
|
||||
lock_kernel();
|
||||
#endif
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if_used--;
|
||||
|
@ -209,7 +185,11 @@ isdn_divert_close(struct inode *ino, struct file *filep)
|
|||
divert_info_head = divert_info_head->next;
|
||||
kfree(inf);
|
||||
}
|
||||
#ifdef COMPAT_USE_MODCOUNT_LOCK
|
||||
MOD_DEC_USE_COUNT;
|
||||
#else
|
||||
unlock_kernel();
|
||||
#endif
|
||||
return (0);
|
||||
} /* isdn_divert_close */
|
||||
|
||||
|
@ -221,7 +201,8 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
|
|||
uint cmd, ulong arg)
|
||||
{
|
||||
divert_ioctl dioctl;
|
||||
int i, flags;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
divert_rule *rulep;
|
||||
char *cp;
|
||||
|
||||
|
@ -299,27 +280,16 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
|
|||
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static loff_t
|
||||
isdn_divert_lseek(struct file *file, loff_t offset, int orig)
|
||||
{
|
||||
return -ESPIPE;
|
||||
}
|
||||
|
||||
static struct file_operations isdn_fops =
|
||||
{
|
||||
isdn_divert_lseek,
|
||||
isdn_divert_read,
|
||||
isdn_divert_write,
|
||||
NULL, /* isdn_readdir */
|
||||
isdn_divert_poll, /* isdn_poll */
|
||||
isdn_divert_ioctl, /* isdn_ioctl */
|
||||
NULL, /* isdn_mmap */
|
||||
isdn_divert_open,
|
||||
NULL, /* flush */
|
||||
isdn_divert_close,
|
||||
NULL /* fsync */
|
||||
llseek: no_llseek,
|
||||
read: isdn_divert_read,
|
||||
write: isdn_divert_write,
|
||||
poll: isdn_divert_poll,
|
||||
ioctl: isdn_divert_ioctl,
|
||||
open: isdn_divert_open,
|
||||
release: isdn_divert_close,
|
||||
};
|
||||
|
||||
#ifdef COMPAT_NO_SOFTNET
|
||||
struct inode_operations divert_file_inode_operations;
|
||||
#endif
|
||||
|
@ -338,9 +308,7 @@ int
|
|||
divert_dev_init(void)
|
||||
{
|
||||
|
||||
#ifdef COMPAT_HAS_NEW_WAITQ
|
||||
init_waitqueue_head(&rd_queue);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
|
||||
|
@ -357,8 +325,10 @@ divert_dev_init(void)
|
|||
isdn_divert_entry->ops = &divert_file_inode_operations;
|
||||
#else
|
||||
isdn_divert_entry->proc_fops = &isdn_fops;
|
||||
#ifdef COMPAT_HAS_FILEOP_OWNER
|
||||
isdn_divert_entry->owner = THIS_MODULE;
|
||||
#endif
|
||||
|
||||
#endif /* COMPAT_NO_SOFTNET */
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
return (0);
|
||||
|
|
|
@ -1,46 +1,14 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* DSS1 main diversion supplementary handling for i4l.
|
||||
*
|
||||
* Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.4 1999/08/25 20:02:21 werner
|
||||
* Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts
|
||||
* with existing software definitions. (PtP incomplete called party number)
|
||||
*
|
||||
* Revision 1.3 1999/08/22 20:26:35 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.2 1999/07/04 21:37:32 werner
|
||||
* Ported from kernel version 2.0
|
||||
*
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include "isdn_divert.h"
|
||||
|
@ -83,7 +51,7 @@ static unsigned char extern_wait_max = 4; /* maximum wait in s for external proc
|
|||
/* timer callback function */
|
||||
/***************************/
|
||||
static void deflect_timer_expire(ulong arg)
|
||||
{ int flags;
|
||||
{ unsigned long flags;
|
||||
struct call_struc *cs = (struct call_struc *) arg;
|
||||
|
||||
save_flags(flags);
|
||||
|
@ -116,6 +84,9 @@ static void deflect_timer_expire(ulong arg)
|
|||
restore_flags(flags);
|
||||
break;
|
||||
|
||||
case NETWORK_DIAL:
|
||||
divert_if.dial_net_name(cs->deflect_dest);
|
||||
|
||||
case DEFLECT_AUTODEL:
|
||||
default:
|
||||
save_flags(flags);
|
||||
|
@ -141,7 +112,8 @@ static void deflect_timer_expire(ulong arg)
|
|||
int cf_command(int drvid, int mode,
|
||||
u_char proc, char *msn,
|
||||
u_char service, char *fwd_nr, ulong *procid)
|
||||
{ int retval,msnlen,flags;
|
||||
{ unsigned long flags;
|
||||
int retval,msnlen;
|
||||
int fwd_len;
|
||||
char *p,*ielenp,tmp[60];
|
||||
struct call_struc *cs;
|
||||
|
@ -203,7 +175,7 @@ int cf_command(int drvid, int mode,
|
|||
restore_flags(flags);
|
||||
*procid = cs->ics.parm.dss1_io.ll_id;
|
||||
|
||||
sprintf(cs->info,"%d 0x%lx %s%s 0 %s %0x %d%s%s\n",
|
||||
sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
|
||||
(!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
|
||||
cs->ics.parm.dss1_io.ll_id,
|
||||
(mode != 2) ? "" : "0 ",
|
||||
|
@ -236,7 +208,7 @@ int cf_command(int drvid, int mode,
|
|||
int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
|
||||
{ struct call_struc *cs;
|
||||
isdn_ctrl ic;
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */
|
||||
|
@ -306,8 +278,8 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
|
|||
/* insert a new rule before idx */
|
||||
/********************************/
|
||||
int insertrule(int idx, divert_rule *newrule)
|
||||
{ struct deflect_struc *ds,*ds1;
|
||||
int flags;
|
||||
{ struct deflect_struc *ds,*ds1=NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc),
|
||||
GFP_KERNEL)))
|
||||
|
@ -353,7 +325,7 @@ int insertrule(int idx, divert_rule *newrule)
|
|||
/***********************************/
|
||||
int deleterule(int idx)
|
||||
{ struct deflect_struc *ds,*ds1;
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
|
||||
if (idx < 0)
|
||||
{ save_flags(flags);
|
||||
|
@ -421,7 +393,7 @@ divert_rule *getruleptr(int idx)
|
|||
/*************************************************/
|
||||
int isdn_divert_icall(isdn_ctrl *ic)
|
||||
{ int retval = 0;
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
struct call_struc *cs = NULL;
|
||||
struct deflect_struc *dv;
|
||||
char *p,*p1;
|
||||
|
@ -483,6 +455,7 @@ int isdn_divert_icall(isdn_ctrl *ic)
|
|||
case DEFLECT_PROCEED:
|
||||
case DEFLECT_REPORT:
|
||||
case DEFLECT_REJECT:
|
||||
case NETWORK_DIAL:
|
||||
if (dv->rule.action == DEFLECT_PROCEED)
|
||||
if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
|
||||
return(0); /* no external deflection needed */
|
||||
|
@ -526,6 +499,11 @@ int isdn_divert_icall(isdn_ctrl *ic)
|
|||
else
|
||||
{ cs->deflect_dest[0] = '\0';
|
||||
retval = 4; /* only proceed */
|
||||
if (cs->akt_state == NETWORK_DIAL) {
|
||||
strcpy(cs->deflect_dest,dv->rule.to_nr);
|
||||
cs->timer.expires = jiffies + 10;
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
|
||||
cs->akt_state,
|
||||
|
@ -573,7 +551,7 @@ int isdn_divert_icall(isdn_ctrl *ic)
|
|||
|
||||
void deleteprocs(void)
|
||||
{ struct call_struc *cs, *cs1;
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
@ -730,7 +708,8 @@ int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
|
|||
/*********************************************/
|
||||
int prot_stat_callback(isdn_ctrl *ic)
|
||||
{ struct call_struc *cs, *cs1;
|
||||
int i,flags;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
cs = divert_head; /* start of list */
|
||||
cs1 = NULL;
|
||||
|
@ -833,7 +812,8 @@ int prot_stat_callback(isdn_ctrl *ic)
|
|||
/***************************/
|
||||
int isdn_divert_stat_callback(isdn_ctrl *ic)
|
||||
{ struct call_struc *cs, *cs1;
|
||||
int flags, retval;
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
retval = -1;
|
||||
cs = divert_head; /* start of list */
|
||||
|
|
|
@ -1,37 +1,14 @@
|
|||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* Header for the diversion supplementary ioctl interface.
|
||||
*
|
||||
* Copyright 1998 by Werner Cornelius (werner@ikt.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1999/08/22 20:26:37 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.2 1999/07/04 21:37:33 werner
|
||||
* Ported from kernel version 2.0
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
@ -59,9 +36,10 @@
|
|||
#define DEFLECT_PROCEED 2 /* deflect when externally triggered */
|
||||
#define DEFLECT_ALERT 3 /* alert and deflect after delay */
|
||||
#define DEFLECT_REJECT 4 /* reject immediately */
|
||||
#define DIVERT_ACTIVATE 5 /* diversion activate */
|
||||
#define DIVERT_DEACTIVATE 6 /* diversion deactivate */
|
||||
#define DIVERT_REPORT 7 /* interrogation result */
|
||||
#define NETWORK_DIAL 5 /* dial a network interface */
|
||||
#define DIVERT_ACTIVATE 16 /* diversion activate */
|
||||
#define DIVERT_DEACTIVATE 17 /* diversion deactivate */
|
||||
#define DIVERT_REPORT 18 /* interrogation result */
|
||||
#define DEFLECT_AUTODEL 255 /* only for internal use */
|
||||
|
||||
#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */
|
||||
|
@ -83,6 +61,7 @@ typedef struct
|
|||
2 = report call, send proceed, wait max waittime secs
|
||||
3 = report call, alert and deflect after waittime
|
||||
4 = report call, reject immediately
|
||||
5 = dial net interface specified in to_nr
|
||||
actions 1-2 only take place if interface is opened
|
||||
*/
|
||||
u_char waittime; /* maximum wait time for proceeding */
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#undef N_DATA
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "adapter.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#include <linux/isdn_compat.h>
|
||||
|
||||
MODULE_DESCRIPTION("ISDN4Linux: Driver for Eicon Diva Server cards");
|
||||
MODULE_AUTHOR("Armin Schindler");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef MODULE
|
||||
#include "idi.h"
|
||||
void DIVA_DIDD_Write(DESCRIPTOR *, int);
|
||||
EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
|
||||
EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Write);
|
||||
EXPORT_SYMBOL_NOVERS(DivasPrintf);
|
||||
#endif
|
||||
|
||||
int DivasCardsDiscover(void);
|
||||
|
||||
static int __init
|
||||
divas_init(void)
|
||||
{
|
||||
printk(KERN_DEBUG "DIVA Server Driver - initialising\n");
|
||||
|
||||
printk(KERN_DEBUG "DIVA Server Driver - Version 2.0.16\n");
|
||||
|
||||
#if !defined(CONFIG_PCI)
|
||||
printk(KERN_WARNING "CONFIG_PCI is not defined!\n");
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
if (pci_present())
|
||||
{
|
||||
if (DivasCardsDiscover() < 0)
|
||||
{
|
||||
printk(KERN_WARNING "Divas: Not loaded\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_WARNING "Divas: No PCI bus present\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
divas_exit(void)
|
||||
{
|
||||
card_t *pCard;
|
||||
word wCardIndex;
|
||||
extern int Divas_major;
|
||||
|
||||
printk(KERN_DEBUG "DIVA Server Driver - unloading\n");
|
||||
|
||||
pCard = DivasCards;
|
||||
for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
|
||||
{
|
||||
if ((pCard->hw) && (pCard->hw->in_use))
|
||||
{
|
||||
|
||||
(*pCard->card_reset)(pCard);
|
||||
|
||||
UxIsrRemove(pCard->hw, pCard);
|
||||
UxCardHandleFree(pCard->hw);
|
||||
|
||||
if(pCard->e_tbl != NULL)
|
||||
{
|
||||
kfree(pCard->e_tbl);
|
||||
}
|
||||
|
||||
|
||||
if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
|
||||
{
|
||||
release_region(pCard->hw->io_base,0x20);
|
||||
release_region(pCard->hw->reset_base,0x80);
|
||||
}
|
||||
|
||||
// If this is a 4BRI ...
|
||||
if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
|
||||
{
|
||||
// Skip over the next 3 virtual adapters
|
||||
wCardIndex += 3;
|
||||
|
||||
// But free their handles
|
||||
pCard++;
|
||||
UxCardHandleFree(pCard->hw);
|
||||
|
||||
if(pCard->e_tbl != NULL)
|
||||
{
|
||||
kfree(pCard->e_tbl);
|
||||
}
|
||||
|
||||
pCard++;
|
||||
UxCardHandleFree(pCard->hw);
|
||||
|
||||
if(pCard->e_tbl != NULL)
|
||||
{
|
||||
kfree(pCard->e_tbl);
|
||||
}
|
||||
|
||||
pCard++;
|
||||
UxCardHandleFree(pCard->hw);
|
||||
|
||||
if(pCard->e_tbl != NULL)
|
||||
{
|
||||
kfree(pCard->e_tbl);
|
||||
}
|
||||
}
|
||||
}
|
||||
pCard++;
|
||||
}
|
||||
|
||||
unregister_chrdev(Divas_major, "Divas");
|
||||
}
|
||||
|
||||
module_init(divas_init);
|
||||
module_exit(divas_exit);
|
||||
|
|
@ -1,13 +1,42 @@
|
|||
L_OBJS :=
|
||||
M_OBJS :=
|
||||
O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
|
||||
# Makefile for the eicon ISDN device driver
|
||||
|
||||
# The target object and module list name.
|
||||
|
||||
O_TARGET := vmlinux-obj.o
|
||||
|
||||
# Objects that export symbols.
|
||||
|
||||
export-objs := Divas_mod.o eicon_mod.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
list-multi := eicon.o divas.o
|
||||
eicon-objs := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o \
|
||||
eicon_io.o
|
||||
divas-objs := common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o \
|
||||
fourbri.o lincfg.o linchr.o linsys.o linio.o Divas_mod.o
|
||||
|
||||
# Optional parts of multipart objects.
|
||||
|
||||
eicon-objs-$(CONFIG_ISDN_DRV_EICON_PCI) += common.o idi.o bri.o pri.o log.o \
|
||||
xlog.o kprintf.o fpga.o fourbri.o lincfg.o linchr.o \
|
||||
linsys.o linio.o
|
||||
|
||||
eicon-objs += $(eicon-objs-y)
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_ISDN_DRV_EICON_OLD) += eicon.o
|
||||
obj-$(CONFIG_ISDN_DRV_EICON_DIVAS) += divas.o
|
||||
|
||||
include $(TOPDIR)/drivers/isdn/Rules.make
|
||||
|
||||
# Link rules for multi-part drivers.
|
||||
|
||||
eicon.o: $(eicon-objs)
|
||||
$(LD) -r -o $@ $(eicon-objs)
|
||||
|
||||
divas.o: $(divas-objs)
|
||||
$(LD) -r -o $@ $(divas-objs)
|
||||
|
||||
O_TARGET :=
|
||||
ifeq ($(CONFIG_ISDN_DRV_EICON),y)
|
||||
O_TARGET += eicon.o
|
||||
else
|
||||
O_TARGET += eicon.o
|
||||
M_OBJS = eicon.o
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Main internal include file for Diva Server driver
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.7
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(ADAPTER_H)
|
||||
#define ADAPTER_H
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "divas.h"
|
||||
#undef ID_MASK
|
||||
#include "pc.h"
|
||||
|
||||
#define XMOREC 0x1f
|
||||
#define XMOREF 0x20
|
||||
#define XBUSY 0x40
|
||||
#define RMORE 0x80
|
||||
|
||||
/* structure for all information we have to keep on a per */
|
||||
/* adapater basis */
|
||||
|
||||
typedef struct adapter_s ADAPTER;
|
||||
|
||||
struct adapter_s {
|
||||
void * io;
|
||||
|
||||
byte IdTable[256];
|
||||
byte ReadyInt;
|
||||
|
||||
byte (* ram_in)(ADAPTER * a, void * adr);
|
||||
word (* ram_inw)(ADAPTER * a, void * adr);
|
||||
void (* ram_in_buffer)(ADAPTER * a, void * adr, void * P, word length);
|
||||
void (* ram_look_ahead)(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
|
||||
|
||||
void (* ram_out)(ADAPTER * a, void * adr, byte data);
|
||||
void (* ram_outw)(ADAPTER * a, void * adr, word data);
|
||||
void (* ram_out_buffer)(ADAPTER * a, void * adr, void * P, word length);
|
||||
|
||||
void (* ram_inc)(ADAPTER * a, void * adr);
|
||||
};
|
||||
|
||||
typedef struct card card_t;
|
||||
|
||||
typedef int card_load_fn_t(card_t *card, dia_load_t *load);
|
||||
typedef int card_config_fn_t(card_t *card, dia_config_t *config);
|
||||
typedef int card_start_fn_t(card_t *card, byte *channels);
|
||||
typedef int card_reset_fn_t(card_t *card);
|
||||
typedef int card_mem_get_fn_t(card_t *card, mem_block_t *mem_block);
|
||||
|
||||
#define MAX_PENTITIES 256 /* Number of entities primary adapter */
|
||||
#define MAX_ENTITIES 16 /* Number of entities standard adapter */
|
||||
|
||||
typedef struct e_info_s E_INFO;
|
||||
|
||||
struct e_info_s
|
||||
{
|
||||
ENTITY *e; /* entity pointer */
|
||||
byte next; /* chaining index */
|
||||
word assign_ref; /* assign reference */
|
||||
};
|
||||
|
||||
/* DIVA card info (details hidden from user) */
|
||||
|
||||
typedef struct ux_diva_card_s ux_diva_card_t;
|
||||
|
||||
/* card info */
|
||||
|
||||
struct card
|
||||
{
|
||||
ADAPTER a; /* per-adapter information */
|
||||
dia_card_t cfg; /* card configuration */
|
||||
int state; /* State of the adapter */
|
||||
dword serial_no; /* serial number */
|
||||
int test_int_pend; /* set for interrupt testing */
|
||||
ux_diva_card_t *hw; /* O/S-specific handle */
|
||||
card_reset_fn_t *card_reset; /* call this to reset card */
|
||||
card_load_fn_t *card_load; /* call this to load card */
|
||||
card_config_fn_t *card_config; /* call this to config card */
|
||||
card_start_fn_t *card_start; /* call this to start card */
|
||||
card_mem_get_fn_t *card_mem_get; /* call this to get card memory */
|
||||
E_INFO *e_tbl; /* table of ENTITY pointers */
|
||||
byte e_head; /* list of active ENTITIES */
|
||||
byte e_tail; /* list of active ENTITIES */
|
||||
int e_count; /* # of active ENTITIES */
|
||||
int e_max; /* total # of ENTITIES */
|
||||
byte assign; /* assign queue entry */
|
||||
PBUFFER RBuffer; /* Copy of receive lookahead buffer */
|
||||
int log_types; /* bit-mask of active logs */
|
||||
word xlog_offset; /* offset to XLOG buffer on card */
|
||||
void (*out)(ADAPTER *a);
|
||||
byte (*dpc)(ADAPTER * a);
|
||||
byte (*test_int)(ADAPTER * a);
|
||||
void (*clear_int)(ADAPTER * a);
|
||||
void (*reset_int)(card_t *c);
|
||||
int is_live;
|
||||
|
||||
int (*card_isr)(card_t *card);
|
||||
|
||||
int int_pend; /* interrupt pending */
|
||||
long interrupt_reentered;
|
||||
long dpc_reentered;
|
||||
int set_xlog_request;
|
||||
|
||||
} ;
|
||||
|
||||
/* card information */
|
||||
|
||||
#define MAX_CARDS 20 /* max number of cards on a system */
|
||||
|
||||
extern
|
||||
card_t DivasCards[];
|
||||
|
||||
extern
|
||||
int DivasCardNext;
|
||||
|
||||
extern
|
||||
dia_config_t DivasCardConfigs[];
|
||||
|
||||
extern
|
||||
byte DivasFlavourConfig[];
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* public functions of IDI common code */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void DivasOut(ADAPTER * a);
|
||||
byte DivasDpc(ADAPTER * a);
|
||||
byte DivasTestInt(ADAPTER * a);
|
||||
void DivasClearInt(ADAPTER * a);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* public functions of configuration platform-specific code */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
int DivasConfigGet(dia_card_t *card);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* public functions of LOG related code */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void DivasXlogReq(int card_num);
|
||||
int DivasXlogRetrieve(card_t *card);
|
||||
void DivasLog(dia_log_t *log);
|
||||
void DivasLogIdi(card_t *card, ENTITY *e, int request);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* public functions to initialise cards for each type supported */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
int DivasPriInit(card_t *card, dia_card_t *cfg);
|
||||
|
||||
int DivasBriInit(card_t *card, dia_card_t *cfg);
|
||||
int Divas4BriInit(card_t *card, dia_card_t *cfg);
|
||||
void DivasBriPatch(card_t *card);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* public functions of log common code */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
extern char *DivasLogFifoRead(void);
|
||||
extern void DivasLogFifoWrite(char *entry, int length);
|
||||
extern int DivasLogFifoEmpty(void);
|
||||
extern int DivasLogFifoFull(void);
|
||||
extern void DivasLogAdd(void *buffer, int length);
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* public functions of misc. platform-specific code */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
int DivasDpcSchedule(void);
|
||||
void DivasDoDpc(void *);
|
||||
void DivasDoRequestDpc(void *pData);
|
||||
int DivasScheduleRequestDpc(void);
|
||||
|
||||
/* table of IDI request functions */
|
||||
|
||||
extern
|
||||
IDI_CALL DivasIdiRequest[];
|
||||
|
||||
/*
|
||||
* intialisation entry point
|
||||
*/
|
||||
|
||||
int DivasInit(void);
|
||||
|
||||
/*
|
||||
* Get information on the number and type of cards present
|
||||
*/
|
||||
|
||||
extern
|
||||
int DivasCardsDiscover(void);
|
||||
|
||||
/*
|
||||
* initialise a new card
|
||||
*/
|
||||
|
||||
int DivasCardNew(dia_card_t *card);
|
||||
|
||||
/*
|
||||
* configure specified card
|
||||
*/
|
||||
|
||||
int DivasCardConfig(dia_config_t *config);
|
||||
|
||||
/*
|
||||
* load specified binary code onto card
|
||||
*/
|
||||
|
||||
int DivasCardLoad(dia_load_t *load);
|
||||
|
||||
/*
|
||||
* start specified card running
|
||||
*/
|
||||
|
||||
int DivasCardStart(int card_id);
|
||||
|
||||
/*
|
||||
* ISR for card
|
||||
* Returns 0 if specified card was interrupting
|
||||
*/
|
||||
|
||||
int DivasIsr(void *arg);
|
||||
|
||||
/*
|
||||
* Get number of active cards
|
||||
*/
|
||||
|
||||
int DivasGetNum(void);
|
||||
|
||||
/*
|
||||
* Get list of active cards
|
||||
*/
|
||||
|
||||
int DivasGetList(dia_card_list_t *card_list);
|
||||
|
||||
/* definitions common to several card types */
|
||||
|
||||
#define DIVAS_SHARED_OFFSET (0x1000)
|
||||
|
||||
#endif /* ADAPTER_H */
|
|
@ -0,0 +1,697 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.8
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "eicon.h"
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "divas.h"
|
||||
#include "pc.h"
|
||||
#include "pr_pc.h"
|
||||
#include "dsp_defs.h"
|
||||
|
||||
#include "adapter.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#define PCI_BADDR0 0x10
|
||||
#define PCI_BADDR1 0x14
|
||||
#define PCI_BADDR2 0x18
|
||||
|
||||
#define DIVAS_SIGNATURE 0x4447
|
||||
|
||||
/* offset to start of MAINT area (used by xlog) */
|
||||
|
||||
#define DIVAS_MAINT_OFFSET 0xff00 /* value for BRI card */
|
||||
|
||||
#define PROTCAP_TELINDUS 0x1
|
||||
#define PROTCAP_V90D 0x8
|
||||
|
||||
word GetProtFeatureValue(char *sw_id);
|
||||
byte io_in(ADAPTER *a, void *adr);
|
||||
word io_inw(ADAPTER *a, void *adr);
|
||||
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length);
|
||||
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
|
||||
void io_out(ADAPTER *a, void *adr, byte data);
|
||||
void io_outw(ADAPTER *a, void *adr, word data);
|
||||
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length);
|
||||
void io_inc(ADAPTER *a, void *adr);
|
||||
|
||||
static int diva_server_bri_test_int(card_t *card);
|
||||
static int bri_ISR (card_t* card);
|
||||
|
||||
#define PLX_IOBASE 0
|
||||
#define DIVAS_IOBASE 1
|
||||
|
||||
#define REG_DATA 0x00
|
||||
#define REG_ADDRLO 0x04
|
||||
#define REG_ADDRHI 0x0C
|
||||
#define REG_IOCTRL 0x10
|
||||
|
||||
#define M_PCI_RESET 0x10
|
||||
|
||||
byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
|
||||
word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
|
||||
void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
|
||||
void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
|
||||
|
||||
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg);
|
||||
|
||||
static
|
||||
int diva_server_bri_reset(card_t *card)
|
||||
{
|
||||
byte *DivasIOBase;
|
||||
word i;
|
||||
dword dwWait;
|
||||
|
||||
UxCardLog(0);
|
||||
|
||||
DPRINTF(("divas: resetting BRI adapter"));
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0);
|
||||
|
||||
for (i=0; i < 50000; i++)
|
||||
;
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x0000);
|
||||
|
||||
for (i=0; i<0x8000; i++)
|
||||
{
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
|
||||
}
|
||||
|
||||
for (dwWait=0; dwWait < 0x00FFFFFF; dwWait++)
|
||||
;
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void diva_server_bri_reset_int(card_t *card)
|
||||
{
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
int diva_server_bri_start(card_t *card, byte *channels)
|
||||
{
|
||||
byte *DivasIOBase, *PLXIOBase;
|
||||
word wSig = 0;
|
||||
word i;
|
||||
dword dwSerialNum;
|
||||
byte bPLX9060 = FALSE;
|
||||
|
||||
DPRINTF(("divas: starting Diva Server BRI card"));
|
||||
|
||||
card->is_live = FALSE;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
|
||||
|
||||
/* wait for signature to indicate card has started */
|
||||
for (i = 0; i < 300; i++)
|
||||
{
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
|
||||
wSig = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
|
||||
|
||||
if (wSig == DIVAS_SIGNATURE)
|
||||
{
|
||||
DPRINTF(("divas: card started after %d ms", i * 10));
|
||||
break;
|
||||
}
|
||||
UxPause(10);
|
||||
}
|
||||
|
||||
if (wSig != DIVAS_SIGNATURE)
|
||||
{
|
||||
DPRINTF(("divas: card failed to start (Sig=0x%x)", wSig));
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
return -1;
|
||||
}
|
||||
|
||||
card->is_live = TRUE;
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x3F6);
|
||||
*channels = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
|
||||
|
||||
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) | UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
|
||||
|
||||
if (bPLX9060)
|
||||
{
|
||||
dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x1E) << 16) |
|
||||
(UxCardPortIoInW(card->hw, PLXIOBase, 0x22));
|
||||
DPRINTF(("divas: PLX9060 in use. Serial number 0x%04X", dwSerialNum));
|
||||
}
|
||||
else
|
||||
{
|
||||
dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x22) << 16) |
|
||||
(UxCardPortIoInW(card->hw, PLXIOBase, 0x26));
|
||||
DPRINTF(("divas: PLX9050 in use. Serial number 0x%04X", dwSerialNum));
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, PLXIOBase);
|
||||
|
||||
card->serial_no = dwSerialNum;
|
||||
|
||||
diva_server_bri_test_int(card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int diva_server_bri_load(card_t *card, dia_load_t *load)
|
||||
{
|
||||
byte *DivasIOBase;
|
||||
dword r3000_base;
|
||||
dword dwAddr, dwLength, i;
|
||||
word wTest, aWord;
|
||||
|
||||
DPRINTF(("divas: loading Diva Server BRI card"));
|
||||
|
||||
switch (load->code_type)
|
||||
{
|
||||
case DIA_CPU_CODE:
|
||||
DPRINTF(("divas: loading RISC %s", &load->code[0x80]));
|
||||
|
||||
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
|
||||
DPRINTF(("divas: features 0x%x", card->hw->features));
|
||||
if (card->hw->features == 0xFFFF)
|
||||
{
|
||||
DPRINTF(("divas: invalid feature string failed load\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
r3000_base = 0;
|
||||
break;
|
||||
|
||||
case DIA_DSP_CODE:
|
||||
DPRINTF(("divas: DSP code \"%s\"", load->code));
|
||||
|
||||
if ((card->hw->features) && (!(card->hw->features & PROTCAP_TELINDUS)))
|
||||
{
|
||||
DPRINTF(("divas: only Telindus style binaries supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
DPRINTF(("divas: V.90 DSP binary"));
|
||||
r3000_base = (0xBF790000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(("divas: non-V.90 DSP binary"));
|
||||
r3000_base = (0xBF7A0000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
|
||||
}
|
||||
DPRINTF(("divas: loading at 0x%x", r3000_base));
|
||||
break;
|
||||
|
||||
case DIA_TABLE_CODE:
|
||||
DPRINTF(("divas: TABLE code"));
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
r3000_base = 0xBF790000 + sizeof(dword);
|
||||
}
|
||||
else
|
||||
{
|
||||
r3000_base = 0xBF7A0000 + sizeof(dword);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DIA_DLOAD_CNT:
|
||||
DPRINTF(("divas: COUNT code"));
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
r3000_base = 0xBF790000;
|
||||
}
|
||||
else
|
||||
{
|
||||
r3000_base = 0xBF7A0000;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF(("divas: unknown code type %d", load->code_type));
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF(("divas: Writing %d bytes to adapter, address 0x%x", load->length, r3000_base));
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
DPRINTF(("divas: Attached to 0x%04X", DivasIOBase));
|
||||
|
||||
dwLength = load->length;
|
||||
|
||||
for (i=0; i < dwLength; i++)
|
||||
{
|
||||
dwAddr = r3000_base + i;
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, load->code[i]);
|
||||
}
|
||||
|
||||
DPRINTF(("divas: Verifying"));
|
||||
|
||||
for (i=0; i<dwLength; i++)
|
||||
{
|
||||
dwAddr = r3000_base + i;
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
|
||||
|
||||
wTest = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
|
||||
|
||||
aWord = load->code[i];
|
||||
|
||||
if (wTest != aWord)
|
||||
{
|
||||
DPRINTF(("divas: load verify failed on byte %d", i));
|
||||
DPRINTF(("divas: RAM 0x%x File 0x%x",wTest,aWord));
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(("divas: Loaded and verified. Detaching from adapter"));
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
UxCardLog(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int diva_server_bri_config(card_t *card, dia_config_t *config)
|
||||
{
|
||||
byte *DivasIOBase, i;
|
||||
|
||||
DPRINTF(("divas: configuring Diva Server BRI card"));
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 8);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->tei);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 9);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->nt2);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 10);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->sig_flags);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 11);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->watchdog);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 12);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->permanent);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 13);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 14);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->stable_l2);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 15);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->no_order_check);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 16);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 17);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 18);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->low_channel);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 19);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->prot_version);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 20);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->crc4);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 21);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
|
||||
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
DPRINTF(("divas: Signifying V.90"));
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
|
||||
}
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 23);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, card->serial_no & 0xFF);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 24);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 8) & 0xFF);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 25);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 16) & 0xFF);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 26);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 21);
|
||||
|
||||
for (i=0; i<32; i++)
|
||||
{
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 32+i);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].oad[i]);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 64+i);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].osa[i]);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 96+i);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].spid[i]);
|
||||
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 128+i);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].oad[i]);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 160+i);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].osa[i]);
|
||||
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 192+i);
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].spid[i]);
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DivasBriPatch(card_t *card)
|
||||
{
|
||||
dword PLXIOBase = 0;
|
||||
dword DivasIOBase = 0;
|
||||
|
||||
PLXIOBase = card->cfg.reset_base;
|
||||
DivasIOBase = card->cfg.io_base;
|
||||
|
||||
if(card->hw == NULL)
|
||||
{
|
||||
DPRINTF(("Divas: BRI PATCH (PLX chip) card->hw is null"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (PLXIOBase == 0)
|
||||
{
|
||||
DPRINTF(("Divas: BRI (PLX chip) cannot be patched. The BRI adapter may"));
|
||||
DPRINTF(("Divas: not function properly. If you do encounter problems,"));
|
||||
DPRINTF(("Divas: ensure that your machine is using the latest BIOS."));
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
|
||||
DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
|
||||
|
||||
if (PLXIOBase & 0x80)
|
||||
{
|
||||
dword dwSize, dwSerialNum, dwCmd;
|
||||
boolean_t bPLX9060;
|
||||
word wSerHi, wSerLo;
|
||||
|
||||
DPRINTF(("Divas: Patch required"));
|
||||
dwCmd = 0;
|
||||
UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
|
||||
|
||||
PLXIOBase &= ~0x80;
|
||||
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &PLXIOBase);
|
||||
|
||||
dwSize = 0xFFFFFFFF;
|
||||
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &dwSize);
|
||||
UxPciConfigRead(card->hw, 4, PCI_BADDR1, &dwSize);
|
||||
|
||||
dwSize = (~ (dwSize & ~7)) + 1;
|
||||
|
||||
DivasIOBase = PLXIOBase + dwSize;
|
||||
|
||||
card->cfg.reset_base = PLXIOBase;
|
||||
card->cfg.io_base = DivasIOBase;
|
||||
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &card->cfg.reset_base);
|
||||
UxPciConfigWrite(card->hw, 4, PCI_BADDR2, &card->cfg.io_base);
|
||||
|
||||
dwCmd = 5;
|
||||
UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
|
||||
|
||||
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) |
|
||||
UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
|
||||
|
||||
if (bPLX9060)
|
||||
{
|
||||
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
|
||||
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
|
||||
dwSerialNum = (wSerHi << 16) | wSerLo;
|
||||
UxCardLog(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
|
||||
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
|
||||
dwSerialNum = (wSerHi << 16) | wSerLo;
|
||||
UxCardLog(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
word wSerHi, wSerLo;
|
||||
boolean_t bPLX9060;
|
||||
dword dwSerialNum;
|
||||
|
||||
DPRINTF(("divas: No patch required"));
|
||||
|
||||
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) |
|
||||
UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
|
||||
|
||||
if (bPLX9060)
|
||||
{
|
||||
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
|
||||
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
|
||||
dwSerialNum = (wSerHi << 16) | wSerLo;
|
||||
}
|
||||
else
|
||||
{
|
||||
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
|
||||
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
|
||||
dwSerialNum = (wSerHi << 16) | wSerLo;
|
||||
}
|
||||
}
|
||||
DPRINTF(("Divas: After patching:"));
|
||||
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
|
||||
DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
|
||||
|
||||
}
|
||||
|
||||
#define TEST_INT_DIVAS_BRI 0x12
|
||||
static
|
||||
int diva_server_bri_test_int(card_t *card)
|
||||
{
|
||||
boolean_t bPLX9060 = FALSE;
|
||||
byte *PLXIOBase = NULL, *DivasIOBase = NULL;
|
||||
|
||||
DPRINTF(("divas: test interrupt for Diva Server BRI card"));
|
||||
|
||||
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
|
||||
|
||||
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) || UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
|
||||
|
||||
if (bPLX9060)
|
||||
{ /* PLX9060 */
|
||||
UxCardPortIoOut(card->hw, PLXIOBase, 0x69, 0x09);
|
||||
}
|
||||
else
|
||||
{ /* PLX9050 */
|
||||
UxCardPortIoOut(card->hw, PLXIOBase, 0x4C, 0x41);
|
||||
}
|
||||
|
||||
card->test_int_pend = TEST_INT_DIVAS_BRI;
|
||||
|
||||
UxCardMemDetach(card->hw, PLXIOBase);
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x89);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int diva_server_bri_mem_get(card_t *card, mem_block_t *mem_block)
|
||||
{
|
||||
dword user_addr = mem_block->addr;
|
||||
word length = 0;
|
||||
dword addr;
|
||||
word i;
|
||||
byte *DivasIOBase;
|
||||
|
||||
DPRINTF(("divas: Retrieving memory from 0x%x", user_addr));
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
addr = user_addr;
|
||||
|
||||
for (i=0; i < (16 * 8); i++)
|
||||
{
|
||||
addr = user_addr + i;
|
||||
|
||||
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, addr >> 16);
|
||||
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, (word) addr);
|
||||
|
||||
mem_block->data[i] = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
|
||||
length++;
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int DivasBriInit(card_t *card, dia_card_t *cfg)
|
||||
{
|
||||
DPRINTF(("divas: initialise Diva Server BRI card"));
|
||||
|
||||
if (DivasBRIInitPCI(card, cfg) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
card->card_reset = diva_server_bri_reset;
|
||||
card->card_start = diva_server_bri_start;
|
||||
card->card_load = diva_server_bri_load;
|
||||
card->card_config = diva_server_bri_config;
|
||||
card->reset_int = diva_server_bri_reset_int;
|
||||
card->card_mem_get = diva_server_bri_mem_get;
|
||||
|
||||
card->xlog_offset = DIVAS_MAINT_OFFSET;
|
||||
|
||||
card->out = DivasOut;
|
||||
card->test_int = DivasTestInt;
|
||||
card->dpc = DivasDpc;
|
||||
card->clear_int = DivasClearInt;
|
||||
card->card_isr = bri_ISR;
|
||||
|
||||
card->a.ram_out = io_out;
|
||||
card->a.ram_outw = io_outw;
|
||||
card->a.ram_out_buffer = io_out_buffer;
|
||||
card->a.ram_inc = io_inc;
|
||||
|
||||
card->a.ram_in = io_in;
|
||||
card->a.ram_inw = io_inw;
|
||||
card->a.ram_in_buffer = io_in_buffer;
|
||||
card->a.ram_look_ahead = io_look_ahead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
word GetProtFeatureValue(char *sw_id)
|
||||
{
|
||||
word features = 0;
|
||||
|
||||
while ((*sw_id) && (sw_id[0] != '['))
|
||||
sw_id++;
|
||||
|
||||
if (sw_id == NULL)
|
||||
{
|
||||
DPRINTF(("divas: no feature string present"));
|
||||
features = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte i, shifter;
|
||||
|
||||
sw_id += 3;
|
||||
|
||||
for (i=0, shifter=12; i<4; i++, shifter-=4)
|
||||
{
|
||||
if ((sw_id[i] >= '0') && (sw_id[i] <= '9'))
|
||||
{
|
||||
features |= (sw_id[i] - '0') << shifter;
|
||||
}
|
||||
else if ((sw_id[i] >= 'a') && (sw_id[i] <= 'f'))
|
||||
{
|
||||
features |= (sw_id[i] - 'a' + 10) << shifter;
|
||||
}
|
||||
else if ((sw_id[i] >= 'A') && (sw_id[i] <= 'F'))
|
||||
{
|
||||
features |= (sw_id[i] - 'A' + 10) << shifter;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(("divas: invalid feature string"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
|
||||
int bri_ISR (card_t* card)
|
||||
{
|
||||
int served = 0;
|
||||
byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01)
|
||||
{
|
||||
served = 1;
|
||||
card->int_pend += 1;
|
||||
DivasDpcSchedule(); /* ISR DPC */
|
||||
UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return (served != 0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,870 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.15
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "eicon.h"
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "constant.h"
|
||||
#include "divas.h"
|
||||
#include "pc.h"
|
||||
#include "pr_pc.h"
|
||||
|
||||
#include "uxio.h"
|
||||
|
||||
#define DIVAS_LOAD_CMD 0x02
|
||||
#define DIVAS_START_CMD 0x03
|
||||
#define DIVAS_IRQ_RESET 0xC18
|
||||
#define DIVAS_IRQ_RESET_VAL 0xFE
|
||||
|
||||
#define TEST_INT_DIVAS 0x11
|
||||
#define TEST_INT_DIVAS_BRI 0x12
|
||||
#define TEST_INT_DIVAS_Q 0x13
|
||||
|
||||
#define DIVAS_RESET 0x81
|
||||
#define DIVAS_LED1 0x04
|
||||
#define DIVAS_LED2 0x08
|
||||
#define DIVAS_LED3 0x20
|
||||
#define DIVAS_LED4 0x40
|
||||
|
||||
#define DIVAS_SIGNATURE 0x4447
|
||||
|
||||
#define MP_PROTOCOL_ADDR 0xA0011000
|
||||
|
||||
#define PLX_IOBASE 0
|
||||
#define DIVAS_IOBASE 1
|
||||
|
||||
typedef struct {
|
||||
dword cmd;
|
||||
dword addr;
|
||||
dword len;
|
||||
dword err;
|
||||
dword live;
|
||||
dword reserved[(0x1020>>2)-6];
|
||||
dword signature;
|
||||
byte data[1];
|
||||
} diva_server_boot_t;
|
||||
|
||||
int DivasCardNext;
|
||||
card_t DivasCards[MAX_CARDS];
|
||||
|
||||
dia_config_t *DivasConfig(card_t *, dia_config_t *);
|
||||
|
||||
static
|
||||
DESCRIPTOR DIDD_Table[32];
|
||||
|
||||
void DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength )
|
||||
{
|
||||
memset(table, 0, tablelength);
|
||||
|
||||
if (tablelength > sizeof(DIDD_Table))
|
||||
tablelength = sizeof(DIDD_Table);
|
||||
|
||||
if(tablelength % sizeof(DESCRIPTOR)) {
|
||||
tablelength /= sizeof(DESCRIPTOR);
|
||||
tablelength *= sizeof(DESCRIPTOR);
|
||||
}
|
||||
|
||||
if (tablelength > 0)
|
||||
memcpy((void *)table, (void *)DIDD_Table, tablelength);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength)
|
||||
{
|
||||
if (tablelength > sizeof(DIDD_Table))
|
||||
tablelength = sizeof(DIDD_Table);
|
||||
|
||||
memcpy((void *)DIDD_Table, (void *)table, tablelength);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void init_idi_tab(void)
|
||||
{
|
||||
DESCRIPTOR d[32];
|
||||
|
||||
memset(d, 0, sizeof(d));
|
||||
|
||||
d[0].type = IDI_DIMAINT; /* identify the DIMAINT entry */
|
||||
d[0].channels = 0; /* zero channels associated with dimaint*/
|
||||
d[0].features = 0; /* no features associated with dimaint */
|
||||
d[0].request = (IDI_CALL) DivasPrintf;
|
||||
|
||||
DIVA_DIDD_Write(d, sizeof(d));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O routines for memory mapped cards
|
||||
*/
|
||||
|
||||
byte mem_in(ADAPTER *a, void *adr)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
byte value;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
value = UxCardMemIn(card->hw, m);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
word mem_inw(ADAPTER *a, void *adr)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
word value;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
value = UxCardMemInW(card->hw, m);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
UxCardMemInBuffer(card->hw, m, P, length);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (dword) &RBuffer->length;
|
||||
card->RBuffer.length = UxCardMemInW(card->hw, m);
|
||||
|
||||
m = b;
|
||||
m += (dword) &RBuffer->P;
|
||||
UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
|
||||
|
||||
e->RBuffer = (DBUFFER *) &card->RBuffer;
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mem_out(ADAPTER *a, void *adr, byte data)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
UxCardMemOut(card->hw, m, data);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mem_outw(ADAPTER *a, void *adr, word data)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
UxCardMemOutW(card->hw, m, data);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
UxCardMemOutBuffer(card->hw, m, P, length);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mem_inc(ADAPTER *a, void *adr)
|
||||
{
|
||||
word value;
|
||||
card_t *card = a->io;
|
||||
unsigned char *b, *m;
|
||||
|
||||
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
m += (unsigned int) adr;
|
||||
|
||||
value = UxCardMemInW(card->hw, m);
|
||||
value++;
|
||||
UxCardMemOutW(card->hw, m, value);
|
||||
|
||||
UxCardMemDetach(card->hw, b);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O routines for I/O mapped cards
|
||||
*/
|
||||
|
||||
byte io_in(ADAPTER *a, void *adr)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
byte value;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
value = UxCardIoIn(card->hw, DivasIOBase, adr);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
word io_inw(ADAPTER *a, void *adr)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
word value;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
value = UxCardIoInW(card->hw, DivasIOBase, adr);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
|
||||
|
||||
UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
e->RBuffer = (DBUFFER *) &card->RBuffer;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void io_out(ADAPTER *a, void *adr, byte data)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardIoOut(card->hw, DivasIOBase, adr, data);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void io_outw(ADAPTER *a, void *adr, word data)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardIoOutW(card->hw, DivasIOBase, adr, data);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
byte *DivasIOBase = NULL;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void io_inc(ADAPTER *a, void *adr)
|
||||
{
|
||||
word value;
|
||||
card_t *card = a->io;
|
||||
byte *DivasIOBase;
|
||||
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
value = UxCardIoInW(card->hw, DivasIOBase, adr);
|
||||
|
||||
value++;
|
||||
|
||||
UxCardIoOutW(card->hw, DivasIOBase, adr, value);
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void test_int(card_t *card)
|
||||
|
||||
{
|
||||
byte *shared, *DivasIOBase;
|
||||
|
||||
switch (card->test_int_pend)
|
||||
{
|
||||
case TEST_INT_DIVAS:
|
||||
DPRINTF(("divas: test interrupt pending"));
|
||||
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
if (UxCardMemIn(card->hw, &shared[0x3FE]))
|
||||
{
|
||||
UxCardMemOut(card->hw,
|
||||
&(((struct pr_ram *)shared)->RcOutput), 0);
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
(*card->reset_int)(card);
|
||||
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
UxCardMemOut(card->hw, &shared[0x3FE], 0);
|
||||
DPRINTF(("divas: test interrupt cleared"));
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
|
||||
card->test_int_pend = 0;
|
||||
break;
|
||||
|
||||
case TEST_INT_DIVAS_BRI:
|
||||
DPRINTF(("divas: BRI test interrupt pending"));
|
||||
(*card->reset_int)(card);
|
||||
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
DPRINTF(("divas: test interrupt cleared"));
|
||||
card->test_int_pend = 0;
|
||||
break;
|
||||
|
||||
case TEST_INT_DIVAS_Q:
|
||||
DPRINTF(("divas: 4BRI test interrupt pending"));
|
||||
(*card->reset_int)(card);
|
||||
card->test_int_pend = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF(("divas: unknown test interrupt pending"));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void card_isr (void *dev_id)
|
||||
{
|
||||
card_t *card = (card_t *) dev_id;
|
||||
ADAPTER *a = &card->a;
|
||||
int ipl;
|
||||
|
||||
if (card->test_int_pend)
|
||||
{
|
||||
ipl = UxCardLock(card->hw);
|
||||
card->int_pend=0;
|
||||
test_int(card);
|
||||
UxCardUnlock(card->hw,ipl);
|
||||
return;
|
||||
}
|
||||
|
||||
if(card->card_isr)
|
||||
{
|
||||
(*(card->card_isr))(card);
|
||||
}
|
||||
else
|
||||
{
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
if ((card->test_int)(a))
|
||||
{
|
||||
(card->reset_int)(card);
|
||||
}
|
||||
|
||||
UxCardUnlock(card->hw,ipl);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int DivasCardNew(dia_card_t *card_info)
|
||||
{
|
||||
card_t *card;
|
||||
static boolean_t first_call = TRUE;
|
||||
boolean_t NeedISRandReset = FALSE;
|
||||
|
||||
DPRINTF(("divas: new card "));
|
||||
|
||||
if (first_call)
|
||||
{
|
||||
first_call = FALSE;
|
||||
init_idi_tab();
|
||||
}
|
||||
|
||||
DivasConfigGet(card_info);
|
||||
|
||||
if (DivasCardNext == DIM(DivasCards))
|
||||
{
|
||||
KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
card = &DivasCards[DivasCardNext];
|
||||
|
||||
card->state = DIA_UNKNOWN;
|
||||
|
||||
card->cfg = *card_info;
|
||||
|
||||
card->a.io = card;
|
||||
|
||||
if (UxCardHandleGet(&card->hw, card_info))
|
||||
{
|
||||
KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
|
||||
{
|
||||
DivasBriPatch(card);
|
||||
card_info->io_base = card->cfg.io_base;
|
||||
}
|
||||
|
||||
switch (card_info->card_type)
|
||||
{
|
||||
case DIA_CARD_TYPE_DIVA_SERVER:
|
||||
if (DivasPriInit(card, card_info))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
NeedISRandReset = TRUE;
|
||||
break;
|
||||
|
||||
case DIA_CARD_TYPE_DIVA_SERVER_B:
|
||||
if (DivasBriInit(card, card_info))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
NeedISRandReset = TRUE;
|
||||
break;
|
||||
|
||||
case DIA_CARD_TYPE_DIVA_SERVER_Q:
|
||||
if (Divas4BriInit(card, card_info))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (card_info->name[6] == '0')
|
||||
{
|
||||
NeedISRandReset = TRUE;
|
||||
}
|
||||
else // Need to set paramater for ISR anyway
|
||||
{
|
||||
card->hw->user_isr_arg = card;
|
||||
card->hw->user_isr = card_isr;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NeedISRandReset)
|
||||
{
|
||||
if (UxIsrInstall(card->hw, card_isr, card))
|
||||
{
|
||||
KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
|
||||
UxCardHandleFree(card->hw);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
|
||||
{
|
||||
if ((*card->card_reset)(card))
|
||||
{
|
||||
KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
|
||||
return -1;
|
||||
}
|
||||
card->state = DIA_RESET;
|
||||
}
|
||||
|
||||
NeedISRandReset = FALSE;
|
||||
}
|
||||
|
||||
DivasCardNext++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *get_card(int card_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < DivasCardNext; i++)
|
||||
{
|
||||
if (DivasCards[i].cfg.card_id == card_id)
|
||||
{
|
||||
return(&DivasCards[i]);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int DivasCardConfig(dia_config_t *config)
|
||||
{
|
||||
card_t *card;
|
||||
int status;
|
||||
|
||||
DPRINTF(("divas: configuring card"));
|
||||
|
||||
card = get_card(config->card_id);
|
||||
if (!card)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
config = DivasConfig(card, config);
|
||||
|
||||
status = (*card->card_config)(card, config);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
card->state = DIA_CONFIGURED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int DivasCardLoad(dia_load_t *load)
|
||||
{
|
||||
card_t *card;
|
||||
int status;
|
||||
|
||||
card = get_card(load->card_id);
|
||||
if (!card)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (card->state == DIA_RUNNING)
|
||||
{
|
||||
(*card->card_reset)(card);
|
||||
}
|
||||
|
||||
status = (*card->card_load)(card, load);
|
||||
if (!status)
|
||||
{
|
||||
card->state = DIA_LOADED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int idi_register(card_t *card, byte channels)
|
||||
{
|
||||
DESCRIPTOR d[32];
|
||||
int length, num_entities;
|
||||
|
||||
DPRINTF(("divas: registering card with IDI"));
|
||||
|
||||
num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
|
||||
card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
|
||||
|
||||
if (!card->e_tbl)
|
||||
{
|
||||
KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities);
|
||||
card->e_max = num_entities;
|
||||
|
||||
DIVA_DIDD_Read(d, sizeof(d));
|
||||
|
||||
for(length=0; length < DIM(d); length++)
|
||||
if (d[length].type == 0) break;
|
||||
|
||||
if (length >= DIM(d))
|
||||
{
|
||||
KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (card->cfg.card_type)
|
||||
{
|
||||
case DIA_CARD_TYPE_DIVA_SERVER:
|
||||
d[length].type = IDI_ADAPTER_PR;
|
||||
/* d[length].serial = card->serial_no; */
|
||||
break;
|
||||
|
||||
case DIA_CARD_TYPE_DIVA_SERVER_B:
|
||||
d[length].type = IDI_ADAPTER_MAESTRA;
|
||||
/* d[length].serial = card->serial_no; */
|
||||
break;
|
||||
|
||||
// 4BRI is treated as 4 BRI adapters
|
||||
case DIA_CARD_TYPE_DIVA_SERVER_Q:
|
||||
d[length].type = IDI_ADAPTER_MAESTRA;
|
||||
/* d[length].serial = card->cfg.serial; */
|
||||
}
|
||||
|
||||
d[length].features = 0;
|
||||
d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
|
||||
|
||||
if ( card->hw->features & PROTCAP_MANIF )
|
||||
{
|
||||
d[length].features |= DI_MANAGE ;
|
||||
}
|
||||
if ( card->hw->features & PROTCAP_V_42 )
|
||||
{
|
||||
d[length].features |= DI_V_42 ;
|
||||
}
|
||||
if ( card->hw->features & PROTCAP_EXTD_FAX )
|
||||
{
|
||||
d[length].features |= DI_EXTD_FAX ;
|
||||
}
|
||||
|
||||
d[length].channels = channels;
|
||||
d[length].request = DivasIdiRequest[card - DivasCards];
|
||||
|
||||
length++;
|
||||
|
||||
DIVA_DIDD_Write(d, sizeof(d));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DivasCardStart(int card_id)
|
||||
{
|
||||
card_t *card;
|
||||
byte channels;
|
||||
int status;
|
||||
|
||||
DPRINTF(("divas: starting card"));
|
||||
|
||||
card = get_card(card_id);
|
||||
if (!card)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = (*card->card_start)(card, &channels);
|
||||
if (status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
|
||||
if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
|
||||
{
|
||||
int i;
|
||||
card_t *FourBRISlave;
|
||||
|
||||
for (i=3; i >= 0; i--)
|
||||
{
|
||||
FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
|
||||
if (FourBRISlave)
|
||||
{
|
||||
idi_register(FourBRISlave, 2);
|
||||
FourBRISlave->state = DIA_RUNNING;
|
||||
}
|
||||
}
|
||||
card->serial_no = card->cfg.serial;
|
||||
|
||||
DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels",
|
||||
card_id - 3, card->serial_no, (int) channels));
|
||||
}
|
||||
else
|
||||
{
|
||||
status = idi_register(card, channels);
|
||||
if (!status)
|
||||
{
|
||||
card->state = DIA_RUNNING;
|
||||
DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels",
|
||||
card_id, card->serial_no, (int) channels));
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int DivasGetMem(mem_block_t *mem_block)
|
||||
{
|
||||
card_t *card;
|
||||
word card_id = mem_block->card_id;
|
||||
|
||||
card = get_card(card_id);
|
||||
if (!card)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (*card->card_mem_get)(card, mem_block);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deleyed Procedure Call for handling interrupts from card
|
||||
*/
|
||||
|
||||
void DivaDoCardDpc(card_t *card)
|
||||
{
|
||||
ADAPTER *a;
|
||||
|
||||
a = &card->a;
|
||||
|
||||
if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
do{
|
||||
if((*(card->test_int))(a))
|
||||
{
|
||||
(*(card->dpc))(a);
|
||||
(*(card->clear_int))(a);
|
||||
}
|
||||
(*(card->out))(a);
|
||||
}while(UxInterlockedDecrement(card->hw, &card->dpc_reentered));
|
||||
|
||||
}
|
||||
|
||||
void DivasDoDpc(void *pData)
|
||||
{
|
||||
card_t *card = DivasCards;
|
||||
int i = DivasCardNext;
|
||||
|
||||
while(i--)
|
||||
{
|
||||
DivaDoCardDpc(card++);
|
||||
}
|
||||
}
|
||||
|
||||
void DivasDoRequestDpc(void *pData)
|
||||
{
|
||||
DivasDoDpc(pData);
|
||||
}
|
||||
|
||||
/*
|
||||
* DivasGetNum
|
||||
* Returns the number of active adapters
|
||||
*/
|
||||
|
||||
int DivasGetNum(void)
|
||||
{
|
||||
return(DivasCardNext);
|
||||
}
|
||||
|
||||
/*
|
||||
* DivasGetList
|
||||
* Returns a list of active adapters
|
||||
*/
|
||||
int DivasGetList(dia_card_list_t *card_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(card_list, 0, sizeof(dia_card_list_t));
|
||||
|
||||
for(i = 0; i < DivasCardNext; i++)
|
||||
{
|
||||
card_list->card_type = DivasCards[i].cfg.card_type;
|
||||
card_list->card_slot = DivasCards[i].cfg.slot;
|
||||
card_list->state = DivasCards[i].state;
|
||||
card_list++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* control logging for specified card
|
||||
*/
|
||||
|
||||
void DivasLog(dia_log_t *log)
|
||||
{
|
||||
card_t *card;
|
||||
|
||||
card = get_card(log->card_id);
|
||||
if (!card)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
card->log_types = log->log_types;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Q.931 information elements maximum length */
|
||||
/* excluding the identifier, including the length field */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define MAX_LEN_BC 13
|
||||
#define MAX_LEN_LLC 19 /* ctr3 */
|
||||
#define MAX_LEN_HLC 6 /* ctr3 */
|
||||
#define MAX_LEN_UUI 200 /* Hicom USBS req */
|
||||
#define MAX_LEN_NUM 24
|
||||
#define MAX_LEN_DSP 83 /* ctr3 */
|
||||
#define MAX_LEN_NI 4
|
||||
#define MAX_LEN_PI 5
|
||||
#define MAX_LEN_SIN 3
|
||||
#define MAX_LEN_CST 4
|
||||
#define MAX_LEN_SIG 2
|
||||
#define MAX_LEN_SPID 32
|
||||
#define MAX_LEN_EID 3
|
||||
#define MAX_LEN_CHI 35 /* ctr3 */
|
||||
#define MAX_LEN_CAU 33
|
||||
#define MAX_LEN_FTY 130
|
||||
#define MAX_LEN_KEY 83 /* ctr3 */
|
||||
#define MAX_LEN_RSI 4
|
||||
#define MAX_LEN_CAI 11
|
||||
#define MAX_NUM_SPID 4
|
||||
#define MAX_LEN_USERID 9
|
||||
#define MAX_LEN_APPLID 5
|
||||
#define MAX_LEN_NTTCIF 15
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* decision return values */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* w element coding */
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
#define NTTCIF 0x01
|
||||
#define BC 0x04
|
||||
#define CAU 0x08
|
||||
#define CAD 0x0c
|
||||
#define CAI 0x10
|
||||
#define CST 0x14
|
||||
#define CHI 0x18
|
||||
#define LLI 0x19
|
||||
#define CHA 0x1a
|
||||
#define FTY 0x1c
|
||||
#define PI 0x1e
|
||||
#define NFAC 0x20
|
||||
#define TC 0x24
|
||||
#define ATT_EID 0x26
|
||||
#define NI 0x27
|
||||
#define DSP 0x28
|
||||
#define DT 0x29
|
||||
#define KEY 0x2c
|
||||
#define KP 0x2c
|
||||
#define UID 0x2d
|
||||
#define SIG 0x34
|
||||
#define FI 0x39
|
||||
#define SPID 0x3a
|
||||
#define EID 0x3b
|
||||
#define DSPF 0x3c
|
||||
#define ECAD 0x4c
|
||||
#define OAD 0x6c
|
||||
#define OSA 0x6d
|
||||
#define DAD 0x70
|
||||
#define CPN 0x70
|
||||
#define DSA 0x71
|
||||
#define RDX 0x73
|
||||
#define RAD 0x74
|
||||
#define RDN 0x74
|
||||
#define RSI 0x79
|
||||
#define SCR 0x7A /* internal unscreened CPN */
|
||||
#define MIE 0x7a /* internal management info element */
|
||||
#define LLC 0x7c
|
||||
#define HLC 0x7d
|
||||
#define UUI 0x7e
|
||||
#define ESC 0x7f
|
||||
|
||||
#define SHIFT 0x90
|
||||
#define MORE 0xa0
|
||||
#define CL 0xb0
|
||||
|
||||
/* information elements used on the spid interface */
|
||||
#define SPID_CMD 0xc0
|
||||
#define SPID_LINK 0x10
|
||||
#define SPID_DN 0x70
|
||||
#define SPID_BC 0x04
|
||||
#define SPID_SWITCH 0x11
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* global configuration parameters, defined in exec.c */
|
||||
/* these parameters are configured with program loading */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define PROT_1TR6 0
|
||||
#define PROT_ETSI 1
|
||||
#define PROT_FRANC 2
|
||||
#define PROT_BELG 3
|
||||
#define PROT_SWED 4
|
||||
#define PROT_NI 5
|
||||
#define PROT_5ESS 6
|
||||
#define PROT_JAPAN 7
|
||||
#define PROT_ATEL 8
|
||||
#define PROT_US 9
|
||||
#define PROT_ITALY 10
|
||||
#define PROT_TWAN 11
|
||||
#define PROT_AUSTRAL 12
|
||||
|
||||
#define INIT_PROT_1TR6 0x80|PROT_1TR6
|
||||
#define INIT_PROT_ETSI 0x80|PROT_ETSI
|
||||
#define INIT_PROT_FRANC 0x80|PROT_FRANC
|
||||
#define INIT_PROT_BELG 0x80|PROT_BELG
|
||||
#define INIT_PROT_SWED 0x80|PROT_SWED
|
||||
#define INIT_PROT_NI 0x80|PROT_NI
|
||||
#define INIT_PROT_5ESS 0x80|PROT_5ESS
|
||||
#define INIT_PROT_JAPAN 0x80|PROT_JAPAN
|
||||
#define INIT_PROT_ATEL 0x80|PROT_ATEL
|
||||
#define INIT_PROT_ITALY 0x80|PROT_ITALY
|
||||
#define INIT_PROT_TWAN 0x80|PROT_TWAN
|
||||
#define INIT_PROT_AUSTRAL 0x80|PROT_AUSTRAL
|
||||
|
||||
|
||||
/* -----------------------------------------------------------**
|
||||
** The PROTOCOL_FEATURE_STRING in feature.h (included **
|
||||
** in prstart.sx and astart.sx) defines capabilities and **
|
||||
** features of the actual protocol code. It's used as a bit **
|
||||
** mask. **
|
||||
** The following Bits are defined: **
|
||||
** -----------------------------------------------------------*/
|
||||
|
||||
#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
|
||||
#define PROTCAP_MANIF 0x0002 /* Management interface implemented */
|
||||
#define PROTCAP_V_42 0x0004 /* V42 implemented */
|
||||
#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
|
||||
#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
|
||||
#define PROTCAP_FREE4 0x0020 /* not used */
|
||||
#define PROTCAP_FREE5 0x0040 /* not used */
|
||||
#define PROTCAP_FREE6 0x0080 /* not used */
|
||||
#define PROTCAP_FREE7 0x0100 /* not used */
|
||||
#define PROTCAP_FREE8 0x0200 /* not used */
|
||||
#define PROTCAP_FREE9 0x0400 /* not used */
|
||||
#define PROTCAP_FREE10 0x0800 /* not used */
|
||||
#define PROTCAP_FREE11 0x1000 /* not used */
|
||||
#define PROTCAP_FREE12 0x2000 /* not used */
|
||||
#define PROTCAP_FREE13 0x4000 /* not used */
|
||||
#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Include file for defining the kernel loggger messages
|
||||
* These definitions are shared between the klog driver and the
|
||||
* klogd daemon process
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(_KLOGMSG_H)
|
||||
#define _KLOGMSG_H
|
||||
|
||||
/* define a type for a log entry */
|
||||
|
||||
#define KLOG_TEXT_MSG (0)
|
||||
#define KLOG_XLOG_MSG (1)
|
||||
#define KLOG_XTXT_MSG (2)
|
||||
#define KLOG_IDI_REQ (4)
|
||||
#define KLOG_IDI_CALLBACK (5)
|
||||
#define KLOG_CAPI_MSG (6)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long time_stamp; /* in ms since last system boot */
|
||||
int card; /* card number (-1 for all) */
|
||||
unsigned int type; /* type of log message (0 is text) */
|
||||
unsigned int length; /* message length (non-text messages only) */
|
||||
unsigned short code; /* message code (non-text messages only) */
|
||||
char buffer[110];/* text/data to log */
|
||||
} klog_t;
|
||||
|
||||
void DivasLogAdd(void *buffer, int length);
|
||||
#endif /* of _KLOGMSG_H */
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* External Diva Server driver include file
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.5
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(DIVAS_H)
|
||||
#define DIVAS_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
/* IOCTL commands */
|
||||
|
||||
#define DIA_IOCTL_INIT (0)
|
||||
#define DIA_IOCTL_LOAD (1)
|
||||
#define DIA_IOCTL_CONFIG (2)
|
||||
#define DIA_IOCTL_START (3)
|
||||
#define DIA_IOCTL_GET_NUM (4)
|
||||
#define DIA_IOCTL_GET_LIST (5)
|
||||
#define DIA_IOCTL_LOG (6)
|
||||
#define DIA_IOCTL_DETECT (7)
|
||||
#define DIA_IOCTL_SPACE (8)
|
||||
#define DIA_IOCTL_GET_MEM (9)
|
||||
#define DIA_IOCTL_FLAVOUR (10)
|
||||
#define DIA_IOCTL_XLOG_REQ (11)
|
||||
|
||||
/* Error codes */
|
||||
|
||||
#define XLOG_ERR_CARD_NUM (13)
|
||||
#define XLOG_ERR_DONE (14)
|
||||
#define XLOG_ERR_CMD (15)
|
||||
#define XLOG_ERR_TIMEOUT (16)
|
||||
#define XLOG_ERR_CARD_STATE (17)
|
||||
#define XLOG_ERR_UNKNOWN (18)
|
||||
#define XLOG_OK (0)
|
||||
|
||||
/* Adapter states */
|
||||
|
||||
#define DIA_UNKNOWN (0)
|
||||
#define DIA_RESET (1)
|
||||
#define DIA_LOADED (2)
|
||||
#define DIA_CONFIGURED (3)
|
||||
#define DIA_RUNNING (4)
|
||||
|
||||
/* Stucture for getting card specific information from active cad driver */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int card_type;
|
||||
int card_slot;
|
||||
int state;
|
||||
} dia_card_list_t;
|
||||
|
||||
/* use following to select which logging to have active */
|
||||
|
||||
#define DIVAS_LOG_DEBUG (1 << 0)
|
||||
#define DIVAS_LOG_XLOG (1 << 1)
|
||||
#define DIVAS_LOG_IDI (1 << 2)
|
||||
#define DIVAS_LOG_CAPI (1 << 3)
|
||||
|
||||
/* stucture for DIA_IOCTL_LOG to get information from adapter */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int card_id;
|
||||
int log_types; /* bit mask of log types: use DIVAS_LOG_XXX */
|
||||
} dia_log_t;
|
||||
|
||||
/* list of cards supported by this driver */
|
||||
|
||||
#define DIA_CARD_TYPE_DIVA_SERVER (0) /* Diva Server PRI */
|
||||
#define DIA_CARD_TYPE_DIVA_SERVER_B (1) /* Diva Server BRI */
|
||||
#define DIA_CARD_TYPE_DIVA_SERVER_Q (2) /* Diva Server 4-BRI */
|
||||
|
||||
/* bus types */
|
||||
|
||||
#define DIA_BUS_TYPE_ISA (0)
|
||||
#define DIA_BUS_TYPE_ISA_PNP (1)
|
||||
#define DIA_BUS_TYPE_PCI (2)
|
||||
#define DIA_BUS_TYPE_MCA (3)
|
||||
|
||||
/* types of memory used (index for memory array below) */
|
||||
|
||||
#define DIVAS_RAM_MEMORY 0
|
||||
#define DIVAS_REG_MEMORY 1
|
||||
#define DIVAS_CFG_MEMORY 2
|
||||
#define DIVAS_SHARED_MEMORY 3
|
||||
#define DIVAS_CTL_MEMORY 4
|
||||
/*
|
||||
* card config information
|
||||
* passed as parameter to DIA_IOCTL_INIT ioctl to initialise new card
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int card_id; /* unique id assigned to this card */
|
||||
int card_type; /* use DIA_CARD_TYPE_xxx above */
|
||||
int bus_type; /* use DIA_BUS_TYPE_xxx above */
|
||||
int bus_num; /* bus number (instance number of bus type) */
|
||||
int func_num; /* adapter function number (PCI register) */
|
||||
int slot; /* slot number in bus */
|
||||
unsigned char irq; /* IRQ number */
|
||||
int reset_base; /* Reset register for I/O mapped cards */
|
||||
int io_base; /* I/O base for I/O mapped cards */
|
||||
void *memory[5]; /* memory base addresses for memory mapped cards */
|
||||
char name[9]; /* name of adapter */
|
||||
int serial; /* serial number */
|
||||
unsigned char int_priority; /* Interrupt priority */
|
||||
} dia_card_t;
|
||||
|
||||
/*
|
||||
* protocol configuration information
|
||||
* passed as parameter to DIA_IOCTL_CONFIG ioctl to configure card
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int card_id; /* to identify particular card */
|
||||
unsigned char tei;
|
||||
unsigned char nt2;
|
||||
unsigned char watchdog;
|
||||
unsigned char permanent;
|
||||
unsigned char x_interface;
|
||||
unsigned char stable_l2;
|
||||
unsigned char no_order_check;
|
||||
unsigned char handset_type;
|
||||
unsigned char sig_flags;
|
||||
unsigned char low_channel;
|
||||
unsigned char prot_version;
|
||||
unsigned char crc4;
|
||||
struct
|
||||
{
|
||||
unsigned char oad[32];
|
||||
unsigned char osa[32];
|
||||
unsigned char spid[32];
|
||||
}terminal[2];
|
||||
} dia_config_t;
|
||||
|
||||
/*
|
||||
* code configuration
|
||||
* passed as parameter to DIA_IOCTL_LOAD ioctl
|
||||
* one of these ioctl per code file to load
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int card_id; /* card to load */
|
||||
enum
|
||||
{
|
||||
DIA_CPU_CODE, /* CPU code */
|
||||
DIA_DSP_CODE, /* DSP code */
|
||||
DIA_CONT_CODE, /* continuation of code */
|
||||
DIA_TABLE_CODE, /* code table */
|
||||
DIA_DLOAD_CNT, /* number of downloads*/
|
||||
DIA_FPGA_CODE
|
||||
} code_type; /* code for CPU or DSP ? */
|
||||
int length; /* length of code */
|
||||
unsigned char *code; /* pointer (in user-space) to code */
|
||||
} dia_load_t;
|
||||
|
||||
/*
|
||||
* start configuration
|
||||
* passed as parameter to DIA_IOCTL_START ioctl
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int card_id; /* card to start */
|
||||
} dia_start_t;
|
||||
|
||||
/* used for retrieving memory from the card */
|
||||
|
||||
typedef struct {
|
||||
word card_id;
|
||||
dword addr;
|
||||
byte data[16 * 8];
|
||||
} mem_block_t;
|
||||
|
||||
/* DIVA Server specific addresses */
|
||||
|
||||
#define DIVAS_CPU_START_ADDR (0x0)
|
||||
#define ORG_MAX_PROTOCOL_CODE_SIZE 0x000A0000
|
||||
#define ORG_MAX_DSP_CODE_SIZE (0x000F0000 - ORG_MAX_PROTOCOL_CODE_SIZE)
|
||||
#define ORG_DSP_CODE_BASE (0xBF7F0000 - ORG_MAX_DSP_CODE_SIZE)
|
||||
#define DIVAS_DSP_START_ADDR (0xBF7A0000)
|
||||
#define DIVAS_SHARED_OFFSET (0x1000)
|
||||
#define MP_DSP_CODE_BASE 0xa03a0000
|
||||
#define MQ_PROTCODE_OFFSET 0x100000
|
||||
#define MQ_SM_OFFSET 0X0f0000
|
||||
|
||||
#define V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000
|
||||
#define V90D_MAX_DSP_CODE_SIZE (0x000F0000 - V90D_MAX_PROTOCOL_CODE_SIZE)
|
||||
#define V90D_DSP_CODE_BASE (0xBF7F0000 - V90D_MAX_DSP_CODE_SIZE)
|
||||
|
||||
#define MQ_ORG_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */
|
||||
#define MQ_ORG_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code */
|
||||
#define MQ_ORG_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
|
||||
- MQ_ORG_MAX_DSP_CODE_SIZE)
|
||||
#define MQ_V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000 /* max 576K Protocol-Code */
|
||||
#define MQ_V90D_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code if V.90D included */
|
||||
#define MQ_MAX_DSP_DOWNLOAD_ADDR 0xa03f0000
|
||||
#define MQ_V90D_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
|
||||
- MQ_V90D_MAX_DSP_CODE_SIZE)
|
||||
|
||||
|
||||
#define ALIGNMENT_MASK_MAESTRA 0xfffffffc
|
||||
|
||||
#endif /* DIVAS_H */
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DSP_DEFS_H_
|
||||
#define DSP_DEFS_H_
|
||||
|
||||
#ifndef DSPDIDS_H_
|
||||
#include "dspdids.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE (0 == 0)
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE (0 != 0)
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define DSP_MEMORY_TYPE_EXTERNAL_DM 0
|
||||
#define DSP_MEMORY_TYPE_EXTERNAL_PM 1
|
||||
#define DSP_MEMORY_TYPE_INTERNAL_DM 2
|
||||
#define DSP_MEMORY_TYPE_INTERNAL_PM 3
|
||||
|
||||
#define DSP_DOWNLOAD_FLAG_BOOTABLE 0x0001
|
||||
#define DSP_DOWNLOAD_FLAG_2181 0x0002
|
||||
#define DSP_DOWNLOAD_FLAG_TIMECRITICAL 0x0004
|
||||
#define DSP_DOWNLOAD_FLAG_COMPAND 0x0008
|
||||
|
||||
#define DSP_MEMORY_BLOCK_COUNT 16
|
||||
|
||||
#define DSP_SEGMENT_PM_FLAG 0x0001
|
||||
#define DSP_SEGMENT_SHARED_FLAG 0x0002
|
||||
|
||||
#define DSP_SEGMENT_EXTERNAL_DM DSP_MEMORY_TYPE_EXTERNAL_DM
|
||||
#define DSP_SEGMENT_EXTERNAL_PM DSP_MEMORY_TYPE_EXTERNAL_PM
|
||||
#define DSP_SEGMENT_INTERNAL_DM DSP_MEMORY_TYPE_INTERNAL_DM
|
||||
#define DSP_SEGMENT_INTERNAL_PM DSP_MEMORY_TYPE_INTERNAL_PM
|
||||
#define DSP_SEGMENT_FIRST_RELOCATABLE 4
|
||||
|
||||
#define DSP_DATA_BLOCK_PM_FLAG 0x0001
|
||||
#define DSP_DATA_BLOCK_DWORD_FLAG 0x0002
|
||||
#define DSP_DATA_BLOCK_RESOLVE_FLAG 0x0004
|
||||
|
||||
#define DSP_RELOC_NONE 0x00
|
||||
#define DSP_RELOC_SEGMENT_MASK 0x3f
|
||||
#define DSP_RELOC_TYPE_MASK 0xc0
|
||||
#define DSP_RELOC_TYPE_0 0x00 /* relocation of address in DM word / high part of PM word */
|
||||
#define DSP_RELOC_TYPE_1 0x40 /* relocation of address in low part of PM data word */
|
||||
#define DSP_RELOC_TYPE_2 0x80 /* relocation of address in standard command */
|
||||
#define DSP_RELOC_TYPE_3 0xc0 /* relocation of address in call/jump on flag in */
|
||||
|
||||
#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
|
||||
#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100
|
||||
|
||||
#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
|
||||
#define DSP_FILE_FORMAT_VERSION_BCD 0x0100
|
||||
|
||||
|
||||
typedef struct tag_dsp_combifile_header
|
||||
{
|
||||
char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE];
|
||||
word format_version_bcd;
|
||||
word header_size;
|
||||
word combifile_description_size;
|
||||
word directory_entries;
|
||||
word directory_size;
|
||||
word download_count;
|
||||
word usage_mask_size;
|
||||
} t_dsp_combifile_header;
|
||||
|
||||
typedef struct tag_dsp_combifile_directory_entry
|
||||
{
|
||||
word card_type_number;
|
||||
word file_set_number;
|
||||
} t_dsp_combifile_directory_entry;
|
||||
|
||||
typedef struct tag_dsp_file_header
|
||||
{
|
||||
char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE];
|
||||
word format_version_bcd;
|
||||
word download_id;
|
||||
word download_flags;
|
||||
word required_processing_power;
|
||||
word interface_channel_count;
|
||||
word header_size;
|
||||
word download_description_size;
|
||||
word memory_block_table_size;
|
||||
word memory_block_count;
|
||||
word segment_table_size;
|
||||
word segment_count;
|
||||
word symbol_table_size;
|
||||
word symbol_count;
|
||||
word total_data_size_dm;
|
||||
word data_block_count_dm;
|
||||
word total_data_size_pm;
|
||||
word data_block_count_pm;
|
||||
} t_dsp_file_header;
|
||||
|
||||
typedef struct tag_dsp_memory_block_desc
|
||||
{
|
||||
word alias_memory_block;
|
||||
word memory_type;
|
||||
word address;
|
||||
word size; /* DSP words */
|
||||
} t_dsp_memory_block_desc;
|
||||
|
||||
typedef struct tag_dsp_segment_desc
|
||||
{
|
||||
word memory_block;
|
||||
word attributes;
|
||||
word base;
|
||||
word size;
|
||||
word alignment; /* ==0 -> no other legal start address than base */
|
||||
} t_dsp_segment_desc;
|
||||
|
||||
typedef struct tag_dsp_symbol_desc
|
||||
{
|
||||
word symbol_id;
|
||||
word segment;
|
||||
word offset;
|
||||
word size; /* DSP words */
|
||||
} t_dsp_symbol_desc;
|
||||
|
||||
typedef struct tag_dsp_data_block_header
|
||||
{
|
||||
word attributes;
|
||||
word segment;
|
||||
word offset;
|
||||
word size; /* DSP words */
|
||||
} t_dsp_data_block_header;
|
||||
|
||||
typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */
|
||||
{
|
||||
word download_id;
|
||||
word download_flags;
|
||||
word required_processing_power;
|
||||
word interface_channel_count;
|
||||
word excess_header_size;
|
||||
word memory_block_count;
|
||||
word segment_count;
|
||||
word symbol_count;
|
||||
word data_block_count_dm;
|
||||
word data_block_count_pm;
|
||||
byte *p_excess_header_data;
|
||||
char *p_download_description;
|
||||
t_dsp_memory_block_desc *p_memory_block_table;
|
||||
t_dsp_segment_desc *p_segment_table;
|
||||
t_dsp_symbol_desc *p_symbol_table;
|
||||
word *p_data_blocks_dm;
|
||||
word *p_data_blocks_pm;
|
||||
} t_dsp_download_desc;
|
||||
|
||||
#define DSP_DOWNLOAD_INDEX_KERNEL 0
|
||||
#define DSP30TX_DOWNLOAD_INDEX_KERNEL 1
|
||||
#define DSP30RX_DOWNLOAD_INDEX_KERNEL 2
|
||||
#define DSP_MAX_DOWNLOAD_COUNT 35
|
||||
|
||||
|
||||
#define DSP_DOWNLOAD_MAX_SEGMENTS 16
|
||||
|
||||
#define DSP_UDATA_REQUEST_RECONFIGURE 0
|
||||
/*
|
||||
parameters:
|
||||
<word> reconfigure delay (in 8kHz samples)
|
||||
<word> reconfigure code
|
||||
<byte> reconfigure hdlc preamble flags
|
||||
*/
|
||||
|
||||
#define DSP_RECONFIGURE_TX_FLAG 0x8000
|
||||
#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000
|
||||
#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
|
||||
#define DSP_RECONFIGURE_HDLC_FLAG 0x1000
|
||||
#define DSP_RECONFIGURE_SYNC_FLAG 0x0800
|
||||
#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff
|
||||
#define DSP_RECONFIGURE_IDLE 0
|
||||
#define DSP_RECONFIGURE_V25 1
|
||||
#define DSP_RECONFIGURE_V21_CH2 2
|
||||
#define DSP_RECONFIGURE_V27_2400 3
|
||||
#define DSP_RECONFIGURE_V27_4800 4
|
||||
#define DSP_RECONFIGURE_V29_7200 5
|
||||
#define DSP_RECONFIGURE_V29_9600 6
|
||||
#define DSP_RECONFIGURE_V33_12000 7
|
||||
#define DSP_RECONFIGURE_V33_14400 8
|
||||
#define DSP_RECONFIGURE_V17_7200 9
|
||||
#define DSP_RECONFIGURE_V17_9600 10
|
||||
#define DSP_RECONFIGURE_V17_12000 11
|
||||
#define DSP_RECONFIGURE_V17_14400 12
|
||||
|
||||
/*
|
||||
data indications if transparent framer
|
||||
<byte> data 0
|
||||
<byte> data 1
|
||||
...
|
||||
|
||||
data indications if HDLC framer
|
||||
<byte> data 0
|
||||
<byte> data 1
|
||||
...
|
||||
<byte> CRC 0
|
||||
<byte> CRC 1
|
||||
<byte> preamble flags
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_SYNC 0
|
||||
/*
|
||||
returns:
|
||||
<word> time of sync (sampled from counter at 8kHz)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_DCD_OFF 1
|
||||
/*
|
||||
returns:
|
||||
<word> time of DCD off (sampled from counter at 8kHz)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_DCD_ON 2
|
||||
/*
|
||||
returns:
|
||||
<word> time of DCD on (sampled from counter at 8kHz)
|
||||
<byte> connected norm
|
||||
<word> connected options
|
||||
<dword> connected speed (bit/s)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_CTS_OFF 3
|
||||
/*
|
||||
returns:
|
||||
<word> time of CTS off (sampled from counter at 8kHz)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_CTS_ON 4
|
||||
/*
|
||||
returns:
|
||||
<word> time of CTS on (sampled from counter at 8kHz)
|
||||
<byte> connected norm
|
||||
<word> connected options
|
||||
<dword> connected speed (bit/s)
|
||||
*/
|
||||
|
||||
#define DSP_CONNECTED_NORM_UNSPECIFIED 0
|
||||
#define DSP_CONNECTED_NORM_V21 1
|
||||
#define DSP_CONNECTED_NORM_V23 2
|
||||
#define DSP_CONNECTED_NORM_V22 3
|
||||
#define DSP_CONNECTED_NORM_V22_BIS 4
|
||||
#define DSP_CONNECTED_NORM_V32_BIS 5
|
||||
#define DSP_CONNECTED_NORM_V34 6
|
||||
#define DSP_CONNECTED_NORM_V8 7
|
||||
#define DSP_CONNECTED_NORM_BELL_212A 8
|
||||
#define DSP_CONNECTED_NORM_BELL_103 9
|
||||
#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
|
||||
#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
|
||||
#define DSP_CONNECTED_NORM_TFAST 12
|
||||
#define DSP_CONNECTED_NORM_V21_CH2 13
|
||||
#define DSP_CONNECTED_NORM_V27_TER 14
|
||||
#define DSP_CONNECTED_NORM_V29 15
|
||||
#define DSP_CONNECTED_NORM_V33 16
|
||||
#define DSP_CONNECTED_NORM_V17 17
|
||||
|
||||
#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DSPDIDS_H_
|
||||
#define DSPDIDS_H_
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define DSP_DID_INVALID 0
|
||||
#define DSP_DID_DIVA 1
|
||||
#define DSP_DID_DIVA_PRO 2
|
||||
#define DSP_DID_DIVA_PRO_20 3
|
||||
#define DSP_DID_DIVA_PRO_PCCARD 4
|
||||
#define DSP_DID_DIVA_SERVER_BRI_1M 5
|
||||
#define DSP_DID_DIVA_SERVER_BRI_2M 6
|
||||
#define DSP_DID_DIVA_SERVER_PRI_2M_TX 7
|
||||
#define DSP_DID_DIVA_SERVER_PRI_2M_RX 8
|
||||
#define DSP_DID_DIVA_SERVER_PRI_30M 9
|
||||
#define DSP_DID_TASK_HSCX 100
|
||||
#define DSP_DID_TASK_HSCX_PRI_2M_TX 101
|
||||
#define DSP_DID_TASK_HSCX_PRI_2M_RX 102
|
||||
#define DSP_DID_TASK_V110KRNL 200
|
||||
#define DSP_DID_OVERLAY_V1100 201
|
||||
#define DSP_DID_OVERLAY_V1101 202
|
||||
#define DSP_DID_OVERLAY_V1102 203
|
||||
#define DSP_DID_OVERLAY_V1103 204
|
||||
#define DSP_DID_OVERLAY_V1104 205
|
||||
#define DSP_DID_OVERLAY_V1105 206
|
||||
#define DSP_DID_OVERLAY_V1106 207
|
||||
#define DSP_DID_OVERLAY_V1107 208
|
||||
#define DSP_DID_OVERLAY_V1108 209
|
||||
#define DSP_DID_OVERLAY_V1109 210
|
||||
#define DSP_DID_TASK_V110_PRI_2M_TX 220
|
||||
#define DSP_DID_TASK_V110_PRI_2M_RX 221
|
||||
#define DSP_DID_TASK_MODEM 300
|
||||
#define DSP_DID_TASK_FAX05 400
|
||||
#define DSP_DID_TASK_VOICE 500
|
||||
#define DSP_DID_TASK_TIKRNL81 600
|
||||
#define DSP_DID_OVERLAY_DIAL 601
|
||||
#define DSP_DID_OVERLAY_V22 602
|
||||
#define DSP_DID_OVERLAY_V32 603
|
||||
#define DSP_DID_OVERLAY_FSK 604
|
||||
#define DSP_DID_OVERLAY_FAX 605
|
||||
#define DSP_DID_OVERLAY_VXX 606
|
||||
#define DSP_DID_OVERLAY_V8 607
|
||||
#define DSP_DID_OVERLAY_INFO 608
|
||||
#define DSP_DID_OVERLAY_V34 609
|
||||
#define DSP_DID_OVERLAY_DFX 610
|
||||
#define DSP_DID_PARTIAL_OVERLAY_DIAL 611
|
||||
#define DSP_DID_PARTIAL_OVERLAY_FSK 612
|
||||
#define DSP_DID_PARTIAL_OVERLAY_FAX 613
|
||||
#define DSP_DID_TASK_TIKRNL05 700
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -2,103 +2,15 @@
|
|||
*
|
||||
* ISDN low-level module for Eicon active ISDN-Cards.
|
||||
*
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
|
||||
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.18 1999/11/25 11:43:27 armin
|
||||
* Fixed statectrl and connect message.
|
||||
* X.75 fix and HDLC/transparent with autoconnect.
|
||||
* Minor cleanup.
|
||||
*
|
||||
* Revision 1.17 1999/10/26 21:15:33 armin
|
||||
* using define for checking phone number len to avoid buffer overflow.
|
||||
*
|
||||
* Revision 1.16 1999/10/08 22:09:33 armin
|
||||
* Some fixes of cards interface handling.
|
||||
* Bugfix of NULL pointer occurence.
|
||||
* Changed a few log outputs.
|
||||
*
|
||||
* Revision 1.15 1999/09/26 14:17:53 armin
|
||||
* Improved debug and log via readstat()
|
||||
*
|
||||
* Revision 1.14 1999/09/08 20:17:31 armin
|
||||
* Added microchannel patch from Erik Weber.
|
||||
*
|
||||
* Revision 1.13 1999/09/06 07:29:35 fritz
|
||||
* Changed my mail-address.
|
||||
*
|
||||
* Revision 1.12 1999/09/04 06:20:05 keil
|
||||
* Changes from kernel set_current_state()
|
||||
*
|
||||
* Revision 1.11 1999/08/29 17:23:44 armin
|
||||
* New setup compat.
|
||||
* Bugfix if compile as not module.
|
||||
*
|
||||
* Revision 1.10 1999/08/22 20:26:41 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.9 1999/08/18 20:16:57 armin
|
||||
* Added XLOG function for all cards.
|
||||
* Bugfix of alloc_skb NULL pointer.
|
||||
*
|
||||
* Revision 1.8 1999/07/25 15:12:01 armin
|
||||
* fix of some debug logs.
|
||||
* enabled ISA-cards option.
|
||||
*
|
||||
* Revision 1.7 1999/07/11 17:16:23 armin
|
||||
* Bugfixes in queue handling.
|
||||
* Added DSP-DTMF decoder functions.
|
||||
* Reorganized ack_handler.
|
||||
*
|
||||
* Revision 1.6 1999/06/09 19:31:24 armin
|
||||
* Wrong PLX size for request_region() corrected.
|
||||
* Added first MCA code from Erik Weber.
|
||||
*
|
||||
* Revision 1.5 1999/03/29 11:19:41 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.4 1999/03/02 12:37:42 armin
|
||||
* Added some important checks.
|
||||
* Analog Modem with DSP.
|
||||
* Channels will be added to Link-Level after loading firmware.
|
||||
*
|
||||
* Revision 1.3 1999/01/24 20:14:07 armin
|
||||
* Changed and added debug stuff.
|
||||
* Better data sending. (still problems with tty's flip buffer)
|
||||
*
|
||||
* Revision 1.2 1999/01/10 18:46:04 armin
|
||||
* Bug with wrong values in HLC fixed.
|
||||
* Bytes to send are counted and limited now.
|
||||
*
|
||||
* Revision 1.1 1999/01/01 18:09:41 armin
|
||||
* First checkin of new eicon driver.
|
||||
* DIVA-Server BRI/PCI and PRI/PCI are supported.
|
||||
* Old diehl code is obsolete.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef eicon_h
|
||||
#define eicon_h
|
||||
|
||||
|
@ -120,6 +32,8 @@
|
|||
#define EICON_IOCTL_TEST 98
|
||||
#define EICON_IOCTL_DEBUGVAR 99
|
||||
|
||||
#define EICON_IOCTL_DIA_OFFSET 100
|
||||
|
||||
/* Bus types */
|
||||
#define EICON_BUS_ISA 1
|
||||
#define EICON_BUS_MCA 2
|
||||
|
@ -181,39 +95,10 @@ typedef struct {
|
|||
unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */
|
||||
} eicon_isa_codebuf;
|
||||
|
||||
/* Struct for downloading protocol via ioctl for PCI cards */
|
||||
typedef struct {
|
||||
/* start-up parameters */
|
||||
unsigned char tei;
|
||||
unsigned char nt2;
|
||||
unsigned char WatchDog;
|
||||
unsigned char Permanent;
|
||||
unsigned char XInterface;
|
||||
unsigned char StableL2;
|
||||
unsigned char NoOrderCheck;
|
||||
unsigned char HandsetType;
|
||||
unsigned char LowChannel;
|
||||
unsigned char ProtVersion;
|
||||
unsigned char Crc4;
|
||||
unsigned char NoHscx30Mode; /* switch PRI into No HSCX30 test mode */
|
||||
unsigned char Loopback; /* switch card into Loopback mode */
|
||||
struct q931_link_s
|
||||
{
|
||||
unsigned char oad[32];
|
||||
unsigned char osa[32];
|
||||
unsigned char spid[32];
|
||||
} l[2];
|
||||
unsigned long protocol_len;
|
||||
unsigned int dsp_code_num;
|
||||
unsigned long dsp_code_len[9];
|
||||
unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */
|
||||
} eicon_pci_codebuf;
|
||||
|
||||
/* Data for downloading protocol via ioctl */
|
||||
typedef union {
|
||||
eicon_isa_codebuf isa;
|
||||
eicon_isa_codebuf mca;
|
||||
eicon_pci_codebuf pci;
|
||||
} eicon_codebuf;
|
||||
|
||||
/* Data for Management interface */
|
||||
|
@ -224,6 +109,7 @@ typedef struct {
|
|||
unsigned char data[700];
|
||||
} eicon_manifbuf;
|
||||
|
||||
#define TRACE_OK (1)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
@ -241,7 +127,7 @@ typedef struct {
|
|||
#include <asm/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/ioport.h>
|
||||
|
@ -249,11 +135,11 @@ typedef struct {
|
|||
#include <linux/wait.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <linux/isdn.h>
|
||||
#include <linux/isdnif.h>
|
||||
|
||||
#include <linux/isdn_compat.h>
|
||||
|
||||
typedef struct {
|
||||
__u16 length __attribute__ ((packed)); /* length of data/parameter field */
|
||||
|
@ -262,206 +148,34 @@ typedef struct {
|
|||
|
||||
#include "eicon_isa.h"
|
||||
|
||||
#include "idi.h"
|
||||
|
||||
typedef struct {
|
||||
__u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */
|
||||
__u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */
|
||||
__u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */
|
||||
__u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */
|
||||
__u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */
|
||||
__u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */
|
||||
__u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */
|
||||
__u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */
|
||||
__u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */
|
||||
__u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */
|
||||
__u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */
|
||||
__u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */
|
||||
__u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */
|
||||
__u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */
|
||||
__u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */
|
||||
__u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */
|
||||
__u8 B[1]; /* buffer space for Req,Ind and Rc */
|
||||
} eicon_pr_ram;
|
||||
|
||||
/* Macro for delay via schedule() */
|
||||
#define SLEEP(j) { \
|
||||
set_current_state(TASK_UNINTERRUPTIBLE); \
|
||||
schedule_timeout(j); \
|
||||
}
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
#define DIVAS_SHARED_OFFSET (0x1000)
|
||||
|
||||
#define MIPS_BUFFER_SZ 128
|
||||
#define MIPS_MAINT_OFFS 0xff00
|
||||
|
||||
#define XLOG_ERR_CARD_NUM (13)
|
||||
#define XLOG_ERR_DONE (14)
|
||||
#define XLOG_ERR_CMD (15)
|
||||
#define XLOG_ERR_TIMEOUT (16)
|
||||
#define XLOG_ERR_CARD_STATE (17)
|
||||
#define XLOG_ERR_UNKNOWN (18)
|
||||
#define XLOG_OK (0)
|
||||
|
||||
#define TRACE_OK (1)
|
||||
|
||||
typedef struct {
|
||||
__u8 Id __attribute__ ((packed));
|
||||
__u8 uX __attribute__ ((packed));
|
||||
__u8 listen __attribute__ ((packed));
|
||||
__u8 active __attribute__ ((packed));
|
||||
__u8 sin[3] __attribute__ ((packed));
|
||||
__u8 bc[6] __attribute__ ((packed));
|
||||
__u8 llc[6] __attribute__ ((packed));
|
||||
__u8 hlc[6] __attribute__ ((packed));
|
||||
__u8 oad[20] __attribute__ ((packed));
|
||||
}DSigStruc;
|
||||
|
||||
typedef struct {
|
||||
__u32 cx_b1 __attribute__ ((packed));
|
||||
__u32 cx_b2 __attribute__ ((packed));
|
||||
__u32 cr_b1 __attribute__ ((packed));
|
||||
__u32 cr_b2 __attribute__ ((packed));
|
||||
__u32 px_b1 __attribute__ ((packed));
|
||||
__u32 px_b2 __attribute__ ((packed));
|
||||
__u32 pr_b1 __attribute__ ((packed));
|
||||
__u32 pr_b2 __attribute__ ((packed));
|
||||
__u16 er_b1 __attribute__ ((packed));
|
||||
__u16 er_b2 __attribute__ ((packed));
|
||||
}BL1Struc;
|
||||
|
||||
typedef struct {
|
||||
__u32 XTotal __attribute__ ((packed));
|
||||
__u32 RTotal __attribute__ ((packed));
|
||||
__u16 XError __attribute__ ((packed));
|
||||
__u16 RError __attribute__ ((packed));
|
||||
}L2Struc;
|
||||
|
||||
typedef struct {
|
||||
__u16 free_n;
|
||||
}OSStruc;
|
||||
|
||||
typedef union
|
||||
{
|
||||
DSigStruc DSigStats;
|
||||
BL1Struc BL1Stats;
|
||||
L2Struc L2Stats;
|
||||
OSStruc OSStats;
|
||||
__u8 b[MIPS_BUFFER_SZ];
|
||||
__u16 w[MIPS_BUFFER_SZ>>1];
|
||||
__u16 l[MIPS_BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
|
||||
__u32 d[MIPS_BUFFER_SZ>>2];
|
||||
} MIPS_BUFFER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__u8 req __attribute__ ((packed));
|
||||
__u8 rc __attribute__ ((packed));
|
||||
__u8 reserved[2] __attribute__ ((packed)); /* R3000 alignment ... */
|
||||
__u8 *mem __attribute__ ((packed));
|
||||
__u16 length __attribute__ ((packed)); /* used to be short */
|
||||
__u16 port __attribute__ ((packed));
|
||||
__u8 fill[4] __attribute__ ((packed)); /* data at offset 16 */
|
||||
MIPS_BUFFER data __attribute__ ((packed));
|
||||
} mi_pc_maint_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__u16 command;
|
||||
mi_pc_maint_t pcm;
|
||||
}xlogreq_t;
|
||||
|
||||
typedef struct{
|
||||
__u16 code __attribute__ ((packed)); /* used to be short */
|
||||
__u16 timeh __attribute__ ((packed));
|
||||
__u16 timel __attribute__ ((packed));
|
||||
char buffer[MIPS_BUFFER_SZ - 6];
|
||||
}xlog_entry_t;
|
||||
|
||||
|
||||
#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
|
||||
#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100
|
||||
|
||||
#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
|
||||
#define DSP_FILE_FORMAT_VERSION_BCD 0x0100
|
||||
|
||||
typedef struct tag_dsp_combifile_header
|
||||
{
|
||||
char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
|
||||
__u16 format_version_bcd __attribute__ ((packed));
|
||||
__u16 header_size __attribute__ ((packed));
|
||||
__u16 combifile_description_size __attribute__ ((packed));
|
||||
__u16 directory_entries __attribute__ ((packed));
|
||||
__u16 directory_size __attribute__ ((packed));
|
||||
__u16 download_count __attribute__ ((packed));
|
||||
__u16 usage_mask_size __attribute__ ((packed));
|
||||
} t_dsp_combifile_header;
|
||||
|
||||
typedef struct tag_dsp_combifile_directory_entry
|
||||
{
|
||||
__u16 card_type_number __attribute__ ((packed));
|
||||
__u16 file_set_number __attribute__ ((packed));
|
||||
} t_dsp_combifile_directory_entry;
|
||||
|
||||
typedef struct tag_dsp_file_header
|
||||
{
|
||||
char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
|
||||
__u16 format_version_bcd __attribute__ ((packed));
|
||||
__u16 download_id __attribute__ ((packed));
|
||||
__u16 download_flags __attribute__ ((packed));
|
||||
__u16 required_processing_power __attribute__ ((packed));
|
||||
__u16 interface_channel_count __attribute__ ((packed));
|
||||
__u16 header_size __attribute__ ((packed));
|
||||
__u16 download_description_size __attribute__ ((packed));
|
||||
__u16 memory_block_table_size __attribute__ ((packed));
|
||||
__u16 memory_block_count __attribute__ ((packed));
|
||||
__u16 segment_table_size __attribute__ ((packed));
|
||||
__u16 segment_count __attribute__ ((packed));
|
||||
__u16 symbol_table_size __attribute__ ((packed));
|
||||
__u16 symbol_count __attribute__ ((packed));
|
||||
__u16 total_data_size_dm __attribute__ ((packed));
|
||||
__u16 data_block_count_dm __attribute__ ((packed));
|
||||
__u16 total_data_size_pm __attribute__ ((packed));
|
||||
__u16 data_block_count_pm __attribute__ ((packed));
|
||||
} t_dsp_file_header;
|
||||
|
||||
typedef struct tag_dsp_memory_block_desc
|
||||
{
|
||||
__u16 alias_memory_block;
|
||||
__u16 memory_type;
|
||||
__u16 address;
|
||||
__u16 size; /* DSP words */
|
||||
} t_dsp_memory_block_desc;
|
||||
|
||||
typedef struct tag_dsp_segment_desc
|
||||
{
|
||||
__u16 memory_block;
|
||||
__u16 attributes;
|
||||
__u16 base;
|
||||
__u16 size;
|
||||
__u16 alignment; /* ==0 -> no other legal start address than base */
|
||||
} t_dsp_segment_desc;
|
||||
|
||||
typedef struct tag_dsp_symbol_desc
|
||||
{
|
||||
__u16 symbol_id;
|
||||
__u16 segment;
|
||||
__u16 offset;
|
||||
__u16 size; /* DSP words */
|
||||
} t_dsp_symbol_desc;
|
||||
|
||||
typedef struct tag_dsp_data_block_header
|
||||
{
|
||||
__u16 attributes;
|
||||
__u16 segment;
|
||||
__u16 offset;
|
||||
__u16 size; /* DSP words */
|
||||
} t_dsp_data_block_header;
|
||||
|
||||
typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */
|
||||
{
|
||||
__u16 download_id;
|
||||
__u16 download_flags;
|
||||
__u16 required_processing_power;
|
||||
__u16 interface_channel_count;
|
||||
__u16 excess_header_size;
|
||||
__u16 memory_block_count;
|
||||
__u16 segment_count;
|
||||
__u16 symbol_count;
|
||||
__u16 data_block_count_dm;
|
||||
__u16 data_block_count_pm;
|
||||
__u8 * p_excess_header_data __attribute__ ((packed));
|
||||
char * p_download_description __attribute__ ((packed));
|
||||
t_dsp_memory_block_desc *p_memory_block_table __attribute__ ((packed));
|
||||
t_dsp_segment_desc *p_segment_table __attribute__ ((packed));
|
||||
t_dsp_symbol_desc *p_symbol_table __attribute__ ((packed));
|
||||
__u16 * p_data_blocks_dm __attribute__ ((packed));
|
||||
__u16 * p_data_blocks_pm __attribute__ ((packed));
|
||||
} t_dsp_download_desc;
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
typedef struct {
|
||||
__u8 Req; /* pending request */
|
||||
__u8 Rc; /* return code received */
|
||||
|
@ -505,6 +219,7 @@ typedef struct {
|
|||
unsigned short statectrl; /* State controling bits */
|
||||
unsigned short eazmask; /* EAZ-Mask for this Channel */
|
||||
int queued; /* User-Data Bytes in TX queue */
|
||||
int pqueued; /* User-Data Packets in TX queue */
|
||||
int waitq; /* User-Data Bytes in wait queue */
|
||||
int waitpq; /* User-Data Bytes in packet queue */
|
||||
struct sk_buff *tskb1; /* temp skb 1 */
|
||||
|
@ -515,7 +230,9 @@ typedef struct {
|
|||
T30_s *fax; /* pointer to fax data in LL */
|
||||
eicon_ch_fax_buf fax2; /* fax related struct */
|
||||
#endif
|
||||
entity e; /* Entity */
|
||||
entity e; /* Native Entity */
|
||||
ENTITY de; /* Divas D Entity */
|
||||
ENTITY be; /* Divas B Entity */
|
||||
char cpn[32]; /* remember cpn */
|
||||
char oad[32]; /* remember oad */
|
||||
char dsa[32]; /* remember dsa */
|
||||
|
@ -539,8 +256,6 @@ typedef struct {
|
|||
#define EICON_FLAGS_MVALID 8 /* Cards membase is valid */
|
||||
#define EICON_FLAGS_LOADED 8 /* Firmware loaded */
|
||||
|
||||
#define EICON_BCH 2 /* # of channels per card */
|
||||
|
||||
/* D-Channel states */
|
||||
#define EICON_STATE_NULL 0
|
||||
#define EICON_STATE_ICALL 1
|
||||
|
@ -562,9 +277,6 @@ typedef struct {
|
|||
|
||||
#define EICON_MAX_QUEUE 2138
|
||||
|
||||
#define EICON_LOCK_TX 0
|
||||
#define EICON_LOCK_RX 1
|
||||
|
||||
typedef union {
|
||||
eicon_isa_card isa;
|
||||
eicon_pci_card pci;
|
||||
|
@ -590,17 +302,12 @@ typedef struct {
|
|||
__u8 more;
|
||||
} eicon_indhdr;
|
||||
|
||||
typedef struct msn_entry {
|
||||
char eaz;
|
||||
char msn[16];
|
||||
struct msn_entry * next;
|
||||
} msn_entry;
|
||||
|
||||
/*
|
||||
* Per card driver data
|
||||
*/
|
||||
typedef struct eicon_card {
|
||||
eicon_hwif hwif; /* Hardware dependant interface */
|
||||
DESCRIPTOR *d; /* IDI Descriptor */
|
||||
u_char ptype; /* Protocol type (1TR6 or Euro) */
|
||||
u_char bus; /* Bustype (ISA, MCA, PCI) */
|
||||
u_char type; /* Cardtype (EICON_CTYPE_...) */
|
||||
|
@ -618,49 +325,23 @@ typedef struct eicon_card {
|
|||
struct tq_struct snd_tq; /* Task struct for xmit bh */
|
||||
struct tq_struct rcv_tq; /* Task struct for rcv bh */
|
||||
struct tq_struct ack_tq; /* Task struct for ack bh */
|
||||
msn_entry *msn_list;
|
||||
eicon_chan* IdTable[256]; /* Table to find entity */
|
||||
__u16 ref_in;
|
||||
__u16 ref_out;
|
||||
int nchannels; /* Number of B-Channels */
|
||||
int ReadyInt; /* Ready Interrupt */
|
||||
eicon_chan *bch; /* B-Channel status/control */
|
||||
char status_buf[256]; /* Buffer for status messages */
|
||||
char *status_buf_read;
|
||||
char *status_buf_write;
|
||||
char *status_buf_end;
|
||||
DBUFFER *dbuf; /* Dbuffer for Diva Server */
|
||||
BUFFERS *sbuf; /* Buffer for Diva Server */
|
||||
char *sbufp; /* Data Buffer for Diva Server */
|
||||
isdn_if interface; /* Interface to upper layer */
|
||||
char regname[35]; /* Name used for request_region */
|
||||
char regname[35]; /* Drivers card name */
|
||||
#ifdef CONFIG_MCA
|
||||
int mca_slot; /* # of cards MCA slot */
|
||||
int mca_io; /* MCA cards IO port */
|
||||
#endif /* CONFIG_MCA */
|
||||
} eicon_card;
|
||||
|
||||
/* -----------------------------------------------------------**
|
||||
** The PROTOCOL_FEATURE_STRING **
|
||||
** defines capabilities and **
|
||||
** features of the actual protocol code. It's used as a bit **
|
||||
** mask. **
|
||||
** The following Bits are defined: **
|
||||
** -----------------------------------------------------------*/
|
||||
#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
|
||||
#define PROTCAP_MANIF 0x0002 /* Management interface implemented */
|
||||
#define PROTCAP_V_42 0x0004 /* V42 implemented */
|
||||
#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
|
||||
#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
|
||||
#define PROTCAP_FREE4 0x0020 /* not used */
|
||||
#define PROTCAP_FREE5 0x0040 /* not used */
|
||||
#define PROTCAP_FREE6 0x0080 /* not used */
|
||||
#define PROTCAP_FREE7 0x0100 /* not used */
|
||||
#define PROTCAP_FREE8 0x0200 /* not used */
|
||||
#define PROTCAP_FREE9 0x0400 /* not used */
|
||||
#define PROTCAP_FREE10 0x0800 /* not used */
|
||||
#define PROTCAP_FREE11 0x1000 /* not used */
|
||||
#define PROTCAP_FREE12 0x2000 /* not used */
|
||||
#define PROTCAP_FREE13 0x4000 /* not used */
|
||||
#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */
|
||||
|
||||
#include "eicon_idi.h"
|
||||
|
||||
extern eicon_card *cards;
|
||||
|
@ -685,13 +366,11 @@ extern __inline__ void eicon_schedule_ack(eicon_card *card)
|
|||
mark_bh(IMMEDIATE_BH);
|
||||
}
|
||||
|
||||
extern char *eicon_find_eaz(eicon_card *, char);
|
||||
extern int eicon_addcard(int, int, int, char *);
|
||||
extern int eicon_addcard(int, int, int, char *, int);
|
||||
extern void eicon_io_transmit(eicon_card *card);
|
||||
extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
|
||||
extern void eicon_io_rcv_dispatch(eicon_card *ccard);
|
||||
extern void eicon_io_ack_dispatch(eicon_card *ccard);
|
||||
extern int eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq);
|
||||
#ifdef CONFIG_MCA
|
||||
extern int eicon_mca_find_card(int, int, int, char *);
|
||||
extern int eicon_mca_probe(int, int, int, int, char *);
|
||||
|
@ -702,6 +381,8 @@ extern ulong DebugVar;
|
|||
extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
|
||||
extern void eicon_putstatus(eicon_card * card, char * buf);
|
||||
|
||||
extern spinlock_t eicon_lock;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* eicon_h */
|
||||
|
|
|
@ -1,90 +1,21 @@
|
|||
/* $Id$
|
||||
*
|
||||
* ISDN lowlevel-module for Eicon active cards.
|
||||
* DSP definitions
|
||||
* DSP definitions
|
||||
*
|
||||
* Copyright 1999,2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.4 1999/07/25 15:12:02 armin
|
||||
* fix of some debug logs.
|
||||
* enabled ISA-cards option.
|
||||
*
|
||||
* Revision 1.3 1999/07/11 17:16:24 armin
|
||||
* Bugfixes in queue handling.
|
||||
* Added DSP-DTMF decoder functions.
|
||||
* Reorganized ack_handler.
|
||||
*
|
||||
* Revision 1.2 1999/03/29 11:19:42 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.1 1999/03/02 12:18:54 armin
|
||||
* First checkin of DSP defines for audio features.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DSP_H
|
||||
#define DSP_H
|
||||
|
||||
#define DSP_UDATA_REQUEST_RECONFIGURE 0
|
||||
/*
|
||||
parameters:
|
||||
<word> reconfigure delay (in 8kHz samples)
|
||||
<word> reconfigure code
|
||||
<byte> reconfigure hdlc preamble flags
|
||||
*/
|
||||
#include "dsp_defs.h"
|
||||
|
||||
#define DSP_RECONFIGURE_TX_FLAG 0x8000
|
||||
#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000
|
||||
#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
|
||||
#define DSP_RECONFIGURE_HDLC_FLAG 0x1000
|
||||
#define DSP_RECONFIGURE_SYNC_FLAG 0x0800
|
||||
#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff
|
||||
#define DSP_RECONFIGURE_IDLE 0
|
||||
#define DSP_RECONFIGURE_V25 1
|
||||
#define DSP_RECONFIGURE_V21_CH2 2
|
||||
#define DSP_RECONFIGURE_V27_2400 3
|
||||
#define DSP_RECONFIGURE_V27_4800 4
|
||||
#define DSP_RECONFIGURE_V29_7200 5
|
||||
#define DSP_RECONFIGURE_V29_9600 6
|
||||
#define DSP_RECONFIGURE_V33_12000 7
|
||||
#define DSP_RECONFIGURE_V33_14400 8
|
||||
#define DSP_RECONFIGURE_V17_7200 9
|
||||
#define DSP_RECONFIGURE_V17_9600 10
|
||||
#define DSP_RECONFIGURE_V17_12000 11
|
||||
#define DSP_RECONFIGURE_V17_14400 12
|
||||
|
||||
/*
|
||||
data indications if transparent framer
|
||||
<byte> data 0
|
||||
<byte> data 1
|
||||
...
|
||||
|
||||
data indications if HDLC framer
|
||||
<byte> data 0
|
||||
<byte> data 1
|
||||
...
|
||||
<byte> CRC 0
|
||||
<byte> CRC 1
|
||||
<byte> preamble flags
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1
|
||||
/*
|
||||
|
@ -118,49 +49,6 @@ parameters:
|
|||
- none -
|
||||
*/
|
||||
|
||||
|
||||
#define DSP_UDATA_INDICATION_SYNC 0
|
||||
/*
|
||||
returns:
|
||||
<word> time of sync (sampled from counter at 8kHz)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_DCD_OFF 1
|
||||
/*
|
||||
returns:
|
||||
<word> time of DCD off (sampled from counter at 8kHz)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_DCD_ON 2
|
||||
/*
|
||||
returns:
|
||||
<word> time of DCD on (sampled from counter at 8kHz)
|
||||
<byte> connected norm
|
||||
<word> connected options
|
||||
<dword> connected speed (bit/s, max of tx and rx speed)
|
||||
<word> roundtrip delay (ms)
|
||||
<dword> connected speed tx (bit/s)
|
||||
<dword> connected speed rx (bit/s)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_CTS_OFF 3
|
||||
/*
|
||||
returns:
|
||||
<word> time of CTS off (sampled from counter at 8kHz)
|
||||
*/
|
||||
|
||||
#define DSP_UDATA_INDICATION_CTS_ON 4
|
||||
/*
|
||||
returns:
|
||||
<word> time of CTS on (sampled from counter at 8kHz)
|
||||
<byte> connected norm
|
||||
<word> connected options
|
||||
<dword> connected speed (bit/s, max of tx and rx speed)
|
||||
<word> roundtrip delay (ms)
|
||||
<dword> connected speed tx (bit/s)
|
||||
<dword> connected speed rx (bit/s)
|
||||
*/
|
||||
|
||||
typedef struct eicon_dsp_ind {
|
||||
__u16 time __attribute__ ((packed));
|
||||
__u8 norm __attribute__ ((packed));
|
||||
|
@ -171,32 +59,11 @@ typedef struct eicon_dsp_ind {
|
|||
__u32 rxspeed __attribute__ ((packed));
|
||||
} eicon_dsp_ind;
|
||||
|
||||
#define DSP_CONNECTED_NORM_UNSPECIFIED 0
|
||||
#define DSP_CONNECTED_NORM_V21 1
|
||||
#define DSP_CONNECTED_NORM_V23 2
|
||||
#define DSP_CONNECTED_NORM_V22 3
|
||||
#define DSP_CONNECTED_NORM_V22_BIS 4
|
||||
#define DSP_CONNECTED_NORM_V32_BIS 5
|
||||
#define DSP_CONNECTED_NORM_V34 6
|
||||
#define DSP_CONNECTED_NORM_V8 7
|
||||
#define DSP_CONNECTED_NORM_BELL_212A 8
|
||||
#define DSP_CONNECTED_NORM_BELL_103 9
|
||||
#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
|
||||
#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
|
||||
#define DSP_CONNECTED_NORM_V90 12
|
||||
#define DSP_CONNECTED_NORM_V21_CH2 13
|
||||
#define DSP_CONNECTED_NORM_V27_TER 14
|
||||
#define DSP_CONNECTED_NORM_V29 15
|
||||
#define DSP_CONNECTED_NORM_V33 16
|
||||
#define DSP_CONNECTED_NORM_V17 17
|
||||
|
||||
#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
|
||||
#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002
|
||||
#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004
|
||||
#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008
|
||||
#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
|
||||
|
||||
|
||||
#define DSP_UDATA_INDICATION_DISCONNECT 5
|
||||
/*
|
||||
returns:
|
||||
|
@ -210,7 +77,6 @@ returns:
|
|||
#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04
|
||||
#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05
|
||||
|
||||
|
||||
#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6
|
||||
/*
|
||||
returns:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* ISDN lowlevel-module for Eicon active cards.
|
||||
* IDI interface
|
||||
* IDI interface
|
||||
*
|
||||
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
|
@ -11,136 +11,8 @@
|
|||
* capabilities with Diva Server cards.
|
||||
* (dor@deutschemailbox.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.30 2000/02/16 16:08:46 armin
|
||||
* Fixed virtual channel handling of IDI.
|
||||
*
|
||||
* Revision 1.29 2000/01/23 21:21:23 armin
|
||||
* Added new trace capability and some updates.
|
||||
* DIVA Server BRI now supports data for ISDNLOG.
|
||||
*
|
||||
* Revision 1.28 2000/01/20 19:55:34 keil
|
||||
* Add FAX Class 1 support
|
||||
*
|
||||
* Revision 1.27 1999/11/29 13:12:03 armin
|
||||
* Autoconnect on L2_TRANS doesn't work with link_level correctly,
|
||||
* changed back to former mode.
|
||||
*
|
||||
* Revision 1.26 1999/11/25 11:43:27 armin
|
||||
* Fixed statectrl and connect message.
|
||||
* X.75 fix and HDLC/transparent with autoconnect.
|
||||
* Minor cleanup.
|
||||
*
|
||||
* Revision 1.25 1999/11/18 20:30:55 armin
|
||||
* removed old workaround for ISA cards.
|
||||
*
|
||||
* Revision 1.24 1999/10/26 21:15:33 armin
|
||||
* using define for checking phone number len to avoid buffer overflow.
|
||||
*
|
||||
* Revision 1.23 1999/10/11 18:13:25 armin
|
||||
* Added fax capabilities for Eicon Diva Server cards.
|
||||
*
|
||||
* Revision 1.22 1999/10/08 22:09:33 armin
|
||||
* Some fixes of cards interface handling.
|
||||
* Bugfix of NULL pointer occurence.
|
||||
* Changed a few log outputs.
|
||||
*
|
||||
* Revision 1.21 1999/09/26 14:17:53 armin
|
||||
* Improved debug and log via readstat()
|
||||
*
|
||||
* Revision 1.20 1999/09/21 20:35:43 armin
|
||||
* added more error checking.
|
||||
*
|
||||
* Revision 1.19 1999/09/21 20:06:40 armin
|
||||
* Added pointer checks.
|
||||
*
|
||||
* Revision 1.18 1999/09/07 12:48:05 armin
|
||||
* Prepared for sub-address usage.
|
||||
*
|
||||
* Revision 1.17 1999/09/07 12:35:39 armin
|
||||
* Better checking and channel Id handling.
|
||||
*
|
||||
* Revision 1.16 1999/09/04 13:44:19 armin
|
||||
* Fix of V.42 analog Modem negotiation handling.
|
||||
*
|
||||
* Revision 1.15 1999/08/28 21:32:50 armin
|
||||
* Prepared for fax related functions.
|
||||
* Now compilable without errors/warnings.
|
||||
*
|
||||
* Revision 1.14 1999/08/28 20:24:40 armin
|
||||
* Corrected octet 3/3a in CPN/OAD information element.
|
||||
* Thanks to John Simpson <xfl23@dial.pipex.com>
|
||||
*
|
||||
* Revision 1.13 1999/08/22 20:26:44 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.12 1999/08/18 20:16:59 armin
|
||||
* Added XLOG function for all cards.
|
||||
* Bugfix of alloc_skb NULL pointer.
|
||||
*
|
||||
* Revision 1.11 1999/07/25 15:12:03 armin
|
||||
* fix of some debug logs.
|
||||
* enabled ISA-cards option.
|
||||
*
|
||||
* Revision 1.10 1999/07/11 17:16:24 armin
|
||||
* Bugfixes in queue handling.
|
||||
* Added DSP-DTMF decoder functions.
|
||||
* Reorganized ack_handler.
|
||||
*
|
||||
* Revision 1.9 1999/03/29 11:19:42 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.8 1999/03/02 12:37:43 armin
|
||||
* Added some important checks.
|
||||
* Analog Modem with DSP.
|
||||
* Channels will be added to Link-Level after loading firmware.
|
||||
*
|
||||
* Revision 1.7 1999/02/03 18:34:35 armin
|
||||
* Channel selection for outgoing calls w/o CHI.
|
||||
* Added channel # in debug messages.
|
||||
* L2 Transparent should work with 800 byte/packet now.
|
||||
*
|
||||
* Revision 1.6 1999/01/26 07:18:59 armin
|
||||
* Bug with wrong added CPN fixed.
|
||||
*
|
||||
* Revision 1.5 1999/01/24 20:14:11 armin
|
||||
* Changed and added debug stuff.
|
||||
* Better data sending. (still problems with tty's flip buffer)
|
||||
*
|
||||
* Revision 1.4 1999/01/10 18:46:05 armin
|
||||
* Bug with wrong values in HLC fixed.
|
||||
* Bytes to send are counted and limited now.
|
||||
*
|
||||
* Revision 1.3 1999/01/05 14:49:34 armin
|
||||
* Added experimental usage of full BC and HLC for
|
||||
* speech, 3.1kHz audio, fax gr.2/3
|
||||
*
|
||||
* Revision 1.2 1999/01/04 13:19:29 armin
|
||||
* Channel status with listen-request wrong - fixed.
|
||||
*
|
||||
* Revision 1.1 1999/01/01 18:09:41 armin
|
||||
* First checkin of new eicon driver.
|
||||
* DIVA-Server BRI/PCI and PRI/PCI are supported.
|
||||
* Old diehl code is obsolete.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -149,6 +21,7 @@
|
|||
#include "eicon.h"
|
||||
#include "eicon_idi.h"
|
||||
#include "eicon_dsp.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#undef EICON_FULL_SERVICE_OKTETT
|
||||
|
||||
|
@ -156,18 +29,6 @@ char *eicon_idi_revision = "$Revision$";
|
|||
|
||||
eicon_manifbuf *manbuf;
|
||||
|
||||
static char BC_Speech[3] = { 0x80, 0x90, 0xa3 };
|
||||
static char BC_31khz[3] = { 0x90, 0x90, 0xa3 };
|
||||
static char BC_64k[2] = { 0x88, 0x90 };
|
||||
static char BC_video[3] = { 0x91, 0x90, 0xa5 };
|
||||
|
||||
#ifdef EICON_FULL_SERVICE_OKTETT
|
||||
/*
|
||||
static char HLC_telephony[2] = { 0x91, 0x81 };
|
||||
*/
|
||||
static char HLC_faxg3[2] = { 0x91, 0x84 };
|
||||
#endif
|
||||
|
||||
int eicon_idi_manage_assign(eicon_card *card);
|
||||
int eicon_idi_manage_remove(eicon_card *card);
|
||||
int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer);
|
||||
|
@ -197,7 +58,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
|
|||
reqbuf->XBuffer.P[l++] = 0; /* end */
|
||||
reqbuf->Req = ASSIGN;
|
||||
reqbuf->ReqCh = 0;
|
||||
reqbuf->ReqId = 0;
|
||||
reqbuf->ReqId = DSIG_ID;
|
||||
reqbuf->XBuffer.length = l;
|
||||
reqbuf->Reference = 0; /* Sig Entity */
|
||||
}
|
||||
|
@ -209,6 +70,9 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
|
|||
reqbuf->XBuffer.P[l++] = LLC;
|
||||
reqbuf->XBuffer.P[l++] = 2;
|
||||
switch(chan->l2prot) {
|
||||
case ISDN_PROTO_L2_V11096:
|
||||
case ISDN_PROTO_L2_V11019:
|
||||
case ISDN_PROTO_L2_V11038:
|
||||
case ISDN_PROTO_L2_TRANS:
|
||||
reqbuf->XBuffer.P[l++] = 2; /* transparent */
|
||||
break;
|
||||
|
@ -250,7 +114,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
|
|||
reqbuf->XBuffer.P[l++] = 0; /* end */
|
||||
reqbuf->Req = ASSIGN;
|
||||
reqbuf->ReqCh = 0;
|
||||
reqbuf->ReqId = 0x20;
|
||||
reqbuf->ReqId = NL_ID;
|
||||
reqbuf->XBuffer.length = l;
|
||||
reqbuf->Reference = 1; /* Net Entity */
|
||||
}
|
||||
|
@ -269,6 +133,21 @@ idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
idi_put_suspend_req(eicon_REQ *reqbuf, eicon_chan *chan)
|
||||
{
|
||||
reqbuf->Req = SUSPEND;
|
||||
reqbuf->ReqCh = 0;
|
||||
reqbuf->ReqId = 1;
|
||||
reqbuf->XBuffer.P[0] = CAI;
|
||||
reqbuf->XBuffer.P[1] = 1;
|
||||
reqbuf->XBuffer.P[2] = chan->No;
|
||||
reqbuf->XBuffer.P[3] = 0;
|
||||
reqbuf->XBuffer.length = 4;
|
||||
reqbuf->Reference = 0; /* Sig Entity */
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
|
||||
{
|
||||
|
@ -283,7 +162,7 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
|
|||
reqbuf->XBuffer.P[4] = 0;
|
||||
reqbuf->XBuffer.P[5] = 0;
|
||||
reqbuf->XBuffer.P[6] = 32;
|
||||
reqbuf->XBuffer.P[7] = 3;
|
||||
reqbuf->XBuffer.P[7] = 0;
|
||||
switch(chan->l2prot) {
|
||||
case ISDN_PROTO_L2_X75I:
|
||||
case ISDN_PROTO_L2_X75UI:
|
||||
|
@ -379,6 +258,12 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
|
|||
case HANGUP:
|
||||
idi_put_req(reqbuf, HANGUP, 0, 0);
|
||||
break;
|
||||
case SUSPEND:
|
||||
idi_put_suspend_req(reqbuf, chan);
|
||||
break;
|
||||
case RESUME:
|
||||
idi_put_req(reqbuf, RESUME, 0 ,0);
|
||||
break;
|
||||
case REJECT:
|
||||
idi_put_req(reqbuf, REJECT, 0 ,0);
|
||||
break;
|
||||
|
@ -388,17 +273,20 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
|
|||
case CALL_RES:
|
||||
idi_call_res_req(reqbuf, chan);
|
||||
break;
|
||||
case IDI_N_CONNECT|0x700:
|
||||
idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
|
||||
case CALL_HOLD:
|
||||
idi_put_req(reqbuf, CALL_HOLD, 0, 0);
|
||||
break;
|
||||
case IDI_N_CONNECT_ACK|0x700:
|
||||
idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
|
||||
case N_CONNECT|0x700:
|
||||
idi_put_req(reqbuf, N_CONNECT, 1, 0);
|
||||
break;
|
||||
case IDI_N_DISC|0x700:
|
||||
idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
|
||||
case N_CONNECT_ACK|0x700:
|
||||
idi_put_req(reqbuf, N_CONNECT_ACK, 1, 0);
|
||||
break;
|
||||
case IDI_N_DISC_ACK|0x700:
|
||||
idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
|
||||
case N_DISC|0x700:
|
||||
idi_put_req(reqbuf, N_DISC, 1, chan->e.IndCh);
|
||||
break;
|
||||
case N_DISC_ACK|0x700:
|
||||
idi_put_req(reqbuf, N_DISC_ACK, 1, chan->e.IndCh);
|
||||
break;
|
||||
default:
|
||||
eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
|
||||
|
@ -480,7 +368,7 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
|
|||
|
||||
if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
|
||||
(chan->fsm_state == EICON_STATE_WMCONN)) {
|
||||
if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
|
||||
if (chan->e.B2Id) idi_do_req(card, chan, N_DISC, 1);
|
||||
}
|
||||
if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
|
||||
if (chan->fsm_state != EICON_STATE_NULL) {
|
||||
|
@ -495,6 +383,32 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm)
|
||||
{
|
||||
if ((cm->para[0] != 3) || (cm->para[1] != 0))
|
||||
return -1;
|
||||
if (cm->para[2] < 3)
|
||||
return -1;
|
||||
if (cm->para[4] != 0)
|
||||
return -1;
|
||||
switch(cm->para[3]) {
|
||||
case 4: /* Suspend */
|
||||
eicon_log(card, 8, "idi_req: Ch%d: Call Suspend\n", chan->No);
|
||||
if (cm->para[5]) {
|
||||
idi_do_req(card, chan, SUSPEND, 0);
|
||||
} else {
|
||||
idi_do_req(card, chan, CALL_HOLD, 0);
|
||||
}
|
||||
break;
|
||||
case 5: /* Resume */
|
||||
eicon_log(card, 8, "idi_req: Ch%d: Call Resume\n", chan->No);
|
||||
idi_do_req(card, chan, RESUME, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
idi_connect_res(eicon_card *card, eicon_chan *chan)
|
||||
{
|
||||
|
@ -600,7 +514,14 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
|
|||
reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
|
||||
}
|
||||
|
||||
if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
|
||||
if (si2 > 2) {
|
||||
reqbuf->XBuffer.P[l++] = SHIFT|6;
|
||||
reqbuf->XBuffer.P[l++] = SIN;
|
||||
reqbuf->XBuffer.P[l++] = 2;
|
||||
reqbuf->XBuffer.P[l++] = si1;
|
||||
reqbuf->XBuffer.P[l++] = si2;
|
||||
}
|
||||
else if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
|
||||
reqbuf->XBuffer.P[l++] = BC;
|
||||
reqbuf->XBuffer.P[l++] = tmp;
|
||||
for(i=0; i<tmp;i++)
|
||||
|
@ -620,7 +541,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
|
|||
reqbuf->XBuffer.P[l++] = 0;
|
||||
reqbuf->XBuffer.P[l++] = 0;
|
||||
reqbuf->XBuffer.P[l++] = 32;
|
||||
reqbuf->XBuffer.P[l++] = 3;
|
||||
reqbuf->XBuffer.P[l++] = 0;
|
||||
switch(chan->l2prot) {
|
||||
case ISDN_PROTO_L2_X75I:
|
||||
case ISDN_PROTO_L2_X75UI:
|
||||
|
@ -847,7 +768,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
|
|||
}
|
||||
for(i=0; i < wlen; i++)
|
||||
message->llc[i] = buffer[pos++];
|
||||
eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0],
|
||||
eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d ...\n", chan->No, message->llc[0],
|
||||
message->llc[1],message->llc[2],message->llc[3]);
|
||||
break;
|
||||
case HLC:
|
||||
|
@ -857,7 +778,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
|
|||
}
|
||||
for(i=0; i < wlen; i++)
|
||||
message->hlc[i] = buffer[pos++];
|
||||
eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No,
|
||||
eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x ...\n", chan->No,
|
||||
message->hlc[0], message->hlc[1],
|
||||
message->hlc[2], message->hlc[3], message->hlc[4]);
|
||||
break;
|
||||
|
@ -1049,31 +970,55 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
|
|||
}
|
||||
|
||||
void
|
||||
idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2)
|
||||
idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *sin, unsigned char *si1, unsigned char *si2)
|
||||
{
|
||||
si1[0] = 0;
|
||||
si2[0] = 0;
|
||||
if (memcmp(bc, BC_Speech, 3) == 0) { /* Speech */
|
||||
si1[0] = 1;
|
||||
si1[0] = 0;
|
||||
si2[0] = 0;
|
||||
|
||||
switch (bc[0] & 0x7f) {
|
||||
case 0x00: /* Speech */
|
||||
si1[0] = 1;
|
||||
#ifdef EICON_FULL_SERVICE_OKTETT
|
||||
si2[0] = 1;
|
||||
si1[0] = sin[0];
|
||||
si2[0] = sin[1];
|
||||
#endif
|
||||
}
|
||||
if (memcmp(bc, BC_31khz, 3) == 0) { /* 3.1kHz audio */
|
||||
si1[0] = 1;
|
||||
break;
|
||||
case 0x10: /* 3.1 Khz audio */
|
||||
si1[0] = 1;
|
||||
#ifdef EICON_FULL_SERVICE_OKTETT
|
||||
si2[0] = 2;
|
||||
if (memcmp(hlc, HLC_faxg3, 2) == 0) { /* Fax Gr.2/3 */
|
||||
si1[0] = 2;
|
||||
si1[0] = sin[0];
|
||||
si2[0] = sin[1];
|
||||
#endif
|
||||
break;
|
||||
case 0x08: /* Unrestricted digital information */
|
||||
si1[0] = 7;
|
||||
si2[0] = sin[1];
|
||||
break;
|
||||
case 0x09: /* Restricted digital information */
|
||||
si1[0] = 2;
|
||||
break;
|
||||
case 0x11:
|
||||
/* Unrestr. digital information with
|
||||
* tones/announcements ( or 7 kHz audio
|
||||
*/
|
||||
si1[0] = 3;
|
||||
break;
|
||||
case 0x18: /* Video */
|
||||
si1[0] = 4;
|
||||
break;
|
||||
}
|
||||
switch (bc[1] & 0x7f) {
|
||||
case 0x40: /* packed mode */
|
||||
si1[0] = 8;
|
||||
break;
|
||||
case 0x10: /* 64 kbit */
|
||||
case 0x11: /* 2*64 kbit */
|
||||
case 0x13: /* 384 kbit */
|
||||
case 0x15: /* 1536 kbit */
|
||||
case 0x17: /* 1920 kbit */
|
||||
/* moderate = bc[1] & 0x7f; */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (memcmp(bc, BC_64k, 2) == 0) { /* unrestricted 64 kbits */
|
||||
si1[0] = 7;
|
||||
}
|
||||
if (memcmp(bc, BC_video, 3) == 0) { /* video */
|
||||
si1[0] = 4;
|
||||
}
|
||||
}
|
||||
|
||||
/********************* FAX stuff ***************************/
|
||||
|
@ -1213,7 +1158,7 @@ idi_send_edata(eicon_card *card, eicon_chan *chan)
|
|||
|
||||
reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
|
||||
|
||||
reqbuf->Req = IDI_N_EDATA;
|
||||
reqbuf->Req = N_EDATA;
|
||||
reqbuf->ReqCh = chan->e.IndCh;
|
||||
reqbuf->ReqId = 1;
|
||||
|
||||
|
@ -1347,7 +1292,7 @@ idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
|
|||
eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength);
|
||||
break;
|
||||
}
|
||||
idi_send_data(card, chan, 0, skb, 0);
|
||||
idi_send_data(card, chan, 0, skb, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1932,7 +1877,7 @@ idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf
|
|||
OutBuf->Len = 0;
|
||||
OutBuf->Next = OutBuf->Data;
|
||||
|
||||
return(idi_send_data(ccard, chan, 0, skb, 1));
|
||||
return(idi_send_data(ccard, chan, 0, skb, 1, 0));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1977,6 +1922,8 @@ idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
|
|||
|
||||
if (chan->queued + skb->len > 1200)
|
||||
return 0;
|
||||
if (chan->pqueued > 1)
|
||||
return 0;
|
||||
|
||||
InBuf.Data = skb->data;
|
||||
InBuf.Size = skb->len;
|
||||
|
@ -2202,6 +2149,7 @@ idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
|
|||
}
|
||||
if ((chan->fax->code > 1) && (chan->fax->code < 120))
|
||||
chan->fax->code += 120;
|
||||
eicon_log(ccard, 8, "idi_fax: Ch%d: Hangup (code=%d)\n", chan->No, chan->fax->code);
|
||||
chan->fax->r_code = ISDN_TTY_FAX_HNG;
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_FAXIND;
|
||||
|
@ -2243,7 +2191,7 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int
|
|||
|
||||
reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
|
||||
|
||||
reqbuf->Req = IDI_N_UDATA;
|
||||
reqbuf->Req = N_UDATA;
|
||||
reqbuf->ReqCh = chan->e.IndCh;
|
||||
reqbuf->ReqId = 1;
|
||||
|
||||
|
@ -2293,7 +2241,10 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
|
|||
static char *connmsg[] =
|
||||
{"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34",
|
||||
"V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90",
|
||||
"V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"};
|
||||
"V.21 CH2", "V.27ter", "V.29", "V.33", "V.17", "V.32", "K56Flex",
|
||||
"X2", "V.18", "V.18LH", "V.18HL", "V.21LH", "V.21HL",
|
||||
"Bell 103LH", "Bell 103HL", "V.23", "V.23", "EDT 110",
|
||||
"Baudot45", "Baudot47", "Baudot50", "DTMF" };
|
||||
static u_char dtmf_code[] = {
|
||||
'1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'
|
||||
};
|
||||
|
@ -2315,7 +2266,11 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
|
|||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_BCONN;
|
||||
cmd.arg = chan->No;
|
||||
sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
|
||||
if (p->norm > 34) {
|
||||
sprintf(cmd.parm.num, "%d/(%d)", p->speed, p->norm);
|
||||
} else {
|
||||
sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
|
||||
}
|
||||
ccard->interface.statcallb(&cmd);
|
||||
}
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time);
|
||||
|
@ -2437,12 +2392,12 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
while((skb2 = skb_dequeue(&chan->e.X))) {
|
||||
dev_kfree_skb(skb2);
|
||||
}
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
chan->queued = 0;
|
||||
chan->pqueued = 0;
|
||||
chan->waitq = 0;
|
||||
chan->waitpq = 0;
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
if (message.e_cau[0] & 0x7f) {
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.arg = chan->No;
|
||||
|
@ -2452,10 +2407,6 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
ccard->interface.statcallb(&cmd);
|
||||
}
|
||||
chan->cause[0] = 0;
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
if (!chan->e.B2Id)
|
||||
chan->fax = 0;
|
||||
#endif
|
||||
if (((chan->fsm_state == EICON_STATE_ACTIVE) ||
|
||||
(chan->fsm_state == EICON_STATE_WMCONN)) ||
|
||||
((chan->l2prot == ISDN_PROTO_L2_FAX) &&
|
||||
|
@ -2471,6 +2422,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
}
|
||||
#endif
|
||||
chan->statectrl &= ~WAITING_FOR_HANGUP;
|
||||
chan->statectrl &= ~IN_HOLD;
|
||||
if (chan->statectrl & HAVE_CONN_REQ) {
|
||||
eicon_log(ccard, 32, "idi_req: Ch%d: queueing delayed conn_req\n", chan->No);
|
||||
chan->statectrl &= ~HAVE_CONN_REQ;
|
||||
|
@ -2488,6 +2440,9 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
cmd.command = ISDN_STAT_DHUP;
|
||||
ccard->interface.statcallb(&cmd);
|
||||
eicon_idi_listen_req(ccard, chan);
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
chan->fax = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2500,7 +2455,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
chan->fsm_state = EICON_STATE_ICALL;
|
||||
idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2);
|
||||
idi_bc2si(message.bc, message.hlc, message.sin, &chan->si1, &chan->si2);
|
||||
strcpy(chan->cpn, message.cpn + 1);
|
||||
strcpy(chan->oad, message.oad);
|
||||
strcpy(chan->dsa, message.dsa);
|
||||
|
@ -2548,15 +2503,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
break;
|
||||
case 3: /* incomplete number */
|
||||
eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
|
||||
switch(ccard->type) {
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
case EICON_CTYPE_S2M:
|
||||
/* TODO (other protocols) */
|
||||
chan->fsm_state = EICON_STATE_ICALLW;
|
||||
break;
|
||||
default:
|
||||
idi_do_req(ccard, chan, HANGUP, 0);
|
||||
}
|
||||
chan->fsm_state = EICON_STATE_ICALLW;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -2586,46 +2533,68 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
case ISDN_PROTO_L2_MODEM:
|
||||
/* do nothing, wait for connect */
|
||||
break;
|
||||
case ISDN_PROTO_L2_V11096:
|
||||
case ISDN_PROTO_L2_V11019:
|
||||
case ISDN_PROTO_L2_V11038:
|
||||
case ISDN_PROTO_L2_TRANS:
|
||||
idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
|
||||
idi_do_req(ccard, chan, N_CONNECT, 1);
|
||||
break;
|
||||
default:
|
||||
default:;
|
||||
/* On most incoming calls we use automatic connect */
|
||||
/* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
|
||||
/* idi_do_req(ccard, chan, N_CONNECT, 1); */
|
||||
}
|
||||
} else
|
||||
idi_hangup(ccard, chan);
|
||||
} else {
|
||||
if (chan->fsm_state != EICON_STATE_ACTIVE)
|
||||
idi_hangup(ccard, chan);
|
||||
}
|
||||
break;
|
||||
case CALL_CON:
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
|
||||
if (chan->fsm_state == EICON_STATE_OCALL) {
|
||||
chan->fsm_state = EICON_STATE_OBWAIT;
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_DCONN;
|
||||
cmd.arg = chan->No;
|
||||
ccard->interface.statcallb(&cmd);
|
||||
|
||||
/* check if old NetID has been removed */
|
||||
if (chan->e.B2Id) {
|
||||
eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n",
|
||||
chan->No, chan->e.B2Id);
|
||||
idi_do_req(ccard, chan, REMOVE, 1);
|
||||
}
|
||||
|
||||
idi_do_req(ccard, chan, ASSIGN, 1);
|
||||
idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
|
||||
if (chan->fax)
|
||||
if (chan->fax) {
|
||||
chan->fax->phase = ISDN_FAX_PHASE_A;
|
||||
} else {
|
||||
eicon_log(ccard, 1, "idi_ind: Call_Con with NULL fax struct, ERROR\n");
|
||||
idi_hangup(ccard, chan);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
chan->fsm_state = EICON_STATE_OBWAIT;
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_DCONN;
|
||||
cmd.arg = chan->No;
|
||||
ccard->interface.statcallb(&cmd);
|
||||
|
||||
idi_do_req(ccard, chan, ASSIGN, 1);
|
||||
idi_do_req(ccard, chan, N_CONNECT, 1);
|
||||
} else
|
||||
idi_hangup(ccard, chan);
|
||||
idi_hangup(ccard, chan);
|
||||
break;
|
||||
case AOC_IND:
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No);
|
||||
break;
|
||||
case CALL_HOLD_ACK:
|
||||
chan->statectrl |= IN_HOLD;
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: Call Hold Ack\n", chan->No);
|
||||
break;
|
||||
case SUSPEND_REJ:
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Rejected\n", chan->No);
|
||||
break;
|
||||
case SUSPEND:
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Ack\n", chan->No);
|
||||
break;
|
||||
case RESUME:
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: Resume Ack\n", chan->No);
|
||||
break;
|
||||
default:
|
||||
eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
|
||||
}
|
||||
|
@ -2644,7 +2613,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
}
|
||||
else
|
||||
switch(ind->Ind) {
|
||||
case IDI_N_CONNECT_ACK:
|
||||
case N_CONNECT_ACK:
|
||||
eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
|
||||
if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
|
||||
chan->fsm_state = EICON_STATE_WMCONN;
|
||||
|
@ -2665,7 +2634,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
else {
|
||||
eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
|
||||
eicon_log(ccard, 1, "idi_ind: N_Connect_Ack with NULL fax struct, ERROR\n");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -2677,10 +2646,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
strcpy(cmd.parm.num, "64000");
|
||||
ccard->interface.statcallb(&cmd);
|
||||
break;
|
||||
case IDI_N_CONNECT:
|
||||
case N_CONNECT:
|
||||
eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
|
||||
chan->e.IndCh = ind->IndCh;
|
||||
if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
|
||||
if (chan->e.B2Id) idi_do_req(ccard, chan, N_CONNECT_ACK, 1);
|
||||
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
|
||||
break;
|
||||
}
|
||||
|
@ -2695,43 +2664,47 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
strcpy(cmd.parm.num, "64000");
|
||||
ccard->interface.statcallb(&cmd);
|
||||
break;
|
||||
case IDI_N_DISC:
|
||||
eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No);
|
||||
case N_DISC:
|
||||
eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc\n", chan->No);
|
||||
if (chan->e.B2Id) {
|
||||
while((skb2 = skb_dequeue(&chan->e.X))) {
|
||||
dev_kfree_skb(skb2);
|
||||
}
|
||||
idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
|
||||
idi_do_req(ccard, chan, N_DISC_ACK, 1);
|
||||
idi_do_req(ccard, chan, REMOVE, 1);
|
||||
}
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
|
||||
if ((chan->l2prot == ISDN_PROTO_L2_FAX) && (chan->fax)){
|
||||
idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
|
||||
idi_fax_hangup(ccard, chan);
|
||||
}
|
||||
#endif
|
||||
chan->e.IndCh = 0;
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
chan->queued = 0;
|
||||
chan->pqueued = 0;
|
||||
chan->waitq = 0;
|
||||
chan->waitpq = 0;
|
||||
restore_flags(flags);
|
||||
idi_do_req(ccard, chan, HANGUP, 0);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
if (!(chan->statectrl & IN_HOLD)) {
|
||||
idi_do_req(ccard, chan, HANGUP, 0);
|
||||
}
|
||||
if (chan->fsm_state == EICON_STATE_ACTIVE) {
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_BHUP;
|
||||
cmd.arg = chan->No;
|
||||
ccard->interface.statcallb(&cmd);
|
||||
chan->fsm_state = EICON_STATE_NULL;
|
||||
chan->statectrl |= WAITING_FOR_HANGUP;
|
||||
if (!(chan->statectrl & IN_HOLD)) {
|
||||
chan->statectrl |= WAITING_FOR_HANGUP;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
chan->fax = 0;
|
||||
#endif
|
||||
break;
|
||||
case IDI_N_DISC_ACK:
|
||||
eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
|
||||
case N_DISC_ACK:
|
||||
eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc_Ack\n", chan->No);
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
|
||||
idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
|
||||
|
@ -2739,10 +2712,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
}
|
||||
#endif
|
||||
break;
|
||||
case IDI_N_DATA_ACK:
|
||||
eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
|
||||
case N_DATA_ACK:
|
||||
eicon_log(ccard, 128, "idi_ind: Ch%d: N_Data_Ack\n", chan->No);
|
||||
break;
|
||||
case IDI_N_DATA:
|
||||
case N_DATA:
|
||||
skb_pull(skb, sizeof(eicon_IND) - 1);
|
||||
eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
|
||||
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
|
||||
|
@ -2754,11 +2727,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
|
|||
free_buff = 0;
|
||||
}
|
||||
break;
|
||||
case IDI_N_UDATA:
|
||||
case N_UDATA:
|
||||
idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
|
||||
break;
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
case IDI_N_EDATA:
|
||||
case N_EDATA:
|
||||
idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
|
||||
break;
|
||||
#endif
|
||||
|
@ -2778,6 +2751,8 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
|
|||
{
|
||||
ulong flags;
|
||||
isdn_ctrl cmd;
|
||||
int tqueued = 0;
|
||||
int twaitpq = 0;
|
||||
|
||||
if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
|
||||
/* I dont know why this happens, should not ! */
|
||||
|
@ -2801,16 +2776,15 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
|
|||
eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
|
||||
ack->Reference, chan->e.ref);
|
||||
}
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
ccard->IdTable[ack->RcId] = NULL;
|
||||
eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
|
||||
ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
|
||||
if (!chan->e.ReqCh)
|
||||
chan->e.D3Id = 0;
|
||||
else
|
||||
chan->e.B2Id = 0;
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
|
||||
ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2821,25 +2795,21 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
|
|||
} else {
|
||||
/* Network layer */
|
||||
switch(chan->e.Req & 0x0f) {
|
||||
case IDI_N_CONNECT:
|
||||
case N_CONNECT:
|
||||
chan->e.IndCh = ack->RcCh;
|
||||
eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
|
||||
ack->RcId, ack->RcCh, ack->Reference);
|
||||
break;
|
||||
case IDI_N_MDATA:
|
||||
case IDI_N_DATA:
|
||||
if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
|
||||
if (chan->queued) {
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_BSENT;
|
||||
cmd.arg = chan->No;
|
||||
cmd.parm.length = chan->waitpq;
|
||||
ccard->interface.statcallb(&cmd);
|
||||
}
|
||||
save_flags(flags);
|
||||
cli();
|
||||
case N_MDATA:
|
||||
case N_DATA:
|
||||
tqueued = chan->queued;
|
||||
twaitpq = chan->waitpq;
|
||||
if ((chan->e.Req & 0x0f) == N_DATA) {
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
chan->waitpq = 0;
|
||||
restore_flags(flags);
|
||||
if(chan->pqueued)
|
||||
chan->pqueued--;
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
|
||||
if (((chan->queued - chan->waitq) < 1) &&
|
||||
|
@ -2859,11 +2829,17 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
chan->queued -= chan->waitq;
|
||||
if (chan->queued < 0) chan->queued = 0;
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
if (((chan->e.Req & 0x0f) == N_DATA) && (tqueued)) {
|
||||
cmd.driver = ccard->myid;
|
||||
cmd.command = ISDN_STAT_BSENT;
|
||||
cmd.arg = chan->No;
|
||||
cmd.parm.length = twaitpq;
|
||||
ccard->interface.statcallb(&cmd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
|
||||
|
@ -2889,11 +2865,10 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
|
|||
return;
|
||||
}
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
if ((chan = ccard->IdTable[ack->RcId]) != NULL)
|
||||
dCh = chan->No;
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
|
||||
switch (ack->Rc) {
|
||||
case OK_FC:
|
||||
|
@ -2921,8 +2896,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
|
|||
eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
|
||||
chan->No, chan->e.D3Id, chan->e.B2Id);
|
||||
}
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
for(j = 0; j < ccard->nchannels + 1; j++) {
|
||||
if ((ccard->bch[j].e.ref == ack->Reference) &&
|
||||
(ccard->bch[j].e.Req == ASSIGN)) {
|
||||
|
@ -2932,12 +2906,12 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
|
|||
ccard->bch[j].e.B2Id = ack->RcId;
|
||||
ccard->IdTable[ack->RcId] = &ccard->bch[j];
|
||||
chan = &ccard->bch[j];
|
||||
eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j,
|
||||
ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
|
||||
break;
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j,
|
||||
ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
|
||||
if (j > ccard->nchannels) {
|
||||
eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n",
|
||||
ack->Reference, ack->RcId);
|
||||
|
@ -2948,6 +2922,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
|
|||
case UNKNOWN_COMMAND:
|
||||
case WRONG_COMMAND:
|
||||
case WRONG_ID:
|
||||
case ADAPTER_DEAD:
|
||||
case WRONG_CH:
|
||||
case UNKNOWN_IE:
|
||||
case WRONG_IE:
|
||||
|
@ -2980,19 +2955,18 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
|
|||
ccard->interface.statcallb(&cmd);
|
||||
}
|
||||
}
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
if (chan) {
|
||||
chan->e.ref = 0;
|
||||
chan->e.busy = 0;
|
||||
}
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
dev_kfree_skb(skb);
|
||||
eicon_schedule_tx(ccard);
|
||||
}
|
||||
|
||||
int
|
||||
idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que)
|
||||
idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk)
|
||||
{
|
||||
struct sk_buff *xmit_skb;
|
||||
struct sk_buff *skb2;
|
||||
|
@ -3016,13 +2990,14 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
|
|||
return -1;
|
||||
if (!len)
|
||||
return 0;
|
||||
if (chan->queued + len > EICON_MAX_QUEUE)
|
||||
|
||||
if ((chk) && (chan->pqueued > 1))
|
||||
return 0;
|
||||
|
||||
eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len);
|
||||
eicon_log(card, 128, "idi_snd: Ch%d: %d bytes (Pqueue=%d)\n",
|
||||
chan->No, len, chan->pqueued);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
while(offset < len) {
|
||||
|
||||
plen = ((len - offset) > 270) ? 270 : len - offset;
|
||||
|
@ -3031,7 +3006,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
|
|||
skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
|
||||
|
||||
if ((!xmit_skb) || (!skb2)) {
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
|
||||
if (xmit_skb)
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -3044,12 +3019,11 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
|
|||
chan2->ptr = chan;
|
||||
|
||||
reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
|
||||
if (((len - offset) > 270) &&
|
||||
(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
|
||||
reqbuf->Req = IDI_N_MDATA;
|
||||
if ((len - offset) > 270) {
|
||||
reqbuf->Req = N_MDATA;
|
||||
} else {
|
||||
reqbuf->Req = IDI_N_DATA;
|
||||
if (ack) reqbuf->Req |= N_D_BIT;
|
||||
reqbuf->Req = N_DATA;
|
||||
/* if (ack) reqbuf->Req |= N_D_BIT; */
|
||||
}
|
||||
reqbuf->ReqCh = chan->e.IndCh;
|
||||
reqbuf->ReqId = 1;
|
||||
|
@ -3062,9 +3036,11 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
|
|||
|
||||
offset += plen;
|
||||
}
|
||||
if (que)
|
||||
if (que) {
|
||||
chan->queued += len;
|
||||
restore_flags(flags);
|
||||
chan->pqueued++;
|
||||
}
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
eicon_schedule_tx(card);
|
||||
dev_kfree_skb(skb);
|
||||
return len;
|
||||
|
@ -3102,7 +3078,7 @@ eicon_idi_manage_assign(eicon_card *card)
|
|||
reqbuf->XBuffer.P[0] = 0;
|
||||
reqbuf->Req = ASSIGN;
|
||||
reqbuf->ReqCh = 0;
|
||||
reqbuf->ReqId = 0xe0;
|
||||
reqbuf->ReqId = MAN_ID;
|
||||
reqbuf->XBuffer.length = 1;
|
||||
reqbuf->Reference = 2; /* Man Entity */
|
||||
|
||||
|
@ -3180,8 +3156,8 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
|
|||
return(ret);
|
||||
}
|
||||
|
||||
timeout = jiffies + 50;
|
||||
while (timeout > jiffies) {
|
||||
timeout = jiffies + HZ / 2;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (chan->e.B2Id) break;
|
||||
SLEEP(10);
|
||||
}
|
||||
|
@ -3228,7 +3204,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
|
|||
reqbuf->XBuffer.P[1] = manbuf->length[0] + 1;
|
||||
|
||||
reqbuf->XBuffer.P[l++] = 0;
|
||||
reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */
|
||||
reqbuf->Req = (manbuf->count) ? manbuf->count : MAN_READ;
|
||||
reqbuf->ReqCh = 0;
|
||||
reqbuf->ReqId = 1;
|
||||
reqbuf->XBuffer.length = l;
|
||||
|
@ -3242,8 +3218,8 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
|
|||
|
||||
eicon_schedule_tx(card);
|
||||
|
||||
timeout = jiffies + 50;
|
||||
while (timeout > jiffies) {
|
||||
timeout = jiffies + HZ / 2;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (chan->fsm_state) break;
|
||||
SLEEP(10);
|
||||
}
|
||||
|
|
|
@ -6,178 +6,32 @@
|
|||
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.8 1999/11/25 11:43:27 armin
|
||||
* Fixed statectrl and connect message.
|
||||
* X.75 fix and HDLC/transparent with autoconnect.
|
||||
* Minor cleanup.
|
||||
*
|
||||
* Revision 1.7 1999/08/22 20:26:46 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.6 1999/07/25 15:12:04 armin
|
||||
* fix of some debug logs.
|
||||
* enabled ISA-cards option.
|
||||
*
|
||||
* Revision 1.5 1999/07/11 17:16:26 armin
|
||||
* Bugfixes in queue handling.
|
||||
* Added DSP-DTMF decoder functions.
|
||||
* Reorganized ack_handler.
|
||||
*
|
||||
* Revision 1.4 1999/03/29 11:19:44 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.3 1999/03/02 12:37:45 armin
|
||||
* Added some important checks.
|
||||
* Analog Modem with DSP.
|
||||
* Channels will be added to Link-Level after loading firmware.
|
||||
*
|
||||
* Revision 1.2 1999/01/24 20:14:18 armin
|
||||
* Changed and added debug stuff.
|
||||
* Better data sending. (still problems with tty's flip buffer)
|
||||
*
|
||||
* Revision 1.1 1999/01/01 18:09:42 armin
|
||||
* First checkin of new eicon driver.
|
||||
* DIVA-Server BRI/PCI and PRI/PCI are supported.
|
||||
* Old diehl code is obsolete.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IDI_H
|
||||
#define IDI_H
|
||||
#ifndef E_IDI_H
|
||||
#define E_IDI_H
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#define ASSIGN 0x01
|
||||
#define REMOVE 0xff
|
||||
|
||||
#define CALL_REQ 1 /* call request */
|
||||
#define CALL_CON 1 /* call confirmation */
|
||||
#define CALL_IND 2 /* incoming call connected */
|
||||
#define LISTEN_REQ 2 /* listen request */
|
||||
#define HANGUP 3 /* hangup request/indication */
|
||||
#define SUSPEND 4 /* call suspend request/confirm */
|
||||
#define RESUME 5 /* call resume request/confirm */
|
||||
#define SUSPEND_REJ 6 /* suspend rejected indication */
|
||||
#define USER_DATA 8 /* user data for user to user signaling */
|
||||
#define CONGESTION 9 /* network congestion indication */
|
||||
#define INDICATE_REQ 10 /* request to indicate an incoming call */
|
||||
#define INDICATE_IND 10 /* indicates that there is an incoming call */
|
||||
#define CALL_RES 11 /* accept an incoming call */
|
||||
#define CALL_ALERT 12 /* send ALERT for incoming call */
|
||||
#define INFO_REQ 13 /* INFO request */
|
||||
#define INFO_IND 13 /* INFO indication */
|
||||
#define REJECT 14 /* reject an incoming call */
|
||||
#define RESOURCES 15 /* reserve B-Channel hardware resources */
|
||||
#define TEL_CTRL 16 /* Telephone control request/indication */
|
||||
#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
|
||||
#define FAC_REG_REQ 18 /* connection idependent fac registration */
|
||||
#define FAC_REG_ACK 19 /* fac registration acknowledge */
|
||||
#define FAC_REG_REJ 20 /* fac registration reject */
|
||||
#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
|
||||
#define AOC_IND 26/* Advice of Charge */
|
||||
#undef N_DATA
|
||||
#undef ID_MASK
|
||||
|
||||
#define IDI_N_MDATA (0x01)
|
||||
#define IDI_N_CONNECT (0x02)
|
||||
#define IDI_N_CONNECT_ACK (0x03)
|
||||
#define IDI_N_DISC (0x04)
|
||||
#define IDI_N_DISC_ACK (0x05)
|
||||
#define IDI_N_RESET (0x06)
|
||||
#define IDI_N_RESET_ACK (0x07)
|
||||
#define IDI_N_DATA (0x08)
|
||||
#define IDI_N_EDATA (0x09)
|
||||
#define IDI_N_UDATA (0x0a)
|
||||
#define IDI_N_BDATA (0x0b)
|
||||
#define IDI_N_DATA_ACK (0x0c)
|
||||
#define IDI_N_EDATA_ACK (0x0d)
|
||||
#include "pc.h"
|
||||
|
||||
#define N_Q_BIT 0x10 /* Q-bit for req/ind */
|
||||
#define N_M_BIT 0x20 /* M-bit for req/ind */
|
||||
#define N_D_BIT 0x40 /* D-bit for req/ind */
|
||||
#define AOC_IND 26 /* Advice of Charge */
|
||||
#define PI 0x1e /* Progress Indicator */
|
||||
#define NI 0x27 /* Notification Indicator */
|
||||
|
||||
|
||||
#define SHIFT 0x90 /* codeset shift */
|
||||
#define MORE 0xa0 /* more data */
|
||||
#define CL 0xb0 /* congestion level */
|
||||
|
||||
/* codeset 0 */
|
||||
|
||||
#define BC 0x04 /* Bearer Capability */
|
||||
#define CAU 0x08 /* cause */
|
||||
#define CAD 0x0c /* Connected address */
|
||||
#define CAI 0x10 /* call identity */
|
||||
#define CHI 0x18 /* channel identification */
|
||||
#define LLI 0x19 /* logical link id */
|
||||
#define CHA 0x1a /* charge advice */
|
||||
#define FTY 0x1c
|
||||
#define PI 0x1e /* Progress Indicator */
|
||||
#define NI 0x27 /* Notification Indicator */
|
||||
#define DT 0x29 /* ETSI date/time */
|
||||
#define KEY 0x2c /* keypad information element */
|
||||
#define DSP 0x28 /* display */
|
||||
#define OAD 0x6c /* origination address */
|
||||
#define OSA 0x6d /* origination sub-address */
|
||||
#define CPN 0x70 /* called party number */
|
||||
#define DSA 0x71 /* destination sub-address */
|
||||
#define RDN 0x74 /* redirecting number */
|
||||
#define LLC 0x7c /* low layer compatibility */
|
||||
#define HLC 0x7d /* high layer compatibility */
|
||||
#define UUI 0x7e /* user user information */
|
||||
#define ESC 0x7f /* escape extension */
|
||||
|
||||
#define DLC 0x20 /* data link layer configuration */
|
||||
#define NLC 0x21 /* network layer configuration */
|
||||
|
||||
/* codeset 6 */
|
||||
|
||||
#define SIN 0x01 /* service indicator */
|
||||
#define CIF 0x02 /* charging information */
|
||||
#define DATE 0x03 /* date */
|
||||
#define CPS 0x07 /* called party status */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* return code coding */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define UNKNOWN_COMMAND 0x01 /* unknown command */
|
||||
#define WRONG_COMMAND 0x02 /* wrong command */
|
||||
#define WRONG_ID 0x03 /* unknown task/entity id */
|
||||
#define WRONG_CH 0x04 /* wrong task/entity id */
|
||||
#define UNKNOWN_IE 0x05 /* unknown information el. */
|
||||
#define WRONG_IE 0x06 /* wrong information el. */
|
||||
#define OUT_OF_RESOURCES 0x07 /* card out of res. */
|
||||
#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
|
||||
#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
|
||||
#define ASSIGN_OK 0xef /* ASSIGN OK */
|
||||
#define OK_FC 0xfc /* Flow-Control RC */
|
||||
#define READY_INT 0xfd /* Ready interrupt */
|
||||
#define TIMER_INT 0xfe /* timer interrupt */
|
||||
#define OK 0xff /* command accepted */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
#define CALL_HOLD 0x22
|
||||
#define CALL_HOLD_ACK 0x24
|
||||
|
||||
/* defines for statectrl */
|
||||
#define WAITING_FOR_HANGUP 0x01
|
||||
#define HAVE_CONN_REQ 0x02
|
||||
#define IN_HOLD 0x04
|
||||
|
||||
typedef struct {
|
||||
char cpn[32];
|
||||
|
@ -237,26 +91,6 @@ typedef struct {
|
|||
eicon_PBUFFER RBuffer;
|
||||
} eicon_IND;
|
||||
|
||||
typedef struct {
|
||||
__u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */
|
||||
__u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */
|
||||
__u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */
|
||||
__u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */
|
||||
__u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */
|
||||
__u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */
|
||||
__u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */
|
||||
__u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */
|
||||
__u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */
|
||||
__u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */
|
||||
__u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */
|
||||
__u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */
|
||||
__u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */
|
||||
__u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */
|
||||
__u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */
|
||||
__u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */
|
||||
__u8 B[1]; /* buffer space for Req,Ind and Rc */
|
||||
} eicon_pr_ram;
|
||||
|
||||
typedef struct {
|
||||
__u8 *Data;
|
||||
unsigned int Size;
|
||||
|
@ -274,8 +108,9 @@ extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
|
|||
extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb);
|
||||
extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb);
|
||||
extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb);
|
||||
extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que);
|
||||
extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk);
|
||||
extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value);
|
||||
extern int capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm);
|
||||
#ifdef CONFIG_ISDN_TTY_FAX
|
||||
extern void idi_fax_cmd(eicon_card *card, eicon_chan *chan);
|
||||
extern int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb);
|
||||
|
|
|
@ -6,65 +6,17 @@
|
|||
* Copyright 1999,2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* Thanks to Eicon Technology GmbH & Co. oHG for
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* Thanks to Eicon Networks for
|
||||
* documents, informations and hardware.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 1999/11/18 20:55:25 armin
|
||||
* Ready_Int fix of ISA cards.
|
||||
*
|
||||
* Revision 1.8 1999/10/08 22:09:34 armin
|
||||
* Some fixes of cards interface handling.
|
||||
* Bugfix of NULL pointer occurence.
|
||||
* Changed a few log outputs.
|
||||
*
|
||||
* Revision 1.7 1999/09/26 14:17:53 armin
|
||||
* Improved debug and log via readstat()
|
||||
*
|
||||
* Revision 1.6 1999/09/21 20:35:43 armin
|
||||
* added more error checking.
|
||||
*
|
||||
* Revision 1.5 1999/08/31 11:20:11 paul
|
||||
* various spelling corrections (new checksums may be needed, Karsten!)
|
||||
*
|
||||
* Revision 1.4 1999/08/22 20:26:47 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.3 1999/08/18 20:17:01 armin
|
||||
* Added XLOG function for all cards.
|
||||
* Bugfix of alloc_skb NULL pointer.
|
||||
*
|
||||
* Revision 1.2 1999/07/25 15:12:05 armin
|
||||
* fix of some debug logs.
|
||||
* enabled ISA-cards option.
|
||||
*
|
||||
* Revision 1.1 1999/03/29 11:19:45 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/config.h>
|
||||
#include "eicon.h"
|
||||
#include "uxio.h"
|
||||
|
||||
void
|
||||
eicon_io_rcv_dispatch(eicon_card *ccard) {
|
||||
|
@ -81,12 +33,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
|
|||
while((skb = skb_dequeue(&ccard->rcvq))) {
|
||||
ind = (eicon_IND *)skb->data;
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
if (DebugVar & 1) {
|
||||
switch(ind->Ind) {
|
||||
case IDI_N_DISC_ACK:
|
||||
case N_DISC_ACK:
|
||||
/* doesn't matter if this happens */
|
||||
break;
|
||||
default:
|
||||
|
@ -95,11 +47,10 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
|
|||
ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
|
||||
}
|
||||
}
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
|
||||
if (chan->e.complete) { /* check for rec-buffer chaining */
|
||||
if (ind->MLength == ind->RBuffer.length) {
|
||||
|
@ -115,12 +66,9 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if (!(skb2 = skb_dequeue(&chan->e.R))) {
|
||||
chan->e.complete = 1;
|
||||
eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
@ -129,7 +77,6 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
|
|||
GFP_ATOMIC);
|
||||
if (!skb_new) {
|
||||
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb(skb2);
|
||||
continue;
|
||||
|
@ -148,14 +95,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
|
|||
dev_kfree_skb(skb2);
|
||||
if (ind->MLength == ind->RBuffer.length) {
|
||||
chan->e.complete = 2;
|
||||
restore_flags(flags);
|
||||
idi_handle_ind(ccard, skb_new);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
chan->e.complete = 0;
|
||||
skb_queue_tail(&chan->e.R, skb_new);
|
||||
restore_flags(flags);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -177,242 +122,120 @@ eicon_io_ack_dispatch(eicon_card *ccard) {
|
|||
|
||||
|
||||
/*
|
||||
* IO-Functions for different card-types
|
||||
* IO-Functions for ISA cards
|
||||
*/
|
||||
|
||||
u8 ram_inb(eicon_card *card, void *adr) {
|
||||
eicon_pci_card *pcard;
|
||||
eicon_isa_card *icard;
|
||||
u32 addr = (u32) adr;
|
||||
|
||||
pcard = &card->hwif.pci;
|
||||
icard = &card->hwif.isa;
|
||||
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
|
||||
return(inb((u16)pcard->PCIreg + M_DATA));
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
case EICON_CTYPE_S2M:
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
return(readb(addr));
|
||||
}
|
||||
return(0);
|
||||
return(readb(addr));
|
||||
}
|
||||
|
||||
u16 ram_inw(eicon_card *card, void *adr) {
|
||||
eicon_pci_card *pcard;
|
||||
eicon_isa_card *icard;
|
||||
u32 addr = (u32) adr;
|
||||
|
||||
pcard = &card->hwif.pci;
|
||||
icard = &card->hwif.isa;
|
||||
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
|
||||
return(inw((u16)pcard->PCIreg + M_DATA));
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
case EICON_CTYPE_S2M:
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
return(readw(addr));
|
||||
}
|
||||
return(0);
|
||||
return(readw(addr));
|
||||
}
|
||||
|
||||
void ram_outb(eicon_card *card, void *adr, u8 data) {
|
||||
eicon_pci_card *pcard;
|
||||
eicon_isa_card *icard;
|
||||
u32 addr = (u32) adr;
|
||||
|
||||
pcard = &card->hwif.pci;
|
||||
icard = &card->hwif.isa;
|
||||
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
|
||||
outb((u8)data, (u16)pcard->PCIreg + M_DATA);
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
case EICON_CTYPE_S2M:
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
writeb(data, addr);
|
||||
break;
|
||||
}
|
||||
writeb(data, addr);
|
||||
}
|
||||
|
||||
void ram_outw(eicon_card *card, void *adr , u16 data) {
|
||||
eicon_pci_card *pcard;
|
||||
eicon_isa_card *icard;
|
||||
u32 addr = (u32) adr;
|
||||
|
||||
pcard = &card->hwif.pci;
|
||||
icard = &card->hwif.isa;
|
||||
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
|
||||
outw((u16)data, (u16)pcard->PCIreg + M_DATA);
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
case EICON_CTYPE_S2M:
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
writew(data, addr);
|
||||
break;
|
||||
}
|
||||
writew(data, addr);
|
||||
}
|
||||
|
||||
void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) {
|
||||
int i;
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
for(i = 0; i < len; i++) {
|
||||
writeb(ram_inb(card, adr + i), adrto + i);
|
||||
}
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
memcpy(adrto, adr, len);
|
||||
break;
|
||||
case EICON_CTYPE_S2M:
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
memcpy_fromio(adrto, adr, len);
|
||||
break;
|
||||
}
|
||||
memcpy_fromio(adrto, adr, len);
|
||||
}
|
||||
|
||||
void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {
|
||||
int i;
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
for(i = 0; i < len; i++) {
|
||||
ram_outb(card, adrto + i, readb(adr + i));
|
||||
}
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
memcpy(adrto, adr, len);
|
||||
break;
|
||||
case EICON_CTYPE_S2M:
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
memcpy_toio(adrto, adr, len);
|
||||
break;
|
||||
}
|
||||
memcpy_toio(adrto, adr, len);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_PCI
|
||||
/*
|
||||
* XLOG
|
||||
* IDI-Callback function
|
||||
*/
|
||||
int
|
||||
eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq)
|
||||
void
|
||||
eicon_idi_callback(ENTITY *de)
|
||||
{
|
||||
int timeout, i;
|
||||
int divas_shared_offset = 0;
|
||||
eicon_card *ccard = (eicon_card *)de->R;
|
||||
struct sk_buff *skb;
|
||||
eicon_RC *ack;
|
||||
eicon_IND *ind;
|
||||
int len = 0;
|
||||
int stype = 0;
|
||||
__u32 time = 0;
|
||||
mi_pc_maint_t *pcm = &xlogreq->pcm;
|
||||
eicon_pci_card *pci_card = &card->hwif.pci;
|
||||
eicon_isa_card *isa_card = &card->hwif.isa;
|
||||
eicon_pr_ram *prram = 0;
|
||||
char *ram;
|
||||
|
||||
switch(card->type) {
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
ram = (char *)pci_card->PCIram;
|
||||
prram = (eicon_pr_ram *)ram;
|
||||
divas_shared_offset = DIVAS_SHARED_OFFSET;
|
||||
len = sizeof(mi_pc_maint_t);
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
prram = 0;
|
||||
divas_shared_offset = 0;
|
||||
len = sizeof(mi_pc_maint_t);
|
||||
break;
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
case EICON_CTYPE_QUADRO:
|
||||
case EICON_CTYPE_S2M:
|
||||
prram = (eicon_pr_ram *)isa_card->shmem;
|
||||
divas_shared_offset = 0xfb80;
|
||||
len = sizeof(mi_pc_maint_t) - 78;
|
||||
stype = 1;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
if (de->complete == 255) {
|
||||
/* Return Code */
|
||||
skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
|
||||
} else {
|
||||
ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
|
||||
ack->Rc = de->Rc;
|
||||
if (de->Rc == ASSIGN_OK) {
|
||||
ack->RcId = de->Id;
|
||||
de->user[1] = de->Id;
|
||||
} else {
|
||||
ack->RcId = de->user[1];
|
||||
}
|
||||
ack->RcCh = de->RcCh;
|
||||
ack->Reference = de->user[0];
|
||||
skb_queue_tail(&ccard->rackq, skb);
|
||||
eicon_schedule_ack(ccard);
|
||||
eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",
|
||||
de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);
|
||||
}
|
||||
} else {
|
||||
/* Indication */
|
||||
if (de->complete) {
|
||||
len = de->RLength;
|
||||
} else {
|
||||
len = 270;
|
||||
if (de->RLength <= 270)
|
||||
eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");
|
||||
}
|
||||
skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
|
||||
} else {
|
||||
ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
|
||||
ind->Ind = de->Ind;
|
||||
ind->IndId = de->user[1];
|
||||
ind->IndCh = de->IndCh;
|
||||
ind->MInd = de->Ind;
|
||||
ind->RBuffer.length = len;
|
||||
ind->MLength = de->RLength;
|
||||
memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);
|
||||
skb_queue_tail(&ccard->rcvq, skb);
|
||||
eicon_schedule_rx(ccard);
|
||||
eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",
|
||||
de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&(xlogreq->pcm), 0, sizeof(mi_pc_maint_t));
|
||||
|
||||
xlogreq->pcm.rc = 0;
|
||||
xlogreq->pcm.req = 1; /* DO_LOG */
|
||||
|
||||
ram = ((char *)prram) + MIPS_MAINT_OFFS - divas_shared_offset;
|
||||
|
||||
ram_outb(card, ram+1, pcm->rc);
|
||||
ram_outb(card, ram+0, pcm->req);
|
||||
|
||||
timeout = jiffies + 50;
|
||||
while (timeout > jiffies) {
|
||||
pcm->rc = ram_inb(card, ram+1);
|
||||
pcm->req = ram_inb(card, ram+0);
|
||||
if (!pcm->req) break;
|
||||
SLEEP(10);
|
||||
}
|
||||
|
||||
if (pcm->req) {
|
||||
return XLOG_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (pcm->rc != OK) {
|
||||
return XLOG_ERR_DONE;
|
||||
}
|
||||
|
||||
ram_copyfromcard(card, pcm, ram, len);
|
||||
|
||||
if (stype) {
|
||||
for (i=0; i<8; i++)
|
||||
((__u8 *)pcm)[11-i] = ((__u8 *)pcm)[9-i];
|
||||
time = (__u32)pcm->data.w[2] * 3600 * 1000 +
|
||||
(__u32)pcm->data.w[1] * 1000 +
|
||||
(__u32)pcm->data.b[1] * 20 +
|
||||
(__u32)pcm->data.b[0] ;
|
||||
pcm->data.w[1] = (__u16) (time >> 16);
|
||||
pcm->data.w[2] = (__u16) (time & 0x0000ffff);
|
||||
pcm->data.w[0] = 2;
|
||||
}
|
||||
|
||||
return XLOG_OK;
|
||||
de->RNum = 0;
|
||||
de->RNR = 0;
|
||||
de->Rc = 0;
|
||||
de->Ind = 0;
|
||||
}
|
||||
#endif /* CONFIG_ISDN_DRV_EICON_PCI */
|
||||
|
||||
/*
|
||||
* Transmit-Function
|
||||
*/
|
||||
void
|
||||
eicon_io_transmit(eicon_card *ccard) {
|
||||
eicon_pci_card *pci_card;
|
||||
eicon_isa_card *isa_card;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb2;
|
||||
unsigned long flags;
|
||||
char *ram, *reg, *cfg;
|
||||
eicon_pr_ram *prram = 0;
|
||||
eicon_isa_com *com = 0;
|
||||
eicon_REQ *ReqOut = 0;
|
||||
|
@ -422,10 +245,11 @@ eicon_io_transmit(eicon_card *ccard) {
|
|||
int ReqCount;
|
||||
int scom = 0;
|
||||
int tmp = 0;
|
||||
int tmpid = 0;
|
||||
int quloop = 1;
|
||||
int dlev = 0;
|
||||
ENTITY *ep = 0;
|
||||
|
||||
pci_card = &ccard->hwif.pci;
|
||||
isa_card = &ccard->hwif.isa;
|
||||
|
||||
if (!ccard) {
|
||||
|
@ -447,20 +271,17 @@ eicon_io_transmit(eicon_card *ccard) {
|
|||
prram = (eicon_pr_ram *)isa_card->shmem;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_PCI
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
scom = 0;
|
||||
ram = (char *)pci_card->PCIram;
|
||||
reg = (char *)pci_card->PCIreg;
|
||||
cfg = (char *)pci_card->PCIcfg;
|
||||
prram = (eicon_pr_ram *)ram;
|
||||
scom = 2;
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRAQ:
|
||||
scom = 2;
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
scom = 0;
|
||||
ram = (char *)pci_card->PCIram;
|
||||
reg = (char *)pci_card->PCIreg;
|
||||
cfg = (char *)pci_card->PCIcfg;
|
||||
prram = 0;
|
||||
scom = 2;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
|
||||
return;
|
||||
|
@ -470,69 +291,91 @@ eicon_io_transmit(eicon_card *ccard) {
|
|||
if (!(skb2 = skb_dequeue(&ccard->sndq)))
|
||||
quloop = 0;
|
||||
while(quloop) {
|
||||
save_flags(flags);
|
||||
cli();
|
||||
if (scom) {
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
switch (scom) {
|
||||
case 1:
|
||||
if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) {
|
||||
if (!ccard->ReadyInt) {
|
||||
tmp = ram_inb(ccard, &com->ReadyInt) + 1;
|
||||
ram_outb(ccard, &com->ReadyInt, tmp);
|
||||
ccard->ReadyInt++;
|
||||
}
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
skb_queue_head(&ccard->sndq, skb2);
|
||||
eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
case 0:
|
||||
if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
skb_queue_head(&ccard->sndq, skb2);
|
||||
eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
restore_flags(flags);
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
|
||||
chan2 = (eicon_chan_ptr *)skb2->data;
|
||||
chan = chan2->ptr;
|
||||
if (!chan->e.busy) {
|
||||
if((skb = skb_dequeue(&chan->e.X))) {
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
reqbuf = (eicon_REQ *)skb->data;
|
||||
if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
|
||||
eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No);
|
||||
} else {
|
||||
if (scom) {
|
||||
spin_lock_irqsave(&eicon_lock, flags);
|
||||
|
||||
switch (scom) {
|
||||
case 1:
|
||||
ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
|
||||
ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
|
||||
ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);
|
||||
|
||||
} else {
|
||||
break;
|
||||
case 0:
|
||||
/* get address of next available request buffer */
|
||||
ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];
|
||||
ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);
|
||||
ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
|
||||
ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
|
||||
ram_outb(ccard, &ReqOut->Req, reqbuf->Req);
|
||||
break;
|
||||
}
|
||||
|
||||
dlev = 160;
|
||||
|
||||
if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
|
||||
|
||||
if (!reqbuf->Reference) { /* Signal Layer */
|
||||
if (scom)
|
||||
switch (scom) {
|
||||
case 1:
|
||||
ram_outb(ccard, &com->ReqId, chan->e.D3Id);
|
||||
else
|
||||
break;
|
||||
case 0:
|
||||
ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
ep = &chan->de;
|
||||
break;
|
||||
}
|
||||
tmpid = chan->e.D3Id;
|
||||
chan->e.ReqCh = 0;
|
||||
}
|
||||
else { /* Net Layer */
|
||||
if (scom)
|
||||
switch(scom) {
|
||||
case 1:
|
||||
ram_outb(ccard, &com->ReqId, chan->e.B2Id);
|
||||
else
|
||||
break;
|
||||
case 0:
|
||||
ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
ep = &chan->be;
|
||||
break;
|
||||
}
|
||||
tmpid = chan->e.B2Id;
|
||||
chan->e.ReqCh = 1;
|
||||
if (((reqbuf->Req & 0x0f) == 0x08) ||
|
||||
((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
|
||||
|
@ -544,51 +387,106 @@ eicon_io_transmit(eicon_card *ccard) {
|
|||
|
||||
} else { /* It is an ASSIGN */
|
||||
|
||||
if (scom)
|
||||
switch(scom) {
|
||||
case 1:
|
||||
ram_outb(ccard, &com->ReqId, reqbuf->ReqId);
|
||||
else
|
||||
break;
|
||||
case 0:
|
||||
ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId);
|
||||
break;
|
||||
case 2:
|
||||
if (!reqbuf->Reference)
|
||||
ep = &chan->de;
|
||||
else
|
||||
ep = &chan->be;
|
||||
ep->Id = reqbuf->ReqId;
|
||||
break;
|
||||
}
|
||||
tmpid = reqbuf->ReqId;
|
||||
|
||||
if (!reqbuf->Reference)
|
||||
chan->e.ReqCh = 0;
|
||||
else
|
||||
chan->e.ReqCh = 1;
|
||||
}
|
||||
if (scom)
|
||||
|
||||
switch(scom) {
|
||||
case 1:
|
||||
chan->e.ref = ccard->ref_out++;
|
||||
else
|
||||
break;
|
||||
case 0:
|
||||
chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
|
||||
break;
|
||||
case 2:
|
||||
chan->e.ref = chan->No;
|
||||
break;
|
||||
}
|
||||
|
||||
chan->e.Req = reqbuf->Req;
|
||||
ReqCount++;
|
||||
if (scom)
|
||||
|
||||
switch (scom) {
|
||||
case 1:
|
||||
ram_outb(ccard, &com->Req, reqbuf->Req);
|
||||
else
|
||||
break;
|
||||
case 0:
|
||||
ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next));
|
||||
break;
|
||||
case 2:
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_PCI
|
||||
if (!ep) break;
|
||||
ep->callback = eicon_idi_callback;
|
||||
ep->R = (BUFFERS *)ccard;
|
||||
ep->user[0] = (word)chan->No;
|
||||
ep->user[1] = (word)tmpid;
|
||||
ep->XNum = 1;
|
||||
ep->RNum = 0;
|
||||
ep->RNR = 0;
|
||||
ep->Rc = 0;
|
||||
ep->Ind = 0;
|
||||
ep->X->PLength = reqbuf->XBuffer.length;
|
||||
memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
|
||||
ep->ReqCh = reqbuf->ReqCh;
|
||||
ep->Req = reqbuf->Req;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
chan->e.busy = 1;
|
||||
spin_unlock_irqrestore(&eicon_lock, flags);
|
||||
eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n",
|
||||
reqbuf->Req,
|
||||
(scom) ? ram_inb(ccard, &com->ReqId) :
|
||||
ram_inb(ccard, &ReqOut->ReqId),
|
||||
reqbuf->Req, tmpid,
|
||||
reqbuf->ReqCh, reqbuf->XBuffer.length,
|
||||
chan->e.ref);
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_PCI
|
||||
if (scom == 2) {
|
||||
if (ep) {
|
||||
ccard->d->request(ep);
|
||||
if (ep->Rc)
|
||||
eicon_idi_callback(ep);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
restore_flags(flags);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
dev_kfree_skb(skb2);
|
||||
}
|
||||
else {
|
||||
skb_queue_tail(&ccard->sackq, skb2);
|
||||
eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No);
|
||||
skb_queue_tail(&ccard->sackq, skb2);
|
||||
eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No);
|
||||
}
|
||||
|
||||
if (scom)
|
||||
quloop = 0;
|
||||
else
|
||||
if (!(skb2 = skb_dequeue(&ccard->sndq)))
|
||||
switch(scom) {
|
||||
case 1:
|
||||
quloop = 0;
|
||||
break;
|
||||
case 0:
|
||||
case 2:
|
||||
if (!(skb2 = skb_dequeue(&ccard->sndq)))
|
||||
quloop = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (!scom)
|
||||
|
@ -599,18 +497,14 @@ eicon_io_transmit(eicon_card *ccard) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_ISA
|
||||
/*
|
||||
* IRQ handler
|
||||
*/
|
||||
void
|
||||
eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
||||
eicon_card *ccard = (eicon_card *)dev_id;
|
||||
eicon_pci_card *pci_card;
|
||||
eicon_isa_card *isa_card;
|
||||
char *ram = 0;
|
||||
char *reg = 0;
|
||||
char *cfg = 0;
|
||||
eicon_pr_ram *prram = 0;
|
||||
eicon_isa_com *com = 0;
|
||||
eicon_RC *RcIn;
|
||||
|
@ -642,11 +536,9 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
}
|
||||
}
|
||||
|
||||
pci_card = &ccard->hwif.pci;
|
||||
isa_card = &ccard->hwif.isa;
|
||||
|
||||
switch(ccard->type) {
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_ISA
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
|
@ -660,23 +552,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
prram = (eicon_pr_ram *)isa_card->shmem;
|
||||
irqprobe = &isa_card->irqprobe;
|
||||
break;
|
||||
#endif
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
scom = 0;
|
||||
ram = (char *)pci_card->PCIram;
|
||||
reg = (char *)pci_card->PCIreg;
|
||||
cfg = (char *)pci_card->PCIcfg;
|
||||
irqprobe = &pci_card->irqprobe;
|
||||
prram = (eicon_pr_ram *)ram;
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
scom = 0;
|
||||
ram = (char *)pci_card->PCIram;
|
||||
reg = (char *)pci_card->PCIreg;
|
||||
cfg = (char *)pci_card->PCIcfg;
|
||||
irqprobe = &pci_card->irqprobe;
|
||||
prram = 0;
|
||||
break;
|
||||
default:
|
||||
eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n");
|
||||
return;
|
||||
|
@ -684,7 +559,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
|
||||
if (*irqprobe) {
|
||||
switch(ccard->type) {
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_ISA
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
|
@ -702,26 +576,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
}
|
||||
(*irqprobe)++;
|
||||
break;
|
||||
#endif
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
if (readb(&ram[0x3fe])) {
|
||||
writeb(0, &prram->RcOutput);
|
||||
writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
|
||||
writew(0, &cfg[MP_IRQ_RESET + 2]);
|
||||
writeb(0, &ram[0x3fe]);
|
||||
}
|
||||
*irqprobe = 0;
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outb(0x08, pci_card->PCIreg + M_RESET);
|
||||
*irqprobe = 0;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ccard->type) {
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_ISA
|
||||
case EICON_CTYPE_S:
|
||||
case EICON_CTYPE_SX:
|
||||
case EICON_CTYPE_SCOM:
|
||||
|
@ -732,20 +591,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
return;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */
|
||||
eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outw(0x3fe, pci_card->PCIreg + M_ADDR);
|
||||
if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */
|
||||
eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (scom) {
|
||||
|
@ -887,7 +732,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
|
||||
/* clear interrupt */
|
||||
switch(ccard->type) {
|
||||
#ifdef CONFIG_ISDN_DRV_EICON_ISA
|
||||
case EICON_CTYPE_QUADRO:
|
||||
writeb(0, isa_card->intack);
|
||||
writeb(0, &com[0x401]);
|
||||
|
@ -898,19 +742,8 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
|
|||
case EICON_CTYPE_S2M:
|
||||
writeb(0, isa_card->intack);
|
||||
break;
|
||||
#endif
|
||||
case EICON_CTYPE_MAESTRAP:
|
||||
writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
|
||||
writew(0, &cfg[MP_IRQ_RESET + 2]);
|
||||
writeb(0, &ram[0x3fe]);
|
||||
break;
|
||||
case EICON_CTYPE_MAESTRA:
|
||||
outb(0x08, pci_card->PCIreg + M_RESET);
|
||||
outw(0x3fe, pci_card->PCIreg + M_ADDR);
|
||||
outb(0, pci_card->PCIreg + M_DATA);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,71 +7,8 @@
|
|||
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.13 2000/01/23 21:21:23 armin
|
||||
* Added new trace capability and some updates.
|
||||
* DIVA Server BRI now supports data for ISDNLOG.
|
||||
*
|
||||
* Revision 1.12 1999/11/27 12:56:19 armin
|
||||
* Forgot some iomem changes for last ioremap compat.
|
||||
*
|
||||
* Revision 1.11 1999/11/25 11:33:09 armin
|
||||
* Microchannel fix from Erik Weber (exrz73@ibm.net).
|
||||
*
|
||||
* Revision 1.10 1999/11/18 21:14:30 armin
|
||||
* New ISA memory mapped IO
|
||||
*
|
||||
* Revision 1.9 1999/09/08 20:17:31 armin
|
||||
* Added microchannel patch from Erik Weber (exrz73@ibm.net).
|
||||
*
|
||||
* Revision 1.8 1999/09/06 07:29:35 fritz
|
||||
* Changed my mail-address.
|
||||
*
|
||||
* Revision 1.7 1999/08/22 20:26:48 calle
|
||||
* backported changes from kernel 2.3.14:
|
||||
* - several #include "config.h" gone, others come.
|
||||
* - "struct device" changed to "struct net_device" in 2.3.14, added a
|
||||
* define in isdn_compat.h for older kernel versions.
|
||||
*
|
||||
* Revision 1.6 1999/07/25 15:12:06 armin
|
||||
* fix of some debug logs.
|
||||
* enabled ISA-cards option.
|
||||
*
|
||||
* Revision 1.5 1999/04/01 12:48:33 armin
|
||||
* Changed some log outputs.
|
||||
*
|
||||
* Revision 1.4 1999/03/29 11:19:46 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.3 1999/03/02 12:37:45 armin
|
||||
* Added some important checks.
|
||||
* Analog Modem with DSP.
|
||||
* Channels will be added to Link-Level after loading firmware.
|
||||
*
|
||||
* Revision 1.2 1999/01/24 20:14:19 armin
|
||||
* Changed and added debug stuff.
|
||||
* Better data sending. (still problems with tty's flip buffer)
|
||||
*
|
||||
* Revision 1.1 1999/01/01 18:09:43 armin
|
||||
* First checkin of new eicon driver.
|
||||
* DIVA-Server BRI/PCI and PRI/PCI are supported.
|
||||
* Old diehl code is obsolete.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -321,7 +258,7 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
|
|||
boot = &card->shmem->boot;
|
||||
|
||||
/* Delay 0.2 sec. */
|
||||
SLEEP(20);
|
||||
SLEEP(HZ / 5);
|
||||
|
||||
/* Start CPU */
|
||||
writeb(cbuf.boot_opt, &boot->ctrl);
|
||||
|
@ -334,10 +271,10 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
|
|||
#endif /* CONFIG_MCA */
|
||||
|
||||
/* Delay 0.2 sec. */
|
||||
SLEEP(20);
|
||||
SLEEP(HZ / 5);
|
||||
|
||||
timeout = jiffies + (HZ * 22);
|
||||
while (timeout > jiffies) {
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (readb(&boot->ctrl) == 0)
|
||||
break;
|
||||
SLEEP(10);
|
||||
|
@ -380,7 +317,7 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
|
|||
printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]);
|
||||
if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) {
|
||||
tmp = eicon_addcard(card->type, card->physmem, card->irq,
|
||||
((eicon_card *)card->card)->regname);
|
||||
((eicon_card *)card->card)->regname, 0);
|
||||
printk(KERN_INFO "Eicon: %d adapters added\n", tmp);
|
||||
}
|
||||
return 0;
|
||||
|
@ -452,8 +389,8 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
|
|||
while (tmp--) {
|
||||
memcpy_toio(&boot->b, p, 256);
|
||||
writeb(1, &boot->ctrl);
|
||||
timeout = jiffies + 10;
|
||||
while (timeout > jiffies) {
|
||||
timeout = jiffies + HZ / 10;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (readb(&boot->ctrl) == 0)
|
||||
break;
|
||||
SLEEP(2);
|
||||
|
@ -476,7 +413,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
|
|||
/* Start firmware, wait for signature */
|
||||
writeb(2, &boot->ctrl);
|
||||
timeout = jiffies + (5*HZ);
|
||||
while (timeout > jiffies) {
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (readw(&boot->signature) == 0x4447)
|
||||
break;
|
||||
SLEEP(2);
|
||||
|
@ -500,8 +437,8 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
|
|||
tmp = readb(&card->shmem->com.ReadyInt);
|
||||
tmp ++;
|
||||
writeb(tmp, &card->shmem->com.ReadyInt);
|
||||
timeout = jiffies + 20;
|
||||
while (timeout > jiffies) {
|
||||
timeout = jiffies + HZ / 5;
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (card->irqprobe > 1)
|
||||
break;
|
||||
SLEEP(2);
|
||||
|
|
|
@ -6,47 +6,8 @@
|
|||
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.7 1999/11/18 21:14:30 armin
|
||||
* New ISA memory mapped IO
|
||||
*
|
||||
* Revision 1.6 1999/11/15 19:37:04 keil
|
||||
* need config.h
|
||||
*
|
||||
* Revision 1.5 1999/09/08 20:17:31 armin
|
||||
* Added microchannel patch from Erik Weber.
|
||||
*
|
||||
* Revision 1.4 1999/09/06 07:29:35 fritz
|
||||
* Changed my mail-address.
|
||||
*
|
||||
* Revision 1.3 1999/03/29 11:19:47 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.2 1999/03/02 12:37:46 armin
|
||||
* Added some important checks.
|
||||
* Analog Modem with DSP.
|
||||
* Channels will be added to Link-Level after loading firmware.
|
||||
*
|
||||
* Revision 1.1 1999/01/01 18:09:44 armin
|
||||
* First checkin of new eicon driver.
|
||||
* DIVA-Server BRI/PCI and PRI/PCI are supported.
|
||||
* Old diehl code is obsolete.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -134,7 +95,6 @@ typedef struct {
|
|||
unsigned char mvalid; /* Flag: Memory is valid */
|
||||
unsigned char ivalid; /* Flag: IRQ is valid */
|
||||
unsigned char master; /* Flag: Card ist Quadro 1/4 */
|
||||
void* generic; /* Ptr to generic card struct */
|
||||
} eicon_isa_card;
|
||||
|
||||
/* Offsets for special locations on standard cards */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -5,35 +5,8 @@
|
|||
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
|
||||
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.3 1999/03/29 11:19:51 armin
|
||||
* I/O stuff now in seperate file (eicon_io.c)
|
||||
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
|
||||
*
|
||||
* Revision 1.2 1999/03/02 12:37:50 armin
|
||||
* Added some important checks.
|
||||
* Analog Modem with DSP.
|
||||
* Channels will be added to Link-Level after loading firmware.
|
||||
*
|
||||
* Revision 1.1 1999/01/01 18:09:46 armin
|
||||
* First checkin of new eicon driver.
|
||||
* DIVA-Server BRI/PCI and PRI/PCI are supported.
|
||||
* Old diehl code is obsolete.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -42,147 +15,20 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
||||
#define PCI_VENDOR_EICON 0x1133
|
||||
#define PCI_DIVA_PRO20 0xe001 /* Not supported */
|
||||
#define PCI_DIVA20 0xe002 /* Not supported */
|
||||
#define PCI_DIVA_PRO20_U 0xe003 /* Not supported */
|
||||
#define PCI_DIVA20_U 0xe004 /* Not supported */
|
||||
#define PCI_MAESTRA 0xe010
|
||||
#define PCI_MAESTRAQ 0xe012
|
||||
#define PCI_MAESTRAQ_U 0xe013
|
||||
#define PCI_MAESTRAP 0xe014
|
||||
|
||||
#define DIVA_PRO20 1
|
||||
#define DIVA20 2
|
||||
#define DIVA_PRO20_U 3
|
||||
#define DIVA20_U 4
|
||||
#define MAESTRA 5
|
||||
#define MAESTRAQ 6
|
||||
#define MAESTRAQ_U 7
|
||||
#define MAESTRAP 8
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define DIVAS_SIGNATURE 0x4447
|
||||
|
||||
|
||||
/* MAESTRA BRI PCI */
|
||||
|
||||
#define M_RESET 0x10 /* offset of reset register */
|
||||
#define M_DATA 0x00 /* offset of data register */
|
||||
#define M_ADDR 0x04 /* offset of address register */
|
||||
#define M_ADDRH 0x0c /* offset of high address register */
|
||||
|
||||
#define M_DSP_CODE_LEN 0xbf7d0000
|
||||
#define M_DSP_CODE 0xbf7d0004 /* max 128K DSP-Code */
|
||||
#define M_DSP_CODE_BASE 0xbf7a0000
|
||||
#define M_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code (Telindus) */
|
||||
|
||||
|
||||
|
||||
/* MAESTRA PRI PCI */
|
||||
|
||||
#define MP_SHARED_RAM_OFFSET 0x1000 /* offset of shared RAM base in the DRAM memory bar */
|
||||
|
||||
#define MP_IRQ_RESET 0xc18 /* offset of interrupt status register in the CONFIG memory bar */
|
||||
#define MP_IRQ_RESET_VAL 0xfe /* value to clear an interrupt */
|
||||
|
||||
#define MP_PROTOCOL_ADDR 0xa0011000 /* load address of protocol code */
|
||||
#define MP_DSP_ADDR 0xa03c0000 /* load address of DSP code */
|
||||
#define MP_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */
|
||||
#define MP_DSP_CODE_BASE 0xa03a0000
|
||||
#define MP_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code */
|
||||
|
||||
#define MP_RESET 0x20 /* offset of RESET register in the DEVICES memory bar */
|
||||
|
||||
/* RESET register bits */
|
||||
#define _MP_S2M_RESET 0x10 /* active lo */
|
||||
#define _MP_LED2 0x08 /* 1 = on */
|
||||
#define _MP_LED1 0x04 /* 1 = on */
|
||||
#define _MP_DSP_RESET 0x02 /* active lo */
|
||||
#define _MP_RISC_RESET 0x81 /* active hi, bit 7 for compatibility with old boards */
|
||||
|
||||
/* boot interface structure */
|
||||
typedef struct {
|
||||
__u32 cmd __attribute__ ((packed));
|
||||
__u32 addr __attribute__ ((packed));
|
||||
__u32 len __attribute__ ((packed));
|
||||
__u32 err __attribute__ ((packed));
|
||||
__u32 live __attribute__ ((packed));
|
||||
__u32 reserved[(0x1020>>2)-6] __attribute__ ((packed));
|
||||
__u32 signature __attribute__ ((packed));
|
||||
__u8 data[1]; /* real interface description */
|
||||
} eicon_pci_boot;
|
||||
|
||||
|
||||
#define DL_PARA_IO_TYPE 0
|
||||
#define DL_PARA_MEM_TYPE 1
|
||||
|
||||
typedef struct tag_dsp_download_space
|
||||
{
|
||||
__u16 type; /* see definitions above to differ union elements */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
__u32 r3addr;
|
||||
__u16 ioADDR;
|
||||
__u16 ioADDRH;
|
||||
__u16 ioDATA;
|
||||
__u16 BadData; /* in case of verify error */
|
||||
__u16 GoodData;
|
||||
} io; /* for io based adapters */
|
||||
struct
|
||||
{
|
||||
__u32 r3addr;
|
||||
eicon_pci_boot *boot;
|
||||
__u32 BadData; /* in case of verify error */
|
||||
__u32 GoodData;
|
||||
__u16 timeout;
|
||||
} mem; /* for memory based adapters */
|
||||
} dat;
|
||||
} t_dsp_download_space;
|
||||
|
||||
|
||||
/* Shared memory */
|
||||
typedef union {
|
||||
eicon_pci_boot boot;
|
||||
} eicon_pci_shmem;
|
||||
|
||||
/*
|
||||
* card's description
|
||||
*/
|
||||
typedef struct {
|
||||
int ramsize;
|
||||
int irq; /* IRQ */
|
||||
unsigned int PCIram;
|
||||
unsigned int PCIreg;
|
||||
unsigned int PCIcfg;
|
||||
long int serial; /* Serial No. */
|
||||
int channels; /* No. of supported channels */
|
||||
void* card;
|
||||
eicon_pci_shmem* shmem; /* Shared-memory area */
|
||||
unsigned char* intack; /* Int-Acknowledge */
|
||||
unsigned char* stopcpu; /* Writing here stops CPU */
|
||||
unsigned char* startcpu; /* Writing here starts CPU */
|
||||
unsigned char type; /* card type */
|
||||
unsigned char irqprobe; /* Flag: IRQ-probing */
|
||||
unsigned char mvalid; /* Flag: Memory is valid */
|
||||
unsigned char ivalid; /* Flag: IRQ is valid */
|
||||
unsigned char master; /* Flag: Card is Quadro 1/4 */
|
||||
void* generic; /* Ptr to generic card struct */
|
||||
} eicon_pci_card;
|
||||
|
||||
|
||||
|
||||
extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb);
|
||||
extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb);
|
||||
extern void eicon_pci_release(eicon_pci_card *card);
|
||||
extern void eicon_pci_printpar(eicon_pci_card *card);
|
||||
extern int eicon_pci_find_card(char *ID);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* eicon_pci_h */
|
||||
|
||||
|
|
|
@ -0,0 +1,560 @@
|
|||
/*
|
||||
* Diva Server 4BRI specific part of initialisation
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.7
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "divas.h"
|
||||
#include "pc.h"
|
||||
#include "pr_pc.h"
|
||||
#include "dsp_defs.h"
|
||||
#include "constant.h"
|
||||
#include "adapter.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#define TEST_INT_DIVAS_Q 0x13
|
||||
|
||||
#define DIVAS_MAINT_OFFSET 0xff00 /* value for 4BRI card */
|
||||
#define MQ_BOARD_DSP_OFFSET 0x00a00000
|
||||
#define MQ_DSP1_ADDR_OFFSET 0x00000008
|
||||
#define MQ_DSP_JUNK_OFFSET 0x00000400
|
||||
#define MQ_DSP1_DATA_OFFSET 0x00000000
|
||||
#define MQ_BOARD_ISAC_DSP_RESET 0x00800028
|
||||
#define MQ_BREG_RISC 0x1200 /* RISC Reset */
|
||||
#define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
|
||||
#define MQ_RISC_COLD_RESET_MASK 0x0001 /* RISC Cold reset */
|
||||
#define MQ_RISC_WARM_RESET_MASK 0x0002 /* RISC Warm reset */
|
||||
#define MQ_IRQ_REQ_ON 0x1
|
||||
#define MQ_IRQ_REQ_OFF 0x0
|
||||
#define MQ_BREG_IRQ_TEST 0x0608
|
||||
#define PLX9054_INTCSR 0x69
|
||||
#define PLX9054_INT_ENA 0x09
|
||||
|
||||
#define DIVAS_IOBASE 0x01
|
||||
#define M_PCI_RESET 0x10
|
||||
|
||||
byte mem_in(ADAPTER *a, void *adr);
|
||||
word mem_inw(ADAPTER *a, void *adr);
|
||||
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
|
||||
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
|
||||
void mem_out(ADAPTER *a, void *adr, byte data);
|
||||
void mem_outw(ADAPTER *a, void *adr, word data);
|
||||
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
|
||||
void mem_inc(ADAPTER *a, void *adr);
|
||||
|
||||
int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg);
|
||||
static int fourbri_ISR (card_t* card);
|
||||
|
||||
int FPGA_Download(word, dword, byte *, byte *, int);
|
||||
extern byte FPGA_Bytes[];
|
||||
extern void *get_card(int);
|
||||
|
||||
byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
|
||||
void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
|
||||
word GetProtFeatureValue(char *sw_id);
|
||||
|
||||
void memcp(byte *dst, byte *src, dword dwLen);
|
||||
int memcm(byte *dst, byte *src, dword dwLen);
|
||||
|
||||
static int diva_server_4bri_reset(card_t *card)
|
||||
{
|
||||
byte *ctl;
|
||||
|
||||
DPRINTF(("divas: reset Diva Server 4BRI"));
|
||||
|
||||
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
|
||||
|
||||
/* stop RISC, DSP's and ISAC */
|
||||
UxCardMemOut(card->hw, &ctl[MQ_BREG_RISC], 0);
|
||||
UxCardMemOut(card->hw, &ctl[MQ_ISAC_DSP_RESET], 0);
|
||||
|
||||
UxCardMemDetach(card->hw, ctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int diva_server_4bri_config(card_t *card, dia_config_t *config)
|
||||
{
|
||||
byte *shared;
|
||||
int i, j;
|
||||
|
||||
DPRINTF(("divas: configure Diva Server 4BRI"));
|
||||
|
||||
shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[i], 0);
|
||||
}
|
||||
|
||||
UxCardMemOut(card->hw, &shared[ 8], config->tei);
|
||||
UxCardMemOut(card->hw, &shared[ 9], config->nt2);
|
||||
UxCardMemOut(card->hw, &shared[10], config->sig_flags);
|
||||
UxCardMemOut(card->hw, &shared[11], config->watchdog);
|
||||
UxCardMemOut(card->hw, &shared[12], config->permanent);
|
||||
UxCardMemOut(card->hw, &shared[13], config->x_interface);
|
||||
UxCardMemOut(card->hw, &shared[14], config->stable_l2);
|
||||
UxCardMemOut(card->hw, &shared[15], config->no_order_check);
|
||||
UxCardMemOut(card->hw, &shared[16], config->handset_type);
|
||||
UxCardMemOut(card->hw, &shared[17], 0);
|
||||
UxCardMemOut(card->hw, &shared[18], config->low_channel);
|
||||
UxCardMemOut(card->hw, &shared[19], config->prot_version);
|
||||
UxCardMemOut(card->hw, &shared[20], config->crc4);
|
||||
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
DPRINTF(("divas: Signifying V.90"));
|
||||
UxCardMemOut(card->hw, &shared[22], 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[22], 0);
|
||||
}
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
|
||||
}
|
||||
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
|
||||
}
|
||||
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
|
||||
}
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void diva_server_4bri_reset_int(card_t *card)
|
||||
{
|
||||
byte *ctl;
|
||||
|
||||
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
|
||||
|
||||
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
|
||||
|
||||
UxCardMemDetach(card->hw, ctl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int diva_server_4bri_test_int(card_t *card)
|
||||
{
|
||||
byte *ctl, i;
|
||||
byte *reg;
|
||||
|
||||
DPRINTF(("divas: test interrupt for Diva Server 4BRI"));
|
||||
|
||||
/* We get the last (dummy) adapter in so we need to go back to the first */
|
||||
|
||||
card = get_card(card->cfg.card_id - 3);
|
||||
|
||||
/* Enable interrupts on PLX chip */
|
||||
|
||||
reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
|
||||
|
||||
UxCardPortIoOut(card->hw, reg, PLX9054_INTCSR, PLX9054_INT_ENA);
|
||||
|
||||
UxCardMemDetach(card->hw, reg);
|
||||
|
||||
/* Set the test interrupt flag */
|
||||
card->test_int_pend = TEST_INT_DIVAS_Q;
|
||||
|
||||
/* Now to trigger the interrupt */
|
||||
|
||||
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
|
||||
|
||||
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_ON);
|
||||
|
||||
UxCardMemDetach(card->hw, ctl);
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
{
|
||||
if (!card->test_int_pend)
|
||||
{
|
||||
break;
|
||||
}
|
||||
UxPause(10);
|
||||
}
|
||||
|
||||
if (card->test_int_pend)
|
||||
{
|
||||
DPRINTF(("active: timeout waiting for card to interrupt"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void print_hdr(unsigned char *code, int offset)
|
||||
{
|
||||
unsigned char hdr[80];
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
|
||||
while ((i < (DIM(hdr) -1)) &&
|
||||
(code[offset + i] != '\0') &&
|
||||
(code[offset + i] != '\r') &&
|
||||
(code[offset + i] != '\n'))
|
||||
{
|
||||
hdr[i] = code[offset + i];
|
||||
i++;
|
||||
}
|
||||
|
||||
hdr[i] = '\0';
|
||||
|
||||
DPRINTF(("divas: loading %s", hdr));
|
||||
}
|
||||
|
||||
static int diva_server_4bri_load(card_t *card, dia_load_t *load)
|
||||
{
|
||||
byte *pRAM=NULL;
|
||||
int download_offset=0;
|
||||
card_t *FirstCard;
|
||||
byte sw_id[80];
|
||||
|
||||
DPRINTF(("divas: loading Diva Server 4BRI[%d]", load->card_id));
|
||||
|
||||
switch(load->code_type)
|
||||
{
|
||||
case DIA_CPU_CODE:
|
||||
DPRINTF(("divas: RISC code"));
|
||||
print_hdr(load->code, 0x80);
|
||||
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
|
||||
download_offset = 0; // Protocol code written to offset 0
|
||||
pRAM = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
|
||||
break;
|
||||
|
||||
case DIA_DSP_CODE:
|
||||
DPRINTF(("divas: DSP code"));
|
||||
print_hdr(load->code, 0x0);
|
||||
FirstCard = get_card(load->card_id - 3);
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
download_offset = MQ_V90D_DSP_CODE_BASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
download_offset = MQ_ORG_DSP_CODE_BASE;
|
||||
}
|
||||
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
|
||||
download_offset += (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC);
|
||||
|
||||
break;
|
||||
|
||||
case DIA_TABLE_CODE:
|
||||
DPRINTF(("divas: TABLE code"));
|
||||
FirstCard = get_card(load->card_id - 3);
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
download_offset = MQ_V90D_DSP_CODE_BASE + sizeof(dword);
|
||||
}
|
||||
else
|
||||
{
|
||||
download_offset = MQ_ORG_DSP_CODE_BASE + sizeof(dword);
|
||||
}
|
||||
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
|
||||
break;
|
||||
|
||||
case DIA_CONT_CODE:
|
||||
DPRINTF(("divas: continuation code"));
|
||||
break;
|
||||
|
||||
case DIA_DLOAD_CNT:
|
||||
DPRINTF(("divas: COUNT code"));
|
||||
FirstCard = get_card(load->card_id - 3);
|
||||
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
|
||||
{
|
||||
download_offset = MQ_V90D_DSP_CODE_BASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
download_offset = MQ_ORG_DSP_CODE_BASE;
|
||||
}
|
||||
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
|
||||
break;
|
||||
|
||||
case DIA_FPGA_CODE:
|
||||
DPRINTF(("divas: 4BRI FPGA download - %d bytes", load->length));
|
||||
if (FPGA_Download(IDI_ADAPTER_MAESTRAQ,
|
||||
card->hw->io_base,
|
||||
sw_id,
|
||||
load->code,
|
||||
load->length
|
||||
) == -1)
|
||||
{
|
||||
DPRINTF(("divas: FPGA download failed"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NOW reset the 4BRI */
|
||||
diva_server_4bri_reset(card);
|
||||
return 0; // No need for anything further loading
|
||||
|
||||
default:
|
||||
DPRINTF(("divas: unknown code type"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcp(pRAM + (download_offset & 0x3FFFFF), load->code, load->length);
|
||||
|
||||
{
|
||||
int mism_off;
|
||||
if ((mism_off = memcm(pRAM + (download_offset & 0x3FFFFF), load->code, load->length)))
|
||||
{
|
||||
DPRINTF(("divas: memory mismatch at offset %d", mism_off));
|
||||
UxCardMemDetach(card->hw, pRAM);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, pRAM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int diva_server_4bri_start(card_t *card, byte *channels)
|
||||
{
|
||||
byte *ctl;
|
||||
byte *shared, i;
|
||||
int adapter_num;
|
||||
|
||||
DPRINTF(("divas: start Diva Server 4BRI"));
|
||||
*channels = 0;
|
||||
card->is_live = FALSE;
|
||||
|
||||
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
|
||||
|
||||
UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_COLD_RESET_MASK);
|
||||
|
||||
UxPause(2);
|
||||
|
||||
UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
|
||||
|
||||
UxPause(10);
|
||||
|
||||
UxCardMemDetach(card->hw, ctl);
|
||||
|
||||
shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
for ( i = 0 ; i < 300 ; ++i )
|
||||
{
|
||||
UxPause (10) ;
|
||||
|
||||
if ( UxCardMemInW(card->hw, &shared[0x1E]) == 0x4447 )
|
||||
{
|
||||
DPRINTF(("divas: Protocol startup time %d.%02d seconds",
|
||||
(i / 100), (i % 100) ));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i==300)
|
||||
{
|
||||
DPRINTF(("divas: Timeout starting card"));
|
||||
DPRINTF(("divas: Signature == 0x%04X", UxCardMemInW(card->hw, &shared[0x1E])));
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
return -1;
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
|
||||
for (adapter_num=3; adapter_num >= 0; adapter_num--)
|
||||
{
|
||||
card_t *qbri_card;
|
||||
|
||||
qbri_card = get_card(card->cfg.card_id - adapter_num);
|
||||
|
||||
if (qbri_card)
|
||||
{
|
||||
qbri_card->is_live = TRUE;
|
||||
shared = UxCardMemAttach(qbri_card->hw, DIVAS_SHARED_MEMORY);
|
||||
*channels += UxCardMemIn(qbri_card->hw, &shared[0x3F6]);
|
||||
UxCardMemDetach(qbri_card->hw, shared);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(("divas: Couldn't get card info %d", card->cfg.card_id));
|
||||
}
|
||||
}
|
||||
|
||||
diva_server_4bri_test_int(card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int diva_server_4bri_mem_get(card_t *card, mem_block_t *mem_block)
|
||||
|
||||
{
|
||||
byte *a;
|
||||
byte *card_addr;
|
||||
word length = 0;
|
||||
int i;
|
||||
|
||||
a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
|
||||
|
||||
card_addr = a;
|
||||
card_addr += mem_block->addr;
|
||||
|
||||
for (i=0; i < sizeof(mem_block->data); i++)
|
||||
{
|
||||
mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
|
||||
card_addr++;
|
||||
length++;
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, a);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise 4BRI specific entry points
|
||||
*/
|
||||
|
||||
int Divas4BriInit(card_t *card, dia_card_t *cfg)
|
||||
{
|
||||
// byte sw_id[80];
|
||||
// extern int FPGA_Done;
|
||||
|
||||
DPRINTF(("divas: initialise Diva Server 4BRI"));
|
||||
|
||||
if (Divas4BRIInitPCI(card, cfg) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Need to download the FPGA */
|
||||
/* if (!FPGA_Done)
|
||||
{
|
||||
int retVal;
|
||||
|
||||
retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
|
||||
cfg->io_base,
|
||||
sw_id,
|
||||
FPGA_Bytes
|
||||
);
|
||||
if(retVal==-1)
|
||||
{
|
||||
|
||||
DPRINTF(("divas: FPGA Download Failed"));
|
||||
return -1;
|
||||
|
||||
}
|
||||
FPGA_Done = 1;
|
||||
} */
|
||||
|
||||
card->card_reset = diva_server_4bri_reset;
|
||||
card->card_load = diva_server_4bri_load;
|
||||
card->card_config = diva_server_4bri_config;
|
||||
card->card_start = diva_server_4bri_start;
|
||||
card->reset_int = diva_server_4bri_reset_int;
|
||||
card->card_mem_get = diva_server_4bri_mem_get;
|
||||
|
||||
card->xlog_offset = DIVAS_MAINT_OFFSET;
|
||||
|
||||
card->out = DivasOut;
|
||||
card->test_int = DivasTestInt;
|
||||
card->dpc = DivasDpc;
|
||||
card->clear_int = DivasClearInt;
|
||||
card->card_isr = fourbri_ISR;
|
||||
|
||||
card->a.ram_out = mem_out;
|
||||
card->a.ram_outw = mem_outw;
|
||||
card->a.ram_out_buffer = mem_out_buffer;
|
||||
card->a.ram_inc = mem_inc;
|
||||
|
||||
card->a.ram_in = mem_in;
|
||||
card->a.ram_inw = mem_inw;
|
||||
card->a.ram_in_buffer = mem_in_buffer;
|
||||
card->a.ram_look_ahead = mem_look_ahead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void memcp(byte *dst, byte *src, dword dwLen)
|
||||
{
|
||||
while (dwLen)
|
||||
{
|
||||
*dst = *src;
|
||||
dst++; src++;
|
||||
dwLen--;
|
||||
}
|
||||
}
|
||||
|
||||
int memcm(byte *dst, byte *src, dword dwLen)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
while (offset < dwLen)
|
||||
{
|
||||
if(*dst != *src)
|
||||
return (offset+1);
|
||||
|
||||
offset++;
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*int fourbri_ISR (card_t* card)
|
||||
{
|
||||
int served = 0;
|
||||
byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
|
||||
|
||||
|
||||
if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01)
|
||||
{
|
||||
served = 1;
|
||||
card->int_pend += 1;
|
||||
DivasDpcSchedule();
|
||||
UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, DivasIOBase);
|
||||
|
||||
return (served != 0);
|
||||
}*/
|
||||
|
||||
|
||||
static int fourbri_ISR (card_t* card)
|
||||
{
|
||||
byte *ctl;
|
||||
|
||||
card->int_pend += 1;
|
||||
DivasDpcSchedule(); /* ISR DPC */
|
||||
|
||||
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
|
||||
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
|
||||
UxCardMemDetach(card->hw, ctl);
|
||||
|
||||
return (1);
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.2
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#define FPGA_PORT 0x6E
|
||||
#define FPGA_DLOAD_BUFLEN 256
|
||||
#define NAME_OFFSET 0x10
|
||||
#define NAME_MAXLEN 12
|
||||
#define DATE_OFFSET 0x2c
|
||||
#define DATE_MAXLEN 10
|
||||
|
||||
word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
|
||||
void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
|
||||
void UxPause(long int);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* Loads the FPGA configuration file onto the hardware. */
|
||||
/* Function returns 0 on success, else an error number. */
|
||||
/* On success, an identifier string is returned in the buffer */
|
||||
/* */
|
||||
/* A buffer of FPGA_BUFSIZE, a handle to the already opened bitstream */
|
||||
/* file and a file read function has to be provided by the operating */
|
||||
/* system part. */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
int FPGA_Download( word cardtype,
|
||||
dword RegBase,
|
||||
byte *strbuf,
|
||||
byte FPGA_SRC[],
|
||||
int FPGA_LEN
|
||||
)
|
||||
{
|
||||
word i, j, k;
|
||||
word baseval, Mask_PROGRAM, Mask_DONE, Mask_CCLK, Mask_DIN;
|
||||
dword addr;
|
||||
byte *pFPGA;
|
||||
|
||||
//--- check for legal cardtype
|
||||
switch (cardtype)
|
||||
{
|
||||
case IDI_ADAPTER_MAESTRAQ:
|
||||
addr = RegBase ; // address where to access FPGA
|
||||
Mask_PROGRAM = 0x0001; // FPGA pins at address
|
||||
Mask_DONE = 0x0002;
|
||||
Mask_CCLK = 0x0100;
|
||||
Mask_DIN = 0x0400;
|
||||
baseval = 0x000d; // PROGRAM hi, CCLK lo, DIN lo by default
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
DPRINTF(("divas: FPGA Download ,Illegal Card"));
|
||||
return -1; // illegal card
|
||||
}
|
||||
|
||||
//--- generate id string from file content
|
||||
for (j=NAME_OFFSET, k=0; j<(NAME_OFFSET+NAME_MAXLEN); j++, k++) //name
|
||||
{
|
||||
if (!FPGA_SRC[j]) break;
|
||||
strbuf[k] = FPGA_SRC[j];
|
||||
}
|
||||
strbuf[k++] = ' ';
|
||||
for (j=DATE_OFFSET; j<(DATE_OFFSET+DATE_MAXLEN); j++, k++) // date
|
||||
{
|
||||
if (!FPGA_SRC[j]) break;
|
||||
strbuf[k] = FPGA_SRC[j];
|
||||
}
|
||||
strbuf[k] = 0;
|
||||
|
||||
DPRINTF(("divas: FPGA Download - %s", strbuf));
|
||||
|
||||
//--- prepare download, Pulse PROGRAM pin down.
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval &~Mask_PROGRAM); // PROGRAM low pulse
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // release
|
||||
UxPause(50); // wait until FPGA finised internal memory clear
|
||||
|
||||
//--- check done pin, must be low
|
||||
if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE)
|
||||
{
|
||||
DPRINTF(("divas: FPGA_ERR_DONE_WRONG_LEVEL"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pFPGA = FPGA_SRC;
|
||||
|
||||
i = 0;
|
||||
/* Move past the header */
|
||||
while ((FPGA_SRC[i] != 0xFF) && (i < FPGA_LEN))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// We've hit the 0xFF so move on to the next byte
|
||||
// i++;
|
||||
DPRINTF(("divas: FPGA Code starts at offset %d", i));
|
||||
|
||||
//--- put data onto the FPGA
|
||||
for (;i<FPGA_LEN; i++)
|
||||
{
|
||||
//--- put byte onto FPGA
|
||||
for (j=0; j<8; j++)
|
||||
{
|
||||
if (FPGA_SRC[i] &(0x80>>j)) baseval |= Mask_DIN; // write a hi
|
||||
else baseval &=~Mask_DIN; // write a lo
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK); // set CCLK hi
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // set CCLK lo
|
||||
}
|
||||
}
|
||||
|
||||
//--- add some additional startup clock cycles and check done pin
|
||||
for (i=0; i<5; i++)
|
||||
{
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK); // set CCLK hi
|
||||
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // set CCLK lo
|
||||
}
|
||||
|
||||
UxPause(100);
|
||||
|
||||
if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE)
|
||||
{
|
||||
DPRINTF(("divas: FPGA download successful"));
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(("divas: FPGA download failed - 0x%x", UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,854 @@
|
|||
/*
|
||||
* Core driver for Diva Server cards
|
||||
* Implements the IDI interface
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.8
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "idi.h"
|
||||
#include "adapter.h"
|
||||
#include "pc.h"
|
||||
#include "pr_pc.h"
|
||||
#include "sys.h"
|
||||
#include "uxio.h"
|
||||
|
||||
/* IDI request functions */
|
||||
|
||||
static void request(card_t *card, ENTITY *e);
|
||||
|
||||
static void req_0(ENTITY *e) { request(&DivasCards[ 0], e); }
|
||||
static void req_1(ENTITY *e) { request(&DivasCards[ 1], e); }
|
||||
static void req_2(ENTITY *e) { request(&DivasCards[ 2], e); }
|
||||
static void req_3(ENTITY *e) { request(&DivasCards[ 3], e); }
|
||||
static void req_4(ENTITY *e) { request(&DivasCards[ 4], e); }
|
||||
static void req_5(ENTITY *e) { request(&DivasCards[ 5], e); }
|
||||
static void req_6(ENTITY *e) { request(&DivasCards[ 6], e); }
|
||||
static void req_7(ENTITY *e) { request(&DivasCards[ 7], e); }
|
||||
static void req_8(ENTITY *e) { request(&DivasCards[ 8], e); }
|
||||
static void req_9(ENTITY *e) { request(&DivasCards[ 9], e); }
|
||||
static void req_10(ENTITY *e) { request(&DivasCards[10], e); }
|
||||
static void req_11(ENTITY *e) { request(&DivasCards[11], e); }
|
||||
static void req_12(ENTITY *e) { request(&DivasCards[12], e); }
|
||||
static void req_13(ENTITY *e) { request(&DivasCards[13], e); }
|
||||
static void req_14(ENTITY *e) { request(&DivasCards[14], e); }
|
||||
static void req_15(ENTITY *e) { request(&DivasCards[15], e); }
|
||||
|
||||
IDI_CALL DivasIdiRequest[16] =
|
||||
{
|
||||
&req_0, &req_1, &req_2, &req_3,
|
||||
&req_4, &req_5, &req_6, &req_7,
|
||||
&req_8, &req_9, &req_10, &req_11,
|
||||
&req_12, &req_13, &req_14, &req_15
|
||||
};
|
||||
|
||||
#define PR_RAM ((struct pr_ram *)0)
|
||||
#define RAM ((struct dual *)0)
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* local function prototypes */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static byte isdn_rc(ADAPTER *, byte, byte, byte, word);
|
||||
static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
|
||||
|
||||
/*
|
||||
* IDI related functions
|
||||
*/
|
||||
|
||||
static
|
||||
ENTITY *entity_ptr(ADAPTER *a, byte e_no)
|
||||
{
|
||||
card_t *card;
|
||||
|
||||
card = a->io;
|
||||
|
||||
return card->e_tbl[e_no].e;
|
||||
}
|
||||
|
||||
static
|
||||
void CALLBACK(ADAPTER *a, ENTITY *e)
|
||||
{
|
||||
card_t *card = a->io;
|
||||
|
||||
if (card->log_types & DIVAS_LOG_IDI)
|
||||
{
|
||||
DivasLogIdi(card, e, FALSE);
|
||||
}
|
||||
|
||||
(*e->callback)(e);
|
||||
}
|
||||
|
||||
static
|
||||
void *PTR_P(ADAPTER *a, ENTITY *e, void *P)
|
||||
{
|
||||
return(P);
|
||||
}
|
||||
|
||||
static
|
||||
void *PTR_R(ADAPTER *a, ENTITY *e)
|
||||
{
|
||||
return((void*)e->R);
|
||||
}
|
||||
|
||||
static
|
||||
void *PTR_X(ADAPTER *a, ENTITY *e)
|
||||
{
|
||||
return((void*)e->X);
|
||||
}
|
||||
|
||||
static
|
||||
void free_entity(ADAPTER *a, byte e_no)
|
||||
{
|
||||
card_t *card;
|
||||
int ipl;
|
||||
|
||||
card = a->io;
|
||||
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
card->e_tbl[e_no].e = NULL;
|
||||
card->e_count--;
|
||||
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void assign_queue(ADAPTER * a, byte e_no, word ref)
|
||||
{
|
||||
card_t *card;
|
||||
int ipl;
|
||||
|
||||
card = a->io;
|
||||
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
card->e_tbl[e_no].assign_ref = ref;
|
||||
card->e_tbl[e_no].next = card->assign;
|
||||
card->assign = e_no;
|
||||
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
byte get_assign(ADAPTER *a, word ref)
|
||||
{
|
||||
card_t *card;
|
||||
byte e_no;
|
||||
int ipl;
|
||||
|
||||
card = a->io;
|
||||
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
e_no = (byte)card->assign;
|
||||
while (e_no)
|
||||
{
|
||||
if (card->e_tbl[e_no].assign_ref == ref)
|
||||
{
|
||||
break;
|
||||
}
|
||||
e_no = card->e_tbl[e_no].next;
|
||||
}
|
||||
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
|
||||
return e_no;
|
||||
}
|
||||
|
||||
static
|
||||
void req_queue(ADAPTER * a, byte e_no)
|
||||
{
|
||||
card_t *card;
|
||||
int ipl;
|
||||
|
||||
card = a->io;
|
||||
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
card->e_tbl[e_no].next = 0;
|
||||
|
||||
if (card->e_head)
|
||||
{
|
||||
card->e_tbl[card->e_tail].next = e_no;
|
||||
card->e_tail = e_no;
|
||||
}
|
||||
else
|
||||
{
|
||||
card->e_head = e_no;
|
||||
card->e_tail = e_no;
|
||||
}
|
||||
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
byte look_req(ADAPTER * a)
|
||||
{
|
||||
card_t *card;
|
||||
|
||||
card = a->io;
|
||||
|
||||
return(card->e_head);
|
||||
}
|
||||
|
||||
static
|
||||
void next_req(ADAPTER * a)
|
||||
{
|
||||
card_t *card;
|
||||
int ipl;
|
||||
|
||||
|
||||
card = a->io;
|
||||
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
card->e_head = card->e_tbl[card->e_head].next;
|
||||
if (!card->e_head)
|
||||
{
|
||||
card->e_tail = 0;
|
||||
}
|
||||
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IDI request function for active cards
|
||||
*/
|
||||
static
|
||||
void request(card_t *card, ENTITY *e)
|
||||
{
|
||||
word *special_req;
|
||||
int i;
|
||||
int ipl;
|
||||
|
||||
|
||||
if (card->log_types & DIVAS_LOG_IDI)
|
||||
{
|
||||
DivasLogIdi(card, e, TRUE);
|
||||
}
|
||||
|
||||
if (!e->Req)
|
||||
{
|
||||
special_req = (word *) e;
|
||||
|
||||
switch (*special_req)
|
||||
{
|
||||
case REQ_REMOVE:
|
||||
return;
|
||||
|
||||
case REQ_NAME:
|
||||
for (i=0; i < DIM(card->cfg.name); i++)
|
||||
{
|
||||
((struct get_name_s *) e)->name[i] = card->cfg.name[i];
|
||||
}
|
||||
return;
|
||||
|
||||
case REQ_SERIAL:
|
||||
case REQ_XLOG:
|
||||
DPRINTF(("IDI: attempted REQ_SERIAL or REQ_XLOG"));
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ipl = UxCardLock(card->hw);
|
||||
|
||||
if (!(e->Id & 0x1f))
|
||||
{
|
||||
DPRINTF(("IDI: ASSIGN req"));
|
||||
|
||||
for (i = 1; i < card->e_max; i++)
|
||||
{
|
||||
if (!card->e_tbl[i].e)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == card->e_max)
|
||||
{
|
||||
DPRINTF(("IDI: request all ids in use (IDI req ignored)"));
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
e->Rc = OUT_OF_RESOURCES;
|
||||
return;
|
||||
}
|
||||
|
||||
card->e_tbl[i].e = e;
|
||||
card->e_count++;
|
||||
|
||||
e->No = (byte) i;
|
||||
e->More = 0;
|
||||
e->RCurrent = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = e->No;
|
||||
}
|
||||
|
||||
if (e->More & XBUSY)
|
||||
{
|
||||
DPRINTF(("IDI: request - entity is busy"));
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
return;
|
||||
}
|
||||
|
||||
e->More |= XBUSY;
|
||||
e->More &= ~ XMOREF;
|
||||
e->XCurrent = 0;
|
||||
e->XOffset = 0;
|
||||
|
||||
card->e_tbl[i].next = 0;
|
||||
|
||||
if(card->e_head)
|
||||
{
|
||||
card->e_tbl[card->e_tail].next = i;
|
||||
card->e_tail = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
card->e_head = i;
|
||||
card->e_tail = i;
|
||||
}
|
||||
|
||||
UxCardUnlock(card->hw, ipl);
|
||||
|
||||
DivasScheduleRequestDpc();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static byte pr_ready(ADAPTER * a)
|
||||
{
|
||||
byte ReadyCount;
|
||||
|
||||
ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
|
||||
a->ram_in(a, &PR_RAM->ReqInput));
|
||||
|
||||
if(!ReadyCount) {
|
||||
if(!a->ReadyInt) {
|
||||
a->ram_inc(a, &PR_RAM->ReadyInt);
|
||||
a->ReadyInt++;
|
||||
}
|
||||
}
|
||||
return ReadyCount;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* output function */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
void DivasOut(ADAPTER * a)
|
||||
{
|
||||
byte e_no;
|
||||
ENTITY * this = NULL;
|
||||
BUFFERS *X;
|
||||
word length;
|
||||
word i;
|
||||
word clength;
|
||||
REQ * ReqOut;
|
||||
byte more;
|
||||
byte ReadyCount;
|
||||
byte ReqCount;
|
||||
byte Id;
|
||||
|
||||
/* while a request is pending ... */
|
||||
e_no = look_req(a);
|
||||
if(!e_no)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReadyCount = pr_ready(a);
|
||||
if(!ReadyCount)
|
||||
{
|
||||
DPRINTF(("IDI: card not ready for next request"));
|
||||
return;
|
||||
}
|
||||
|
||||
ReqCount = 0;
|
||||
while(e_no && ReadyCount) {
|
||||
|
||||
next_req(a);
|
||||
|
||||
this = entity_ptr(a, e_no);
|
||||
|
||||
#ifdef USE_EXTENDED_DEBUGS
|
||||
if ( !this )
|
||||
{
|
||||
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
|
||||
DBG_FTL(("!A%d ==> NULL entity ptr - try to ignore", (int)io->ANum))
|
||||
e_no = look_req(a) ;
|
||||
ReadyCount-- ;
|
||||
continue ;
|
||||
}
|
||||
{
|
||||
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
|
||||
DPRINTF(("IDI: >A%d Id=0x%x Req=0x%x", io->ANum, this->Id, this->Req))
|
||||
}
|
||||
#else
|
||||
DPRINTF(("IDI: >REQ=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
|
||||
#endif
|
||||
|
||||
/* get address of next available request buffer */
|
||||
ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
|
||||
|
||||
/* now copy the data from the current data buffer into the */
|
||||
/* adapters request buffer */
|
||||
length = 0;
|
||||
i = this->XCurrent;
|
||||
X = PTR_X(a,this);
|
||||
while(i<this->XNum && length<270) {
|
||||
clength = (word)(270-length);
|
||||
if (clength > X[i].PLength-this->XOffset)
|
||||
clength = X[i].PLength-this->XOffset;
|
||||
a->ram_out_buffer(a,
|
||||
&ReqOut->XBuffer.P[length],
|
||||
PTR_P(a,this,&X[i].P[this->XOffset]),
|
||||
clength);
|
||||
|
||||
length +=clength;
|
||||
this->XOffset +=clength;
|
||||
if(this->XOffset==X[i].PLength) {
|
||||
this->XCurrent = (byte)++i;
|
||||
this->XOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
a->ram_outw(a, &ReqOut->XBuffer.length, length);
|
||||
a->ram_out(a, &ReqOut->ReqId, this->Id);
|
||||
a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
|
||||
|
||||
/* if its a specific request (no ASSIGN) ... */
|
||||
|
||||
if(this->Id &0x1f) {
|
||||
|
||||
/* if buffers are left in the list of data buffers do */
|
||||
/* do chaining (LL_MDATA, N_MDATA) */
|
||||
|
||||
this->More++;
|
||||
if(i<this->XNum && this->MInd) {
|
||||
a->ram_out(a, &ReqOut->Req, this->MInd);
|
||||
more = TRUE;
|
||||
}
|
||||
else {
|
||||
this->More |=XMOREF;
|
||||
a->ram_out(a, &ReqOut->Req, this->Req);
|
||||
more = FALSE;
|
||||
}
|
||||
|
||||
/* if we did chaining, this entity is put back into the */
|
||||
/* request queue */
|
||||
|
||||
if(more) {
|
||||
req_queue(a,this->No);
|
||||
}
|
||||
}
|
||||
|
||||
/* else it's a ASSIGN */
|
||||
|
||||
else {
|
||||
|
||||
/* save the request code used for buffer chaining */
|
||||
|
||||
this->MInd = 0;
|
||||
if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
|
||||
if (this->Id==NL_ID ||
|
||||
this->Id==TASK_ID ||
|
||||
this->Id==MAN_ID
|
||||
) this->MInd = N_MDATA;
|
||||
|
||||
/* send the ASSIGN */
|
||||
|
||||
this->More |=XMOREF;
|
||||
a->ram_out(a, &ReqOut->Req, this->Req);
|
||||
|
||||
/* save the reference of the ASSIGN */
|
||||
|
||||
assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
|
||||
}
|
||||
a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
|
||||
ReadyCount--;
|
||||
ReqCount++;
|
||||
|
||||
e_no = look_req(a);
|
||||
}
|
||||
|
||||
/* send the filled request buffers to the ISDN adapter */
|
||||
|
||||
a->ram_out(a, &PR_RAM->ReqInput,
|
||||
(byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
|
||||
|
||||
/* if it is a 'unreturncoded' UREMOVE request, remove the */
|
||||
/* Id from our table after sending the request */
|
||||
if(this->Req==UREMOVE && this->Id) {
|
||||
Id = this->Id;
|
||||
e_no = a->IdTable[Id];
|
||||
free_entity(a, e_no);
|
||||
a->IdTable[Id] = 0;
|
||||
this->Id = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* isdn interrupt handler */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
byte DivasDpc(ADAPTER * a)
|
||||
{
|
||||
byte Count;
|
||||
RC * RcIn;
|
||||
IND * IndIn;
|
||||
byte c;
|
||||
byte RNRId;
|
||||
byte Rc;
|
||||
byte Ind;
|
||||
|
||||
/* if return codes are available ... */
|
||||
if((Count = a->ram_in(a, &PR_RAM->RcOutput))) {
|
||||
|
||||
DPRINTF(("IDI: #Rc=%x",Count));
|
||||
|
||||
/* get the buffer address of the first return code */
|
||||
RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
|
||||
|
||||
/* for all return codes do ... */
|
||||
while(Count--) {
|
||||
|
||||
if((Rc=a->ram_in(a, &RcIn->Rc))) {
|
||||
|
||||
/* call return code handler, if it is not our return code */
|
||||
/* the handler returns 2 */
|
||||
/* for all return codes we process, we clear the Rc field */
|
||||
isdn_rc(a,
|
||||
Rc,
|
||||
a->ram_in(a, &RcIn->RcId),
|
||||
a->ram_in(a, &RcIn->RcCh),
|
||||
a->ram_inw(a, &RcIn->Reference));
|
||||
|
||||
a->ram_out(a, &RcIn->Rc, 0);
|
||||
}
|
||||
|
||||
/* get buffer address of next return code */
|
||||
RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
|
||||
}
|
||||
|
||||
/* clear all return codes (no chaining!) */
|
||||
a->ram_out(a, &PR_RAM->RcOutput ,0);
|
||||
|
||||
/* call output function */
|
||||
DivasOut(a);
|
||||
}
|
||||
|
||||
/* clear RNR flag */
|
||||
RNRId = 0;
|
||||
|
||||
/* if indications are available ... */
|
||||
if((Count = a->ram_in(a, &PR_RAM->IndOutput))) {
|
||||
|
||||
DPRINTF(("IDI: #Ind=%x",Count));
|
||||
|
||||
/* get the buffer address of the first indication */
|
||||
IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
|
||||
|
||||
/* for all indications do ... */
|
||||
while(Count--) {
|
||||
|
||||
/* if the application marks an indication as RNR, all */
|
||||
/* indications from the same Id delivered in this interrupt */
|
||||
/* are marked RNR */
|
||||
if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
|
||||
a->ram_out(a, &IndIn->Ind, 0);
|
||||
a->ram_out(a, &IndIn->RNR, TRUE);
|
||||
}
|
||||
else {
|
||||
Ind = a->ram_in(a, &IndIn->Ind);
|
||||
if(Ind) {
|
||||
RNRId = 0;
|
||||
|
||||
/* call indication handler, a return value of 2 means chain */
|
||||
/* a return value of 1 means RNR */
|
||||
/* for all indications we process, we clear the Ind field */
|
||||
c = isdn_ind(a,
|
||||
Ind,
|
||||
a->ram_in(a, &IndIn->IndId),
|
||||
a->ram_in(a, &IndIn->IndCh),
|
||||
&IndIn->RBuffer,
|
||||
a->ram_in(a, &IndIn->MInd),
|
||||
a->ram_inw(a, &IndIn->MLength));
|
||||
|
||||
if(c==1) {
|
||||
DPRINTF(("IDI: RNR"));
|
||||
a->ram_out(a, &IndIn->Ind, 0);
|
||||
RNRId = a->ram_in(a, &IndIn->IndId);
|
||||
a->ram_out(a, &IndIn->RNR, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get buffer address of next indication */
|
||||
IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
|
||||
}
|
||||
|
||||
a->ram_out(a, &PR_RAM->IndOutput, 0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
byte DivasTestInt(ADAPTER * a)
|
||||
{
|
||||
return a->ram_in(a,(void *)0x3fe);
|
||||
}
|
||||
|
||||
void DivasClearInt(ADAPTER * a)
|
||||
{
|
||||
a->ram_out(a,(void *)0x3fe,0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* return code handler */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
byte isdn_rc(ADAPTER * a,
|
||||
byte Rc,
|
||||
byte Id,
|
||||
byte Ch,
|
||||
word Ref)
|
||||
{
|
||||
ENTITY * this;
|
||||
byte e_no;
|
||||
|
||||
#ifdef USE_EXTENDED_DEBUGS
|
||||
{
|
||||
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
|
||||
DPRINTF(("IDI: <A%d Id=0x%x Rc=0x%x", io->ANum, Id, Rc))
|
||||
}
|
||||
#else
|
||||
DPRINTF(("IDI: <RC(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
|
||||
#endif
|
||||
|
||||
/* check for ready interrupt */
|
||||
if(Rc==READY_INT) {
|
||||
if(a->ReadyInt) {
|
||||
a->ReadyInt--;
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* if we know this Id ... */
|
||||
e_no = a->IdTable[Id];
|
||||
if(e_no) {
|
||||
|
||||
this = entity_ptr(a,e_no);
|
||||
|
||||
this->RcCh = Ch;
|
||||
|
||||
/* if it is a return code to a REMOVE request, remove the */
|
||||
/* Id from our table */
|
||||
if(this->Req==REMOVE && Rc==OK) {
|
||||
free_entity(a, e_no);
|
||||
a->IdTable[Id] = 0;
|
||||
this->Id = 0;
|
||||
/**************************************************************/
|
||||
if ((this->More & XMOREC) > 1) {
|
||||
this->More &= ~XMOREC;
|
||||
this->More |= 1;
|
||||
DPRINTF(("isdn_rc, Id=%x, correct More on REMOVE", Id));
|
||||
}
|
||||
}
|
||||
|
||||
if (Rc==OK_FC) {
|
||||
this->Rc = Rc;
|
||||
this->More = (this->More & (~XBUSY | XMOREC)) | 1;
|
||||
this->complete = 0xFF;
|
||||
CALLBACK(a, this);
|
||||
return 0;
|
||||
}
|
||||
if(this->More &XMOREC)
|
||||
this->More--;
|
||||
|
||||
/* call the application callback function */
|
||||
if(this->More &XMOREF && !(this->More &XMOREC)) {
|
||||
this->Rc = Rc;
|
||||
this->More &=~XBUSY;
|
||||
this->complete=0xff;
|
||||
CALLBACK(a, this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if it's an ASSIGN return code check if it's a return */
|
||||
/* code to an ASSIGN request from us */
|
||||
if((Rc &0xf0)==ASSIGN_RC) {
|
||||
|
||||
e_no = get_assign(a, Ref);
|
||||
|
||||
if(e_no) {
|
||||
|
||||
this = entity_ptr(a,e_no);
|
||||
|
||||
this->Id = Id;
|
||||
|
||||
/* call the application callback function */
|
||||
this->Rc = Rc;
|
||||
this->More &=~XBUSY;
|
||||
this->complete=0xff;
|
||||
CALLBACK(a, this);
|
||||
|
||||
if(Rc==ASSIGN_OK) {
|
||||
a->IdTable[Id] = e_no;
|
||||
}
|
||||
else
|
||||
{
|
||||
free_entity(a, e_no);
|
||||
a->IdTable[Id] = 0;
|
||||
this->Id = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* indication handler */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
byte isdn_ind(ADAPTER * a,
|
||||
byte Ind,
|
||||
byte Id,
|
||||
byte Ch,
|
||||
PBUFFER * RBuffer,
|
||||
byte MInd,
|
||||
word MLength)
|
||||
{
|
||||
ENTITY * this;
|
||||
word clength;
|
||||
word offset;
|
||||
BUFFERS *R;
|
||||
|
||||
#ifdef USE_EXTENDED_DEBUGS
|
||||
{
|
||||
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
|
||||
DPRINTF(("IDI: <A%d Id=0x%x Ind=0x%x", io->ANum, Id, Ind))
|
||||
}
|
||||
#else
|
||||
DPRINTF(("IDI: <IND(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
|
||||
#endif
|
||||
|
||||
if(a->IdTable[Id]) {
|
||||
|
||||
this = entity_ptr(a,a->IdTable[Id]);
|
||||
|
||||
this->IndCh = Ch;
|
||||
|
||||
/* if the Receive More flag is not yet set, this is the */
|
||||
/* first buffer of the packet */
|
||||
if(this->RCurrent==0xff) {
|
||||
|
||||
/* check for receive buffer chaining */
|
||||
if(Ind==this->MInd) {
|
||||
this->complete = 0;
|
||||
this->Ind = MInd;
|
||||
}
|
||||
else {
|
||||
this->complete = 1;
|
||||
this->Ind = Ind;
|
||||
}
|
||||
|
||||
/* call the application callback function for the receive */
|
||||
/* look ahead */
|
||||
this->RLength = MLength;
|
||||
|
||||
a->ram_look_ahead(a, RBuffer, this);
|
||||
|
||||
this->RNum = 0;
|
||||
CALLBACK(a, this);
|
||||
|
||||
/* map entity ptr, selector could be re-mapped by call to */
|
||||
/* IDI from within callback */
|
||||
this = entity_ptr(a,a->IdTable[Id]);
|
||||
|
||||
/* check for RNR */
|
||||
if(this->RNR==1) {
|
||||
this->RNR = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if no buffers are provided by the application, the */
|
||||
/* application want to copy the data itself including */
|
||||
/* N_MDATA/LL_MDATA chaining */
|
||||
if(!this->RNR && !this->RNum) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if there is no RNR, set the More flag */
|
||||
this->RCurrent = 0;
|
||||
this->ROffset = 0;
|
||||
}
|
||||
|
||||
if(this->RNR==2) {
|
||||
if(Ind!=this->MInd) {
|
||||
this->RCurrent = 0xff;
|
||||
this->RNR = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* if we have received buffers from the application, copy */
|
||||
/* the data into these buffers */
|
||||
offset = 0;
|
||||
R = PTR_R(a,this);
|
||||
do {
|
||||
if(this->ROffset==R[this->RCurrent].PLength) {
|
||||
this->ROffset = 0;
|
||||
this->RCurrent++;
|
||||
}
|
||||
clength = a->ram_inw(a, &RBuffer->length)-offset;
|
||||
if (clength > R[this->RCurrent].PLength-this->ROffset)
|
||||
clength = R[this->RCurrent].PLength-this->ROffset;
|
||||
if(R[this->RCurrent].P) {
|
||||
a->ram_in_buffer(a,
|
||||
&RBuffer->P[offset],
|
||||
PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
|
||||
clength);
|
||||
}
|
||||
offset +=clength;
|
||||
this->ROffset +=clength;
|
||||
} while(offset<(a->ram_inw(a, &RBuffer->length)));
|
||||
|
||||
/* if it's the last buffer of the packet, call the */
|
||||
/* application callback function for the receive complete */
|
||||
/* call */
|
||||
if(Ind!=this->MInd) {
|
||||
R[this->RCurrent].PLength = this->ROffset;
|
||||
if(this->ROffset) this->RCurrent++;
|
||||
this->RNum = this->RCurrent;
|
||||
this->RCurrent = 0xff;
|
||||
this->Ind = Ind;
|
||||
this->complete = 2;
|
||||
CALLBACK(a, this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* External IDI interface
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(IDI_H)
|
||||
#define IDI_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
/* typedefs for our data structures */
|
||||
|
||||
typedef struct get_name_s GET_NAME;
|
||||
typedef struct entity_s ENTITY;
|
||||
typedef struct buffers_s BUFFERS;
|
||||
|
||||
/* IDI request/callback function pointer */
|
||||
|
||||
typedef void (* IDI_CALL)(ENTITY *);
|
||||
|
||||
typedef struct {
|
||||
word length; /* length of data/parameter field */
|
||||
byte P[270]; /* data/parameter field */
|
||||
} DBUFFER;
|
||||
|
||||
#define REQ_NAME 0x0100
|
||||
#define BOARD_NAME_LENGTH 9
|
||||
struct get_name_s {
|
||||
word command; /* command = 0x0100 */
|
||||
byte name[BOARD_NAME_LENGTH];
|
||||
};
|
||||
|
||||
#define REQ_REMOVE 0x0000 /* pointer to word which is 0 */
|
||||
#define REQ_SERIAL 0x0200
|
||||
struct get_serial_s {
|
||||
word command; /* command = 0x0200 */
|
||||
dword serial; /* serial number */
|
||||
};
|
||||
|
||||
#define REQ_POSTCALL 0x0300
|
||||
struct postcall_s {
|
||||
word command; /* command = 0x0300 */
|
||||
word dummy; /* not used */
|
||||
IDI_CALL callback; /* routine address to call back */
|
||||
ENTITY *contxt; /* ptr to entity to use */
|
||||
};
|
||||
|
||||
#define REQ_XLOG 0x0400 /* structure is card dependent/defined locally */
|
||||
|
||||
struct buffers_s {
|
||||
word PLength;
|
||||
byte *P;
|
||||
};
|
||||
|
||||
struct entity_s {
|
||||
byte Req; /* pending request */
|
||||
byte Rc; /* return code received */
|
||||
byte Ind; /* indication received */
|
||||
byte ReqCh; /* channel of current Req */
|
||||
byte RcCh; /* channel of current Rc */
|
||||
byte IndCh; /* channel of current Ind */
|
||||
byte Id; /* ID used by this entity */
|
||||
byte GlobalId; /* reserved field */
|
||||
byte XNum; /* number of X-buffers */
|
||||
byte RNum; /* number of R-buffers */
|
||||
BUFFERS *X; /* pointer to X-buffer list */
|
||||
BUFFERS *R; /* pointer to R-buffer list */
|
||||
word RLength; /* length of current R-data */
|
||||
DBUFFER *RBuffer; /* buffer of current R-data */
|
||||
byte RNR; /* receive not ready flag */
|
||||
byte complete; /* receive complete status */
|
||||
IDI_CALL callback;
|
||||
|
||||
word user[2];
|
||||
|
||||
/* fields used by the driver internally */
|
||||
byte No; /* entity number */
|
||||
byte reserved2; /* reserved field */
|
||||
byte More; /* R/X More flags */
|
||||
byte MInd; /* MDATA coding for this ID */
|
||||
byte XCurrent; /* current transmit buffer */
|
||||
byte RCurrent; /* current receive buffer */
|
||||
word XOffset; /* offset in x-buffer */
|
||||
word ROffset; /* offset in r-buffer */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
byte type;
|
||||
byte channels;
|
||||
word features;
|
||||
/* dword serial; */
|
||||
IDI_CALL request;
|
||||
} DESCRIPTOR;
|
||||
|
||||
extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
|
||||
|
||||
/* descriptor type field coding */
|
||||
#define IDI_ADAPTER_S 1
|
||||
#define IDI_ADAPTER_PR 2
|
||||
#define IDI_ADAPTER_DIVA 3
|
||||
#define IDI_ADAPTER_MAESTRA 4
|
||||
#define IDI_ADAPTER_MAESTRAQ 5
|
||||
#define IDI_ADAPTER_MAESTRAP 6
|
||||
#define IDI_VADAPTER 0x40
|
||||
#define IDI_DRIVER 0x80
|
||||
#define IDI_DIMAINT 0xff
|
||||
|
||||
/* feature bit mask values */
|
||||
|
||||
#define DI_VOICE 0x0 /* obsolete define */
|
||||
#define DI_FAX3 0x1
|
||||
#define DI_MODEM 0x2
|
||||
#define DI_POST 0x4
|
||||
#define DI_V110 0x8
|
||||
#define DI_V120 0x10
|
||||
#define DI_POTS 0x20
|
||||
#define DI_CODEC 0x40
|
||||
#define DI_MANAGE 0x80
|
||||
#define DI_V_42 0x0100
|
||||
#define DI_EXTD_FAX 0x0200 /* Extended FAX (ECM, 2D, T.6, Polling) */
|
||||
|
||||
#endif /* IDI_H */
|
|
@ -0,0 +1,514 @@
|
|||
/*
|
||||
* Source file for kernel interface to kernel log facility
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.3
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "eicon.h"
|
||||
#include "sys.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "divas.h"
|
||||
#include "divalog.h"
|
||||
#include "uxio.h"
|
||||
|
||||
/*
|
||||
* Implementation of printf and sprintf for kernel
|
||||
*/
|
||||
|
||||
#define MAX_BUFF (80) /* limit size of temporary buffers */
|
||||
|
||||
#define WRITE_CHAR(BUFFER, SIZE, C) \
|
||||
if (--(SIZE) < 0) { (BUFFER)--; *(BUFFER) = '\0'; return; } *(BUFFER)++ = (C)
|
||||
|
||||
|
||||
/*
|
||||
* convert a number to decimal ASCII
|
||||
*/
|
||||
|
||||
static
|
||||
void do_decimal( char *temp,
|
||||
int temp_len,
|
||||
unsigned int value,
|
||||
char *s)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
temp[0] = '\0';
|
||||
|
||||
for (i = 1; i < temp_len; i++)
|
||||
{
|
||||
temp[i] = (char) ((value % 10) + (int) '0');
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
for (i = (temp_len - 1); temp[i] == '0'; i--)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i >= 0)
|
||||
{
|
||||
*s++ = temp[i--];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert a number to octal ASCII
|
||||
*/
|
||||
|
||||
static
|
||||
void do_octal( char *temp,
|
||||
unsigned int value,
|
||||
char *s)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
temp[0] = '\0';
|
||||
|
||||
for (i = 1; i <= 11; i++)
|
||||
{
|
||||
temp[i] = (char) ((value & 07) + (int) '0');
|
||||
value >>= 3;
|
||||
}
|
||||
temp[11] &= '3';
|
||||
|
||||
for (i = 11; temp[i] == '0'; i--)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i >= 0)
|
||||
{
|
||||
*s++ = temp[i--];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert a number to hex ASCII
|
||||
*/
|
||||
|
||||
static
|
||||
void do_hex( char *temp,
|
||||
unsigned int value,
|
||||
char *s)
|
||||
|
||||
{
|
||||
int i;
|
||||
static
|
||||
char *dec_to_hex = "0123456789abcdef";
|
||||
|
||||
temp[0] = '\0';
|
||||
|
||||
for (i = 1; i <= 8; i++)
|
||||
{
|
||||
temp[i] = dec_to_hex[value & 0x0f];
|
||||
value >>= 4;
|
||||
}
|
||||
|
||||
for (i = 8; temp[i] == '0'; i--)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i >= 0)
|
||||
{
|
||||
*s++ = temp[i--];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert a buffer to ASCII HEX
|
||||
*/
|
||||
|
||||
static
|
||||
void do_buffer( char *buffer,
|
||||
int length,
|
||||
char *s)
|
||||
|
||||
{
|
||||
static
|
||||
char hex_char [] = "0123456789abcdef";
|
||||
char *b = buffer;
|
||||
int hex_byte;
|
||||
int nybble;
|
||||
|
||||
length = (length >= ((MAX_BUFF / 3) + 1)) ? (MAX_BUFF / 3) : length;
|
||||
|
||||
while (length)
|
||||
{
|
||||
hex_byte = (int) *b++;
|
||||
nybble = (hex_byte >> 4) & 0xf;
|
||||
*s++ = hex_char[nybble];
|
||||
nybble = hex_byte & 0xf;
|
||||
*s++ = hex_char[nybble];
|
||||
*s++ = ' ';
|
||||
length--;
|
||||
}
|
||||
*s = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Body of sprintf function: behaves just like standard sprintf, except we
|
||||
* have an extra argument (buffer size) which we use to ensure we don't
|
||||
* overflow
|
||||
*/
|
||||
|
||||
void Divas_vsprintf( char *buffer,
|
||||
int size,
|
||||
char *fmt,
|
||||
va_list argptr)
|
||||
|
||||
{
|
||||
char c; /* single character buffer */
|
||||
int i; /* handy scratch counter */
|
||||
int f; /* format character (after %) */
|
||||
char *str; /* pointer into string */
|
||||
char temp[20]; /* temp buffer used in printing numbers */
|
||||
char string[MAX_BUFF]; /* output from number conversion */
|
||||
int length; /* length of string "str" */
|
||||
char fill; /* fill character ' ' or '0' */
|
||||
boolean_t leftjust; /* TRUE if left justified, else right justified */
|
||||
int fmax, fmin; /* field specifiers % MIN . MAX s */
|
||||
int leading; /* number of leading/trailing fill characters */
|
||||
char sign; /* set to '-' for negative decimals */
|
||||
int number; /* numeric argument */
|
||||
|
||||
char *buff_ptr; /* pointer to user's buffer of hex data */
|
||||
int buff_len; /* length of hex data */
|
||||
|
||||
/* make sure we have somthing to write into */
|
||||
|
||||
if ((!buffer) || (size <= 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
/* echo characters until end or '%' encountered */
|
||||
|
||||
while ((c = *fmt++) != '%')
|
||||
{
|
||||
if (!c)
|
||||
{
|
||||
*buffer = '\0';
|
||||
return;
|
||||
}
|
||||
WRITE_CHAR(buffer, size, c);
|
||||
}
|
||||
|
||||
/* echo %% as % */
|
||||
|
||||
if (*fmt == '%')
|
||||
{
|
||||
WRITE_CHAR(buffer, size, *fmt);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* %- turns on left-justify */
|
||||
|
||||
if ((leftjust = (boolean_t) ((*fmt == '-') ? TRUE : FALSE)))
|
||||
{
|
||||
fmt++;
|
||||
}
|
||||
|
||||
/* %0 turns on zero filling */
|
||||
|
||||
if (*fmt == '0')
|
||||
{
|
||||
fill = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
fill = ' ';
|
||||
}
|
||||
|
||||
/* minium field width specifier for %d, u, x, c, s */
|
||||
|
||||
fmin = 0;
|
||||
|
||||
if (*fmt == '*')
|
||||
{
|
||||
fmin = va_arg(argptr, int);
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ('0' <= *fmt && *fmt <= '9')
|
||||
{
|
||||
fmin = (fmin * 10) + (*fmt++ - '0');
|
||||
}
|
||||
}
|
||||
|
||||
/* maximum string width specifier for %s */
|
||||
|
||||
fmax = 0;
|
||||
|
||||
if (*fmt == '.')
|
||||
{
|
||||
if (*(++fmt) == '*')
|
||||
{
|
||||
fmax = va_arg(argptr, int);
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ('0' <= *fmt && *fmt <= '9')
|
||||
{
|
||||
fmax = (fmax * 10) + (*fmt++ - '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* skip over 'l' option (ints are assumed same size as longs) */
|
||||
|
||||
if (*fmt == 'l')
|
||||
{
|
||||
fmt++;
|
||||
}
|
||||
|
||||
/* get the format chacater */
|
||||
|
||||
if (!(f = *fmt++))
|
||||
{
|
||||
WRITE_CHAR(buffer, size, '%');
|
||||
*buffer = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
sign = '\0'; /* sign == '-' for negative decimal */
|
||||
|
||||
str = string;
|
||||
|
||||
switch (f)
|
||||
{
|
||||
case 'c' :
|
||||
string[0] = (char) va_arg(argptr, int);
|
||||
string[1] = '\0';
|
||||
fmax = 0;
|
||||
fill = ' ';
|
||||
break;
|
||||
|
||||
case 's' :
|
||||
str = va_arg(argptr, char *);
|
||||
fill = ' ';
|
||||
break;
|
||||
|
||||
case 'D' :
|
||||
case 'd' :
|
||||
number = va_arg(argptr, int);
|
||||
if (number < 0)
|
||||
{
|
||||
sign = '-';
|
||||
number = -number;
|
||||
}
|
||||
do_decimal(temp, DIM(temp), (unsigned int) number, str);
|
||||
fmax = 0;
|
||||
break;
|
||||
|
||||
case 'U' :
|
||||
case 'u' :
|
||||
number = va_arg(argptr, int);
|
||||
do_decimal(temp, DIM(temp), (unsigned int) number, str);
|
||||
fmax = 0;
|
||||
break;
|
||||
|
||||
case 'O' :
|
||||
case 'o' :
|
||||
number = va_arg(argptr, int);
|
||||
do_octal(temp, (unsigned int) number, str);
|
||||
fmax = 0;
|
||||
break;
|
||||
|
||||
case 'X' :
|
||||
case 'x' :
|
||||
number = va_arg(argptr, int);
|
||||
do_hex(temp, (unsigned int) number, str);
|
||||
fmax = 0;
|
||||
break;
|
||||
|
||||
case 'H' :
|
||||
case 'h' :
|
||||
buff_ptr = va_arg(argptr, char *);
|
||||
buff_len = va_arg(argptr, int);
|
||||
do_buffer(buff_ptr, buff_len, str);
|
||||
fmax = 0;
|
||||
break;
|
||||
|
||||
default :
|
||||
WRITE_CHAR(buffer, size, ((char) f));
|
||||
break;
|
||||
}
|
||||
|
||||
/* get the length of the string */
|
||||
|
||||
length = 0;
|
||||
while (str[length])
|
||||
{
|
||||
length++;
|
||||
}
|
||||
|
||||
/* make sure we have fmax and fmin values that are O.K. */
|
||||
|
||||
if (fmin > DIM(string) || fmin < 0)
|
||||
{
|
||||
fmin = 0;
|
||||
}
|
||||
|
||||
if (fmax > DIM(string) || fmax < 0)
|
||||
{
|
||||
fmax = 0;
|
||||
}
|
||||
|
||||
/* figure out how many leading characters thare are */
|
||||
|
||||
leading = 0;
|
||||
|
||||
if (fmax || fmin)
|
||||
{
|
||||
if (fmax)
|
||||
{
|
||||
if (length > fmax)
|
||||
{
|
||||
length = fmax;
|
||||
}
|
||||
}
|
||||
|
||||
if (fmin)
|
||||
{
|
||||
leading = fmin - length;
|
||||
}
|
||||
|
||||
if (sign == '-')
|
||||
{
|
||||
leading--;
|
||||
}
|
||||
}
|
||||
|
||||
/* output sign now, if fill is numeric */
|
||||
|
||||
if (sign == '-' && fill == '0')
|
||||
{
|
||||
WRITE_CHAR(buffer, size, '-');
|
||||
}
|
||||
|
||||
/* if right justified, output fill characters */
|
||||
|
||||
if (!leftjust)
|
||||
{
|
||||
for (i = 0; i < leading; i++)
|
||||
{
|
||||
WRITE_CHAR(buffer, size, fill);
|
||||
}
|
||||
}
|
||||
|
||||
/* output sign now, if fill is spaces */
|
||||
|
||||
if (sign == '-' && fill == ' ')
|
||||
{
|
||||
WRITE_CHAR(buffer, size, '-');
|
||||
}
|
||||
|
||||
/* now the actual value */
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
WRITE_CHAR(buffer, size, str[i]);
|
||||
}
|
||||
|
||||
/* if left justified, fill out with the fill character */
|
||||
|
||||
if (leftjust)
|
||||
{
|
||||
for (i = 0; i < leading; i++)
|
||||
{
|
||||
WRITE_CHAR(buffer, size, fill);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sprintf for kernel
|
||||
*
|
||||
* call our vsprintf assuming user has a big buffer....
|
||||
*/
|
||||
|
||||
void DivasSprintf(char *buffer, char *fmt, ...)
|
||||
|
||||
{
|
||||
va_list argptr; /* pointer to additional args */
|
||||
|
||||
va_start(argptr, fmt);
|
||||
|
||||
Divas_vsprintf(buffer, 1024, fmt, argptr);
|
||||
|
||||
va_end(argptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DivasPrintf(char *fmt, ...)
|
||||
|
||||
{
|
||||
klog_t log; /* log entry buffer */
|
||||
|
||||
va_list argptr; /* pointer to additional args */
|
||||
|
||||
va_start(argptr, fmt);
|
||||
|
||||
/* clear log entry */
|
||||
|
||||
memset((void *) &log, 0, sizeof(klog_t));
|
||||
|
||||
log.card = -1;
|
||||
log.type = KLOG_TEXT_MSG;
|
||||
|
||||
/* time stamp the entry */
|
||||
|
||||
log.time_stamp = UxTimeGet();
|
||||
|
||||
/* call vsprintf to format the user's information */
|
||||
|
||||
Divas_vsprintf(log.buffer, DIM(log.buffer), fmt, argptr);
|
||||
|
||||
va_end(argptr);
|
||||
|
||||
/* send to the log streams driver and return */
|
||||
|
||||
DivasLogAdd(&log, sizeof(klog_t));
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.9
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#undef N_DATA /* Because we have our own definition */
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "constant.h"
|
||||
#include "divas.h"
|
||||
#undef ID_MASK
|
||||
#include "pc.h"
|
||||
#include "pr_pc.h"
|
||||
|
||||
#include "adapter.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#include <linux/pci.h>
|
||||
#ifndef COMPAT_HAS_2_2_PCI
|
||||
#include <linux/pci_ids.h>
|
||||
#endif
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
struct file_operations Divas_fops;
|
||||
int Divas_major;
|
||||
|
||||
extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
|
||||
unsigned int command, unsigned long arg);
|
||||
extern unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable);
|
||||
extern ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset);
|
||||
extern int do_open(struct inode *, struct file *);
|
||||
extern int do_release(struct inode *, struct file *);
|
||||
|
||||
int FPGA_Done=0;
|
||||
|
||||
int DivasCardsDiscover(void)
|
||||
{
|
||||
word wNumCards = 0, wDeviceIndex = 0;
|
||||
byte byBus, byFunc;
|
||||
word wPCIConsultation, PCItmp;
|
||||
dword j, i;
|
||||
unsigned int PCIserial;
|
||||
dia_card_t Card;
|
||||
byte *b;
|
||||
|
||||
while (wDeviceIndex < 10)
|
||||
{
|
||||
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
|
||||
PCI_DEVICE_ID_EICON_MAESTRAQ,
|
||||
wDeviceIndex,
|
||||
&byBus, &byFunc);
|
||||
|
||||
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
|
||||
{
|
||||
|
||||
dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;
|
||||
byte byIRQ;
|
||||
|
||||
printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
|
||||
dwRAM &= 0xFFC00000;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
|
||||
dwDivasIOBase &= 0xFFFFFF00;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
|
||||
dwCFG &= 0xFFFFFF00;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
|
||||
dwCTL &= 0xFFFFE000;
|
||||
|
||||
|
||||
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
|
||||
/* Retrieve the serial number */
|
||||
|
||||
pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
|
||||
|
||||
for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
|
||||
{
|
||||
pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
|
||||
PCItmp &= 0x8000; // extract done flag
|
||||
}
|
||||
|
||||
pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
|
||||
|
||||
|
||||
Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
|
||||
Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
|
||||
Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
|
||||
Card.io_base=dwDivasIOBase;
|
||||
|
||||
Card.irq = byIRQ;
|
||||
|
||||
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
|
||||
Card.bus_type = DIA_BUS_TYPE_PCI;
|
||||
|
||||
FPGA_Done = 0;
|
||||
|
||||
/* Create four virtual card structures as we want to treat
|
||||
the 4Bri card as 4 Bri cards*/
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
|
||||
b=Card.memory[DIVAS_RAM_MEMORY];
|
||||
b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1);
|
||||
DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
|
||||
Card.memory[DIVAS_RAM_MEMORY]=b;
|
||||
|
||||
b = Card.memory[DIVAS_RAM_MEMORY];
|
||||
b += MQ_SM_OFFSET;
|
||||
Card.memory[DIVAS_SHARED_MEMORY] = b;
|
||||
|
||||
Card.bus_num = byBus;
|
||||
Card.func_num = byFunc;
|
||||
Card.slot = -1;
|
||||
|
||||
|
||||
/* Fill in Name */
|
||||
Card.name[0] = 'D';
|
||||
Card.name[1] = 'I';
|
||||
Card.name[2] = 'V';
|
||||
Card.name[3] = 'A';
|
||||
Card.name[4] = 'S';
|
||||
Card.name[5] = 'Q';
|
||||
Card.name[6] = '0' + i;
|
||||
Card.name[7] = '\0';
|
||||
|
||||
Card.serial = PCIserial;
|
||||
|
||||
Card.card_id = wNumCards;
|
||||
|
||||
if (DivasCardNew(&Card) != 0)
|
||||
{
|
||||
// Force for loop to terminate
|
||||
i = 4;
|
||||
continue;
|
||||
}
|
||||
wNumCards++;
|
||||
|
||||
}//for
|
||||
}
|
||||
wDeviceIndex++;
|
||||
}
|
||||
|
||||
wDeviceIndex = 0;
|
||||
|
||||
while (wDeviceIndex < 10)
|
||||
{
|
||||
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
|
||||
PCI_DEVICE_ID_EICON_MAESTRA,
|
||||
wDeviceIndex,
|
||||
&byBus, &byFunc);
|
||||
|
||||
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
|
||||
{
|
||||
dword dwPLXIOBase, dwDivasIOBase;
|
||||
byte byIRQ;
|
||||
|
||||
printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
|
||||
dwPLXIOBase &= 0xFFFFFF80;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
|
||||
dwDivasIOBase &= 0xFFFFFFFC;
|
||||
|
||||
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
|
||||
|
||||
Card.card_id = wNumCards;
|
||||
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
|
||||
Card.bus_type = DIA_BUS_TYPE_PCI;
|
||||
Card.irq = byIRQ;
|
||||
Card.reset_base = dwPLXIOBase;
|
||||
Card.io_base = dwDivasIOBase;
|
||||
Card.bus_num = byBus;
|
||||
Card.func_num = byFunc;
|
||||
Card.slot = -1;
|
||||
Card.name[0] = 'D';
|
||||
Card.name[1] = 'I';
|
||||
Card.name[2] = 'V';
|
||||
Card.name[3] = 'A';
|
||||
Card.name[4] = 'S';
|
||||
Card.name[5] = 'B';
|
||||
Card.name[6] = '\0';
|
||||
|
||||
if (check_region(Card.io_base, 0x20))
|
||||
{
|
||||
printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_region(Card.reset_base, 0x80))
|
||||
{
|
||||
printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DivasCardNew(&Card) != 0)
|
||||
{
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
wNumCards++;
|
||||
}
|
||||
|
||||
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
|
||||
PCI_DEVICE_ID_EICON_MAESTRAQ_U,
|
||||
wDeviceIndex,
|
||||
&byBus, &byFunc);
|
||||
|
||||
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
|
||||
{
|
||||
dword dwPLXIOBase, dwDivasIOBase;
|
||||
byte byIRQ;
|
||||
|
||||
printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
|
||||
dwPLXIOBase &= 0xFFFFFF80;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
|
||||
dwDivasIOBase &= 0xFFFFFFFC;
|
||||
|
||||
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
|
||||
|
||||
Card.card_id = wNumCards;
|
||||
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
|
||||
Card.bus_type = DIA_BUS_TYPE_PCI;
|
||||
Card.irq = byIRQ;
|
||||
Card.reset_base = dwPLXIOBase;
|
||||
Card.io_base = dwDivasIOBase;
|
||||
Card.bus_num = byBus;
|
||||
Card.func_num = byFunc;
|
||||
Card.slot = -1;
|
||||
Card.name[0] = 'D';
|
||||
Card.name[1] = 'I';
|
||||
Card.name[2] = 'V';
|
||||
Card.name[3] = 'A';
|
||||
Card.name[4] = 'S';
|
||||
Card.name[5] = 'B';
|
||||
Card.name[6] = '\0';
|
||||
|
||||
if (check_region(Card.io_base, 0x20))
|
||||
{
|
||||
printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_region(Card.reset_base, 0x80))
|
||||
{
|
||||
printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DivasCardNew(&Card) != 0)
|
||||
{
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
wNumCards++;
|
||||
}
|
||||
|
||||
wDeviceIndex++;
|
||||
}
|
||||
|
||||
wDeviceIndex = 0;
|
||||
|
||||
while (wDeviceIndex < 10)
|
||||
{
|
||||
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
|
||||
PCI_DEVICE_ID_EICON_MAESTRAP,
|
||||
wDeviceIndex,
|
||||
&byBus, &byFunc);
|
||||
|
||||
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
|
||||
{
|
||||
dword dwRAM, dwREG, dwCFG;
|
||||
byte byIRQ;
|
||||
|
||||
printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
|
||||
dwRAM &= 0xFFFFF000;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
|
||||
dwREG &= 0xFFFFF000;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
|
||||
dwCFG &= 0xFFFFF000;
|
||||
|
||||
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
|
||||
|
||||
Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
|
||||
Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
|
||||
Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
|
||||
Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
|
||||
|
||||
/* pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
|
||||
dwPLXIOBase &= 0xFFFFFFFc;
|
||||
|
||||
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
|
||||
dwDivasIOBase &= 0xFFFFFF80;
|
||||
|
||||
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
|
||||
*/
|
||||
Card.card_id = wNumCards;
|
||||
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
|
||||
Card.bus_type = DIA_BUS_TYPE_PCI;
|
||||
Card.irq = byIRQ;
|
||||
/* Card.reset_base = dwPLXIOBase;
|
||||
Card.io_base = dwDivasIOBase;*/
|
||||
Card.bus_num = byBus;
|
||||
Card.func_num = byFunc;
|
||||
Card.slot = -1;
|
||||
Card.name[0] = 'D';
|
||||
Card.name[1] = 'I';
|
||||
Card.name[2] = 'V';
|
||||
Card.name[3] = 'A';
|
||||
Card.name[4] = 'S';
|
||||
Card.name[5] = 'P';
|
||||
Card.name[6] = '\0';
|
||||
|
||||
if (DivasCardNew(&Card) != 0)
|
||||
{
|
||||
wDeviceIndex++;
|
||||
continue;
|
||||
}
|
||||
wNumCards++;
|
||||
}
|
||||
|
||||
wDeviceIndex++;
|
||||
}
|
||||
|
||||
|
||||
printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
|
||||
|
||||
if(wNumCards == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Divas_fops.ioctl = do_ioctl;
|
||||
Divas_fops.poll = do_poll;
|
||||
Divas_fops.read = do_read;
|
||||
Divas_fops.open = do_open;
|
||||
Divas_fops.release = do_release;
|
||||
|
||||
Divas_major = register_chrdev(0, "Divas", &Divas_fops);
|
||||
|
||||
if (Divas_major < 0)
|
||||
{
|
||||
printk(KERN_WARNING "Divas: Unable to register character driver\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Error return -1 */
|
||||
int DivasConfigGet(dia_card_t *card)
|
||||
{
|
||||
/* Retrieve Config from O/S? Not in Linux */
|
||||
return 0;
|
||||
}
|
||||
|
||||
dia_config_t *DivasConfig(card_t *card, dia_config_t *config)
|
||||
{
|
||||
/* If config retrieved from OS then copy the data into a dia_config_t structure here
|
||||
and return the pointer here. If the config 'came from above' then just
|
||||
|
||||
return config;
|
||||
*/
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.12
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#undef N_DATA
|
||||
|
||||
#include "adapter.h"
|
||||
#include "divas.h"
|
||||
#include "divalog.h"
|
||||
|
||||
extern int DivasCardNext;
|
||||
void UxPause(long ms);
|
||||
int DivasGetMem(mem_block_t *);
|
||||
|
||||
#define DIA_IOCTL_UNLOCK 12
|
||||
void UnlockDivas(void);
|
||||
|
||||
int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
|
||||
unsigned int command, unsigned long arg)
|
||||
{
|
||||
byte *pUserCards, card_i;
|
||||
word wCardNum;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case DIA_IOCTL_CONFIG:
|
||||
{
|
||||
dia_config_t DivaConfig;
|
||||
if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t)))
|
||||
return -EFAULT;
|
||||
DivasCardConfig(&DivaConfig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case DIA_IOCTL_DETECT:
|
||||
pUserCards = (byte *) arg;
|
||||
|
||||
if (!verify_area(VERIFY_WRITE, pUserCards, 20))
|
||||
{
|
||||
if(__put_user(DivasCardNext, pUserCards++))
|
||||
return -EFAULT;
|
||||
|
||||
for (card_i=1; card_i < 20; card_i++)
|
||||
{
|
||||
if(__put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
else return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
case DIA_IOCTL_START:
|
||||
{
|
||||
dia_start_t DivaStart;
|
||||
if (copy_from_user(&DivaStart, (void *)arg, sizeof(dia_start_t)))
|
||||
return -EFAULT;
|
||||
return DivasCardStart(DivaStart.card_id);
|
||||
}
|
||||
|
||||
case DIA_IOCTL_FLAVOUR:
|
||||
return 0;
|
||||
|
||||
case DIA_IOCTL_LOAD:
|
||||
{
|
||||
dia_load_t DivaLoad;
|
||||
if(copy_from_user(&DivaLoad, (void *)arg, sizeof(dia_load_t)))
|
||||
return -EFAULT;
|
||||
if (!verify_area(VERIFY_READ, DivaLoad.code,DivaLoad.length))
|
||||
{
|
||||
if (DivasCardLoad(&DivaLoad))
|
||||
{
|
||||
printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -EFAULT;
|
||||
}
|
||||
case DIA_IOCTL_LOG:
|
||||
{
|
||||
dia_log_t DivaLog;
|
||||
if (copy_from_user(&DivaLog, (void *) arg, sizeof(dia_log_t)))
|
||||
return -EFAULT;
|
||||
DivasLog(&DivaLog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case DIA_IOCTL_XLOG_REQ:
|
||||
if(get_user(wCardNum, (word *) arg))
|
||||
return -EFAULT;
|
||||
DivasXlogReq(wCardNum);
|
||||
return 0;
|
||||
|
||||
case DIA_IOCTL_GET_NUM:
|
||||
if(put_user(DivasCardNext, (int *)arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case DIA_IOCTL_GET_LIST:
|
||||
{
|
||||
dia_card_list_t cards;
|
||||
DPRINTF(("divas: DIA_IOCTL_GET_LIST"));
|
||||
DivasGetList(&cards);
|
||||
if(copy_to_user((void *)arg, &cards, sizeof(cards)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case DIA_IOCTL_GET_MEM:
|
||||
{
|
||||
mem_block_t mem_block;
|
||||
if (copy_from_user(&mem_block, (void *)arg, sizeof(mem_block_t)))
|
||||
return -EFAULT;
|
||||
DivasGetMem(&mem_block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case DIA_IOCTL_UNLOCK:
|
||||
UnlockDivas();
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
|
||||
{
|
||||
word wMask = 0;
|
||||
|
||||
if (!DivasLogFifoEmpty())
|
||||
wMask |= POLLIN | POLLRDNORM;
|
||||
return wMask;
|
||||
}
|
||||
|
||||
ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset)
|
||||
{
|
||||
klog_t *pClientLogBuffer = (klog_t *) pUserBuffer;
|
||||
klog_t *pHeadItem;
|
||||
|
||||
if (BufferSize < sizeof(klog_t))
|
||||
{
|
||||
printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
|
||||
BufferSize, sizeof(klog_t));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
pHeadItem = (klog_t *) DivasLogFifoRead();
|
||||
|
||||
if (pHeadItem)
|
||||
{
|
||||
memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t));
|
||||
kfree(pHeadItem);
|
||||
return sizeof(klog_t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int private_usage_count;
|
||||
|
||||
int do_open(struct inode *pInode, struct file *pFile)
|
||||
{
|
||||
MOD_INC_USE_COUNT;
|
||||
#ifdef MODULE
|
||||
private_usage_count++;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_release(struct inode *pInode, struct file *pFile)
|
||||
{
|
||||
MOD_DEC_USE_COUNT;
|
||||
#ifdef MODULE
|
||||
private_usage_count--;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UnlockDivas(void)
|
||||
{
|
||||
while (private_usage_count > 0)
|
||||
{
|
||||
private_usage_count--;
|
||||
MOD_DEC_USE_COUNT;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,734 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.16
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#define N_DATA
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/isdn_compat.h>
|
||||
#undef N_DATA
|
||||
|
||||
#include "uxio.h"
|
||||
|
||||
static
|
||||
int log_on=0;
|
||||
|
||||
int Divasdevflag = 0;
|
||||
|
||||
//spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static
|
||||
ux_diva_card_t card_pool[MAX_CARDS];
|
||||
|
||||
void UxPause(long int ms)
|
||||
{
|
||||
int timeout = jiffies + ((ms * HZ) / 1000);
|
||||
|
||||
while (time_before(jiffies, timeout));
|
||||
}
|
||||
|
||||
int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
|
||||
{
|
||||
int i;
|
||||
ux_diva_card_t *c;
|
||||
|
||||
if (cfg->bus_type != DIA_BUS_TYPE_PCI)
|
||||
{
|
||||
DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (i == DIM(card_pool))
|
||||
{
|
||||
DPRINTF(("divas hw: card_pool exhausted"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = *card = &card_pool[i];
|
||||
|
||||
switch (cfg->bus_type)
|
||||
{
|
||||
case DIA_BUS_TYPE_PCI:
|
||||
c->bus_num = cfg->bus_num;
|
||||
c->func_num = cfg->func_num;
|
||||
c->io_base = cfg->io_base;
|
||||
c->reset_base = cfg->reset_base;
|
||||
c->card_type = cfg->card_type;
|
||||
c->mapped = NULL;
|
||||
c->slot = cfg->slot;
|
||||
c->irq = (int) cfg->irq;
|
||||
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
|
||||
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
|
||||
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
|
||||
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
|
||||
c->pCONTROL = cfg->memory[DIVAS_CTL_MEMORY];
|
||||
|
||||
/* c->bus_type = DIA_BUS_TYPE_PCI;
|
||||
c->bus_num = cfg->bus_num & 0x3f;
|
||||
c->slot = cfg->slot;
|
||||
c->irq = (int) cfg->irq;
|
||||
c->int_priority = (int) cfg->int_priority;
|
||||
c->card_type = cfg->card_type;
|
||||
c->io_base = cfg->io_base;
|
||||
c->reset_base = cfg->reset_base;
|
||||
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
|
||||
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
|
||||
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
|
||||
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
|
||||
DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
|
||||
DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
|
||||
DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
|
||||
c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
c->in_use = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UxCardHandleFree(ux_diva_card_t *card)
|
||||
{
|
||||
card->in_use = FALSE;
|
||||
}
|
||||
|
||||
|
||||
#define PLX_IOBASE 0
|
||||
#define DIVAS_IOBASE 1
|
||||
void *UxCardMemAttach(ux_diva_card_t *card, int id)
|
||||
{
|
||||
if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case DIVAS_SHARED_MEMORY:
|
||||
card->mapped = card->pSHARED;
|
||||
return card->pSHARED;
|
||||
break;
|
||||
case DIVAS_RAM_MEMORY:
|
||||
card->mapped = card->pDRAM;
|
||||
return card->pDRAM;
|
||||
break;
|
||||
case DIVAS_REG_MEMORY:
|
||||
card->mapped = card->pDEVICES;
|
||||
return card->pDEVICES;
|
||||
break;
|
||||
case DIVAS_CFG_MEMORY:
|
||||
card->mapped = card->pCONFIG;
|
||||
return card->pCONFIG;
|
||||
break;
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
card->mapped = NULL;
|
||||
return (void *) 0;
|
||||
}
|
||||
}
|
||||
else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case PLX_IOBASE:
|
||||
return (void *) card->reset_base;
|
||||
break;
|
||||
case DIVAS_IOBASE:
|
||||
return (void *) card->io_base;
|
||||
break;
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case DIVAS_SHARED_MEMORY:
|
||||
card->mapped = card->pSHARED;
|
||||
return card->pSHARED;
|
||||
break;
|
||||
case DIVAS_RAM_MEMORY:
|
||||
card->mapped = card->pDRAM;
|
||||
return card->pDRAM;
|
||||
break;
|
||||
case DIVAS_REG_MEMORY:
|
||||
card->mapped = (void *) card->io_base;
|
||||
return (void *) card->io_base;
|
||||
break;
|
||||
case DIVAS_CTL_MEMORY:
|
||||
card->mapped = card->pCONTROL;
|
||||
return card->pCONTROL;
|
||||
break;
|
||||
default:
|
||||
// ASSERT(FALSE);
|
||||
DPRINTF(("divas: Trying to attach to mem %d", id));
|
||||
card->mapped = NULL;
|
||||
return (void *) 0;
|
||||
}
|
||||
} else
|
||||
DPRINTF(("divas: Tried to attach to unknown card"));
|
||||
|
||||
/* Unknown card type */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UxCardMemDetach(ux_diva_card_t *card, void *address)
|
||||
{
|
||||
return; // Just a place holder. No un-mapping done.
|
||||
}
|
||||
|
||||
void UxCardLog(int turn_on)
|
||||
{
|
||||
log_on = turn_on;
|
||||
}
|
||||
|
||||
/*
|
||||
* Control Register I/O Routines to be performed on Attached I/O ports
|
||||
*/
|
||||
|
||||
void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
|
||||
{
|
||||
word base = (word) (dword) AttachedBase;
|
||||
|
||||
base += offset;
|
||||
|
||||
outb(the_byte, base);
|
||||
}
|
||||
|
||||
void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
|
||||
{
|
||||
word base = (word) (dword) AttachedBase;
|
||||
|
||||
base += offset;
|
||||
|
||||
outw(the_word, base);
|
||||
}
|
||||
|
||||
void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
|
||||
{
|
||||
word base = (word) (dword) AttachedBase;
|
||||
|
||||
base += offset;
|
||||
|
||||
outl(the_dword, base);
|
||||
}
|
||||
|
||||
byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
|
||||
{
|
||||
word base = (word) (dword) AttachedBase;
|
||||
|
||||
base += offset;
|
||||
|
||||
return inb(base);
|
||||
}
|
||||
|
||||
word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
|
||||
{
|
||||
word base = (word) (dword) AttachedBase;
|
||||
|
||||
base += offset;
|
||||
|
||||
return inw(base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory mapped card I/O functions
|
||||
*/
|
||||
|
||||
byte UxCardMemIn(ux_diva_card_t *card, void *address)
|
||||
{
|
||||
byte b;
|
||||
volatile byte* t = (byte*)address;
|
||||
|
||||
b = *t;
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
|
||||
}
|
||||
|
||||
return(b);
|
||||
}
|
||||
|
||||
word UxCardMemInW(ux_diva_card_t *card, void *address)
|
||||
{
|
||||
word w;
|
||||
volatile word* t = (word*)address;
|
||||
|
||||
w = *t;
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
|
||||
}
|
||||
|
||||
return (w);
|
||||
}
|
||||
|
||||
dword UxCardMemInD(ux_diva_card_t *card, void *address)
|
||||
{
|
||||
dword dw;
|
||||
volatile dword* t = (dword*)address;
|
||||
|
||||
dw = *t;
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
|
||||
}
|
||||
|
||||
return (dw);
|
||||
}
|
||||
|
||||
void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
|
||||
{
|
||||
volatile byte *pSource = address;
|
||||
byte *pDest = buffer;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
*pDest++ = *pSource++;
|
||||
}
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
pDest = buffer;
|
||||
DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)",
|
||||
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
|
||||
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
|
||||
a));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
|
||||
{
|
||||
volatile byte* t = (byte*)address;
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
|
||||
}
|
||||
|
||||
*t = data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
|
||||
{
|
||||
volatile word* t = (word*)address;
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
|
||||
}
|
||||
|
||||
*t = data;
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
|
||||
{
|
||||
volatile dword* t = (dword*)address;
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
|
||||
}
|
||||
|
||||
*t = data;
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
|
||||
{
|
||||
byte *pSource = buffer;
|
||||
byte *pDest = address;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
*pDest++ = *pSource++;
|
||||
}
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
byte *a = address;
|
||||
a -= (int) card->mapped;
|
||||
pDest = buffer;
|
||||
DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)",
|
||||
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
|
||||
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
|
||||
a));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory mapped card I/O functions
|
||||
*/
|
||||
|
||||
byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
|
||||
|
||||
{
|
||||
byte the_byte;
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) address, card->io_base + 4);
|
||||
|
||||
the_byte = inb(card->io_base);
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)",
|
||||
the_byte & 0xff, address));
|
||||
}
|
||||
|
||||
return the_byte;
|
||||
}
|
||||
|
||||
word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
|
||||
|
||||
{
|
||||
word the_word;
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) address, card->io_base + 4);
|
||||
the_word = inw(card->io_base);
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)",
|
||||
the_word & 0xffff, address));
|
||||
}
|
||||
|
||||
return the_word;
|
||||
}
|
||||
|
||||
dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
|
||||
|
||||
{
|
||||
dword the_dword;
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) address, card->io_base + 4);
|
||||
the_dword = inl(card->io_base);
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)",
|
||||
the_dword, address));
|
||||
}
|
||||
|
||||
return the_dword;
|
||||
}
|
||||
|
||||
void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
|
||||
|
||||
{
|
||||
byte *pSource = address;
|
||||
byte *pDest = buffer;
|
||||
|
||||
if ((word) (dword) address & 0x1)
|
||||
{
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) pSource, card->io_base + 4);
|
||||
*pDest = (byte) inb(card->io_base);
|
||||
pDest++;
|
||||
pSource++;
|
||||
length--;
|
||||
if (!length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) pSource, card->io_base + 4);
|
||||
insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
pDest = buffer;
|
||||
DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)",
|
||||
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
|
||||
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
|
||||
address));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Output */
|
||||
|
||||
void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
|
||||
{
|
||||
if (log_on)
|
||||
{
|
||||
DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)",
|
||||
data & 0xff, address));
|
||||
}
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) address, card->io_base + 4);
|
||||
outb((byte) data & 0xFF, card->io_base);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
|
||||
{
|
||||
if (log_on)
|
||||
{
|
||||
DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)",
|
||||
data & 0xffff, address));
|
||||
}
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) address, card->io_base + 4);
|
||||
outw((word) data & 0xFFFF, card->io_base);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
|
||||
{
|
||||
if (log_on)
|
||||
{
|
||||
DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
|
||||
}
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) address, card->io_base + 4);
|
||||
outl((dword) data & 0xFFFFFFFF, card->io_base);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
|
||||
|
||||
{
|
||||
byte *pSource = buffer;
|
||||
byte *pDest = address;
|
||||
|
||||
if ((word) (dword) address & 1)
|
||||
{
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) pDest, card->io_base + 4);
|
||||
outb(*pSource, card->io_base);
|
||||
pSource++;
|
||||
pDest++;
|
||||
length--;
|
||||
if (!length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
outb(0xFF, card->io_base + 0xC);
|
||||
outw((word) (dword) pDest, card->io_base + 4);
|
||||
outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
|
||||
|
||||
if (log_on)
|
||||
{
|
||||
pDest = buffer;
|
||||
DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)",
|
||||
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
|
||||
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
|
||||
address));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
|
||||
{
|
||||
int i;
|
||||
card_t *card = NULL;
|
||||
ux_diva_card_t *ux_ref = NULL;
|
||||
|
||||
for (i = 0; i < DivasCardNext; i++)
|
||||
{
|
||||
|
||||
if (arg == DivasCards[i].cfg.irq)
|
||||
{
|
||||
card = &DivasCards[i];
|
||||
ux_ref = card->hw;
|
||||
|
||||
if ((ux_ref) && (card->is_live))
|
||||
{
|
||||
(*ux_ref->user_isr)(ux_ref->user_isr_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(("divas: ISR couldn't locate card"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
|
||||
{
|
||||
int result;
|
||||
|
||||
card->user_isr = isr_fn;
|
||||
card->user_isr_arg = isr_arg;
|
||||
|
||||
result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
|
||||
{
|
||||
free_irq(card->irq, card->user_isr_arg);
|
||||
}
|
||||
|
||||
void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case sizeof(byte):
|
||||
pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
|
||||
break;
|
||||
case sizeof(word):
|
||||
pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
|
||||
break;
|
||||
case sizeof(dword):
|
||||
pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
|
||||
}
|
||||
}
|
||||
|
||||
void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case sizeof(byte):
|
||||
pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
|
||||
break;
|
||||
case sizeof(word):
|
||||
pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
|
||||
break;
|
||||
case sizeof(dword):
|
||||
pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
|
||||
}
|
||||
}
|
||||
|
||||
void *UxAlloc(unsigned int size)
|
||||
{
|
||||
void *m;
|
||||
|
||||
m = kmalloc(size, GFP_ATOMIC);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void UxFree(void *ptr)
|
||||
{
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
long UxCardLock(ux_diva_card_t *card)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
//spin_lock_irqsave(&diva_lock, flags);
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
return flags;
|
||||
|
||||
}
|
||||
|
||||
void UxCardUnlock(ux_diva_card_t *card, long ipl)
|
||||
{
|
||||
//spin_unlock_irqrestore(&diva_lock, ipl);
|
||||
|
||||
restore_flags(ipl);
|
||||
|
||||
}
|
||||
|
||||
dword UxTimeGet(void)
|
||||
{
|
||||
return jiffies;
|
||||
}
|
||||
|
||||
long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
|
||||
{
|
||||
register volatile long *p;
|
||||
register long ret;
|
||||
int ipl;
|
||||
|
||||
p =dst;
|
||||
|
||||
ipl = UxCardLock(card);
|
||||
|
||||
*p += 1;
|
||||
ret = *p;
|
||||
|
||||
UxCardUnlock(card,ipl);
|
||||
|
||||
return(ret);
|
||||
|
||||
}
|
||||
|
||||
long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
|
||||
{
|
||||
register volatile long *p;
|
||||
register long ret;
|
||||
int ipl;
|
||||
|
||||
p =dst;
|
||||
|
||||
ipl = UxCardLock(card);
|
||||
|
||||
*p -= 1;
|
||||
ret = *p;
|
||||
|
||||
UxCardUnlock(card,ipl);
|
||||
|
||||
return(ret);
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.10
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#undef N_DATA
|
||||
#include <linux/tqueue.h>
|
||||
|
||||
#include <linux/smp.h>
|
||||
struct pt_regs;
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include "sys.h"
|
||||
#include "divas.h"
|
||||
#include "adapter.h"
|
||||
#include "divalog.h"
|
||||
|
||||
#include "uxio.h"
|
||||
|
||||
int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg)
|
||||
{
|
||||
/* Use UxPciConfigWrite routines to initialise PCI config space */
|
||||
|
||||
/* wPCIcommand = 0x03;
|
||||
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
|
||||
|
||||
wPCIcommand = 0x280;
|
||||
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
|
||||
|
||||
bPCIcommand = 0x30;
|
||||
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DivasPRIInitPCI(card_t *card, dia_card_t *cfg)
|
||||
{
|
||||
/* Use UxPciConfigWrite routines to initialise PCI config space */
|
||||
|
||||
/* wPCIcommand = 0x03;
|
||||
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
|
||||
|
||||
wPCIcommand = 0x280;
|
||||
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
|
||||
|
||||
bPCIcommand = 0x30;
|
||||
cm_write_devconfig8(CMKey, PCI_LATENCY, &bPCIcommand);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg)
|
||||
{
|
||||
/* Need to set these platform dependent values after patching */
|
||||
|
||||
card->hw->reset_base = card->cfg.reset_base;
|
||||
card->hw->io_base = card->cfg.io_base;
|
||||
|
||||
request_region(card->hw->reset_base,0x80,"Divas");
|
||||
request_region(card->hw->io_base,0x20,"Divas");
|
||||
|
||||
|
||||
/* Same as for PRI */
|
||||
return DivasPRIInitPCI(card, cfg);
|
||||
}
|
||||
|
||||
/* ######################### Stubs of routines that are not done yet ################## */
|
||||
/*void DivasLogIdi(card_t *card, ENTITY *e, int request)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
int DivasDpcSchedule(void)
|
||||
{
|
||||
static struct tq_struct DivasTask;
|
||||
|
||||
DivasTask.routine = DivasDoDpc;
|
||||
DivasTask.data = (void *) 0;
|
||||
|
||||
queue_task(&DivasTask, &tq_immediate);
|
||||
mark_bh(IMMEDIATE_BH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DivasScheduleRequestDpc(void)
|
||||
{
|
||||
static struct tq_struct DivasTask;
|
||||
|
||||
DivasTask.routine = DivasDoRequestDpc;
|
||||
DivasTask.data = (void *) 0;
|
||||
|
||||
queue_task(&DivasTask, &tq_immediate);
|
||||
mark_bh(IMMEDIATE_BH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DivasLogAdd(void *buffer, int length)
|
||||
{
|
||||
static
|
||||
boolean_t overflow = FALSE;
|
||||
static
|
||||
boolean_t busy = FALSE;
|
||||
|
||||
/* make sure we're not interrupting ourselves */
|
||||
|
||||
if (busy)
|
||||
{
|
||||
printk(KERN_DEBUG "Divas: Logging interrupting self !\n");
|
||||
return;
|
||||
}
|
||||
busy = TRUE;
|
||||
|
||||
/* ignore call if daemon isn't running and we've reached limit */
|
||||
|
||||
if (DivasLogFifoFull())
|
||||
{
|
||||
if (!overflow)
|
||||
{
|
||||
printk(KERN_DEBUG "Divas: Trace buffer full\n");
|
||||
overflow = TRUE;
|
||||
}
|
||||
busy = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
DivasLogFifoWrite(buffer, length);
|
||||
|
||||
busy = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* #################################################################################### */
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Source file for diva log facility
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.5
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "divas.h"
|
||||
#include "adapter.h"
|
||||
#include "divalog.h"
|
||||
|
||||
#include "uxio.h"
|
||||
|
||||
/*Counter to monitor number of messages */
|
||||
static int m_count;
|
||||
|
||||
#define MAX_BUFFERED_MSGS (1000)
|
||||
|
||||
/* Our Linked List Structure to hold message */
|
||||
typedef struct klog_link{
|
||||
klog_t klog;
|
||||
struct klog_link *next;
|
||||
}KNODE;
|
||||
|
||||
/* First & Last structures in list*/
|
||||
KNODE *head;
|
||||
KNODE *tail;
|
||||
|
||||
/*
|
||||
* retrieve message from FIFO buffer
|
||||
* returns NULL if buffer empty
|
||||
* otherwise returns pointer to entry
|
||||
*/
|
||||
|
||||
char *DivasLogFifoRead(void)
|
||||
|
||||
{
|
||||
KNODE *old_head;
|
||||
|
||||
if(head==NULL)
|
||||
{
|
||||
/* Buffer Empty - No Messages */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_count--;
|
||||
/* Keep track of message to be read & increment to next message*/
|
||||
old_head = head;
|
||||
head = head->next;
|
||||
/*Return ptr to Msg */
|
||||
return((char *)old_head);
|
||||
}
|
||||
|
||||
/*
|
||||
* write message into FIFO buffer
|
||||
*/
|
||||
|
||||
void DivasLogFifoWrite(char *entry, int length)
|
||||
|
||||
{
|
||||
KNODE *new_klog;
|
||||
|
||||
if(head == NULL)
|
||||
{
|
||||
/* No Entries in Log */
|
||||
tail=NULL;
|
||||
m_count=0;
|
||||
new_klog=UxAlloc(sizeof(KNODE));
|
||||
|
||||
if(new_klog==NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_count++;
|
||||
memset(new_klog, 0, sizeof(KNODE));
|
||||
|
||||
/* Set head & tail to point to the new Msg Struct */
|
||||
head=tail=new_klog;
|
||||
tail->next=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_klog=UxAlloc(sizeof(KNODE));
|
||||
|
||||
if(new_klog==NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_count++;
|
||||
memset(new_klog, 0, sizeof(KNODE));
|
||||
|
||||
/* Let last Msg Struct point to new Msg Struct & inc tail */
|
||||
tail->next=new_klog;
|
||||
tail=new_klog;
|
||||
tail->next=NULL;
|
||||
}
|
||||
|
||||
if (length > sizeof(klog_t))
|
||||
{
|
||||
length = sizeof(klog_t);
|
||||
}
|
||||
|
||||
memcpy(&tail->klog, entry, length);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* DivaslogFifoEmpty:return TRUE if FIFO buffer is empty,otherwise FALSE
|
||||
*/
|
||||
int DivasLogFifoEmpty(void)
|
||||
{
|
||||
return (m_count == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
*DivasLogFifoFull:return TRUE if FIFO buffer is full,otherwise FALSE
|
||||
*/
|
||||
int DivasLogFifoFull(void)
|
||||
{
|
||||
return (m_count == MAX_BUFFERED_MSGS);
|
||||
}
|
||||
|
||||
/*
|
||||
* generate an IDI log entry
|
||||
*/
|
||||
|
||||
void DivasLogIdi(card_t *card, ENTITY *e, int request)
|
||||
|
||||
{
|
||||
klog_t klog;
|
||||
|
||||
memset(&klog, 0, sizeof(klog));
|
||||
|
||||
klog.time_stamp = UxTimeGet();
|
||||
|
||||
klog.length = sizeof(ENTITY) > sizeof(klog.buffer) ?
|
||||
sizeof(klog.buffer) : sizeof(ENTITY);
|
||||
|
||||
klog.card = (int) (card - DivasCards);
|
||||
|
||||
klog.type = request ? KLOG_IDI_REQ : KLOG_IDI_CALLBACK;
|
||||
klog.code = 0;
|
||||
memcpy(klog.buffer, e, klog.length);
|
||||
|
||||
/* send to the log driver and return */
|
||||
|
||||
DivasLogAdd(&klog, sizeof(klog));
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.2
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PC_H_INCLUDED
|
||||
#define PC_H_INCLUDED
|
||||
|
||||
|
||||
#define byte unsigned char
|
||||
#define word unsigned short
|
||||
#define dword unsigned long
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* buffer definition */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
typedef struct {
|
||||
word length; /* length of data/parameter field */
|
||||
byte P[270]; /* data/parameter field */
|
||||
} PBUFFER;
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* dual port ram structure */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
struct dual
|
||||
{
|
||||
byte Req; /* request register */
|
||||
byte ReqId; /* request task/entity identification */
|
||||
byte Rc; /* return code register */
|
||||
byte RcId; /* return code task/entity identification */
|
||||
byte Ind; /* Indication register */
|
||||
byte IndId; /* Indication task/entity identification */
|
||||
byte IMask; /* Interrupt Mask Flag */
|
||||
byte RNR; /* Receiver Not Ready (set by PC) */
|
||||
byte XLock; /* XBuffer locked Flag */
|
||||
byte Int; /* ISDN-S interrupt */
|
||||
byte ReqCh; /* Channel field for layer-3 Requests */
|
||||
byte RcCh; /* Channel field for layer-3 Returncodes */
|
||||
byte IndCh; /* Channel field for layer-3 Indications */
|
||||
byte MInd; /* more data indication field */
|
||||
word MLength; /* more data total packet length */
|
||||
byte ReadyInt; /* request field for ready interrupt */
|
||||
byte SWReg; /* Software register for special purposes */
|
||||
byte Reserved[11]; /* reserved space */
|
||||
byte InterfaceType; /* interface type 1=16K interface */
|
||||
word Signature; /* ISDN-S adapter Signature (GD) */
|
||||
PBUFFER XBuffer; /* Transmit Buffer */
|
||||
PBUFFER RBuffer; /* Receive Buffer */
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* SWReg Values (0 means no command) */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define SWREG_DIE_WITH_LEDON 0x01
|
||||
#define SWREG_HALT_CPU 0x02 /* Push CPU into a while(1) loop */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Id Fields Coding */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define ID_MASK 0xe0 /* Mask for the ID field */
|
||||
#define GL_ERR_ID 0x1f /* ID for error reporting on global requests*/
|
||||
|
||||
#define DSIG_ID 0x00 /* ID for D-channel signaling */
|
||||
#define NL_ID 0x20 /* ID for network-layer access (B or D) */
|
||||
#define BLLC_ID 0x60 /* ID for B-channel link level access */
|
||||
#define TASK_ID 0x80 /* ID for dynamic user tasks */
|
||||
#define TIMER_ID 0xa0 /* ID for timer task */
|
||||
#define TEL_ID 0xc0 /* ID for telephone support */
|
||||
#define MAN_ID 0xe0 /* ID for management */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* ASSIGN and REMOVE requests are the same for all entities */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define ASSIGN 0x01
|
||||
#define UREMOVE 0xfe /* without returncode */
|
||||
#define REMOVE 0xff
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Timer Interrupt Task Interface */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define ASSIGN_TIM 0x01
|
||||
#define REMOVE_TIM 0xff
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* dynamic user task interface */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define ASSIGN_TSK 0x01
|
||||
#define REMOVE_TSK 0xff
|
||||
|
||||
#define LOAD 0xf0
|
||||
#define RELOCATE 0xf1
|
||||
#define START 0xf2
|
||||
#define LOAD2 0xf3
|
||||
#define RELOCATE2 0xf4
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* dynamic user task messages */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define TSK_B2 0x0000
|
||||
#define TSK_WAKEUP 0x2000
|
||||
#define TSK_TIMER 0x4000
|
||||
#define TSK_TSK 0x6000
|
||||
#define TSK_PC 0xe000
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* LL management primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define ASSIGN_LL 1 /* assign logical link */
|
||||
#define REMOVE_LL 0xff /* remove logical link */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* LL service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define LL_UDATA 1 /* link unit data request/indication */
|
||||
#define LL_ESTABLISH 2 /* link establish request/indication */
|
||||
#define LL_RELEASE 3 /* link release request/indication */
|
||||
#define LL_DATA 4 /* data request/indication */
|
||||
#define LL_LOCAL 5 /* switch to local operation (COM only) */
|
||||
#define LL_DATA_PEND 5 /* data pending indication (SDLC SHM only) */
|
||||
#define LL_REMOTE 6 /* switch to remote operation (COM only) */
|
||||
#define LL_TEST 8 /* link test request */
|
||||
#define LL_MDATA 9 /* more data request/indication */
|
||||
#define LL_BUDATA 10 /* broadcast unit data request/indication */
|
||||
#define LL_XID 12 /* XID command request/indication */
|
||||
#define LL_XID_R 13 /* XID response request/indication */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* NL service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define N_MDATA 1 /* more data to come REQ/IND */
|
||||
#define N_CONNECT 2 /* OSI N-CONNECT REQ/IND */
|
||||
#define N_CONNECT_ACK 3 /* OSI N-CONNECT CON/RES */
|
||||
#define N_DISC 4 /* OSI N-DISC REQ/IND */
|
||||
#define N_DISC_ACK 5 /* OSI N-DISC CON/RES */
|
||||
#define N_RESET 6 /* OSI N-RESET REQ/IND */
|
||||
#define N_RESET_ACK 7 /* OSI N-RESET CON/RES */
|
||||
#define N_DATA 8 /* OSI N-DATA REQ/IND */
|
||||
#define N_EDATA 9 /* OSI N-EXPEDITED DATA REQ/IND */
|
||||
#define N_UDATA 10 /* OSI D-UNIT-DATA REQ/IND */
|
||||
#define N_BDATA 11 /* BROADCAST-DATA REQ/IND */
|
||||
#define N_DATA_ACK 12 /* data ack ind for D-bit procedure */
|
||||
#define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */
|
||||
|
||||
#define N_Q_BIT 0x10 /* Q-bit for req/ind */
|
||||
#define N_M_BIT 0x20 /* M-bit for req/ind */
|
||||
#define N_D_BIT 0x40 /* D-bit for req/ind */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Signaling management primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define ASSIGN_SIG 1 /* assign signaling task */
|
||||
#define UREMOVE_SIG 0xfe /* remove signaling task without returncode */
|
||||
#define REMOVE_SIG 0xff /* remove signaling task */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Signaling service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define CALL_REQ 1 /* call request */
|
||||
#define CALL_CON 1 /* call confirmation */
|
||||
#define CALL_IND 2 /* incoming call connected */
|
||||
#define LISTEN_REQ 2 /* listen request */
|
||||
#define HANGUP 3 /* hangup request/indication */
|
||||
#define SUSPEND 4 /* call suspend request/confirm */
|
||||
#define RESUME 5 /* call resume request/confirm */
|
||||
#define SUSPEND_REJ 6 /* suspend rejected indication */
|
||||
#define USER_DATA 8 /* user data for user to user signaling */
|
||||
#define CONGESTION 9 /* network congestion indication */
|
||||
#define INDICATE_REQ 10 /* request to indicate an incoming call */
|
||||
#define INDICATE_IND 10 /* indicates that there is an incoming call */
|
||||
#define CALL_RES 11 /* accept an incoming call */
|
||||
#define CALL_ALERT 12 /* send ALERT for incoming call */
|
||||
#define INFO_REQ 13 /* INFO request */
|
||||
#define INFO_IND 13 /* INFO indication */
|
||||
#define REJECT 14 /* reject an incoming call */
|
||||
#define RESOURCES 15 /* reserve B-Channel hardware resources */
|
||||
#define TEL_CTRL 16 /* Telephone control request/indication */
|
||||
#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
|
||||
#define FAC_REG_REQ 18 /* connection idependent fac registration */
|
||||
#define FAC_REG_ACK 19 /* fac registration acknowledge */
|
||||
#define FAC_REG_REJ 20 /* fac registration reject */
|
||||
#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
|
||||
#define FACILITY_REQ 22 /* send a Facility Message type */
|
||||
#define FACILITY_IND 22 /* Facility Message type indication */
|
||||
#define SIG_CTRL 29 /* Control for signalling hardware */
|
||||
#define DSP_CTRL 30 /* Control for DSPs */
|
||||
#define LAW_REQ 31 /* Law config request for (returns info_i) */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* management service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define MAN_READ 2
|
||||
#define MAN_WRITE 3
|
||||
#define MAN_EXECUTE 4
|
||||
#define MAN_EVENT_ON 5
|
||||
#define MAN_EVENT_OFF 6
|
||||
#define MAN_LOCK 7
|
||||
#define MAN_UNLOCK 8
|
||||
|
||||
#define MAN_INFO_IND 2
|
||||
#define MAN_EVENT_IND 3
|
||||
#define MAN_TRACE_IND 4
|
||||
|
||||
#define MAN_ESC 0x80
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* return code coding */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define UNKNOWN_COMMAND 0x01 /* unknown command */
|
||||
#define WRONG_COMMAND 0x02 /* wrong command */
|
||||
#define WRONG_ID 0x03 /* unknown task/entity id */
|
||||
#define WRONG_CH 0x04 /* wrong task/entity id */
|
||||
#define UNKNOWN_IE 0x05 /* unknown information el. */
|
||||
#define WRONG_IE 0x06 /* wrong information el. */
|
||||
#define OUT_OF_RESOURCES 0x07 /* ISDN-S card out of res. */
|
||||
#define ADAPTER_DEAD 0x08 /* ISDN card CPU halted */
|
||||
#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
|
||||
#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
|
||||
#define ASSIGN_OK 0xef /* ASSIGN OK */
|
||||
#define OK_FC 0xfc /* Flow-Control RC */
|
||||
#define READY_INT 0xfd /* Ready interrupt */
|
||||
#define TIMER_INT 0xfe /* timer interrupt */
|
||||
#define OK 0xff /* command accepted */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* information elements */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define SHIFT 0x90 /* codeset shift */
|
||||
#define MORE 0xa0 /* more data */
|
||||
#define CL 0xb0 /* congestion level */
|
||||
|
||||
/* codeset 0 */
|
||||
|
||||
#define BC 0x04 /* Bearer Capability */
|
||||
#define CAU 0x08 /* cause */
|
||||
#define CAD 0x0c /* Connected address */
|
||||
#define CAI 0x10 /* call identity */
|
||||
#define CHI 0x18 /* channel identification */
|
||||
#define LLI 0x19 /* logical link id */
|
||||
#define CHA 0x1a /* charge advice */
|
||||
#define DT 0x29 /* ETSI date/time */
|
||||
#define KEY 0x2c /* keypad information element */
|
||||
#define FTY 0x1c /* facility information element */
|
||||
#define DSP 0x28 /* display */
|
||||
#define OAD 0x6c /* origination address */
|
||||
#define OSA 0x6d /* origination sub-address */
|
||||
#define CPN 0x70 /* called party number */
|
||||
#define DSA 0x71 /* destination sub-address */
|
||||
#define RDX 0x73 /* redirected number extended */
|
||||
#define RDN 0x74 /* redirected number */
|
||||
#define LLC 0x7c /* low layer compatibility */
|
||||
#define HLC 0x7d /* high layer compatibility */
|
||||
#define UUI 0x7e /* user user information */
|
||||
#define ESC 0x7f /* escape extension */
|
||||
|
||||
#define DLC 0x20 /* data link layer configuration */
|
||||
#define NLC 0x21 /* network layer configuration */
|
||||
|
||||
/* codeset 6 */
|
||||
|
||||
#define SIN 0x01 /* service indicator */
|
||||
#define CIF 0x02 /* charging information */
|
||||
#define DATE 0x03 /* date */
|
||||
#define CPS 0x07 /* called party status */
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* TEL_CTRL contents */
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
#define RING_ON 0x01
|
||||
#define RING_OFF 0x02
|
||||
#define HANDS_FREE_ON 0x03
|
||||
#define HANDS_FREE_OFF 0x04
|
||||
#define ON_HOOK 0x80
|
||||
#define OFF_HOOK 0x90
|
||||
|
||||
#endif
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PC_MAINT_H
|
||||
#define PC_MAINT_H
|
||||
|
||||
#if !defined(MIPS_SCOM)
|
||||
#define BUFFER_SZ 48
|
||||
#define MAINT_OFFS 0x380
|
||||
#else
|
||||
#define BUFFER_SZ 128
|
||||
#define MAINT_OFFS 0xff00
|
||||
#endif
|
||||
|
||||
#define MIPS_BUFFER_SZ 128
|
||||
#define MIPS_MAINT_OFFS 0xff00
|
||||
|
||||
#define DO_LOG 1
|
||||
#define MEMR 2
|
||||
#define MEMW 3
|
||||
#define IOR 4
|
||||
#define IOW 5
|
||||
#define B1TEST 6
|
||||
#define B2TEST 7
|
||||
#define BTESTOFF 8
|
||||
#define DSIG_STATS 9
|
||||
#define B_CH_STATS 10
|
||||
#define D_CH_STATS 11
|
||||
#define BL1_STATS 12
|
||||
#define BL1_STATS_C 13
|
||||
#define GET_VERSION 14
|
||||
#define OS_STATS 15
|
||||
#define XLOG_SET_MASK 16
|
||||
#define XLOG_GET_MASK 17
|
||||
#define DSP_READ 20
|
||||
#define DSP_WRITE 21
|
||||
|
||||
#define OK 0xff
|
||||
#define MORE_EVENTS 0xfe
|
||||
#define NO_EVENT 1
|
||||
|
||||
struct DSigStruc
|
||||
{
|
||||
byte Id;
|
||||
byte uX;
|
||||
byte listen;
|
||||
byte active;
|
||||
byte sin[3];
|
||||
byte bc[6];
|
||||
byte llc[6];
|
||||
byte hlc[6];
|
||||
byte oad[20];
|
||||
};
|
||||
|
||||
struct BL1Struc {
|
||||
dword cx_b1;
|
||||
dword cx_b2;
|
||||
dword cr_b1;
|
||||
dword cr_b2;
|
||||
dword px_b1;
|
||||
dword px_b2;
|
||||
dword pr_b1;
|
||||
dword pr_b2;
|
||||
word er_b1;
|
||||
word er_b2;
|
||||
};
|
||||
|
||||
struct L2Struc {
|
||||
dword XTotal;
|
||||
dword RTotal;
|
||||
word XError;
|
||||
word RError;
|
||||
};
|
||||
|
||||
struct OSStruc {
|
||||
word free_n;
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct DSigStruc DSigStats;
|
||||
struct BL1Struc BL1Stats;
|
||||
struct L2Struc L2Stats;
|
||||
struct OSStruc OSStats;
|
||||
byte b[BUFFER_SZ];
|
||||
word w[BUFFER_SZ>>1];
|
||||
word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
|
||||
dword d[BUFFER_SZ>>2];
|
||||
} BUFFER;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct DSigStruc DSigStats;
|
||||
struct BL1Struc BL1Stats;
|
||||
struct L2Struc L2Stats;
|
||||
struct OSStruc OSStats;
|
||||
byte b[MIPS_BUFFER_SZ];
|
||||
word w[MIPS_BUFFER_SZ>>1];
|
||||
word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
|
||||
dword d[MIPS_BUFFER_SZ>>2];
|
||||
} MIPS_BUFFER;
|
||||
|
||||
|
||||
#if !defined(MIPS_SCOM)
|
||||
struct pc_maint
|
||||
{
|
||||
byte req;
|
||||
byte rc;
|
||||
byte *mem; /*far*/
|
||||
short length;
|
||||
word port;
|
||||
byte fill[6];
|
||||
BUFFER data;
|
||||
};
|
||||
#else
|
||||
struct pc_maint
|
||||
{
|
||||
byte req;
|
||||
byte rc;
|
||||
byte reserved[2]; /* R3000 alignment ... */
|
||||
byte far *mem;
|
||||
short length;
|
||||
word port;
|
||||
byte fill[4]; /* data at offset 16 */
|
||||
BUFFER data;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mi_pc_maint
|
||||
{
|
||||
byte req;
|
||||
byte rc;
|
||||
byte reserved[2]; /* R3000 alignment ... */
|
||||
byte *mem; /*far*/
|
||||
short length;
|
||||
word port;
|
||||
byte fill[4]; /* data at offset 16 */
|
||||
MIPS_BUFFER data;
|
||||
};
|
||||
|
||||
#endif /* PC_MAINT_H */
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.0
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(PR_PC_H)
|
||||
#define PR_PC_H
|
||||
|
||||
struct pr_ram {
|
||||
word NextReq; /* pointer to next Req Buffer */
|
||||
word NextRc; /* pointer to next Rc Buffer */
|
||||
word NextInd; /* pointer to next Ind Buffer */
|
||||
byte ReqInput; /* number of Req Buffers sent */
|
||||
byte ReqOutput; /* number of Req Buffers returned */
|
||||
byte ReqReserved; /* number of Req Buffers reserved */
|
||||
byte Int; /* ISDN-P interrupt */
|
||||
byte XLock; /* Lock field for arbitration */
|
||||
byte RcOutput; /* number of Rc buffers received */
|
||||
byte IndOutput; /* number of Ind buffers received */
|
||||
byte IMask; /* Interrupt Mask Flag */
|
||||
byte Reserved1[2]; /* reserved field, do not use */
|
||||
byte ReadyInt; /* request field for ready interrupt */
|
||||
byte Reserved2[12]; /* reserved field, do not use */
|
||||
byte InterfaceType; /* interface type 1=16K interface */
|
||||
word Signature; /* ISDN-P initialized indication */
|
||||
byte B[1]; /* buffer space for Req,Ind and Rc */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
word next;
|
||||
byte Req;
|
||||
byte ReqId;
|
||||
byte ReqCh;
|
||||
byte Reserved1;
|
||||
word Reference;
|
||||
byte Reserved[8];
|
||||
PBUFFER XBuffer;
|
||||
} REQ;
|
||||
|
||||
typedef struct {
|
||||
word next;
|
||||
byte Rc;
|
||||
byte RcId;
|
||||
byte RcCh;
|
||||
byte Reserved1;
|
||||
word Reference;
|
||||
byte Reserved2[8];
|
||||
} RC;
|
||||
|
||||
typedef struct {
|
||||
word next;
|
||||
byte Ind;
|
||||
byte IndId;
|
||||
byte IndCh;
|
||||
byte MInd;
|
||||
word MLength;
|
||||
word Reference;
|
||||
byte RNR;
|
||||
byte Reserved;
|
||||
dword Ack;
|
||||
PBUFFER RBuffer;
|
||||
} IND;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
* Diva Server PRI specific part of initialisation
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.5
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "divas.h"
|
||||
#include "pc.h"
|
||||
#include "pr_pc.h"
|
||||
#include "dsp_defs.h"
|
||||
|
||||
#include "adapter.h"
|
||||
#include "uxio.h"
|
||||
|
||||
#define DIVAS_LOAD_CMD 0x02
|
||||
#define DIVAS_START_CMD 0x03
|
||||
#define DIVAS_IRQ_RESET 0xC18
|
||||
#define DIVAS_IRQ_RESET_VAL 0xFE
|
||||
|
||||
#define TEST_INT_DIVAS 0x11
|
||||
#define TEST_INT_DIVAS_BRI 0x12
|
||||
|
||||
#define DIVAS_RESET 0x81
|
||||
#define DIVAS_LED1 0x04
|
||||
#define DIVAS_LED2 0x08
|
||||
#define DIVAS_LED3 0x20
|
||||
#define DIVAS_LED4 0x40
|
||||
|
||||
#define DIVAS_RESET_REG 0x20
|
||||
|
||||
#define DIVAS_SIGNATURE 0x4447
|
||||
|
||||
/* offset to start of MAINT area (used by xlog) */
|
||||
|
||||
#define DIVAS_MAINT_OFFSET 0xef00 /* value for PRI card */
|
||||
|
||||
#define MP_PROTOCOL_ADDR 0xA0011000
|
||||
#define MP_DSP_CODE_BASE 0xa03a0000
|
||||
|
||||
typedef struct {
|
||||
dword cmd;
|
||||
dword addr;
|
||||
dword len;
|
||||
dword err;
|
||||
dword live;
|
||||
dword reserved[(0x1020>>2)-6];
|
||||
dword signature;
|
||||
byte data[1];
|
||||
} diva_server_boot_t;
|
||||
|
||||
byte mem_in(ADAPTER *a, void *adr);
|
||||
word mem_inw(ADAPTER *a, void *adr);
|
||||
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
|
||||
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
|
||||
void mem_out(ADAPTER *a, void *adr, byte data);
|
||||
void mem_outw(ADAPTER *a, void *adr, word data);
|
||||
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
|
||||
void mem_inc(ADAPTER *a, void *adr);
|
||||
|
||||
int DivasPRIInitPCI(card_t *card, dia_card_t *cfg);
|
||||
static int pri_ISR (card_t* card);
|
||||
|
||||
static int diva_server_reset(card_t *card)
|
||||
{
|
||||
byte *reg;
|
||||
diva_server_boot_t *boot = NULL;
|
||||
dword live = 0;
|
||||
int i = 0;
|
||||
dword dwWait;
|
||||
|
||||
DPRINTF(("divas: reset Diva Server PRI"));
|
||||
|
||||
reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
|
||||
|
||||
UxCardMemOut(card->hw, ®[DIVAS_RESET_REG], DIVAS_RESET |
|
||||
DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
|
||||
|
||||
for (dwWait = 0x000fffff; dwWait; dwWait--)
|
||||
;
|
||||
|
||||
UxCardMemOut(card->hw, ®[DIVAS_RESET_REG], 0x00);
|
||||
|
||||
for (dwWait = 0x000fffff; dwWait; dwWait--)
|
||||
;
|
||||
|
||||
UxCardMemDetach(card->hw, reg);
|
||||
|
||||
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
|
||||
|
||||
UxCardMemOutD(card->hw, boot->reserved, 0);
|
||||
|
||||
live = UxCardMemInD(card->hw, &boot->live);
|
||||
|
||||
for (i=0; i<5; i++)
|
||||
{
|
||||
if (live != UxCardMemInD(card->hw, &boot->live))
|
||||
{
|
||||
break;
|
||||
}
|
||||
UxPause(10);
|
||||
}
|
||||
|
||||
if (i == 5)
|
||||
{
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
|
||||
DPRINTF(("divas: card is reset but CPU not running"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
|
||||
DPRINTF(("divas: card reset after %d ms", i * 10));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int diva_server_config(card_t *card, dia_config_t *config)
|
||||
{
|
||||
byte *shared;
|
||||
int i, j;
|
||||
|
||||
DPRINTF(("divas: configure Diva Server PRI"));
|
||||
|
||||
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
UxCardLog(0);
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[i], 0);
|
||||
}
|
||||
|
||||
UxCardMemOut(card->hw, &shared[ 8], config->tei);
|
||||
UxCardMemOut(card->hw, &shared[ 9], config->nt2);
|
||||
UxCardMemOut(card->hw, &shared[10], config->sig_flags);
|
||||
UxCardMemOut(card->hw, &shared[11], config->watchdog);
|
||||
UxCardMemOut(card->hw, &shared[12], config->permanent);
|
||||
UxCardMemOut(card->hw, &shared[13], config->x_interface);
|
||||
UxCardMemOut(card->hw, &shared[14], config->stable_l2);
|
||||
UxCardMemOut(card->hw, &shared[15], config->no_order_check);
|
||||
UxCardMemOut(card->hw, &shared[16], config->handset_type);
|
||||
UxCardMemOut(card->hw, &shared[17], 0);
|
||||
UxCardMemOut(card->hw, &shared[18], config->low_channel);
|
||||
UxCardMemOut(card->hw, &shared[19], config->prot_version);
|
||||
UxCardMemOut(card->hw, &shared[20], config->crc4);
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
|
||||
}
|
||||
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
|
||||
}
|
||||
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
|
||||
}
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void diva_server_reset_int(card_t *card)
|
||||
{
|
||||
byte *cfg;
|
||||
|
||||
cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
|
||||
|
||||
UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL);
|
||||
UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0);
|
||||
UxCardMemDetach(card->hw, cfg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int diva_server_test_int(card_t *card)
|
||||
{
|
||||
int i;
|
||||
byte *shared;
|
||||
byte req_int;
|
||||
|
||||
DPRINTF(("divas: test interrupt for Diva Server PRI"));
|
||||
|
||||
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
UxCardMemIn(card->hw, &shared[0x3FE]);
|
||||
UxCardMemOut(card->hw, &shared[0x3FE], 0);
|
||||
UxCardMemIn(card->hw, &shared[0x3FE]);
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
|
||||
diva_server_reset_int(card);
|
||||
|
||||
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
|
||||
|
||||
card->test_int_pend = TEST_INT_DIVAS;
|
||||
|
||||
req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt));
|
||||
|
||||
req_int++;
|
||||
|
||||
UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int);
|
||||
|
||||
UxCardMemDetach(card->hw, shared);
|
||||
|
||||
UxCardLog(0);
|
||||
for (i = 0; i < 50; i++)
|
||||
{
|
||||
if (!card->test_int_pend)
|
||||
{
|
||||
break;
|
||||
}
|
||||
UxPause(10);
|
||||
}
|
||||
|
||||
|
||||
if (card->test_int_pend)
|
||||
{
|
||||
|
||||
DPRINTF(("active: timeout waiting for card to interrupt"));
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void print_hdr(unsigned char *code, int offset)
|
||||
{
|
||||
unsigned char hdr[80];
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
|
||||
while ((i < (DIM(hdr) -1)) &&
|
||||
(code[offset + i] != '\0') &&
|
||||
(code[offset + i] != '\r') &&
|
||||
(code[offset + i] != '\n'))
|
||||
{
|
||||
hdr[i] = code[offset + i];
|
||||
i++;
|
||||
}
|
||||
|
||||
hdr[i] = '\0';
|
||||
|
||||
DPRINTF(("divas: loading %s", hdr));
|
||||
}
|
||||
|
||||
static int diva_server_load(card_t *card, dia_load_t *load)
|
||||
{
|
||||
diva_server_boot_t *boot;
|
||||
int i, offset, length;
|
||||
dword cmd = 0;
|
||||
|
||||
DPRINTF(("divas: loading Diva Server PRI"));
|
||||
|
||||
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
|
||||
|
||||
switch(load->code_type)
|
||||
{
|
||||
case DIA_CPU_CODE:
|
||||
DPRINTF(("divas: RISC code"));
|
||||
print_hdr(load->code, 0x80);
|
||||
|
||||
UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
|
||||
break;
|
||||
|
||||
case DIA_DSP_CODE:
|
||||
DPRINTF(("divas: DSP code"));
|
||||
print_hdr(load->code, 0x0);
|
||||
|
||||
UxCardMemOutD(card->hw, &boot->addr,
|
||||
(MP_DSP_CODE_BASE + (((sizeof(dword) +
|
||||
(sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT))
|
||||
+ ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA)));
|
||||
break;
|
||||
|
||||
case DIA_TABLE_CODE:
|
||||
DPRINTF(("divas: TABLE code"));
|
||||
UxCardMemOutD(card->hw, &boot->addr,
|
||||
(MP_DSP_CODE_BASE + sizeof(dword)));
|
||||
break;
|
||||
|
||||
case DIA_CONT_CODE:
|
||||
DPRINTF(("divas: continuation code"));
|
||||
break;
|
||||
|
||||
case DIA_DLOAD_CNT:
|
||||
DPRINTF(("divas: COUNT code"));
|
||||
UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE);
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF(("divas: unknown code type"));
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
UxCardLog(0);
|
||||
offset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
length = (load->length - offset >= 400) ? 400 : load->length - offset;
|
||||
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]);
|
||||
}
|
||||
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i]))
|
||||
{
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
|
||||
DPRINTF(("divas: card code block verify failed"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4);
|
||||
UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD);
|
||||
|
||||
for (i=0; i<50000; i++)
|
||||
{
|
||||
cmd = UxCardMemInD(card->hw, &boot->cmd);
|
||||
if (!cmd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/*UxPause(1);*/
|
||||
}
|
||||
|
||||
if (cmd)
|
||||
{
|
||||
DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset));
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += length;
|
||||
|
||||
} while (offset < load->length);
|
||||
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
|
||||
DPRINTF(("divas: DIVA Server card loaded"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int diva_server_start(card_t *card, byte *channels)
|
||||
{
|
||||
diva_server_boot_t *boot;
|
||||
byte *ram;
|
||||
int i;
|
||||
dword signature = 0;
|
||||
|
||||
DPRINTF(("divas: start Diva Server PRI"));
|
||||
|
||||
card->is_live = FALSE;
|
||||
|
||||
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
|
||||
|
||||
UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
|
||||
UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD);
|
||||
|
||||
UxCardLog(0);
|
||||
|
||||
for (i = 0; i < 300; i++)
|
||||
{
|
||||
signature = UxCardMemInD(card->hw, &boot->signature);
|
||||
if ((signature >> 16) == DIVAS_SIGNATURE)
|
||||
{
|
||||
DPRINTF(("divas: started card after %d ms", i * 10));
|
||||
break;
|
||||
}
|
||||
UxPause(10);
|
||||
}
|
||||
|
||||
if ((signature >> 16) != DIVAS_SIGNATURE)
|
||||
{
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature));
|
||||
return -1;
|
||||
}
|
||||
|
||||
card->is_live = TRUE;
|
||||
|
||||
ram = (byte *) boot;
|
||||
ram += DIVAS_SHARED_OFFSET;
|
||||
|
||||
*channels = UxCardMemIn(card->hw, &ram[0x3F6]);
|
||||
card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]);
|
||||
|
||||
UxCardMemDetach(card->hw, boot);
|
||||
|
||||
if (diva_server_test_int(card))
|
||||
{
|
||||
DPRINTF(("divas: interrupt test failed"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
DPRINTF(("divas: DIVA Server card started"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int diva_server_mem_get(card_t *card, mem_block_t *mem_block)
|
||||
|
||||
{
|
||||
byte *a;
|
||||
byte *card_addr;
|
||||
word length = 0;
|
||||
int i;
|
||||
|
||||
a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
|
||||
|
||||
card_addr = a;
|
||||
card_addr += mem_block->addr;
|
||||
|
||||
for (i=0; i < sizeof(mem_block->data); i++)
|
||||
{
|
||||
mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
|
||||
card_addr++;
|
||||
length++;
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, a);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise PRI specific entry points
|
||||
*/
|
||||
|
||||
int DivasPriInit(card_t *card, dia_card_t *cfg)
|
||||
{
|
||||
DPRINTF(("divas: initialise Diva Server PRI"));
|
||||
|
||||
if (DivasPRIInitPCI(card, cfg) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
card->card_reset = diva_server_reset;
|
||||
card->card_load = diva_server_load;
|
||||
card->card_config = diva_server_config;
|
||||
card->card_start = diva_server_start;
|
||||
card->reset_int = diva_server_reset_int;
|
||||
card->card_mem_get = diva_server_mem_get;
|
||||
|
||||
card->xlog_offset = DIVAS_MAINT_OFFSET;
|
||||
|
||||
card->out = DivasOut;
|
||||
card->test_int = DivasTestInt;
|
||||
card->dpc = DivasDpc;
|
||||
card->clear_int = DivasClearInt;
|
||||
card->card_isr = pri_ISR;
|
||||
|
||||
card->a.ram_out = mem_out;
|
||||
card->a.ram_outw = mem_outw;
|
||||
card->a.ram_out_buffer = mem_out_buffer;
|
||||
card->a.ram_inc = mem_inc;
|
||||
|
||||
card->a.ram_in = mem_in;
|
||||
card->a.ram_inw = mem_inw;
|
||||
card->a.ram_in_buffer = mem_in_buffer;
|
||||
card->a.ram_look_ahead = mem_look_ahead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pri_ISR (card_t* card)
|
||||
{
|
||||
int served = 0;
|
||||
byte* cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
|
||||
volatile unsigned long* isr = (unsigned long*)&cfg[DIVAS_IRQ_RESET];
|
||||
register unsigned long val = *isr;
|
||||
|
||||
if (val & 0x80000000) /* our card had caused interrupt ??? */
|
||||
{
|
||||
served = 1;
|
||||
card->int_pend += 1;
|
||||
DivasDpcSchedule(); /* ISR DPC */
|
||||
|
||||
*isr = (unsigned long)~0x03E00000; /* Clear interrupt line */
|
||||
}
|
||||
|
||||
UxCardMemDetach(card->hw, cfg);
|
||||
|
||||
return (served != 0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Environment provided by system and miscellaneous definitions
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.2
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(SYS_H)
|
||||
#define SYS_H
|
||||
|
||||
/* abreviations for unsigned types */
|
||||
typedef int boolean_t;
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef unsigned long dword;
|
||||
typedef unsigned short word;
|
||||
|
||||
/* abreviations for volatile types */
|
||||
|
||||
typedef volatile byte vbyte;
|
||||
typedef volatile word vword;
|
||||
typedef volatile dword vdword;
|
||||
|
||||
/* Booleans */
|
||||
|
||||
#if !defined(TRUE)
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
/* NULL pointer */
|
||||
|
||||
#if !defined(NULL)
|
||||
#define NULL ((void *) 0)
|
||||
#endif
|
||||
|
||||
/* Return the dimension of an array */
|
||||
|
||||
#if !defined(DIM)
|
||||
#define DIM(array) (sizeof (array)/sizeof ((array)[0]))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the number of milliseconds since last boot
|
||||
*/
|
||||
|
||||
extern dword UxTimeGet(void);
|
||||
|
||||
extern void DivasSprintf(char *buffer, char *format, ...);
|
||||
extern void DivasPrintf(char *format, ...);
|
||||
|
||||
/* fatal errors, asserts and tracing */
|
||||
|
||||
void HwFatalErrorFrom(char *file, int line);
|
||||
void HwFatalError(void);
|
||||
/* void HwAssert(char *file, int line, char *condition); */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define _PRINTK printk
|
||||
|
||||
#define _PRINTF DivasPrintf
|
||||
void _PRINTF(char *format, ...);
|
||||
#define PRINTF(arg_list) _PRINTF arg_list
|
||||
#if defined DTRACE
|
||||
# define DPRINTF(arg_list) _PRINTF arg_list
|
||||
# define KDPRINTF(arg_list) _PRINTF arg_list ; _PRINTK arg_list ; _PRINTK("\n");
|
||||
#else
|
||||
# define DPRINTF(arg_list) (void)0
|
||||
# define KDPRINTF(arg_list) _PRINTK arg_list ; _PRINTK("\n");
|
||||
#endif
|
||||
|
||||
#if !defined(ASSERT)
|
||||
#if defined DEBUG || defined DBG
|
||||
# define HwFatalError() HwFatalErrorFrom(__FILE__, __LINE__)
|
||||
# define ASSERT(cond) \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
/* HwAssert(__FILE__, __LINE__, #cond);*/ \
|
||||
}
|
||||
#else
|
||||
# define ASSERT(cond) ((void)0)
|
||||
#endif
|
||||
#endif /* !defined(ASSERT) */
|
||||
|
||||
#define TRACE (_PRINTF(__FILE__"@%d\n", __LINE__))
|
||||
|
||||
#endif /* SYS_H */
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Interface to Unix specific code for performing card I/O
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.6
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(UXIO_H)
|
||||
#define UXIO_H
|
||||
|
||||
#include "sys.h"
|
||||
#include "adapter.h"
|
||||
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
/* user callback, returns zero if interrupt was from this card */
|
||||
typedef void isr_fn_t(void *);
|
||||
struct ux_diva_card_s
|
||||
{
|
||||
word in_use;
|
||||
int io_base;
|
||||
int reset_base;
|
||||
int card_type;
|
||||
byte *mapped;
|
||||
int bus_num;
|
||||
int func_num;
|
||||
int slot;
|
||||
int irq;
|
||||
byte *pDRAM;
|
||||
byte *pDEVICES;
|
||||
byte *pCONFIG;
|
||||
byte *pSHARED;
|
||||
byte *pCONTROL;
|
||||
word features;
|
||||
void *user_isr_arg;
|
||||
isr_fn_t *user_isr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get a card handle to enable card to be accessed
|
||||
*/
|
||||
|
||||
int UxCardHandleGet( ux_diva_card_t **card,
|
||||
dia_card_t *cfg);
|
||||
|
||||
/*
|
||||
* Free a card handle as no longer needed
|
||||
*/
|
||||
|
||||
void UxCardHandleFree(ux_diva_card_t *card);
|
||||
|
||||
/*
|
||||
* Lock and unlock access to a card
|
||||
*/
|
||||
|
||||
long UxCardLock(ux_diva_card_t *card);
|
||||
void UxCardUnlock(ux_diva_card_t *card, long ipl);
|
||||
|
||||
/*
|
||||
* Set the mapping address for PCI cards
|
||||
*/
|
||||
|
||||
int UxCardAddrMappingSet(ux_diva_card_t *card,
|
||||
int id,
|
||||
void *address,
|
||||
int size);
|
||||
|
||||
/*
|
||||
* Attach card to memory to enable it to be accessed
|
||||
* Returns the mapped address
|
||||
*/
|
||||
|
||||
void *UxCardMemAttach(ux_diva_card_t *card, int id);
|
||||
|
||||
/*
|
||||
* map card out of memory after completion of access
|
||||
*/
|
||||
|
||||
void UxCardMemDetach(ux_diva_card_t *card, void *address);
|
||||
|
||||
/*
|
||||
* input functions for memory-mapped cards
|
||||
*/
|
||||
|
||||
byte UxCardMemIn(ux_diva_card_t *card, void *address);
|
||||
|
||||
word UxCardMemInW(ux_diva_card_t *card, void *address);
|
||||
|
||||
dword UxCardMemInD(ux_diva_card_t *card, void *address);
|
||||
|
||||
void UxCardMemInBuffer( ux_diva_card_t *card,
|
||||
void *address,
|
||||
void *buffer,
|
||||
int length);
|
||||
|
||||
/*
|
||||
* output functions for memory-mapped cards
|
||||
*/
|
||||
|
||||
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data);
|
||||
|
||||
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data);
|
||||
|
||||
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data);
|
||||
|
||||
void UxCardMemOutBuffer( ux_diva_card_t *card,
|
||||
void *address,
|
||||
void *buffer,
|
||||
int length);
|
||||
|
||||
/*
|
||||
* input functions for I/O-mapped cards
|
||||
*/
|
||||
|
||||
byte UxCardIoIn(ux_diva_card_t *card, void *, void *address);
|
||||
|
||||
word UxCardIoInW(ux_diva_card_t *card, void *, void *address);
|
||||
|
||||
dword UxCardIoInD(ux_diva_card_t *card, void *, void *address);
|
||||
|
||||
void UxCardIoInBuffer( ux_diva_card_t *card,
|
||||
void *, void *address,
|
||||
void *buffer,
|
||||
int length);
|
||||
|
||||
/*
|
||||
* output functions for I/O-mapped cards
|
||||
*/
|
||||
|
||||
void UxCardIoOut(ux_diva_card_t *card, void *, void *address, byte data);
|
||||
|
||||
void UxCardIoOutW(ux_diva_card_t *card, void *, void *address, word data);
|
||||
|
||||
void UxCardIoOutD(ux_diva_card_t *card, void *, void *address, dword data);
|
||||
|
||||
void UxCardIoOutBuffer( ux_diva_card_t *card,
|
||||
void *, void *address,
|
||||
void *buffer,
|
||||
int length);
|
||||
|
||||
/*
|
||||
* Get specified PCI config
|
||||
*/
|
||||
|
||||
void UxPciConfigRead(ux_diva_card_t *card,
|
||||
int size,
|
||||
int offset,
|
||||
void *value);
|
||||
|
||||
/*
|
||||
* Set specified PCI config
|
||||
*/
|
||||
|
||||
void UxPciConfigWrite(ux_diva_card_t *card,
|
||||
int size,
|
||||
int offset,
|
||||
void *value);
|
||||
|
||||
/* allocate memory, returning NULL if none available */
|
||||
|
||||
void *UxAlloc(unsigned int size);
|
||||
|
||||
void UxFree(void *);
|
||||
|
||||
/*
|
||||
* Pause for specified number of milli-seconds
|
||||
*/
|
||||
|
||||
void UxPause(long ms);
|
||||
|
||||
/*
|
||||
* Install an ISR for the specified card
|
||||
*/
|
||||
|
||||
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg);
|
||||
|
||||
/*
|
||||
* Remove an ISR for the specified card
|
||||
*/
|
||||
void UxIsrRemove(ux_diva_card_t *card, void *);
|
||||
|
||||
/*
|
||||
* DEBUG function to turn logging ON or OFF
|
||||
*/
|
||||
|
||||
void UxCardLog(int turn_on);
|
||||
|
||||
long UxInterlockedIncrement(ux_diva_card_t *card, long *dst);
|
||||
long UxInterlockedDecrement(ux_diva_card_t *card, long *dst);
|
||||
|
||||
#endif /* of UXIO_H */
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Unix Eicon active card driver
|
||||
* XLOG related functions
|
||||
*
|
||||
* Copyright (C) Eicon Technology Corporation, 2000.
|
||||
*
|
||||
* Eicon File Revision : 1.2
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "idi.h"
|
||||
#include "pc.h"
|
||||
#include "pc_maint.h"
|
||||
#include "divalog.h"
|
||||
|
||||
#include "adapter.h"
|
||||
#include "uxio.h"
|
||||
|
||||
/*
|
||||
* convert/copy XLOG info into a KLOG entry
|
||||
*/
|
||||
|
||||
static
|
||||
void xlog_to_klog(byte *b, int size, int card_num)
|
||||
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
word code;
|
||||
word time_hi;
|
||||
word time_lo;
|
||||
word xcode;
|
||||
byte data[2];
|
||||
} card_xlog_t;
|
||||
|
||||
card_xlog_t *x;
|
||||
|
||||
klog_t klog;
|
||||
|
||||
x = (card_xlog_t *) b;
|
||||
|
||||
memset(&klog, 0, sizeof(klog));
|
||||
|
||||
klog.time_stamp = (dword) x->time_hi;
|
||||
klog.time_stamp = (klog.time_stamp << 16) | (dword) x->time_lo;
|
||||
|
||||
klog.length = size > sizeof(klog.buffer) ? sizeof(klog.buffer) : size;
|
||||
|
||||
klog.card = card_num;
|
||||
if (x->code == 1)
|
||||
{
|
||||
klog.type = KLOG_XTXT_MSG;
|
||||
klog.code = 0;
|
||||
memcpy(klog.buffer, &x->xcode, klog.length);
|
||||
}
|
||||
else if (x->code == 2)
|
||||
{
|
||||
klog.type = KLOG_XLOG_MSG;
|
||||
klog.code = x->xcode;
|
||||
memcpy(klog.buffer, &x->data, klog.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *c; int i;
|
||||
klog.type = KLOG_TEXT_MSG;
|
||||
klog.code = 0;
|
||||
c = "divas: invalid xlog message code from card";
|
||||
i = 0;
|
||||
while (*c)
|
||||
{
|
||||
klog.buffer[i] = *c;
|
||||
c++;
|
||||
i++;
|
||||
}
|
||||
klog.buffer[i] = *c;
|
||||
}
|
||||
|
||||
/* send to the log driver and return */
|
||||
|
||||
DivasLogAdd(&klog, sizeof(klog));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* send an XLOG request down to specified card
|
||||
* if response available from previous request then read it
|
||||
* if not then just send down new request, ready for next time
|
||||
*/
|
||||
|
||||
void DivasXlogReq(int card_num)
|
||||
|
||||
{
|
||||
card_t *card;
|
||||
ADAPTER *a;
|
||||
|
||||
if ((card_num < 0) || (card_num > DivasCardNext))
|
||||
{
|
||||
DPRINTF(("xlog: invalid card number"));
|
||||
return;
|
||||
}
|
||||
|
||||
card = &DivasCards[card_num];
|
||||
|
||||
if (DivasXlogRetrieve(card))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* send down request for next time */
|
||||
|
||||
a = &card->a;
|
||||
|
||||
a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
|
||||
a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* retrieve XLOG request from specified card
|
||||
* returns non-zero if new request sent to card
|
||||
*/
|
||||
|
||||
int DivasXlogRetrieve(card_t *card)
|
||||
|
||||
{
|
||||
ADAPTER *a;
|
||||
struct mi_pc_maint pcm;
|
||||
|
||||
a = &card->a;
|
||||
|
||||
/* get status of last request */
|
||||
|
||||
pcm.rc = a->ram_in(a, (word *)(card->xlog_offset + 1));
|
||||
|
||||
/* if nothing there from previous request, send down a new one */
|
||||
|
||||
if (pcm.rc == OK)
|
||||
{
|
||||
/* read in response */
|
||||
|
||||
a->ram_in_buffer(a, (word *) (dword) card->xlog_offset, &pcm, sizeof(pcm));
|
||||
|
||||
xlog_to_klog((byte *) &pcm.data, sizeof(pcm.data),
|
||||
(int) (card - DivasCards));
|
||||
}
|
||||
|
||||
/* if any response received from card, re-send request */
|
||||
|
||||
if (pcm.rc)
|
||||
{
|
||||
a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
|
||||
a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,217 +1,74 @@
|
|||
L_OBJS :=
|
||||
M_OBJS :=
|
||||
LX_OBJS :=
|
||||
MX_OBJS :=
|
||||
O_OBJS :=
|
||||
OX_OBJS :=
|
||||
L_TARGET :=
|
||||
O_TARGET :=
|
||||
# Makefile for the hisax ISDN device driver
|
||||
|
||||
O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \
|
||||
lmgr.o q931.o callc.o fsm.o cert.o
|
||||
# The target object and module list name.
|
||||
|
||||
# EXTRA_CFLAGS += -S
|
||||
O_TARGET := vmlinux-obj.o
|
||||
|
||||
ifeq ($(CONFIG_HISAX_EURO),y)
|
||||
O_OBJS += l3dss1.o
|
||||
endif
|
||||
# Objects that export symbols.
|
||||
|
||||
ifeq ($(CONFIG_HISAX_NI1),y)
|
||||
O_OBJS += l3ni1.o
|
||||
endif
|
||||
export-objs := config.o fsm.o hisax_isac.o
|
||||
|
||||
ifeq ($(CONFIG_HISAX_1TR6),y)
|
||||
O_OBJS += l3_1tr6.o
|
||||
endif
|
||||
# Multipart objects.
|
||||
|
||||
ISAC_OBJ :=
|
||||
HSCX_OBJ :=
|
||||
ISAR_OBJ :=
|
||||
HFC_OBJ :=
|
||||
HFC_2BDS0 :=
|
||||
JADE_OBJ :=
|
||||
W6692_OBJ :=
|
||||
list-multi := hisax.o hisax_st5481.o
|
||||
hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
|
||||
lmgr.o q931.o callc.o fsm.o cert.o
|
||||
hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o \
|
||||
st5481_hdlc.o
|
||||
|
||||
ifeq ($(CONFIG_HISAX_16_0),y)
|
||||
O_OBJS += teles0.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
# Optional parts of multipart objects.
|
||||
hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o
|
||||
hisax-objs-$(CONFIG_HISAX_NI1) += l3ni1.o
|
||||
hisax-objs-$(CONFIG_HISAX_1TR6) += l3_1tr6.o
|
||||
|
||||
ifeq ($(CONFIG_HISAX_16_3),y)
|
||||
O_OBJS += teles3.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
hisax-objs-$(CONFIG_HISAX_16_0) += teles0.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_16_3) += teles3.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_TELESPCI) += telespci.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
|
||||
hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
|
||||
hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
|
||||
hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o
|
||||
hisax-objs-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o
|
||||
hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
|
||||
hisax-objs-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o
|
||||
hisax-objs-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o
|
||||
hisax-objs-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
|
||||
hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o
|
||||
hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
|
||||
hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o
|
||||
#hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o
|
||||
|
||||
ifeq ($(CONFIG_HISAX_TELESPCI),y)
|
||||
O_OBJS += telespci.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
hisax-objs += $(sort $(hisax-objs-y))
|
||||
|
||||
ifeq ($(CONFIG_HISAX_S0BOX),y)
|
||||
O_OBJS += s0box.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
ifeq ($(CONFIG_HISAX_AVM_A1),y)
|
||||
O_OBJS += avm_a1.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o
|
||||
obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o
|
||||
obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o
|
||||
obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
|
||||
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_fcpcipnp.o hisax_isac.o
|
||||
|
||||
ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y)
|
||||
O_OBJS += avm_a1p.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_FRITZPCI),y)
|
||||
O_OBJS += avm_pci.o
|
||||
ISAC_OBJ := isac.o
|
||||
endif
|
||||
CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
|
||||
CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
|
||||
|
||||
include $(TOPDIR)/drivers/isdn/Rules.make
|
||||
|
||||
ifeq ($(CONFIG_HISAX_ELSA),y)
|
||||
O_OBJS += elsa.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
# Link rules for multi-part drivers.
|
||||
|
||||
ifeq ($(CONFIG_HISAX_IX1MICROR2),y)
|
||||
O_OBJS += ix1_micro.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_DIEHLDIVA),y)
|
||||
O_OBJS += diva.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_ASUSCOM),y)
|
||||
O_OBJS += asuscom.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_TELEINT),y)
|
||||
O_OBJS += teleint.o
|
||||
ISAC_OBJ := isac.o
|
||||
HFC_OBJ := hfc_2bs0.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_SEDLBAUER),y)
|
||||
O_OBJS += sedlbauer.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
ISAR_OBJ := isar.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_SPORTSTER),y)
|
||||
O_OBJS += sportster.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_MIC),y)
|
||||
O_OBJS += mic.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_NETJET),y)
|
||||
O_OBJS += netjet.o
|
||||
ISAC_OBJ := isac.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_HFCS),y)
|
||||
O_OBJS += hfcscard.o
|
||||
HFC_2BDS0 := hfc_2bds0.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_HFC_PCI),y)
|
||||
HFC_2BDS0 += hfc_pci.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_HFC_SX),y)
|
||||
HFC_2BDS0 += hfc_sx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_NICCY),y)
|
||||
O_OBJS += niccy.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_ISURF),y)
|
||||
O_OBJS += isurf.o
|
||||
ISAC_OBJ := isac.o
|
||||
ISAR_OBJ := isar.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_HSTSAPHIR),y)
|
||||
O_OBJS += saphir.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_BKM_A4T),y)
|
||||
O_OBJS += bkm_a4t.o
|
||||
ISAC_OBJ := isac.o
|
||||
JADE_OBJ := jade.o
|
||||
endif
|
||||
ifeq ($(CONFIG_HISAX_SCT_QUADRO),y)
|
||||
O_OBJS += bkm_a8.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_GAZEL),y)
|
||||
O_OBJS += gazel.o
|
||||
ISAC_OBJ := isac.o
|
||||
HSCX_OBJ := hscx.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_HISAX_W6692),y)
|
||||
W6692_OBJ := w6692.o
|
||||
endif
|
||||
|
||||
# ifeq ($(CONFIG_HISAX_TESTEMU),y)
|
||||
# O_OBJS += testemu.o
|
||||
# endif
|
||||
|
||||
ifeq ($(ISAC_OBJ), isac.o)
|
||||
ISAC_OBJ += arcofi.o
|
||||
endif
|
||||
|
||||
O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ)
|
||||
O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(W6692_OBJ)
|
||||
OX_OBJS += config.o
|
||||
|
||||
O_TARGET :=
|
||||
|
||||
ifeq ($(CONFIG_ISDN_DRV_HISAX),y)
|
||||
O_TARGET += hisax.o
|
||||
else
|
||||
ifeq ($(CONFIG_ISDN_DRV_HISAX),m)
|
||||
O_TARGET += hisax.o
|
||||
M_OBJS += hisax.o
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
||||
MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
|
||||
tei.c callc.c cert.c l3dss1.c l3_1tr6.c \
|
||||
elsa.c diva.c
|
||||
|
||||
CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
|
||||
|
||||
cert.o: $(MD5FILES) md5sums.asc
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c
|
||||
hisax.o: $(hisax-objs)
|
||||
$(LD) -r -o $@ $(hisax-objs)
|
||||
|
||||
hisax_st5481.o: $(hisax_st5481-objs)
|
||||
$(LD) -r -o $@ $(hisax_st5481-objs)
|
||||
|
|
|
@ -2,19 +2,11 @@
|
|||
*
|
||||
* HiSax ISDN driver - chip specific routines for AMD 7930
|
||||
*
|
||||
* Author Brent Baccala (baccala@FreeSoft.org)
|
||||
* Author Brent Baccala
|
||||
* Copyright by Brent Baccala <baccala@FreeSoft.org>
|
||||
*
|
||||
*
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.2 1998/02/12 23:07:10 keil
|
||||
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
|
||||
*
|
||||
* Revision 1.1 1998/02/03 23:20:51 keil
|
||||
* New files for SPARC isdn support
|
||||
*
|
||||
* Revision 1.1 1998/01/08 04:17:12 baccala
|
||||
* ISDN comes to the Sparc. Key points:
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* - Existing ISDN HiSax driver provides all the smarts
|
||||
* - it compiles, runs, talks to an isolated phone switch, connects
|
||||
|
@ -26,6 +18,7 @@
|
|||
*
|
||||
* The code is unreliable enough to be consider alpha
|
||||
*
|
||||
* This file is (c) under GNU General Public License
|
||||
*
|
||||
* Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
|
||||
* SparcStation 1+. The chip provides microphone and speaker interfaces
|
||||
|
@ -373,12 +366,8 @@ Bchan_close(struct BCState *bcs)
|
|||
amd7930_bclose(0, bcs->channel);
|
||||
|
||||
if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
|
||||
while ((skb = skb_dequeue(&bcs->rqueue))) {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
while ((skb = skb_dequeue(&bcs->squeue))) {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
skb_queue_purge(&bcs->rqueue);
|
||||
skb_queue_purge(&bcs->squeue);
|
||||
}
|
||||
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
|
||||
}
|
||||
|
@ -745,8 +734,8 @@ amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
|
|||
return(0);
|
||||
}
|
||||
|
||||
__initfunc(int
|
||||
setup_amd7930(struct IsdnCard *card))
|
||||
int __init
|
||||
setup_amd7930(struct IsdnCard *card)
|
||||
{
|
||||
struct IsdnCardState *cs = card->cs;
|
||||
char tmp[64];
|
||||
|
|
|
@ -1,40 +1,12 @@
|
|||
/* $Id$
|
||||
|
||||
* arcofi.c Ansteuerung ARCOFI 2165
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
* Ansteuerung ARCOFI 2165
|
||||
*
|
||||
* Author Karsten Keil
|
||||
* Copyright by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.9 1999/12/19 13:09:41 keil
|
||||
* changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
|
||||
* signal proof delays
|
||||
*
|
||||
* Revision 1.8 1999/08/25 16:50:51 keil
|
||||
* Fix bugs which cause 2.3.14 hangs (waitqueue init)
|
||||
*
|
||||
* Revision 1.7 1999/07/01 08:11:17 keil
|
||||
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
|
||||
*
|
||||
* Revision 1.6 1998/09/30 22:21:56 keil
|
||||
* cosmetics
|
||||
*
|
||||
* Revision 1.5 1998/09/27 12:52:57 keil
|
||||
* cosmetics
|
||||
*
|
||||
* Revision 1.4 1998/08/20 13:50:24 keil
|
||||
* More support for hybrid modem (not working yet)
|
||||
*
|
||||
* Revision 1.3 1998/05/25 12:57:38 keil
|
||||
* HiSax golden code from certification, Don't use !!!
|
||||
* No leased lines, no X75, but many changes.
|
||||
*
|
||||
* Revision 1.2 1998/04/15 16:47:16 keil
|
||||
* new interface
|
||||
*
|
||||
* Revision 1.1 1997/10/29 18:51:20 keil
|
||||
* New files
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -158,8 +130,6 @@ init_arcofi(struct IsdnCardState *cs) {
|
|||
cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
|
||||
cs->dc.isac.arcofitimer.data = (long) cs;
|
||||
init_timer(&cs->dc.isac.arcofitimer);
|
||||
#ifdef COMPAT_HAS_NEW_WAITQ
|
||||
init_waitqueue_head(&cs->dc.isac.arcofi_wait);
|
||||
#endif
|
||||
test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,12 @@
|
|||
/* $Id$
|
||||
|
||||
* arcofi.h Ansteuerung ARCOFI 2165
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
* Ansteuerung ARCOFI 2165
|
||||
*
|
||||
* Author Karsten Keil
|
||||
* Copyright by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.4 1999/07/01 08:11:18 keil
|
||||
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
|
||||
*
|
||||
* Revision 1.3 1998/05/25 12:57:39 keil
|
||||
* HiSax golden code from certification, Don't use !!!
|
||||
* No leased lines, no X75, but many changes.
|
||||
*
|
||||
* Revision 1.2 1998/04/15 16:47:17 keil
|
||||
* new interface
|
||||
*
|
||||
* Revision 1.1 1997/10/29 18:51:20 keil
|
||||
* New files
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,39 +1,19 @@
|
|||
/* $Id$
|
||||
|
||||
* asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
* low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
|
||||
*
|
||||
* Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for informations
|
||||
* Author Karsten Keil
|
||||
* Copyright by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.8 1999/09/04 06:20:05 keil
|
||||
* Changes from kernel set_current_state()
|
||||
*
|
||||
* Revision 1.7 1999/07/12 21:04:53 keil
|
||||
* fix race in IRQ handling
|
||||
* added watchdog for lost IRQs
|
||||
*
|
||||
* Revision 1.6 1999/07/01 08:11:18 keil
|
||||
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
|
||||
*
|
||||
* Revision 1.5 1998/11/15 23:54:19 keil
|
||||
* changes from 2.0
|
||||
*
|
||||
* Revision 1.4 1998/06/18 23:18:20 keil
|
||||
* Support for new IPAC card
|
||||
*
|
||||
* Revision 1.3 1998/04/15 16:46:53 keil
|
||||
* new init code
|
||||
*
|
||||
* Revision 1.2 1998/02/02 13:27:06 keil
|
||||
* New
|
||||
*
|
||||
* Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for information
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/init.h>
|
||||
#include "hisax.h"
|
||||
#include "isac.h"
|
||||
#include "ipac.h"
|
||||
|
@ -329,8 +309,8 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
|
|||
return(0);
|
||||
}
|
||||
|
||||
__initfunc(int
|
||||
setup_asuscom(struct IsdnCard *card))
|
||||
int __init
|
||||
setup_asuscom(struct IsdnCard *card)
|
||||
{
|
||||
int bytecnt;
|
||||
struct IsdnCardState *cs = card->cs;
|
||||
|
@ -363,7 +343,7 @@ setup_asuscom(struct IsdnCard *card))
|
|||
cs->cardmsg = &Asus_card_msg;
|
||||
val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE,
|
||||
cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
|
||||
if (val == 1) {
|
||||
if ((val == 1) || (val == 2)) {
|
||||
cs->subtyp = ASUS_IPAC;
|
||||
cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
|
||||
cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
|
||||
|
|
|
@ -1,65 +1,17 @@
|
|||
/* $Id$
|
||||
|
||||
* avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
* low level stuff for AVM A1 (Fritz) isdn cards
|
||||
*
|
||||
* Author Karsten Keil
|
||||
* Copyright by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 2.10 1998/11/15 23:54:21 keil
|
||||
* changes from 2.0
|
||||
*
|
||||
* Revision 2.9 1998/08/13 23:36:12 keil
|
||||
* HiSax 3.1 - don't work stable with current LinkLevel
|
||||
*
|
||||
* Revision 2.8 1998/04/15 16:44:27 keil
|
||||
* new init code
|
||||
*
|
||||
* Revision 2.7 1998/02/02 13:29:37 keil
|
||||
* fast io
|
||||
*
|
||||
* Revision 2.6 1998/01/13 23:09:46 keil
|
||||
* really disable timer
|
||||
*
|
||||
* Revision 2.5 1998/01/02 06:50:29 calle
|
||||
* Perodic timer of A1 now disabled, no need for linux driver.
|
||||
*
|
||||
* Revision 2.4 1997/11/08 21:35:42 keil
|
||||
* new l1 init
|
||||
*
|
||||
* Revision 2.3 1997/11/06 17:13:32 keil
|
||||
* New 2.1 init code
|
||||
*
|
||||
* Revision 2.2 1997/10/29 18:55:48 keil
|
||||
* changes for 2.1.60 (irq2dev_map)
|
||||
*
|
||||
* Revision 2.1 1997/07/27 21:47:13 keil
|
||||
* new interface structures
|
||||
*
|
||||
* Revision 2.0 1997/06/26 11:02:48 keil
|
||||
* New Layer and card interface
|
||||
*
|
||||
* Revision 1.6 1997/04/13 19:54:07 keil
|
||||
* Change in IRQ check delay for SMP
|
||||
*
|
||||
* Revision 1.5 1997/04/06 22:54:10 keil
|
||||
* Using SKB's
|
||||
*
|
||||
* Revision 1.4 1997/01/27 15:50:21 keil
|
||||
* SMP proof,cosmetics
|
||||
*
|
||||
* Revision 1.3 1997/01/21 22:14:20 keil
|
||||
* cleanups
|
||||
*
|
||||
* Revision 1.2 1996/10/27 22:07:31 keil
|
||||
* cosmetic changes
|
||||
*
|
||||
* Revision 1.1 1996/10/13 20:04:49 keil
|
||||
* Initial revision
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/init.h>
|
||||
#include "hisax.h"
|
||||
#include "isac.h"
|
||||
#include "hscx.h"
|
||||
|
@ -223,8 +175,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
|
|||
return(0);
|
||||
}
|
||||
|
||||
__initfunc(int
|
||||
setup_avm_a1(struct IsdnCard *card))
|
||||
int __init
|
||||
setup_avm_a1(struct IsdnCard *card)
|
||||
{
|
||||
u_char val;
|
||||
struct IsdnCardState *cs = card->cs;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue