Commit f16f84937d769c893492160b1a8c3672e3992beb
Committed by
Jiri Kosina
1 parent
46e99c4a1d
Exists in
master
and in
20 other branches
isdn: Fix typo in isdn drivers
Fix spelling typo in debug messages within drivers/isdn. Signed-off-by: Masanari Iida <standby24x7@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Showing 4 changed files with 4 additions and 4 deletions Inline Diff
drivers/isdn/hardware/mISDN/mISDNisar.c
1 | /* | 1 | /* |
2 | * mISDNisar.c ISAR (Siemens PSB 7110) specific functions | 2 | * mISDNisar.c ISAR (Siemens PSB 7110) specific functions |
3 | * | 3 | * |
4 | * Author Karsten Keil (keil@isdn4linux.de) | 4 | * Author Karsten Keil (keil@isdn4linux.de) |
5 | * | 5 | * |
6 | * Copyright 2009 by Karsten Keil <keil@isdn4linux.de> | 6 | * Copyright 2009 by Karsten Keil <keil@isdn4linux.de> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* define this to enable static debug messages, if you kernel supports | 23 | /* define this to enable static debug messages, if you kernel supports |
24 | * dynamic debugging, you should use debugfs for this | 24 | * dynamic debugging, you should use debugfs for this |
25 | */ | 25 | */ |
26 | /* #define DEBUG */ | 26 | /* #define DEBUG */ |
27 | 27 | ||
28 | #include <linux/gfp.h> | 28 | #include <linux/gfp.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <linux/mISDNhw.h> | 31 | #include <linux/mISDNhw.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include "isar.h" | 33 | #include "isar.h" |
34 | 34 | ||
35 | #define ISAR_REV "2.1" | 35 | #define ISAR_REV "2.1" |
36 | 36 | ||
37 | MODULE_AUTHOR("Karsten Keil"); | 37 | MODULE_AUTHOR("Karsten Keil"); |
38 | MODULE_LICENSE("GPL v2"); | 38 | MODULE_LICENSE("GPL v2"); |
39 | MODULE_VERSION(ISAR_REV); | 39 | MODULE_VERSION(ISAR_REV); |
40 | 40 | ||
41 | #define DEBUG_HW_FIRMWARE_FIFO 0x10000 | 41 | #define DEBUG_HW_FIRMWARE_FIFO 0x10000 |
42 | 42 | ||
43 | static const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; | 43 | static const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; |
44 | static const u8 faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121, | 44 | static const u8 faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121, |
45 | 122, 145, 146}; | 45 | 122, 145, 146}; |
46 | #define FAXMODCNT 13 | 46 | #define FAXMODCNT 13 |
47 | 47 | ||
48 | static void isar_setup(struct isar_hw *); | 48 | static void isar_setup(struct isar_hw *); |
49 | 49 | ||
50 | static inline int | 50 | static inline int |
51 | waitforHIA(struct isar_hw *isar, int timeout) | 51 | waitforHIA(struct isar_hw *isar, int timeout) |
52 | { | 52 | { |
53 | int t = timeout; | 53 | int t = timeout; |
54 | u8 val = isar->read_reg(isar->hw, ISAR_HIA); | 54 | u8 val = isar->read_reg(isar->hw, ISAR_HIA); |
55 | 55 | ||
56 | while ((val & 1) && t) { | 56 | while ((val & 1) && t) { |
57 | udelay(1); | 57 | udelay(1); |
58 | t--; | 58 | t--; |
59 | val = isar->read_reg(isar->hw, ISAR_HIA); | 59 | val = isar->read_reg(isar->hw, ISAR_HIA); |
60 | } | 60 | } |
61 | pr_debug("%s: HIA after %dus\n", isar->name, timeout - t); | 61 | pr_debug("%s: HIA after %dus\n", isar->name, timeout - t); |
62 | return timeout; | 62 | return timeout; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * send msg to ISAR mailbox | 66 | * send msg to ISAR mailbox |
67 | * if msg is NULL use isar->buf | 67 | * if msg is NULL use isar->buf |
68 | */ | 68 | */ |
69 | static int | 69 | static int |
70 | send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) | 70 | send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) |
71 | { | 71 | { |
72 | if (!waitforHIA(isar, 1000)) | 72 | if (!waitforHIA(isar, 1000)) |
73 | return 0; | 73 | return 0; |
74 | pr_debug("send_mbox(%02x,%02x,%d)\n", his, creg, len); | 74 | pr_debug("send_mbox(%02x,%02x,%d)\n", his, creg, len); |
75 | isar->write_reg(isar->hw, ISAR_CTRL_H, creg); | 75 | isar->write_reg(isar->hw, ISAR_CTRL_H, creg); |
76 | isar->write_reg(isar->hw, ISAR_CTRL_L, len); | 76 | isar->write_reg(isar->hw, ISAR_CTRL_L, len); |
77 | isar->write_reg(isar->hw, ISAR_WADR, 0); | 77 | isar->write_reg(isar->hw, ISAR_WADR, 0); |
78 | if (!msg) | 78 | if (!msg) |
79 | msg = isar->buf; | 79 | msg = isar->buf; |
80 | if (msg && len) { | 80 | if (msg && len) { |
81 | isar->write_fifo(isar->hw, ISAR_MBOX, msg, len); | 81 | isar->write_fifo(isar->hw, ISAR_MBOX, msg, len); |
82 | if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) { | 82 | if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) { |
83 | int l = 0; | 83 | int l = 0; |
84 | 84 | ||
85 | while (l < (int)len) { | 85 | while (l < (int)len) { |
86 | hex_dump_to_buffer(msg + l, len - l, 32, 1, | 86 | hex_dump_to_buffer(msg + l, len - l, 32, 1, |
87 | isar->log, 256, 1); | 87 | isar->log, 256, 1); |
88 | pr_debug("%s: %s %02x: %s\n", isar->name, | 88 | pr_debug("%s: %s %02x: %s\n", isar->name, |
89 | __func__, l, isar->log); | 89 | __func__, l, isar->log); |
90 | l += 32; | 90 | l += 32; |
91 | } | 91 | } |
92 | } | 92 | } |
93 | } | 93 | } |
94 | isar->write_reg(isar->hw, ISAR_HIS, his); | 94 | isar->write_reg(isar->hw, ISAR_HIS, his); |
95 | waitforHIA(isar, 1000); | 95 | waitforHIA(isar, 1000); |
96 | return 1; | 96 | return 1; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * receive message from ISAR mailbox | 100 | * receive message from ISAR mailbox |
101 | * if msg is NULL use isar->buf | 101 | * if msg is NULL use isar->buf |
102 | */ | 102 | */ |
103 | static void | 103 | static void |
104 | rcv_mbox(struct isar_hw *isar, u8 *msg) | 104 | rcv_mbox(struct isar_hw *isar, u8 *msg) |
105 | { | 105 | { |
106 | if (!msg) | 106 | if (!msg) |
107 | msg = isar->buf; | 107 | msg = isar->buf; |
108 | isar->write_reg(isar->hw, ISAR_RADR, 0); | 108 | isar->write_reg(isar->hw, ISAR_RADR, 0); |
109 | if (msg && isar->clsb) { | 109 | if (msg && isar->clsb) { |
110 | isar->read_fifo(isar->hw, ISAR_MBOX, msg, isar->clsb); | 110 | isar->read_fifo(isar->hw, ISAR_MBOX, msg, isar->clsb); |
111 | if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) { | 111 | if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) { |
112 | int l = 0; | 112 | int l = 0; |
113 | 113 | ||
114 | while (l < (int)isar->clsb) { | 114 | while (l < (int)isar->clsb) { |
115 | hex_dump_to_buffer(msg + l, isar->clsb - l, 32, | 115 | hex_dump_to_buffer(msg + l, isar->clsb - l, 32, |
116 | 1, isar->log, 256, 1); | 116 | 1, isar->log, 256, 1); |
117 | pr_debug("%s: %s %02x: %s\n", isar->name, | 117 | pr_debug("%s: %s %02x: %s\n", isar->name, |
118 | __func__, l, isar->log); | 118 | __func__, l, isar->log); |
119 | l += 32; | 119 | l += 32; |
120 | } | 120 | } |
121 | } | 121 | } |
122 | } | 122 | } |
123 | isar->write_reg(isar->hw, ISAR_IIA, 0); | 123 | isar->write_reg(isar->hw, ISAR_IIA, 0); |
124 | } | 124 | } |
125 | 125 | ||
126 | static inline void | 126 | static inline void |
127 | get_irq_infos(struct isar_hw *isar) | 127 | get_irq_infos(struct isar_hw *isar) |
128 | { | 128 | { |
129 | isar->iis = isar->read_reg(isar->hw, ISAR_IIS); | 129 | isar->iis = isar->read_reg(isar->hw, ISAR_IIS); |
130 | isar->cmsb = isar->read_reg(isar->hw, ISAR_CTRL_H); | 130 | isar->cmsb = isar->read_reg(isar->hw, ISAR_CTRL_H); |
131 | isar->clsb = isar->read_reg(isar->hw, ISAR_CTRL_L); | 131 | isar->clsb = isar->read_reg(isar->hw, ISAR_CTRL_L); |
132 | pr_debug("%s: rcv_mbox(%02x,%02x,%d)\n", isar->name, | 132 | pr_debug("%s: rcv_mbox(%02x,%02x,%d)\n", isar->name, |
133 | isar->iis, isar->cmsb, isar->clsb); | 133 | isar->iis, isar->cmsb, isar->clsb); |
134 | } | 134 | } |
135 | 135 | ||
136 | /* | 136 | /* |
137 | * poll answer message from ISAR mailbox | 137 | * poll answer message from ISAR mailbox |
138 | * should be used only with ISAR IRQs disabled before DSP was started | 138 | * should be used only with ISAR IRQs disabled before DSP was started |
139 | * | 139 | * |
140 | */ | 140 | */ |
141 | static int | 141 | static int |
142 | poll_mbox(struct isar_hw *isar, int maxdelay) | 142 | poll_mbox(struct isar_hw *isar, int maxdelay) |
143 | { | 143 | { |
144 | int t = maxdelay; | 144 | int t = maxdelay; |
145 | u8 irq; | 145 | u8 irq; |
146 | 146 | ||
147 | irq = isar->read_reg(isar->hw, ISAR_IRQBIT); | 147 | irq = isar->read_reg(isar->hw, ISAR_IRQBIT); |
148 | while (t && !(irq & ISAR_IRQSTA)) { | 148 | while (t && !(irq & ISAR_IRQSTA)) { |
149 | udelay(1); | 149 | udelay(1); |
150 | t--; | 150 | t--; |
151 | } | 151 | } |
152 | if (t) { | 152 | if (t) { |
153 | get_irq_infos(isar); | 153 | get_irq_infos(isar); |
154 | rcv_mbox(isar, NULL); | 154 | rcv_mbox(isar, NULL); |
155 | } | 155 | } |
156 | pr_debug("%s: pulled %d bytes after %d us\n", | 156 | pr_debug("%s: pulled %d bytes after %d us\n", |
157 | isar->name, isar->clsb, maxdelay - t); | 157 | isar->name, isar->clsb, maxdelay - t); |
158 | return t; | 158 | return t; |
159 | } | 159 | } |
160 | 160 | ||
161 | static int | 161 | static int |
162 | ISARVersion(struct isar_hw *isar) | 162 | ISARVersion(struct isar_hw *isar) |
163 | { | 163 | { |
164 | int ver; | 164 | int ver; |
165 | 165 | ||
166 | /* disable ISAR IRQ */ | 166 | /* disable ISAR IRQ */ |
167 | isar->write_reg(isar->hw, ISAR_IRQBIT, 0); | 167 | isar->write_reg(isar->hw, ISAR_IRQBIT, 0); |
168 | isar->buf[0] = ISAR_MSG_HWVER; | 168 | isar->buf[0] = ISAR_MSG_HWVER; |
169 | isar->buf[1] = 0; | 169 | isar->buf[1] = 0; |
170 | isar->buf[2] = 1; | 170 | isar->buf[2] = 1; |
171 | if (!send_mbox(isar, ISAR_HIS_VNR, 0, 3, NULL)) | 171 | if (!send_mbox(isar, ISAR_HIS_VNR, 0, 3, NULL)) |
172 | return -1; | 172 | return -1; |
173 | if (!poll_mbox(isar, 1000)) | 173 | if (!poll_mbox(isar, 1000)) |
174 | return -2; | 174 | return -2; |
175 | if (isar->iis == ISAR_IIS_VNR) { | 175 | if (isar->iis == ISAR_IIS_VNR) { |
176 | if (isar->clsb == 1) { | 176 | if (isar->clsb == 1) { |
177 | ver = isar->buf[0] & 0xf; | 177 | ver = isar->buf[0] & 0xf; |
178 | return ver; | 178 | return ver; |
179 | } | 179 | } |
180 | return -3; | 180 | return -3; |
181 | } | 181 | } |
182 | return -4; | 182 | return -4; |
183 | } | 183 | } |
184 | 184 | ||
185 | static int | 185 | static int |
186 | load_firmware(struct isar_hw *isar, const u8 *buf, int size) | 186 | load_firmware(struct isar_hw *isar, const u8 *buf, int size) |
187 | { | 187 | { |
188 | u32 saved_debug = isar->ch[0].bch.debug; | 188 | u32 saved_debug = isar->ch[0].bch.debug; |
189 | int ret, cnt; | 189 | int ret, cnt; |
190 | u8 nom, noc; | 190 | u8 nom, noc; |
191 | u16 left, val, *sp = (u16 *)buf; | 191 | u16 left, val, *sp = (u16 *)buf; |
192 | u8 *mp; | 192 | u8 *mp; |
193 | u_long flags; | 193 | u_long flags; |
194 | 194 | ||
195 | struct { | 195 | struct { |
196 | u16 sadr; | 196 | u16 sadr; |
197 | u16 len; | 197 | u16 len; |
198 | u16 d_key; | 198 | u16 d_key; |
199 | } blk_head; | 199 | } blk_head; |
200 | 200 | ||
201 | if (1 != isar->version) { | 201 | if (1 != isar->version) { |
202 | pr_err("%s: ISAR wrong version %d firmware download aborted\n", | 202 | pr_err("%s: ISAR wrong version %d firmware download aborted\n", |
203 | isar->name, isar->version); | 203 | isar->name, isar->version); |
204 | return -EINVAL; | 204 | return -EINVAL; |
205 | } | 205 | } |
206 | if (!(saved_debug & DEBUG_HW_FIRMWARE_FIFO)) | 206 | if (!(saved_debug & DEBUG_HW_FIRMWARE_FIFO)) |
207 | isar->ch[0].bch.debug &= ~DEBUG_HW_BFIFO; | 207 | isar->ch[0].bch.debug &= ~DEBUG_HW_BFIFO; |
208 | pr_debug("%s: load firmware %d words (%d bytes)\n", | 208 | pr_debug("%s: load firmware %d words (%d bytes)\n", |
209 | isar->name, size / 2, size); | 209 | isar->name, size / 2, size); |
210 | cnt = 0; | 210 | cnt = 0; |
211 | size /= 2; | 211 | size /= 2; |
212 | /* disable ISAR IRQ */ | 212 | /* disable ISAR IRQ */ |
213 | spin_lock_irqsave(isar->hwlock, flags); | 213 | spin_lock_irqsave(isar->hwlock, flags); |
214 | isar->write_reg(isar->hw, ISAR_IRQBIT, 0); | 214 | isar->write_reg(isar->hw, ISAR_IRQBIT, 0); |
215 | spin_unlock_irqrestore(isar->hwlock, flags); | 215 | spin_unlock_irqrestore(isar->hwlock, flags); |
216 | while (cnt < size) { | 216 | while (cnt < size) { |
217 | blk_head.sadr = le16_to_cpu(*sp++); | 217 | blk_head.sadr = le16_to_cpu(*sp++); |
218 | blk_head.len = le16_to_cpu(*sp++); | 218 | blk_head.len = le16_to_cpu(*sp++); |
219 | blk_head.d_key = le16_to_cpu(*sp++); | 219 | blk_head.d_key = le16_to_cpu(*sp++); |
220 | cnt += 3; | 220 | cnt += 3; |
221 | pr_debug("ISAR firmware block (%#x,%d,%#x)\n", | 221 | pr_debug("ISAR firmware block (%#x,%d,%#x)\n", |
222 | blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); | 222 | blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); |
223 | left = blk_head.len; | 223 | left = blk_head.len; |
224 | if (cnt + left > size) { | 224 | if (cnt + left > size) { |
225 | pr_info("%s: firmware error have %d need %d words\n", | 225 | pr_info("%s: firmware error have %d need %d words\n", |
226 | isar->name, size, cnt + left); | 226 | isar->name, size, cnt + left); |
227 | ret = -EINVAL; | 227 | ret = -EINVAL; |
228 | goto reterrflg; | 228 | goto reterrflg; |
229 | } | 229 | } |
230 | spin_lock_irqsave(isar->hwlock, flags); | 230 | spin_lock_irqsave(isar->hwlock, flags); |
231 | if (!send_mbox(isar, ISAR_HIS_DKEY, blk_head.d_key & 0xff, | 231 | if (!send_mbox(isar, ISAR_HIS_DKEY, blk_head.d_key & 0xff, |
232 | 0, NULL)) { | 232 | 0, NULL)) { |
233 | pr_info("ISAR send_mbox dkey failed\n"); | 233 | pr_info("ISAR send_mbox dkey failed\n"); |
234 | ret = -ETIME; | 234 | ret = -ETIME; |
235 | goto reterror; | 235 | goto reterror; |
236 | } | 236 | } |
237 | if (!poll_mbox(isar, 1000)) { | 237 | if (!poll_mbox(isar, 1000)) { |
238 | pr_warning("ISAR poll_mbox dkey failed\n"); | 238 | pr_warning("ISAR poll_mbox dkey failed\n"); |
239 | ret = -ETIME; | 239 | ret = -ETIME; |
240 | goto reterror; | 240 | goto reterror; |
241 | } | 241 | } |
242 | spin_unlock_irqrestore(isar->hwlock, flags); | 242 | spin_unlock_irqrestore(isar->hwlock, flags); |
243 | if ((isar->iis != ISAR_IIS_DKEY) || isar->cmsb || isar->clsb) { | 243 | if ((isar->iis != ISAR_IIS_DKEY) || isar->cmsb || isar->clsb) { |
244 | pr_info("ISAR wrong dkey response (%x,%x,%x)\n", | 244 | pr_info("ISAR wrong dkey response (%x,%x,%x)\n", |
245 | isar->iis, isar->cmsb, isar->clsb); | 245 | isar->iis, isar->cmsb, isar->clsb); |
246 | ret = 1; | 246 | ret = 1; |
247 | goto reterrflg; | 247 | goto reterrflg; |
248 | } | 248 | } |
249 | while (left > 0) { | 249 | while (left > 0) { |
250 | if (left > 126) | 250 | if (left > 126) |
251 | noc = 126; | 251 | noc = 126; |
252 | else | 252 | else |
253 | noc = left; | 253 | noc = left; |
254 | nom = (2 * noc) + 3; | 254 | nom = (2 * noc) + 3; |
255 | mp = isar->buf; | 255 | mp = isar->buf; |
256 | /* the ISAR is big endian */ | 256 | /* the ISAR is big endian */ |
257 | *mp++ = blk_head.sadr >> 8; | 257 | *mp++ = blk_head.sadr >> 8; |
258 | *mp++ = blk_head.sadr & 0xFF; | 258 | *mp++ = blk_head.sadr & 0xFF; |
259 | left -= noc; | 259 | left -= noc; |
260 | cnt += noc; | 260 | cnt += noc; |
261 | *mp++ = noc; | 261 | *mp++ = noc; |
262 | pr_debug("%s: load %3d words at %04x\n", isar->name, | 262 | pr_debug("%s: load %3d words at %04x\n", isar->name, |
263 | noc, blk_head.sadr); | 263 | noc, blk_head.sadr); |
264 | blk_head.sadr += noc; | 264 | blk_head.sadr += noc; |
265 | while (noc) { | 265 | while (noc) { |
266 | val = le16_to_cpu(*sp++); | 266 | val = le16_to_cpu(*sp++); |
267 | *mp++ = val >> 8; | 267 | *mp++ = val >> 8; |
268 | *mp++ = val & 0xFF; | 268 | *mp++ = val & 0xFF; |
269 | noc--; | 269 | noc--; |
270 | } | 270 | } |
271 | spin_lock_irqsave(isar->hwlock, flags); | 271 | spin_lock_irqsave(isar->hwlock, flags); |
272 | if (!send_mbox(isar, ISAR_HIS_FIRM, 0, nom, NULL)) { | 272 | if (!send_mbox(isar, ISAR_HIS_FIRM, 0, nom, NULL)) { |
273 | pr_info("ISAR send_mbox prog failed\n"); | 273 | pr_info("ISAR send_mbox prog failed\n"); |
274 | ret = -ETIME; | 274 | ret = -ETIME; |
275 | goto reterror; | 275 | goto reterror; |
276 | } | 276 | } |
277 | if (!poll_mbox(isar, 1000)) { | 277 | if (!poll_mbox(isar, 1000)) { |
278 | pr_info("ISAR poll_mbox prog failed\n"); | 278 | pr_info("ISAR poll_mbox prog failed\n"); |
279 | ret = -ETIME; | 279 | ret = -ETIME; |
280 | goto reterror; | 280 | goto reterror; |
281 | } | 281 | } |
282 | spin_unlock_irqrestore(isar->hwlock, flags); | 282 | spin_unlock_irqrestore(isar->hwlock, flags); |
283 | if ((isar->iis != ISAR_IIS_FIRM) || | 283 | if ((isar->iis != ISAR_IIS_FIRM) || |
284 | isar->cmsb || isar->clsb) { | 284 | isar->cmsb || isar->clsb) { |
285 | pr_info("ISAR wrong prog response (%x,%x,%x)\n", | 285 | pr_info("ISAR wrong prog response (%x,%x,%x)\n", |
286 | isar->iis, isar->cmsb, isar->clsb); | 286 | isar->iis, isar->cmsb, isar->clsb); |
287 | ret = -EIO; | 287 | ret = -EIO; |
288 | goto reterrflg; | 288 | goto reterrflg; |
289 | } | 289 | } |
290 | } | 290 | } |
291 | pr_debug("%s: ISAR firmware block %d words loaded\n", | 291 | pr_debug("%s: ISAR firmware block %d words loaded\n", |
292 | isar->name, blk_head.len); | 292 | isar->name, blk_head.len); |
293 | } | 293 | } |
294 | isar->ch[0].bch.debug = saved_debug; | 294 | isar->ch[0].bch.debug = saved_debug; |
295 | /* 10ms delay */ | 295 | /* 10ms delay */ |
296 | cnt = 10; | 296 | cnt = 10; |
297 | while (cnt--) | 297 | while (cnt--) |
298 | mdelay(1); | 298 | mdelay(1); |
299 | isar->buf[0] = 0xff; | 299 | isar->buf[0] = 0xff; |
300 | isar->buf[1] = 0xfe; | 300 | isar->buf[1] = 0xfe; |
301 | isar->bstat = 0; | 301 | isar->bstat = 0; |
302 | spin_lock_irqsave(isar->hwlock, flags); | 302 | spin_lock_irqsave(isar->hwlock, flags); |
303 | if (!send_mbox(isar, ISAR_HIS_STDSP, 0, 2, NULL)) { | 303 | if (!send_mbox(isar, ISAR_HIS_STDSP, 0, 2, NULL)) { |
304 | pr_info("ISAR send_mbox start dsp failed\n"); | 304 | pr_info("ISAR send_mbox start dsp failed\n"); |
305 | ret = -ETIME; | 305 | ret = -ETIME; |
306 | goto reterror; | 306 | goto reterror; |
307 | } | 307 | } |
308 | if (!poll_mbox(isar, 1000)) { | 308 | if (!poll_mbox(isar, 1000)) { |
309 | pr_info("ISAR poll_mbox start dsp failed\n"); | 309 | pr_info("ISAR poll_mbox start dsp failed\n"); |
310 | ret = -ETIME; | 310 | ret = -ETIME; |
311 | goto reterror; | 311 | goto reterror; |
312 | } | 312 | } |
313 | if ((isar->iis != ISAR_IIS_STDSP) || isar->cmsb || isar->clsb) { | 313 | if ((isar->iis != ISAR_IIS_STDSP) || isar->cmsb || isar->clsb) { |
314 | pr_info("ISAR wrong start dsp response (%x,%x,%x)\n", | 314 | pr_info("ISAR wrong start dsp response (%x,%x,%x)\n", |
315 | isar->iis, isar->cmsb, isar->clsb); | 315 | isar->iis, isar->cmsb, isar->clsb); |
316 | ret = -EIO; | 316 | ret = -EIO; |
317 | goto reterror; | 317 | goto reterror; |
318 | } else | 318 | } else |
319 | pr_debug("%s: ISAR start dsp success\n", isar->name); | 319 | pr_debug("%s: ISAR start dsp success\n", isar->name); |
320 | 320 | ||
321 | /* NORMAL mode entered */ | 321 | /* NORMAL mode entered */ |
322 | /* Enable IRQs of ISAR */ | 322 | /* Enable IRQs of ISAR */ |
323 | isar->write_reg(isar->hw, ISAR_IRQBIT, ISAR_IRQSTA); | 323 | isar->write_reg(isar->hw, ISAR_IRQBIT, ISAR_IRQSTA); |
324 | spin_unlock_irqrestore(isar->hwlock, flags); | 324 | spin_unlock_irqrestore(isar->hwlock, flags); |
325 | cnt = 1000; /* max 1s */ | 325 | cnt = 1000; /* max 1s */ |
326 | while ((!isar->bstat) && cnt) { | 326 | while ((!isar->bstat) && cnt) { |
327 | mdelay(1); | 327 | mdelay(1); |
328 | cnt--; | 328 | cnt--; |
329 | } | 329 | } |
330 | if (!cnt) { | 330 | if (!cnt) { |
331 | pr_info("ISAR no general status event received\n"); | 331 | pr_info("ISAR no general status event received\n"); |
332 | ret = -ETIME; | 332 | ret = -ETIME; |
333 | goto reterrflg; | 333 | goto reterrflg; |
334 | } else | 334 | } else |
335 | pr_debug("%s: ISAR general status event %x\n", | 335 | pr_debug("%s: ISAR general status event %x\n", |
336 | isar->name, isar->bstat); | 336 | isar->name, isar->bstat); |
337 | /* 10ms delay */ | 337 | /* 10ms delay */ |
338 | cnt = 10; | 338 | cnt = 10; |
339 | while (cnt--) | 339 | while (cnt--) |
340 | mdelay(1); | 340 | mdelay(1); |
341 | isar->iis = 0; | 341 | isar->iis = 0; |
342 | spin_lock_irqsave(isar->hwlock, flags); | 342 | spin_lock_irqsave(isar->hwlock, flags); |
343 | if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { | 343 | if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { |
344 | pr_info("ISAR send_mbox self tst failed\n"); | 344 | pr_info("ISAR send_mbox self tst failed\n"); |
345 | ret = -ETIME; | 345 | ret = -ETIME; |
346 | goto reterror; | 346 | goto reterror; |
347 | } | 347 | } |
348 | spin_unlock_irqrestore(isar->hwlock, flags); | 348 | spin_unlock_irqrestore(isar->hwlock, flags); |
349 | cnt = 10000; /* max 100 ms */ | 349 | cnt = 10000; /* max 100 ms */ |
350 | while ((isar->iis != ISAR_IIS_DIAG) && cnt) { | 350 | while ((isar->iis != ISAR_IIS_DIAG) && cnt) { |
351 | udelay(10); | 351 | udelay(10); |
352 | cnt--; | 352 | cnt--; |
353 | } | 353 | } |
354 | mdelay(1); | 354 | mdelay(1); |
355 | if (!cnt) { | 355 | if (!cnt) { |
356 | pr_info("ISAR no self tst response\n"); | 356 | pr_info("ISAR no self tst response\n"); |
357 | ret = -ETIME; | 357 | ret = -ETIME; |
358 | goto reterrflg; | 358 | goto reterrflg; |
359 | } | 359 | } |
360 | if ((isar->cmsb == ISAR_CTRL_STST) && (isar->clsb == 1) | 360 | if ((isar->cmsb == ISAR_CTRL_STST) && (isar->clsb == 1) |
361 | && (isar->buf[0] == 0)) | 361 | && (isar->buf[0] == 0)) |
362 | pr_debug("%s: ISAR selftest OK\n", isar->name); | 362 | pr_debug("%s: ISAR selftest OK\n", isar->name); |
363 | else { | 363 | else { |
364 | pr_info("ISAR selftest not OK %x/%x/%x\n", | 364 | pr_info("ISAR selftest not OK %x/%x/%x\n", |
365 | isar->cmsb, isar->clsb, isar->buf[0]); | 365 | isar->cmsb, isar->clsb, isar->buf[0]); |
366 | ret = -EIO; | 366 | ret = -EIO; |
367 | goto reterrflg; | 367 | goto reterrflg; |
368 | } | 368 | } |
369 | spin_lock_irqsave(isar->hwlock, flags); | 369 | spin_lock_irqsave(isar->hwlock, flags); |
370 | isar->iis = 0; | 370 | isar->iis = 0; |
371 | if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { | 371 | if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { |
372 | pr_info("ISAR RQST SVN failed\n"); | 372 | pr_info("ISAR RQST SVN failed\n"); |
373 | ret = -ETIME; | 373 | ret = -ETIME; |
374 | goto reterror; | 374 | goto reterror; |
375 | } | 375 | } |
376 | spin_unlock_irqrestore(isar->hwlock, flags); | 376 | spin_unlock_irqrestore(isar->hwlock, flags); |
377 | cnt = 30000; /* max 300 ms */ | 377 | cnt = 30000; /* max 300 ms */ |
378 | while ((isar->iis != ISAR_IIS_DIAG) && cnt) { | 378 | while ((isar->iis != ISAR_IIS_DIAG) && cnt) { |
379 | udelay(10); | 379 | udelay(10); |
380 | cnt--; | 380 | cnt--; |
381 | } | 381 | } |
382 | mdelay(1); | 382 | mdelay(1); |
383 | if (!cnt) { | 383 | if (!cnt) { |
384 | pr_info("ISAR no SVN response\n"); | 384 | pr_info("ISAR no SVN response\n"); |
385 | ret = -ETIME; | 385 | ret = -ETIME; |
386 | goto reterrflg; | 386 | goto reterrflg; |
387 | } else { | 387 | } else { |
388 | if ((isar->cmsb == ISAR_CTRL_SWVER) && (isar->clsb == 1)) { | 388 | if ((isar->cmsb == ISAR_CTRL_SWVER) && (isar->clsb == 1)) { |
389 | pr_notice("%s: ISAR software version %#x\n", | 389 | pr_notice("%s: ISAR software version %#x\n", |
390 | isar->name, isar->buf[0]); | 390 | isar->name, isar->buf[0]); |
391 | } else { | 391 | } else { |
392 | pr_info("%s: ISAR wrong swver response (%x,%x)" | 392 | pr_info("%s: ISAR wrong swver response (%x,%x)" |
393 | " cnt(%d)\n", isar->name, isar->cmsb, | 393 | " cnt(%d)\n", isar->name, isar->cmsb, |
394 | isar->clsb, cnt); | 394 | isar->clsb, cnt); |
395 | ret = -EIO; | 395 | ret = -EIO; |
396 | goto reterrflg; | 396 | goto reterrflg; |
397 | } | 397 | } |
398 | } | 398 | } |
399 | spin_lock_irqsave(isar->hwlock, flags); | 399 | spin_lock_irqsave(isar->hwlock, flags); |
400 | isar_setup(isar); | 400 | isar_setup(isar); |
401 | spin_unlock_irqrestore(isar->hwlock, flags); | 401 | spin_unlock_irqrestore(isar->hwlock, flags); |
402 | ret = 0; | 402 | ret = 0; |
403 | reterrflg: | 403 | reterrflg: |
404 | spin_lock_irqsave(isar->hwlock, flags); | 404 | spin_lock_irqsave(isar->hwlock, flags); |
405 | reterror: | 405 | reterror: |
406 | isar->ch[0].bch.debug = saved_debug; | 406 | isar->ch[0].bch.debug = saved_debug; |
407 | if (ret) | 407 | if (ret) |
408 | /* disable ISAR IRQ */ | 408 | /* disable ISAR IRQ */ |
409 | isar->write_reg(isar->hw, ISAR_IRQBIT, 0); | 409 | isar->write_reg(isar->hw, ISAR_IRQBIT, 0); |
410 | spin_unlock_irqrestore(isar->hwlock, flags); | 410 | spin_unlock_irqrestore(isar->hwlock, flags); |
411 | return ret; | 411 | return ret; |
412 | } | 412 | } |
413 | 413 | ||
414 | static inline void | 414 | static inline void |
415 | deliver_status(struct isar_ch *ch, int status) | 415 | deliver_status(struct isar_ch *ch, int status) |
416 | { | 416 | { |
417 | pr_debug("%s: HL->LL FAXIND %x\n", ch->is->name, status); | 417 | pr_debug("%s: HL->LL FAXIND %x\n", ch->is->name, status); |
418 | _queue_data(&ch->bch.ch, PH_CONTROL_IND, status, 0, NULL, GFP_ATOMIC); | 418 | _queue_data(&ch->bch.ch, PH_CONTROL_IND, status, 0, NULL, GFP_ATOMIC); |
419 | } | 419 | } |
420 | 420 | ||
421 | static inline void | 421 | static inline void |
422 | isar_rcv_frame(struct isar_ch *ch) | 422 | isar_rcv_frame(struct isar_ch *ch) |
423 | { | 423 | { |
424 | u8 *ptr; | 424 | u8 *ptr; |
425 | int maxlen; | 425 | int maxlen; |
426 | 426 | ||
427 | if (!ch->is->clsb) { | 427 | if (!ch->is->clsb) { |
428 | pr_debug("%s; ISAR zero len frame\n", ch->is->name); | 428 | pr_debug("%s; ISAR zero len frame\n", ch->is->name); |
429 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 429 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
430 | return; | 430 | return; |
431 | } | 431 | } |
432 | if (test_bit(FLG_RX_OFF, &ch->bch.Flags)) { | 432 | if (test_bit(FLG_RX_OFF, &ch->bch.Flags)) { |
433 | ch->bch.dropcnt += ch->is->clsb; | 433 | ch->bch.dropcnt += ch->is->clsb; |
434 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 434 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
435 | return; | 435 | return; |
436 | } | 436 | } |
437 | switch (ch->bch.state) { | 437 | switch (ch->bch.state) { |
438 | case ISDN_P_NONE: | 438 | case ISDN_P_NONE: |
439 | pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n", | 439 | pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n", |
440 | ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb); | 440 | ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb); |
441 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 441 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
442 | break; | 442 | break; |
443 | case ISDN_P_B_RAW: | 443 | case ISDN_P_B_RAW: |
444 | case ISDN_P_B_L2DTMF: | 444 | case ISDN_P_B_L2DTMF: |
445 | case ISDN_P_B_MODEM_ASYNC: | 445 | case ISDN_P_B_MODEM_ASYNC: |
446 | maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); | 446 | maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); |
447 | if (maxlen < 0) { | 447 | if (maxlen < 0) { |
448 | pr_warning("%s.B%d: No bufferspace for %d bytes\n", | 448 | pr_warning("%s.B%d: No bufferspace for %d bytes\n", |
449 | ch->is->name, ch->bch.nr, ch->is->clsb); | 449 | ch->is->name, ch->bch.nr, ch->is->clsb); |
450 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 450 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
451 | break; | 451 | break; |
452 | } | 452 | } |
453 | rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); | 453 | rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); |
454 | recv_Bchannel(&ch->bch, 0, false); | 454 | recv_Bchannel(&ch->bch, 0, false); |
455 | break; | 455 | break; |
456 | case ISDN_P_B_HDLC: | 456 | case ISDN_P_B_HDLC: |
457 | maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); | 457 | maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); |
458 | if (maxlen < 0) { | 458 | if (maxlen < 0) { |
459 | pr_warning("%s.B%d: No bufferspace for %d bytes\n", | 459 | pr_warning("%s.B%d: No bufferspace for %d bytes\n", |
460 | ch->is->name, ch->bch.nr, ch->is->clsb); | 460 | ch->is->name, ch->bch.nr, ch->is->clsb); |
461 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 461 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
462 | break; | 462 | break; |
463 | } | 463 | } |
464 | if (ch->is->cmsb & HDLC_ERROR) { | 464 | if (ch->is->cmsb & HDLC_ERROR) { |
465 | pr_debug("%s: ISAR frame error %x len %d\n", | 465 | pr_debug("%s: ISAR frame error %x len %d\n", |
466 | ch->is->name, ch->is->cmsb, ch->is->clsb); | 466 | ch->is->name, ch->is->cmsb, ch->is->clsb); |
467 | #ifdef ERROR_STATISTIC | 467 | #ifdef ERROR_STATISTIC |
468 | if (ch->is->cmsb & HDLC_ERR_RER) | 468 | if (ch->is->cmsb & HDLC_ERR_RER) |
469 | ch->bch.err_inv++; | 469 | ch->bch.err_inv++; |
470 | if (ch->is->cmsb & HDLC_ERR_CER) | 470 | if (ch->is->cmsb & HDLC_ERR_CER) |
471 | ch->bch.err_crc++; | 471 | ch->bch.err_crc++; |
472 | #endif | 472 | #endif |
473 | skb_trim(ch->bch.rx_skb, 0); | 473 | skb_trim(ch->bch.rx_skb, 0); |
474 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 474 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
475 | break; | 475 | break; |
476 | } | 476 | } |
477 | if (ch->is->cmsb & HDLC_FSD) | 477 | if (ch->is->cmsb & HDLC_FSD) |
478 | skb_trim(ch->bch.rx_skb, 0); | 478 | skb_trim(ch->bch.rx_skb, 0); |
479 | ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); | 479 | ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); |
480 | rcv_mbox(ch->is, ptr); | 480 | rcv_mbox(ch->is, ptr); |
481 | if (ch->is->cmsb & HDLC_FED) { | 481 | if (ch->is->cmsb & HDLC_FED) { |
482 | if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ | 482 | if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ |
483 | pr_debug("%s: ISAR frame to short %d\n", | 483 | pr_debug("%s: ISAR frame to short %d\n", |
484 | ch->is->name, ch->bch.rx_skb->len); | 484 | ch->is->name, ch->bch.rx_skb->len); |
485 | skb_trim(ch->bch.rx_skb, 0); | 485 | skb_trim(ch->bch.rx_skb, 0); |
486 | break; | 486 | break; |
487 | } | 487 | } |
488 | skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); | 488 | skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); |
489 | recv_Bchannel(&ch->bch, 0, false); | 489 | recv_Bchannel(&ch->bch, 0, false); |
490 | } | 490 | } |
491 | break; | 491 | break; |
492 | case ISDN_P_B_T30_FAX: | 492 | case ISDN_P_B_T30_FAX: |
493 | if (ch->state != STFAX_ACTIV) { | 493 | if (ch->state != STFAX_ACTIV) { |
494 | pr_debug("%s: isar_rcv_frame: not ACTIV\n", | 494 | pr_debug("%s: isar_rcv_frame: not ACTIV\n", |
495 | ch->is->name); | 495 | ch->is->name); |
496 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 496 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
497 | if (ch->bch.rx_skb) | 497 | if (ch->bch.rx_skb) |
498 | skb_trim(ch->bch.rx_skb, 0); | 498 | skb_trim(ch->bch.rx_skb, 0); |
499 | break; | 499 | break; |
500 | } | 500 | } |
501 | if (!ch->bch.rx_skb) { | 501 | if (!ch->bch.rx_skb) { |
502 | ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, | 502 | ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen, |
503 | GFP_ATOMIC); | 503 | GFP_ATOMIC); |
504 | if (unlikely(!ch->bch.rx_skb)) { | 504 | if (unlikely(!ch->bch.rx_skb)) { |
505 | pr_info("%s: B receive out of memory\n", | 505 | pr_info("%s: B receive out of memory\n", |
506 | __func__); | 506 | __func__); |
507 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 507 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
508 | break; | 508 | break; |
509 | } | 509 | } |
510 | } | 510 | } |
511 | if (ch->cmd == PCTRL_CMD_FRM) { | 511 | if (ch->cmd == PCTRL_CMD_FRM) { |
512 | rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); | 512 | rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb)); |
513 | pr_debug("%s: isar_rcv_frame: %d\n", | 513 | pr_debug("%s: isar_rcv_frame: %d\n", |
514 | ch->is->name, ch->bch.rx_skb->len); | 514 | ch->is->name, ch->bch.rx_skb->len); |
515 | if (ch->is->cmsb & SART_NMD) { /* ABORT */ | 515 | if (ch->is->cmsb & SART_NMD) { /* ABORT */ |
516 | pr_debug("%s: isar_rcv_frame: no more data\n", | 516 | pr_debug("%s: isar_rcv_frame: no more data\n", |
517 | ch->is->name); | 517 | ch->is->name); |
518 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 518 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
519 | send_mbox(ch->is, SET_DPS(ch->dpath) | | 519 | send_mbox(ch->is, SET_DPS(ch->dpath) | |
520 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, | 520 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, |
521 | 0, NULL); | 521 | 0, NULL); |
522 | ch->state = STFAX_ESCAPE; | 522 | ch->state = STFAX_ESCAPE; |
523 | /* set_skb_flag(skb, DF_NOMOREDATA); */ | 523 | /* set_skb_flag(skb, DF_NOMOREDATA); */ |
524 | } | 524 | } |
525 | recv_Bchannel(&ch->bch, 0, false); | 525 | recv_Bchannel(&ch->bch, 0, false); |
526 | if (ch->is->cmsb & SART_NMD) | 526 | if (ch->is->cmsb & SART_NMD) |
527 | deliver_status(ch, HW_MOD_NOCARR); | 527 | deliver_status(ch, HW_MOD_NOCARR); |
528 | break; | 528 | break; |
529 | } | 529 | } |
530 | if (ch->cmd != PCTRL_CMD_FRH) { | 530 | if (ch->cmd != PCTRL_CMD_FRH) { |
531 | pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n", | 531 | pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n", |
532 | ch->is->name, ch->cmd); | 532 | ch->is->name, ch->cmd); |
533 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 533 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
534 | if (ch->bch.rx_skb) | 534 | if (ch->bch.rx_skb) |
535 | skb_trim(ch->bch.rx_skb, 0); | 535 | skb_trim(ch->bch.rx_skb, 0); |
536 | break; | 536 | break; |
537 | } | 537 | } |
538 | /* PCTRL_CMD_FRH */ | 538 | /* PCTRL_CMD_FRH */ |
539 | if ((ch->bch.rx_skb->len + ch->is->clsb) > | 539 | if ((ch->bch.rx_skb->len + ch->is->clsb) > |
540 | (ch->bch.maxlen + 2)) { | 540 | (ch->bch.maxlen + 2)) { |
541 | pr_info("%s: %s incoming packet too large\n", | 541 | pr_info("%s: %s incoming packet too large\n", |
542 | ch->is->name, __func__); | 542 | ch->is->name, __func__); |
543 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 543 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
544 | skb_trim(ch->bch.rx_skb, 0); | 544 | skb_trim(ch->bch.rx_skb, 0); |
545 | break; | 545 | break; |
546 | } else if (ch->is->cmsb & HDLC_ERROR) { | 546 | } else if (ch->is->cmsb & HDLC_ERROR) { |
547 | pr_info("%s: ISAR frame error %x len %d\n", | 547 | pr_info("%s: ISAR frame error %x len %d\n", |
548 | ch->is->name, ch->is->cmsb, ch->is->clsb); | 548 | ch->is->name, ch->is->cmsb, ch->is->clsb); |
549 | skb_trim(ch->bch.rx_skb, 0); | 549 | skb_trim(ch->bch.rx_skb, 0); |
550 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 550 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
551 | break; | 551 | break; |
552 | } | 552 | } |
553 | if (ch->is->cmsb & HDLC_FSD) | 553 | if (ch->is->cmsb & HDLC_FSD) |
554 | skb_trim(ch->bch.rx_skb, 0); | 554 | skb_trim(ch->bch.rx_skb, 0); |
555 | ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); | 555 | ptr = skb_put(ch->bch.rx_skb, ch->is->clsb); |
556 | rcv_mbox(ch->is, ptr); | 556 | rcv_mbox(ch->is, ptr); |
557 | if (ch->is->cmsb & HDLC_FED) { | 557 | if (ch->is->cmsb & HDLC_FED) { |
558 | if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ | 558 | if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */ |
559 | pr_info("%s: ISAR frame to short %d\n", | 559 | pr_info("%s: ISAR frame to short %d\n", |
560 | ch->is->name, ch->bch.rx_skb->len); | 560 | ch->is->name, ch->bch.rx_skb->len); |
561 | skb_trim(ch->bch.rx_skb, 0); | 561 | skb_trim(ch->bch.rx_skb, 0); |
562 | break; | 562 | break; |
563 | } | 563 | } |
564 | skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); | 564 | skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2); |
565 | recv_Bchannel(&ch->bch, 0, false); | 565 | recv_Bchannel(&ch->bch, 0, false); |
566 | } | 566 | } |
567 | if (ch->is->cmsb & SART_NMD) { /* ABORT */ | 567 | if (ch->is->cmsb & SART_NMD) { /* ABORT */ |
568 | pr_debug("%s: isar_rcv_frame: no more data\n", | 568 | pr_debug("%s: isar_rcv_frame: no more data\n", |
569 | ch->is->name); | 569 | ch->is->name); |
570 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 570 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
571 | if (ch->bch.rx_skb) | 571 | if (ch->bch.rx_skb) |
572 | skb_trim(ch->bch.rx_skb, 0); | 572 | skb_trim(ch->bch.rx_skb, 0); |
573 | send_mbox(ch->is, SET_DPS(ch->dpath) | | 573 | send_mbox(ch->is, SET_DPS(ch->dpath) | |
574 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); | 574 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); |
575 | ch->state = STFAX_ESCAPE; | 575 | ch->state = STFAX_ESCAPE; |
576 | deliver_status(ch, HW_MOD_NOCARR); | 576 | deliver_status(ch, HW_MOD_NOCARR); |
577 | } | 577 | } |
578 | break; | 578 | break; |
579 | default: | 579 | default: |
580 | pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state); | 580 | pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state); |
581 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); | 581 | ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); |
582 | break; | 582 | break; |
583 | } | 583 | } |
584 | } | 584 | } |
585 | 585 | ||
586 | static void | 586 | static void |
587 | isar_fill_fifo(struct isar_ch *ch) | 587 | isar_fill_fifo(struct isar_ch *ch) |
588 | { | 588 | { |
589 | int count; | 589 | int count; |
590 | u8 msb; | 590 | u8 msb; |
591 | u8 *ptr; | 591 | u8 *ptr; |
592 | 592 | ||
593 | pr_debug("%s: ch%d tx_skb %d tx_idx %d\n", ch->is->name, ch->bch.nr, | 593 | pr_debug("%s: ch%d tx_skb %d tx_idx %d\n", ch->is->name, ch->bch.nr, |
594 | ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, ch->bch.tx_idx); | 594 | ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, ch->bch.tx_idx); |
595 | if (!(ch->is->bstat & | 595 | if (!(ch->is->bstat & |
596 | (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) | 596 | (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) |
597 | return; | 597 | return; |
598 | if (!ch->bch.tx_skb) { | 598 | if (!ch->bch.tx_skb) { |
599 | if (!test_bit(FLG_TX_EMPTY, &ch->bch.Flags) || | 599 | if (!test_bit(FLG_TX_EMPTY, &ch->bch.Flags) || |
600 | (ch->bch.state != ISDN_P_B_RAW)) | 600 | (ch->bch.state != ISDN_P_B_RAW)) |
601 | return; | 601 | return; |
602 | count = ch->mml; | 602 | count = ch->mml; |
603 | /* use the card buffer */ | 603 | /* use the card buffer */ |
604 | memset(ch->is->buf, ch->bch.fill[0], count); | 604 | memset(ch->is->buf, ch->bch.fill[0], count); |
605 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, | 605 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, |
606 | 0, count, ch->is->buf); | 606 | 0, count, ch->is->buf); |
607 | return; | 607 | return; |
608 | } | 608 | } |
609 | count = ch->bch.tx_skb->len - ch->bch.tx_idx; | 609 | count = ch->bch.tx_skb->len - ch->bch.tx_idx; |
610 | if (count <= 0) | 610 | if (count <= 0) |
611 | return; | 611 | return; |
612 | if (count > ch->mml) { | 612 | if (count > ch->mml) { |
613 | msb = 0; | 613 | msb = 0; |
614 | count = ch->mml; | 614 | count = ch->mml; |
615 | } else { | 615 | } else { |
616 | msb = HDLC_FED; | 616 | msb = HDLC_FED; |
617 | } | 617 | } |
618 | ptr = ch->bch.tx_skb->data + ch->bch.tx_idx; | 618 | ptr = ch->bch.tx_skb->data + ch->bch.tx_idx; |
619 | if (!ch->bch.tx_idx) { | 619 | if (!ch->bch.tx_idx) { |
620 | pr_debug("%s: frame start\n", ch->is->name); | 620 | pr_debug("%s: frame start\n", ch->is->name); |
621 | if ((ch->bch.state == ISDN_P_B_T30_FAX) && | 621 | if ((ch->bch.state == ISDN_P_B_T30_FAX) && |
622 | (ch->cmd == PCTRL_CMD_FTH)) { | 622 | (ch->cmd == PCTRL_CMD_FTH)) { |
623 | if (count > 1) { | 623 | if (count > 1) { |
624 | if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) { | 624 | if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) { |
625 | /* last frame */ | 625 | /* last frame */ |
626 | test_and_set_bit(FLG_LASTDATA, | 626 | test_and_set_bit(FLG_LASTDATA, |
627 | &ch->bch.Flags); | 627 | &ch->bch.Flags); |
628 | pr_debug("%s: set LASTDATA\n", | 628 | pr_debug("%s: set LASTDATA\n", |
629 | ch->is->name); | 629 | ch->is->name); |
630 | if (msb == HDLC_FED) | 630 | if (msb == HDLC_FED) |
631 | test_and_set_bit(FLG_DLEETX, | 631 | test_and_set_bit(FLG_DLEETX, |
632 | &ch->bch.Flags); | 632 | &ch->bch.Flags); |
633 | } | 633 | } |
634 | } | 634 | } |
635 | } | 635 | } |
636 | msb |= HDLC_FST; | 636 | msb |= HDLC_FST; |
637 | } | 637 | } |
638 | ch->bch.tx_idx += count; | 638 | ch->bch.tx_idx += count; |
639 | switch (ch->bch.state) { | 639 | switch (ch->bch.state) { |
640 | case ISDN_P_NONE: | 640 | case ISDN_P_NONE: |
641 | pr_info("%s: wrong protocol 0\n", __func__); | 641 | pr_info("%s: wrong protocol 0\n", __func__); |
642 | break; | 642 | break; |
643 | case ISDN_P_B_RAW: | 643 | case ISDN_P_B_RAW: |
644 | case ISDN_P_B_L2DTMF: | 644 | case ISDN_P_B_L2DTMF: |
645 | case ISDN_P_B_MODEM_ASYNC: | 645 | case ISDN_P_B_MODEM_ASYNC: |
646 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, | 646 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, |
647 | 0, count, ptr); | 647 | 0, count, ptr); |
648 | break; | 648 | break; |
649 | case ISDN_P_B_HDLC: | 649 | case ISDN_P_B_HDLC: |
650 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, | 650 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, |
651 | msb, count, ptr); | 651 | msb, count, ptr); |
652 | break; | 652 | break; |
653 | case ISDN_P_B_T30_FAX: | 653 | case ISDN_P_B_T30_FAX: |
654 | if (ch->state != STFAX_ACTIV) | 654 | if (ch->state != STFAX_ACTIV) |
655 | pr_debug("%s: not ACTIV\n", ch->is->name); | 655 | pr_debug("%s: not ACTIV\n", ch->is->name); |
656 | else if (ch->cmd == PCTRL_CMD_FTH) | 656 | else if (ch->cmd == PCTRL_CMD_FTH) |
657 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, | 657 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, |
658 | msb, count, ptr); | 658 | msb, count, ptr); |
659 | else if (ch->cmd == PCTRL_CMD_FTM) | 659 | else if (ch->cmd == PCTRL_CMD_FTM) |
660 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, | 660 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, |
661 | 0, count, ptr); | 661 | 0, count, ptr); |
662 | else | 662 | else |
663 | pr_debug("%s: not FTH/FTM\n", ch->is->name); | 663 | pr_debug("%s: not FTH/FTM\n", ch->is->name); |
664 | break; | 664 | break; |
665 | default: | 665 | default: |
666 | pr_info("%s: protocol(%x) error\n", | 666 | pr_info("%s: protocol(%x) error\n", |
667 | __func__, ch->bch.state); | 667 | __func__, ch->bch.state); |
668 | break; | 668 | break; |
669 | } | 669 | } |
670 | } | 670 | } |
671 | 671 | ||
672 | static inline struct isar_ch * | 672 | static inline struct isar_ch * |
673 | sel_bch_isar(struct isar_hw *isar, u8 dpath) | 673 | sel_bch_isar(struct isar_hw *isar, u8 dpath) |
674 | { | 674 | { |
675 | struct isar_ch *base = &isar->ch[0]; | 675 | struct isar_ch *base = &isar->ch[0]; |
676 | 676 | ||
677 | if ((!dpath) || (dpath > 2)) | 677 | if ((!dpath) || (dpath > 2)) |
678 | return NULL; | 678 | return NULL; |
679 | if (base->dpath == dpath) | 679 | if (base->dpath == dpath) |
680 | return base; | 680 | return base; |
681 | base++; | 681 | base++; |
682 | if (base->dpath == dpath) | 682 | if (base->dpath == dpath) |
683 | return base; | 683 | return base; |
684 | return NULL; | 684 | return NULL; |
685 | } | 685 | } |
686 | 686 | ||
687 | static void | 687 | static void |
688 | send_next(struct isar_ch *ch) | 688 | send_next(struct isar_ch *ch) |
689 | { | 689 | { |
690 | pr_debug("%s: %s ch%d tx_skb %d tx_idx %d\n", ch->is->name, __func__, | 690 | pr_debug("%s: %s ch%d tx_skb %d tx_idx %d\n", ch->is->name, __func__, |
691 | ch->bch.nr, ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, | 691 | ch->bch.nr, ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, |
692 | ch->bch.tx_idx); | 692 | ch->bch.tx_idx); |
693 | if (ch->bch.state == ISDN_P_B_T30_FAX) { | 693 | if (ch->bch.state == ISDN_P_B_T30_FAX) { |
694 | if (ch->cmd == PCTRL_CMD_FTH) { | 694 | if (ch->cmd == PCTRL_CMD_FTH) { |
695 | if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { | 695 | if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { |
696 | pr_debug("set NMD_DATA\n"); | 696 | pr_debug("set NMD_DATA\n"); |
697 | test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); | 697 | test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); |
698 | } | 698 | } |
699 | } else if (ch->cmd == PCTRL_CMD_FTM) { | 699 | } else if (ch->cmd == PCTRL_CMD_FTM) { |
700 | if (test_bit(FLG_DLEETX, &ch->bch.Flags)) { | 700 | if (test_bit(FLG_DLEETX, &ch->bch.Flags)) { |
701 | test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags); | 701 | test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags); |
702 | test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); | 702 | test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); |
703 | } | 703 | } |
704 | } | 704 | } |
705 | } | 705 | } |
706 | if (ch->bch.tx_skb) | 706 | if (ch->bch.tx_skb) |
707 | dev_kfree_skb(ch->bch.tx_skb); | 707 | dev_kfree_skb(ch->bch.tx_skb); |
708 | if (get_next_bframe(&ch->bch)) { | 708 | if (get_next_bframe(&ch->bch)) { |
709 | isar_fill_fifo(ch); | 709 | isar_fill_fifo(ch); |
710 | test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags); | 710 | test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags); |
711 | } else if (test_bit(FLG_TX_EMPTY, &ch->bch.Flags)) { | 711 | } else if (test_bit(FLG_TX_EMPTY, &ch->bch.Flags)) { |
712 | isar_fill_fifo(ch); | 712 | isar_fill_fifo(ch); |
713 | } else { | 713 | } else { |
714 | if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { | 714 | if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { |
715 | if (test_and_clear_bit(FLG_LASTDATA, | 715 | if (test_and_clear_bit(FLG_LASTDATA, |
716 | &ch->bch.Flags)) { | 716 | &ch->bch.Flags)) { |
717 | if (test_and_clear_bit(FLG_NMD_DATA, | 717 | if (test_and_clear_bit(FLG_NMD_DATA, |
718 | &ch->bch.Flags)) { | 718 | &ch->bch.Flags)) { |
719 | u8 zd = 0; | 719 | u8 zd = 0; |
720 | send_mbox(ch->is, SET_DPS(ch->dpath) | | 720 | send_mbox(ch->is, SET_DPS(ch->dpath) | |
721 | ISAR_HIS_SDATA, 0x01, 1, &zd); | 721 | ISAR_HIS_SDATA, 0x01, 1, &zd); |
722 | } | 722 | } |
723 | test_and_set_bit(FLG_LL_OK, &ch->bch.Flags); | 723 | test_and_set_bit(FLG_LL_OK, &ch->bch.Flags); |
724 | } else { | 724 | } else { |
725 | deliver_status(ch, HW_MOD_CONNECT); | 725 | deliver_status(ch, HW_MOD_CONNECT); |
726 | } | 726 | } |
727 | } else if (test_bit(FLG_FILLEMPTY, &ch->bch.Flags)) { | 727 | } else if (test_bit(FLG_FILLEMPTY, &ch->bch.Flags)) { |
728 | test_and_set_bit(FLG_TX_EMPTY, &ch->bch.Flags); | 728 | test_and_set_bit(FLG_TX_EMPTY, &ch->bch.Flags); |
729 | } | 729 | } |
730 | } | 730 | } |
731 | } | 731 | } |
732 | 732 | ||
733 | static void | 733 | static void |
734 | check_send(struct isar_hw *isar, u8 rdm) | 734 | check_send(struct isar_hw *isar, u8 rdm) |
735 | { | 735 | { |
736 | struct isar_ch *ch; | 736 | struct isar_ch *ch; |
737 | 737 | ||
738 | pr_debug("%s: rdm %x\n", isar->name, rdm); | 738 | pr_debug("%s: rdm %x\n", isar->name, rdm); |
739 | if (rdm & BSTAT_RDM1) { | 739 | if (rdm & BSTAT_RDM1) { |
740 | ch = sel_bch_isar(isar, 1); | 740 | ch = sel_bch_isar(isar, 1); |
741 | if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { | 741 | if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { |
742 | if (ch->bch.tx_skb && (ch->bch.tx_skb->len > | 742 | if (ch->bch.tx_skb && (ch->bch.tx_skb->len > |
743 | ch->bch.tx_idx)) | 743 | ch->bch.tx_idx)) |
744 | isar_fill_fifo(ch); | 744 | isar_fill_fifo(ch); |
745 | else | 745 | else |
746 | send_next(ch); | 746 | send_next(ch); |
747 | } | 747 | } |
748 | } | 748 | } |
749 | if (rdm & BSTAT_RDM2) { | 749 | if (rdm & BSTAT_RDM2) { |
750 | ch = sel_bch_isar(isar, 2); | 750 | ch = sel_bch_isar(isar, 2); |
751 | if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { | 751 | if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { |
752 | if (ch->bch.tx_skb && (ch->bch.tx_skb->len > | 752 | if (ch->bch.tx_skb && (ch->bch.tx_skb->len > |
753 | ch->bch.tx_idx)) | 753 | ch->bch.tx_idx)) |
754 | isar_fill_fifo(ch); | 754 | isar_fill_fifo(ch); |
755 | else | 755 | else |
756 | send_next(ch); | 756 | send_next(ch); |
757 | } | 757 | } |
758 | } | 758 | } |
759 | } | 759 | } |
760 | 760 | ||
761 | const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4", | 761 | const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4", |
762 | "300", "600", "1200", "2400", "4800", "7200", | 762 | "300", "600", "1200", "2400", "4800", "7200", |
763 | "9600nt", "9600t", "12000", "14400", "WRONG"}; | 763 | "9600nt", "9600t", "12000", "14400", "WRONG"}; |
764 | const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21", | 764 | const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21", |
765 | "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"}; | 765 | "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"}; |
766 | 766 | ||
767 | static void | 767 | static void |
768 | isar_pump_status_rsp(struct isar_ch *ch) { | 768 | isar_pump_status_rsp(struct isar_ch *ch) { |
769 | u8 ril = ch->is->buf[0]; | 769 | u8 ril = ch->is->buf[0]; |
770 | u8 rim; | 770 | u8 rim; |
771 | 771 | ||
772 | if (!test_and_clear_bit(ISAR_RATE_REQ, &ch->is->Flags)) | 772 | if (!test_and_clear_bit(ISAR_RATE_REQ, &ch->is->Flags)) |
773 | return; | 773 | return; |
774 | if (ril > 14) { | 774 | if (ril > 14) { |
775 | pr_info("%s: wrong pstrsp ril=%d\n", ch->is->name, ril); | 775 | pr_info("%s: wrong pstrsp ril=%d\n", ch->is->name, ril); |
776 | ril = 15; | 776 | ril = 15; |
777 | } | 777 | } |
778 | switch (ch->is->buf[1]) { | 778 | switch (ch->is->buf[1]) { |
779 | case 0: | 779 | case 0: |
780 | rim = 0; | 780 | rim = 0; |
781 | break; | 781 | break; |
782 | case 0x20: | 782 | case 0x20: |
783 | rim = 2; | 783 | rim = 2; |
784 | break; | 784 | break; |
785 | case 0x40: | 785 | case 0x40: |
786 | rim = 3; | 786 | rim = 3; |
787 | break; | 787 | break; |
788 | case 0x41: | 788 | case 0x41: |
789 | rim = 4; | 789 | rim = 4; |
790 | break; | 790 | break; |
791 | case 0x51: | 791 | case 0x51: |
792 | rim = 5; | 792 | rim = 5; |
793 | break; | 793 | break; |
794 | case 0x61: | 794 | case 0x61: |
795 | rim = 6; | 795 | rim = 6; |
796 | break; | 796 | break; |
797 | case 0x71: | 797 | case 0x71: |
798 | rim = 7; | 798 | rim = 7; |
799 | break; | 799 | break; |
800 | case 0x82: | 800 | case 0x82: |
801 | rim = 8; | 801 | rim = 8; |
802 | break; | 802 | break; |
803 | case 0x92: | 803 | case 0x92: |
804 | rim = 9; | 804 | rim = 9; |
805 | break; | 805 | break; |
806 | case 0xa2: | 806 | case 0xa2: |
807 | rim = 10; | 807 | rim = 10; |
808 | break; | 808 | break; |
809 | default: | 809 | default: |
810 | rim = 1; | 810 | rim = 1; |
811 | break; | 811 | break; |
812 | } | 812 | } |
813 | sprintf(ch->conmsg, "%s %s", dmril[ril], dmrim[rim]); | 813 | sprintf(ch->conmsg, "%s %s", dmril[ril], dmrim[rim]); |
814 | pr_debug("%s: pump strsp %s\n", ch->is->name, ch->conmsg); | 814 | pr_debug("%s: pump strsp %s\n", ch->is->name, ch->conmsg); |
815 | } | 815 | } |
816 | 816 | ||
817 | static void | 817 | static void |
818 | isar_pump_statev_modem(struct isar_ch *ch, u8 devt) { | 818 | isar_pump_statev_modem(struct isar_ch *ch, u8 devt) { |
819 | u8 dps = SET_DPS(ch->dpath); | 819 | u8 dps = SET_DPS(ch->dpath); |
820 | 820 | ||
821 | switch (devt) { | 821 | switch (devt) { |
822 | case PSEV_10MS_TIMER: | 822 | case PSEV_10MS_TIMER: |
823 | pr_debug("%s: pump stev TIMER\n", ch->is->name); | 823 | pr_debug("%s: pump stev TIMER\n", ch->is->name); |
824 | break; | 824 | break; |
825 | case PSEV_CON_ON: | 825 | case PSEV_CON_ON: |
826 | pr_debug("%s: pump stev CONNECT\n", ch->is->name); | 826 | pr_debug("%s: pump stev CONNECT\n", ch->is->name); |
827 | deliver_status(ch, HW_MOD_CONNECT); | 827 | deliver_status(ch, HW_MOD_CONNECT); |
828 | break; | 828 | break; |
829 | case PSEV_CON_OFF: | 829 | case PSEV_CON_OFF: |
830 | pr_debug("%s: pump stev NO CONNECT\n", ch->is->name); | 830 | pr_debug("%s: pump stev NO CONNECT\n", ch->is->name); |
831 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 831 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
832 | deliver_status(ch, HW_MOD_NOCARR); | 832 | deliver_status(ch, HW_MOD_NOCARR); |
833 | break; | 833 | break; |
834 | case PSEV_V24_OFF: | 834 | case PSEV_V24_OFF: |
835 | pr_debug("%s: pump stev V24 OFF\n", ch->is->name); | 835 | pr_debug("%s: pump stev V24 OFF\n", ch->is->name); |
836 | break; | 836 | break; |
837 | case PSEV_CTS_ON: | 837 | case PSEV_CTS_ON: |
838 | pr_debug("%s: pump stev CTS ON\n", ch->is->name); | 838 | pr_debug("%s: pump stev CTS ON\n", ch->is->name); |
839 | break; | 839 | break; |
840 | case PSEV_CTS_OFF: | 840 | case PSEV_CTS_OFF: |
841 | pr_debug("%s pump stev CTS OFF\n", ch->is->name); | 841 | pr_debug("%s pump stev CTS OFF\n", ch->is->name); |
842 | break; | 842 | break; |
843 | case PSEV_DCD_ON: | 843 | case PSEV_DCD_ON: |
844 | pr_debug("%s: pump stev CARRIER ON\n", ch->is->name); | 844 | pr_debug("%s: pump stev CARRIER ON\n", ch->is->name); |
845 | test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags); | 845 | test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags); |
846 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 846 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
847 | break; | 847 | break; |
848 | case PSEV_DCD_OFF: | 848 | case PSEV_DCD_OFF: |
849 | pr_debug("%s: pump stev CARRIER OFF\n", ch->is->name); | 849 | pr_debug("%s: pump stev CARRIER OFF\n", ch->is->name); |
850 | break; | 850 | break; |
851 | case PSEV_DSR_ON: | 851 | case PSEV_DSR_ON: |
852 | pr_debug("%s: pump stev DSR ON\n", ch->is->name); | 852 | pr_debug("%s: pump stev DSR ON\n", ch->is->name); |
853 | break; | 853 | break; |
854 | case PSEV_DSR_OFF: | 854 | case PSEV_DSR_OFF: |
855 | pr_debug("%s: pump stev DSR_OFF\n", ch->is->name); | 855 | pr_debug("%s: pump stev DSR_OFF\n", ch->is->name); |
856 | break; | 856 | break; |
857 | case PSEV_REM_RET: | 857 | case PSEV_REM_RET: |
858 | pr_debug("%s: pump stev REMOTE RETRAIN\n", ch->is->name); | 858 | pr_debug("%s: pump stev REMOTE RETRAIN\n", ch->is->name); |
859 | break; | 859 | break; |
860 | case PSEV_REM_REN: | 860 | case PSEV_REM_REN: |
861 | pr_debug("%s: pump stev REMOTE RENEGOTIATE\n", ch->is->name); | 861 | pr_debug("%s: pump stev REMOTE RENEGOTIATE\n", ch->is->name); |
862 | break; | 862 | break; |
863 | case PSEV_GSTN_CLR: | 863 | case PSEV_GSTN_CLR: |
864 | pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name); | 864 | pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name); |
865 | break; | 865 | break; |
866 | default: | 866 | default: |
867 | pr_info("u%s: unknown pump stev %x\n", ch->is->name, devt); | 867 | pr_info("u%s: unknown pump stev %x\n", ch->is->name, devt); |
868 | break; | 868 | break; |
869 | } | 869 | } |
870 | } | 870 | } |
871 | 871 | ||
872 | static void | 872 | static void |
873 | isar_pump_statev_fax(struct isar_ch *ch, u8 devt) { | 873 | isar_pump_statev_fax(struct isar_ch *ch, u8 devt) { |
874 | u8 dps = SET_DPS(ch->dpath); | 874 | u8 dps = SET_DPS(ch->dpath); |
875 | u8 p1; | 875 | u8 p1; |
876 | 876 | ||
877 | switch (devt) { | 877 | switch (devt) { |
878 | case PSEV_10MS_TIMER: | 878 | case PSEV_10MS_TIMER: |
879 | pr_debug("%s: pump stev TIMER\n", ch->is->name); | 879 | pr_debug("%s: pump stev TIMER\n", ch->is->name); |
880 | break; | 880 | break; |
881 | case PSEV_RSP_READY: | 881 | case PSEV_RSP_READY: |
882 | pr_debug("%s: pump stev RSP_READY\n", ch->is->name); | 882 | pr_debug("%s: pump stev RSP_READY\n", ch->is->name); |
883 | ch->state = STFAX_READY; | 883 | ch->state = STFAX_READY; |
884 | deliver_status(ch, HW_MOD_READY); | 884 | deliver_status(ch, HW_MOD_READY); |
885 | #ifdef AUTOCON | 885 | #ifdef AUTOCON |
886 | if (test_bit(BC_FLG_ORIG, &ch->bch.Flags)) | 886 | if (test_bit(BC_FLG_ORIG, &ch->bch.Flags)) |
887 | isar_pump_cmd(bch, HW_MOD_FRH, 3); | 887 | isar_pump_cmd(bch, HW_MOD_FRH, 3); |
888 | else | 888 | else |
889 | isar_pump_cmd(bch, HW_MOD_FTH, 3); | 889 | isar_pump_cmd(bch, HW_MOD_FTH, 3); |
890 | #endif | 890 | #endif |
891 | break; | 891 | break; |
892 | case PSEV_LINE_TX_H: | 892 | case PSEV_LINE_TX_H: |
893 | if (ch->state == STFAX_LINE) { | 893 | if (ch->state == STFAX_LINE) { |
894 | pr_debug("%s: pump stev LINE_TX_H\n", ch->is->name); | 894 | pr_debug("%s: pump stev LINE_TX_H\n", ch->is->name); |
895 | ch->state = STFAX_CONT; | 895 | ch->state = STFAX_CONT; |
896 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 896 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
897 | PCTRL_CMD_CONT, 0, NULL); | 897 | PCTRL_CMD_CONT, 0, NULL); |
898 | } else { | 898 | } else { |
899 | pr_debug("%s: pump stev LINE_TX_H wrong st %x\n", | 899 | pr_debug("%s: pump stev LINE_TX_H wrong st %x\n", |
900 | ch->is->name, ch->state); | 900 | ch->is->name, ch->state); |
901 | } | 901 | } |
902 | break; | 902 | break; |
903 | case PSEV_LINE_RX_H: | 903 | case PSEV_LINE_RX_H: |
904 | if (ch->state == STFAX_LINE) { | 904 | if (ch->state == STFAX_LINE) { |
905 | pr_debug("%s: pump stev LINE_RX_H\n", ch->is->name); | 905 | pr_debug("%s: pump stev LINE_RX_H\n", ch->is->name); |
906 | ch->state = STFAX_CONT; | 906 | ch->state = STFAX_CONT; |
907 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 907 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
908 | PCTRL_CMD_CONT, 0, NULL); | 908 | PCTRL_CMD_CONT, 0, NULL); |
909 | } else { | 909 | } else { |
910 | pr_debug("%s: pump stev LINE_RX_H wrong st %x\n", | 910 | pr_debug("%s: pump stev LINE_RX_H wrong st %x\n", |
911 | ch->is->name, ch->state); | 911 | ch->is->name, ch->state); |
912 | } | 912 | } |
913 | break; | 913 | break; |
914 | case PSEV_LINE_TX_B: | 914 | case PSEV_LINE_TX_B: |
915 | if (ch->state == STFAX_LINE) { | 915 | if (ch->state == STFAX_LINE) { |
916 | pr_debug("%s: pump stev LINE_TX_B\n", ch->is->name); | 916 | pr_debug("%s: pump stev LINE_TX_B\n", ch->is->name); |
917 | ch->state = STFAX_CONT; | 917 | ch->state = STFAX_CONT; |
918 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 918 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
919 | PCTRL_CMD_CONT, 0, NULL); | 919 | PCTRL_CMD_CONT, 0, NULL); |
920 | } else { | 920 | } else { |
921 | pr_debug("%s: pump stev LINE_TX_B wrong st %x\n", | 921 | pr_debug("%s: pump stev LINE_TX_B wrong st %x\n", |
922 | ch->is->name, ch->state); | 922 | ch->is->name, ch->state); |
923 | } | 923 | } |
924 | break; | 924 | break; |
925 | case PSEV_LINE_RX_B: | 925 | case PSEV_LINE_RX_B: |
926 | if (ch->state == STFAX_LINE) { | 926 | if (ch->state == STFAX_LINE) { |
927 | pr_debug("%s: pump stev LINE_RX_B\n", ch->is->name); | 927 | pr_debug("%s: pump stev LINE_RX_B\n", ch->is->name); |
928 | ch->state = STFAX_CONT; | 928 | ch->state = STFAX_CONT; |
929 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 929 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
930 | PCTRL_CMD_CONT, 0, NULL); | 930 | PCTRL_CMD_CONT, 0, NULL); |
931 | } else { | 931 | } else { |
932 | pr_debug("%s: pump stev LINE_RX_B wrong st %x\n", | 932 | pr_debug("%s: pump stev LINE_RX_B wrong st %x\n", |
933 | ch->is->name, ch->state); | 933 | ch->is->name, ch->state); |
934 | } | 934 | } |
935 | break; | 935 | break; |
936 | case PSEV_RSP_CONN: | 936 | case PSEV_RSP_CONN: |
937 | if (ch->state == STFAX_CONT) { | 937 | if (ch->state == STFAX_CONT) { |
938 | pr_debug("%s: pump stev RSP_CONN\n", ch->is->name); | 938 | pr_debug("%s: pump stev RSP_CONN\n", ch->is->name); |
939 | ch->state = STFAX_ACTIV; | 939 | ch->state = STFAX_ACTIV; |
940 | test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags); | 940 | test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags); |
941 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 941 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
942 | if (ch->cmd == PCTRL_CMD_FTH) { | 942 | if (ch->cmd == PCTRL_CMD_FTH) { |
943 | int delay = (ch->mod == 3) ? 1000 : 200; | 943 | int delay = (ch->mod == 3) ? 1000 : 200; |
944 | /* 1s (200 ms) Flags before data */ | 944 | /* 1s (200 ms) Flags before data */ |
945 | if (test_and_set_bit(FLG_FTI_RUN, | 945 | if (test_and_set_bit(FLG_FTI_RUN, |
946 | &ch->bch.Flags)) | 946 | &ch->bch.Flags)) |
947 | del_timer(&ch->ftimer); | 947 | del_timer(&ch->ftimer); |
948 | ch->ftimer.expires = | 948 | ch->ftimer.expires = |
949 | jiffies + ((delay * HZ) / 1000); | 949 | jiffies + ((delay * HZ) / 1000); |
950 | test_and_set_bit(FLG_LL_CONN, | 950 | test_and_set_bit(FLG_LL_CONN, |
951 | &ch->bch.Flags); | 951 | &ch->bch.Flags); |
952 | add_timer(&ch->ftimer); | 952 | add_timer(&ch->ftimer); |
953 | } else { | 953 | } else { |
954 | deliver_status(ch, HW_MOD_CONNECT); | 954 | deliver_status(ch, HW_MOD_CONNECT); |
955 | } | 955 | } |
956 | } else { | 956 | } else { |
957 | pr_debug("%s: pump stev RSP_CONN wrong st %x\n", | 957 | pr_debug("%s: pump stev RSP_CONN wrong st %x\n", |
958 | ch->is->name, ch->state); | 958 | ch->is->name, ch->state); |
959 | } | 959 | } |
960 | break; | 960 | break; |
961 | case PSEV_FLAGS_DET: | 961 | case PSEV_FLAGS_DET: |
962 | pr_debug("%s: pump stev FLAGS_DET\n", ch->is->name); | 962 | pr_debug("%s: pump stev FLAGS_DET\n", ch->is->name); |
963 | break; | 963 | break; |
964 | case PSEV_RSP_DISC: | 964 | case PSEV_RSP_DISC: |
965 | pr_debug("%s: pump stev RSP_DISC state(%d)\n", | 965 | pr_debug("%s: pump stev RSP_DISC state(%d)\n", |
966 | ch->is->name, ch->state); | 966 | ch->is->name, ch->state); |
967 | if (ch->state == STFAX_ESCAPE) { | 967 | if (ch->state == STFAX_ESCAPE) { |
968 | p1 = 5; | 968 | p1 = 5; |
969 | switch (ch->newcmd) { | 969 | switch (ch->newcmd) { |
970 | case 0: | 970 | case 0: |
971 | ch->state = STFAX_READY; | 971 | ch->state = STFAX_READY; |
972 | break; | 972 | break; |
973 | case PCTRL_CMD_FTM: | 973 | case PCTRL_CMD_FTM: |
974 | p1 = 2; | 974 | p1 = 2; |
975 | case PCTRL_CMD_FTH: | 975 | case PCTRL_CMD_FTH: |
976 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 976 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
977 | PCTRL_CMD_SILON, 1, &p1); | 977 | PCTRL_CMD_SILON, 1, &p1); |
978 | ch->state = STFAX_SILDET; | 978 | ch->state = STFAX_SILDET; |
979 | break; | 979 | break; |
980 | case PCTRL_CMD_FRH: | 980 | case PCTRL_CMD_FRH: |
981 | case PCTRL_CMD_FRM: | 981 | case PCTRL_CMD_FRM: |
982 | ch->mod = ch->newmod; | 982 | ch->mod = ch->newmod; |
983 | p1 = ch->newmod; | 983 | p1 = ch->newmod; |
984 | ch->newmod = 0; | 984 | ch->newmod = 0; |
985 | ch->cmd = ch->newcmd; | 985 | ch->cmd = ch->newcmd; |
986 | ch->newcmd = 0; | 986 | ch->newcmd = 0; |
987 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 987 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
988 | ch->cmd, 1, &p1); | 988 | ch->cmd, 1, &p1); |
989 | ch->state = STFAX_LINE; | 989 | ch->state = STFAX_LINE; |
990 | ch->try_mod = 3; | 990 | ch->try_mod = 3; |
991 | break; | 991 | break; |
992 | default: | 992 | default: |
993 | pr_debug("%s: RSP_DISC unknown newcmd %x\n", | 993 | pr_debug("%s: RSP_DISC unknown newcmd %x\n", |
994 | ch->is->name, ch->newcmd); | 994 | ch->is->name, ch->newcmd); |
995 | break; | 995 | break; |
996 | } | 996 | } |
997 | } else if (ch->state == STFAX_ACTIV) { | 997 | } else if (ch->state == STFAX_ACTIV) { |
998 | if (test_and_clear_bit(FLG_LL_OK, &ch->bch.Flags)) | 998 | if (test_and_clear_bit(FLG_LL_OK, &ch->bch.Flags)) |
999 | deliver_status(ch, HW_MOD_OK); | 999 | deliver_status(ch, HW_MOD_OK); |
1000 | else if (ch->cmd == PCTRL_CMD_FRM) | 1000 | else if (ch->cmd == PCTRL_CMD_FRM) |
1001 | deliver_status(ch, HW_MOD_NOCARR); | 1001 | deliver_status(ch, HW_MOD_NOCARR); |
1002 | else | 1002 | else |
1003 | deliver_status(ch, HW_MOD_FCERROR); | 1003 | deliver_status(ch, HW_MOD_FCERROR); |
1004 | ch->state = STFAX_READY; | 1004 | ch->state = STFAX_READY; |
1005 | } else if (ch->state != STFAX_SILDET) { | 1005 | } else if (ch->state != STFAX_SILDET) { |
1006 | /* ignore in STFAX_SILDET */ | 1006 | /* ignore in STFAX_SILDET */ |
1007 | ch->state = STFAX_READY; | 1007 | ch->state = STFAX_READY; |
1008 | deliver_status(ch, HW_MOD_FCERROR); | 1008 | deliver_status(ch, HW_MOD_FCERROR); |
1009 | } | 1009 | } |
1010 | break; | 1010 | break; |
1011 | case PSEV_RSP_SILDET: | 1011 | case PSEV_RSP_SILDET: |
1012 | pr_debug("%s: pump stev RSP_SILDET\n", ch->is->name); | 1012 | pr_debug("%s: pump stev RSP_SILDET\n", ch->is->name); |
1013 | if (ch->state == STFAX_SILDET) { | 1013 | if (ch->state == STFAX_SILDET) { |
1014 | ch->mod = ch->newmod; | 1014 | ch->mod = ch->newmod; |
1015 | p1 = ch->newmod; | 1015 | p1 = ch->newmod; |
1016 | ch->newmod = 0; | 1016 | ch->newmod = 0; |
1017 | ch->cmd = ch->newcmd; | 1017 | ch->cmd = ch->newcmd; |
1018 | ch->newcmd = 0; | 1018 | ch->newcmd = 0; |
1019 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 1019 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
1020 | ch->cmd, 1, &p1); | 1020 | ch->cmd, 1, &p1); |
1021 | ch->state = STFAX_LINE; | 1021 | ch->state = STFAX_LINE; |
1022 | ch->try_mod = 3; | 1022 | ch->try_mod = 3; |
1023 | } | 1023 | } |
1024 | break; | 1024 | break; |
1025 | case PSEV_RSP_SILOFF: | 1025 | case PSEV_RSP_SILOFF: |
1026 | pr_debug("%s: pump stev RSP_SILOFF\n", ch->is->name); | 1026 | pr_debug("%s: pump stev RSP_SILOFF\n", ch->is->name); |
1027 | break; | 1027 | break; |
1028 | case PSEV_RSP_FCERR: | 1028 | case PSEV_RSP_FCERR: |
1029 | if (ch->state == STFAX_LINE) { | 1029 | if (ch->state == STFAX_LINE) { |
1030 | pr_debug("%s: pump stev RSP_FCERR try %d\n", | 1030 | pr_debug("%s: pump stev RSP_FCERR try %d\n", |
1031 | ch->is->name, ch->try_mod); | 1031 | ch->is->name, ch->try_mod); |
1032 | if (ch->try_mod--) { | 1032 | if (ch->try_mod--) { |
1033 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, | 1033 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, |
1034 | ch->cmd, 1, &ch->mod); | 1034 | ch->cmd, 1, &ch->mod); |
1035 | break; | 1035 | break; |
1036 | } | 1036 | } |
1037 | } | 1037 | } |
1038 | pr_debug("%s: pump stev RSP_FCERR\n", ch->is->name); | 1038 | pr_debug("%s: pump stev RSP_FCERR\n", ch->is->name); |
1039 | ch->state = STFAX_ESCAPE; | 1039 | ch->state = STFAX_ESCAPE; |
1040 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, | 1040 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, |
1041 | 0, NULL); | 1041 | 0, NULL); |
1042 | deliver_status(ch, HW_MOD_FCERROR); | 1042 | deliver_status(ch, HW_MOD_FCERROR); |
1043 | break; | 1043 | break; |
1044 | default: | 1044 | default: |
1045 | break; | 1045 | break; |
1046 | } | 1046 | } |
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | void | 1049 | void |
1050 | mISDNisar_irq(struct isar_hw *isar) | 1050 | mISDNisar_irq(struct isar_hw *isar) |
1051 | { | 1051 | { |
1052 | struct isar_ch *ch; | 1052 | struct isar_ch *ch; |
1053 | 1053 | ||
1054 | get_irq_infos(isar); | 1054 | get_irq_infos(isar); |
1055 | switch (isar->iis & ISAR_IIS_MSCMSD) { | 1055 | switch (isar->iis & ISAR_IIS_MSCMSD) { |
1056 | case ISAR_IIS_RDATA: | 1056 | case ISAR_IIS_RDATA: |
1057 | ch = sel_bch_isar(isar, isar->iis >> 6); | 1057 | ch = sel_bch_isar(isar, isar->iis >> 6); |
1058 | if (ch) | 1058 | if (ch) |
1059 | isar_rcv_frame(ch); | 1059 | isar_rcv_frame(ch); |
1060 | else { | 1060 | else { |
1061 | pr_debug("%s: ISAR spurious IIS_RDATA %x/%x/%x\n", | 1061 | pr_debug("%s: ISAR spurious IIS_RDATA %x/%x/%x\n", |
1062 | isar->name, isar->iis, isar->cmsb, | 1062 | isar->name, isar->iis, isar->cmsb, |
1063 | isar->clsb); | 1063 | isar->clsb); |
1064 | isar->write_reg(isar->hw, ISAR_IIA, 0); | 1064 | isar->write_reg(isar->hw, ISAR_IIA, 0); |
1065 | } | 1065 | } |
1066 | break; | 1066 | break; |
1067 | case ISAR_IIS_GSTEV: | 1067 | case ISAR_IIS_GSTEV: |
1068 | isar->write_reg(isar->hw, ISAR_IIA, 0); | 1068 | isar->write_reg(isar->hw, ISAR_IIA, 0); |
1069 | isar->bstat |= isar->cmsb; | 1069 | isar->bstat |= isar->cmsb; |
1070 | check_send(isar, isar->cmsb); | 1070 | check_send(isar, isar->cmsb); |
1071 | break; | 1071 | break; |
1072 | case ISAR_IIS_BSTEV: | 1072 | case ISAR_IIS_BSTEV: |
1073 | #ifdef ERROR_STATISTIC | 1073 | #ifdef ERROR_STATISTIC |
1074 | ch = sel_bch_isar(isar, isar->iis >> 6); | 1074 | ch = sel_bch_isar(isar, isar->iis >> 6); |
1075 | if (ch) { | 1075 | if (ch) { |
1076 | if (isar->cmsb == BSTEV_TBO) | 1076 | if (isar->cmsb == BSTEV_TBO) |
1077 | ch->bch.err_tx++; | 1077 | ch->bch.err_tx++; |
1078 | if (isar->cmsb == BSTEV_RBO) | 1078 | if (isar->cmsb == BSTEV_RBO) |
1079 | ch->bch.err_rdo++; | 1079 | ch->bch.err_rdo++; |
1080 | } | 1080 | } |
1081 | #endif | 1081 | #endif |
1082 | pr_debug("%s: Buffer STEV dpath%d msb(%x)\n", | 1082 | pr_debug("%s: Buffer STEV dpath%d msb(%x)\n", |
1083 | isar->name, isar->iis >> 6, isar->cmsb); | 1083 | isar->name, isar->iis >> 6, isar->cmsb); |
1084 | isar->write_reg(isar->hw, ISAR_IIA, 0); | 1084 | isar->write_reg(isar->hw, ISAR_IIA, 0); |
1085 | break; | 1085 | break; |
1086 | case ISAR_IIS_PSTEV: | 1086 | case ISAR_IIS_PSTEV: |
1087 | ch = sel_bch_isar(isar, isar->iis >> 6); | 1087 | ch = sel_bch_isar(isar, isar->iis >> 6); |
1088 | if (ch) { | 1088 | if (ch) { |
1089 | rcv_mbox(isar, NULL); | 1089 | rcv_mbox(isar, NULL); |
1090 | if (ch->bch.state == ISDN_P_B_MODEM_ASYNC) | 1090 | if (ch->bch.state == ISDN_P_B_MODEM_ASYNC) |
1091 | isar_pump_statev_modem(ch, isar->cmsb); | 1091 | isar_pump_statev_modem(ch, isar->cmsb); |
1092 | else if (ch->bch.state == ISDN_P_B_T30_FAX) | 1092 | else if (ch->bch.state == ISDN_P_B_T30_FAX) |
1093 | isar_pump_statev_fax(ch, isar->cmsb); | 1093 | isar_pump_statev_fax(ch, isar->cmsb); |
1094 | else if (ch->bch.state == ISDN_P_B_RAW) { | 1094 | else if (ch->bch.state == ISDN_P_B_RAW) { |
1095 | int tt; | 1095 | int tt; |
1096 | tt = isar->cmsb | 0x30; | 1096 | tt = isar->cmsb | 0x30; |
1097 | if (tt == 0x3e) | 1097 | if (tt == 0x3e) |
1098 | tt = '*'; | 1098 | tt = '*'; |
1099 | else if (tt == 0x3f) | 1099 | else if (tt == 0x3f) |
1100 | tt = '#'; | 1100 | tt = '#'; |
1101 | else if (tt > '9') | 1101 | else if (tt > '9') |
1102 | tt += 7; | 1102 | tt += 7; |
1103 | tt |= DTMF_TONE_VAL; | 1103 | tt |= DTMF_TONE_VAL; |
1104 | _queue_data(&ch->bch.ch, PH_CONTROL_IND, | 1104 | _queue_data(&ch->bch.ch, PH_CONTROL_IND, |
1105 | MISDN_ID_ANY, sizeof(tt), &tt, | 1105 | MISDN_ID_ANY, sizeof(tt), &tt, |
1106 | GFP_ATOMIC); | 1106 | GFP_ATOMIC); |
1107 | } else | 1107 | } else |
1108 | pr_debug("%s: ISAR IIS_PSTEV pm %d sta %x\n", | 1108 | pr_debug("%s: ISAR IIS_PSTEV pm %d sta %x\n", |
1109 | isar->name, ch->bch.state, | 1109 | isar->name, ch->bch.state, |
1110 | isar->cmsb); | 1110 | isar->cmsb); |
1111 | } else { | 1111 | } else { |
1112 | pr_debug("%s: ISAR spurious IIS_PSTEV %x/%x/%x\n", | 1112 | pr_debug("%s: ISAR spurious IIS_PSTEV %x/%x/%x\n", |
1113 | isar->name, isar->iis, isar->cmsb, | 1113 | isar->name, isar->iis, isar->cmsb, |
1114 | isar->clsb); | 1114 | isar->clsb); |
1115 | isar->write_reg(isar->hw, ISAR_IIA, 0); | 1115 | isar->write_reg(isar->hw, ISAR_IIA, 0); |
1116 | } | 1116 | } |
1117 | break; | 1117 | break; |
1118 | case ISAR_IIS_PSTRSP: | 1118 | case ISAR_IIS_PSTRSP: |
1119 | ch = sel_bch_isar(isar, isar->iis >> 6); | 1119 | ch = sel_bch_isar(isar, isar->iis >> 6); |
1120 | if (ch) { | 1120 | if (ch) { |
1121 | rcv_mbox(isar, NULL); | 1121 | rcv_mbox(isar, NULL); |
1122 | isar_pump_status_rsp(ch); | 1122 | isar_pump_status_rsp(ch); |
1123 | } else { | 1123 | } else { |
1124 | pr_debug("%s: ISAR spurious IIS_PSTRSP %x/%x/%x\n", | 1124 | pr_debug("%s: ISAR spurious IIS_PSTRSP %x/%x/%x\n", |
1125 | isar->name, isar->iis, isar->cmsb, | 1125 | isar->name, isar->iis, isar->cmsb, |
1126 | isar->clsb); | 1126 | isar->clsb); |
1127 | isar->write_reg(isar->hw, ISAR_IIA, 0); | 1127 | isar->write_reg(isar->hw, ISAR_IIA, 0); |
1128 | } | 1128 | } |
1129 | break; | 1129 | break; |
1130 | case ISAR_IIS_DIAG: | 1130 | case ISAR_IIS_DIAG: |
1131 | case ISAR_IIS_BSTRSP: | 1131 | case ISAR_IIS_BSTRSP: |
1132 | case ISAR_IIS_IOM2RSP: | 1132 | case ISAR_IIS_IOM2RSP: |
1133 | rcv_mbox(isar, NULL); | 1133 | rcv_mbox(isar, NULL); |
1134 | break; | 1134 | break; |
1135 | case ISAR_IIS_INVMSG: | 1135 | case ISAR_IIS_INVMSG: |
1136 | rcv_mbox(isar, NULL); | 1136 | rcv_mbox(isar, NULL); |
1137 | pr_debug("%s: invalid msg his:%x\n", isar->name, isar->cmsb); | 1137 | pr_debug("%s: invalid msg his:%x\n", isar->name, isar->cmsb); |
1138 | break; | 1138 | break; |
1139 | default: | 1139 | default: |
1140 | rcv_mbox(isar, NULL); | 1140 | rcv_mbox(isar, NULL); |
1141 | pr_debug("%s: unhandled msg iis(%x) ctrl(%x/%x)\n", | 1141 | pr_debug("%s: unhandled msg iis(%x) ctrl(%x/%x)\n", |
1142 | isar->name, isar->iis, isar->cmsb, isar->clsb); | 1142 | isar->name, isar->iis, isar->cmsb, isar->clsb); |
1143 | break; | 1143 | break; |
1144 | } | 1144 | } |
1145 | } | 1145 | } |
1146 | EXPORT_SYMBOL(mISDNisar_irq); | 1146 | EXPORT_SYMBOL(mISDNisar_irq); |
1147 | 1147 | ||
1148 | static void | 1148 | static void |
1149 | ftimer_handler(unsigned long data) | 1149 | ftimer_handler(unsigned long data) |
1150 | { | 1150 | { |
1151 | struct isar_ch *ch = (struct isar_ch *)data; | 1151 | struct isar_ch *ch = (struct isar_ch *)data; |
1152 | 1152 | ||
1153 | pr_debug("%s: ftimer flags %lx\n", ch->is->name, ch->bch.Flags); | 1153 | pr_debug("%s: ftimer flags %lx\n", ch->is->name, ch->bch.Flags); |
1154 | test_and_clear_bit(FLG_FTI_RUN, &ch->bch.Flags); | 1154 | test_and_clear_bit(FLG_FTI_RUN, &ch->bch.Flags); |
1155 | if (test_and_clear_bit(FLG_LL_CONN, &ch->bch.Flags)) | 1155 | if (test_and_clear_bit(FLG_LL_CONN, &ch->bch.Flags)) |
1156 | deliver_status(ch, HW_MOD_CONNECT); | 1156 | deliver_status(ch, HW_MOD_CONNECT); |
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | static void | 1159 | static void |
1160 | setup_pump(struct isar_ch *ch) { | 1160 | setup_pump(struct isar_ch *ch) { |
1161 | u8 dps = SET_DPS(ch->dpath); | 1161 | u8 dps = SET_DPS(ch->dpath); |
1162 | u8 ctrl, param[6]; | 1162 | u8 ctrl, param[6]; |
1163 | 1163 | ||
1164 | switch (ch->bch.state) { | 1164 | switch (ch->bch.state) { |
1165 | case ISDN_P_NONE: | 1165 | case ISDN_P_NONE: |
1166 | case ISDN_P_B_RAW: | 1166 | case ISDN_P_B_RAW: |
1167 | case ISDN_P_B_HDLC: | 1167 | case ISDN_P_B_HDLC: |
1168 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL); | 1168 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL); |
1169 | break; | 1169 | break; |
1170 | case ISDN_P_B_L2DTMF: | 1170 | case ISDN_P_B_L2DTMF: |
1171 | if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) { | 1171 | if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) { |
1172 | param[0] = 5; /* TOA 5 db */ | 1172 | param[0] = 5; /* TOA 5 db */ |
1173 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, | 1173 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, |
1174 | PMOD_DTMF_TRANS, 1, param); | 1174 | PMOD_DTMF_TRANS, 1, param); |
1175 | } else { | 1175 | } else { |
1176 | param[0] = 40; /* REL -46 dbm */ | 1176 | param[0] = 40; /* REL -46 dbm */ |
1177 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, | 1177 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, |
1178 | PMOD_DTMF, 1, param); | 1178 | PMOD_DTMF, 1, param); |
1179 | } | 1179 | } |
1180 | case ISDN_P_B_MODEM_ASYNC: | 1180 | case ISDN_P_B_MODEM_ASYNC: |
1181 | ctrl = PMOD_DATAMODEM; | 1181 | ctrl = PMOD_DATAMODEM; |
1182 | if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { | 1182 | if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { |
1183 | ctrl |= PCTRL_ORIG; | 1183 | ctrl |= PCTRL_ORIG; |
1184 | param[5] = PV32P6_CTN; | 1184 | param[5] = PV32P6_CTN; |
1185 | } else { | 1185 | } else { |
1186 | param[5] = PV32P6_ATN; | 1186 | param[5] = PV32P6_ATN; |
1187 | } | 1187 | } |
1188 | param[0] = 6; /* 6 db */ | 1188 | param[0] = 6; /* 6 db */ |
1189 | param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | | 1189 | param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | |
1190 | PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; | 1190 | PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; |
1191 | param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; | 1191 | param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; |
1192 | param[3] = PV32P4_UT144; | 1192 | param[3] = PV32P4_UT144; |
1193 | param[4] = PV32P5_UT144; | 1193 | param[4] = PV32P5_UT144; |
1194 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param); | 1194 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param); |
1195 | break; | 1195 | break; |
1196 | case ISDN_P_B_T30_FAX: | 1196 | case ISDN_P_B_T30_FAX: |
1197 | ctrl = PMOD_FAX; | 1197 | ctrl = PMOD_FAX; |
1198 | if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { | 1198 | if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { |
1199 | ctrl |= PCTRL_ORIG; | 1199 | ctrl |= PCTRL_ORIG; |
1200 | param[1] = PFAXP2_CTN; | 1200 | param[1] = PFAXP2_CTN; |
1201 | } else { | 1201 | } else { |
1202 | param[1] = PFAXP2_ATN; | 1202 | param[1] = PFAXP2_ATN; |
1203 | } | 1203 | } |
1204 | param[0] = 6; /* 6 db */ | 1204 | param[0] = 6; /* 6 db */ |
1205 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); | 1205 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); |
1206 | ch->state = STFAX_NULL; | 1206 | ch->state = STFAX_NULL; |
1207 | ch->newcmd = 0; | 1207 | ch->newcmd = 0; |
1208 | ch->newmod = 0; | 1208 | ch->newmod = 0; |
1209 | test_and_set_bit(FLG_FTI_RUN, &ch->bch.Flags); | 1209 | test_and_set_bit(FLG_FTI_RUN, &ch->bch.Flags); |
1210 | break; | 1210 | break; |
1211 | } | 1211 | } |
1212 | udelay(1000); | 1212 | udelay(1000); |
1213 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 1213 | send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
1214 | udelay(1000); | 1214 | udelay(1000); |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | static void | 1217 | static void |
1218 | setup_sart(struct isar_ch *ch) { | 1218 | setup_sart(struct isar_ch *ch) { |
1219 | u8 dps = SET_DPS(ch->dpath); | 1219 | u8 dps = SET_DPS(ch->dpath); |
1220 | u8 ctrl, param[2] = {0, 0}; | 1220 | u8 ctrl, param[2] = {0, 0}; |
1221 | 1221 | ||
1222 | switch (ch->bch.state) { | 1222 | switch (ch->bch.state) { |
1223 | case ISDN_P_NONE: | 1223 | case ISDN_P_NONE: |
1224 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, | 1224 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, |
1225 | 0, NULL); | 1225 | 0, NULL); |
1226 | break; | 1226 | break; |
1227 | case ISDN_P_B_RAW: | 1227 | case ISDN_P_B_RAW: |
1228 | case ISDN_P_B_L2DTMF: | 1228 | case ISDN_P_B_L2DTMF: |
1229 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, | 1229 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, |
1230 | 2, param); | 1230 | 2, param); |
1231 | break; | 1231 | break; |
1232 | case ISDN_P_B_HDLC: | 1232 | case ISDN_P_B_HDLC: |
1233 | case ISDN_P_B_T30_FAX: | 1233 | case ISDN_P_B_T30_FAX: |
1234 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, | 1234 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, |
1235 | 1, param); | 1235 | 1, param); |
1236 | break; | 1236 | break; |
1237 | case ISDN_P_B_MODEM_ASYNC: | 1237 | case ISDN_P_B_MODEM_ASYNC: |
1238 | ctrl = SMODE_V14 | SCTRL_HDMC_BOTH; | 1238 | ctrl = SMODE_V14 | SCTRL_HDMC_BOTH; |
1239 | param[0] = S_P1_CHS_8; | 1239 | param[0] = S_P1_CHS_8; |
1240 | param[1] = S_P2_BFT_DEF; | 1240 | param[1] = S_P2_BFT_DEF; |
1241 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, ctrl, 2, param); | 1241 | send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, ctrl, 2, param); |
1242 | break; | 1242 | break; |
1243 | } | 1243 | } |
1244 | udelay(1000); | 1244 | udelay(1000); |
1245 | send_mbox(ch->is, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); | 1245 | send_mbox(ch->is, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); |
1246 | udelay(1000); | 1246 | udelay(1000); |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | static void | 1249 | static void |
1250 | setup_iom2(struct isar_ch *ch) { | 1250 | setup_iom2(struct isar_ch *ch) { |
1251 | u8 dps = SET_DPS(ch->dpath); | 1251 | u8 dps = SET_DPS(ch->dpath); |
1252 | u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0}; | 1252 | u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0}; |
1253 | 1253 | ||
1254 | if (ch->bch.nr == 2) { | 1254 | if (ch->bch.nr == 2) { |
1255 | msg[1] = 1; | 1255 | msg[1] = 1; |
1256 | msg[3] = 1; | 1256 | msg[3] = 1; |
1257 | } | 1257 | } |
1258 | switch (ch->bch.state) { | 1258 | switch (ch->bch.state) { |
1259 | case ISDN_P_NONE: | 1259 | case ISDN_P_NONE: |
1260 | cmsb = 0; | 1260 | cmsb = 0; |
1261 | /* dummy slot */ | 1261 | /* dummy slot */ |
1262 | msg[1] = ch->dpath + 2; | 1262 | msg[1] = ch->dpath + 2; |
1263 | msg[3] = ch->dpath + 2; | 1263 | msg[3] = ch->dpath + 2; |
1264 | break; | 1264 | break; |
1265 | case ISDN_P_B_RAW: | 1265 | case ISDN_P_B_RAW: |
1266 | case ISDN_P_B_HDLC: | 1266 | case ISDN_P_B_HDLC: |
1267 | break; | 1267 | break; |
1268 | case ISDN_P_B_MODEM_ASYNC: | 1268 | case ISDN_P_B_MODEM_ASYNC: |
1269 | case ISDN_P_B_T30_FAX: | 1269 | case ISDN_P_B_T30_FAX: |
1270 | cmsb |= IOM_CTRL_RCV; | 1270 | cmsb |= IOM_CTRL_RCV; |
1271 | case ISDN_P_B_L2DTMF: | 1271 | case ISDN_P_B_L2DTMF: |
1272 | if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) | 1272 | if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) |
1273 | cmsb |= IOM_CTRL_RCV; | 1273 | cmsb |= IOM_CTRL_RCV; |
1274 | cmsb |= IOM_CTRL_ALAW; | 1274 | cmsb |= IOM_CTRL_ALAW; |
1275 | break; | 1275 | break; |
1276 | } | 1276 | } |
1277 | send_mbox(ch->is, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg); | 1277 | send_mbox(ch->is, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg); |
1278 | udelay(1000); | 1278 | udelay(1000); |
1279 | send_mbox(ch->is, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL); | 1279 | send_mbox(ch->is, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL); |
1280 | udelay(1000); | 1280 | udelay(1000); |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | static int | 1283 | static int |
1284 | modeisar(struct isar_ch *ch, u32 bprotocol) | 1284 | modeisar(struct isar_ch *ch, u32 bprotocol) |
1285 | { | 1285 | { |
1286 | /* Here we are selecting the best datapath for requested protocol */ | 1286 | /* Here we are selecting the best datapath for requested protocol */ |
1287 | if (ch->bch.state == ISDN_P_NONE) { /* New Setup */ | 1287 | if (ch->bch.state == ISDN_P_NONE) { /* New Setup */ |
1288 | switch (bprotocol) { | 1288 | switch (bprotocol) { |
1289 | case ISDN_P_NONE: /* init */ | 1289 | case ISDN_P_NONE: /* init */ |
1290 | if (!ch->dpath) | 1290 | if (!ch->dpath) |
1291 | /* no init for dpath 0 */ | 1291 | /* no init for dpath 0 */ |
1292 | return 0; | 1292 | return 0; |
1293 | test_and_clear_bit(FLG_HDLC, &ch->bch.Flags); | 1293 | test_and_clear_bit(FLG_HDLC, &ch->bch.Flags); |
1294 | test_and_clear_bit(FLG_TRANSPARENT, &ch->bch.Flags); | 1294 | test_and_clear_bit(FLG_TRANSPARENT, &ch->bch.Flags); |
1295 | break; | 1295 | break; |
1296 | case ISDN_P_B_RAW: | 1296 | case ISDN_P_B_RAW: |
1297 | case ISDN_P_B_HDLC: | 1297 | case ISDN_P_B_HDLC: |
1298 | /* best is datapath 2 */ | 1298 | /* best is datapath 2 */ |
1299 | if (!test_and_set_bit(ISAR_DP2_USE, &ch->is->Flags)) | 1299 | if (!test_and_set_bit(ISAR_DP2_USE, &ch->is->Flags)) |
1300 | ch->dpath = 2; | 1300 | ch->dpath = 2; |
1301 | else if (!test_and_set_bit(ISAR_DP1_USE, | 1301 | else if (!test_and_set_bit(ISAR_DP1_USE, |
1302 | &ch->is->Flags)) | 1302 | &ch->is->Flags)) |
1303 | ch->dpath = 1; | 1303 | ch->dpath = 1; |
1304 | else { | 1304 | else { |
1305 | pr_info("modeisar both pathes in use\n"); | 1305 | pr_info("modeisar both paths in use\n"); |
1306 | return -EBUSY; | 1306 | return -EBUSY; |
1307 | } | 1307 | } |
1308 | if (bprotocol == ISDN_P_B_HDLC) | 1308 | if (bprotocol == ISDN_P_B_HDLC) |
1309 | test_and_set_bit(FLG_HDLC, &ch->bch.Flags); | 1309 | test_and_set_bit(FLG_HDLC, &ch->bch.Flags); |
1310 | else | 1310 | else |
1311 | test_and_set_bit(FLG_TRANSPARENT, | 1311 | test_and_set_bit(FLG_TRANSPARENT, |
1312 | &ch->bch.Flags); | 1312 | &ch->bch.Flags); |
1313 | break; | 1313 | break; |
1314 | case ISDN_P_B_MODEM_ASYNC: | 1314 | case ISDN_P_B_MODEM_ASYNC: |
1315 | case ISDN_P_B_T30_FAX: | 1315 | case ISDN_P_B_T30_FAX: |
1316 | case ISDN_P_B_L2DTMF: | 1316 | case ISDN_P_B_L2DTMF: |
1317 | /* only datapath 1 */ | 1317 | /* only datapath 1 */ |
1318 | if (!test_and_set_bit(ISAR_DP1_USE, &ch->is->Flags)) | 1318 | if (!test_and_set_bit(ISAR_DP1_USE, &ch->is->Flags)) |
1319 | ch->dpath = 1; | 1319 | ch->dpath = 1; |
1320 | else { | 1320 | else { |
1321 | pr_info("%s: ISAR modeisar analog functions" | 1321 | pr_info("%s: ISAR modeisar analog functions" |
1322 | "only with DP1\n", ch->is->name); | 1322 | "only with DP1\n", ch->is->name); |
1323 | return -EBUSY; | 1323 | return -EBUSY; |
1324 | } | 1324 | } |
1325 | break; | 1325 | break; |
1326 | default: | 1326 | default: |
1327 | pr_info("%s: protocol not known %x\n", ch->is->name, | 1327 | pr_info("%s: protocol not known %x\n", ch->is->name, |
1328 | bprotocol); | 1328 | bprotocol); |
1329 | return -ENOPROTOOPT; | 1329 | return -ENOPROTOOPT; |
1330 | } | 1330 | } |
1331 | } | 1331 | } |
1332 | pr_debug("%s: ISAR ch%d dp%d protocol %x->%x\n", ch->is->name, | 1332 | pr_debug("%s: ISAR ch%d dp%d protocol %x->%x\n", ch->is->name, |
1333 | ch->bch.nr, ch->dpath, ch->bch.state, bprotocol); | 1333 | ch->bch.nr, ch->dpath, ch->bch.state, bprotocol); |
1334 | ch->bch.state = bprotocol; | 1334 | ch->bch.state = bprotocol; |
1335 | setup_pump(ch); | 1335 | setup_pump(ch); |
1336 | setup_iom2(ch); | 1336 | setup_iom2(ch); |
1337 | setup_sart(ch); | 1337 | setup_sart(ch); |
1338 | if (ch->bch.state == ISDN_P_NONE) { | 1338 | if (ch->bch.state == ISDN_P_NONE) { |
1339 | /* Clear resources */ | 1339 | /* Clear resources */ |
1340 | if (ch->dpath == 1) | 1340 | if (ch->dpath == 1) |
1341 | test_and_clear_bit(ISAR_DP1_USE, &ch->is->Flags); | 1341 | test_and_clear_bit(ISAR_DP1_USE, &ch->is->Flags); |
1342 | else if (ch->dpath == 2) | 1342 | else if (ch->dpath == 2) |
1343 | test_and_clear_bit(ISAR_DP2_USE, &ch->is->Flags); | 1343 | test_and_clear_bit(ISAR_DP2_USE, &ch->is->Flags); |
1344 | ch->dpath = 0; | 1344 | ch->dpath = 0; |
1345 | ch->is->ctrl(ch->is->hw, HW_DEACT_IND, ch->bch.nr); | 1345 | ch->is->ctrl(ch->is->hw, HW_DEACT_IND, ch->bch.nr); |
1346 | } else | 1346 | } else |
1347 | ch->is->ctrl(ch->is->hw, HW_ACTIVATE_IND, ch->bch.nr); | 1347 | ch->is->ctrl(ch->is->hw, HW_ACTIVATE_IND, ch->bch.nr); |
1348 | return 0; | 1348 | return 0; |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | static void | 1351 | static void |
1352 | isar_pump_cmd(struct isar_ch *ch, u32 cmd, u8 para) | 1352 | isar_pump_cmd(struct isar_ch *ch, u32 cmd, u8 para) |
1353 | { | 1353 | { |
1354 | u8 dps = SET_DPS(ch->dpath); | 1354 | u8 dps = SET_DPS(ch->dpath); |
1355 | u8 ctrl = 0, nom = 0, p1 = 0; | 1355 | u8 ctrl = 0, nom = 0, p1 = 0; |
1356 | 1356 | ||
1357 | pr_debug("%s: isar_pump_cmd %x/%x state(%x)\n", | 1357 | pr_debug("%s: isar_pump_cmd %x/%x state(%x)\n", |
1358 | ch->is->name, cmd, para, ch->bch.state); | 1358 | ch->is->name, cmd, para, ch->bch.state); |
1359 | switch (cmd) { | 1359 | switch (cmd) { |
1360 | case HW_MOD_FTM: | 1360 | case HW_MOD_FTM: |
1361 | if (ch->state == STFAX_READY) { | 1361 | if (ch->state == STFAX_READY) { |
1362 | p1 = para; | 1362 | p1 = para; |
1363 | ctrl = PCTRL_CMD_FTM; | 1363 | ctrl = PCTRL_CMD_FTM; |
1364 | nom = 1; | 1364 | nom = 1; |
1365 | ch->state = STFAX_LINE; | 1365 | ch->state = STFAX_LINE; |
1366 | ch->cmd = ctrl; | 1366 | ch->cmd = ctrl; |
1367 | ch->mod = para; | 1367 | ch->mod = para; |
1368 | ch->newmod = 0; | 1368 | ch->newmod = 0; |
1369 | ch->newcmd = 0; | 1369 | ch->newcmd = 0; |
1370 | ch->try_mod = 3; | 1370 | ch->try_mod = 3; |
1371 | } else if ((ch->state == STFAX_ACTIV) && | 1371 | } else if ((ch->state == STFAX_ACTIV) && |
1372 | (ch->cmd == PCTRL_CMD_FTM) && (ch->mod == para)) | 1372 | (ch->cmd == PCTRL_CMD_FTM) && (ch->mod == para)) |
1373 | deliver_status(ch, HW_MOD_CONNECT); | 1373 | deliver_status(ch, HW_MOD_CONNECT); |
1374 | else { | 1374 | else { |
1375 | ch->newmod = para; | 1375 | ch->newmod = para; |
1376 | ch->newcmd = PCTRL_CMD_FTM; | 1376 | ch->newcmd = PCTRL_CMD_FTM; |
1377 | nom = 0; | 1377 | nom = 0; |
1378 | ctrl = PCTRL_CMD_ESC; | 1378 | ctrl = PCTRL_CMD_ESC; |
1379 | ch->state = STFAX_ESCAPE; | 1379 | ch->state = STFAX_ESCAPE; |
1380 | } | 1380 | } |
1381 | break; | 1381 | break; |
1382 | case HW_MOD_FTH: | 1382 | case HW_MOD_FTH: |
1383 | if (ch->state == STFAX_READY) { | 1383 | if (ch->state == STFAX_READY) { |
1384 | p1 = para; | 1384 | p1 = para; |
1385 | ctrl = PCTRL_CMD_FTH; | 1385 | ctrl = PCTRL_CMD_FTH; |
1386 | nom = 1; | 1386 | nom = 1; |
1387 | ch->state = STFAX_LINE; | 1387 | ch->state = STFAX_LINE; |
1388 | ch->cmd = ctrl; | 1388 | ch->cmd = ctrl; |
1389 | ch->mod = para; | 1389 | ch->mod = para; |
1390 | ch->newmod = 0; | 1390 | ch->newmod = 0; |
1391 | ch->newcmd = 0; | 1391 | ch->newcmd = 0; |
1392 | ch->try_mod = 3; | 1392 | ch->try_mod = 3; |
1393 | } else if ((ch->state == STFAX_ACTIV) && | 1393 | } else if ((ch->state == STFAX_ACTIV) && |
1394 | (ch->cmd == PCTRL_CMD_FTH) && (ch->mod == para)) | 1394 | (ch->cmd == PCTRL_CMD_FTH) && (ch->mod == para)) |
1395 | deliver_status(ch, HW_MOD_CONNECT); | 1395 | deliver_status(ch, HW_MOD_CONNECT); |
1396 | else { | 1396 | else { |
1397 | ch->newmod = para; | 1397 | ch->newmod = para; |
1398 | ch->newcmd = PCTRL_CMD_FTH; | 1398 | ch->newcmd = PCTRL_CMD_FTH; |
1399 | nom = 0; | 1399 | nom = 0; |
1400 | ctrl = PCTRL_CMD_ESC; | 1400 | ctrl = PCTRL_CMD_ESC; |
1401 | ch->state = STFAX_ESCAPE; | 1401 | ch->state = STFAX_ESCAPE; |
1402 | } | 1402 | } |
1403 | break; | 1403 | break; |
1404 | case HW_MOD_FRM: | 1404 | case HW_MOD_FRM: |
1405 | if (ch->state == STFAX_READY) { | 1405 | if (ch->state == STFAX_READY) { |
1406 | p1 = para; | 1406 | p1 = para; |
1407 | ctrl = PCTRL_CMD_FRM; | 1407 | ctrl = PCTRL_CMD_FRM; |
1408 | nom = 1; | 1408 | nom = 1; |
1409 | ch->state = STFAX_LINE; | 1409 | ch->state = STFAX_LINE; |
1410 | ch->cmd = ctrl; | 1410 | ch->cmd = ctrl; |
1411 | ch->mod = para; | 1411 | ch->mod = para; |
1412 | ch->newmod = 0; | 1412 | ch->newmod = 0; |
1413 | ch->newcmd = 0; | 1413 | ch->newcmd = 0; |
1414 | ch->try_mod = 3; | 1414 | ch->try_mod = 3; |
1415 | } else if ((ch->state == STFAX_ACTIV) && | 1415 | } else if ((ch->state == STFAX_ACTIV) && |
1416 | (ch->cmd == PCTRL_CMD_FRM) && (ch->mod == para)) | 1416 | (ch->cmd == PCTRL_CMD_FRM) && (ch->mod == para)) |
1417 | deliver_status(ch, HW_MOD_CONNECT); | 1417 | deliver_status(ch, HW_MOD_CONNECT); |
1418 | else { | 1418 | else { |
1419 | ch->newmod = para; | 1419 | ch->newmod = para; |
1420 | ch->newcmd = PCTRL_CMD_FRM; | 1420 | ch->newcmd = PCTRL_CMD_FRM; |
1421 | nom = 0; | 1421 | nom = 0; |
1422 | ctrl = PCTRL_CMD_ESC; | 1422 | ctrl = PCTRL_CMD_ESC; |
1423 | ch->state = STFAX_ESCAPE; | 1423 | ch->state = STFAX_ESCAPE; |
1424 | } | 1424 | } |
1425 | break; | 1425 | break; |
1426 | case HW_MOD_FRH: | 1426 | case HW_MOD_FRH: |
1427 | if (ch->state == STFAX_READY) { | 1427 | if (ch->state == STFAX_READY) { |
1428 | p1 = para; | 1428 | p1 = para; |
1429 | ctrl = PCTRL_CMD_FRH; | 1429 | ctrl = PCTRL_CMD_FRH; |
1430 | nom = 1; | 1430 | nom = 1; |
1431 | ch->state = STFAX_LINE; | 1431 | ch->state = STFAX_LINE; |
1432 | ch->cmd = ctrl; | 1432 | ch->cmd = ctrl; |
1433 | ch->mod = para; | 1433 | ch->mod = para; |
1434 | ch->newmod = 0; | 1434 | ch->newmod = 0; |
1435 | ch->newcmd = 0; | 1435 | ch->newcmd = 0; |
1436 | ch->try_mod = 3; | 1436 | ch->try_mod = 3; |
1437 | } else if ((ch->state == STFAX_ACTIV) && | 1437 | } else if ((ch->state == STFAX_ACTIV) && |
1438 | (ch->cmd == PCTRL_CMD_FRH) && (ch->mod == para)) | 1438 | (ch->cmd == PCTRL_CMD_FRH) && (ch->mod == para)) |
1439 | deliver_status(ch, HW_MOD_CONNECT); | 1439 | deliver_status(ch, HW_MOD_CONNECT); |
1440 | else { | 1440 | else { |
1441 | ch->newmod = para; | 1441 | ch->newmod = para; |
1442 | ch->newcmd = PCTRL_CMD_FRH; | 1442 | ch->newcmd = PCTRL_CMD_FRH; |
1443 | nom = 0; | 1443 | nom = 0; |
1444 | ctrl = PCTRL_CMD_ESC; | 1444 | ctrl = PCTRL_CMD_ESC; |
1445 | ch->state = STFAX_ESCAPE; | 1445 | ch->state = STFAX_ESCAPE; |
1446 | } | 1446 | } |
1447 | break; | 1447 | break; |
1448 | case PCTRL_CMD_TDTMF: | 1448 | case PCTRL_CMD_TDTMF: |
1449 | p1 = para; | 1449 | p1 = para; |
1450 | nom = 1; | 1450 | nom = 1; |
1451 | ctrl = PCTRL_CMD_TDTMF; | 1451 | ctrl = PCTRL_CMD_TDTMF; |
1452 | break; | 1452 | break; |
1453 | } | 1453 | } |
1454 | if (ctrl) | 1454 | if (ctrl) |
1455 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); | 1455 | send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); |
1456 | } | 1456 | } |
1457 | 1457 | ||
1458 | static void | 1458 | static void |
1459 | isar_setup(struct isar_hw *isar) | 1459 | isar_setup(struct isar_hw *isar) |
1460 | { | 1460 | { |
1461 | u8 msg; | 1461 | u8 msg; |
1462 | int i; | 1462 | int i; |
1463 | 1463 | ||
1464 | /* Dpath 1, 2 */ | 1464 | /* Dpath 1, 2 */ |
1465 | msg = 61; | 1465 | msg = 61; |
1466 | for (i = 0; i < 2; i++) { | 1466 | for (i = 0; i < 2; i++) { |
1467 | /* Buffer Config */ | 1467 | /* Buffer Config */ |
1468 | send_mbox(isar, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) | | 1468 | send_mbox(isar, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) | |
1469 | ISAR_HIS_P12CFG, 4, 1, &msg); | 1469 | ISAR_HIS_P12CFG, 4, 1, &msg); |
1470 | isar->ch[i].mml = msg; | 1470 | isar->ch[i].mml = msg; |
1471 | isar->ch[i].bch.state = 0; | 1471 | isar->ch[i].bch.state = 0; |
1472 | isar->ch[i].dpath = i + 1; | 1472 | isar->ch[i].dpath = i + 1; |
1473 | modeisar(&isar->ch[i], ISDN_P_NONE); | 1473 | modeisar(&isar->ch[i], ISDN_P_NONE); |
1474 | } | 1474 | } |
1475 | } | 1475 | } |
1476 | 1476 | ||
1477 | static int | 1477 | static int |
1478 | isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb) | 1478 | isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb) |
1479 | { | 1479 | { |
1480 | struct bchannel *bch = container_of(ch, struct bchannel, ch); | 1480 | struct bchannel *bch = container_of(ch, struct bchannel, ch); |
1481 | struct isar_ch *ich = container_of(bch, struct isar_ch, bch); | 1481 | struct isar_ch *ich = container_of(bch, struct isar_ch, bch); |
1482 | int ret = -EINVAL; | 1482 | int ret = -EINVAL; |
1483 | struct mISDNhead *hh = mISDN_HEAD_P(skb); | 1483 | struct mISDNhead *hh = mISDN_HEAD_P(skb); |
1484 | u32 id, *val; | 1484 | u32 id, *val; |
1485 | u_long flags; | 1485 | u_long flags; |
1486 | 1486 | ||
1487 | switch (hh->prim) { | 1487 | switch (hh->prim) { |
1488 | case PH_DATA_REQ: | 1488 | case PH_DATA_REQ: |
1489 | spin_lock_irqsave(ich->is->hwlock, flags); | 1489 | spin_lock_irqsave(ich->is->hwlock, flags); |
1490 | ret = bchannel_senddata(bch, skb); | 1490 | ret = bchannel_senddata(bch, skb); |
1491 | if (ret > 0) { /* direct TX */ | 1491 | if (ret > 0) { /* direct TX */ |
1492 | ret = 0; | 1492 | ret = 0; |
1493 | isar_fill_fifo(ich); | 1493 | isar_fill_fifo(ich); |
1494 | } | 1494 | } |
1495 | spin_unlock_irqrestore(ich->is->hwlock, flags); | 1495 | spin_unlock_irqrestore(ich->is->hwlock, flags); |
1496 | return ret; | 1496 | return ret; |
1497 | case PH_ACTIVATE_REQ: | 1497 | case PH_ACTIVATE_REQ: |
1498 | spin_lock_irqsave(ich->is->hwlock, flags); | 1498 | spin_lock_irqsave(ich->is->hwlock, flags); |
1499 | if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) | 1499 | if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) |
1500 | ret = modeisar(ich, ch->protocol); | 1500 | ret = modeisar(ich, ch->protocol); |
1501 | else | 1501 | else |
1502 | ret = 0; | 1502 | ret = 0; |
1503 | spin_unlock_irqrestore(ich->is->hwlock, flags); | 1503 | spin_unlock_irqrestore(ich->is->hwlock, flags); |
1504 | if (!ret) | 1504 | if (!ret) |
1505 | _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, | 1505 | _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, |
1506 | NULL, GFP_KERNEL); | 1506 | NULL, GFP_KERNEL); |
1507 | break; | 1507 | break; |
1508 | case PH_DEACTIVATE_REQ: | 1508 | case PH_DEACTIVATE_REQ: |
1509 | spin_lock_irqsave(ich->is->hwlock, flags); | 1509 | spin_lock_irqsave(ich->is->hwlock, flags); |
1510 | mISDN_clear_bchannel(bch); | 1510 | mISDN_clear_bchannel(bch); |
1511 | modeisar(ich, ISDN_P_NONE); | 1511 | modeisar(ich, ISDN_P_NONE); |
1512 | spin_unlock_irqrestore(ich->is->hwlock, flags); | 1512 | spin_unlock_irqrestore(ich->is->hwlock, flags); |
1513 | _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, | 1513 | _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, |
1514 | NULL, GFP_KERNEL); | 1514 | NULL, GFP_KERNEL); |
1515 | ret = 0; | 1515 | ret = 0; |
1516 | break; | 1516 | break; |
1517 | case PH_CONTROL_REQ: | 1517 | case PH_CONTROL_REQ: |
1518 | val = (u32 *)skb->data; | 1518 | val = (u32 *)skb->data; |
1519 | pr_debug("%s: PH_CONTROL | REQUEST %x/%x\n", ich->is->name, | 1519 | pr_debug("%s: PH_CONTROL | REQUEST %x/%x\n", ich->is->name, |
1520 | hh->id, *val); | 1520 | hh->id, *val); |
1521 | if ((hh->id == 0) && ((*val & ~DTMF_TONE_MASK) == | 1521 | if ((hh->id == 0) && ((*val & ~DTMF_TONE_MASK) == |
1522 | DTMF_TONE_VAL)) { | 1522 | DTMF_TONE_VAL)) { |
1523 | if (bch->state == ISDN_P_B_L2DTMF) { | 1523 | if (bch->state == ISDN_P_B_L2DTMF) { |
1524 | char tt = *val & DTMF_TONE_MASK; | 1524 | char tt = *val & DTMF_TONE_MASK; |
1525 | 1525 | ||
1526 | if (tt == '*') | 1526 | if (tt == '*') |
1527 | tt = 0x1e; | 1527 | tt = 0x1e; |
1528 | else if (tt == '#') | 1528 | else if (tt == '#') |
1529 | tt = 0x1f; | 1529 | tt = 0x1f; |
1530 | else if (tt > '9') | 1530 | else if (tt > '9') |
1531 | tt -= 7; | 1531 | tt -= 7; |
1532 | tt &= 0x1f; | 1532 | tt &= 0x1f; |
1533 | spin_lock_irqsave(ich->is->hwlock, flags); | 1533 | spin_lock_irqsave(ich->is->hwlock, flags); |
1534 | isar_pump_cmd(ich, PCTRL_CMD_TDTMF, tt); | 1534 | isar_pump_cmd(ich, PCTRL_CMD_TDTMF, tt); |
1535 | spin_unlock_irqrestore(ich->is->hwlock, flags); | 1535 | spin_unlock_irqrestore(ich->is->hwlock, flags); |
1536 | } else { | 1536 | } else { |
1537 | pr_info("%s: DTMF send wrong protocol %x\n", | 1537 | pr_info("%s: DTMF send wrong protocol %x\n", |
1538 | __func__, bch->state); | 1538 | __func__, bch->state); |
1539 | return -EINVAL; | 1539 | return -EINVAL; |
1540 | } | 1540 | } |
1541 | } else if ((hh->id == HW_MOD_FRM) || (hh->id == HW_MOD_FRH) || | 1541 | } else if ((hh->id == HW_MOD_FRM) || (hh->id == HW_MOD_FRH) || |
1542 | (hh->id == HW_MOD_FTM) || (hh->id == HW_MOD_FTH)) { | 1542 | (hh->id == HW_MOD_FTM) || (hh->id == HW_MOD_FTH)) { |
1543 | for (id = 0; id < FAXMODCNT; id++) | 1543 | for (id = 0; id < FAXMODCNT; id++) |
1544 | if (faxmodulation[id] == *val) | 1544 | if (faxmodulation[id] == *val) |
1545 | break; | 1545 | break; |
1546 | if ((FAXMODCNT > id) && | 1546 | if ((FAXMODCNT > id) && |
1547 | test_bit(FLG_INITIALIZED, &bch->Flags)) { | 1547 | test_bit(FLG_INITIALIZED, &bch->Flags)) { |
1548 | pr_debug("%s: isar: new mod\n", ich->is->name); | 1548 | pr_debug("%s: isar: new mod\n", ich->is->name); |
1549 | isar_pump_cmd(ich, hh->id, *val); | 1549 | isar_pump_cmd(ich, hh->id, *val); |
1550 | ret = 0; | 1550 | ret = 0; |
1551 | } else { | 1551 | } else { |
1552 | pr_info("%s: wrong modulation\n", | 1552 | pr_info("%s: wrong modulation\n", |
1553 | ich->is->name); | 1553 | ich->is->name); |
1554 | ret = -EINVAL; | 1554 | ret = -EINVAL; |
1555 | } | 1555 | } |
1556 | } else if (hh->id == HW_MOD_LASTDATA) | 1556 | } else if (hh->id == HW_MOD_LASTDATA) |
1557 | test_and_set_bit(FLG_DLEETX, &bch->Flags); | 1557 | test_and_set_bit(FLG_DLEETX, &bch->Flags); |
1558 | else { | 1558 | else { |
1559 | pr_info("%s: unknown PH_CONTROL_REQ %x\n", | 1559 | pr_info("%s: unknown PH_CONTROL_REQ %x\n", |
1560 | ich->is->name, hh->id); | 1560 | ich->is->name, hh->id); |
1561 | ret = -EINVAL; | 1561 | ret = -EINVAL; |
1562 | } | 1562 | } |
1563 | default: | 1563 | default: |
1564 | pr_info("%s: %s unknown prim(%x,%x)\n", | 1564 | pr_info("%s: %s unknown prim(%x,%x)\n", |
1565 | ich->is->name, __func__, hh->prim, hh->id); | 1565 | ich->is->name, __func__, hh->prim, hh->id); |
1566 | ret = -EINVAL; | 1566 | ret = -EINVAL; |
1567 | } | 1567 | } |
1568 | if (!ret) | 1568 | if (!ret) |
1569 | dev_kfree_skb(skb); | 1569 | dev_kfree_skb(skb); |
1570 | return ret; | 1570 | return ret; |
1571 | } | 1571 | } |
1572 | 1572 | ||
1573 | static int | 1573 | static int |
1574 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | 1574 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) |
1575 | { | 1575 | { |
1576 | return mISDN_ctrl_bchannel(bch, cq); | 1576 | return mISDN_ctrl_bchannel(bch, cq); |
1577 | } | 1577 | } |
1578 | 1578 | ||
1579 | static int | 1579 | static int |
1580 | isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) | 1580 | isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) |
1581 | { | 1581 | { |
1582 | struct bchannel *bch = container_of(ch, struct bchannel, ch); | 1582 | struct bchannel *bch = container_of(ch, struct bchannel, ch); |
1583 | struct isar_ch *ich = container_of(bch, struct isar_ch, bch); | 1583 | struct isar_ch *ich = container_of(bch, struct isar_ch, bch); |
1584 | int ret = -EINVAL; | 1584 | int ret = -EINVAL; |
1585 | u_long flags; | 1585 | u_long flags; |
1586 | 1586 | ||
1587 | pr_debug("%s: %s cmd:%x %p\n", ich->is->name, __func__, cmd, arg); | 1587 | pr_debug("%s: %s cmd:%x %p\n", ich->is->name, __func__, cmd, arg); |
1588 | switch (cmd) { | 1588 | switch (cmd) { |
1589 | case CLOSE_CHANNEL: | 1589 | case CLOSE_CHANNEL: |
1590 | test_and_clear_bit(FLG_OPEN, &bch->Flags); | 1590 | test_and_clear_bit(FLG_OPEN, &bch->Flags); |
1591 | cancel_work_sync(&bch->workq); | 1591 | cancel_work_sync(&bch->workq); |
1592 | spin_lock_irqsave(ich->is->hwlock, flags); | 1592 | spin_lock_irqsave(ich->is->hwlock, flags); |
1593 | mISDN_clear_bchannel(bch); | 1593 | mISDN_clear_bchannel(bch); |
1594 | modeisar(ich, ISDN_P_NONE); | 1594 | modeisar(ich, ISDN_P_NONE); |
1595 | spin_unlock_irqrestore(ich->is->hwlock, flags); | 1595 | spin_unlock_irqrestore(ich->is->hwlock, flags); |
1596 | ch->protocol = ISDN_P_NONE; | 1596 | ch->protocol = ISDN_P_NONE; |
1597 | ch->peer = NULL; | 1597 | ch->peer = NULL; |
1598 | module_put(ich->is->owner); | 1598 | module_put(ich->is->owner); |
1599 | ret = 0; | 1599 | ret = 0; |
1600 | break; | 1600 | break; |
1601 | case CONTROL_CHANNEL: | 1601 | case CONTROL_CHANNEL: |
1602 | ret = channel_bctrl(bch, arg); | 1602 | ret = channel_bctrl(bch, arg); |
1603 | break; | 1603 | break; |
1604 | default: | 1604 | default: |
1605 | pr_info("%s: %s unknown prim(%x)\n", | 1605 | pr_info("%s: %s unknown prim(%x)\n", |
1606 | ich->is->name, __func__, cmd); | 1606 | ich->is->name, __func__, cmd); |
1607 | } | 1607 | } |
1608 | return ret; | 1608 | return ret; |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | static void | 1611 | static void |
1612 | free_isar(struct isar_hw *isar) | 1612 | free_isar(struct isar_hw *isar) |
1613 | { | 1613 | { |
1614 | modeisar(&isar->ch[0], ISDN_P_NONE); | 1614 | modeisar(&isar->ch[0], ISDN_P_NONE); |
1615 | modeisar(&isar->ch[1], ISDN_P_NONE); | 1615 | modeisar(&isar->ch[1], ISDN_P_NONE); |
1616 | del_timer(&isar->ch[0].ftimer); | 1616 | del_timer(&isar->ch[0].ftimer); |
1617 | del_timer(&isar->ch[1].ftimer); | 1617 | del_timer(&isar->ch[1].ftimer); |
1618 | test_and_clear_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); | 1618 | test_and_clear_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); |
1619 | test_and_clear_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); | 1619 | test_and_clear_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); |
1620 | } | 1620 | } |
1621 | 1621 | ||
1622 | static int | 1622 | static int |
1623 | init_isar(struct isar_hw *isar) | 1623 | init_isar(struct isar_hw *isar) |
1624 | { | 1624 | { |
1625 | int cnt = 3; | 1625 | int cnt = 3; |
1626 | 1626 | ||
1627 | while (cnt--) { | 1627 | while (cnt--) { |
1628 | isar->version = ISARVersion(isar); | 1628 | isar->version = ISARVersion(isar); |
1629 | if (isar->ch[0].bch.debug & DEBUG_HW) | 1629 | if (isar->ch[0].bch.debug & DEBUG_HW) |
1630 | pr_notice("%s: Testing version %d (%d time)\n", | 1630 | pr_notice("%s: Testing version %d (%d time)\n", |
1631 | isar->name, isar->version, 3 - cnt); | 1631 | isar->name, isar->version, 3 - cnt); |
1632 | if (isar->version == 1) | 1632 | if (isar->version == 1) |
1633 | break; | 1633 | break; |
1634 | isar->ctrl(isar->hw, HW_RESET_REQ, 0); | 1634 | isar->ctrl(isar->hw, HW_RESET_REQ, 0); |
1635 | } | 1635 | } |
1636 | if (isar->version != 1) | 1636 | if (isar->version != 1) |
1637 | return -EINVAL; | 1637 | return -EINVAL; |
1638 | isar->ch[0].ftimer.function = &ftimer_handler; | 1638 | isar->ch[0].ftimer.function = &ftimer_handler; |
1639 | isar->ch[0].ftimer.data = (long)&isar->ch[0]; | 1639 | isar->ch[0].ftimer.data = (long)&isar->ch[0]; |
1640 | init_timer(&isar->ch[0].ftimer); | 1640 | init_timer(&isar->ch[0].ftimer); |
1641 | test_and_set_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); | 1641 | test_and_set_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); |
1642 | isar->ch[1].ftimer.function = &ftimer_handler; | 1642 | isar->ch[1].ftimer.function = &ftimer_handler; |
1643 | isar->ch[1].ftimer.data = (long)&isar->ch[1]; | 1643 | isar->ch[1].ftimer.data = (long)&isar->ch[1]; |
1644 | init_timer(&isar->ch[1].ftimer); | 1644 | init_timer(&isar->ch[1].ftimer); |
1645 | test_and_set_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); | 1645 | test_and_set_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); |
1646 | return 0; | 1646 | return 0; |
1647 | } | 1647 | } |
1648 | 1648 | ||
1649 | static int | 1649 | static int |
1650 | isar_open(struct isar_hw *isar, struct channel_req *rq) | 1650 | isar_open(struct isar_hw *isar, struct channel_req *rq) |
1651 | { | 1651 | { |
1652 | struct bchannel *bch; | 1652 | struct bchannel *bch; |
1653 | 1653 | ||
1654 | if (rq->adr.channel == 0 || rq->adr.channel > 2) | 1654 | if (rq->adr.channel == 0 || rq->adr.channel > 2) |
1655 | return -EINVAL; | 1655 | return -EINVAL; |
1656 | if (rq->protocol == ISDN_P_NONE) | 1656 | if (rq->protocol == ISDN_P_NONE) |
1657 | return -EINVAL; | 1657 | return -EINVAL; |
1658 | bch = &isar->ch[rq->adr.channel - 1].bch; | 1658 | bch = &isar->ch[rq->adr.channel - 1].bch; |
1659 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 1659 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
1660 | return -EBUSY; /* b-channel can be only open once */ | 1660 | return -EBUSY; /* b-channel can be only open once */ |
1661 | bch->ch.protocol = rq->protocol; | 1661 | bch->ch.protocol = rq->protocol; |
1662 | rq->ch = &bch->ch; | 1662 | rq->ch = &bch->ch; |
1663 | return 0; | 1663 | return 0; |
1664 | } | 1664 | } |
1665 | 1665 | ||
1666 | u32 | 1666 | u32 |
1667 | mISDNisar_init(struct isar_hw *isar, void *hw) | 1667 | mISDNisar_init(struct isar_hw *isar, void *hw) |
1668 | { | 1668 | { |
1669 | u32 ret, i; | 1669 | u32 ret, i; |
1670 | 1670 | ||
1671 | isar->hw = hw; | 1671 | isar->hw = hw; |
1672 | for (i = 0; i < 2; i++) { | 1672 | for (i = 0; i < 2; i++) { |
1673 | isar->ch[i].bch.nr = i + 1; | 1673 | isar->ch[i].bch.nr = i + 1; |
1674 | mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32); | 1674 | mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32); |
1675 | isar->ch[i].bch.ch.nr = i + 1; | 1675 | isar->ch[i].bch.ch.nr = i + 1; |
1676 | isar->ch[i].bch.ch.send = &isar_l2l1; | 1676 | isar->ch[i].bch.ch.send = &isar_l2l1; |
1677 | isar->ch[i].bch.ch.ctrl = isar_bctrl; | 1677 | isar->ch[i].bch.ch.ctrl = isar_bctrl; |
1678 | isar->ch[i].bch.hw = hw; | 1678 | isar->ch[i].bch.hw = hw; |
1679 | isar->ch[i].is = isar; | 1679 | isar->ch[i].is = isar; |
1680 | } | 1680 | } |
1681 | 1681 | ||
1682 | isar->init = &init_isar; | 1682 | isar->init = &init_isar; |
1683 | isar->release = &free_isar; | 1683 | isar->release = &free_isar; |
1684 | isar->firmware = &load_firmware; | 1684 | isar->firmware = &load_firmware; |
1685 | isar->open = &isar_open; | 1685 | isar->open = &isar_open; |
1686 | 1686 | ||
1687 | ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | | 1687 | ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | |
1688 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)) | | 1688 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)) | |
1689 | (1 << (ISDN_P_B_L2DTMF & ISDN_P_B_MASK)) | | 1689 | (1 << (ISDN_P_B_L2DTMF & ISDN_P_B_MASK)) | |
1690 | (1 << (ISDN_P_B_MODEM_ASYNC & ISDN_P_B_MASK)) | | 1690 | (1 << (ISDN_P_B_MODEM_ASYNC & ISDN_P_B_MASK)) | |
1691 | (1 << (ISDN_P_B_T30_FAX & ISDN_P_B_MASK)); | 1691 | (1 << (ISDN_P_B_T30_FAX & ISDN_P_B_MASK)); |
1692 | 1692 | ||
1693 | return ret; | 1693 | return ret; |
1694 | } | 1694 | } |
1695 | EXPORT_SYMBOL(mISDNisar_init); | 1695 | EXPORT_SYMBOL(mISDNisar_init); |
1696 | 1696 | ||
1697 | static int __init isar_mod_init(void) | 1697 | static int __init isar_mod_init(void) |
1698 | { | 1698 | { |
1699 | pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); | 1699 | pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); |
1700 | return 0; | 1700 | return 0; |
1701 | } | 1701 | } |
1702 | 1702 | ||
1703 | static void __exit isar_mod_cleanup(void) | 1703 | static void __exit isar_mod_cleanup(void) |
1704 | { | 1704 | { |
1705 | pr_notice("mISDN: ISAR module unloaded\n"); | 1705 | pr_notice("mISDN: ISAR module unloaded\n"); |
1706 | } | 1706 | } |
1707 | module_init(isar_mod_init); | 1707 | module_init(isar_mod_init); |
1708 | module_exit(isar_mod_cleanup); | 1708 | module_exit(isar_mod_cleanup); |
1709 | 1709 |
drivers/isdn/hisax/amd7930_fn.c
1 | /* gerdes_amd7930.c,v 0.99 2001/10/02 | 1 | /* gerdes_amd7930.c,v 0.99 2001/10/02 |
2 | * | 2 | * |
3 | * gerdes_amd7930.c Amd 79C30A and 79C32A specific routines | 3 | * gerdes_amd7930.c Amd 79C30A and 79C32A specific routines |
4 | * (based on HiSax driver by Karsten Keil) | 4 | * (based on HiSax driver by Karsten Keil) |
5 | * | 5 | * |
6 | * Author Christoph Ersfeld <info@formula-n.de> | 6 | * Author Christoph Ersfeld <info@formula-n.de> |
7 | * Formula-n Europe AG (www.formula-n.com) | 7 | * Formula-n Europe AG (www.formula-n.com) |
8 | * previously Gerdes AG | 8 | * previously Gerdes AG |
9 | * | 9 | * |
10 | * | 10 | * |
11 | * This file is (c) under GNU PUBLIC LICENSE | 11 | * This file is (c) under GNU PUBLIC LICENSE |
12 | * | 12 | * |
13 | * | 13 | * |
14 | * Notes: | 14 | * Notes: |
15 | * Version 0.99 is the first release of this driver and there are | 15 | * Version 0.99 is the first release of this driver and there are |
16 | * certainly a few bugs. | 16 | * certainly a few bugs. |
17 | * | 17 | * |
18 | * Please don't report any malfunction to me without sending | 18 | * Please don't report any malfunction to me without sending |
19 | * (compressed) debug-logs. | 19 | * (compressed) debug-logs. |
20 | * It would be nearly impossible to retrace it. | 20 | * It would be nearly impossible to retrace it. |
21 | * | 21 | * |
22 | * Log D-channel-processing as follows: | 22 | * Log D-channel-processing as follows: |
23 | * | 23 | * |
24 | * 1. Load hisax with card-specific parameters, this example ist for | 24 | * 1. Load hisax with card-specific parameters, this example ist for |
25 | * Formula-n enter:now ISDN PCI and compatible | 25 | * Formula-n enter:now ISDN PCI and compatible |
26 | * (f.e. Gerdes Power ISDN PCI) | 26 | * (f.e. Gerdes Power ISDN PCI) |
27 | * | 27 | * |
28 | * modprobe hisax type=41 protocol=2 id=gerdes | 28 | * modprobe hisax type=41 protocol=2 id=gerdes |
29 | * | 29 | * |
30 | * if you chose an other value for id, you need to modify the | 30 | * if you chose an other value for id, you need to modify the |
31 | * code below, too. | 31 | * code below, too. |
32 | * | 32 | * |
33 | * 2. set debug-level | 33 | * 2. set debug-level |
34 | * | 34 | * |
35 | * hisaxctrl gerdes 1 0x3ff | 35 | * hisaxctrl gerdes 1 0x3ff |
36 | * hisaxctrl gerdes 11 0x4f | 36 | * hisaxctrl gerdes 11 0x4f |
37 | * cat /dev/isdnctrl >> ~/log & | 37 | * cat /dev/isdnctrl >> ~/log & |
38 | * | 38 | * |
39 | * Please take also a look into /var/log/messages if there is | 39 | * Please take also a look into /var/log/messages if there is |
40 | * anything importand concerning HISAX. | 40 | * anything importand concerning HISAX. |
41 | * | 41 | * |
42 | * | 42 | * |
43 | * Credits: | 43 | * Credits: |
44 | * Programming the driver for Formula-n enter:now ISDN PCI and | 44 | * Programming the driver for Formula-n enter:now ISDN PCI and |
45 | * necessary this driver for the used Amd 7930 D-channel-controller | 45 | * necessary this driver for the used Amd 7930 D-channel-controller |
46 | * was spnsored by Formula-n Europe AG. | 46 | * was spnsored by Formula-n Europe AG. |
47 | * Thanks to Karsten Keil and Petr Novak, who gave me support in | 47 | * Thanks to Karsten Keil and Petr Novak, who gave me support in |
48 | * Hisax-specific questions. | 48 | * Hisax-specific questions. |
49 | * I want so say special thanks to Carl-Friedrich Braun, who had to | 49 | * I want so say special thanks to Carl-Friedrich Braun, who had to |
50 | * answer a lot of questions about generally ISDN and about handling | 50 | * answer a lot of questions about generally ISDN and about handling |
51 | * of the Amd-Chip. | 51 | * of the Amd-Chip. |
52 | * | 52 | * |
53 | */ | 53 | */ |
54 | 54 | ||
55 | 55 | ||
56 | #include "hisax.h" | 56 | #include "hisax.h" |
57 | #include "isdnl1.h" | 57 | #include "isdnl1.h" |
58 | #include "isac.h" | 58 | #include "isac.h" |
59 | #include "amd7930_fn.h" | 59 | #include "amd7930_fn.h" |
60 | #include <linux/interrupt.h> | 60 | #include <linux/interrupt.h> |
61 | #include <linux/init.h> | 61 | #include <linux/init.h> |
62 | #include <linux/gfp.h> | 62 | #include <linux/gfp.h> |
63 | 63 | ||
64 | static void Amd7930_new_ph(struct IsdnCardState *cs); | 64 | static void Amd7930_new_ph(struct IsdnCardState *cs); |
65 | 65 | ||
66 | static WORD initAMD[] = { | 66 | static WORD initAMD[] = { |
67 | 0x0100, | 67 | 0x0100, |
68 | 68 | ||
69 | 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2 | 69 | 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2 |
70 | 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on) | 70 | 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on) |
71 | 0x0087, 1, 0xFF, // DMR2 | 71 | 0x0087, 1, 0xFF, // DMR2 |
72 | 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on) | 72 | 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on) |
73 | 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition ) | 73 | 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition ) |
74 | 0x0084, 2, 0x80, 0x00, // DRLR | 74 | 0x0084, 2, 0x80, 0x00, // DRLR |
75 | 0x00C0, 1, 0x47, // PPCR1 | 75 | 0x00C0, 1, 0x47, // PPCR1 |
76 | 0x00C8, 1, 0x01, // PPCR2 | 76 | 0x00C8, 1, 0x01, // PPCR2 |
77 | 77 | ||
78 | 0x0102, | 78 | 0x0102, |
79 | 0x0107, | 79 | 0x0107, |
80 | 0x01A1, 1, | 80 | 0x01A1, 1, |
81 | 0x0121, 1, | 81 | 0x0121, 1, |
82 | 0x0189, 2, | 82 | 0x0189, 2, |
83 | 83 | ||
84 | 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4 | 84 | 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4 |
85 | 0x0063, 2, 0x08, 0x08, // GX | 85 | 0x0063, 2, 0x08, 0x08, // GX |
86 | 0x0064, 2, 0x08, 0x08, // GR | 86 | 0x0064, 2, 0x08, 0x08, // GR |
87 | 0x0065, 2, 0x99, 0x00, // GER | 87 | 0x0065, 2, 0x99, 0x00, // GER |
88 | 0x0066, 2, 0x7C, 0x8B, // STG | 88 | 0x0066, 2, 0x7C, 0x8B, // STG |
89 | 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2 | 89 | 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2 |
90 | 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2 | 90 | 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2 |
91 | 0x0069, 1, 0x4F, // MMR1 | 91 | 0x0069, 1, 0x4F, // MMR1 |
92 | 0x006A, 1, 0x00, // MMR2 | 92 | 0x006A, 1, 0x00, // MMR2 |
93 | 0x006C, 1, 0x40, // MMR3 | 93 | 0x006C, 1, 0x40, // MMR3 |
94 | 0x0021, 1, 0x02, // INIT | 94 | 0x0021, 1, 0x02, // INIT |
95 | 0x00A3, 1, 0x40, // LMR1 | 95 | 0x00A3, 1, 0x40, // LMR1 |
96 | 96 | ||
97 | 0xFFFF | 97 | 0xFFFF |
98 | }; | 98 | }; |
99 | 99 | ||
100 | 100 | ||
101 | static void /* macro wWordAMD */ | 101 | static void /* macro wWordAMD */ |
102 | WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val) | 102 | WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val) |
103 | { | 103 | { |
104 | wByteAMD(cs, 0x00, reg); | 104 | wByteAMD(cs, 0x00, reg); |
105 | wByteAMD(cs, 0x01, LOBYTE(val)); | 105 | wByteAMD(cs, 0x01, LOBYTE(val)); |
106 | wByteAMD(cs, 0x01, HIBYTE(val)); | 106 | wByteAMD(cs, 0x01, HIBYTE(val)); |
107 | } | 107 | } |
108 | 108 | ||
109 | static WORD /* macro rWordAMD */ | 109 | static WORD /* macro rWordAMD */ |
110 | ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg) | 110 | ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg) |
111 | { | 111 | { |
112 | WORD res; | 112 | WORD res; |
113 | /* direct access register */ | 113 | /* direct access register */ |
114 | if (reg < 8) { | 114 | if (reg < 8) { |
115 | res = rByteAMD(cs, reg); | 115 | res = rByteAMD(cs, reg); |
116 | res += 256 * rByteAMD(cs, reg); | 116 | res += 256 * rByteAMD(cs, reg); |
117 | } | 117 | } |
118 | /* indirect access register */ | 118 | /* indirect access register */ |
119 | else { | 119 | else { |
120 | wByteAMD(cs, 0x00, reg); | 120 | wByteAMD(cs, 0x00, reg); |
121 | res = rByteAMD(cs, 0x01); | 121 | res = rByteAMD(cs, 0x01); |
122 | res += 256 * rByteAMD(cs, 0x01); | 122 | res += 256 * rByteAMD(cs, 0x01); |
123 | } | 123 | } |
124 | return (res); | 124 | return (res); |
125 | } | 125 | } |
126 | 126 | ||
127 | 127 | ||
128 | static void | 128 | static void |
129 | Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s) | 129 | Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s) |
130 | { | 130 | { |
131 | if (cs->debug & L1_DEB_ISAC) | 131 | if (cs->debug & L1_DEB_ISAC) |
132 | debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command); | 132 | debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command); |
133 | 133 | ||
134 | cs->dc.amd7930.lmr1 = command; | 134 | cs->dc.amd7930.lmr1 = command; |
135 | wByteAMD(cs, 0xA3, command); | 135 | wByteAMD(cs, 0xA3, command); |
136 | } | 136 | } |
137 | 137 | ||
138 | 138 | ||
139 | 139 | ||
140 | static BYTE i430States[] = { | 140 | static BYTE i430States[] = { |
141 | // to reset F3 F4 F5 F6 F7 F8 AR from | 141 | // to reset F3 F4 F5 F6 F7 F8 AR from |
142 | 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // init | 142 | 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // init |
143 | 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // reset | 143 | 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // reset |
144 | 0x01, 0x02, 0x00, 0x00, 0x00, 0x09, 0x05, 0x04, // F3 | 144 | 0x01, 0x02, 0x00, 0x00, 0x00, 0x09, 0x05, 0x04, // F3 |
145 | 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F4 | 145 | 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F4 |
146 | 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F5 | 146 | 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F5 |
147 | 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, // F6 | 147 | 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, // F6 |
148 | 0x11, 0x13, 0x00, 0x00, 0x1B, 0x00, 0x15, 0x00, // F7 | 148 | 0x11, 0x13, 0x00, 0x00, 0x1B, 0x00, 0x15, 0x00, // F7 |
149 | 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, // F8 | 149 | 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, // F8 |
150 | 0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0A}; // AR | 150 | 0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0A}; // AR |
151 | 151 | ||
152 | 152 | ||
153 | /* Row init - reset F3 F4 F5 F6 F7 F8 AR */ | 153 | /* Row init - reset F3 F4 F5 F6 F7 F8 AR */ |
154 | static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; | 154 | static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; |
155 | 155 | ||
156 | 156 | ||
157 | 157 | ||
158 | 158 | ||
159 | static void | 159 | static void |
160 | Amd7930_get_state(struct IsdnCardState *cs) { | 160 | Amd7930_get_state(struct IsdnCardState *cs) { |
161 | BYTE lsr = rByteAMD(cs, 0xA1); | 161 | BYTE lsr = rByteAMD(cs, 0xA1); |
162 | cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; | 162 | cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; |
163 | Amd7930_new_ph(cs); | 163 | Amd7930_new_ph(cs); |
164 | } | 164 | } |
165 | 165 | ||
166 | 166 | ||
167 | 167 | ||
168 | static void | 168 | static void |
169 | Amd7930_new_ph(struct IsdnCardState *cs) | 169 | Amd7930_new_ph(struct IsdnCardState *cs) |
170 | { | 170 | { |
171 | u_char index = stateHelper[cs->dc.amd7930.old_state] * 8 + stateHelper[cs->dc.amd7930.ph_state] - 1; | 171 | u_char index = stateHelper[cs->dc.amd7930.old_state] * 8 + stateHelper[cs->dc.amd7930.ph_state] - 1; |
172 | u_char message = i430States[index]; | 172 | u_char message = i430States[index]; |
173 | 173 | ||
174 | if (cs->debug & L1_DEB_ISAC) | 174 | if (cs->debug & L1_DEB_ISAC) |
175 | debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d", | 175 | debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d", |
176 | cs->dc.amd7930.ph_state, cs->dc.amd7930.old_state, message & 0x0f, index); | 176 | cs->dc.amd7930.ph_state, cs->dc.amd7930.old_state, message & 0x0f, index); |
177 | 177 | ||
178 | cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state; | 178 | cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state; |
179 | 179 | ||
180 | /* abort transmit if nessesary */ | 180 | /* abort transmit if nessesary */ |
181 | if ((message & 0xf0) && (cs->tx_skb)) { | 181 | if ((message & 0xf0) && (cs->tx_skb)) { |
182 | wByteAMD(cs, 0x21, 0xC2); | 182 | wByteAMD(cs, 0x21, 0xC2); |
183 | wByteAMD(cs, 0x21, 0x02); | 183 | wByteAMD(cs, 0x21, 0x02); |
184 | } | 184 | } |
185 | 185 | ||
186 | switch (message & 0x0f) { | 186 | switch (message & 0x0f) { |
187 | 187 | ||
188 | case (1): | 188 | case (1): |
189 | l1_msg(cs, HW_RESET | INDICATION, NULL); | 189 | l1_msg(cs, HW_RESET | INDICATION, NULL); |
190 | Amd7930_get_state(cs); | 190 | Amd7930_get_state(cs); |
191 | break; | 191 | break; |
192 | case (2): /* init, Card starts in F3 */ | 192 | case (2): /* init, Card starts in F3 */ |
193 | l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); | 193 | l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); |
194 | break; | 194 | break; |
195 | case (3): | 195 | case (3): |
196 | l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); | 196 | l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); |
197 | break; | 197 | break; |
198 | case (4): | 198 | case (4): |
199 | l1_msg(cs, HW_POWERUP | CONFIRM, NULL); | 199 | l1_msg(cs, HW_POWERUP | CONFIRM, NULL); |
200 | Amd7930_ph_command(cs, 0x50, "HW_ENABLE REQUEST"); | 200 | Amd7930_ph_command(cs, 0x50, "HW_ENABLE REQUEST"); |
201 | break; | 201 | break; |
202 | case (5): | 202 | case (5): |
203 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); | 203 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); |
204 | break; | 204 | break; |
205 | case (6): | 205 | case (6): |
206 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); | 206 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); |
207 | break; | 207 | break; |
208 | case (7): /* init, Card starts in F7 */ | 208 | case (7): /* init, Card starts in F7 */ |
209 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); | 209 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); |
210 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); | 210 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); |
211 | break; | 211 | break; |
212 | case (8): | 212 | case (8): |
213 | l1_msg(cs, HW_POWERUP | CONFIRM, NULL); | 213 | l1_msg(cs, HW_POWERUP | CONFIRM, NULL); |
214 | /* fall through */ | 214 | /* fall through */ |
215 | case (9): | 215 | case (9): |
216 | Amd7930_ph_command(cs, 0x40, "HW_ENABLE REQ cleared if set"); | 216 | Amd7930_ph_command(cs, 0x40, "HW_ENABLE REQ cleared if set"); |
217 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); | 217 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); |
218 | l1_msg(cs, HW_INFO2 | INDICATION, NULL); | 218 | l1_msg(cs, HW_INFO2 | INDICATION, NULL); |
219 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); | 219 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); |
220 | break; | 220 | break; |
221 | case (10): | 221 | case (10): |
222 | Amd7930_ph_command(cs, 0x40, "T3 expired, HW_ENABLE REQ cleared"); | 222 | Amd7930_ph_command(cs, 0x40, "T3 expired, HW_ENABLE REQ cleared"); |
223 | cs->dc.amd7930.old_state = 3; | 223 | cs->dc.amd7930.old_state = 3; |
224 | break; | 224 | break; |
225 | case (11): | 225 | case (11): |
226 | l1_msg(cs, HW_INFO2 | INDICATION, NULL); | 226 | l1_msg(cs, HW_INFO2 | INDICATION, NULL); |
227 | break; | 227 | break; |
228 | default: | 228 | default: |
229 | break; | 229 | break; |
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | 233 | ||
234 | 234 | ||
235 | static void | 235 | static void |
236 | Amd7930_bh(struct work_struct *work) | 236 | Amd7930_bh(struct work_struct *work) |
237 | { | 237 | { |
238 | struct IsdnCardState *cs = | 238 | struct IsdnCardState *cs = |
239 | container_of(work, struct IsdnCardState, tqueue); | 239 | container_of(work, struct IsdnCardState, tqueue); |
240 | struct PStack *stptr; | 240 | struct PStack *stptr; |
241 | 241 | ||
242 | if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { | 242 | if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { |
243 | if (cs->debug) | 243 | if (cs->debug) |
244 | debugl1(cs, "Amd7930: bh, D-Channel Busy cleared"); | 244 | debugl1(cs, "Amd7930: bh, D-Channel Busy cleared"); |
245 | stptr = cs->stlist; | 245 | stptr = cs->stlist; |
246 | while (stptr != NULL) { | 246 | while (stptr != NULL) { |
247 | stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); | 247 | stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); |
248 | stptr = stptr->next; | 248 | stptr = stptr->next; |
249 | } | 249 | } |
250 | } | 250 | } |
251 | if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { | 251 | if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { |
252 | if (cs->debug & L1_DEB_ISAC) | 252 | if (cs->debug & L1_DEB_ISAC) |
253 | debugl1(cs, "AMD7930: bh, D_L1STATECHANGE"); | 253 | debugl1(cs, "AMD7930: bh, D_L1STATECHANGE"); |
254 | Amd7930_new_ph(cs); | 254 | Amd7930_new_ph(cs); |
255 | } | 255 | } |
256 | 256 | ||
257 | if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) { | 257 | if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) { |
258 | if (cs->debug & L1_DEB_ISAC) | 258 | if (cs->debug & L1_DEB_ISAC) |
259 | debugl1(cs, "AMD7930: bh, D_RCVBUFREADY"); | 259 | debugl1(cs, "AMD7930: bh, D_RCVBUFREADY"); |
260 | DChannel_proc_rcv(cs); | 260 | DChannel_proc_rcv(cs); |
261 | } | 261 | } |
262 | 262 | ||
263 | if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) { | 263 | if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) { |
264 | if (cs->debug & L1_DEB_ISAC) | 264 | if (cs->debug & L1_DEB_ISAC) |
265 | debugl1(cs, "AMD7930: bh, D_XMTBUFREADY"); | 265 | debugl1(cs, "AMD7930: bh, D_XMTBUFREADY"); |
266 | DChannel_proc_xmt(cs); | 266 | DChannel_proc_xmt(cs); |
267 | } | 267 | } |
268 | } | 268 | } |
269 | 269 | ||
270 | static void | 270 | static void |
271 | Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) | 271 | Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) |
272 | { | 272 | { |
273 | 273 | ||
274 | BYTE stat, der; | 274 | BYTE stat, der; |
275 | BYTE *ptr; | 275 | BYTE *ptr; |
276 | struct sk_buff *skb; | 276 | struct sk_buff *skb; |
277 | 277 | ||
278 | 278 | ||
279 | if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) | 279 | if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) |
280 | debugl1(cs, "Amd7930: empty_Dfifo"); | 280 | debugl1(cs, "Amd7930: empty_Dfifo"); |
281 | 281 | ||
282 | 282 | ||
283 | ptr = cs->rcvbuf + cs->rcvidx; | 283 | ptr = cs->rcvbuf + cs->rcvidx; |
284 | 284 | ||
285 | /* AMD interrupts off */ | 285 | /* AMD interrupts off */ |
286 | AmdIrqOff(cs); | 286 | AmdIrqOff(cs); |
287 | 287 | ||
288 | /* read D-Channel-Fifo*/ | 288 | /* read D-Channel-Fifo*/ |
289 | stat = rByteAMD(cs, 0x07); // DSR2 | 289 | stat = rByteAMD(cs, 0x07); // DSR2 |
290 | 290 | ||
291 | /* while Data in Fifo ... */ | 291 | /* while Data in Fifo ... */ |
292 | while ((stat & 2) && ((ptr-cs->rcvbuf) < MAX_DFRAME_LEN_L1)) { | 292 | while ((stat & 2) && ((ptr-cs->rcvbuf) < MAX_DFRAME_LEN_L1)) { |
293 | *ptr = rByteAMD(cs, 0x04); // DCRB | 293 | *ptr = rByteAMD(cs, 0x04); // DCRB |
294 | ptr++; | 294 | ptr++; |
295 | stat = rByteAMD(cs, 0x07); // DSR2 | 295 | stat = rByteAMD(cs, 0x07); // DSR2 |
296 | cs->rcvidx = ptr - cs->rcvbuf; | 296 | cs->rcvidx = ptr - cs->rcvbuf; |
297 | 297 | ||
298 | /* Paket ready? */ | 298 | /* Paket ready? */ |
299 | if (stat & 1) { | 299 | if (stat & 1) { |
300 | 300 | ||
301 | der = rWordAMD(cs, 0x03); | 301 | der = rWordAMD(cs, 0x03); |
302 | 302 | ||
303 | /* no errors, packet ok */ | 303 | /* no errors, packet ok */ |
304 | if (!der && !flag) { | 304 | if (!der && !flag) { |
305 | rWordAMD(cs, 0x89); // clear DRCR | 305 | rWordAMD(cs, 0x89); // clear DRCR |
306 | 306 | ||
307 | if ((cs->rcvidx) > 0) { | 307 | if ((cs->rcvidx) > 0) { |
308 | if (!(skb = alloc_skb(cs->rcvidx, GFP_ATOMIC))) | 308 | if (!(skb = alloc_skb(cs->rcvidx, GFP_ATOMIC))) |
309 | printk(KERN_WARNING "HiSax: Amd7930: empty_Dfifo, D receive out of memory!\n"); | 309 | printk(KERN_WARNING "HiSax: Amd7930: empty_Dfifo, D receive out of memory!\n"); |
310 | else { | 310 | else { |
311 | /* Debugging */ | 311 | /* Debugging */ |
312 | if (cs->debug & L1_DEB_ISAC_FIFO) { | 312 | if (cs->debug & L1_DEB_ISAC_FIFO) { |
313 | char *t = cs->dlog; | 313 | char *t = cs->dlog; |
314 | 314 | ||
315 | t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx); | 315 | t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx); |
316 | QuickHex(t, cs->rcvbuf, cs->rcvidx); | 316 | QuickHex(t, cs->rcvbuf, cs->rcvidx); |
317 | debugl1(cs, cs->dlog); | 317 | debugl1(cs, cs->dlog); |
318 | } | 318 | } |
319 | /* moves received data in sk-buffer */ | 319 | /* moves received data in sk-buffer */ |
320 | memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx); | 320 | memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx); |
321 | skb_queue_tail(&cs->rq, skb); | 321 | skb_queue_tail(&cs->rq, skb); |
322 | } | 322 | } |
323 | } | 323 | } |
324 | 324 | ||
325 | } | 325 | } |
326 | /* throw damaged packets away, reset receive-buffer, indicate RX */ | 326 | /* throw damaged packets away, reset receive-buffer, indicate RX */ |
327 | ptr = cs->rcvbuf; | 327 | ptr = cs->rcvbuf; |
328 | cs->rcvidx = 0; | 328 | cs->rcvidx = 0; |
329 | schedule_event(cs, D_RCVBUFREADY); | 329 | schedule_event(cs, D_RCVBUFREADY); |
330 | } | 330 | } |
331 | } | 331 | } |
332 | /* Packet to long, overflow */ | 332 | /* Packet to long, overflow */ |
333 | if (cs->rcvidx >= MAX_DFRAME_LEN_L1) { | 333 | if (cs->rcvidx >= MAX_DFRAME_LEN_L1) { |
334 | if (cs->debug & L1_DEB_WARN) | 334 | if (cs->debug & L1_DEB_WARN) |
335 | debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun"); | 335 | debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun"); |
336 | cs->rcvidx = 0; | 336 | cs->rcvidx = 0; |
337 | return; | 337 | return; |
338 | } | 338 | } |
339 | /* AMD interrupts on */ | 339 | /* AMD interrupts on */ |
340 | AmdIrqOn(cs); | 340 | AmdIrqOn(cs); |
341 | } | 341 | } |
342 | 342 | ||
343 | 343 | ||
344 | static void | 344 | static void |
345 | Amd7930_fill_Dfifo(struct IsdnCardState *cs) | 345 | Amd7930_fill_Dfifo(struct IsdnCardState *cs) |
346 | { | 346 | { |
347 | 347 | ||
348 | WORD dtcrr, dtcrw, len, count; | 348 | WORD dtcrr, dtcrw, len, count; |
349 | BYTE txstat, dmr3; | 349 | BYTE txstat, dmr3; |
350 | BYTE *ptr, *deb_ptr; | 350 | BYTE *ptr, *deb_ptr; |
351 | 351 | ||
352 | if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) | 352 | if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) |
353 | debugl1(cs, "Amd7930: fill_Dfifo"); | 353 | debugl1(cs, "Amd7930: fill_Dfifo"); |
354 | 354 | ||
355 | if ((!cs->tx_skb) || (cs->tx_skb->len <= 0)) | 355 | if ((!cs->tx_skb) || (cs->tx_skb->len <= 0)) |
356 | return; | 356 | return; |
357 | 357 | ||
358 | dtcrw = 0; | 358 | dtcrw = 0; |
359 | if (!cs->dc.amd7930.tx_xmtlen) | 359 | if (!cs->dc.amd7930.tx_xmtlen) |
360 | /* new Frame */ | 360 | /* new Frame */ |
361 | len = dtcrw = cs->tx_skb->len; | 361 | len = dtcrw = cs->tx_skb->len; |
362 | /* continue frame */ | 362 | /* continue frame */ |
363 | else len = cs->dc.amd7930.tx_xmtlen; | 363 | else len = cs->dc.amd7930.tx_xmtlen; |
364 | 364 | ||
365 | 365 | ||
366 | /* AMD interrupts off */ | 366 | /* AMD interrupts off */ |
367 | AmdIrqOff(cs); | 367 | AmdIrqOff(cs); |
368 | 368 | ||
369 | deb_ptr = ptr = cs->tx_skb->data; | 369 | deb_ptr = ptr = cs->tx_skb->data; |
370 | 370 | ||
371 | /* while free place in tx-fifo available and data in sk-buffer */ | 371 | /* while free place in tx-fifo available and data in sk-buffer */ |
372 | txstat = 0x10; | 372 | txstat = 0x10; |
373 | while ((txstat & 0x10) && (cs->tx_cnt < len)) { | 373 | while ((txstat & 0x10) && (cs->tx_cnt < len)) { |
374 | wByteAMD(cs, 0x04, *ptr); | 374 | wByteAMD(cs, 0x04, *ptr); |
375 | ptr++; | 375 | ptr++; |
376 | cs->tx_cnt++; | 376 | cs->tx_cnt++; |
377 | txstat = rByteAMD(cs, 0x07); | 377 | txstat = rByteAMD(cs, 0x07); |
378 | } | 378 | } |
379 | count = ptr - cs->tx_skb->data; | 379 | count = ptr - cs->tx_skb->data; |
380 | skb_pull(cs->tx_skb, count); | 380 | skb_pull(cs->tx_skb, count); |
381 | 381 | ||
382 | 382 | ||
383 | dtcrr = rWordAMD(cs, 0x85); // DTCR | 383 | dtcrr = rWordAMD(cs, 0x85); // DTCR |
384 | dmr3 = rByteAMD(cs, 0x8E); | 384 | dmr3 = rByteAMD(cs, 0x8E); |
385 | 385 | ||
386 | if (cs->debug & L1_DEB_ISAC) { | 386 | if (cs->debug & L1_DEB_ISAC) { |
387 | debugl1(cs, "Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X", dmr3, dtcrr, LOBYTE(dtcrw), HIBYTE(dtcrw)); | 387 | debugl1(cs, "Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X", dmr3, dtcrr, LOBYTE(dtcrw), HIBYTE(dtcrw)); |
388 | } | 388 | } |
389 | 389 | ||
390 | /* writeing of dtcrw starts transmit */ | 390 | /* writeing of dtcrw starts transmit */ |
391 | if (!cs->dc.amd7930.tx_xmtlen) { | 391 | if (!cs->dc.amd7930.tx_xmtlen) { |
392 | wWordAMD(cs, 0x85, dtcrw); | 392 | wWordAMD(cs, 0x85, dtcrw); |
393 | cs->dc.amd7930.tx_xmtlen = dtcrw; | 393 | cs->dc.amd7930.tx_xmtlen = dtcrw; |
394 | } | 394 | } |
395 | 395 | ||
396 | if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { | 396 | if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { |
397 | debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running"); | 397 | debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running"); |
398 | del_timer(&cs->dbusytimer); | 398 | del_timer(&cs->dbusytimer); |
399 | } | 399 | } |
400 | init_timer(&cs->dbusytimer); | 400 | init_timer(&cs->dbusytimer); |
401 | cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); | 401 | cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); |
402 | add_timer(&cs->dbusytimer); | 402 | add_timer(&cs->dbusytimer); |
403 | 403 | ||
404 | if (cs->debug & L1_DEB_ISAC_FIFO) { | 404 | if (cs->debug & L1_DEB_ISAC_FIFO) { |
405 | char *t = cs->dlog; | 405 | char *t = cs->dlog; |
406 | 406 | ||
407 | t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count); | 407 | t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count); |
408 | QuickHex(t, deb_ptr, count); | 408 | QuickHex(t, deb_ptr, count); |
409 | debugl1(cs, cs->dlog); | 409 | debugl1(cs, cs->dlog); |
410 | } | 410 | } |
411 | /* AMD interrupts on */ | 411 | /* AMD interrupts on */ |
412 | AmdIrqOn(cs); | 412 | AmdIrqOn(cs); |
413 | } | 413 | } |
414 | 414 | ||
415 | 415 | ||
416 | void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags) | 416 | void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags) |
417 | { | 417 | { |
418 | BYTE dsr1, dsr2, lsr; | 418 | BYTE dsr1, dsr2, lsr; |
419 | WORD der; | 419 | WORD der; |
420 | 420 | ||
421 | while (irflags) | 421 | while (irflags) |
422 | { | 422 | { |
423 | 423 | ||
424 | dsr1 = rByteAMD(cs, 0x02); | 424 | dsr1 = rByteAMD(cs, 0x02); |
425 | der = rWordAMD(cs, 0x03); | 425 | der = rWordAMD(cs, 0x03); |
426 | dsr2 = rByteAMD(cs, 0x07); | 426 | dsr2 = rByteAMD(cs, 0x07); |
427 | lsr = rByteAMD(cs, 0xA1); | 427 | lsr = rByteAMD(cs, 0xA1); |
428 | 428 | ||
429 | if (cs->debug & L1_DEB_ISAC) | 429 | if (cs->debug & L1_DEB_ISAC) |
430 | debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der); | 430 | debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der); |
431 | 431 | ||
432 | /* D error -> read DER and DSR2 bit 2 */ | 432 | /* D error -> read DER and DSR2 bit 2 */ |
433 | if (der || (dsr2 & 4)) { | 433 | if (der || (dsr2 & 4)) { |
434 | 434 | ||
435 | if (cs->debug & L1_DEB_WARN) | 435 | if (cs->debug & L1_DEB_WARN) |
436 | debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der); | 436 | debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der); |
437 | 437 | ||
438 | /* RX, TX abort if collision detected */ | 438 | /* RX, TX abort if collision detected */ |
439 | if (der & 2) { | 439 | if (der & 2) { |
440 | wByteAMD(cs, 0x21, 0xC2); | 440 | wByteAMD(cs, 0x21, 0xC2); |
441 | wByteAMD(cs, 0x21, 0x02); | 441 | wByteAMD(cs, 0x21, 0x02); |
442 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) | 442 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) |
443 | del_timer(&cs->dbusytimer); | 443 | del_timer(&cs->dbusytimer); |
444 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) | 444 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) |
445 | schedule_event(cs, D_CLEARBUSY); | 445 | schedule_event(cs, D_CLEARBUSY); |
446 | /* restart frame */ | 446 | /* restart frame */ |
447 | if (cs->tx_skb) { | 447 | if (cs->tx_skb) { |
448 | skb_push(cs->tx_skb, cs->tx_cnt); | 448 | skb_push(cs->tx_skb, cs->tx_cnt); |
449 | cs->tx_cnt = 0; | 449 | cs->tx_cnt = 0; |
450 | cs->dc.amd7930.tx_xmtlen = 0; | 450 | cs->dc.amd7930.tx_xmtlen = 0; |
451 | Amd7930_fill_Dfifo(cs); | 451 | Amd7930_fill_Dfifo(cs); |
452 | } else { | 452 | } else { |
453 | printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n"); | 453 | printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n"); |
454 | debugl1(cs, "Amd7930: interrupt: D-Collision, no skb"); | 454 | debugl1(cs, "Amd7930: interrupt: D-Collision, no skb"); |
455 | } | 455 | } |
456 | } | 456 | } |
457 | /* remove damaged data from fifo */ | 457 | /* remove damaged data from fifo */ |
458 | Amd7930_empty_Dfifo(cs, 1); | 458 | Amd7930_empty_Dfifo(cs, 1); |
459 | 459 | ||
460 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) | 460 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) |
461 | del_timer(&cs->dbusytimer); | 461 | del_timer(&cs->dbusytimer); |
462 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) | 462 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) |
463 | schedule_event(cs, D_CLEARBUSY); | 463 | schedule_event(cs, D_CLEARBUSY); |
464 | /* restart TX-Frame */ | 464 | /* restart TX-Frame */ |
465 | if (cs->tx_skb) { | 465 | if (cs->tx_skb) { |
466 | skb_push(cs->tx_skb, cs->tx_cnt); | 466 | skb_push(cs->tx_skb, cs->tx_cnt); |
467 | cs->tx_cnt = 0; | 467 | cs->tx_cnt = 0; |
468 | cs->dc.amd7930.tx_xmtlen = 0; | 468 | cs->dc.amd7930.tx_xmtlen = 0; |
469 | Amd7930_fill_Dfifo(cs); | 469 | Amd7930_fill_Dfifo(cs); |
470 | } | 470 | } |
471 | } | 471 | } |
472 | 472 | ||
473 | /* D TX FIFO empty -> fill */ | 473 | /* D TX FIFO empty -> fill */ |
474 | if (irflags & 1) { | 474 | if (irflags & 1) { |
475 | if (cs->debug & L1_DEB_ISAC) | 475 | if (cs->debug & L1_DEB_ISAC) |
476 | debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data"); | 476 | debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data"); |
477 | 477 | ||
478 | /* AMD interrupts off */ | 478 | /* AMD interrupts off */ |
479 | AmdIrqOff(cs); | 479 | AmdIrqOff(cs); |
480 | 480 | ||
481 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) | 481 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) |
482 | del_timer(&cs->dbusytimer); | 482 | del_timer(&cs->dbusytimer); |
483 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) | 483 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) |
484 | schedule_event(cs, D_CLEARBUSY); | 484 | schedule_event(cs, D_CLEARBUSY); |
485 | if (cs->tx_skb) { | 485 | if (cs->tx_skb) { |
486 | if (cs->tx_skb->len) | 486 | if (cs->tx_skb->len) |
487 | Amd7930_fill_Dfifo(cs); | 487 | Amd7930_fill_Dfifo(cs); |
488 | } | 488 | } |
489 | /* AMD interrupts on */ | 489 | /* AMD interrupts on */ |
490 | AmdIrqOn(cs); | 490 | AmdIrqOn(cs); |
491 | } | 491 | } |
492 | 492 | ||
493 | 493 | ||
494 | /* D RX FIFO full or tiny packet in Fifo -> empty */ | 494 | /* D RX FIFO full or tiny packet in Fifo -> empty */ |
495 | if ((irflags & 2) || (dsr1 & 2)) { | 495 | if ((irflags & 2) || (dsr1 & 2)) { |
496 | if (cs->debug & L1_DEB_ISAC) | 496 | if (cs->debug & L1_DEB_ISAC) |
497 | debugl1(cs, "Amd7930: interrupt: empty D-FIFO"); | 497 | debugl1(cs, "Amd7930: interrupt: empty D-FIFO"); |
498 | Amd7930_empty_Dfifo(cs, 0); | 498 | Amd7930_empty_Dfifo(cs, 0); |
499 | } | 499 | } |
500 | 500 | ||
501 | 501 | ||
502 | /* D-Frame transmit complete */ | 502 | /* D-Frame transmit complete */ |
503 | if (dsr1 & 64) { | 503 | if (dsr1 & 64) { |
504 | if (cs->debug & L1_DEB_ISAC) { | 504 | if (cs->debug & L1_DEB_ISAC) { |
505 | debugl1(cs, "Amd7930: interrupt: transmit packet ready"); | 505 | debugl1(cs, "Amd7930: interrupt: transmit packet ready"); |
506 | } | 506 | } |
507 | /* AMD interrupts off */ | 507 | /* AMD interrupts off */ |
508 | AmdIrqOff(cs); | 508 | AmdIrqOff(cs); |
509 | 509 | ||
510 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) | 510 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) |
511 | del_timer(&cs->dbusytimer); | 511 | del_timer(&cs->dbusytimer); |
512 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) | 512 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) |
513 | schedule_event(cs, D_CLEARBUSY); | 513 | schedule_event(cs, D_CLEARBUSY); |
514 | 514 | ||
515 | if (cs->tx_skb) { | 515 | if (cs->tx_skb) { |
516 | if (cs->debug & L1_DEB_ISAC) | 516 | if (cs->debug & L1_DEB_ISAC) |
517 | debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb"); | 517 | debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb"); |
518 | dev_kfree_skb_irq(cs->tx_skb); | 518 | dev_kfree_skb_irq(cs->tx_skb); |
519 | cs->tx_cnt = 0; | 519 | cs->tx_cnt = 0; |
520 | cs->dc.amd7930.tx_xmtlen = 0; | 520 | cs->dc.amd7930.tx_xmtlen = 0; |
521 | cs->tx_skb = NULL; | 521 | cs->tx_skb = NULL; |
522 | } | 522 | } |
523 | if ((cs->tx_skb = skb_dequeue(&cs->sq))) { | 523 | if ((cs->tx_skb = skb_dequeue(&cs->sq))) { |
524 | if (cs->debug & L1_DEB_ISAC) | 524 | if (cs->debug & L1_DEB_ISAC) |
525 | debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued"); | 525 | debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued"); |
526 | cs->tx_cnt = 0; | 526 | cs->tx_cnt = 0; |
527 | cs->dc.amd7930.tx_xmtlen = 0; | 527 | cs->dc.amd7930.tx_xmtlen = 0; |
528 | Amd7930_fill_Dfifo(cs); | 528 | Amd7930_fill_Dfifo(cs); |
529 | } | 529 | } |
530 | else | 530 | else |
531 | schedule_event(cs, D_XMTBUFREADY); | 531 | schedule_event(cs, D_XMTBUFREADY); |
532 | /* AMD interrupts on */ | 532 | /* AMD interrupts on */ |
533 | AmdIrqOn(cs); | 533 | AmdIrqOn(cs); |
534 | } | 534 | } |
535 | 535 | ||
536 | /* LIU status interrupt -> read LSR, check statechanges */ | 536 | /* LIU status interrupt -> read LSR, check statechanges */ |
537 | if (lsr & 0x38) { | 537 | if (lsr & 0x38) { |
538 | /* AMD interrupts off */ | 538 | /* AMD interrupts off */ |
539 | AmdIrqOff(cs); | 539 | AmdIrqOff(cs); |
540 | 540 | ||
541 | if (cs->debug & L1_DEB_ISAC) | 541 | if (cs->debug & L1_DEB_ISAC) |
542 | debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) + 2)); | 542 | debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) + 2)); |
543 | 543 | ||
544 | cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; | 544 | cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; |
545 | 545 | ||
546 | schedule_event(cs, D_L1STATECHANGE); | 546 | schedule_event(cs, D_L1STATECHANGE); |
547 | /* AMD interrupts on */ | 547 | /* AMD interrupts on */ |
548 | AmdIrqOn(cs); | 548 | AmdIrqOn(cs); |
549 | } | 549 | } |
550 | 550 | ||
551 | /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */ | 551 | /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */ |
552 | irflags = rByteAMD(cs, 0x00); | 552 | irflags = rByteAMD(cs, 0x00); |
553 | } | 553 | } |
554 | 554 | ||
555 | } | 555 | } |
556 | 556 | ||
557 | static void | 557 | static void |
558 | Amd7930_l1hw(struct PStack *st, int pr, void *arg) | 558 | Amd7930_l1hw(struct PStack *st, int pr, void *arg) |
559 | { | 559 | { |
560 | struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; | 560 | struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; |
561 | struct sk_buff *skb = arg; | 561 | struct sk_buff *skb = arg; |
562 | u_long flags; | 562 | u_long flags; |
563 | 563 | ||
564 | if (cs->debug & L1_DEB_ISAC) | 564 | if (cs->debug & L1_DEB_ISAC) |
565 | debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr); | 565 | debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr); |
566 | 566 | ||
567 | switch (pr) { | 567 | switch (pr) { |
568 | case (PH_DATA | REQUEST): | 568 | case (PH_DATA | REQUEST): |
569 | if (cs->debug & DEB_DLOG_HEX) | 569 | if (cs->debug & DEB_DLOG_HEX) |
570 | LogFrame(cs, skb->data, skb->len); | 570 | LogFrame(cs, skb->data, skb->len); |
571 | if (cs->debug & DEB_DLOG_VERBOSE) | 571 | if (cs->debug & DEB_DLOG_VERBOSE) |
572 | dlogframe(cs, skb, 0); | 572 | dlogframe(cs, skb, 0); |
573 | spin_lock_irqsave(&cs->lock, flags); | 573 | spin_lock_irqsave(&cs->lock, flags); |
574 | if (cs->tx_skb) { | 574 | if (cs->tx_skb) { |
575 | skb_queue_tail(&cs->sq, skb); | 575 | skb_queue_tail(&cs->sq, skb); |
576 | #ifdef L2FRAME_DEBUG /* psa */ | 576 | #ifdef L2FRAME_DEBUG /* psa */ |
577 | if (cs->debug & L1_DEB_LAPD) | 577 | if (cs->debug & L1_DEB_LAPD) |
578 | Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA Queued", 0); | 578 | Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA Queued", 0); |
579 | #endif | 579 | #endif |
580 | } else { | 580 | } else { |
581 | cs->tx_skb = skb; | 581 | cs->tx_skb = skb; |
582 | cs->tx_cnt = 0; | 582 | cs->tx_cnt = 0; |
583 | cs->dc.amd7930.tx_xmtlen = 0; | 583 | cs->dc.amd7930.tx_xmtlen = 0; |
584 | #ifdef L2FRAME_DEBUG /* psa */ | 584 | #ifdef L2FRAME_DEBUG /* psa */ |
585 | if (cs->debug & L1_DEB_LAPD) | 585 | if (cs->debug & L1_DEB_LAPD) |
586 | Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0); | 586 | Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0); |
587 | #endif | 587 | #endif |
588 | Amd7930_fill_Dfifo(cs); | 588 | Amd7930_fill_Dfifo(cs); |
589 | } | 589 | } |
590 | spin_unlock_irqrestore(&cs->lock, flags); | 590 | spin_unlock_irqrestore(&cs->lock, flags); |
591 | break; | 591 | break; |
592 | case (PH_PULL | INDICATION): | 592 | case (PH_PULL | INDICATION): |
593 | spin_lock_irqsave(&cs->lock, flags); | 593 | spin_lock_irqsave(&cs->lock, flags); |
594 | if (cs->tx_skb) { | 594 | if (cs->tx_skb) { |
595 | if (cs->debug & L1_DEB_WARN) | 595 | if (cs->debug & L1_DEB_WARN) |
596 | debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen"); | 596 | debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen"); |
597 | skb_queue_tail(&cs->sq, skb); | 597 | skb_queue_tail(&cs->sq, skb); |
598 | spin_unlock_irqrestore(&cs->lock, flags); | 598 | spin_unlock_irqrestore(&cs->lock, flags); |
599 | break; | 599 | break; |
600 | } | 600 | } |
601 | if (cs->debug & DEB_DLOG_HEX) | 601 | if (cs->debug & DEB_DLOG_HEX) |
602 | LogFrame(cs, skb->data, skb->len); | 602 | LogFrame(cs, skb->data, skb->len); |
603 | if (cs->debug & DEB_DLOG_VERBOSE) | 603 | if (cs->debug & DEB_DLOG_VERBOSE) |
604 | dlogframe(cs, skb, 0); | 604 | dlogframe(cs, skb, 0); |
605 | cs->tx_skb = skb; | 605 | cs->tx_skb = skb; |
606 | cs->tx_cnt = 0; | 606 | cs->tx_cnt = 0; |
607 | cs->dc.amd7930.tx_xmtlen = 0; | 607 | cs->dc.amd7930.tx_xmtlen = 0; |
608 | #ifdef L2FRAME_DEBUG /* psa */ | 608 | #ifdef L2FRAME_DEBUG /* psa */ |
609 | if (cs->debug & L1_DEB_LAPD) | 609 | if (cs->debug & L1_DEB_LAPD) |
610 | Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0); | 610 | Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0); |
611 | #endif | 611 | #endif |
612 | Amd7930_fill_Dfifo(cs); | 612 | Amd7930_fill_Dfifo(cs); |
613 | spin_unlock_irqrestore(&cs->lock, flags); | 613 | spin_unlock_irqrestore(&cs->lock, flags); |
614 | break; | 614 | break; |
615 | case (PH_PULL | REQUEST): | 615 | case (PH_PULL | REQUEST): |
616 | #ifdef L2FRAME_DEBUG /* psa */ | 616 | #ifdef L2FRAME_DEBUG /* psa */ |
617 | if (cs->debug & L1_DEB_LAPD) | 617 | if (cs->debug & L1_DEB_LAPD) |
618 | debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb) ? "yes" : "no"); | 618 | debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb) ? "yes" : "no"); |
619 | #endif | 619 | #endif |
620 | if (!cs->tx_skb) { | 620 | if (!cs->tx_skb) { |
621 | test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | 621 | test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); |
622 | st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); | 622 | st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); |
623 | } else | 623 | } else |
624 | test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | 624 | test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); |
625 | break; | 625 | break; |
626 | case (HW_RESET | REQUEST): | 626 | case (HW_RESET | REQUEST): |
627 | spin_lock_irqsave(&cs->lock, flags); | 627 | spin_lock_irqsave(&cs->lock, flags); |
628 | if ((cs->dc.amd7930.ph_state == 8)) { | 628 | if ((cs->dc.amd7930.ph_state == 8)) { |
629 | /* b-channels off, PH-AR cleared | 629 | /* b-channels off, PH-AR cleared |
630 | * change to F3 */ | 630 | * change to F3 */ |
631 | Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5 | 631 | Amd7930_ph_command(cs, 0x20, "HW_RESET REQUEST"); //LMR1 bit 5 |
632 | spin_unlock_irqrestore(&cs->lock, flags); | 632 | spin_unlock_irqrestore(&cs->lock, flags); |
633 | } else { | 633 | } else { |
634 | Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST"); | 634 | Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST"); |
635 | cs->dc.amd7930.ph_state = 2; | 635 | cs->dc.amd7930.ph_state = 2; |
636 | spin_unlock_irqrestore(&cs->lock, flags); | 636 | spin_unlock_irqrestore(&cs->lock, flags); |
637 | Amd7930_new_ph(cs); | 637 | Amd7930_new_ph(cs); |
638 | } | 638 | } |
639 | break; | 639 | break; |
640 | case (HW_ENABLE | REQUEST): | 640 | case (HW_ENABLE | REQUEST): |
641 | cs->dc.amd7930.ph_state = 9; | 641 | cs->dc.amd7930.ph_state = 9; |
642 | Amd7930_new_ph(cs); | 642 | Amd7930_new_ph(cs); |
643 | break; | 643 | break; |
644 | case (HW_INFO3 | REQUEST): | 644 | case (HW_INFO3 | REQUEST): |
645 | // automatic | 645 | // automatic |
646 | break; | 646 | break; |
647 | case (HW_TESTLOOP | REQUEST): | 647 | case (HW_TESTLOOP | REQUEST): |
648 | /* not implemented yet */ | 648 | /* not implemented yet */ |
649 | break; | 649 | break; |
650 | case (HW_DEACTIVATE | RESPONSE): | 650 | case (HW_DEACTIVATE | RESPONSE): |
651 | skb_queue_purge(&cs->rq); | 651 | skb_queue_purge(&cs->rq); |
652 | skb_queue_purge(&cs->sq); | 652 | skb_queue_purge(&cs->sq); |
653 | if (cs->tx_skb) { | 653 | if (cs->tx_skb) { |
654 | dev_kfree_skb(cs->tx_skb); | 654 | dev_kfree_skb(cs->tx_skb); |
655 | cs->tx_skb = NULL; | 655 | cs->tx_skb = NULL; |
656 | } | 656 | } |
657 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) | 657 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) |
658 | del_timer(&cs->dbusytimer); | 658 | del_timer(&cs->dbusytimer); |
659 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) | 659 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) |
660 | schedule_event(cs, D_CLEARBUSY); | 660 | schedule_event(cs, D_CLEARBUSY); |
661 | break; | 661 | break; |
662 | default: | 662 | default: |
663 | if (cs->debug & L1_DEB_WARN) | 663 | if (cs->debug & L1_DEB_WARN) |
664 | debugl1(cs, "Amd7930: l1hw: unknown %04x", pr); | 664 | debugl1(cs, "Amd7930: l1hw: unknown %04x", pr); |
665 | break; | 665 | break; |
666 | } | 666 | } |
667 | } | 667 | } |
668 | 668 | ||
669 | static void | 669 | static void |
670 | setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs) | 670 | setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs) |
671 | { | 671 | { |
672 | 672 | ||
673 | if (cs->debug & L1_DEB_ISAC) | 673 | if (cs->debug & L1_DEB_ISAC) |
674 | debugl1(cs, "Amd7930: setstack called"); | 674 | debugl1(cs, "Amd7930: setstack called"); |
675 | 675 | ||
676 | st->l1.l1hw = Amd7930_l1hw; | 676 | st->l1.l1hw = Amd7930_l1hw; |
677 | } | 677 | } |
678 | 678 | ||
679 | 679 | ||
680 | static void | 680 | static void |
681 | DC_Close_Amd7930(struct IsdnCardState *cs) { | 681 | DC_Close_Amd7930(struct IsdnCardState *cs) { |
682 | if (cs->debug & L1_DEB_ISAC) | 682 | if (cs->debug & L1_DEB_ISAC) |
683 | debugl1(cs, "Amd7930: DC_Close called"); | 683 | debugl1(cs, "Amd7930: DC_Close called"); |
684 | } | 684 | } |
685 | 685 | ||
686 | 686 | ||
687 | static void | 687 | static void |
688 | dbusy_timer_handler(struct IsdnCardState *cs) | 688 | dbusy_timer_handler(struct IsdnCardState *cs) |
689 | { | 689 | { |
690 | u_long flags; | 690 | u_long flags; |
691 | struct PStack *stptr; | 691 | struct PStack *stptr; |
692 | WORD dtcr, der; | 692 | WORD dtcr, der; |
693 | BYTE dsr1, dsr2; | 693 | BYTE dsr1, dsr2; |
694 | 694 | ||
695 | 695 | ||
696 | if (cs->debug & L1_DEB_ISAC) | 696 | if (cs->debug & L1_DEB_ISAC) |
697 | debugl1(cs, "Amd7930: dbusy_timer expired!"); | 697 | debugl1(cs, "Amd7930: dbusy_timer expired!"); |
698 | 698 | ||
699 | if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { | 699 | if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { |
700 | spin_lock_irqsave(&cs->lock, flags); | 700 | spin_lock_irqsave(&cs->lock, flags); |
701 | /* D Transmit Byte Count Register: | 701 | /* D Transmit Byte Count Register: |
702 | * Counts down packet's number of Bytes, 0 if packet ready */ | 702 | * Counts down packet's number of Bytes, 0 if packet ready */ |
703 | dtcr = rWordAMD(cs, 0x85); | 703 | dtcr = rWordAMD(cs, 0x85); |
704 | dsr1 = rByteAMD(cs, 0x02); | 704 | dsr1 = rByteAMD(cs, 0x02); |
705 | dsr2 = rByteAMD(cs, 0x07); | 705 | dsr2 = rByteAMD(cs, 0x07); |
706 | der = rWordAMD(cs, 0x03); | 706 | der = rWordAMD(cs, 0x03); |
707 | 707 | ||
708 | if (cs->debug & L1_DEB_ISAC) | 708 | if (cs->debug & L1_DEB_ISAC) |
709 | debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); | 709 | debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); |
710 | 710 | ||
711 | if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ | 711 | if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ |
712 | test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); | 712 | test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); |
713 | stptr = cs->stlist; | 713 | stptr = cs->stlist; |
714 | spin_unlock_irqrestore(&cs->lock, flags); | 714 | spin_unlock_irqrestore(&cs->lock, flags); |
715 | while (stptr != NULL) { | 715 | while (stptr != NULL) { |
716 | stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); | 716 | stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); |
717 | stptr = stptr->next; | 717 | stptr = stptr->next; |
718 | } | 718 | } |
719 | 719 | ||
720 | } else { | 720 | } else { |
721 | /* discard frame; reset transceiver */ | 721 | /* discard frame; reset transceiver */ |
722 | test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); | 722 | test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); |
723 | if (cs->tx_skb) { | 723 | if (cs->tx_skb) { |
724 | dev_kfree_skb_any(cs->tx_skb); | 724 | dev_kfree_skb_any(cs->tx_skb); |
725 | cs->tx_cnt = 0; | 725 | cs->tx_cnt = 0; |
726 | cs->tx_skb = NULL; | 726 | cs->tx_skb = NULL; |
727 | cs->dc.amd7930.tx_xmtlen = 0; | 727 | cs->dc.amd7930.tx_xmtlen = 0; |
728 | } else { | 728 | } else { |
729 | printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n"); | 729 | printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n"); |
730 | debugl1(cs, "Amd7930: D-Channel Busy no skb"); | 730 | debugl1(cs, "Amd7930: D-Channel Busy no skb"); |
731 | 731 | ||
732 | } | 732 | } |
733 | /* Transmitter reset, abort transmit */ | 733 | /* Transmitter reset, abort transmit */ |
734 | wByteAMD(cs, 0x21, 0x82); | 734 | wByteAMD(cs, 0x21, 0x82); |
735 | wByteAMD(cs, 0x21, 0x02); | 735 | wByteAMD(cs, 0x21, 0x02); |
736 | spin_unlock_irqrestore(&cs->lock, flags); | 736 | spin_unlock_irqrestore(&cs->lock, flags); |
737 | cs->irq_func(cs->irq, cs); | 737 | cs->irq_func(cs->irq, cs); |
738 | 738 | ||
739 | if (cs->debug & L1_DEB_ISAC) | 739 | if (cs->debug & L1_DEB_ISAC) |
740 | debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset"); | 740 | debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset"); |
741 | } | 741 | } |
742 | } | 742 | } |
743 | } | 743 | } |
744 | 744 | ||
745 | 745 | ||
746 | 746 | ||
747 | void Amd7930_init(struct IsdnCardState *cs) | 747 | void Amd7930_init(struct IsdnCardState *cs) |
748 | { | 748 | { |
749 | WORD *ptr; | 749 | WORD *ptr; |
750 | BYTE cmd, cnt; | 750 | BYTE cmd, cnt; |
751 | 751 | ||
752 | if (cs->debug & L1_DEB_ISAC) | 752 | if (cs->debug & L1_DEB_ISAC) |
753 | debugl1(cs, "Amd7930: initamd called"); | 753 | debugl1(cs, "Amd7930: initamd called"); |
754 | 754 | ||
755 | cs->dc.amd7930.tx_xmtlen = 0; | 755 | cs->dc.amd7930.tx_xmtlen = 0; |
756 | cs->dc.amd7930.old_state = 0; | 756 | cs->dc.amd7930.old_state = 0; |
757 | cs->dc.amd7930.lmr1 = 0x40; | 757 | cs->dc.amd7930.lmr1 = 0x40; |
758 | cs->dc.amd7930.ph_command = Amd7930_ph_command; | 758 | cs->dc.amd7930.ph_command = Amd7930_ph_command; |
759 | cs->setstack_d = setstack_Amd7930; | 759 | cs->setstack_d = setstack_Amd7930; |
760 | cs->DC_Close = DC_Close_Amd7930; | 760 | cs->DC_Close = DC_Close_Amd7930; |
761 | 761 | ||
762 | /* AMD Initialisation */ | 762 | /* AMD Initialisation */ |
763 | for (ptr = initAMD; *ptr != 0xFFFF; ) { | 763 | for (ptr = initAMD; *ptr != 0xFFFF; ) { |
764 | cmd = LOBYTE(*ptr); | 764 | cmd = LOBYTE(*ptr); |
765 | 765 | ||
766 | /* read */ | 766 | /* read */ |
767 | if (*ptr++ >= 0x100) { | 767 | if (*ptr++ >= 0x100) { |
768 | if (cmd < 8) | 768 | if (cmd < 8) |
769 | /* reset register */ | 769 | /* reset register */ |
770 | rByteAMD(cs, cmd); | 770 | rByteAMD(cs, cmd); |
771 | else { | 771 | else { |
772 | wByteAMD(cs, 0x00, cmd); | 772 | wByteAMD(cs, 0x00, cmd); |
773 | for (cnt = *ptr++; cnt > 0; cnt--) | 773 | for (cnt = *ptr++; cnt > 0; cnt--) |
774 | rByteAMD(cs, 0x01); | 774 | rByteAMD(cs, 0x01); |
775 | } | 775 | } |
776 | } | 776 | } |
777 | /* write */ | 777 | /* write */ |
778 | else if (cmd < 8) | 778 | else if (cmd < 8) |
779 | wByteAMD(cs, cmd, LOBYTE(*ptr++)); | 779 | wByteAMD(cs, cmd, LOBYTE(*ptr++)); |
780 | 780 | ||
781 | else { | 781 | else { |
782 | wByteAMD(cs, 0x00, cmd); | 782 | wByteAMD(cs, 0x00, cmd); |
783 | for (cnt = *ptr++; cnt > 0; cnt--) | 783 | for (cnt = *ptr++; cnt > 0; cnt--) |
784 | wByteAMD(cs, 0x01, LOBYTE(*ptr++)); | 784 | wByteAMD(cs, 0x01, LOBYTE(*ptr++)); |
785 | } | 785 | } |
786 | } | 786 | } |
787 | } | 787 | } |
788 | 788 | ||
789 | void __devinit | 789 | void __devinit |
790 | setup_Amd7930(struct IsdnCardState *cs) | 790 | setup_Amd7930(struct IsdnCardState *cs) |
791 | { | 791 | { |
792 | INIT_WORK(&cs->tqueue, Amd7930_bh); | 792 | INIT_WORK(&cs->tqueue, Amd7930_bh); |
793 | cs->dbusytimer.function = (void *) dbusy_timer_handler; | 793 | cs->dbusytimer.function = (void *) dbusy_timer_handler; |
794 | cs->dbusytimer.data = (long) cs; | 794 | cs->dbusytimer.data = (long) cs; |
795 | init_timer(&cs->dbusytimer); | 795 | init_timer(&cs->dbusytimer); |
796 | } | 796 | } |
797 | 797 |
drivers/isdn/hisax/isar.c
1 | /* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $ | 1 | /* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $ |
2 | * | 2 | * |
3 | * isar.c ISAR (Siemens PSB 7110) specific routines | 3 | * isar.c ISAR (Siemens PSB 7110) specific routines |
4 | * | 4 | * |
5 | * Author Karsten Keil (keil@isdn4linux.de) | 5 | * Author Karsten Keil (keil@isdn4linux.de) |
6 | * | 6 | * |
7 | * This file is (c) under GNU General Public License | 7 | * This file is (c) under GNU General Public License |
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include "hisax.h" | 12 | #include "hisax.h" |
13 | #include "isar.h" | 13 | #include "isar.h" |
14 | #include "isdnl1.h" | 14 | #include "isdnl1.h" |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | #define DBG_LOADFIRM 0 | 18 | #define DBG_LOADFIRM 0 |
19 | #define DUMP_MBOXFRAME 2 | 19 | #define DUMP_MBOXFRAME 2 |
20 | 20 | ||
21 | #define DLE 0x10 | 21 | #define DLE 0x10 |
22 | #define ETX 0x03 | 22 | #define ETX 0x03 |
23 | 23 | ||
24 | #define FAXMODCNT 13 | 24 | #define FAXMODCNT 13 |
25 | static const u_char faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121, 122, 145, 146}; | 25 | static const u_char faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121, 122, 145, 146}; |
26 | static u_int modmask = 0x1fff; | 26 | static u_int modmask = 0x1fff; |
27 | static int frm_extra_delay = 2; | 27 | static int frm_extra_delay = 2; |
28 | static int para_TOA = 6; | 28 | static int para_TOA = 6; |
29 | static const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL"}; | 29 | static const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL"}; |
30 | 30 | ||
31 | static void isar_setup(struct IsdnCardState *cs); | 31 | static void isar_setup(struct IsdnCardState *cs); |
32 | static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para); | 32 | static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para); |
33 | static void ll_deliver_faxstat(struct BCState *bcs, u_char status); | 33 | static void ll_deliver_faxstat(struct BCState *bcs, u_char status); |
34 | 34 | ||
35 | static inline int | 35 | static inline int |
36 | waitforHIA(struct IsdnCardState *cs, int timeout) | 36 | waitforHIA(struct IsdnCardState *cs, int timeout) |
37 | { | 37 | { |
38 | 38 | ||
39 | while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) { | 39 | while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) { |
40 | udelay(1); | 40 | udelay(1); |
41 | timeout--; | 41 | timeout--; |
42 | } | 42 | } |
43 | if (!timeout) | 43 | if (!timeout) |
44 | printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n"); | 44 | printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n"); |
45 | return (timeout); | 45 | return (timeout); |
46 | } | 46 | } |
47 | 47 | ||
48 | 48 | ||
49 | static int | 49 | static int |
50 | sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len, | 50 | sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len, |
51 | u_char *msg) | 51 | u_char *msg) |
52 | { | 52 | { |
53 | int i; | 53 | int i; |
54 | 54 | ||
55 | if (!waitforHIA(cs, 4000)) | 55 | if (!waitforHIA(cs, 4000)) |
56 | return (0); | 56 | return (0); |
57 | #if DUMP_MBOXFRAME | 57 | #if DUMP_MBOXFRAME |
58 | if (cs->debug & L1_DEB_HSCX) | 58 | if (cs->debug & L1_DEB_HSCX) |
59 | debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len); | 59 | debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len); |
60 | #endif | 60 | #endif |
61 | cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg); | 61 | cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg); |
62 | cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len); | 62 | cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len); |
63 | cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0); | 63 | cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0); |
64 | if (msg && len) { | 64 | if (msg && len) { |
65 | cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]); | 65 | cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]); |
66 | for (i = 1; i < len; i++) | 66 | for (i = 1; i < len; i++) |
67 | cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]); | 67 | cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]); |
68 | #if DUMP_MBOXFRAME > 1 | 68 | #if DUMP_MBOXFRAME > 1 |
69 | if (cs->debug & L1_DEB_HSCX_FIFO) { | 69 | if (cs->debug & L1_DEB_HSCX_FIFO) { |
70 | char tmp[256], *t; | 70 | char tmp[256], *t; |
71 | 71 | ||
72 | i = len; | 72 | i = len; |
73 | while (i > 0) { | 73 | while (i > 0) { |
74 | t = tmp; | 74 | t = tmp; |
75 | t += sprintf(t, "sendmbox cnt %d", len); | 75 | t += sprintf(t, "sendmbox cnt %d", len); |
76 | QuickHex(t, &msg[len-i], (i > 64) ? 64 : i); | 76 | QuickHex(t, &msg[len-i], (i > 64) ? 64 : i); |
77 | debugl1(cs, tmp); | 77 | debugl1(cs, tmp); |
78 | i -= 64; | 78 | i -= 64; |
79 | } | 79 | } |
80 | } | 80 | } |
81 | #endif | 81 | #endif |
82 | } | 82 | } |
83 | cs->BC_Write_Reg(cs, 1, ISAR_HIS, his); | 83 | cs->BC_Write_Reg(cs, 1, ISAR_HIS, his); |
84 | waitforHIA(cs, 10000); | 84 | waitforHIA(cs, 10000); |
85 | return (1); | 85 | return (1); |
86 | } | 86 | } |
87 | 87 | ||
88 | /* Call only with IRQ disabled !!! */ | 88 | /* Call only with IRQ disabled !!! */ |
89 | static inline void | 89 | static inline void |
90 | rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg) | 90 | rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg) |
91 | { | 91 | { |
92 | int i; | 92 | int i; |
93 | 93 | ||
94 | cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0); | 94 | cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0); |
95 | if (msg && ireg->clsb) { | 95 | if (msg && ireg->clsb) { |
96 | msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX); | 96 | msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX); |
97 | for (i = 1; i < ireg->clsb; i++) | 97 | for (i = 1; i < ireg->clsb; i++) |
98 | msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX); | 98 | msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX); |
99 | #if DUMP_MBOXFRAME > 1 | 99 | #if DUMP_MBOXFRAME > 1 |
100 | if (cs->debug & L1_DEB_HSCX_FIFO) { | 100 | if (cs->debug & L1_DEB_HSCX_FIFO) { |
101 | char tmp[256], *t; | 101 | char tmp[256], *t; |
102 | 102 | ||
103 | i = ireg->clsb; | 103 | i = ireg->clsb; |
104 | while (i > 0) { | 104 | while (i > 0) { |
105 | t = tmp; | 105 | t = tmp; |
106 | t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb); | 106 | t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb); |
107 | QuickHex(t, &msg[ireg->clsb - i], (i > 64) ? 64 : i); | 107 | QuickHex(t, &msg[ireg->clsb - i], (i > 64) ? 64 : i); |
108 | debugl1(cs, tmp); | 108 | debugl1(cs, tmp); |
109 | i -= 64; | 109 | i -= 64; |
110 | } | 110 | } |
111 | } | 111 | } |
112 | #endif | 112 | #endif |
113 | } | 113 | } |
114 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 114 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
115 | } | 115 | } |
116 | 116 | ||
117 | /* Call only with IRQ disabled !!! */ | 117 | /* Call only with IRQ disabled !!! */ |
118 | static inline void | 118 | static inline void |
119 | get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg) | 119 | get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg) |
120 | { | 120 | { |
121 | ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS); | 121 | ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS); |
122 | ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H); | 122 | ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H); |
123 | ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L); | 123 | ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L); |
124 | #if DUMP_MBOXFRAME | 124 | #if DUMP_MBOXFRAME |
125 | if (cs->debug & L1_DEB_HSCX) | 125 | if (cs->debug & L1_DEB_HSCX) |
126 | debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb, | 126 | debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb, |
127 | ireg->clsb); | 127 | ireg->clsb); |
128 | #endif | 128 | #endif |
129 | } | 129 | } |
130 | 130 | ||
131 | static int | 131 | static int |
132 | waitrecmsg(struct IsdnCardState *cs, u_char *len, | 132 | waitrecmsg(struct IsdnCardState *cs, u_char *len, |
133 | u_char *msg, int maxdelay) | 133 | u_char *msg, int maxdelay) |
134 | { | 134 | { |
135 | int timeout = 0; | 135 | int timeout = 0; |
136 | struct isar_reg *ir = cs->bcs[0].hw.isar.reg; | 136 | struct isar_reg *ir = cs->bcs[0].hw.isar.reg; |
137 | 137 | ||
138 | 138 | ||
139 | while ((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && | 139 | while ((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && |
140 | (timeout++ < maxdelay)) | 140 | (timeout++ < maxdelay)) |
141 | udelay(1); | 141 | udelay(1); |
142 | if (timeout > maxdelay) { | 142 | if (timeout > maxdelay) { |
143 | printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); | 143 | printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); |
144 | return (0); | 144 | return (0); |
145 | } | 145 | } |
146 | get_irq_infos(cs, ir); | 146 | get_irq_infos(cs, ir); |
147 | rcv_mbox(cs, ir, msg); | 147 | rcv_mbox(cs, ir, msg); |
148 | *len = ir->clsb; | 148 | *len = ir->clsb; |
149 | return (1); | 149 | return (1); |
150 | } | 150 | } |
151 | 151 | ||
152 | int | 152 | int |
153 | ISARVersion(struct IsdnCardState *cs, char *s) | 153 | ISARVersion(struct IsdnCardState *cs, char *s) |
154 | { | 154 | { |
155 | int ver; | 155 | int ver; |
156 | u_char msg[] = ISAR_MSG_HWVER; | 156 | u_char msg[] = ISAR_MSG_HWVER; |
157 | u_char tmp[64]; | 157 | u_char tmp[64]; |
158 | u_char len; | 158 | u_char len; |
159 | u_long flags; | 159 | u_long flags; |
160 | int debug; | 160 | int debug; |
161 | 161 | ||
162 | cs->cardmsg(cs, CARD_RESET, NULL); | 162 | cs->cardmsg(cs, CARD_RESET, NULL); |
163 | spin_lock_irqsave(&cs->lock, flags); | 163 | spin_lock_irqsave(&cs->lock, flags); |
164 | /* disable ISAR IRQ */ | 164 | /* disable ISAR IRQ */ |
165 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); | 165 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); |
166 | debug = cs->debug; | 166 | debug = cs->debug; |
167 | cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); | 167 | cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); |
168 | if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) { | 168 | if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) { |
169 | spin_unlock_irqrestore(&cs->lock, flags); | 169 | spin_unlock_irqrestore(&cs->lock, flags); |
170 | return (-1); | 170 | return (-1); |
171 | } | 171 | } |
172 | if (!waitrecmsg(cs, &len, tmp, 100000)) { | 172 | if (!waitrecmsg(cs, &len, tmp, 100000)) { |
173 | spin_unlock_irqrestore(&cs->lock, flags); | 173 | spin_unlock_irqrestore(&cs->lock, flags); |
174 | return (-2); | 174 | return (-2); |
175 | } | 175 | } |
176 | cs->debug = debug; | 176 | cs->debug = debug; |
177 | if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) { | 177 | if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) { |
178 | if (len == 1) { | 178 | if (len == 1) { |
179 | ver = tmp[0] & 0xf; | 179 | ver = tmp[0] & 0xf; |
180 | printk(KERN_INFO "%s ISAR version %d\n", s, ver); | 180 | printk(KERN_INFO "%s ISAR version %d\n", s, ver); |
181 | } else | 181 | } else |
182 | ver = -3; | 182 | ver = -3; |
183 | } else | 183 | } else |
184 | ver = -4; | 184 | ver = -4; |
185 | spin_unlock_irqrestore(&cs->lock, flags); | 185 | spin_unlock_irqrestore(&cs->lock, flags); |
186 | return (ver); | 186 | return (ver); |
187 | } | 187 | } |
188 | 188 | ||
189 | static int | 189 | static int |
190 | isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf) | 190 | isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf) |
191 | { | 191 | { |
192 | int cfu_ret, ret, size, cnt, debug; | 192 | int cfu_ret, ret, size, cnt, debug; |
193 | u_char len, nom, noc; | 193 | u_char len, nom, noc; |
194 | u_short sadr, left, *sp; | 194 | u_short sadr, left, *sp; |
195 | u_char __user *p = buf; | 195 | u_char __user *p = buf; |
196 | u_char *msg, *tmpmsg, *mp, tmp[64]; | 196 | u_char *msg, *tmpmsg, *mp, tmp[64]; |
197 | u_long flags; | 197 | u_long flags; |
198 | struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; | 198 | struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; |
199 | 199 | ||
200 | struct {u_short sadr; | 200 | struct {u_short sadr; |
201 | u_short len; | 201 | u_short len; |
202 | u_short d_key; | 202 | u_short d_key; |
203 | } blk_head; | 203 | } blk_head; |
204 | 204 | ||
205 | #define BLK_HEAD_SIZE 6 | 205 | #define BLK_HEAD_SIZE 6 |
206 | if (1 != (ret = ISARVersion(cs, "Testing"))) { | 206 | if (1 != (ret = ISARVersion(cs, "Testing"))) { |
207 | printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret); | 207 | printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret); |
208 | return (1); | 208 | return (1); |
209 | } | 209 | } |
210 | debug = cs->debug; | 210 | debug = cs->debug; |
211 | #if DBG_LOADFIRM < 2 | 211 | #if DBG_LOADFIRM < 2 |
212 | cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); | 212 | cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); |
213 | #endif | 213 | #endif |
214 | 214 | ||
215 | cfu_ret = copy_from_user(&size, p, sizeof(int)); | 215 | cfu_ret = copy_from_user(&size, p, sizeof(int)); |
216 | if (cfu_ret) { | 216 | if (cfu_ret) { |
217 | printk(KERN_ERR "isar_load_firmware copy_from_user ret %d\n", cfu_ret); | 217 | printk(KERN_ERR "isar_load_firmware copy_from_user ret %d\n", cfu_ret); |
218 | return -EFAULT; | 218 | return -EFAULT; |
219 | } | 219 | } |
220 | p += sizeof(int); | 220 | p += sizeof(int); |
221 | printk(KERN_DEBUG"isar_load_firmware size: %d\n", size); | 221 | printk(KERN_DEBUG"isar_load_firmware size: %d\n", size); |
222 | cnt = 0; | 222 | cnt = 0; |
223 | /* disable ISAR IRQ */ | 223 | /* disable ISAR IRQ */ |
224 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); | 224 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); |
225 | if (!(msg = kmalloc(256, GFP_KERNEL))) { | 225 | if (!(msg = kmalloc(256, GFP_KERNEL))) { |
226 | printk(KERN_ERR"isar_load_firmware no buffer\n"); | 226 | printk(KERN_ERR"isar_load_firmware no buffer\n"); |
227 | return (1); | 227 | return (1); |
228 | } | 228 | } |
229 | if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) { | 229 | if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) { |
230 | printk(KERN_ERR"isar_load_firmware no tmp buffer\n"); | 230 | printk(KERN_ERR"isar_load_firmware no tmp buffer\n"); |
231 | kfree(msg); | 231 | kfree(msg); |
232 | return (1); | 232 | return (1); |
233 | } | 233 | } |
234 | spin_lock_irqsave(&cs->lock, flags); | 234 | spin_lock_irqsave(&cs->lock, flags); |
235 | /* disable ISAR IRQ */ | 235 | /* disable ISAR IRQ */ |
236 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); | 236 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); |
237 | spin_unlock_irqrestore(&cs->lock, flags); | 237 | spin_unlock_irqrestore(&cs->lock, flags); |
238 | while (cnt < size) { | 238 | while (cnt < size) { |
239 | if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) { | 239 | if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) { |
240 | printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); | 240 | printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); |
241 | goto reterror; | 241 | goto reterror; |
242 | } | 242 | } |
243 | #ifdef __BIG_ENDIAN | 243 | #ifdef __BIG_ENDIAN |
244 | sadr = (blk_head.sadr & 0xff) * 256 + blk_head.sadr / 256; | 244 | sadr = (blk_head.sadr & 0xff) * 256 + blk_head.sadr / 256; |
245 | blk_head.sadr = sadr; | 245 | blk_head.sadr = sadr; |
246 | sadr = (blk_head.len & 0xff) * 256 + blk_head.len / 256; | 246 | sadr = (blk_head.len & 0xff) * 256 + blk_head.len / 256; |
247 | blk_head.len = sadr; | 247 | blk_head.len = sadr; |
248 | sadr = (blk_head.d_key & 0xff) * 256 + blk_head.d_key / 256; | 248 | sadr = (blk_head.d_key & 0xff) * 256 + blk_head.d_key / 256; |
249 | blk_head.d_key = sadr; | 249 | blk_head.d_key = sadr; |
250 | #endif /* __BIG_ENDIAN */ | 250 | #endif /* __BIG_ENDIAN */ |
251 | cnt += BLK_HEAD_SIZE; | 251 | cnt += BLK_HEAD_SIZE; |
252 | p += BLK_HEAD_SIZE; | 252 | p += BLK_HEAD_SIZE; |
253 | printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n", | 253 | printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n", |
254 | blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); | 254 | blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); |
255 | sadr = blk_head.sadr; | 255 | sadr = blk_head.sadr; |
256 | left = blk_head.len; | 256 | left = blk_head.len; |
257 | spin_lock_irqsave(&cs->lock, flags); | 257 | spin_lock_irqsave(&cs->lock, flags); |
258 | if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) { | 258 | if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) { |
259 | printk(KERN_ERR"isar sendmsg dkey failed\n"); | 259 | printk(KERN_ERR"isar sendmsg dkey failed\n"); |
260 | ret = 1; goto reterr_unlock; | 260 | ret = 1; goto reterr_unlock; |
261 | } | 261 | } |
262 | if (!waitrecmsg(cs, &len, tmp, 100000)) { | 262 | if (!waitrecmsg(cs, &len, tmp, 100000)) { |
263 | printk(KERN_ERR"isar waitrecmsg dkey failed\n"); | 263 | printk(KERN_ERR"isar waitrecmsg dkey failed\n"); |
264 | ret = 1; goto reterr_unlock; | 264 | ret = 1; goto reterr_unlock; |
265 | } | 265 | } |
266 | if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) { | 266 | if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) { |
267 | printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n", | 267 | printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n", |
268 | ireg->iis, ireg->cmsb, len); | 268 | ireg->iis, ireg->cmsb, len); |
269 | ret = 1; goto reterr_unlock; | 269 | ret = 1; goto reterr_unlock; |
270 | } | 270 | } |
271 | spin_unlock_irqrestore(&cs->lock, flags); | 271 | spin_unlock_irqrestore(&cs->lock, flags); |
272 | while (left > 0) { | 272 | while (left > 0) { |
273 | if (left > 126) | 273 | if (left > 126) |
274 | noc = 126; | 274 | noc = 126; |
275 | else | 275 | else |
276 | noc = left; | 276 | noc = left; |
277 | nom = 2 * noc; | 277 | nom = 2 * noc; |
278 | mp = msg; | 278 | mp = msg; |
279 | *mp++ = sadr / 256; | 279 | *mp++ = sadr / 256; |
280 | *mp++ = sadr % 256; | 280 | *mp++ = sadr % 256; |
281 | left -= noc; | 281 | left -= noc; |
282 | *mp++ = noc; | 282 | *mp++ = noc; |
283 | if ((ret = copy_from_user(tmpmsg, p, nom))) { | 283 | if ((ret = copy_from_user(tmpmsg, p, nom))) { |
284 | printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); | 284 | printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); |
285 | goto reterror; | 285 | goto reterror; |
286 | } | 286 | } |
287 | p += nom; | 287 | p += nom; |
288 | cnt += nom; | 288 | cnt += nom; |
289 | nom += 3; | 289 | nom += 3; |
290 | sp = (u_short *)tmpmsg; | 290 | sp = (u_short *)tmpmsg; |
291 | #if DBG_LOADFIRM | 291 | #if DBG_LOADFIRM |
292 | printk(KERN_DEBUG"isar: load %3d words at %04x left %d\n", | 292 | printk(KERN_DEBUG"isar: load %3d words at %04x left %d\n", |
293 | noc, sadr, left); | 293 | noc, sadr, left); |
294 | #endif | 294 | #endif |
295 | sadr += noc; | 295 | sadr += noc; |
296 | while (noc) { | 296 | while (noc) { |
297 | #ifdef __BIG_ENDIAN | 297 | #ifdef __BIG_ENDIAN |
298 | *mp++ = *sp % 256; | 298 | *mp++ = *sp % 256; |
299 | *mp++ = *sp / 256; | 299 | *mp++ = *sp / 256; |
300 | #else | 300 | #else |
301 | *mp++ = *sp / 256; | 301 | *mp++ = *sp / 256; |
302 | *mp++ = *sp % 256; | 302 | *mp++ = *sp % 256; |
303 | #endif /* __BIG_ENDIAN */ | 303 | #endif /* __BIG_ENDIAN */ |
304 | sp++; | 304 | sp++; |
305 | noc--; | 305 | noc--; |
306 | } | 306 | } |
307 | spin_lock_irqsave(&cs->lock, flags); | 307 | spin_lock_irqsave(&cs->lock, flags); |
308 | if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) { | 308 | if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) { |
309 | printk(KERN_ERR"isar sendmsg prog failed\n"); | 309 | printk(KERN_ERR"isar sendmsg prog failed\n"); |
310 | ret = 1; goto reterr_unlock; | 310 | ret = 1; goto reterr_unlock; |
311 | } | 311 | } |
312 | if (!waitrecmsg(cs, &len, tmp, 100000)) { | 312 | if (!waitrecmsg(cs, &len, tmp, 100000)) { |
313 | printk(KERN_ERR"isar waitrecmsg prog failed\n"); | 313 | printk(KERN_ERR"isar waitrecmsg prog failed\n"); |
314 | ret = 1; goto reterr_unlock; | 314 | ret = 1; goto reterr_unlock; |
315 | } | 315 | } |
316 | if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) { | 316 | if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) { |
317 | printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n", | 317 | printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n", |
318 | ireg->iis, ireg->cmsb, len); | 318 | ireg->iis, ireg->cmsb, len); |
319 | ret = 1; goto reterr_unlock; | 319 | ret = 1; goto reterr_unlock; |
320 | } | 320 | } |
321 | spin_unlock_irqrestore(&cs->lock, flags); | 321 | spin_unlock_irqrestore(&cs->lock, flags); |
322 | } | 322 | } |
323 | printk(KERN_DEBUG"isar firmware block %5d words loaded\n", | 323 | printk(KERN_DEBUG"isar firmware block %5d words loaded\n", |
324 | blk_head.len); | 324 | blk_head.len); |
325 | } | 325 | } |
326 | /* 10ms delay */ | 326 | /* 10ms delay */ |
327 | cnt = 10; | 327 | cnt = 10; |
328 | while (cnt--) | 328 | while (cnt--) |
329 | udelay(1000); | 329 | udelay(1000); |
330 | msg[0] = 0xff; | 330 | msg[0] = 0xff; |
331 | msg[1] = 0xfe; | 331 | msg[1] = 0xfe; |
332 | ireg->bstat = 0; | 332 | ireg->bstat = 0; |
333 | spin_lock_irqsave(&cs->lock, flags); | 333 | spin_lock_irqsave(&cs->lock, flags); |
334 | if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) { | 334 | if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) { |
335 | printk(KERN_ERR"isar sendmsg start dsp failed\n"); | 335 | printk(KERN_ERR"isar sendmsg start dsp failed\n"); |
336 | ret = 1; goto reterr_unlock; | 336 | ret = 1; goto reterr_unlock; |
337 | } | 337 | } |
338 | if (!waitrecmsg(cs, &len, tmp, 100000)) { | 338 | if (!waitrecmsg(cs, &len, tmp, 100000)) { |
339 | printk(KERN_ERR"isar waitrecmsg start dsp failed\n"); | 339 | printk(KERN_ERR"isar waitrecmsg start dsp failed\n"); |
340 | ret = 1; goto reterr_unlock; | 340 | ret = 1; goto reterr_unlock; |
341 | } | 341 | } |
342 | if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) { | 342 | if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) { |
343 | printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n", | 343 | printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n", |
344 | ireg->iis, ireg->cmsb, len); | 344 | ireg->iis, ireg->cmsb, len); |
345 | ret = 1; goto reterr_unlock; | 345 | ret = 1; goto reterr_unlock; |
346 | } else | 346 | } else |
347 | printk(KERN_DEBUG"isar start dsp success\n"); | 347 | printk(KERN_DEBUG"isar start dsp success\n"); |
348 | /* NORMAL mode entered */ | 348 | /* NORMAL mode entered */ |
349 | /* Enable IRQs of ISAR */ | 349 | /* Enable IRQs of ISAR */ |
350 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); | 350 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); |
351 | spin_unlock_irqrestore(&cs->lock, flags); | 351 | spin_unlock_irqrestore(&cs->lock, flags); |
352 | cnt = 1000; /* max 1s */ | 352 | cnt = 1000; /* max 1s */ |
353 | while ((!ireg->bstat) && cnt) { | 353 | while ((!ireg->bstat) && cnt) { |
354 | udelay(1000); | 354 | udelay(1000); |
355 | cnt--; | 355 | cnt--; |
356 | } | 356 | } |
357 | if (!cnt) { | 357 | if (!cnt) { |
358 | printk(KERN_ERR"isar no general status event received\n"); | 358 | printk(KERN_ERR"isar no general status event received\n"); |
359 | ret = 1; goto reterror; | 359 | ret = 1; goto reterror; |
360 | } else { | 360 | } else { |
361 | printk(KERN_DEBUG"isar general status event %x\n", | 361 | printk(KERN_DEBUG"isar general status event %x\n", |
362 | ireg->bstat); | 362 | ireg->bstat); |
363 | } | 363 | } |
364 | /* 10ms delay */ | 364 | /* 10ms delay */ |
365 | cnt = 10; | 365 | cnt = 10; |
366 | while (cnt--) | 366 | while (cnt--) |
367 | udelay(1000); | 367 | udelay(1000); |
368 | spin_lock_irqsave(&cs->lock, flags); | 368 | spin_lock_irqsave(&cs->lock, flags); |
369 | ireg->iis = 0; | 369 | ireg->iis = 0; |
370 | if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { | 370 | if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { |
371 | printk(KERN_ERR"isar sendmsg self tst failed\n"); | 371 | printk(KERN_ERR"isar sendmsg self tst failed\n"); |
372 | ret = 1; goto reterr_unlock; | 372 | ret = 1; goto reterr_unlock; |
373 | } | 373 | } |
374 | cnt = 10000; /* max 100 ms */ | 374 | cnt = 10000; /* max 100 ms */ |
375 | spin_unlock_irqrestore(&cs->lock, flags); | 375 | spin_unlock_irqrestore(&cs->lock, flags); |
376 | while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { | 376 | while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { |
377 | udelay(10); | 377 | udelay(10); |
378 | cnt--; | 378 | cnt--; |
379 | } | 379 | } |
380 | udelay(1000); | 380 | udelay(1000); |
381 | if (!cnt) { | 381 | if (!cnt) { |
382 | printk(KERN_ERR"isar no self tst response\n"); | 382 | printk(KERN_ERR"isar no self tst response\n"); |
383 | ret = 1; goto reterror; | 383 | ret = 1; goto reterror; |
384 | } | 384 | } |
385 | if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1) | 385 | if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1) |
386 | && (ireg->par[0] == 0)) { | 386 | && (ireg->par[0] == 0)) { |
387 | printk(KERN_DEBUG"isar selftest OK\n"); | 387 | printk(KERN_DEBUG"isar selftest OK\n"); |
388 | } else { | 388 | } else { |
389 | printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n", | 389 | printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n", |
390 | ireg->cmsb, ireg->clsb, ireg->par[0]); | 390 | ireg->cmsb, ireg->clsb, ireg->par[0]); |
391 | ret = 1; goto reterror; | 391 | ret = 1; goto reterror; |
392 | } | 392 | } |
393 | spin_lock_irqsave(&cs->lock, flags); | 393 | spin_lock_irqsave(&cs->lock, flags); |
394 | ireg->iis = 0; | 394 | ireg->iis = 0; |
395 | if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { | 395 | if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { |
396 | printk(KERN_ERR"isar RQST SVN failed\n"); | 396 | printk(KERN_ERR"isar RQST SVN failed\n"); |
397 | ret = 1; goto reterr_unlock; | 397 | ret = 1; goto reterr_unlock; |
398 | } | 398 | } |
399 | spin_unlock_irqrestore(&cs->lock, flags); | 399 | spin_unlock_irqrestore(&cs->lock, flags); |
400 | cnt = 30000; /* max 300 ms */ | 400 | cnt = 30000; /* max 300 ms */ |
401 | while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { | 401 | while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { |
402 | udelay(10); | 402 | udelay(10); |
403 | cnt--; | 403 | cnt--; |
404 | } | 404 | } |
405 | udelay(1000); | 405 | udelay(1000); |
406 | if (!cnt) { | 406 | if (!cnt) { |
407 | printk(KERN_ERR"isar no SVN response\n"); | 407 | printk(KERN_ERR"isar no SVN response\n"); |
408 | ret = 1; goto reterror; | 408 | ret = 1; goto reterror; |
409 | } else { | 409 | } else { |
410 | if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1)) | 410 | if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1)) |
411 | printk(KERN_DEBUG"isar software version %#x\n", | 411 | printk(KERN_DEBUG"isar software version %#x\n", |
412 | ireg->par[0]); | 412 | ireg->par[0]); |
413 | else { | 413 | else { |
414 | printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n", | 414 | printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n", |
415 | ireg->cmsb, ireg->clsb, cnt); | 415 | ireg->cmsb, ireg->clsb, cnt); |
416 | ret = 1; goto reterror; | 416 | ret = 1; goto reterror; |
417 | } | 417 | } |
418 | } | 418 | } |
419 | spin_lock_irqsave(&cs->lock, flags); | 419 | spin_lock_irqsave(&cs->lock, flags); |
420 | cs->debug = debug; | 420 | cs->debug = debug; |
421 | isar_setup(cs); | 421 | isar_setup(cs); |
422 | 422 | ||
423 | ret = 0; | 423 | ret = 0; |
424 | reterr_unlock: | 424 | reterr_unlock: |
425 | spin_unlock_irqrestore(&cs->lock, flags); | 425 | spin_unlock_irqrestore(&cs->lock, flags); |
426 | reterror: | 426 | reterror: |
427 | cs->debug = debug; | 427 | cs->debug = debug; |
428 | if (ret) | 428 | if (ret) |
429 | /* disable ISAR IRQ */ | 429 | /* disable ISAR IRQ */ |
430 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); | 430 | cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); |
431 | kfree(msg); | 431 | kfree(msg); |
432 | kfree(tmpmsg); | 432 | kfree(tmpmsg); |
433 | return (ret); | 433 | return (ret); |
434 | } | 434 | } |
435 | 435 | ||
436 | #define B_LL_NOCARRIER 8 | 436 | #define B_LL_NOCARRIER 8 |
437 | #define B_LL_CONNECT 9 | 437 | #define B_LL_CONNECT 9 |
438 | #define B_LL_OK 10 | 438 | #define B_LL_OK 10 |
439 | 439 | ||
440 | static void | 440 | static void |
441 | isar_bh(struct work_struct *work) | 441 | isar_bh(struct work_struct *work) |
442 | { | 442 | { |
443 | struct BCState *bcs = container_of(work, struct BCState, tqueue); | 443 | struct BCState *bcs = container_of(work, struct BCState, tqueue); |
444 | 444 | ||
445 | BChannel_bh(work); | 445 | BChannel_bh(work); |
446 | if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) | 446 | if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) |
447 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); | 447 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); |
448 | if (test_and_clear_bit(B_LL_CONNECT, &bcs->event)) | 448 | if (test_and_clear_bit(B_LL_CONNECT, &bcs->event)) |
449 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); | 449 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); |
450 | if (test_and_clear_bit(B_LL_OK, &bcs->event)) | 450 | if (test_and_clear_bit(B_LL_OK, &bcs->event)) |
451 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK); | 451 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK); |
452 | } | 452 | } |
453 | 453 | ||
454 | static void | 454 | static void |
455 | send_DLE_ETX(struct BCState *bcs) | 455 | send_DLE_ETX(struct BCState *bcs) |
456 | { | 456 | { |
457 | u_char dleetx[2] = {DLE, ETX}; | 457 | u_char dleetx[2] = {DLE, ETX}; |
458 | struct sk_buff *skb; | 458 | struct sk_buff *skb; |
459 | 459 | ||
460 | if ((skb = dev_alloc_skb(2))) { | 460 | if ((skb = dev_alloc_skb(2))) { |
461 | memcpy(skb_put(skb, 2), dleetx, 2); | 461 | memcpy(skb_put(skb, 2), dleetx, 2); |
462 | skb_queue_tail(&bcs->rqueue, skb); | 462 | skb_queue_tail(&bcs->rqueue, skb); |
463 | schedule_event(bcs, B_RCVBUFREADY); | 463 | schedule_event(bcs, B_RCVBUFREADY); |
464 | } else { | 464 | } else { |
465 | printk(KERN_WARNING "HiSax: skb out of memory\n"); | 465 | printk(KERN_WARNING "HiSax: skb out of memory\n"); |
466 | } | 466 | } |
467 | } | 467 | } |
468 | 468 | ||
469 | static inline int | 469 | static inline int |
470 | dle_count(unsigned char *buf, int len) | 470 | dle_count(unsigned char *buf, int len) |
471 | { | 471 | { |
472 | int count = 0; | 472 | int count = 0; |
473 | 473 | ||
474 | while (len--) | 474 | while (len--) |
475 | if (*buf++ == DLE) | 475 | if (*buf++ == DLE) |
476 | count++; | 476 | count++; |
477 | return count; | 477 | return count; |
478 | } | 478 | } |
479 | 479 | ||
480 | static inline void | 480 | static inline void |
481 | insert_dle(unsigned char *dest, unsigned char *src, int count) { | 481 | insert_dle(unsigned char *dest, unsigned char *src, int count) { |
482 | /* <DLE> in input stream have to be flagged as <DLE><DLE> */ | 482 | /* <DLE> in input stream have to be flagged as <DLE><DLE> */ |
483 | while (count--) { | 483 | while (count--) { |
484 | *dest++ = *src; | 484 | *dest++ = *src; |
485 | if (*src++ == DLE) | 485 | if (*src++ == DLE) |
486 | *dest++ = DLE; | 486 | *dest++ = DLE; |
487 | } | 487 | } |
488 | } | 488 | } |
489 | 489 | ||
490 | static void | 490 | static void |
491 | isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) | 491 | isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) |
492 | { | 492 | { |
493 | u_char *ptr; | 493 | u_char *ptr; |
494 | struct sk_buff *skb; | 494 | struct sk_buff *skb; |
495 | struct isar_reg *ireg = bcs->hw.isar.reg; | 495 | struct isar_reg *ireg = bcs->hw.isar.reg; |
496 | 496 | ||
497 | if (!ireg->clsb) { | 497 | if (!ireg->clsb) { |
498 | debugl1(cs, "isar zero len frame"); | 498 | debugl1(cs, "isar zero len frame"); |
499 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 499 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
500 | return; | 500 | return; |
501 | } | 501 | } |
502 | switch (bcs->mode) { | 502 | switch (bcs->mode) { |
503 | case L1_MODE_NULL: | 503 | case L1_MODE_NULL: |
504 | debugl1(cs, "isar mode 0 spurious IIS_RDATA %x/%x/%x", | 504 | debugl1(cs, "isar mode 0 spurious IIS_RDATA %x/%x/%x", |
505 | ireg->iis, ireg->cmsb, ireg->clsb); | 505 | ireg->iis, ireg->cmsb, ireg->clsb); |
506 | printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n", | 506 | printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n", |
507 | ireg->iis, ireg->cmsb, ireg->clsb); | 507 | ireg->iis, ireg->cmsb, ireg->clsb); |
508 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 508 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
509 | break; | 509 | break; |
510 | case L1_MODE_TRANS: | 510 | case L1_MODE_TRANS: |
511 | case L1_MODE_V32: | 511 | case L1_MODE_V32: |
512 | if ((skb = dev_alloc_skb(ireg->clsb))) { | 512 | if ((skb = dev_alloc_skb(ireg->clsb))) { |
513 | rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); | 513 | rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); |
514 | skb_queue_tail(&bcs->rqueue, skb); | 514 | skb_queue_tail(&bcs->rqueue, skb); |
515 | schedule_event(bcs, B_RCVBUFREADY); | 515 | schedule_event(bcs, B_RCVBUFREADY); |
516 | } else { | 516 | } else { |
517 | printk(KERN_WARNING "HiSax: skb out of memory\n"); | 517 | printk(KERN_WARNING "HiSax: skb out of memory\n"); |
518 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 518 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
519 | } | 519 | } |
520 | break; | 520 | break; |
521 | case L1_MODE_HDLC: | 521 | case L1_MODE_HDLC: |
522 | if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { | 522 | if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { |
523 | if (cs->debug & L1_DEB_WARN) | 523 | if (cs->debug & L1_DEB_WARN) |
524 | debugl1(cs, "isar_rcv_frame: incoming packet too large"); | 524 | debugl1(cs, "isar_rcv_frame: incoming packet too large"); |
525 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 525 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
526 | bcs->hw.isar.rcvidx = 0; | 526 | bcs->hw.isar.rcvidx = 0; |
527 | } else if (ireg->cmsb & HDLC_ERROR) { | 527 | } else if (ireg->cmsb & HDLC_ERROR) { |
528 | if (cs->debug & L1_DEB_WARN) | 528 | if (cs->debug & L1_DEB_WARN) |
529 | debugl1(cs, "isar frame error %x len %d", | 529 | debugl1(cs, "isar frame error %x len %d", |
530 | ireg->cmsb, ireg->clsb); | 530 | ireg->cmsb, ireg->clsb); |
531 | #ifdef ERROR_STATISTIC | 531 | #ifdef ERROR_STATISTIC |
532 | if (ireg->cmsb & HDLC_ERR_RER) | 532 | if (ireg->cmsb & HDLC_ERR_RER) |
533 | bcs->err_inv++; | 533 | bcs->err_inv++; |
534 | if (ireg->cmsb & HDLC_ERR_CER) | 534 | if (ireg->cmsb & HDLC_ERR_CER) |
535 | bcs->err_crc++; | 535 | bcs->err_crc++; |
536 | #endif | 536 | #endif |
537 | bcs->hw.isar.rcvidx = 0; | 537 | bcs->hw.isar.rcvidx = 0; |
538 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 538 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
539 | } else { | 539 | } else { |
540 | if (ireg->cmsb & HDLC_FSD) | 540 | if (ireg->cmsb & HDLC_FSD) |
541 | bcs->hw.isar.rcvidx = 0; | 541 | bcs->hw.isar.rcvidx = 0; |
542 | ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; | 542 | ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; |
543 | bcs->hw.isar.rcvidx += ireg->clsb; | 543 | bcs->hw.isar.rcvidx += ireg->clsb; |
544 | rcv_mbox(cs, ireg, ptr); | 544 | rcv_mbox(cs, ireg, ptr); |
545 | if (ireg->cmsb & HDLC_FED) { | 545 | if (ireg->cmsb & HDLC_FED) { |
546 | if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */ | 546 | if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */ |
547 | if (cs->debug & L1_DEB_WARN) | 547 | if (cs->debug & L1_DEB_WARN) |
548 | debugl1(cs, "isar frame to short %d", | 548 | debugl1(cs, "isar frame to short %d", |
549 | bcs->hw.isar.rcvidx); | 549 | bcs->hw.isar.rcvidx); |
550 | } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx - 2))) { | 550 | } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx - 2))) { |
551 | printk(KERN_WARNING "ISAR: receive out of memory\n"); | 551 | printk(KERN_WARNING "ISAR: receive out of memory\n"); |
552 | } else { | 552 | } else { |
553 | memcpy(skb_put(skb, bcs->hw.isar.rcvidx - 2), | 553 | memcpy(skb_put(skb, bcs->hw.isar.rcvidx - 2), |
554 | bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx - 2); | 554 | bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx - 2); |
555 | skb_queue_tail(&bcs->rqueue, skb); | 555 | skb_queue_tail(&bcs->rqueue, skb); |
556 | schedule_event(bcs, B_RCVBUFREADY); | 556 | schedule_event(bcs, B_RCVBUFREADY); |
557 | } | 557 | } |
558 | bcs->hw.isar.rcvidx = 0; | 558 | bcs->hw.isar.rcvidx = 0; |
559 | } | 559 | } |
560 | } | 560 | } |
561 | break; | 561 | break; |
562 | case L1_MODE_FAX: | 562 | case L1_MODE_FAX: |
563 | if (bcs->hw.isar.state != STFAX_ACTIV) { | 563 | if (bcs->hw.isar.state != STFAX_ACTIV) { |
564 | if (cs->debug & L1_DEB_WARN) | 564 | if (cs->debug & L1_DEB_WARN) |
565 | debugl1(cs, "isar_rcv_frame: not ACTIV"); | 565 | debugl1(cs, "isar_rcv_frame: not ACTIV"); |
566 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 566 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
567 | bcs->hw.isar.rcvidx = 0; | 567 | bcs->hw.isar.rcvidx = 0; |
568 | break; | 568 | break; |
569 | } | 569 | } |
570 | if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { | 570 | if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { |
571 | rcv_mbox(cs, ireg, bcs->hw.isar.rcvbuf); | 571 | rcv_mbox(cs, ireg, bcs->hw.isar.rcvbuf); |
572 | bcs->hw.isar.rcvidx = ireg->clsb + | 572 | bcs->hw.isar.rcvidx = ireg->clsb + |
573 | dle_count(bcs->hw.isar.rcvbuf, ireg->clsb); | 573 | dle_count(bcs->hw.isar.rcvbuf, ireg->clsb); |
574 | if (cs->debug & L1_DEB_HSCX) | 574 | if (cs->debug & L1_DEB_HSCX) |
575 | debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)", | 575 | debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)", |
576 | ireg->clsb, bcs->hw.isar.rcvidx); | 576 | ireg->clsb, bcs->hw.isar.rcvidx); |
577 | if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) { | 577 | if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) { |
578 | insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx), | 578 | insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx), |
579 | bcs->hw.isar.rcvbuf, ireg->clsb); | 579 | bcs->hw.isar.rcvbuf, ireg->clsb); |
580 | skb_queue_tail(&bcs->rqueue, skb); | 580 | skb_queue_tail(&bcs->rqueue, skb); |
581 | schedule_event(bcs, B_RCVBUFREADY); | 581 | schedule_event(bcs, B_RCVBUFREADY); |
582 | if (ireg->cmsb & SART_NMD) { /* ABORT */ | 582 | if (ireg->cmsb & SART_NMD) { /* ABORT */ |
583 | if (cs->debug & L1_DEB_WARN) | 583 | if (cs->debug & L1_DEB_WARN) |
584 | debugl1(cs, "isar_rcv_frame: no more data"); | 584 | debugl1(cs, "isar_rcv_frame: no more data"); |
585 | bcs->hw.isar.rcvidx = 0; | 585 | bcs->hw.isar.rcvidx = 0; |
586 | send_DLE_ETX(bcs); | 586 | send_DLE_ETX(bcs); |
587 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | | 587 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | |
588 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, | 588 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, |
589 | 0, NULL); | 589 | 0, NULL); |
590 | bcs->hw.isar.state = STFAX_ESCAPE; | 590 | bcs->hw.isar.state = STFAX_ESCAPE; |
591 | schedule_event(bcs, B_LL_NOCARRIER); | 591 | schedule_event(bcs, B_LL_NOCARRIER); |
592 | } | 592 | } |
593 | } else { | 593 | } else { |
594 | printk(KERN_WARNING "HiSax: skb out of memory\n"); | 594 | printk(KERN_WARNING "HiSax: skb out of memory\n"); |
595 | } | 595 | } |
596 | break; | 596 | break; |
597 | } | 597 | } |
598 | if (bcs->hw.isar.cmd != PCTRL_CMD_FRH) { | 598 | if (bcs->hw.isar.cmd != PCTRL_CMD_FRH) { |
599 | if (cs->debug & L1_DEB_WARN) | 599 | if (cs->debug & L1_DEB_WARN) |
600 | debugl1(cs, "isar_rcv_frame: unknown fax mode %x", | 600 | debugl1(cs, "isar_rcv_frame: unknown fax mode %x", |
601 | bcs->hw.isar.cmd); | 601 | bcs->hw.isar.cmd); |
602 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 602 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
603 | bcs->hw.isar.rcvidx = 0; | 603 | bcs->hw.isar.rcvidx = 0; |
604 | break; | 604 | break; |
605 | } | 605 | } |
606 | /* PCTRL_CMD_FRH */ | 606 | /* PCTRL_CMD_FRH */ |
607 | if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { | 607 | if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { |
608 | if (cs->debug & L1_DEB_WARN) | 608 | if (cs->debug & L1_DEB_WARN) |
609 | debugl1(cs, "isar_rcv_frame: incoming packet too large"); | 609 | debugl1(cs, "isar_rcv_frame: incoming packet too large"); |
610 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 610 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
611 | bcs->hw.isar.rcvidx = 0; | 611 | bcs->hw.isar.rcvidx = 0; |
612 | } else if (ireg->cmsb & HDLC_ERROR) { | 612 | } else if (ireg->cmsb & HDLC_ERROR) { |
613 | if (cs->debug & L1_DEB_WARN) | 613 | if (cs->debug & L1_DEB_WARN) |
614 | debugl1(cs, "isar frame error %x len %d", | 614 | debugl1(cs, "isar frame error %x len %d", |
615 | ireg->cmsb, ireg->clsb); | 615 | ireg->cmsb, ireg->clsb); |
616 | bcs->hw.isar.rcvidx = 0; | 616 | bcs->hw.isar.rcvidx = 0; |
617 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 617 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
618 | } else { | 618 | } else { |
619 | if (ireg->cmsb & HDLC_FSD) { | 619 | if (ireg->cmsb & HDLC_FSD) { |
620 | bcs->hw.isar.rcvidx = 0; | 620 | bcs->hw.isar.rcvidx = 0; |
621 | } | 621 | } |
622 | ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; | 622 | ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; |
623 | bcs->hw.isar.rcvidx += ireg->clsb; | 623 | bcs->hw.isar.rcvidx += ireg->clsb; |
624 | rcv_mbox(cs, ireg, ptr); | 624 | rcv_mbox(cs, ireg, ptr); |
625 | if (ireg->cmsb & HDLC_FED) { | 625 | if (ireg->cmsb & HDLC_FED) { |
626 | int len = bcs->hw.isar.rcvidx + | 626 | int len = bcs->hw.isar.rcvidx + |
627 | dle_count(bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx); | 627 | dle_count(bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx); |
628 | if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */ | 628 | if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */ |
629 | if (cs->debug & L1_DEB_WARN) | 629 | if (cs->debug & L1_DEB_WARN) |
630 | debugl1(cs, "isar frame to short %d", | 630 | debugl1(cs, "isar frame to short %d", |
631 | bcs->hw.isar.rcvidx); | 631 | bcs->hw.isar.rcvidx); |
632 | printk(KERN_WARNING "ISAR: frame to short %d\n", | 632 | printk(KERN_WARNING "ISAR: frame to short %d\n", |
633 | bcs->hw.isar.rcvidx); | 633 | bcs->hw.isar.rcvidx); |
634 | } else if (!(skb = dev_alloc_skb(len))) { | 634 | } else if (!(skb = dev_alloc_skb(len))) { |
635 | printk(KERN_WARNING "ISAR: receive out of memory\n"); | 635 | printk(KERN_WARNING "ISAR: receive out of memory\n"); |
636 | } else { | 636 | } else { |
637 | insert_dle((u_char *)skb_put(skb, len), | 637 | insert_dle((u_char *)skb_put(skb, len), |
638 | bcs->hw.isar.rcvbuf, | 638 | bcs->hw.isar.rcvbuf, |
639 | bcs->hw.isar.rcvidx); | 639 | bcs->hw.isar.rcvidx); |
640 | skb_queue_tail(&bcs->rqueue, skb); | 640 | skb_queue_tail(&bcs->rqueue, skb); |
641 | schedule_event(bcs, B_RCVBUFREADY); | 641 | schedule_event(bcs, B_RCVBUFREADY); |
642 | send_DLE_ETX(bcs); | 642 | send_DLE_ETX(bcs); |
643 | schedule_event(bcs, B_LL_OK); | 643 | schedule_event(bcs, B_LL_OK); |
644 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); | 644 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); |
645 | } | 645 | } |
646 | bcs->hw.isar.rcvidx = 0; | 646 | bcs->hw.isar.rcvidx = 0; |
647 | } | 647 | } |
648 | } | 648 | } |
649 | if (ireg->cmsb & SART_NMD) { /* ABORT */ | 649 | if (ireg->cmsb & SART_NMD) { /* ABORT */ |
650 | if (cs->debug & L1_DEB_WARN) | 650 | if (cs->debug & L1_DEB_WARN) |
651 | debugl1(cs, "isar_rcv_frame: no more data"); | 651 | debugl1(cs, "isar_rcv_frame: no more data"); |
652 | bcs->hw.isar.rcvidx = 0; | 652 | bcs->hw.isar.rcvidx = 0; |
653 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | | 653 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | |
654 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); | 654 | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); |
655 | bcs->hw.isar.state = STFAX_ESCAPE; | 655 | bcs->hw.isar.state = STFAX_ESCAPE; |
656 | if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) { | 656 | if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) { |
657 | send_DLE_ETX(bcs); | 657 | send_DLE_ETX(bcs); |
658 | schedule_event(bcs, B_LL_NOCARRIER); | 658 | schedule_event(bcs, B_LL_NOCARRIER); |
659 | } | 659 | } |
660 | } | 660 | } |
661 | break; | 661 | break; |
662 | default: | 662 | default: |
663 | printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode); | 663 | printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode); |
664 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 664 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
665 | break; | 665 | break; |
666 | } | 666 | } |
667 | } | 667 | } |
668 | 668 | ||
669 | void | 669 | void |
670 | isar_fill_fifo(struct BCState *bcs) | 670 | isar_fill_fifo(struct BCState *bcs) |
671 | { | 671 | { |
672 | struct IsdnCardState *cs = bcs->cs; | 672 | struct IsdnCardState *cs = bcs->cs; |
673 | int count; | 673 | int count; |
674 | u_char msb; | 674 | u_char msb; |
675 | u_char *ptr; | 675 | u_char *ptr; |
676 | 676 | ||
677 | if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) | 677 | if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) |
678 | debugl1(cs, "isar_fill_fifo"); | 678 | debugl1(cs, "isar_fill_fifo"); |
679 | if (!bcs->tx_skb) | 679 | if (!bcs->tx_skb) |
680 | return; | 680 | return; |
681 | if (bcs->tx_skb->len <= 0) | 681 | if (bcs->tx_skb->len <= 0) |
682 | return; | 682 | return; |
683 | if (!(bcs->hw.isar.reg->bstat & | 683 | if (!(bcs->hw.isar.reg->bstat & |
684 | (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) | 684 | (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) |
685 | return; | 685 | return; |
686 | if (bcs->tx_skb->len > bcs->hw.isar.mml) { | 686 | if (bcs->tx_skb->len > bcs->hw.isar.mml) { |
687 | msb = 0; | 687 | msb = 0; |
688 | count = bcs->hw.isar.mml; | 688 | count = bcs->hw.isar.mml; |
689 | } else { | 689 | } else { |
690 | count = bcs->tx_skb->len; | 690 | count = bcs->tx_skb->len; |
691 | msb = HDLC_FED; | 691 | msb = HDLC_FED; |
692 | } | 692 | } |
693 | ptr = bcs->tx_skb->data; | 693 | ptr = bcs->tx_skb->data; |
694 | if (!bcs->hw.isar.txcnt) { | 694 | if (!bcs->hw.isar.txcnt) { |
695 | msb |= HDLC_FST; | 695 | msb |= HDLC_FST; |
696 | if ((bcs->mode == L1_MODE_FAX) && | 696 | if ((bcs->mode == L1_MODE_FAX) && |
697 | (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) { | 697 | (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) { |
698 | if (bcs->tx_skb->len > 1) { | 698 | if (bcs->tx_skb->len > 1) { |
699 | if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) | 699 | if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) |
700 | /* last frame */ | 700 | /* last frame */ |
701 | test_and_set_bit(BC_FLG_LASTDATA, | 701 | test_and_set_bit(BC_FLG_LASTDATA, |
702 | &bcs->Flag); | 702 | &bcs->Flag); |
703 | } | 703 | } |
704 | } | 704 | } |
705 | } | 705 | } |
706 | skb_pull(bcs->tx_skb, count); | 706 | skb_pull(bcs->tx_skb, count); |
707 | bcs->tx_cnt -= count; | 707 | bcs->tx_cnt -= count; |
708 | bcs->hw.isar.txcnt += count; | 708 | bcs->hw.isar.txcnt += count; |
709 | switch (bcs->mode) { | 709 | switch (bcs->mode) { |
710 | case L1_MODE_NULL: | 710 | case L1_MODE_NULL: |
711 | printk(KERN_ERR"isar_fill_fifo wrong mode 0\n"); | 711 | printk(KERN_ERR"isar_fill_fifo wrong mode 0\n"); |
712 | break; | 712 | break; |
713 | case L1_MODE_TRANS: | 713 | case L1_MODE_TRANS: |
714 | case L1_MODE_V32: | 714 | case L1_MODE_V32: |
715 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, | 715 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, |
716 | 0, count, ptr); | 716 | 0, count, ptr); |
717 | break; | 717 | break; |
718 | case L1_MODE_HDLC: | 718 | case L1_MODE_HDLC: |
719 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, | 719 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, |
720 | msb, count, ptr); | 720 | msb, count, ptr); |
721 | break; | 721 | break; |
722 | case L1_MODE_FAX: | 722 | case L1_MODE_FAX: |
723 | if (bcs->hw.isar.state != STFAX_ACTIV) { | 723 | if (bcs->hw.isar.state != STFAX_ACTIV) { |
724 | if (cs->debug & L1_DEB_WARN) | 724 | if (cs->debug & L1_DEB_WARN) |
725 | debugl1(cs, "isar_fill_fifo: not ACTIV"); | 725 | debugl1(cs, "isar_fill_fifo: not ACTIV"); |
726 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { | 726 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { |
727 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, | 727 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, |
728 | msb, count, ptr); | 728 | msb, count, ptr); |
729 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) { | 729 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) { |
730 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, | 730 | sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, |
731 | 0, count, ptr); | 731 | 0, count, ptr); |
732 | } else { | 732 | } else { |
733 | if (cs->debug & L1_DEB_WARN) | 733 | if (cs->debug & L1_DEB_WARN) |
734 | debugl1(cs, "isar_fill_fifo: not FTH/FTM"); | 734 | debugl1(cs, "isar_fill_fifo: not FTH/FTM"); |
735 | } | 735 | } |
736 | break; | 736 | break; |
737 | default: | 737 | default: |
738 | if (cs->debug) | 738 | if (cs->debug) |
739 | debugl1(cs, "isar_fill_fifo mode(%x) error", bcs->mode); | 739 | debugl1(cs, "isar_fill_fifo mode(%x) error", bcs->mode); |
740 | printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode); | 740 | printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode); |
741 | break; | 741 | break; |
742 | } | 742 | } |
743 | } | 743 | } |
744 | 744 | ||
745 | static inline | 745 | static inline |
746 | struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath) | 746 | struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath) |
747 | { | 747 | { |
748 | if ((!dpath) || (dpath == 3)) | 748 | if ((!dpath) || (dpath == 3)) |
749 | return (NULL); | 749 | return (NULL); |
750 | if (cs->bcs[0].hw.isar.dpath == dpath) | 750 | if (cs->bcs[0].hw.isar.dpath == dpath) |
751 | return (&cs->bcs[0]); | 751 | return (&cs->bcs[0]); |
752 | if (cs->bcs[1].hw.isar.dpath == dpath) | 752 | if (cs->bcs[1].hw.isar.dpath == dpath) |
753 | return (&cs->bcs[1]); | 753 | return (&cs->bcs[1]); |
754 | return (NULL); | 754 | return (NULL); |
755 | } | 755 | } |
756 | 756 | ||
757 | static void | 757 | static void |
758 | send_frames(struct BCState *bcs) | 758 | send_frames(struct BCState *bcs) |
759 | { | 759 | { |
760 | if (bcs->tx_skb) { | 760 | if (bcs->tx_skb) { |
761 | if (bcs->tx_skb->len) { | 761 | if (bcs->tx_skb->len) { |
762 | isar_fill_fifo(bcs); | 762 | isar_fill_fifo(bcs); |
763 | return; | 763 | return; |
764 | } else { | 764 | } else { |
765 | if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) && | 765 | if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) && |
766 | (PACKET_NOACK != bcs->tx_skb->pkt_type)) { | 766 | (PACKET_NOACK != bcs->tx_skb->pkt_type)) { |
767 | u_long flags; | 767 | u_long flags; |
768 | spin_lock_irqsave(&bcs->aclock, flags); | 768 | spin_lock_irqsave(&bcs->aclock, flags); |
769 | bcs->ackcnt += bcs->hw.isar.txcnt; | 769 | bcs->ackcnt += bcs->hw.isar.txcnt; |
770 | spin_unlock_irqrestore(&bcs->aclock, flags); | 770 | spin_unlock_irqrestore(&bcs->aclock, flags); |
771 | schedule_event(bcs, B_ACKPENDING); | 771 | schedule_event(bcs, B_ACKPENDING); |
772 | } | 772 | } |
773 | if (bcs->mode == L1_MODE_FAX) { | 773 | if (bcs->mode == L1_MODE_FAX) { |
774 | if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { | 774 | if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { |
775 | if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) { | 775 | if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) { |
776 | test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag); | 776 | test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag); |
777 | } | 777 | } |
778 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) { | 778 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) { |
779 | if (test_bit(BC_FLG_DLEETX, &bcs->Flag)) { | 779 | if (test_bit(BC_FLG_DLEETX, &bcs->Flag)) { |
780 | test_and_set_bit(BC_FLG_LASTDATA, &bcs->Flag); | 780 | test_and_set_bit(BC_FLG_LASTDATA, &bcs->Flag); |
781 | test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag); | 781 | test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag); |
782 | } | 782 | } |
783 | } | 783 | } |
784 | } | 784 | } |
785 | dev_kfree_skb_any(bcs->tx_skb); | 785 | dev_kfree_skb_any(bcs->tx_skb); |
786 | bcs->hw.isar.txcnt = 0; | 786 | bcs->hw.isar.txcnt = 0; |
787 | bcs->tx_skb = NULL; | 787 | bcs->tx_skb = NULL; |
788 | } | 788 | } |
789 | } | 789 | } |
790 | if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { | 790 | if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { |
791 | bcs->hw.isar.txcnt = 0; | 791 | bcs->hw.isar.txcnt = 0; |
792 | test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); | 792 | test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); |
793 | isar_fill_fifo(bcs); | 793 | isar_fill_fifo(bcs); |
794 | } else { | 794 | } else { |
795 | if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) { | 795 | if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) { |
796 | if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) { | 796 | if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) { |
797 | if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) { | 797 | if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) { |
798 | u_char dummy = 0; | 798 | u_char dummy = 0; |
799 | sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) | | 799 | sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) | |
800 | ISAR_HIS_SDATA, 0x01, 1, &dummy); | 800 | ISAR_HIS_SDATA, 0x01, 1, &dummy); |
801 | } | 801 | } |
802 | test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag); | 802 | test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag); |
803 | } else { | 803 | } else { |
804 | schedule_event(bcs, B_LL_CONNECT); | 804 | schedule_event(bcs, B_LL_CONNECT); |
805 | } | 805 | } |
806 | } | 806 | } |
807 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | 807 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); |
808 | schedule_event(bcs, B_XMTBUFREADY); | 808 | schedule_event(bcs, B_XMTBUFREADY); |
809 | } | 809 | } |
810 | } | 810 | } |
811 | 811 | ||
812 | static inline void | 812 | static inline void |
813 | check_send(struct IsdnCardState *cs, u_char rdm) | 813 | check_send(struct IsdnCardState *cs, u_char rdm) |
814 | { | 814 | { |
815 | struct BCState *bcs; | 815 | struct BCState *bcs; |
816 | 816 | ||
817 | if (rdm & BSTAT_RDM1) { | 817 | if (rdm & BSTAT_RDM1) { |
818 | if ((bcs = sel_bcs_isar(cs, 1))) { | 818 | if ((bcs = sel_bcs_isar(cs, 1))) { |
819 | if (bcs->mode) { | 819 | if (bcs->mode) { |
820 | send_frames(bcs); | 820 | send_frames(bcs); |
821 | } | 821 | } |
822 | } | 822 | } |
823 | } | 823 | } |
824 | if (rdm & BSTAT_RDM2) { | 824 | if (rdm & BSTAT_RDM2) { |
825 | if ((bcs = sel_bcs_isar(cs, 2))) { | 825 | if ((bcs = sel_bcs_isar(cs, 2))) { |
826 | if (bcs->mode) { | 826 | if (bcs->mode) { |
827 | send_frames(bcs); | 827 | send_frames(bcs); |
828 | } | 828 | } |
829 | } | 829 | } |
830 | } | 830 | } |
831 | 831 | ||
832 | } | 832 | } |
833 | 833 | ||
834 | static const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", | 834 | static const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", |
835 | "NODEF4", "300", "600", "1200", "2400", | 835 | "NODEF4", "300", "600", "1200", "2400", |
836 | "4800", "7200", "9600nt", "9600t", "12000", | 836 | "4800", "7200", "9600nt", "9600t", "12000", |
837 | "14400", "WRONG"}; | 837 | "14400", "WRONG"}; |
838 | static const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21", | 838 | static const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21", |
839 | "Bell103", "V23", "Bell202", "V17", "V29", | 839 | "Bell103", "V23", "Bell202", "V17", "V29", |
840 | "V27ter"}; | 840 | "V27ter"}; |
841 | 841 | ||
842 | static void | 842 | static void |
843 | isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) { | 843 | isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) { |
844 | struct IsdnCardState *cs = bcs->cs; | 844 | struct IsdnCardState *cs = bcs->cs; |
845 | u_char ril = ireg->par[0]; | 845 | u_char ril = ireg->par[0]; |
846 | u_char rim; | 846 | u_char rim; |
847 | 847 | ||
848 | if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags)) | 848 | if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags)) |
849 | return; | 849 | return; |
850 | if (ril > 14) { | 850 | if (ril > 14) { |
851 | if (cs->debug & L1_DEB_WARN) | 851 | if (cs->debug & L1_DEB_WARN) |
852 | debugl1(cs, "wrong pstrsp ril=%d", ril); | 852 | debugl1(cs, "wrong pstrsp ril=%d", ril); |
853 | ril = 15; | 853 | ril = 15; |
854 | } | 854 | } |
855 | switch (ireg->par[1]) { | 855 | switch (ireg->par[1]) { |
856 | case 0: | 856 | case 0: |
857 | rim = 0; | 857 | rim = 0; |
858 | break; | 858 | break; |
859 | case 0x20: | 859 | case 0x20: |
860 | rim = 2; | 860 | rim = 2; |
861 | break; | 861 | break; |
862 | case 0x40: | 862 | case 0x40: |
863 | rim = 3; | 863 | rim = 3; |
864 | break; | 864 | break; |
865 | case 0x41: | 865 | case 0x41: |
866 | rim = 4; | 866 | rim = 4; |
867 | break; | 867 | break; |
868 | case 0x51: | 868 | case 0x51: |
869 | rim = 5; | 869 | rim = 5; |
870 | break; | 870 | break; |
871 | case 0x61: | 871 | case 0x61: |
872 | rim = 6; | 872 | rim = 6; |
873 | break; | 873 | break; |
874 | case 0x71: | 874 | case 0x71: |
875 | rim = 7; | 875 | rim = 7; |
876 | break; | 876 | break; |
877 | case 0x82: | 877 | case 0x82: |
878 | rim = 8; | 878 | rim = 8; |
879 | break; | 879 | break; |
880 | case 0x92: | 880 | case 0x92: |
881 | rim = 9; | 881 | rim = 9; |
882 | break; | 882 | break; |
883 | case 0xa2: | 883 | case 0xa2: |
884 | rim = 10; | 884 | rim = 10; |
885 | break; | 885 | break; |
886 | default: | 886 | default: |
887 | rim = 1; | 887 | rim = 1; |
888 | break; | 888 | break; |
889 | } | 889 | } |
890 | sprintf(bcs->hw.isar.conmsg, "%s %s", dmril[ril], dmrim[rim]); | 890 | sprintf(bcs->hw.isar.conmsg, "%s %s", dmril[ril], dmrim[rim]); |
891 | bcs->conmsg = bcs->hw.isar.conmsg; | 891 | bcs->conmsg = bcs->hw.isar.conmsg; |
892 | if (cs->debug & L1_DEB_HSCX) | 892 | if (cs->debug & L1_DEB_HSCX) |
893 | debugl1(cs, "pump strsp %s", bcs->conmsg); | 893 | debugl1(cs, "pump strsp %s", bcs->conmsg); |
894 | } | 894 | } |
895 | 895 | ||
896 | static void | 896 | static void |
897 | isar_pump_statev_modem(struct BCState *bcs, u_char devt) { | 897 | isar_pump_statev_modem(struct BCState *bcs, u_char devt) { |
898 | struct IsdnCardState *cs = bcs->cs; | 898 | struct IsdnCardState *cs = bcs->cs; |
899 | u_char dps = SET_DPS(bcs->hw.isar.dpath); | 899 | u_char dps = SET_DPS(bcs->hw.isar.dpath); |
900 | 900 | ||
901 | switch (devt) { | 901 | switch (devt) { |
902 | case PSEV_10MS_TIMER: | 902 | case PSEV_10MS_TIMER: |
903 | if (cs->debug & L1_DEB_HSCX) | 903 | if (cs->debug & L1_DEB_HSCX) |
904 | debugl1(cs, "pump stev TIMER"); | 904 | debugl1(cs, "pump stev TIMER"); |
905 | break; | 905 | break; |
906 | case PSEV_CON_ON: | 906 | case PSEV_CON_ON: |
907 | if (cs->debug & L1_DEB_HSCX) | 907 | if (cs->debug & L1_DEB_HSCX) |
908 | debugl1(cs, "pump stev CONNECT"); | 908 | debugl1(cs, "pump stev CONNECT"); |
909 | l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL); | 909 | l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL); |
910 | break; | 910 | break; |
911 | case PSEV_CON_OFF: | 911 | case PSEV_CON_OFF: |
912 | if (cs->debug & L1_DEB_HSCX) | 912 | if (cs->debug & L1_DEB_HSCX) |
913 | debugl1(cs, "pump stev NO CONNECT"); | 913 | debugl1(cs, "pump stev NO CONNECT"); |
914 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 914 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
915 | l1_msg_b(bcs->st, PH_DEACTIVATE | REQUEST, NULL); | 915 | l1_msg_b(bcs->st, PH_DEACTIVATE | REQUEST, NULL); |
916 | break; | 916 | break; |
917 | case PSEV_V24_OFF: | 917 | case PSEV_V24_OFF: |
918 | if (cs->debug & L1_DEB_HSCX) | 918 | if (cs->debug & L1_DEB_HSCX) |
919 | debugl1(cs, "pump stev V24 OFF"); | 919 | debugl1(cs, "pump stev V24 OFF"); |
920 | break; | 920 | break; |
921 | case PSEV_CTS_ON: | 921 | case PSEV_CTS_ON: |
922 | if (cs->debug & L1_DEB_HSCX) | 922 | if (cs->debug & L1_DEB_HSCX) |
923 | debugl1(cs, "pump stev CTS ON"); | 923 | debugl1(cs, "pump stev CTS ON"); |
924 | break; | 924 | break; |
925 | case PSEV_CTS_OFF: | 925 | case PSEV_CTS_OFF: |
926 | if (cs->debug & L1_DEB_HSCX) | 926 | if (cs->debug & L1_DEB_HSCX) |
927 | debugl1(cs, "pump stev CTS OFF"); | 927 | debugl1(cs, "pump stev CTS OFF"); |
928 | break; | 928 | break; |
929 | case PSEV_DCD_ON: | 929 | case PSEV_DCD_ON: |
930 | if (cs->debug & L1_DEB_HSCX) | 930 | if (cs->debug & L1_DEB_HSCX) |
931 | debugl1(cs, "pump stev CARRIER ON"); | 931 | debugl1(cs, "pump stev CARRIER ON"); |
932 | test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags); | 932 | test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags); |
933 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 933 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
934 | break; | 934 | break; |
935 | case PSEV_DCD_OFF: | 935 | case PSEV_DCD_OFF: |
936 | if (cs->debug & L1_DEB_HSCX) | 936 | if (cs->debug & L1_DEB_HSCX) |
937 | debugl1(cs, "pump stev CARRIER OFF"); | 937 | debugl1(cs, "pump stev CARRIER OFF"); |
938 | break; | 938 | break; |
939 | case PSEV_DSR_ON: | 939 | case PSEV_DSR_ON: |
940 | if (cs->debug & L1_DEB_HSCX) | 940 | if (cs->debug & L1_DEB_HSCX) |
941 | debugl1(cs, "pump stev DSR ON"); | 941 | debugl1(cs, "pump stev DSR ON"); |
942 | break; | 942 | break; |
943 | case PSEV_DSR_OFF: | 943 | case PSEV_DSR_OFF: |
944 | if (cs->debug & L1_DEB_HSCX) | 944 | if (cs->debug & L1_DEB_HSCX) |
945 | debugl1(cs, "pump stev DSR_OFF"); | 945 | debugl1(cs, "pump stev DSR_OFF"); |
946 | break; | 946 | break; |
947 | case PSEV_REM_RET: | 947 | case PSEV_REM_RET: |
948 | if (cs->debug & L1_DEB_HSCX) | 948 | if (cs->debug & L1_DEB_HSCX) |
949 | debugl1(cs, "pump stev REMOTE RETRAIN"); | 949 | debugl1(cs, "pump stev REMOTE RETRAIN"); |
950 | break; | 950 | break; |
951 | case PSEV_REM_REN: | 951 | case PSEV_REM_REN: |
952 | if (cs->debug & L1_DEB_HSCX) | 952 | if (cs->debug & L1_DEB_HSCX) |
953 | debugl1(cs, "pump stev REMOTE RENEGOTIATE"); | 953 | debugl1(cs, "pump stev REMOTE RENEGOTIATE"); |
954 | break; | 954 | break; |
955 | case PSEV_GSTN_CLR: | 955 | case PSEV_GSTN_CLR: |
956 | if (cs->debug & L1_DEB_HSCX) | 956 | if (cs->debug & L1_DEB_HSCX) |
957 | debugl1(cs, "pump stev GSTN CLEAR"); | 957 | debugl1(cs, "pump stev GSTN CLEAR"); |
958 | break; | 958 | break; |
959 | default: | 959 | default: |
960 | if (cs->debug & L1_DEB_HSCX) | 960 | if (cs->debug & L1_DEB_HSCX) |
961 | debugl1(cs, "unknown pump stev %x", devt); | 961 | debugl1(cs, "unknown pump stev %x", devt); |
962 | break; | 962 | break; |
963 | } | 963 | } |
964 | } | 964 | } |
965 | 965 | ||
966 | static void | 966 | static void |
967 | ll_deliver_faxstat(struct BCState *bcs, u_char status) | 967 | ll_deliver_faxstat(struct BCState *bcs, u_char status) |
968 | { | 968 | { |
969 | isdn_ctrl ic; | 969 | isdn_ctrl ic; |
970 | struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata; | 970 | struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata; |
971 | 971 | ||
972 | if (bcs->cs->debug & L1_DEB_HSCX) | 972 | if (bcs->cs->debug & L1_DEB_HSCX) |
973 | debugl1(bcs->cs, "HL->LL FAXIND %x", status); | 973 | debugl1(bcs->cs, "HL->LL FAXIND %x", status); |
974 | ic.driver = bcs->cs->myid; | 974 | ic.driver = bcs->cs->myid; |
975 | ic.command = ISDN_STAT_FAXIND; | 975 | ic.command = ISDN_STAT_FAXIND; |
976 | ic.arg = chanp->chan; | 976 | ic.arg = chanp->chan; |
977 | ic.parm.aux.cmd = status; | 977 | ic.parm.aux.cmd = status; |
978 | bcs->cs->iif.statcallb(&ic); | 978 | bcs->cs->iif.statcallb(&ic); |
979 | } | 979 | } |
980 | 980 | ||
981 | static void | 981 | static void |
982 | isar_pump_statev_fax(struct BCState *bcs, u_char devt) { | 982 | isar_pump_statev_fax(struct BCState *bcs, u_char devt) { |
983 | struct IsdnCardState *cs = bcs->cs; | 983 | struct IsdnCardState *cs = bcs->cs; |
984 | u_char dps = SET_DPS(bcs->hw.isar.dpath); | 984 | u_char dps = SET_DPS(bcs->hw.isar.dpath); |
985 | u_char p1; | 985 | u_char p1; |
986 | 986 | ||
987 | switch (devt) { | 987 | switch (devt) { |
988 | case PSEV_10MS_TIMER: | 988 | case PSEV_10MS_TIMER: |
989 | if (cs->debug & L1_DEB_HSCX) | 989 | if (cs->debug & L1_DEB_HSCX) |
990 | debugl1(cs, "pump stev TIMER"); | 990 | debugl1(cs, "pump stev TIMER"); |
991 | break; | 991 | break; |
992 | case PSEV_RSP_READY: | 992 | case PSEV_RSP_READY: |
993 | if (cs->debug & L1_DEB_HSCX) | 993 | if (cs->debug & L1_DEB_HSCX) |
994 | debugl1(cs, "pump stev RSP_READY"); | 994 | debugl1(cs, "pump stev RSP_READY"); |
995 | bcs->hw.isar.state = STFAX_READY; | 995 | bcs->hw.isar.state = STFAX_READY; |
996 | l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL); | 996 | l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL); |
997 | if (test_bit(BC_FLG_ORIG, &bcs->Flag)) { | 997 | if (test_bit(BC_FLG_ORIG, &bcs->Flag)) { |
998 | isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FRH, 3); | 998 | isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FRH, 3); |
999 | } else { | 999 | } else { |
1000 | isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FTH, 3); | 1000 | isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FTH, 3); |
1001 | } | 1001 | } |
1002 | break; | 1002 | break; |
1003 | case PSEV_LINE_TX_H: | 1003 | case PSEV_LINE_TX_H: |
1004 | if (bcs->hw.isar.state == STFAX_LINE) { | 1004 | if (bcs->hw.isar.state == STFAX_LINE) { |
1005 | if (cs->debug & L1_DEB_HSCX) | 1005 | if (cs->debug & L1_DEB_HSCX) |
1006 | debugl1(cs, "pump stev LINE_TX_H"); | 1006 | debugl1(cs, "pump stev LINE_TX_H"); |
1007 | bcs->hw.isar.state = STFAX_CONT; | 1007 | bcs->hw.isar.state = STFAX_CONT; |
1008 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); | 1008 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); |
1009 | } else { | 1009 | } else { |
1010 | if (cs->debug & L1_DEB_WARN) | 1010 | if (cs->debug & L1_DEB_WARN) |
1011 | debugl1(cs, "pump stev LINE_TX_H wrong st %x", | 1011 | debugl1(cs, "pump stev LINE_TX_H wrong st %x", |
1012 | bcs->hw.isar.state); | 1012 | bcs->hw.isar.state); |
1013 | } | 1013 | } |
1014 | break; | 1014 | break; |
1015 | case PSEV_LINE_RX_H: | 1015 | case PSEV_LINE_RX_H: |
1016 | if (bcs->hw.isar.state == STFAX_LINE) { | 1016 | if (bcs->hw.isar.state == STFAX_LINE) { |
1017 | if (cs->debug & L1_DEB_HSCX) | 1017 | if (cs->debug & L1_DEB_HSCX) |
1018 | debugl1(cs, "pump stev LINE_RX_H"); | 1018 | debugl1(cs, "pump stev LINE_RX_H"); |
1019 | bcs->hw.isar.state = STFAX_CONT; | 1019 | bcs->hw.isar.state = STFAX_CONT; |
1020 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); | 1020 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); |
1021 | } else { | 1021 | } else { |
1022 | if (cs->debug & L1_DEB_WARN) | 1022 | if (cs->debug & L1_DEB_WARN) |
1023 | debugl1(cs, "pump stev LINE_RX_H wrong st %x", | 1023 | debugl1(cs, "pump stev LINE_RX_H wrong st %x", |
1024 | bcs->hw.isar.state); | 1024 | bcs->hw.isar.state); |
1025 | } | 1025 | } |
1026 | break; | 1026 | break; |
1027 | case PSEV_LINE_TX_B: | 1027 | case PSEV_LINE_TX_B: |
1028 | if (bcs->hw.isar.state == STFAX_LINE) { | 1028 | if (bcs->hw.isar.state == STFAX_LINE) { |
1029 | if (cs->debug & L1_DEB_HSCX) | 1029 | if (cs->debug & L1_DEB_HSCX) |
1030 | debugl1(cs, "pump stev LINE_TX_B"); | 1030 | debugl1(cs, "pump stev LINE_TX_B"); |
1031 | bcs->hw.isar.state = STFAX_CONT; | 1031 | bcs->hw.isar.state = STFAX_CONT; |
1032 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); | 1032 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); |
1033 | } else { | 1033 | } else { |
1034 | if (cs->debug & L1_DEB_WARN) | 1034 | if (cs->debug & L1_DEB_WARN) |
1035 | debugl1(cs, "pump stev LINE_TX_B wrong st %x", | 1035 | debugl1(cs, "pump stev LINE_TX_B wrong st %x", |
1036 | bcs->hw.isar.state); | 1036 | bcs->hw.isar.state); |
1037 | } | 1037 | } |
1038 | break; | 1038 | break; |
1039 | case PSEV_LINE_RX_B: | 1039 | case PSEV_LINE_RX_B: |
1040 | if (bcs->hw.isar.state == STFAX_LINE) { | 1040 | if (bcs->hw.isar.state == STFAX_LINE) { |
1041 | if (cs->debug & L1_DEB_HSCX) | 1041 | if (cs->debug & L1_DEB_HSCX) |
1042 | debugl1(cs, "pump stev LINE_RX_B"); | 1042 | debugl1(cs, "pump stev LINE_RX_B"); |
1043 | bcs->hw.isar.state = STFAX_CONT; | 1043 | bcs->hw.isar.state = STFAX_CONT; |
1044 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); | 1044 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL); |
1045 | } else { | 1045 | } else { |
1046 | if (cs->debug & L1_DEB_WARN) | 1046 | if (cs->debug & L1_DEB_WARN) |
1047 | debugl1(cs, "pump stev LINE_RX_B wrong st %x", | 1047 | debugl1(cs, "pump stev LINE_RX_B wrong st %x", |
1048 | bcs->hw.isar.state); | 1048 | bcs->hw.isar.state); |
1049 | } | 1049 | } |
1050 | break; | 1050 | break; |
1051 | case PSEV_RSP_CONN: | 1051 | case PSEV_RSP_CONN: |
1052 | if (bcs->hw.isar.state == STFAX_CONT) { | 1052 | if (bcs->hw.isar.state == STFAX_CONT) { |
1053 | if (cs->debug & L1_DEB_HSCX) | 1053 | if (cs->debug & L1_DEB_HSCX) |
1054 | debugl1(cs, "pump stev RSP_CONN"); | 1054 | debugl1(cs, "pump stev RSP_CONN"); |
1055 | bcs->hw.isar.state = STFAX_ACTIV; | 1055 | bcs->hw.isar.state = STFAX_ACTIV; |
1056 | test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags); | 1056 | test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags); |
1057 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 1057 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
1058 | if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { | 1058 | if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { |
1059 | /* 1s Flags before data */ | 1059 | /* 1s Flags before data */ |
1060 | if (test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) | 1060 | if (test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) |
1061 | del_timer(&bcs->hw.isar.ftimer); | 1061 | del_timer(&bcs->hw.isar.ftimer); |
1062 | /* 1000 ms */ | 1062 | /* 1000 ms */ |
1063 | bcs->hw.isar.ftimer.expires = | 1063 | bcs->hw.isar.ftimer.expires = |
1064 | jiffies + ((1000 * HZ) / 1000); | 1064 | jiffies + ((1000 * HZ) / 1000); |
1065 | test_and_set_bit(BC_FLG_LL_CONN, | 1065 | test_and_set_bit(BC_FLG_LL_CONN, |
1066 | &bcs->Flag); | 1066 | &bcs->Flag); |
1067 | add_timer(&bcs->hw.isar.ftimer); | 1067 | add_timer(&bcs->hw.isar.ftimer); |
1068 | } else { | 1068 | } else { |
1069 | schedule_event(bcs, B_LL_CONNECT); | 1069 | schedule_event(bcs, B_LL_CONNECT); |
1070 | } | 1070 | } |
1071 | } else { | 1071 | } else { |
1072 | if (cs->debug & L1_DEB_WARN) | 1072 | if (cs->debug & L1_DEB_WARN) |
1073 | debugl1(cs, "pump stev RSP_CONN wrong st %x", | 1073 | debugl1(cs, "pump stev RSP_CONN wrong st %x", |
1074 | bcs->hw.isar.state); | 1074 | bcs->hw.isar.state); |
1075 | } | 1075 | } |
1076 | break; | 1076 | break; |
1077 | case PSEV_FLAGS_DET: | 1077 | case PSEV_FLAGS_DET: |
1078 | if (cs->debug & L1_DEB_HSCX) | 1078 | if (cs->debug & L1_DEB_HSCX) |
1079 | debugl1(cs, "pump stev FLAGS_DET"); | 1079 | debugl1(cs, "pump stev FLAGS_DET"); |
1080 | break; | 1080 | break; |
1081 | case PSEV_RSP_DISC: | 1081 | case PSEV_RSP_DISC: |
1082 | if (cs->debug & L1_DEB_HSCX) | 1082 | if (cs->debug & L1_DEB_HSCX) |
1083 | debugl1(cs, "pump stev RSP_DISC"); | 1083 | debugl1(cs, "pump stev RSP_DISC"); |
1084 | if (bcs->hw.isar.state == STFAX_ESCAPE) { | 1084 | if (bcs->hw.isar.state == STFAX_ESCAPE) { |
1085 | p1 = 5; | 1085 | p1 = 5; |
1086 | switch (bcs->hw.isar.newcmd) { | 1086 | switch (bcs->hw.isar.newcmd) { |
1087 | case 0: | 1087 | case 0: |
1088 | bcs->hw.isar.state = STFAX_READY; | 1088 | bcs->hw.isar.state = STFAX_READY; |
1089 | break; | 1089 | break; |
1090 | case PCTRL_CMD_FTM: | 1090 | case PCTRL_CMD_FTM: |
1091 | p1 = 2; | 1091 | p1 = 2; |
1092 | case PCTRL_CMD_FTH: | 1092 | case PCTRL_CMD_FTH: |
1093 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, | 1093 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, |
1094 | PCTRL_CMD_SILON, 1, &p1); | 1094 | PCTRL_CMD_SILON, 1, &p1); |
1095 | bcs->hw.isar.state = STFAX_SILDET; | 1095 | bcs->hw.isar.state = STFAX_SILDET; |
1096 | break; | 1096 | break; |
1097 | case PCTRL_CMD_FRM: | 1097 | case PCTRL_CMD_FRM: |
1098 | if (frm_extra_delay) | 1098 | if (frm_extra_delay) |
1099 | mdelay(frm_extra_delay); | 1099 | mdelay(frm_extra_delay); |
1100 | case PCTRL_CMD_FRH: | 1100 | case PCTRL_CMD_FRH: |
1101 | p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod; | 1101 | p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod; |
1102 | bcs->hw.isar.newmod = 0; | 1102 | bcs->hw.isar.newmod = 0; |
1103 | bcs->hw.isar.cmd = bcs->hw.isar.newcmd; | 1103 | bcs->hw.isar.cmd = bcs->hw.isar.newcmd; |
1104 | bcs->hw.isar.newcmd = 0; | 1104 | bcs->hw.isar.newcmd = 0; |
1105 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, | 1105 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, |
1106 | bcs->hw.isar.cmd, 1, &p1); | 1106 | bcs->hw.isar.cmd, 1, &p1); |
1107 | bcs->hw.isar.state = STFAX_LINE; | 1107 | bcs->hw.isar.state = STFAX_LINE; |
1108 | bcs->hw.isar.try_mod = 3; | 1108 | bcs->hw.isar.try_mod = 3; |
1109 | break; | 1109 | break; |
1110 | default: | 1110 | default: |
1111 | if (cs->debug & L1_DEB_HSCX) | 1111 | if (cs->debug & L1_DEB_HSCX) |
1112 | debugl1(cs, "RSP_DISC unknown newcmd %x", bcs->hw.isar.newcmd); | 1112 | debugl1(cs, "RSP_DISC unknown newcmd %x", bcs->hw.isar.newcmd); |
1113 | break; | 1113 | break; |
1114 | } | 1114 | } |
1115 | } else if (bcs->hw.isar.state == STFAX_ACTIV) { | 1115 | } else if (bcs->hw.isar.state == STFAX_ACTIV) { |
1116 | if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) { | 1116 | if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) { |
1117 | schedule_event(bcs, B_LL_OK); | 1117 | schedule_event(bcs, B_LL_OK); |
1118 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { | 1118 | } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { |
1119 | send_DLE_ETX(bcs); | 1119 | send_DLE_ETX(bcs); |
1120 | schedule_event(bcs, B_LL_NOCARRIER); | 1120 | schedule_event(bcs, B_LL_NOCARRIER); |
1121 | } else { | 1121 | } else { |
1122 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); | 1122 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); |
1123 | } | 1123 | } |
1124 | bcs->hw.isar.state = STFAX_READY; | 1124 | bcs->hw.isar.state = STFAX_READY; |
1125 | } else { | 1125 | } else { |
1126 | bcs->hw.isar.state = STFAX_READY; | 1126 | bcs->hw.isar.state = STFAX_READY; |
1127 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); | 1127 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); |
1128 | } | 1128 | } |
1129 | break; | 1129 | break; |
1130 | case PSEV_RSP_SILDET: | 1130 | case PSEV_RSP_SILDET: |
1131 | if (cs->debug & L1_DEB_HSCX) | 1131 | if (cs->debug & L1_DEB_HSCX) |
1132 | debugl1(cs, "pump stev RSP_SILDET"); | 1132 | debugl1(cs, "pump stev RSP_SILDET"); |
1133 | if (bcs->hw.isar.state == STFAX_SILDET) { | 1133 | if (bcs->hw.isar.state == STFAX_SILDET) { |
1134 | p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod; | 1134 | p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod; |
1135 | bcs->hw.isar.newmod = 0; | 1135 | bcs->hw.isar.newmod = 0; |
1136 | bcs->hw.isar.cmd = bcs->hw.isar.newcmd; | 1136 | bcs->hw.isar.cmd = bcs->hw.isar.newcmd; |
1137 | bcs->hw.isar.newcmd = 0; | 1137 | bcs->hw.isar.newcmd = 0; |
1138 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, | 1138 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, |
1139 | bcs->hw.isar.cmd, 1, &p1); | 1139 | bcs->hw.isar.cmd, 1, &p1); |
1140 | bcs->hw.isar.state = STFAX_LINE; | 1140 | bcs->hw.isar.state = STFAX_LINE; |
1141 | bcs->hw.isar.try_mod = 3; | 1141 | bcs->hw.isar.try_mod = 3; |
1142 | } | 1142 | } |
1143 | break; | 1143 | break; |
1144 | case PSEV_RSP_SILOFF: | 1144 | case PSEV_RSP_SILOFF: |
1145 | if (cs->debug & L1_DEB_HSCX) | 1145 | if (cs->debug & L1_DEB_HSCX) |
1146 | debugl1(cs, "pump stev RSP_SILOFF"); | 1146 | debugl1(cs, "pump stev RSP_SILOFF"); |
1147 | break; | 1147 | break; |
1148 | case PSEV_RSP_FCERR: | 1148 | case PSEV_RSP_FCERR: |
1149 | if (bcs->hw.isar.state == STFAX_LINE) { | 1149 | if (bcs->hw.isar.state == STFAX_LINE) { |
1150 | if (cs->debug & L1_DEB_HSCX) | 1150 | if (cs->debug & L1_DEB_HSCX) |
1151 | debugl1(cs, "pump stev RSP_FCERR try %d", | 1151 | debugl1(cs, "pump stev RSP_FCERR try %d", |
1152 | bcs->hw.isar.try_mod); | 1152 | bcs->hw.isar.try_mod); |
1153 | if (bcs->hw.isar.try_mod--) { | 1153 | if (bcs->hw.isar.try_mod--) { |
1154 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, | 1154 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, |
1155 | bcs->hw.isar.cmd, 1, | 1155 | bcs->hw.isar.cmd, 1, |
1156 | &bcs->hw.isar.mod); | 1156 | &bcs->hw.isar.mod); |
1157 | break; | 1157 | break; |
1158 | } | 1158 | } |
1159 | } | 1159 | } |
1160 | if (cs->debug & L1_DEB_HSCX) | 1160 | if (cs->debug & L1_DEB_HSCX) |
1161 | debugl1(cs, "pump stev RSP_FCERR"); | 1161 | debugl1(cs, "pump stev RSP_FCERR"); |
1162 | bcs->hw.isar.state = STFAX_ESCAPE; | 1162 | bcs->hw.isar.state = STFAX_ESCAPE; |
1163 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); | 1163 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); |
1164 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); | 1164 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); |
1165 | break; | 1165 | break; |
1166 | default: | 1166 | default: |
1167 | break; | 1167 | break; |
1168 | } | 1168 | } |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | static char debbuf[128]; | 1171 | static char debbuf[128]; |
1172 | 1172 | ||
1173 | void | 1173 | void |
1174 | isar_int_main(struct IsdnCardState *cs) | 1174 | isar_int_main(struct IsdnCardState *cs) |
1175 | { | 1175 | { |
1176 | struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; | 1176 | struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; |
1177 | struct BCState *bcs; | 1177 | struct BCState *bcs; |
1178 | 1178 | ||
1179 | get_irq_infos(cs, ireg); | 1179 | get_irq_infos(cs, ireg); |
1180 | switch (ireg->iis & ISAR_IIS_MSCMSD) { | 1180 | switch (ireg->iis & ISAR_IIS_MSCMSD) { |
1181 | case ISAR_IIS_RDATA: | 1181 | case ISAR_IIS_RDATA: |
1182 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { | 1182 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { |
1183 | isar_rcv_frame(cs, bcs); | 1183 | isar_rcv_frame(cs, bcs); |
1184 | } else { | 1184 | } else { |
1185 | debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x", | 1185 | debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x", |
1186 | ireg->iis, ireg->cmsb, ireg->clsb); | 1186 | ireg->iis, ireg->cmsb, ireg->clsb); |
1187 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 1187 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
1188 | } | 1188 | } |
1189 | break; | 1189 | break; |
1190 | case ISAR_IIS_GSTEV: | 1190 | case ISAR_IIS_GSTEV: |
1191 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 1191 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
1192 | ireg->bstat |= ireg->cmsb; | 1192 | ireg->bstat |= ireg->cmsb; |
1193 | check_send(cs, ireg->cmsb); | 1193 | check_send(cs, ireg->cmsb); |
1194 | break; | 1194 | break; |
1195 | case ISAR_IIS_BSTEV: | 1195 | case ISAR_IIS_BSTEV: |
1196 | #ifdef ERROR_STATISTIC | 1196 | #ifdef ERROR_STATISTIC |
1197 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { | 1197 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { |
1198 | if (ireg->cmsb == BSTEV_TBO) | 1198 | if (ireg->cmsb == BSTEV_TBO) |
1199 | bcs->err_tx++; | 1199 | bcs->err_tx++; |
1200 | if (ireg->cmsb == BSTEV_RBO) | 1200 | if (ireg->cmsb == BSTEV_RBO) |
1201 | bcs->err_rdo++; | 1201 | bcs->err_rdo++; |
1202 | } | 1202 | } |
1203 | #endif | 1203 | #endif |
1204 | if (cs->debug & L1_DEB_WARN) | 1204 | if (cs->debug & L1_DEB_WARN) |
1205 | debugl1(cs, "Buffer STEV dpath%d msb(%x)", | 1205 | debugl1(cs, "Buffer STEV dpath%d msb(%x)", |
1206 | ireg->iis >> 6, ireg->cmsb); | 1206 | ireg->iis >> 6, ireg->cmsb); |
1207 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 1207 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
1208 | break; | 1208 | break; |
1209 | case ISAR_IIS_PSTEV: | 1209 | case ISAR_IIS_PSTEV: |
1210 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { | 1210 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { |
1211 | rcv_mbox(cs, ireg, (u_char *)ireg->par); | 1211 | rcv_mbox(cs, ireg, (u_char *)ireg->par); |
1212 | if (bcs->mode == L1_MODE_V32) { | 1212 | if (bcs->mode == L1_MODE_V32) { |
1213 | isar_pump_statev_modem(bcs, ireg->cmsb); | 1213 | isar_pump_statev_modem(bcs, ireg->cmsb); |
1214 | } else if (bcs->mode == L1_MODE_FAX) { | 1214 | } else if (bcs->mode == L1_MODE_FAX) { |
1215 | isar_pump_statev_fax(bcs, ireg->cmsb); | 1215 | isar_pump_statev_fax(bcs, ireg->cmsb); |
1216 | } else if (ireg->cmsb == PSEV_10MS_TIMER) { | 1216 | } else if (ireg->cmsb == PSEV_10MS_TIMER) { |
1217 | if (cs->debug & L1_DEB_HSCX) | 1217 | if (cs->debug & L1_DEB_HSCX) |
1218 | debugl1(cs, "pump stev TIMER"); | 1218 | debugl1(cs, "pump stev TIMER"); |
1219 | } else { | 1219 | } else { |
1220 | if (cs->debug & L1_DEB_WARN) | 1220 | if (cs->debug & L1_DEB_WARN) |
1221 | debugl1(cs, "isar IIS_PSTEV pmode %d stat %x", | 1221 | debugl1(cs, "isar IIS_PSTEV pmode %d stat %x", |
1222 | bcs->mode, ireg->cmsb); | 1222 | bcs->mode, ireg->cmsb); |
1223 | } | 1223 | } |
1224 | } else { | 1224 | } else { |
1225 | debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x", | 1225 | debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x", |
1226 | ireg->iis, ireg->cmsb, ireg->clsb); | 1226 | ireg->iis, ireg->cmsb, ireg->clsb); |
1227 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 1227 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
1228 | } | 1228 | } |
1229 | break; | 1229 | break; |
1230 | case ISAR_IIS_PSTRSP: | 1230 | case ISAR_IIS_PSTRSP: |
1231 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { | 1231 | if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { |
1232 | rcv_mbox(cs, ireg, (u_char *)ireg->par); | 1232 | rcv_mbox(cs, ireg, (u_char *)ireg->par); |
1233 | isar_pump_status_rsp(bcs, ireg); | 1233 | isar_pump_status_rsp(bcs, ireg); |
1234 | } else { | 1234 | } else { |
1235 | debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x", | 1235 | debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x", |
1236 | ireg->iis, ireg->cmsb, ireg->clsb); | 1236 | ireg->iis, ireg->cmsb, ireg->clsb); |
1237 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); | 1237 | cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); |
1238 | } | 1238 | } |
1239 | break; | 1239 | break; |
1240 | case ISAR_IIS_DIAG: | 1240 | case ISAR_IIS_DIAG: |
1241 | case ISAR_IIS_BSTRSP: | 1241 | case ISAR_IIS_BSTRSP: |
1242 | case ISAR_IIS_IOM2RSP: | 1242 | case ISAR_IIS_IOM2RSP: |
1243 | rcv_mbox(cs, ireg, (u_char *)ireg->par); | 1243 | rcv_mbox(cs, ireg, (u_char *)ireg->par); |
1244 | if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO)) | 1244 | if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO)) |
1245 | == L1_DEB_HSCX) { | 1245 | == L1_DEB_HSCX) { |
1246 | u_char *tp = debbuf; | 1246 | u_char *tp = debbuf; |
1247 | 1247 | ||
1248 | tp += sprintf(debbuf, "msg iis(%x) msb(%x)", | 1248 | tp += sprintf(debbuf, "msg iis(%x) msb(%x)", |
1249 | ireg->iis, ireg->cmsb); | 1249 | ireg->iis, ireg->cmsb); |
1250 | QuickHex(tp, (u_char *)ireg->par, ireg->clsb); | 1250 | QuickHex(tp, (u_char *)ireg->par, ireg->clsb); |
1251 | debugl1(cs, debbuf); | 1251 | debugl1(cs, debbuf); |
1252 | } | 1252 | } |
1253 | break; | 1253 | break; |
1254 | case ISAR_IIS_INVMSG: | 1254 | case ISAR_IIS_INVMSG: |
1255 | rcv_mbox(cs, ireg, debbuf); | 1255 | rcv_mbox(cs, ireg, debbuf); |
1256 | if (cs->debug & L1_DEB_WARN) | 1256 | if (cs->debug & L1_DEB_WARN) |
1257 | debugl1(cs, "invalid msg his:%x", | 1257 | debugl1(cs, "invalid msg his:%x", |
1258 | ireg->cmsb); | 1258 | ireg->cmsb); |
1259 | break; | 1259 | break; |
1260 | default: | 1260 | default: |
1261 | rcv_mbox(cs, ireg, debbuf); | 1261 | rcv_mbox(cs, ireg, debbuf); |
1262 | if (cs->debug & L1_DEB_WARN) | 1262 | if (cs->debug & L1_DEB_WARN) |
1263 | debugl1(cs, "unhandled msg iis(%x) ctrl(%x/%x)", | 1263 | debugl1(cs, "unhandled msg iis(%x) ctrl(%x/%x)", |
1264 | ireg->iis, ireg->cmsb, ireg->clsb); | 1264 | ireg->iis, ireg->cmsb, ireg->clsb); |
1265 | break; | 1265 | break; |
1266 | } | 1266 | } |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | static void | 1269 | static void |
1270 | ftimer_handler(struct BCState *bcs) { | 1270 | ftimer_handler(struct BCState *bcs) { |
1271 | if (bcs->cs->debug) | 1271 | if (bcs->cs->debug) |
1272 | debugl1(bcs->cs, "ftimer flags %04lx", | 1272 | debugl1(bcs->cs, "ftimer flags %04lx", |
1273 | bcs->Flag); | 1273 | bcs->Flag); |
1274 | test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag); | 1274 | test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag); |
1275 | if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) { | 1275 | if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) { |
1276 | schedule_event(bcs, B_LL_CONNECT); | 1276 | schedule_event(bcs, B_LL_CONNECT); |
1277 | } | 1277 | } |
1278 | if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) { | 1278 | if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) { |
1279 | schedule_event(bcs, B_LL_OK); | 1279 | schedule_event(bcs, B_LL_OK); |
1280 | } | 1280 | } |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | static void | 1283 | static void |
1284 | setup_pump(struct BCState *bcs) { | 1284 | setup_pump(struct BCState *bcs) { |
1285 | struct IsdnCardState *cs = bcs->cs; | 1285 | struct IsdnCardState *cs = bcs->cs; |
1286 | u_char dps = SET_DPS(bcs->hw.isar.dpath); | 1286 | u_char dps = SET_DPS(bcs->hw.isar.dpath); |
1287 | u_char ctrl, param[6]; | 1287 | u_char ctrl, param[6]; |
1288 | 1288 | ||
1289 | switch (bcs->mode) { | 1289 | switch (bcs->mode) { |
1290 | case L1_MODE_NULL: | 1290 | case L1_MODE_NULL: |
1291 | case L1_MODE_TRANS: | 1291 | case L1_MODE_TRANS: |
1292 | case L1_MODE_HDLC: | 1292 | case L1_MODE_HDLC: |
1293 | sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL); | 1293 | sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL); |
1294 | break; | 1294 | break; |
1295 | case L1_MODE_V32: | 1295 | case L1_MODE_V32: |
1296 | ctrl = PMOD_DATAMODEM; | 1296 | ctrl = PMOD_DATAMODEM; |
1297 | if (test_bit(BC_FLG_ORIG, &bcs->Flag)) { | 1297 | if (test_bit(BC_FLG_ORIG, &bcs->Flag)) { |
1298 | ctrl |= PCTRL_ORIG; | 1298 | ctrl |= PCTRL_ORIG; |
1299 | param[5] = PV32P6_CTN; | 1299 | param[5] = PV32P6_CTN; |
1300 | } else { | 1300 | } else { |
1301 | param[5] = PV32P6_ATN; | 1301 | param[5] = PV32P6_ATN; |
1302 | } | 1302 | } |
1303 | param[0] = para_TOA; /* 6 db */ | 1303 | param[0] = para_TOA; /* 6 db */ |
1304 | param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | | 1304 | param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | |
1305 | PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; | 1305 | PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; |
1306 | param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; | 1306 | param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; |
1307 | param[3] = PV32P4_UT144; | 1307 | param[3] = PV32P4_UT144; |
1308 | param[4] = PV32P5_UT144; | 1308 | param[4] = PV32P5_UT144; |
1309 | sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param); | 1309 | sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param); |
1310 | break; | 1310 | break; |
1311 | case L1_MODE_FAX: | 1311 | case L1_MODE_FAX: |
1312 | ctrl = PMOD_FAX; | 1312 | ctrl = PMOD_FAX; |
1313 | if (test_bit(BC_FLG_ORIG, &bcs->Flag)) { | 1313 | if (test_bit(BC_FLG_ORIG, &bcs->Flag)) { |
1314 | ctrl |= PCTRL_ORIG; | 1314 | ctrl |= PCTRL_ORIG; |
1315 | param[1] = PFAXP2_CTN; | 1315 | param[1] = PFAXP2_CTN; |
1316 | } else { | 1316 | } else { |
1317 | param[1] = PFAXP2_ATN; | 1317 | param[1] = PFAXP2_ATN; |
1318 | } | 1318 | } |
1319 | param[0] = para_TOA; /* 6 db */ | 1319 | param[0] = para_TOA; /* 6 db */ |
1320 | sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); | 1320 | sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); |
1321 | bcs->hw.isar.state = STFAX_NULL; | 1321 | bcs->hw.isar.state = STFAX_NULL; |
1322 | bcs->hw.isar.newcmd = 0; | 1322 | bcs->hw.isar.newcmd = 0; |
1323 | bcs->hw.isar.newmod = 0; | 1323 | bcs->hw.isar.newmod = 0; |
1324 | test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag); | 1324 | test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag); |
1325 | break; | 1325 | break; |
1326 | } | 1326 | } |
1327 | udelay(1000); | 1327 | udelay(1000); |
1328 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); | 1328 | sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL); |
1329 | udelay(1000); | 1329 | udelay(1000); |
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | static void | 1332 | static void |
1333 | setup_sart(struct BCState *bcs) { | 1333 | setup_sart(struct BCState *bcs) { |
1334 | struct IsdnCardState *cs = bcs->cs; | 1334 | struct IsdnCardState *cs = bcs->cs; |
1335 | u_char dps = SET_DPS(bcs->hw.isar.dpath); | 1335 | u_char dps = SET_DPS(bcs->hw.isar.dpath); |
1336 | u_char ctrl, param[2]; | 1336 | u_char ctrl, param[2]; |
1337 | 1337 | ||
1338 | switch (bcs->mode) { | 1338 | switch (bcs->mode) { |
1339 | case L1_MODE_NULL: | 1339 | case L1_MODE_NULL: |
1340 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, | 1340 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, |
1341 | NULL); | 1341 | NULL); |
1342 | break; | 1342 | break; |
1343 | case L1_MODE_TRANS: | 1343 | case L1_MODE_TRANS: |
1344 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, | 1344 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, |
1345 | "\0\0"); | 1345 | "\0\0"); |
1346 | break; | 1346 | break; |
1347 | case L1_MODE_HDLC: | 1347 | case L1_MODE_HDLC: |
1348 | param[0] = 0; | 1348 | param[0] = 0; |
1349 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, | 1349 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, |
1350 | param); | 1350 | param); |
1351 | break; | 1351 | break; |
1352 | case L1_MODE_V32: | 1352 | case L1_MODE_V32: |
1353 | ctrl = SMODE_V14 | SCTRL_HDMC_BOTH; | 1353 | ctrl = SMODE_V14 | SCTRL_HDMC_BOTH; |
1354 | param[0] = S_P1_CHS_8; | 1354 | param[0] = S_P1_CHS_8; |
1355 | param[1] = S_P2_BFT_DEF; | 1355 | param[1] = S_P2_BFT_DEF; |
1356 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, | 1356 | sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, |
1357 | param); | 1357 | param); |
1358 | break; | 1358 | break; |
1359 | case L1_MODE_FAX: | 1359 | case L1_MODE_FAX: |
1360 | /* SART must not configured with FAX */ | 1360 | /* SART must not configured with FAX */ |
1361 | break; | 1361 | break; |
1362 | } | 1362 | } |
1363 | udelay(1000); | 1363 | udelay(1000); |
1364 | sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); | 1364 | sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); |
1365 | udelay(1000); | 1365 | udelay(1000); |
1366 | } | 1366 | } |
1367 | 1367 | ||
1368 | static void | 1368 | static void |
1369 | setup_iom2(struct BCState *bcs) { | 1369 | setup_iom2(struct BCState *bcs) { |
1370 | struct IsdnCardState *cs = bcs->cs; | 1370 | struct IsdnCardState *cs = bcs->cs; |
1371 | u_char dps = SET_DPS(bcs->hw.isar.dpath); | 1371 | u_char dps = SET_DPS(bcs->hw.isar.dpath); |
1372 | u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0}; | 1372 | u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0}; |
1373 | 1373 | ||
1374 | if (bcs->channel) | 1374 | if (bcs->channel) |
1375 | msg[1] = msg[3] = 1; | 1375 | msg[1] = msg[3] = 1; |
1376 | switch (bcs->mode) { | 1376 | switch (bcs->mode) { |
1377 | case L1_MODE_NULL: | 1377 | case L1_MODE_NULL: |
1378 | cmsb = 0; | 1378 | cmsb = 0; |
1379 | /* dummy slot */ | 1379 | /* dummy slot */ |
1380 | msg[1] = msg[3] = bcs->hw.isar.dpath + 2; | 1380 | msg[1] = msg[3] = bcs->hw.isar.dpath + 2; |
1381 | break; | 1381 | break; |
1382 | case L1_MODE_TRANS: | 1382 | case L1_MODE_TRANS: |
1383 | case L1_MODE_HDLC: | 1383 | case L1_MODE_HDLC: |
1384 | break; | 1384 | break; |
1385 | case L1_MODE_V32: | 1385 | case L1_MODE_V32: |
1386 | case L1_MODE_FAX: | 1386 | case L1_MODE_FAX: |
1387 | cmsb |= IOM_CTRL_ALAW | IOM_CTRL_RCV; | 1387 | cmsb |= IOM_CTRL_ALAW | IOM_CTRL_RCV; |
1388 | break; | 1388 | break; |
1389 | } | 1389 | } |
1390 | sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg); | 1390 | sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg); |
1391 | udelay(1000); | 1391 | udelay(1000); |
1392 | sendmsg(cs, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL); | 1392 | sendmsg(cs, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL); |
1393 | udelay(1000); | 1393 | udelay(1000); |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | static int | 1396 | static int |
1397 | modeisar(struct BCState *bcs, int mode, int bc) | 1397 | modeisar(struct BCState *bcs, int mode, int bc) |
1398 | { | 1398 | { |
1399 | struct IsdnCardState *cs = bcs->cs; | 1399 | struct IsdnCardState *cs = bcs->cs; |
1400 | 1400 | ||
1401 | /* Here we are selecting the best datapath for requested mode */ | 1401 | /* Here we are selecting the best datapath for requested mode */ |
1402 | if (bcs->mode == L1_MODE_NULL) { /* New Setup */ | 1402 | if (bcs->mode == L1_MODE_NULL) { /* New Setup */ |
1403 | bcs->channel = bc; | 1403 | bcs->channel = bc; |
1404 | switch (mode) { | 1404 | switch (mode) { |
1405 | case L1_MODE_NULL: /* init */ | 1405 | case L1_MODE_NULL: /* init */ |
1406 | if (!bcs->hw.isar.dpath) | 1406 | if (!bcs->hw.isar.dpath) |
1407 | /* no init for dpath 0 */ | 1407 | /* no init for dpath 0 */ |
1408 | return (0); | 1408 | return (0); |
1409 | break; | 1409 | break; |
1410 | case L1_MODE_TRANS: | 1410 | case L1_MODE_TRANS: |
1411 | case L1_MODE_HDLC: | 1411 | case L1_MODE_HDLC: |
1412 | /* best is datapath 2 */ | 1412 | /* best is datapath 2 */ |
1413 | if (!test_and_set_bit(ISAR_DP2_USE, | 1413 | if (!test_and_set_bit(ISAR_DP2_USE, |
1414 | &bcs->hw.isar.reg->Flags)) | 1414 | &bcs->hw.isar.reg->Flags)) |
1415 | bcs->hw.isar.dpath = 2; | 1415 | bcs->hw.isar.dpath = 2; |
1416 | else if (!test_and_set_bit(ISAR_DP1_USE, | 1416 | else if (!test_and_set_bit(ISAR_DP1_USE, |
1417 | &bcs->hw.isar.reg->Flags)) | 1417 | &bcs->hw.isar.reg->Flags)) |
1418 | bcs->hw.isar.dpath = 1; | 1418 | bcs->hw.isar.dpath = 1; |
1419 | else { | 1419 | else { |
1420 | printk(KERN_WARNING"isar modeisar both pathes in use\n"); | 1420 | printk(KERN_WARNING"isar modeisar both paths in use\n"); |
1421 | return (1); | 1421 | return (1); |
1422 | } | 1422 | } |
1423 | break; | 1423 | break; |
1424 | case L1_MODE_V32: | 1424 | case L1_MODE_V32: |
1425 | case L1_MODE_FAX: | 1425 | case L1_MODE_FAX: |
1426 | /* only datapath 1 */ | 1426 | /* only datapath 1 */ |
1427 | if (!test_and_set_bit(ISAR_DP1_USE, | 1427 | if (!test_and_set_bit(ISAR_DP1_USE, |
1428 | &bcs->hw.isar.reg->Flags)) | 1428 | &bcs->hw.isar.reg->Flags)) |
1429 | bcs->hw.isar.dpath = 1; | 1429 | bcs->hw.isar.dpath = 1; |
1430 | else { | 1430 | else { |
1431 | printk(KERN_WARNING"isar modeisar analog functions only with DP1\n"); | 1431 | printk(KERN_WARNING"isar modeisar analog functions only with DP1\n"); |
1432 | debugl1(cs, "isar modeisar analog functions only with DP1"); | 1432 | debugl1(cs, "isar modeisar analog functions only with DP1"); |
1433 | return (1); | 1433 | return (1); |
1434 | } | 1434 | } |
1435 | break; | 1435 | break; |
1436 | } | 1436 | } |
1437 | } | 1437 | } |
1438 | if (cs->debug & L1_DEB_HSCX) | 1438 | if (cs->debug & L1_DEB_HSCX) |
1439 | debugl1(cs, "isar dp%d mode %d->%d ichan %d", | 1439 | debugl1(cs, "isar dp%d mode %d->%d ichan %d", |
1440 | bcs->hw.isar.dpath, bcs->mode, mode, bc); | 1440 | bcs->hw.isar.dpath, bcs->mode, mode, bc); |
1441 | bcs->mode = mode; | 1441 | bcs->mode = mode; |
1442 | setup_pump(bcs); | 1442 | setup_pump(bcs); |
1443 | setup_iom2(bcs); | 1443 | setup_iom2(bcs); |
1444 | setup_sart(bcs); | 1444 | setup_sart(bcs); |
1445 | if (bcs->mode == L1_MODE_NULL) { | 1445 | if (bcs->mode == L1_MODE_NULL) { |
1446 | /* Clear resources */ | 1446 | /* Clear resources */ |
1447 | if (bcs->hw.isar.dpath == 1) | 1447 | if (bcs->hw.isar.dpath == 1) |
1448 | test_and_clear_bit(ISAR_DP1_USE, &bcs->hw.isar.reg->Flags); | 1448 | test_and_clear_bit(ISAR_DP1_USE, &bcs->hw.isar.reg->Flags); |
1449 | else if (bcs->hw.isar.dpath == 2) | 1449 | else if (bcs->hw.isar.dpath == 2) |
1450 | test_and_clear_bit(ISAR_DP2_USE, &bcs->hw.isar.reg->Flags); | 1450 | test_and_clear_bit(ISAR_DP2_USE, &bcs->hw.isar.reg->Flags); |
1451 | bcs->hw.isar.dpath = 0; | 1451 | bcs->hw.isar.dpath = 0; |
1452 | } | 1452 | } |
1453 | return (0); | 1453 | return (0); |
1454 | } | 1454 | } |
1455 | 1455 | ||
1456 | static void | 1456 | static void |
1457 | isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para) | 1457 | isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para) |
1458 | { | 1458 | { |
1459 | struct IsdnCardState *cs = bcs->cs; | 1459 | struct IsdnCardState *cs = bcs->cs; |
1460 | u_char dps = SET_DPS(bcs->hw.isar.dpath); | 1460 | u_char dps = SET_DPS(bcs->hw.isar.dpath); |
1461 | u_char ctrl = 0, nom = 0, p1 = 0; | 1461 | u_char ctrl = 0, nom = 0, p1 = 0; |
1462 | 1462 | ||
1463 | switch (cmd) { | 1463 | switch (cmd) { |
1464 | case ISDN_FAX_CLASS1_FTM: | 1464 | case ISDN_FAX_CLASS1_FTM: |
1465 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); | 1465 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); |
1466 | if (bcs->hw.isar.state == STFAX_READY) { | 1466 | if (bcs->hw.isar.state == STFAX_READY) { |
1467 | p1 = para; | 1467 | p1 = para; |
1468 | ctrl = PCTRL_CMD_FTM; | 1468 | ctrl = PCTRL_CMD_FTM; |
1469 | nom = 1; | 1469 | nom = 1; |
1470 | bcs->hw.isar.state = STFAX_LINE; | 1470 | bcs->hw.isar.state = STFAX_LINE; |
1471 | bcs->hw.isar.cmd = ctrl; | 1471 | bcs->hw.isar.cmd = ctrl; |
1472 | bcs->hw.isar.mod = para; | 1472 | bcs->hw.isar.mod = para; |
1473 | bcs->hw.isar.newmod = 0; | 1473 | bcs->hw.isar.newmod = 0; |
1474 | bcs->hw.isar.newcmd = 0; | 1474 | bcs->hw.isar.newcmd = 0; |
1475 | bcs->hw.isar.try_mod = 3; | 1475 | bcs->hw.isar.try_mod = 3; |
1476 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && | 1476 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && |
1477 | (bcs->hw.isar.cmd == PCTRL_CMD_FTM) && | 1477 | (bcs->hw.isar.cmd == PCTRL_CMD_FTM) && |
1478 | (bcs->hw.isar.mod == para)) { | 1478 | (bcs->hw.isar.mod == para)) { |
1479 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); | 1479 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); |
1480 | } else { | 1480 | } else { |
1481 | bcs->hw.isar.newmod = para; | 1481 | bcs->hw.isar.newmod = para; |
1482 | bcs->hw.isar.newcmd = PCTRL_CMD_FTM; | 1482 | bcs->hw.isar.newcmd = PCTRL_CMD_FTM; |
1483 | nom = 0; | 1483 | nom = 0; |
1484 | ctrl = PCTRL_CMD_ESC; | 1484 | ctrl = PCTRL_CMD_ESC; |
1485 | bcs->hw.isar.state = STFAX_ESCAPE; | 1485 | bcs->hw.isar.state = STFAX_ESCAPE; |
1486 | } | 1486 | } |
1487 | break; | 1487 | break; |
1488 | case ISDN_FAX_CLASS1_FTH: | 1488 | case ISDN_FAX_CLASS1_FTH: |
1489 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); | 1489 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); |
1490 | if (bcs->hw.isar.state == STFAX_READY) { | 1490 | if (bcs->hw.isar.state == STFAX_READY) { |
1491 | p1 = para; | 1491 | p1 = para; |
1492 | ctrl = PCTRL_CMD_FTH; | 1492 | ctrl = PCTRL_CMD_FTH; |
1493 | nom = 1; | 1493 | nom = 1; |
1494 | bcs->hw.isar.state = STFAX_LINE; | 1494 | bcs->hw.isar.state = STFAX_LINE; |
1495 | bcs->hw.isar.cmd = ctrl; | 1495 | bcs->hw.isar.cmd = ctrl; |
1496 | bcs->hw.isar.mod = para; | 1496 | bcs->hw.isar.mod = para; |
1497 | bcs->hw.isar.newmod = 0; | 1497 | bcs->hw.isar.newmod = 0; |
1498 | bcs->hw.isar.newcmd = 0; | 1498 | bcs->hw.isar.newcmd = 0; |
1499 | bcs->hw.isar.try_mod = 3; | 1499 | bcs->hw.isar.try_mod = 3; |
1500 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && | 1500 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && |
1501 | (bcs->hw.isar.cmd == PCTRL_CMD_FTH) && | 1501 | (bcs->hw.isar.cmd == PCTRL_CMD_FTH) && |
1502 | (bcs->hw.isar.mod == para)) { | 1502 | (bcs->hw.isar.mod == para)) { |
1503 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); | 1503 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); |
1504 | } else { | 1504 | } else { |
1505 | bcs->hw.isar.newmod = para; | 1505 | bcs->hw.isar.newmod = para; |
1506 | bcs->hw.isar.newcmd = PCTRL_CMD_FTH; | 1506 | bcs->hw.isar.newcmd = PCTRL_CMD_FTH; |
1507 | nom = 0; | 1507 | nom = 0; |
1508 | ctrl = PCTRL_CMD_ESC; | 1508 | ctrl = PCTRL_CMD_ESC; |
1509 | bcs->hw.isar.state = STFAX_ESCAPE; | 1509 | bcs->hw.isar.state = STFAX_ESCAPE; |
1510 | } | 1510 | } |
1511 | break; | 1511 | break; |
1512 | case ISDN_FAX_CLASS1_FRM: | 1512 | case ISDN_FAX_CLASS1_FRM: |
1513 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); | 1513 | test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); |
1514 | if (bcs->hw.isar.state == STFAX_READY) { | 1514 | if (bcs->hw.isar.state == STFAX_READY) { |
1515 | p1 = para; | 1515 | p1 = para; |
1516 | ctrl = PCTRL_CMD_FRM; | 1516 | ctrl = PCTRL_CMD_FRM; |
1517 | nom = 1; | 1517 | nom = 1; |
1518 | bcs->hw.isar.state = STFAX_LINE; | 1518 | bcs->hw.isar.state = STFAX_LINE; |
1519 | bcs->hw.isar.cmd = ctrl; | 1519 | bcs->hw.isar.cmd = ctrl; |
1520 | bcs->hw.isar.mod = para; | 1520 | bcs->hw.isar.mod = para; |
1521 | bcs->hw.isar.newmod = 0; | 1521 | bcs->hw.isar.newmod = 0; |
1522 | bcs->hw.isar.newcmd = 0; | 1522 | bcs->hw.isar.newcmd = 0; |
1523 | bcs->hw.isar.try_mod = 3; | 1523 | bcs->hw.isar.try_mod = 3; |
1524 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && | 1524 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && |
1525 | (bcs->hw.isar.cmd == PCTRL_CMD_FRM) && | 1525 | (bcs->hw.isar.cmd == PCTRL_CMD_FRM) && |
1526 | (bcs->hw.isar.mod == para)) { | 1526 | (bcs->hw.isar.mod == para)) { |
1527 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); | 1527 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); |
1528 | } else { | 1528 | } else { |
1529 | bcs->hw.isar.newmod = para; | 1529 | bcs->hw.isar.newmod = para; |
1530 | bcs->hw.isar.newcmd = PCTRL_CMD_FRM; | 1530 | bcs->hw.isar.newcmd = PCTRL_CMD_FRM; |
1531 | nom = 0; | 1531 | nom = 0; |
1532 | ctrl = PCTRL_CMD_ESC; | 1532 | ctrl = PCTRL_CMD_ESC; |
1533 | bcs->hw.isar.state = STFAX_ESCAPE; | 1533 | bcs->hw.isar.state = STFAX_ESCAPE; |
1534 | } | 1534 | } |
1535 | break; | 1535 | break; |
1536 | case ISDN_FAX_CLASS1_FRH: | 1536 | case ISDN_FAX_CLASS1_FRH: |
1537 | test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag); | 1537 | test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag); |
1538 | if (bcs->hw.isar.state == STFAX_READY) { | 1538 | if (bcs->hw.isar.state == STFAX_READY) { |
1539 | p1 = para; | 1539 | p1 = para; |
1540 | ctrl = PCTRL_CMD_FRH; | 1540 | ctrl = PCTRL_CMD_FRH; |
1541 | nom = 1; | 1541 | nom = 1; |
1542 | bcs->hw.isar.state = STFAX_LINE; | 1542 | bcs->hw.isar.state = STFAX_LINE; |
1543 | bcs->hw.isar.cmd = ctrl; | 1543 | bcs->hw.isar.cmd = ctrl; |
1544 | bcs->hw.isar.mod = para; | 1544 | bcs->hw.isar.mod = para; |
1545 | bcs->hw.isar.newmod = 0; | 1545 | bcs->hw.isar.newmod = 0; |
1546 | bcs->hw.isar.newcmd = 0; | 1546 | bcs->hw.isar.newcmd = 0; |
1547 | bcs->hw.isar.try_mod = 3; | 1547 | bcs->hw.isar.try_mod = 3; |
1548 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && | 1548 | } else if ((bcs->hw.isar.state == STFAX_ACTIV) && |
1549 | (bcs->hw.isar.cmd == PCTRL_CMD_FRH) && | 1549 | (bcs->hw.isar.cmd == PCTRL_CMD_FRH) && |
1550 | (bcs->hw.isar.mod == para)) { | 1550 | (bcs->hw.isar.mod == para)) { |
1551 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); | 1551 | ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT); |
1552 | } else { | 1552 | } else { |
1553 | bcs->hw.isar.newmod = para; | 1553 | bcs->hw.isar.newmod = para; |
1554 | bcs->hw.isar.newcmd = PCTRL_CMD_FRH; | 1554 | bcs->hw.isar.newcmd = PCTRL_CMD_FRH; |
1555 | nom = 0; | 1555 | nom = 0; |
1556 | ctrl = PCTRL_CMD_ESC; | 1556 | ctrl = PCTRL_CMD_ESC; |
1557 | bcs->hw.isar.state = STFAX_ESCAPE; | 1557 | bcs->hw.isar.state = STFAX_ESCAPE; |
1558 | } | 1558 | } |
1559 | break; | 1559 | break; |
1560 | case ISDN_FAXPUMP_HALT: | 1560 | case ISDN_FAXPUMP_HALT: |
1561 | bcs->hw.isar.state = STFAX_NULL; | 1561 | bcs->hw.isar.state = STFAX_NULL; |
1562 | nom = 0; | 1562 | nom = 0; |
1563 | ctrl = PCTRL_CMD_HALT; | 1563 | ctrl = PCTRL_CMD_HALT; |
1564 | break; | 1564 | break; |
1565 | } | 1565 | } |
1566 | if (ctrl) | 1566 | if (ctrl) |
1567 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); | 1567 | sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); |
1568 | } | 1568 | } |
1569 | 1569 | ||
1570 | static void | 1570 | static void |
1571 | isar_setup(struct IsdnCardState *cs) | 1571 | isar_setup(struct IsdnCardState *cs) |
1572 | { | 1572 | { |
1573 | u_char msg; | 1573 | u_char msg; |
1574 | int i; | 1574 | int i; |
1575 | 1575 | ||
1576 | /* Dpath 1, 2 */ | 1576 | /* Dpath 1, 2 */ |
1577 | msg = 61; | 1577 | msg = 61; |
1578 | for (i = 0; i < 2; i++) { | 1578 | for (i = 0; i < 2; i++) { |
1579 | /* Buffer Config */ | 1579 | /* Buffer Config */ |
1580 | sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) | | 1580 | sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) | |
1581 | ISAR_HIS_P12CFG, 4, 1, &msg); | 1581 | ISAR_HIS_P12CFG, 4, 1, &msg); |
1582 | cs->bcs[i].hw.isar.mml = msg; | 1582 | cs->bcs[i].hw.isar.mml = msg; |
1583 | cs->bcs[i].mode = 0; | 1583 | cs->bcs[i].mode = 0; |
1584 | cs->bcs[i].hw.isar.dpath = i + 1; | 1584 | cs->bcs[i].hw.isar.dpath = i + 1; |
1585 | modeisar(&cs->bcs[i], 0, 0); | 1585 | modeisar(&cs->bcs[i], 0, 0); |
1586 | INIT_WORK(&cs->bcs[i].tqueue, isar_bh); | 1586 | INIT_WORK(&cs->bcs[i].tqueue, isar_bh); |
1587 | } | 1587 | } |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | static void | 1590 | static void |
1591 | isar_l2l1(struct PStack *st, int pr, void *arg) | 1591 | isar_l2l1(struct PStack *st, int pr, void *arg) |
1592 | { | 1592 | { |
1593 | struct BCState *bcs = st->l1.bcs; | 1593 | struct BCState *bcs = st->l1.bcs; |
1594 | struct sk_buff *skb = arg; | 1594 | struct sk_buff *skb = arg; |
1595 | int ret; | 1595 | int ret; |
1596 | u_long flags; | 1596 | u_long flags; |
1597 | 1597 | ||
1598 | switch (pr) { | 1598 | switch (pr) { |
1599 | case (PH_DATA | REQUEST): | 1599 | case (PH_DATA | REQUEST): |
1600 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1600 | spin_lock_irqsave(&bcs->cs->lock, flags); |
1601 | if (bcs->tx_skb) { | 1601 | if (bcs->tx_skb) { |
1602 | skb_queue_tail(&bcs->squeue, skb); | 1602 | skb_queue_tail(&bcs->squeue, skb); |
1603 | } else { | 1603 | } else { |
1604 | bcs->tx_skb = skb; | 1604 | bcs->tx_skb = skb; |
1605 | test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); | 1605 | test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); |
1606 | if (bcs->cs->debug & L1_DEB_HSCX) | 1606 | if (bcs->cs->debug & L1_DEB_HSCX) |
1607 | debugl1(bcs->cs, "DRQ set BC_FLG_BUSY"); | 1607 | debugl1(bcs->cs, "DRQ set BC_FLG_BUSY"); |
1608 | bcs->hw.isar.txcnt = 0; | 1608 | bcs->hw.isar.txcnt = 0; |
1609 | bcs->cs->BC_Send_Data(bcs); | 1609 | bcs->cs->BC_Send_Data(bcs); |
1610 | } | 1610 | } |
1611 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1611 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1612 | break; | 1612 | break; |
1613 | case (PH_PULL | INDICATION): | 1613 | case (PH_PULL | INDICATION): |
1614 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1614 | spin_lock_irqsave(&bcs->cs->lock, flags); |
1615 | if (bcs->tx_skb) { | 1615 | if (bcs->tx_skb) { |
1616 | printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n"); | 1616 | printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n"); |
1617 | } else { | 1617 | } else { |
1618 | test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); | 1618 | test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); |
1619 | if (bcs->cs->debug & L1_DEB_HSCX) | 1619 | if (bcs->cs->debug & L1_DEB_HSCX) |
1620 | debugl1(bcs->cs, "PUI set BC_FLG_BUSY"); | 1620 | debugl1(bcs->cs, "PUI set BC_FLG_BUSY"); |
1621 | bcs->tx_skb = skb; | 1621 | bcs->tx_skb = skb; |
1622 | bcs->hw.isar.txcnt = 0; | 1622 | bcs->hw.isar.txcnt = 0; |
1623 | bcs->cs->BC_Send_Data(bcs); | 1623 | bcs->cs->BC_Send_Data(bcs); |
1624 | } | 1624 | } |
1625 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1625 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1626 | break; | 1626 | break; |
1627 | case (PH_PULL | REQUEST): | 1627 | case (PH_PULL | REQUEST): |
1628 | if (!bcs->tx_skb) { | 1628 | if (!bcs->tx_skb) { |
1629 | test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | 1629 | test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); |
1630 | st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); | 1630 | st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); |
1631 | } else | 1631 | } else |
1632 | test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | 1632 | test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); |
1633 | break; | 1633 | break; |
1634 | case (PH_ACTIVATE | REQUEST): | 1634 | case (PH_ACTIVATE | REQUEST): |
1635 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1635 | spin_lock_irqsave(&bcs->cs->lock, flags); |
1636 | test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); | 1636 | test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); |
1637 | bcs->hw.isar.conmsg[0] = 0; | 1637 | bcs->hw.isar.conmsg[0] = 0; |
1638 | if (test_bit(FLG_ORIG, &st->l2.flag)) | 1638 | if (test_bit(FLG_ORIG, &st->l2.flag)) |
1639 | test_and_set_bit(BC_FLG_ORIG, &bcs->Flag); | 1639 | test_and_set_bit(BC_FLG_ORIG, &bcs->Flag); |
1640 | else | 1640 | else |
1641 | test_and_clear_bit(BC_FLG_ORIG, &bcs->Flag); | 1641 | test_and_clear_bit(BC_FLG_ORIG, &bcs->Flag); |
1642 | switch (st->l1.mode) { | 1642 | switch (st->l1.mode) { |
1643 | case L1_MODE_TRANS: | 1643 | case L1_MODE_TRANS: |
1644 | case L1_MODE_HDLC: | 1644 | case L1_MODE_HDLC: |
1645 | ret = modeisar(bcs, st->l1.mode, st->l1.bc); | 1645 | ret = modeisar(bcs, st->l1.mode, st->l1.bc); |
1646 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1646 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1647 | if (ret) | 1647 | if (ret) |
1648 | l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); | 1648 | l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); |
1649 | else | 1649 | else |
1650 | l1_msg_b(st, PH_ACTIVATE | REQUEST, arg); | 1650 | l1_msg_b(st, PH_ACTIVATE | REQUEST, arg); |
1651 | break; | 1651 | break; |
1652 | case L1_MODE_V32: | 1652 | case L1_MODE_V32: |
1653 | case L1_MODE_FAX: | 1653 | case L1_MODE_FAX: |
1654 | ret = modeisar(bcs, st->l1.mode, st->l1.bc); | 1654 | ret = modeisar(bcs, st->l1.mode, st->l1.bc); |
1655 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1655 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1656 | if (ret) | 1656 | if (ret) |
1657 | l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); | 1657 | l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); |
1658 | break; | 1658 | break; |
1659 | default: | 1659 | default: |
1660 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1660 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1661 | break; | 1661 | break; |
1662 | } | 1662 | } |
1663 | break; | 1663 | break; |
1664 | case (PH_DEACTIVATE | REQUEST): | 1664 | case (PH_DEACTIVATE | REQUEST): |
1665 | l1_msg_b(st, pr, arg); | 1665 | l1_msg_b(st, pr, arg); |
1666 | break; | 1666 | break; |
1667 | case (PH_DEACTIVATE | CONFIRM): | 1667 | case (PH_DEACTIVATE | CONFIRM): |
1668 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1668 | spin_lock_irqsave(&bcs->cs->lock, flags); |
1669 | switch (st->l1.mode) { | 1669 | switch (st->l1.mode) { |
1670 | case L1_MODE_TRANS: | 1670 | case L1_MODE_TRANS: |
1671 | case L1_MODE_HDLC: | 1671 | case L1_MODE_HDLC: |
1672 | case L1_MODE_V32: | 1672 | case L1_MODE_V32: |
1673 | break; | 1673 | break; |
1674 | case L1_MODE_FAX: | 1674 | case L1_MODE_FAX: |
1675 | isar_pump_cmd(bcs, ISDN_FAXPUMP_HALT, 0); | 1675 | isar_pump_cmd(bcs, ISDN_FAXPUMP_HALT, 0); |
1676 | break; | 1676 | break; |
1677 | } | 1677 | } |
1678 | test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); | 1678 | test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); |
1679 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | 1679 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); |
1680 | if (bcs->cs->debug & L1_DEB_HSCX) | 1680 | if (bcs->cs->debug & L1_DEB_HSCX) |
1681 | debugl1(bcs->cs, "PDAC clear BC_FLG_BUSY"); | 1681 | debugl1(bcs->cs, "PDAC clear BC_FLG_BUSY"); |
1682 | modeisar(bcs, 0, st->l1.bc); | 1682 | modeisar(bcs, 0, st->l1.bc); |
1683 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1683 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1684 | st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); | 1684 | st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); |
1685 | break; | 1685 | break; |
1686 | } | 1686 | } |
1687 | } | 1687 | } |
1688 | 1688 | ||
1689 | static void | 1689 | static void |
1690 | close_isarstate(struct BCState *bcs) | 1690 | close_isarstate(struct BCState *bcs) |
1691 | { | 1691 | { |
1692 | modeisar(bcs, 0, bcs->channel); | 1692 | modeisar(bcs, 0, bcs->channel); |
1693 | if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { | 1693 | if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { |
1694 | kfree(bcs->hw.isar.rcvbuf); | 1694 | kfree(bcs->hw.isar.rcvbuf); |
1695 | bcs->hw.isar.rcvbuf = NULL; | 1695 | bcs->hw.isar.rcvbuf = NULL; |
1696 | skb_queue_purge(&bcs->rqueue); | 1696 | skb_queue_purge(&bcs->rqueue); |
1697 | skb_queue_purge(&bcs->squeue); | 1697 | skb_queue_purge(&bcs->squeue); |
1698 | if (bcs->tx_skb) { | 1698 | if (bcs->tx_skb) { |
1699 | dev_kfree_skb_any(bcs->tx_skb); | 1699 | dev_kfree_skb_any(bcs->tx_skb); |
1700 | bcs->tx_skb = NULL; | 1700 | bcs->tx_skb = NULL; |
1701 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | 1701 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); |
1702 | if (bcs->cs->debug & L1_DEB_HSCX) | 1702 | if (bcs->cs->debug & L1_DEB_HSCX) |
1703 | debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY"); | 1703 | debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY"); |
1704 | } | 1704 | } |
1705 | } | 1705 | } |
1706 | del_timer(&bcs->hw.isar.ftimer); | 1706 | del_timer(&bcs->hw.isar.ftimer); |
1707 | } | 1707 | } |
1708 | 1708 | ||
1709 | static int | 1709 | static int |
1710 | open_isarstate(struct IsdnCardState *cs, struct BCState *bcs) | 1710 | open_isarstate(struct IsdnCardState *cs, struct BCState *bcs) |
1711 | { | 1711 | { |
1712 | if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { | 1712 | if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { |
1713 | if (!(bcs->hw.isar.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { | 1713 | if (!(bcs->hw.isar.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { |
1714 | printk(KERN_WARNING | 1714 | printk(KERN_WARNING |
1715 | "HiSax: No memory for isar.rcvbuf\n"); | 1715 | "HiSax: No memory for isar.rcvbuf\n"); |
1716 | return (1); | 1716 | return (1); |
1717 | } | 1717 | } |
1718 | skb_queue_head_init(&bcs->rqueue); | 1718 | skb_queue_head_init(&bcs->rqueue); |
1719 | skb_queue_head_init(&bcs->squeue); | 1719 | skb_queue_head_init(&bcs->squeue); |
1720 | } | 1720 | } |
1721 | bcs->tx_skb = NULL; | 1721 | bcs->tx_skb = NULL; |
1722 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | 1722 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); |
1723 | if (cs->debug & L1_DEB_HSCX) | 1723 | if (cs->debug & L1_DEB_HSCX) |
1724 | debugl1(cs, "openisar clear BC_FLG_BUSY"); | 1724 | debugl1(cs, "openisar clear BC_FLG_BUSY"); |
1725 | bcs->event = 0; | 1725 | bcs->event = 0; |
1726 | bcs->hw.isar.rcvidx = 0; | 1726 | bcs->hw.isar.rcvidx = 0; |
1727 | bcs->tx_cnt = 0; | 1727 | bcs->tx_cnt = 0; |
1728 | return (0); | 1728 | return (0); |
1729 | } | 1729 | } |
1730 | 1730 | ||
1731 | static int | 1731 | static int |
1732 | setstack_isar(struct PStack *st, struct BCState *bcs) | 1732 | setstack_isar(struct PStack *st, struct BCState *bcs) |
1733 | { | 1733 | { |
1734 | bcs->channel = st->l1.bc; | 1734 | bcs->channel = st->l1.bc; |
1735 | if (open_isarstate(st->l1.hardware, bcs)) | 1735 | if (open_isarstate(st->l1.hardware, bcs)) |
1736 | return (-1); | 1736 | return (-1); |
1737 | st->l1.bcs = bcs; | 1737 | st->l1.bcs = bcs; |
1738 | st->l2.l2l1 = isar_l2l1; | 1738 | st->l2.l2l1 = isar_l2l1; |
1739 | setstack_manager(st); | 1739 | setstack_manager(st); |
1740 | bcs->st = st; | 1740 | bcs->st = st; |
1741 | setstack_l1_B(st); | 1741 | setstack_l1_B(st); |
1742 | return (0); | 1742 | return (0); |
1743 | } | 1743 | } |
1744 | 1744 | ||
1745 | int | 1745 | int |
1746 | isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { | 1746 | isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { |
1747 | u_long adr; | 1747 | u_long adr; |
1748 | int features, i; | 1748 | int features, i; |
1749 | struct BCState *bcs; | 1749 | struct BCState *bcs; |
1750 | 1750 | ||
1751 | if (cs->debug & L1_DEB_HSCX) | 1751 | if (cs->debug & L1_DEB_HSCX) |
1752 | debugl1(cs, "isar_auxcmd cmd/ch %x/%ld", ic->command, ic->arg); | 1752 | debugl1(cs, "isar_auxcmd cmd/ch %x/%ld", ic->command, ic->arg); |
1753 | switch (ic->command) { | 1753 | switch (ic->command) { |
1754 | case (ISDN_CMD_FAXCMD): | 1754 | case (ISDN_CMD_FAXCMD): |
1755 | bcs = cs->channel[ic->arg].bcs; | 1755 | bcs = cs->channel[ic->arg].bcs; |
1756 | if (cs->debug & L1_DEB_HSCX) | 1756 | if (cs->debug & L1_DEB_HSCX) |
1757 | debugl1(cs, "isar_auxcmd cmd/subcmd %d/%d", | 1757 | debugl1(cs, "isar_auxcmd cmd/subcmd %d/%d", |
1758 | ic->parm.aux.cmd, ic->parm.aux.subcmd); | 1758 | ic->parm.aux.cmd, ic->parm.aux.subcmd); |
1759 | switch (ic->parm.aux.cmd) { | 1759 | switch (ic->parm.aux.cmd) { |
1760 | case ISDN_FAX_CLASS1_CTRL: | 1760 | case ISDN_FAX_CLASS1_CTRL: |
1761 | if (ic->parm.aux.subcmd == ETX) | 1761 | if (ic->parm.aux.subcmd == ETX) |
1762 | test_and_set_bit(BC_FLG_DLEETX, | 1762 | test_and_set_bit(BC_FLG_DLEETX, |
1763 | &bcs->Flag); | 1763 | &bcs->Flag); |
1764 | break; | 1764 | break; |
1765 | case ISDN_FAX_CLASS1_FTS: | 1765 | case ISDN_FAX_CLASS1_FTS: |
1766 | if (ic->parm.aux.subcmd == AT_QUERY) { | 1766 | if (ic->parm.aux.subcmd == AT_QUERY) { |
1767 | ic->command = ISDN_STAT_FAXIND; | 1767 | ic->command = ISDN_STAT_FAXIND; |
1768 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; | 1768 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; |
1769 | cs->iif.statcallb(ic); | 1769 | cs->iif.statcallb(ic); |
1770 | return (0); | 1770 | return (0); |
1771 | } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { | 1771 | } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { |
1772 | strcpy(ic->parm.aux.para, "0-255"); | 1772 | strcpy(ic->parm.aux.para, "0-255"); |
1773 | ic->command = ISDN_STAT_FAXIND; | 1773 | ic->command = ISDN_STAT_FAXIND; |
1774 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; | 1774 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; |
1775 | cs->iif.statcallb(ic); | 1775 | cs->iif.statcallb(ic); |
1776 | return (0); | 1776 | return (0); |
1777 | } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { | 1777 | } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { |
1778 | if (cs->debug & L1_DEB_HSCX) | 1778 | if (cs->debug & L1_DEB_HSCX) |
1779 | debugl1(cs, "isar_auxcmd %s=%d", | 1779 | debugl1(cs, "isar_auxcmd %s=%d", |
1780 | FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); | 1780 | FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); |
1781 | if (bcs->hw.isar.state == STFAX_READY) { | 1781 | if (bcs->hw.isar.state == STFAX_READY) { |
1782 | if (!ic->parm.aux.para[0]) { | 1782 | if (!ic->parm.aux.para[0]) { |
1783 | ic->command = ISDN_STAT_FAXIND; | 1783 | ic->command = ISDN_STAT_FAXIND; |
1784 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; | 1784 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; |
1785 | cs->iif.statcallb(ic); | 1785 | cs->iif.statcallb(ic); |
1786 | return (0); | 1786 | return (0); |
1787 | } | 1787 | } |
1788 | if (!test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) { | 1788 | if (!test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) { |
1789 | /* n*10 ms */ | 1789 | /* n*10 ms */ |
1790 | bcs->hw.isar.ftimer.expires = | 1790 | bcs->hw.isar.ftimer.expires = |
1791 | jiffies + ((ic->parm.aux.para[0] * 10 * HZ) / 1000); | 1791 | jiffies + ((ic->parm.aux.para[0] * 10 * HZ) / 1000); |
1792 | test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag); | 1792 | test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag); |
1793 | add_timer(&bcs->hw.isar.ftimer); | 1793 | add_timer(&bcs->hw.isar.ftimer); |
1794 | return (0); | 1794 | return (0); |
1795 | } else { | 1795 | } else { |
1796 | if (cs->debug) | 1796 | if (cs->debug) |
1797 | debugl1(cs, "isar FTS=%d and FTI busy", | 1797 | debugl1(cs, "isar FTS=%d and FTI busy", |
1798 | ic->parm.aux.para[0]); | 1798 | ic->parm.aux.para[0]); |
1799 | } | 1799 | } |
1800 | } else { | 1800 | } else { |
1801 | if (cs->debug) | 1801 | if (cs->debug) |
1802 | debugl1(cs, "isar FTS=%d and isar.state not ready(%x)", | 1802 | debugl1(cs, "isar FTS=%d and isar.state not ready(%x)", |
1803 | ic->parm.aux.para[0], bcs->hw.isar.state); | 1803 | ic->parm.aux.para[0], bcs->hw.isar.state); |
1804 | } | 1804 | } |
1805 | ic->command = ISDN_STAT_FAXIND; | 1805 | ic->command = ISDN_STAT_FAXIND; |
1806 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR; | 1806 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR; |
1807 | cs->iif.statcallb(ic); | 1807 | cs->iif.statcallb(ic); |
1808 | } | 1808 | } |
1809 | break; | 1809 | break; |
1810 | case ISDN_FAX_CLASS1_FRM: | 1810 | case ISDN_FAX_CLASS1_FRM: |
1811 | case ISDN_FAX_CLASS1_FRH: | 1811 | case ISDN_FAX_CLASS1_FRH: |
1812 | case ISDN_FAX_CLASS1_FTM: | 1812 | case ISDN_FAX_CLASS1_FTM: |
1813 | case ISDN_FAX_CLASS1_FTH: | 1813 | case ISDN_FAX_CLASS1_FTH: |
1814 | if (ic->parm.aux.subcmd == AT_QUERY) { | 1814 | if (ic->parm.aux.subcmd == AT_QUERY) { |
1815 | sprintf(ic->parm.aux.para, | 1815 | sprintf(ic->parm.aux.para, |
1816 | "%d", bcs->hw.isar.mod); | 1816 | "%d", bcs->hw.isar.mod); |
1817 | ic->command = ISDN_STAT_FAXIND; | 1817 | ic->command = ISDN_STAT_FAXIND; |
1818 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; | 1818 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; |
1819 | cs->iif.statcallb(ic); | 1819 | cs->iif.statcallb(ic); |
1820 | return (0); | 1820 | return (0); |
1821 | } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { | 1821 | } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { |
1822 | char *p = ic->parm.aux.para; | 1822 | char *p = ic->parm.aux.para; |
1823 | for (i = 0; i < FAXMODCNT; i++) | 1823 | for (i = 0; i < FAXMODCNT; i++) |
1824 | if ((1 << i) & modmask) | 1824 | if ((1 << i) & modmask) |
1825 | p += sprintf(p, "%d,", faxmodulation[i]); | 1825 | p += sprintf(p, "%d,", faxmodulation[i]); |
1826 | p--; | 1826 | p--; |
1827 | *p = 0; | 1827 | *p = 0; |
1828 | ic->command = ISDN_STAT_FAXIND; | 1828 | ic->command = ISDN_STAT_FAXIND; |
1829 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; | 1829 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; |
1830 | cs->iif.statcallb(ic); | 1830 | cs->iif.statcallb(ic); |
1831 | return (0); | 1831 | return (0); |
1832 | } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { | 1832 | } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { |
1833 | if (cs->debug & L1_DEB_HSCX) | 1833 | if (cs->debug & L1_DEB_HSCX) |
1834 | debugl1(cs, "isar_auxcmd %s=%d", | 1834 | debugl1(cs, "isar_auxcmd %s=%d", |
1835 | FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); | 1835 | FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); |
1836 | for (i = 0; i < FAXMODCNT; i++) | 1836 | for (i = 0; i < FAXMODCNT; i++) |
1837 | if (faxmodulation[i] == ic->parm.aux.para[0]) | 1837 | if (faxmodulation[i] == ic->parm.aux.para[0]) |
1838 | break; | 1838 | break; |
1839 | if ((i < FAXMODCNT) && ((1 << i) & modmask) && | 1839 | if ((i < FAXMODCNT) && ((1 << i) & modmask) && |
1840 | test_bit(BC_FLG_INIT, &bcs->Flag)) { | 1840 | test_bit(BC_FLG_INIT, &bcs->Flag)) { |
1841 | isar_pump_cmd(bcs, | 1841 | isar_pump_cmd(bcs, |
1842 | ic->parm.aux.cmd, | 1842 | ic->parm.aux.cmd, |
1843 | ic->parm.aux.para[0]); | 1843 | ic->parm.aux.para[0]); |
1844 | return (0); | 1844 | return (0); |
1845 | } | 1845 | } |
1846 | } | 1846 | } |
1847 | /* wrong modulation or not activ */ | 1847 | /* wrong modulation or not activ */ |
1848 | /* fall through */ | 1848 | /* fall through */ |
1849 | default: | 1849 | default: |
1850 | ic->command = ISDN_STAT_FAXIND; | 1850 | ic->command = ISDN_STAT_FAXIND; |
1851 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR; | 1851 | ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR; |
1852 | cs->iif.statcallb(ic); | 1852 | cs->iif.statcallb(ic); |
1853 | } | 1853 | } |
1854 | break; | 1854 | break; |
1855 | case (ISDN_CMD_IOCTL): | 1855 | case (ISDN_CMD_IOCTL): |
1856 | switch (ic->arg) { | 1856 | switch (ic->arg) { |
1857 | case 9: /* load firmware */ | 1857 | case 9: /* load firmware */ |
1858 | features = ISDN_FEATURE_L2_MODEM | | 1858 | features = ISDN_FEATURE_L2_MODEM | |
1859 | ISDN_FEATURE_L2_FAX | | 1859 | ISDN_FEATURE_L2_FAX | |
1860 | ISDN_FEATURE_L3_FCLASS1; | 1860 | ISDN_FEATURE_L3_FCLASS1; |
1861 | memcpy(&adr, ic->parm.num, sizeof(ulong)); | 1861 | memcpy(&adr, ic->parm.num, sizeof(ulong)); |
1862 | if (isar_load_firmware(cs, (u_char __user *)adr)) | 1862 | if (isar_load_firmware(cs, (u_char __user *)adr)) |
1863 | return (1); | 1863 | return (1); |
1864 | else | 1864 | else |
1865 | ll_run(cs, features); | 1865 | ll_run(cs, features); |
1866 | break; | 1866 | break; |
1867 | case 20: | 1867 | case 20: |
1868 | features = *(unsigned int *) ic->parm.num; | 1868 | features = *(unsigned int *) ic->parm.num; |
1869 | printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n", | 1869 | printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n", |
1870 | modmask, features); | 1870 | modmask, features); |
1871 | modmask = features; | 1871 | modmask = features; |
1872 | break; | 1872 | break; |
1873 | case 21: | 1873 | case 21: |
1874 | features = *(unsigned int *) ic->parm.num; | 1874 | features = *(unsigned int *) ic->parm.num; |
1875 | printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n", | 1875 | printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n", |
1876 | frm_extra_delay, features); | 1876 | frm_extra_delay, features); |
1877 | if (features >= 0) | 1877 | if (features >= 0) |
1878 | frm_extra_delay = features; | 1878 | frm_extra_delay = features; |
1879 | break; | 1879 | break; |
1880 | case 22: | 1880 | case 22: |
1881 | features = *(unsigned int *) ic->parm.num; | 1881 | features = *(unsigned int *) ic->parm.num; |
1882 | printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n", | 1882 | printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n", |
1883 | para_TOA, features); | 1883 | para_TOA, features); |
1884 | if (features >= 0 && features < 32) | 1884 | if (features >= 0 && features < 32) |
1885 | para_TOA = features; | 1885 | para_TOA = features; |
1886 | break; | 1886 | break; |
1887 | default: | 1887 | default: |
1888 | printk(KERN_DEBUG "HiSax: invalid ioctl %d\n", | 1888 | printk(KERN_DEBUG "HiSax: invalid ioctl %d\n", |
1889 | (int) ic->arg); | 1889 | (int) ic->arg); |
1890 | return (-EINVAL); | 1890 | return (-EINVAL); |
1891 | } | 1891 | } |
1892 | break; | 1892 | break; |
1893 | default: | 1893 | default: |
1894 | return (-EINVAL); | 1894 | return (-EINVAL); |
1895 | } | 1895 | } |
1896 | return (0); | 1896 | return (0); |
1897 | } | 1897 | } |
1898 | 1898 | ||
1899 | void initisar(struct IsdnCardState *cs) | 1899 | void initisar(struct IsdnCardState *cs) |
1900 | { | 1900 | { |
1901 | cs->bcs[0].BC_SetStack = setstack_isar; | 1901 | cs->bcs[0].BC_SetStack = setstack_isar; |
1902 | cs->bcs[1].BC_SetStack = setstack_isar; | 1902 | cs->bcs[1].BC_SetStack = setstack_isar; |
1903 | cs->bcs[0].BC_Close = close_isarstate; | 1903 | cs->bcs[0].BC_Close = close_isarstate; |
1904 | cs->bcs[1].BC_Close = close_isarstate; | 1904 | cs->bcs[1].BC_Close = close_isarstate; |
1905 | cs->bcs[0].hw.isar.ftimer.function = (void *) ftimer_handler; | 1905 | cs->bcs[0].hw.isar.ftimer.function = (void *) ftimer_handler; |
1906 | cs->bcs[0].hw.isar.ftimer.data = (long) &cs->bcs[0]; | 1906 | cs->bcs[0].hw.isar.ftimer.data = (long) &cs->bcs[0]; |
1907 | init_timer(&cs->bcs[0].hw.isar.ftimer); | 1907 | init_timer(&cs->bcs[0].hw.isar.ftimer); |
1908 | cs->bcs[1].hw.isar.ftimer.function = (void *) ftimer_handler; | 1908 | cs->bcs[1].hw.isar.ftimer.function = (void *) ftimer_handler; |
1909 | cs->bcs[1].hw.isar.ftimer.data = (long) &cs->bcs[1]; | 1909 | cs->bcs[1].hw.isar.ftimer.data = (long) &cs->bcs[1]; |
1910 | init_timer(&cs->bcs[1].hw.isar.ftimer); | 1910 | init_timer(&cs->bcs[1].hw.isar.ftimer); |
1911 | } | 1911 | } |
1912 | 1912 |
drivers/isdn/pcbit/layer2.c
1 | /* | 1 | /* |
2 | * PCBIT-D low-layer interface | 2 | * PCBIT-D low-layer interface |
3 | * | 3 | * |
4 | * Copyright (C) 1996 Universidade de Lisboa | 4 | * Copyright (C) 1996 Universidade de Lisboa |
5 | * | 5 | * |
6 | * Written by Pedro Roque Marques (roque@di.fc.ul.pt) | 6 | * Written by Pedro Roque Marques (roque@di.fc.ul.pt) |
7 | * | 7 | * |
8 | * This software may be used and distributed according to the terms of | 8 | * This software may be used and distributed according to the terms of |
9 | * the GNU General Public License, incorporated herein by reference. | 9 | * the GNU General Public License, incorporated herein by reference. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * 19991203 - Fernando Carvalho - takion@superbofh.org | 13 | * 19991203 - Fernando Carvalho - takion@superbofh.org |
14 | * Hacked to compile with egcs and run with current version of isdn modules | 14 | * Hacked to compile with egcs and run with current version of isdn modules |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* | 17 | /* |
18 | * Based on documentation provided by Inesc: | 18 | * Based on documentation provided by Inesc: |
19 | * - "Interface com bus do PC para o PCBIT e PCBIT-D", Inesc, Jan 93 | 19 | * - "Interface com bus do PC para o PCBIT e PCBIT-D", Inesc, Jan 93 |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /* | 22 | /* |
23 | * TODO: better handling of errors | 23 | * TODO: better handling of errors |
24 | * re-write/remove debug printks | 24 | * re-write/remove debug printks |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
35 | #include <linux/skbuff.h> | 35 | #include <linux/skbuff.h> |
36 | 36 | ||
37 | #include <linux/isdnif.h> | 37 | #include <linux/isdnif.h> |
38 | 38 | ||
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | 40 | ||
41 | 41 | ||
42 | #include "pcbit.h" | 42 | #include "pcbit.h" |
43 | #include "layer2.h" | 43 | #include "layer2.h" |
44 | #include "edss1.h" | 44 | #include "edss1.h" |
45 | 45 | ||
46 | #undef DEBUG_FRAG | 46 | #undef DEBUG_FRAG |
47 | 47 | ||
48 | 48 | ||
49 | /* | 49 | /* |
50 | * Prototypes | 50 | * Prototypes |
51 | */ | 51 | */ |
52 | 52 | ||
53 | static void pcbit_transmit(struct pcbit_dev *dev); | 53 | static void pcbit_transmit(struct pcbit_dev *dev); |
54 | 54 | ||
55 | static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); | 55 | static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); |
56 | 56 | ||
57 | static void pcbit_l2_error(struct pcbit_dev *dev); | 57 | static void pcbit_l2_error(struct pcbit_dev *dev); |
58 | static void pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info); | 58 | static void pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info); |
59 | static void pcbit_l2_err_recover(unsigned long data); | 59 | static void pcbit_l2_err_recover(unsigned long data); |
60 | 60 | ||
61 | static void pcbit_firmware_bug(struct pcbit_dev *dev); | 61 | static void pcbit_firmware_bug(struct pcbit_dev *dev); |
62 | 62 | ||
63 | static __inline__ void | 63 | static __inline__ void |
64 | pcbit_sched_delivery(struct pcbit_dev *dev) | 64 | pcbit_sched_delivery(struct pcbit_dev *dev) |
65 | { | 65 | { |
66 | schedule_work(&dev->qdelivery); | 66 | schedule_work(&dev->qdelivery); |
67 | } | 67 | } |
68 | 68 | ||
69 | 69 | ||
70 | /* | 70 | /* |
71 | * Called from layer3 | 71 | * Called from layer3 |
72 | */ | 72 | */ |
73 | 73 | ||
74 | int | 74 | int |
75 | pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum, | 75 | pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum, |
76 | struct sk_buff *skb, unsigned short hdr_len) | 76 | struct sk_buff *skb, unsigned short hdr_len) |
77 | { | 77 | { |
78 | struct frame_buf *frame, | 78 | struct frame_buf *frame, |
79 | *ptr; | 79 | *ptr; |
80 | unsigned long flags; | 80 | unsigned long flags; |
81 | 81 | ||
82 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { | 82 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { |
83 | dev_kfree_skb(skb); | 83 | dev_kfree_skb(skb); |
84 | return -1; | 84 | return -1; |
85 | } | 85 | } |
86 | if ((frame = kmalloc(sizeof(struct frame_buf), | 86 | if ((frame = kmalloc(sizeof(struct frame_buf), |
87 | GFP_ATOMIC)) == NULL) { | 87 | GFP_ATOMIC)) == NULL) { |
88 | printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n"); | 88 | printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n"); |
89 | dev_kfree_skb(skb); | 89 | dev_kfree_skb(skb); |
90 | return -1; | 90 | return -1; |
91 | } | 91 | } |
92 | frame->msg = msg; | 92 | frame->msg = msg; |
93 | frame->refnum = refnum; | 93 | frame->refnum = refnum; |
94 | frame->copied = 0; | 94 | frame->copied = 0; |
95 | frame->hdr_len = hdr_len; | 95 | frame->hdr_len = hdr_len; |
96 | 96 | ||
97 | if (skb) | 97 | if (skb) |
98 | frame->dt_len = skb->len - hdr_len; | 98 | frame->dt_len = skb->len - hdr_len; |
99 | else | 99 | else |
100 | frame->dt_len = 0; | 100 | frame->dt_len = 0; |
101 | 101 | ||
102 | frame->skb = skb; | 102 | frame->skb = skb; |
103 | 103 | ||
104 | frame->next = NULL; | 104 | frame->next = NULL; |
105 | 105 | ||
106 | spin_lock_irqsave(&dev->lock, flags); | 106 | spin_lock_irqsave(&dev->lock, flags); |
107 | 107 | ||
108 | if (dev->write_queue == NULL) { | 108 | if (dev->write_queue == NULL) { |
109 | dev->write_queue = frame; | 109 | dev->write_queue = frame; |
110 | spin_unlock_irqrestore(&dev->lock, flags); | 110 | spin_unlock_irqrestore(&dev->lock, flags); |
111 | pcbit_transmit(dev); | 111 | pcbit_transmit(dev); |
112 | } else { | 112 | } else { |
113 | for (ptr = dev->write_queue; ptr->next; ptr = ptr->next); | 113 | for (ptr = dev->write_queue; ptr->next; ptr = ptr->next); |
114 | ptr->next = frame; | 114 | ptr->next = frame; |
115 | 115 | ||
116 | spin_unlock_irqrestore(&dev->lock, flags); | 116 | spin_unlock_irqrestore(&dev->lock, flags); |
117 | } | 117 | } |
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | static __inline__ void | 121 | static __inline__ void |
122 | pcbit_tx_update(struct pcbit_dev *dev, ushort len) | 122 | pcbit_tx_update(struct pcbit_dev *dev, ushort len) |
123 | { | 123 | { |
124 | u_char info; | 124 | u_char info; |
125 | 125 | ||
126 | dev->send_seq = (dev->send_seq + 1) % 8; | 126 | dev->send_seq = (dev->send_seq + 1) % 8; |
127 | 127 | ||
128 | dev->fsize[dev->send_seq] = len; | 128 | dev->fsize[dev->send_seq] = len; |
129 | info = 0; | 129 | info = 0; |
130 | info |= dev->rcv_seq << 3; | 130 | info |= dev->rcv_seq << 3; |
131 | info |= dev->send_seq; | 131 | info |= dev->send_seq; |
132 | 132 | ||
133 | writeb(info, dev->sh_mem + BANK4); | 133 | writeb(info, dev->sh_mem + BANK4); |
134 | 134 | ||
135 | } | 135 | } |
136 | 136 | ||
137 | /* | 137 | /* |
138 | * called by interrupt service routine or by write_2 | 138 | * called by interrupt service routine or by write_2 |
139 | */ | 139 | */ |
140 | 140 | ||
141 | static void | 141 | static void |
142 | pcbit_transmit(struct pcbit_dev *dev) | 142 | pcbit_transmit(struct pcbit_dev *dev) |
143 | { | 143 | { |
144 | struct frame_buf *frame = NULL; | 144 | struct frame_buf *frame = NULL; |
145 | unsigned char unacked; | 145 | unsigned char unacked; |
146 | int flen; /* fragment frame length including all headers */ | 146 | int flen; /* fragment frame length including all headers */ |
147 | int free; | 147 | int free; |
148 | int count, | 148 | int count, |
149 | cp_len; | 149 | cp_len; |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | unsigned short tt; | 151 | unsigned short tt; |
152 | 152 | ||
153 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) | 153 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) |
154 | return; | 154 | return; |
155 | 155 | ||
156 | unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; | 156 | unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; |
157 | 157 | ||
158 | spin_lock_irqsave(&dev->lock, flags); | 158 | spin_lock_irqsave(&dev->lock, flags); |
159 | 159 | ||
160 | if (dev->free > 16 && dev->write_queue && unacked < 7) { | 160 | if (dev->free > 16 && dev->write_queue && unacked < 7) { |
161 | 161 | ||
162 | if (!dev->w_busy) | 162 | if (!dev->w_busy) |
163 | dev->w_busy = 1; | 163 | dev->w_busy = 1; |
164 | else { | 164 | else { |
165 | spin_unlock_irqrestore(&dev->lock, flags); | 165 | spin_unlock_irqrestore(&dev->lock, flags); |
166 | return; | 166 | return; |
167 | } | 167 | } |
168 | 168 | ||
169 | 169 | ||
170 | frame = dev->write_queue; | 170 | frame = dev->write_queue; |
171 | free = dev->free; | 171 | free = dev->free; |
172 | 172 | ||
173 | spin_unlock_irqrestore(&dev->lock, flags); | 173 | spin_unlock_irqrestore(&dev->lock, flags); |
174 | 174 | ||
175 | if (frame->copied == 0) { | 175 | if (frame->copied == 0) { |
176 | 176 | ||
177 | /* Type 0 frame */ | 177 | /* Type 0 frame */ |
178 | 178 | ||
179 | ulong msg; | 179 | ulong msg; |
180 | 180 | ||
181 | if (frame->skb) | 181 | if (frame->skb) |
182 | flen = FRAME_HDR_LEN + PREHDR_LEN + frame->skb->len; | 182 | flen = FRAME_HDR_LEN + PREHDR_LEN + frame->skb->len; |
183 | else | 183 | else |
184 | flen = FRAME_HDR_LEN + PREHDR_LEN; | 184 | flen = FRAME_HDR_LEN + PREHDR_LEN; |
185 | 185 | ||
186 | if (flen > free) | 186 | if (flen > free) |
187 | flen = free; | 187 | flen = free; |
188 | 188 | ||
189 | msg = frame->msg; | 189 | msg = frame->msg; |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * Board level 2 header | 192 | * Board level 2 header |
193 | */ | 193 | */ |
194 | 194 | ||
195 | pcbit_writew(dev, flen - FRAME_HDR_LEN); | 195 | pcbit_writew(dev, flen - FRAME_HDR_LEN); |
196 | 196 | ||
197 | pcbit_writeb(dev, GET_MSG_CPU(msg)); | 197 | pcbit_writeb(dev, GET_MSG_CPU(msg)); |
198 | 198 | ||
199 | pcbit_writeb(dev, GET_MSG_PROC(msg)); | 199 | pcbit_writeb(dev, GET_MSG_PROC(msg)); |
200 | 200 | ||
201 | /* TH */ | 201 | /* TH */ |
202 | pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); | 202 | pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); |
203 | 203 | ||
204 | /* TD */ | 204 | /* TD */ |
205 | pcbit_writew(dev, frame->dt_len); | 205 | pcbit_writew(dev, frame->dt_len); |
206 | 206 | ||
207 | 207 | ||
208 | /* | 208 | /* |
209 | * Board level 3 fixed-header | 209 | * Board level 3 fixed-header |
210 | */ | 210 | */ |
211 | 211 | ||
212 | /* LEN = TH */ | 212 | /* LEN = TH */ |
213 | pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); | 213 | pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); |
214 | 214 | ||
215 | /* XX */ | 215 | /* XX */ |
216 | pcbit_writew(dev, 0); | 216 | pcbit_writew(dev, 0); |
217 | 217 | ||
218 | /* C + S */ | 218 | /* C + S */ |
219 | pcbit_writeb(dev, GET_MSG_CMD(msg)); | 219 | pcbit_writeb(dev, GET_MSG_CMD(msg)); |
220 | pcbit_writeb(dev, GET_MSG_SCMD(msg)); | 220 | pcbit_writeb(dev, GET_MSG_SCMD(msg)); |
221 | 221 | ||
222 | /* NUM */ | 222 | /* NUM */ |
223 | pcbit_writew(dev, frame->refnum); | 223 | pcbit_writew(dev, frame->refnum); |
224 | 224 | ||
225 | count = FRAME_HDR_LEN + PREHDR_LEN; | 225 | count = FRAME_HDR_LEN + PREHDR_LEN; |
226 | } else { | 226 | } else { |
227 | /* Type 1 frame */ | 227 | /* Type 1 frame */ |
228 | 228 | ||
229 | flen = 2 + (frame->skb->len - frame->copied); | 229 | flen = 2 + (frame->skb->len - frame->copied); |
230 | 230 | ||
231 | if (flen > free) | 231 | if (flen > free) |
232 | flen = free; | 232 | flen = free; |
233 | 233 | ||
234 | /* TT */ | 234 | /* TT */ |
235 | tt = ((ushort) (flen - 2)) | 0x8000U; /* Type 1 */ | 235 | tt = ((ushort) (flen - 2)) | 0x8000U; /* Type 1 */ |
236 | pcbit_writew(dev, tt); | 236 | pcbit_writew(dev, tt); |
237 | 237 | ||
238 | count = 2; | 238 | count = 2; |
239 | } | 239 | } |
240 | 240 | ||
241 | if (frame->skb) { | 241 | if (frame->skb) { |
242 | cp_len = frame->skb->len - frame->copied; | 242 | cp_len = frame->skb->len - frame->copied; |
243 | if (cp_len > flen - count) | 243 | if (cp_len > flen - count) |
244 | cp_len = flen - count; | 244 | cp_len = flen - count; |
245 | 245 | ||
246 | memcpy_topcbit(dev, frame->skb->data + frame->copied, | 246 | memcpy_topcbit(dev, frame->skb->data + frame->copied, |
247 | cp_len); | 247 | cp_len); |
248 | frame->copied += cp_len; | 248 | frame->copied += cp_len; |
249 | } | 249 | } |
250 | /* bookkeeping */ | 250 | /* bookkeeping */ |
251 | dev->free -= flen; | 251 | dev->free -= flen; |
252 | pcbit_tx_update(dev, flen); | 252 | pcbit_tx_update(dev, flen); |
253 | 253 | ||
254 | spin_lock_irqsave(&dev->lock, flags); | 254 | spin_lock_irqsave(&dev->lock, flags); |
255 | 255 | ||
256 | if (frame->skb == NULL || frame->copied == frame->skb->len) { | 256 | if (frame->skb == NULL || frame->copied == frame->skb->len) { |
257 | 257 | ||
258 | dev->write_queue = frame->next; | 258 | dev->write_queue = frame->next; |
259 | 259 | ||
260 | if (frame->skb != NULL) { | 260 | if (frame->skb != NULL) { |
261 | /* free frame */ | 261 | /* free frame */ |
262 | dev_kfree_skb(frame->skb); | 262 | dev_kfree_skb(frame->skb); |
263 | } | 263 | } |
264 | kfree(frame); | 264 | kfree(frame); |
265 | } | 265 | } |
266 | dev->w_busy = 0; | 266 | dev->w_busy = 0; |
267 | spin_unlock_irqrestore(&dev->lock, flags); | 267 | spin_unlock_irqrestore(&dev->lock, flags); |
268 | } else { | 268 | } else { |
269 | spin_unlock_irqrestore(&dev->lock, flags); | 269 | spin_unlock_irqrestore(&dev->lock, flags); |
270 | #ifdef DEBUG | 270 | #ifdef DEBUG |
271 | printk(KERN_DEBUG "unacked %d free %d write_queue %s\n", | 271 | printk(KERN_DEBUG "unacked %d free %d write_queue %s\n", |
272 | unacked, dev->free, dev->write_queue ? "not empty" : | 272 | unacked, dev->free, dev->write_queue ? "not empty" : |
273 | "empty"); | 273 | "empty"); |
274 | #endif | 274 | #endif |
275 | } | 275 | } |
276 | } | 276 | } |
277 | 277 | ||
278 | 278 | ||
279 | /* | 279 | /* |
280 | * deliver a queued frame to the upper layer | 280 | * deliver a queued frame to the upper layer |
281 | */ | 281 | */ |
282 | 282 | ||
283 | void | 283 | void |
284 | pcbit_deliver(struct work_struct *work) | 284 | pcbit_deliver(struct work_struct *work) |
285 | { | 285 | { |
286 | struct frame_buf *frame; | 286 | struct frame_buf *frame; |
287 | unsigned long flags, msg; | 287 | unsigned long flags, msg; |
288 | struct pcbit_dev *dev = | 288 | struct pcbit_dev *dev = |
289 | container_of(work, struct pcbit_dev, qdelivery); | 289 | container_of(work, struct pcbit_dev, qdelivery); |
290 | 290 | ||
291 | spin_lock_irqsave(&dev->lock, flags); | 291 | spin_lock_irqsave(&dev->lock, flags); |
292 | 292 | ||
293 | while ((frame = dev->read_queue)) { | 293 | while ((frame = dev->read_queue)) { |
294 | dev->read_queue = frame->next; | 294 | dev->read_queue = frame->next; |
295 | spin_unlock_irqrestore(&dev->lock, flags); | 295 | spin_unlock_irqrestore(&dev->lock, flags); |
296 | 296 | ||
297 | msg = 0; | 297 | msg = 0; |
298 | SET_MSG_CPU(msg, 0); | 298 | SET_MSG_CPU(msg, 0); |
299 | SET_MSG_PROC(msg, 0); | 299 | SET_MSG_PROC(msg, 0); |
300 | SET_MSG_CMD(msg, frame->skb->data[2]); | 300 | SET_MSG_CMD(msg, frame->skb->data[2]); |
301 | SET_MSG_SCMD(msg, frame->skb->data[3]); | 301 | SET_MSG_SCMD(msg, frame->skb->data[3]); |
302 | 302 | ||
303 | frame->refnum = *((ushort *)frame->skb->data + 4); | 303 | frame->refnum = *((ushort *)frame->skb->data + 4); |
304 | frame->msg = *((ulong *)&msg); | 304 | frame->msg = *((ulong *)&msg); |
305 | 305 | ||
306 | skb_pull(frame->skb, 6); | 306 | skb_pull(frame->skb, 6); |
307 | 307 | ||
308 | pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len, | 308 | pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len, |
309 | frame->refnum); | 309 | frame->refnum); |
310 | 310 | ||
311 | kfree(frame); | 311 | kfree(frame); |
312 | 312 | ||
313 | spin_lock_irqsave(&dev->lock, flags); | 313 | spin_lock_irqsave(&dev->lock, flags); |
314 | } | 314 | } |
315 | 315 | ||
316 | spin_unlock_irqrestore(&dev->lock, flags); | 316 | spin_unlock_irqrestore(&dev->lock, flags); |
317 | } | 317 | } |
318 | 318 | ||
319 | /* | 319 | /* |
320 | * Reads BANK 2 & Reassembles | 320 | * Reads BANK 2 & Reassembles |
321 | */ | 321 | */ |
322 | 322 | ||
323 | static void | 323 | static void |
324 | pcbit_receive(struct pcbit_dev *dev) | 324 | pcbit_receive(struct pcbit_dev *dev) |
325 | { | 325 | { |
326 | unsigned short tt; | 326 | unsigned short tt; |
327 | u_char cpu, | 327 | u_char cpu, |
328 | proc; | 328 | proc; |
329 | struct frame_buf *frame = NULL; | 329 | struct frame_buf *frame = NULL; |
330 | unsigned long flags; | 330 | unsigned long flags; |
331 | u_char type1; | 331 | u_char type1; |
332 | 332 | ||
333 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) | 333 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) |
334 | return; | 334 | return; |
335 | 335 | ||
336 | tt = pcbit_readw(dev); | 336 | tt = pcbit_readw(dev); |
337 | 337 | ||
338 | if ((tt & 0x7fffU) > 511) { | 338 | if ((tt & 0x7fffU) > 511) { |
339 | printk(KERN_INFO "pcbit: invalid frame length -> TT=%04x\n", | 339 | printk(KERN_INFO "pcbit: invalid frame length -> TT=%04x\n", |
340 | tt); | 340 | tt); |
341 | pcbit_l2_error(dev); | 341 | pcbit_l2_error(dev); |
342 | return; | 342 | return; |
343 | } | 343 | } |
344 | if (!(tt & 0x8000U)) { /* Type 0 */ | 344 | if (!(tt & 0x8000U)) { /* Type 0 */ |
345 | type1 = 0; | 345 | type1 = 0; |
346 | 346 | ||
347 | if (dev->read_frame) { | 347 | if (dev->read_frame) { |
348 | printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n"); | 348 | printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n"); |
349 | /* discard previous queued frame */ | 349 | /* discard previous queued frame */ |
350 | kfree_skb(dev->read_frame->skb); | 350 | kfree_skb(dev->read_frame->skb); |
351 | kfree(dev->read_frame); | 351 | kfree(dev->read_frame); |
352 | dev->read_frame = NULL; | 352 | dev->read_frame = NULL; |
353 | } | 353 | } |
354 | frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC); | 354 | frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC); |
355 | 355 | ||
356 | if (frame == NULL) { | 356 | if (frame == NULL) { |
357 | printk(KERN_WARNING "kmalloc failed\n"); | 357 | printk(KERN_WARNING "kmalloc failed\n"); |
358 | return; | 358 | return; |
359 | } | 359 | } |
360 | 360 | ||
361 | cpu = pcbit_readb(dev); | 361 | cpu = pcbit_readb(dev); |
362 | proc = pcbit_readb(dev); | 362 | proc = pcbit_readb(dev); |
363 | 363 | ||
364 | 364 | ||
365 | if (cpu != 0x06 && cpu != 0x02) { | 365 | if (cpu != 0x06 && cpu != 0x02) { |
366 | printk(KERN_DEBUG "pcbit: invalid cpu value\n"); | 366 | printk(KERN_DEBUG "pcbit: invalid cpu value\n"); |
367 | kfree(frame); | 367 | kfree(frame); |
368 | pcbit_l2_error(dev); | 368 | pcbit_l2_error(dev); |
369 | return; | 369 | return; |
370 | } | 370 | } |
371 | /* | 371 | /* |
372 | * we discard cpu & proc on receiving | 372 | * we discard cpu & proc on receiving |
373 | * but we read it to update the pointer | 373 | * but we read it to update the pointer |
374 | */ | 374 | */ |
375 | 375 | ||
376 | frame->hdr_len = pcbit_readw(dev); | 376 | frame->hdr_len = pcbit_readw(dev); |
377 | frame->dt_len = pcbit_readw(dev); | 377 | frame->dt_len = pcbit_readw(dev); |
378 | 378 | ||
379 | /* | 379 | /* |
380 | * 0 sized packet | 380 | * 0 sized packet |
381 | * I don't know if they are an error or not... | 381 | * I don't know if they are an error or not... |
382 | * But they are very frequent | 382 | * But they are very frequent |
383 | * Not documented | 383 | * Not documented |
384 | */ | 384 | */ |
385 | 385 | ||
386 | if (frame->hdr_len == 0) { | 386 | if (frame->hdr_len == 0) { |
387 | kfree(frame); | 387 | kfree(frame); |
388 | #ifdef DEBUG | 388 | #ifdef DEBUG |
389 | printk(KERN_DEBUG "0 sized frame\n"); | 389 | printk(KERN_DEBUG "0 sized frame\n"); |
390 | #endif | 390 | #endif |
391 | pcbit_firmware_bug(dev); | 391 | pcbit_firmware_bug(dev); |
392 | return; | 392 | return; |
393 | } | 393 | } |
394 | /* sanity check the length values */ | 394 | /* sanity check the length values */ |
395 | if (frame->hdr_len > 1024 || frame->dt_len > 2048) { | 395 | if (frame->hdr_len > 1024 || frame->dt_len > 2048) { |
396 | #ifdef DEBUG | 396 | #ifdef DEBUG |
397 | printk(KERN_DEBUG "length problem: "); | 397 | printk(KERN_DEBUG "length problem: "); |
398 | printk(KERN_DEBUG "TH=%04x TD=%04x\n", | 398 | printk(KERN_DEBUG "TH=%04x TD=%04x\n", |
399 | frame->hdr_len, | 399 | frame->hdr_len, |
400 | frame->dt_len); | 400 | frame->dt_len); |
401 | #endif | 401 | #endif |
402 | pcbit_l2_error(dev); | 402 | pcbit_l2_error(dev); |
403 | kfree(frame); | 403 | kfree(frame); |
404 | return; | 404 | return; |
405 | } | 405 | } |
406 | /* minimum frame read */ | 406 | /* minimum frame read */ |
407 | 407 | ||
408 | frame->skb = dev_alloc_skb(frame->hdr_len + frame->dt_len + | 408 | frame->skb = dev_alloc_skb(frame->hdr_len + frame->dt_len + |
409 | ((frame->hdr_len + 15) & ~15)); | 409 | ((frame->hdr_len + 15) & ~15)); |
410 | 410 | ||
411 | if (!frame->skb) { | 411 | if (!frame->skb) { |
412 | printk(KERN_DEBUG "pcbit_receive: out of memory\n"); | 412 | printk(KERN_DEBUG "pcbit_receive: out of memory\n"); |
413 | kfree(frame); | 413 | kfree(frame); |
414 | return; | 414 | return; |
415 | } | 415 | } |
416 | /* 16 byte alignment for IP */ | 416 | /* 16 byte alignment for IP */ |
417 | if (frame->dt_len) | 417 | if (frame->dt_len) |
418 | skb_reserve(frame->skb, (frame->hdr_len + 15) & ~15); | 418 | skb_reserve(frame->skb, (frame->hdr_len + 15) & ~15); |
419 | 419 | ||
420 | } else { | 420 | } else { |
421 | /* Type 1 */ | 421 | /* Type 1 */ |
422 | type1 = 1; | 422 | type1 = 1; |
423 | tt &= 0x7fffU; | 423 | tt &= 0x7fffU; |
424 | 424 | ||
425 | if (!(frame = dev->read_frame)) { | 425 | if (!(frame = dev->read_frame)) { |
426 | printk("Type 1 frame and no frame queued\n"); | 426 | printk("Type 1 frame and no frame queued\n"); |
427 | /* usually after an error: toss frame */ | 427 | /* usually after an error: toss frame */ |
428 | dev->readptr += tt; | 428 | dev->readptr += tt; |
429 | if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN) | 429 | if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN) |
430 | dev->readptr -= BANKLEN; | 430 | dev->readptr -= BANKLEN; |
431 | return; | 431 | return; |
432 | 432 | ||
433 | } | 433 | } |
434 | } | 434 | } |
435 | 435 | ||
436 | memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt); | 436 | memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt); |
437 | 437 | ||
438 | frame->copied += tt; | 438 | frame->copied += tt; |
439 | spin_lock_irqsave(&dev->lock, flags); | 439 | spin_lock_irqsave(&dev->lock, flags); |
440 | if (frame->copied == frame->hdr_len + frame->dt_len) { | 440 | if (frame->copied == frame->hdr_len + frame->dt_len) { |
441 | 441 | ||
442 | if (type1) { | 442 | if (type1) { |
443 | dev->read_frame = NULL; | 443 | dev->read_frame = NULL; |
444 | } | 444 | } |
445 | if (dev->read_queue) { | 445 | if (dev->read_queue) { |
446 | struct frame_buf *ptr; | 446 | struct frame_buf *ptr; |
447 | for (ptr = dev->read_queue; ptr->next; ptr = ptr->next); | 447 | for (ptr = dev->read_queue; ptr->next; ptr = ptr->next); |
448 | ptr->next = frame; | 448 | ptr->next = frame; |
449 | } else | 449 | } else |
450 | dev->read_queue = frame; | 450 | dev->read_queue = frame; |
451 | 451 | ||
452 | } else { | 452 | } else { |
453 | dev->read_frame = frame; | 453 | dev->read_frame = frame; |
454 | } | 454 | } |
455 | spin_unlock_irqrestore(&dev->lock, flags); | 455 | spin_unlock_irqrestore(&dev->lock, flags); |
456 | } | 456 | } |
457 | 457 | ||
458 | /* | 458 | /* |
459 | * The board sends 0 sized frames | 459 | * The board sends 0 sized frames |
460 | * They are TDATA_CONFs that get messed up somehow | 460 | * They are TDATA_CONFs that get messed up somehow |
461 | * gotta send a fake acknowledgment to the upper layer somehow | 461 | * gotta send a fake acknowledgment to the upper layer somehow |
462 | */ | 462 | */ |
463 | 463 | ||
464 | static __inline__ void | 464 | static __inline__ void |
465 | pcbit_fake_conf(struct pcbit_dev *dev, struct pcbit_chan *chan) | 465 | pcbit_fake_conf(struct pcbit_dev *dev, struct pcbit_chan *chan) |
466 | { | 466 | { |
467 | isdn_ctrl ictl; | 467 | isdn_ctrl ictl; |
468 | 468 | ||
469 | if (chan->queued) { | 469 | if (chan->queued) { |
470 | chan->queued--; | 470 | chan->queued--; |
471 | 471 | ||
472 | ictl.driver = dev->id; | 472 | ictl.driver = dev->id; |
473 | ictl.command = ISDN_STAT_BSENT; | 473 | ictl.command = ISDN_STAT_BSENT; |
474 | ictl.arg = chan->id; | 474 | ictl.arg = chan->id; |
475 | dev->dev_if->statcallb(&ictl); | 475 | dev->dev_if->statcallb(&ictl); |
476 | } | 476 | } |
477 | } | 477 | } |
478 | 478 | ||
479 | static void | 479 | static void |
480 | pcbit_firmware_bug(struct pcbit_dev *dev) | 480 | pcbit_firmware_bug(struct pcbit_dev *dev) |
481 | { | 481 | { |
482 | struct pcbit_chan *chan; | 482 | struct pcbit_chan *chan; |
483 | 483 | ||
484 | chan = dev->b1; | 484 | chan = dev->b1; |
485 | 485 | ||
486 | if (chan->fsm_state == ST_ACTIVE) { | 486 | if (chan->fsm_state == ST_ACTIVE) { |
487 | pcbit_fake_conf(dev, chan); | 487 | pcbit_fake_conf(dev, chan); |
488 | } | 488 | } |
489 | chan = dev->b2; | 489 | chan = dev->b2; |
490 | 490 | ||
491 | if (chan->fsm_state == ST_ACTIVE) { | 491 | if (chan->fsm_state == ST_ACTIVE) { |
492 | pcbit_fake_conf(dev, chan); | 492 | pcbit_fake_conf(dev, chan); |
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | irqreturn_t | 496 | irqreturn_t |
497 | pcbit_irq_handler(int interrupt, void *devptr) | 497 | pcbit_irq_handler(int interrupt, void *devptr) |
498 | { | 498 | { |
499 | struct pcbit_dev *dev; | 499 | struct pcbit_dev *dev; |
500 | u_char info, | 500 | u_char info, |
501 | ack_seq, | 501 | ack_seq, |
502 | read_seq; | 502 | read_seq; |
503 | 503 | ||
504 | dev = (struct pcbit_dev *) devptr; | 504 | dev = (struct pcbit_dev *) devptr; |
505 | 505 | ||
506 | if (!dev) { | 506 | if (!dev) { |
507 | printk(KERN_WARNING "pcbit_irq_handler: wrong device\n"); | 507 | printk(KERN_WARNING "pcbit_irq_handler: wrong device\n"); |
508 | return IRQ_NONE; | 508 | return IRQ_NONE; |
509 | } | 509 | } |
510 | if (dev->interrupt) { | 510 | if (dev->interrupt) { |
511 | printk(KERN_DEBUG "pcbit: reentering interrupt hander\n"); | 511 | printk(KERN_DEBUG "pcbit: reentering interrupt handler\n"); |
512 | return IRQ_HANDLED; | 512 | return IRQ_HANDLED; |
513 | } | 513 | } |
514 | dev->interrupt = 1; | 514 | dev->interrupt = 1; |
515 | 515 | ||
516 | info = readb(dev->sh_mem + BANK3); | 516 | info = readb(dev->sh_mem + BANK3); |
517 | 517 | ||
518 | if (dev->l2_state == L2_STARTING || dev->l2_state == L2_ERROR) { | 518 | if (dev->l2_state == L2_STARTING || dev->l2_state == L2_ERROR) { |
519 | pcbit_l2_active_conf(dev, info); | 519 | pcbit_l2_active_conf(dev, info); |
520 | dev->interrupt = 0; | 520 | dev->interrupt = 0; |
521 | return IRQ_HANDLED; | 521 | return IRQ_HANDLED; |
522 | } | 522 | } |
523 | if (info & 0x40U) { /* E bit set */ | 523 | if (info & 0x40U) { /* E bit set */ |
524 | #ifdef DEBUG | 524 | #ifdef DEBUG |
525 | printk(KERN_DEBUG "pcbit_irq_handler: E bit on\n"); | 525 | printk(KERN_DEBUG "pcbit_irq_handler: E bit on\n"); |
526 | #endif | 526 | #endif |
527 | pcbit_l2_error(dev); | 527 | pcbit_l2_error(dev); |
528 | dev->interrupt = 0; | 528 | dev->interrupt = 0; |
529 | return IRQ_HANDLED; | 529 | return IRQ_HANDLED; |
530 | } | 530 | } |
531 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { | 531 | if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { |
532 | dev->interrupt = 0; | 532 | dev->interrupt = 0; |
533 | return IRQ_HANDLED; | 533 | return IRQ_HANDLED; |
534 | } | 534 | } |
535 | ack_seq = (info >> 3) & 0x07U; | 535 | ack_seq = (info >> 3) & 0x07U; |
536 | read_seq = (info & 0x07U); | 536 | read_seq = (info & 0x07U); |
537 | 537 | ||
538 | dev->interrupt = 0; | 538 | dev->interrupt = 0; |
539 | 539 | ||
540 | if (read_seq != dev->rcv_seq) { | 540 | if (read_seq != dev->rcv_seq) { |
541 | while (read_seq != dev->rcv_seq) { | 541 | while (read_seq != dev->rcv_seq) { |
542 | pcbit_receive(dev); | 542 | pcbit_receive(dev); |
543 | dev->rcv_seq = (dev->rcv_seq + 1) % 8; | 543 | dev->rcv_seq = (dev->rcv_seq + 1) % 8; |
544 | } | 544 | } |
545 | pcbit_sched_delivery(dev); | 545 | pcbit_sched_delivery(dev); |
546 | } | 546 | } |
547 | if (ack_seq != dev->unack_seq) { | 547 | if (ack_seq != dev->unack_seq) { |
548 | pcbit_recv_ack(dev, ack_seq); | 548 | pcbit_recv_ack(dev, ack_seq); |
549 | } | 549 | } |
550 | info = dev->rcv_seq << 3; | 550 | info = dev->rcv_seq << 3; |
551 | info |= dev->send_seq; | 551 | info |= dev->send_seq; |
552 | 552 | ||
553 | writeb(info, dev->sh_mem + BANK4); | 553 | writeb(info, dev->sh_mem + BANK4); |
554 | return IRQ_HANDLED; | 554 | return IRQ_HANDLED; |
555 | } | 555 | } |
556 | 556 | ||
557 | 557 | ||
558 | static void | 558 | static void |
559 | pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info) | 559 | pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info) |
560 | { | 560 | { |
561 | u_char state; | 561 | u_char state; |
562 | 562 | ||
563 | state = dev->l2_state; | 563 | state = dev->l2_state; |
564 | 564 | ||
565 | #ifdef DEBUG | 565 | #ifdef DEBUG |
566 | printk(KERN_DEBUG "layer2_active_confirm\n"); | 566 | printk(KERN_DEBUG "layer2_active_confirm\n"); |
567 | #endif | 567 | #endif |
568 | 568 | ||
569 | 569 | ||
570 | if (info & 0x80U) { | 570 | if (info & 0x80U) { |
571 | dev->rcv_seq = info & 0x07U; | 571 | dev->rcv_seq = info & 0x07U; |
572 | dev->l2_state = L2_RUNNING; | 572 | dev->l2_state = L2_RUNNING; |
573 | } else | 573 | } else |
574 | dev->l2_state = L2_DOWN; | 574 | dev->l2_state = L2_DOWN; |
575 | 575 | ||
576 | if (state == L2_STARTING) | 576 | if (state == L2_STARTING) |
577 | wake_up_interruptible(&dev->set_running_wq); | 577 | wake_up_interruptible(&dev->set_running_wq); |
578 | 578 | ||
579 | if (state == L2_ERROR && dev->l2_state == L2_RUNNING) { | 579 | if (state == L2_ERROR && dev->l2_state == L2_RUNNING) { |
580 | pcbit_transmit(dev); | 580 | pcbit_transmit(dev); |
581 | } | 581 | } |
582 | } | 582 | } |
583 | 583 | ||
584 | static void | 584 | static void |
585 | pcbit_l2_err_recover(unsigned long data) | 585 | pcbit_l2_err_recover(unsigned long data) |
586 | { | 586 | { |
587 | 587 | ||
588 | struct pcbit_dev *dev; | 588 | struct pcbit_dev *dev; |
589 | struct frame_buf *frame; | 589 | struct frame_buf *frame; |
590 | 590 | ||
591 | dev = (struct pcbit_dev *) data; | 591 | dev = (struct pcbit_dev *) data; |
592 | 592 | ||
593 | del_timer(&dev->error_recover_timer); | 593 | del_timer(&dev->error_recover_timer); |
594 | if (dev->w_busy || dev->r_busy) { | 594 | if (dev->w_busy || dev->r_busy) { |
595 | init_timer(&dev->error_recover_timer); | 595 | init_timer(&dev->error_recover_timer); |
596 | dev->error_recover_timer.expires = jiffies + ERRTIME; | 596 | dev->error_recover_timer.expires = jiffies + ERRTIME; |
597 | add_timer(&dev->error_recover_timer); | 597 | add_timer(&dev->error_recover_timer); |
598 | return; | 598 | return; |
599 | } | 599 | } |
600 | dev->w_busy = dev->r_busy = 1; | 600 | dev->w_busy = dev->r_busy = 1; |
601 | 601 | ||
602 | if (dev->read_frame) { | 602 | if (dev->read_frame) { |
603 | kfree_skb(dev->read_frame->skb); | 603 | kfree_skb(dev->read_frame->skb); |
604 | kfree(dev->read_frame); | 604 | kfree(dev->read_frame); |
605 | dev->read_frame = NULL; | 605 | dev->read_frame = NULL; |
606 | } | 606 | } |
607 | if (dev->write_queue) { | 607 | if (dev->write_queue) { |
608 | frame = dev->write_queue; | 608 | frame = dev->write_queue; |
609 | #ifdef FREE_ON_ERROR | 609 | #ifdef FREE_ON_ERROR |
610 | dev->write_queue = dev->write_queue->next; | 610 | dev->write_queue = dev->write_queue->next; |
611 | 611 | ||
612 | if (frame->skb) { | 612 | if (frame->skb) { |
613 | dev_kfree_skb(frame->skb); | 613 | dev_kfree_skb(frame->skb); |
614 | } | 614 | } |
615 | kfree(frame); | 615 | kfree(frame); |
616 | #else | 616 | #else |
617 | frame->copied = 0; | 617 | frame->copied = 0; |
618 | #endif | 618 | #endif |
619 | } | 619 | } |
620 | dev->rcv_seq = dev->send_seq = dev->unack_seq = 0; | 620 | dev->rcv_seq = dev->send_seq = dev->unack_seq = 0; |
621 | dev->free = 511; | 621 | dev->free = 511; |
622 | dev->l2_state = L2_ERROR; | 622 | dev->l2_state = L2_ERROR; |
623 | 623 | ||
624 | /* this is an hack... */ | 624 | /* this is an hack... */ |
625 | pcbit_firmware_bug(dev); | 625 | pcbit_firmware_bug(dev); |
626 | 626 | ||
627 | dev->writeptr = dev->sh_mem; | 627 | dev->writeptr = dev->sh_mem; |
628 | dev->readptr = dev->sh_mem + BANK2; | 628 | dev->readptr = dev->sh_mem + BANK2; |
629 | 629 | ||
630 | writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), | 630 | writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), |
631 | dev->sh_mem + BANK4); | 631 | dev->sh_mem + BANK4); |
632 | dev->w_busy = dev->r_busy = 0; | 632 | dev->w_busy = dev->r_busy = 0; |
633 | 633 | ||
634 | } | 634 | } |
635 | 635 | ||
636 | static void | 636 | static void |
637 | pcbit_l2_error(struct pcbit_dev *dev) | 637 | pcbit_l2_error(struct pcbit_dev *dev) |
638 | { | 638 | { |
639 | if (dev->l2_state == L2_RUNNING) { | 639 | if (dev->l2_state == L2_RUNNING) { |
640 | 640 | ||
641 | printk(KERN_INFO "pcbit: layer 2 error\n"); | 641 | printk(KERN_INFO "pcbit: layer 2 error\n"); |
642 | 642 | ||
643 | #ifdef DEBUG | 643 | #ifdef DEBUG |
644 | log_state(dev); | 644 | log_state(dev); |
645 | #endif | 645 | #endif |
646 | 646 | ||
647 | dev->l2_state = L2_DOWN; | 647 | dev->l2_state = L2_DOWN; |
648 | 648 | ||
649 | init_timer(&dev->error_recover_timer); | 649 | init_timer(&dev->error_recover_timer); |
650 | dev->error_recover_timer.function = &pcbit_l2_err_recover; | 650 | dev->error_recover_timer.function = &pcbit_l2_err_recover; |
651 | dev->error_recover_timer.data = (ulong) dev; | 651 | dev->error_recover_timer.data = (ulong) dev; |
652 | dev->error_recover_timer.expires = jiffies + ERRTIME; | 652 | dev->error_recover_timer.expires = jiffies + ERRTIME; |
653 | add_timer(&dev->error_recover_timer); | 653 | add_timer(&dev->error_recover_timer); |
654 | } | 654 | } |
655 | } | 655 | } |
656 | 656 | ||
657 | /* | 657 | /* |
658 | * Description: | 658 | * Description: |
659 | * if board acks frames | 659 | * if board acks frames |
660 | * update dev->free | 660 | * update dev->free |
661 | * call pcbit_transmit to write possible queued frames | 661 | * call pcbit_transmit to write possible queued frames |
662 | */ | 662 | */ |
663 | 663 | ||
664 | static void | 664 | static void |
665 | pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack) | 665 | pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack) |
666 | { | 666 | { |
667 | int i, | 667 | int i, |
668 | count; | 668 | count; |
669 | int unacked; | 669 | int unacked; |
670 | 670 | ||
671 | unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; | 671 | unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; |
672 | 672 | ||
673 | /* dev->unack_seq < ack <= dev->send_seq; */ | 673 | /* dev->unack_seq < ack <= dev->send_seq; */ |
674 | 674 | ||
675 | if (unacked) { | 675 | if (unacked) { |
676 | 676 | ||
677 | if (dev->send_seq > dev->unack_seq) { | 677 | if (dev->send_seq > dev->unack_seq) { |
678 | if (ack <= dev->unack_seq || ack > dev->send_seq) { | 678 | if (ack <= dev->unack_seq || ack > dev->send_seq) { |
679 | printk(KERN_DEBUG | 679 | printk(KERN_DEBUG |
680 | "layer 2 ack unacceptable - dev %d", | 680 | "layer 2 ack unacceptable - dev %d", |
681 | dev->id); | 681 | dev->id); |
682 | 682 | ||
683 | pcbit_l2_error(dev); | 683 | pcbit_l2_error(dev); |
684 | } else if (ack > dev->send_seq && ack <= dev->unack_seq) { | 684 | } else if (ack > dev->send_seq && ack <= dev->unack_seq) { |
685 | printk(KERN_DEBUG | 685 | printk(KERN_DEBUG |
686 | "layer 2 ack unacceptable - dev %d", | 686 | "layer 2 ack unacceptable - dev %d", |
687 | dev->id); | 687 | dev->id); |
688 | pcbit_l2_error(dev); | 688 | pcbit_l2_error(dev); |
689 | } | 689 | } |
690 | } | 690 | } |
691 | /* ack is acceptable */ | 691 | /* ack is acceptable */ |
692 | 692 | ||
693 | 693 | ||
694 | i = dev->unack_seq; | 694 | i = dev->unack_seq; |
695 | 695 | ||
696 | do { | 696 | do { |
697 | dev->unack_seq = i = (i + 1) % 8; | 697 | dev->unack_seq = i = (i + 1) % 8; |
698 | dev->free += dev->fsize[i]; | 698 | dev->free += dev->fsize[i]; |
699 | } while (i != ack); | 699 | } while (i != ack); |
700 | 700 | ||
701 | count = 0; | 701 | count = 0; |
702 | while (count < 7 && dev->write_queue) { | 702 | while (count < 7 && dev->write_queue) { |
703 | u8 lsend_seq = dev->send_seq; | 703 | u8 lsend_seq = dev->send_seq; |
704 | 704 | ||
705 | pcbit_transmit(dev); | 705 | pcbit_transmit(dev); |
706 | 706 | ||
707 | if (dev->send_seq == lsend_seq) | 707 | if (dev->send_seq == lsend_seq) |
708 | break; | 708 | break; |
709 | count++; | 709 | count++; |
710 | } | 710 | } |
711 | } else | 711 | } else |
712 | printk(KERN_DEBUG "recv_ack: unacked = 0\n"); | 712 | printk(KERN_DEBUG "recv_ack: unacked = 0\n"); |
713 | } | 713 | } |
714 | 714 |