blob: e74ad385e73fe9452236f6dcc65957f089f4be15 [file] [log] [blame]
Karsten Keilda2272c92009-07-22 20:01:59 +02001/*
2 * mISDNisar.c ISAR (Siemens PSB 7110) specific functions
3 *
4 * Author Karsten Keil (keil@isdn4linux.de)
5 *
6 * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
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
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23/* define this to enable static debug messages, if you kernel supports
24 * dynamic debugging, you should use debugfs for this
25 */
26/* #define DEBUG */
27
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090028#include <linux/gfp.h>
Karsten Keilda2272c92009-07-22 20:01:59 +020029#include <linux/delay.h>
30#include <linux/vmalloc.h>
31#include <linux/mISDNhw.h>
Paul Gortmaker07a97fe2011-08-30 12:08:51 -040032#include <linux/module.h>
Karsten Keilda2272c92009-07-22 20:01:59 +020033#include "isar.h"
34
35#define ISAR_REV "2.1"
36
37MODULE_AUTHOR("Karsten Keil");
38MODULE_LICENSE("GPL v2");
39MODULE_VERSION(ISAR_REV);
40
41#define DEBUG_HW_FIRMWARE_FIFO 0x10000
42
43static const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146";
44static const u8 faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121,
Joe Perches475be4d2012-02-19 19:52:38 -080045 122, 145, 146};
Karsten Keilda2272c92009-07-22 20:01:59 +020046#define FAXMODCNT 13
47
48static void isar_setup(struct isar_hw *);
49
50static inline int
51waitforHIA(struct isar_hw *isar, int timeout)
52{
53 int t = timeout;
54 u8 val = isar->read_reg(isar->hw, ISAR_HIA);
55
56 while ((val & 1) && t) {
57 udelay(1);
58 t--;
59 val = isar->read_reg(isar->hw, ISAR_HIA);
60 }
61 pr_debug("%s: HIA after %dus\n", isar->name, timeout - t);
62 return timeout;
63}
64
65/*
66 * send msg to ISAR mailbox
67 * if msg is NULL use isar->buf
68 */
69static int
70send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg)
71{
72 if (!waitforHIA(isar, 1000))
73 return 0;
74 pr_debug("send_mbox(%02x,%02x,%d)\n", his, creg, len);
75 isar->write_reg(isar->hw, ISAR_CTRL_H, creg);
76 isar->write_reg(isar->hw, ISAR_CTRL_L, len);
77 isar->write_reg(isar->hw, ISAR_WADR, 0);
78 if (!msg)
79 msg = isar->buf;
80 if (msg && len) {
81 isar->write_fifo(isar->hw, ISAR_MBOX, msg, len);
82 if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) {
83 int l = 0;
84
85 while (l < (int)len) {
86 hex_dump_to_buffer(msg + l, len - l, 32, 1,
Joe Perches475be4d2012-02-19 19:52:38 -080087 isar->log, 256, 1);
Karsten Keilda2272c92009-07-22 20:01:59 +020088 pr_debug("%s: %s %02x: %s\n", isar->name,
Joe Perches475be4d2012-02-19 19:52:38 -080089 __func__, l, isar->log);
Karsten Keilda2272c92009-07-22 20:01:59 +020090 l += 32;
91 }
92 }
93 }
94 isar->write_reg(isar->hw, ISAR_HIS, his);
95 waitforHIA(isar, 1000);
96 return 1;
97}
98
99/*
100 * receive message from ISAR mailbox
101 * if msg is NULL use isar->buf
102 */
103static void
104rcv_mbox(struct isar_hw *isar, u8 *msg)
105{
106 if (!msg)
107 msg = isar->buf;
108 isar->write_reg(isar->hw, ISAR_RADR, 0);
109 if (msg && isar->clsb) {
110 isar->read_fifo(isar->hw, ISAR_MBOX, msg, isar->clsb);
111 if (isar->ch[0].bch.debug & DEBUG_HW_BFIFO) {
112 int l = 0;
113
114 while (l < (int)isar->clsb) {
115 hex_dump_to_buffer(msg + l, isar->clsb - l, 32,
Joe Perches475be4d2012-02-19 19:52:38 -0800116 1, isar->log, 256, 1);
Karsten Keilda2272c92009-07-22 20:01:59 +0200117 pr_debug("%s: %s %02x: %s\n", isar->name,
Joe Perches475be4d2012-02-19 19:52:38 -0800118 __func__, l, isar->log);
Karsten Keilda2272c92009-07-22 20:01:59 +0200119 l += 32;
120 }
121 }
122 }
123 isar->write_reg(isar->hw, ISAR_IIA, 0);
124}
125
126static inline void
127get_irq_infos(struct isar_hw *isar)
128{
129 isar->iis = isar->read_reg(isar->hw, ISAR_IIS);
130 isar->cmsb = isar->read_reg(isar->hw, ISAR_CTRL_H);
131 isar->clsb = isar->read_reg(isar->hw, ISAR_CTRL_L);
132 pr_debug("%s: rcv_mbox(%02x,%02x,%d)\n", isar->name,
Joe Perches475be4d2012-02-19 19:52:38 -0800133 isar->iis, isar->cmsb, isar->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +0200134}
135
136/*
137 * poll answer message from ISAR mailbox
138 * should be used only with ISAR IRQs disabled before DSP was started
139 *
140 */
141static int
142poll_mbox(struct isar_hw *isar, int maxdelay)
143{
144 int t = maxdelay;
145 u8 irq;
146
147 irq = isar->read_reg(isar->hw, ISAR_IRQBIT);
148 while (t && !(irq & ISAR_IRQSTA)) {
149 udelay(1);
150 t--;
151 }
152 if (t) {
153 get_irq_infos(isar);
154 rcv_mbox(isar, NULL);
155 }
156 pr_debug("%s: pulled %d bytes after %d us\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800157 isar->name, isar->clsb, maxdelay - t);
Karsten Keilda2272c92009-07-22 20:01:59 +0200158 return t;
159}
160
161static int
162ISARVersion(struct isar_hw *isar)
163{
164 int ver;
165
166 /* disable ISAR IRQ */
167 isar->write_reg(isar->hw, ISAR_IRQBIT, 0);
168 isar->buf[0] = ISAR_MSG_HWVER;
169 isar->buf[1] = 0;
170 isar->buf[2] = 1;
171 if (!send_mbox(isar, ISAR_HIS_VNR, 0, 3, NULL))
172 return -1;
173 if (!poll_mbox(isar, 1000))
174 return -2;
175 if (isar->iis == ISAR_IIS_VNR) {
176 if (isar->clsb == 1) {
177 ver = isar->buf[0] & 0xf;
178 return ver;
179 }
180 return -3;
181 }
182 return -4;
183}
184
185static int
186load_firmware(struct isar_hw *isar, const u8 *buf, int size)
187{
188 u32 saved_debug = isar->ch[0].bch.debug;
189 int ret, cnt;
190 u8 nom, noc;
191 u16 left, val, *sp = (u16 *)buf;
192 u8 *mp;
193 u_long flags;
194
195 struct {
196 u16 sadr;
197 u16 len;
198 u16 d_key;
199 } blk_head;
200
201 if (1 != isar->version) {
202 pr_err("%s: ISAR wrong version %d firmware download aborted\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800203 isar->name, isar->version);
Karsten Keilda2272c92009-07-22 20:01:59 +0200204 return -EINVAL;
205 }
206 if (!(saved_debug & DEBUG_HW_FIRMWARE_FIFO))
207 isar->ch[0].bch.debug &= ~DEBUG_HW_BFIFO;
208 pr_debug("%s: load firmware %d words (%d bytes)\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800209 isar->name, size / 2, size);
Karsten Keilda2272c92009-07-22 20:01:59 +0200210 cnt = 0;
211 size /= 2;
212 /* disable ISAR IRQ */
213 spin_lock_irqsave(isar->hwlock, flags);
214 isar->write_reg(isar->hw, ISAR_IRQBIT, 0);
215 spin_unlock_irqrestore(isar->hwlock, flags);
216 while (cnt < size) {
217 blk_head.sadr = le16_to_cpu(*sp++);
218 blk_head.len = le16_to_cpu(*sp++);
219 blk_head.d_key = le16_to_cpu(*sp++);
220 cnt += 3;
221 pr_debug("ISAR firmware block (%#x,%d,%#x)\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800222 blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);
Karsten Keilda2272c92009-07-22 20:01:59 +0200223 left = blk_head.len;
224 if (cnt + left > size) {
225 pr_info("%s: firmware error have %d need %d words\n",
226 isar->name, size, cnt + left);
227 ret = -EINVAL;
228 goto reterrflg;
229 }
230 spin_lock_irqsave(isar->hwlock, flags);
231 if (!send_mbox(isar, ISAR_HIS_DKEY, blk_head.d_key & 0xff,
Joe Perches475be4d2012-02-19 19:52:38 -0800232 0, NULL)) {
Karsten Keilda2272c92009-07-22 20:01:59 +0200233 pr_info("ISAR send_mbox dkey failed\n");
234 ret = -ETIME;
235 goto reterror;
236 }
237 if (!poll_mbox(isar, 1000)) {
238 pr_warning("ISAR poll_mbox dkey failed\n");
239 ret = -ETIME;
240 goto reterror;
241 }
242 spin_unlock_irqrestore(isar->hwlock, flags);
243 if ((isar->iis != ISAR_IIS_DKEY) || isar->cmsb || isar->clsb) {
244 pr_info("ISAR wrong dkey response (%x,%x,%x)\n",
245 isar->iis, isar->cmsb, isar->clsb);
246 ret = 1;
247 goto reterrflg;
248 }
249 while (left > 0) {
250 if (left > 126)
251 noc = 126;
252 else
253 noc = left;
254 nom = (2 * noc) + 3;
255 mp = isar->buf;
256 /* the ISAR is big endian */
257 *mp++ = blk_head.sadr >> 8;
258 *mp++ = blk_head.sadr & 0xFF;
259 left -= noc;
260 cnt += noc;
261 *mp++ = noc;
262 pr_debug("%s: load %3d words at %04x\n", isar->name,
Joe Perches475be4d2012-02-19 19:52:38 -0800263 noc, blk_head.sadr);
Karsten Keilda2272c92009-07-22 20:01:59 +0200264 blk_head.sadr += noc;
265 while (noc) {
266 val = le16_to_cpu(*sp++);
267 *mp++ = val >> 8;
Joe Perchesad65ffd2010-11-14 17:04:26 +0000268 *mp++ = val & 0xFF;
Karsten Keilda2272c92009-07-22 20:01:59 +0200269 noc--;
270 }
271 spin_lock_irqsave(isar->hwlock, flags);
272 if (!send_mbox(isar, ISAR_HIS_FIRM, 0, nom, NULL)) {
273 pr_info("ISAR send_mbox prog failed\n");
274 ret = -ETIME;
275 goto reterror;
276 }
277 if (!poll_mbox(isar, 1000)) {
278 pr_info("ISAR poll_mbox prog failed\n");
279 ret = -ETIME;
280 goto reterror;
281 }
282 spin_unlock_irqrestore(isar->hwlock, flags);
283 if ((isar->iis != ISAR_IIS_FIRM) ||
284 isar->cmsb || isar->clsb) {
285 pr_info("ISAR wrong prog response (%x,%x,%x)\n",
286 isar->iis, isar->cmsb, isar->clsb);
287 ret = -EIO;
288 goto reterrflg;
289 }
290 }
291 pr_debug("%s: ISAR firmware block %d words loaded\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800292 isar->name, blk_head.len);
Karsten Keilda2272c92009-07-22 20:01:59 +0200293 }
294 isar->ch[0].bch.debug = saved_debug;
295 /* 10ms delay */
296 cnt = 10;
297 while (cnt--)
298 mdelay(1);
299 isar->buf[0] = 0xff;
300 isar->buf[1] = 0xfe;
301 isar->bstat = 0;
302 spin_lock_irqsave(isar->hwlock, flags);
303 if (!send_mbox(isar, ISAR_HIS_STDSP, 0, 2, NULL)) {
304 pr_info("ISAR send_mbox start dsp failed\n");
305 ret = -ETIME;
306 goto reterror;
307 }
308 if (!poll_mbox(isar, 1000)) {
309 pr_info("ISAR poll_mbox start dsp failed\n");
310 ret = -ETIME;
311 goto reterror;
312 }
313 if ((isar->iis != ISAR_IIS_STDSP) || isar->cmsb || isar->clsb) {
314 pr_info("ISAR wrong start dsp response (%x,%x,%x)\n",
315 isar->iis, isar->cmsb, isar->clsb);
316 ret = -EIO;
317 goto reterror;
318 } else
319 pr_debug("%s: ISAR start dsp success\n", isar->name);
320
321 /* NORMAL mode entered */
322 /* Enable IRQs of ISAR */
323 isar->write_reg(isar->hw, ISAR_IRQBIT, ISAR_IRQSTA);
324 spin_unlock_irqrestore(isar->hwlock, flags);
325 cnt = 1000; /* max 1s */
326 while ((!isar->bstat) && cnt) {
327 mdelay(1);
328 cnt--;
329 }
330 if (!cnt) {
331 pr_info("ISAR no general status event received\n");
332 ret = -ETIME;
333 goto reterrflg;
334 } else
335 pr_debug("%s: ISAR general status event %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800336 isar->name, isar->bstat);
Karsten Keilda2272c92009-07-22 20:01:59 +0200337 /* 10ms delay */
338 cnt = 10;
339 while (cnt--)
340 mdelay(1);
341 isar->iis = 0;
342 spin_lock_irqsave(isar->hwlock, flags);
343 if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
344 pr_info("ISAR send_mbox self tst failed\n");
345 ret = -ETIME;
346 goto reterror;
347 }
348 spin_unlock_irqrestore(isar->hwlock, flags);
349 cnt = 10000; /* max 100 ms */
350 while ((isar->iis != ISAR_IIS_DIAG) && cnt) {
351 udelay(10);
352 cnt--;
353 }
354 mdelay(1);
355 if (!cnt) {
356 pr_info("ISAR no self tst response\n");
357 ret = -ETIME;
358 goto reterrflg;
359 }
360 if ((isar->cmsb == ISAR_CTRL_STST) && (isar->clsb == 1)
361 && (isar->buf[0] == 0))
362 pr_debug("%s: ISAR selftest OK\n", isar->name);
363 else {
364 pr_info("ISAR selftest not OK %x/%x/%x\n",
365 isar->cmsb, isar->clsb, isar->buf[0]);
366 ret = -EIO;
367 goto reterrflg;
368 }
369 spin_lock_irqsave(isar->hwlock, flags);
370 isar->iis = 0;
371 if (!send_mbox(isar, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
372 pr_info("ISAR RQST SVN failed\n");
373 ret = -ETIME;
374 goto reterror;
375 }
376 spin_unlock_irqrestore(isar->hwlock, flags);
377 cnt = 30000; /* max 300 ms */
378 while ((isar->iis != ISAR_IIS_DIAG) && cnt) {
379 udelay(10);
380 cnt--;
381 }
382 mdelay(1);
383 if (!cnt) {
384 pr_info("ISAR no SVN response\n");
385 ret = -ETIME;
386 goto reterrflg;
387 } else {
388 if ((isar->cmsb == ISAR_CTRL_SWVER) && (isar->clsb == 1)) {
389 pr_notice("%s: ISAR software version %#x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800390 isar->name, isar->buf[0]);
Karsten Keilda2272c92009-07-22 20:01:59 +0200391 } else {
392 pr_info("%s: ISAR wrong swver response (%x,%x)"
393 " cnt(%d)\n", isar->name, isar->cmsb,
394 isar->clsb, cnt);
395 ret = -EIO;
396 goto reterrflg;
397 }
398 }
399 spin_lock_irqsave(isar->hwlock, flags);
400 isar_setup(isar);
401 spin_unlock_irqrestore(isar->hwlock, flags);
402 ret = 0;
403reterrflg:
404 spin_lock_irqsave(isar->hwlock, flags);
405reterror:
406 isar->ch[0].bch.debug = saved_debug;
407 if (ret)
408 /* disable ISAR IRQ */
409 isar->write_reg(isar->hw, ISAR_IRQBIT, 0);
410 spin_unlock_irqrestore(isar->hwlock, flags);
411 return ret;
412}
413
414static inline void
415deliver_status(struct isar_ch *ch, int status)
416{
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);
419}
420
421static inline void
422isar_rcv_frame(struct isar_ch *ch)
423{
Karsten Keil7206e652012-05-15 23:51:05 +0000424 u8 *ptr;
425 int maxlen;
Karsten Keilda2272c92009-07-22 20:01:59 +0200426
427 if (!ch->is->clsb) {
428 pr_debug("%s; ISAR zero len frame\n", ch->is->name);
429 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
430 return;
431 }
432 switch (ch->bch.state) {
433 case ISDN_P_NONE:
434 pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800435 ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +0200436 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
437 break;
438 case ISDN_P_B_RAW:
439 case ISDN_P_B_L2DTMF:
440 case ISDN_P_B_MODEM_ASYNC:
Karsten Keil7206e652012-05-15 23:51:05 +0000441 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
442 if (maxlen < 0) {
443 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
444 ch->is->name, ch->bch.nr, ch->is->clsb);
445 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
446 break;
Karsten Keilda2272c92009-07-22 20:01:59 +0200447 }
448 rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
Karsten Keil034005a2012-05-15 23:51:06 +0000449 recv_Bchannel(&ch->bch, 0, false);
Karsten Keilda2272c92009-07-22 20:01:59 +0200450 break;
451 case ISDN_P_B_HDLC:
Karsten Keil7206e652012-05-15 23:51:05 +0000452 maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
453 if (maxlen < 0) {
454 pr_warning("%s.B%d: No bufferspace for %d bytes\n",
455 ch->is->name, ch->bch.nr, ch->is->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +0200456 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
Karsten Keilda2272c92009-07-22 20:01:59 +0200457 break;
458 }
459 if (ch->is->cmsb & HDLC_ERROR) {
460 pr_debug("%s: ISAR frame error %x len %d\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800461 ch->is->name, ch->is->cmsb, ch->is->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +0200462#ifdef ERROR_STATISTIC
463 if (ch->is->cmsb & HDLC_ERR_RER)
464 ch->bch.err_inv++;
465 if (ch->is->cmsb & HDLC_ERR_CER)
466 ch->bch.err_crc++;
467#endif
468 skb_trim(ch->bch.rx_skb, 0);
469 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
470 break;
471 }
472 if (ch->is->cmsb & HDLC_FSD)
473 skb_trim(ch->bch.rx_skb, 0);
474 ptr = skb_put(ch->bch.rx_skb, ch->is->clsb);
475 rcv_mbox(ch->is, ptr);
476 if (ch->is->cmsb & HDLC_FED) {
477 if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
478 pr_debug("%s: ISAR frame to short %d\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800479 ch->is->name, ch->bch.rx_skb->len);
Karsten Keilda2272c92009-07-22 20:01:59 +0200480 skb_trim(ch->bch.rx_skb, 0);
481 break;
482 }
483 skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
Karsten Keil034005a2012-05-15 23:51:06 +0000484 recv_Bchannel(&ch->bch, 0, false);
Karsten Keilda2272c92009-07-22 20:01:59 +0200485 }
486 break;
487 case ISDN_P_B_T30_FAX:
488 if (ch->state != STFAX_ACTIV) {
489 pr_debug("%s: isar_rcv_frame: not ACTIV\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800490 ch->is->name);
Karsten Keilda2272c92009-07-22 20:01:59 +0200491 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
492 if (ch->bch.rx_skb)
493 skb_trim(ch->bch.rx_skb, 0);
494 break;
495 }
496 if (!ch->bch.rx_skb) {
497 ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
Joe Perches475be4d2012-02-19 19:52:38 -0800498 GFP_ATOMIC);
Karsten Keilda2272c92009-07-22 20:01:59 +0200499 if (unlikely(!ch->bch.rx_skb)) {
500 pr_info("%s: B receive out of memory\n",
501 __func__);
502 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
503 break;
504 }
505 }
506 if (ch->cmd == PCTRL_CMD_FRM) {
507 rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
508 pr_debug("%s: isar_rcv_frame: %d\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800509 ch->is->name, ch->bch.rx_skb->len);
Karsten Keilda2272c92009-07-22 20:01:59 +0200510 if (ch->is->cmsb & SART_NMD) { /* ABORT */
511 pr_debug("%s: isar_rcv_frame: no more data\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800512 ch->is->name);
Karsten Keilda2272c92009-07-22 20:01:59 +0200513 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
514 send_mbox(ch->is, SET_DPS(ch->dpath) |
Joe Perches475be4d2012-02-19 19:52:38 -0800515 ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
516 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +0200517 ch->state = STFAX_ESCAPE;
518 /* set_skb_flag(skb, DF_NOMOREDATA); */
519 }
Karsten Keil034005a2012-05-15 23:51:06 +0000520 recv_Bchannel(&ch->bch, 0, false);
Karsten Keilda2272c92009-07-22 20:01:59 +0200521 if (ch->is->cmsb & SART_NMD)
522 deliver_status(ch, HW_MOD_NOCARR);
523 break;
524 }
525 if (ch->cmd != PCTRL_CMD_FRH) {
526 pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800527 ch->is->name, ch->cmd);
Karsten Keilda2272c92009-07-22 20:01:59 +0200528 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
529 if (ch->bch.rx_skb)
530 skb_trim(ch->bch.rx_skb, 0);
531 break;
532 }
533 /* PCTRL_CMD_FRH */
534 if ((ch->bch.rx_skb->len + ch->is->clsb) >
535 (ch->bch.maxlen + 2)) {
536 pr_info("%s: %s incoming packet too large\n",
537 ch->is->name, __func__);
538 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
539 skb_trim(ch->bch.rx_skb, 0);
540 break;
541 } else if (ch->is->cmsb & HDLC_ERROR) {
542 pr_info("%s: ISAR frame error %x len %d\n",
543 ch->is->name, ch->is->cmsb, ch->is->clsb);
544 skb_trim(ch->bch.rx_skb, 0);
545 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
546 break;
547 }
548 if (ch->is->cmsb & HDLC_FSD)
549 skb_trim(ch->bch.rx_skb, 0);
550 ptr = skb_put(ch->bch.rx_skb, ch->is->clsb);
551 rcv_mbox(ch->is, ptr);
552 if (ch->is->cmsb & HDLC_FED) {
553 if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
554 pr_info("%s: ISAR frame to short %d\n",
555 ch->is->name, ch->bch.rx_skb->len);
556 skb_trim(ch->bch.rx_skb, 0);
557 break;
558 }
559 skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
Karsten Keil034005a2012-05-15 23:51:06 +0000560 recv_Bchannel(&ch->bch, 0, false);
Karsten Keilda2272c92009-07-22 20:01:59 +0200561 }
562 if (ch->is->cmsb & SART_NMD) { /* ABORT */
563 pr_debug("%s: isar_rcv_frame: no more data\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800564 ch->is->name);
Karsten Keilda2272c92009-07-22 20:01:59 +0200565 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
566 if (ch->bch.rx_skb)
567 skb_trim(ch->bch.rx_skb, 0);
568 send_mbox(ch->is, SET_DPS(ch->dpath) |
Joe Perches475be4d2012-02-19 19:52:38 -0800569 ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +0200570 ch->state = STFAX_ESCAPE;
571 deliver_status(ch, HW_MOD_NOCARR);
572 }
573 break;
574 default:
575 pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state);
576 ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
577 break;
578 }
579}
580
581static void
582isar_fill_fifo(struct isar_ch *ch)
583{
584 int count;
585 u8 msb;
586 u8 *ptr;
587
588 pr_debug("%s: ch%d tx_skb %p tx_idx %d\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800589 ch->is->name, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx);
Karsten Keilda2272c92009-07-22 20:01:59 +0200590 if (!ch->bch.tx_skb)
591 return;
592 count = ch->bch.tx_skb->len - ch->bch.tx_idx;
593 if (count <= 0)
594 return;
595 if (!(ch->is->bstat &
Joe Perches475be4d2012-02-19 19:52:38 -0800596 (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
Karsten Keilda2272c92009-07-22 20:01:59 +0200597 return;
598 if (count > ch->mml) {
599 msb = 0;
600 count = ch->mml;
601 } else {
602 msb = HDLC_FED;
603 }
604 ptr = ch->bch.tx_skb->data + ch->bch.tx_idx;
605 if (!ch->bch.tx_idx) {
606 pr_debug("%s: frame start\n", ch->is->name);
607 if ((ch->bch.state == ISDN_P_B_T30_FAX) &&
Joe Perches475be4d2012-02-19 19:52:38 -0800608 (ch->cmd == PCTRL_CMD_FTH)) {
Karsten Keilda2272c92009-07-22 20:01:59 +0200609 if (count > 1) {
610 if ((ptr[0] == 0xff) && (ptr[1] == 0x13)) {
611 /* last frame */
612 test_and_set_bit(FLG_LASTDATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800613 &ch->bch.Flags);
Karsten Keilda2272c92009-07-22 20:01:59 +0200614 pr_debug("%s: set LASTDATA\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800615 ch->is->name);
Karsten Keilda2272c92009-07-22 20:01:59 +0200616 if (msb == HDLC_FED)
617 test_and_set_bit(FLG_DLEETX,
Joe Perches475be4d2012-02-19 19:52:38 -0800618 &ch->bch.Flags);
Karsten Keilda2272c92009-07-22 20:01:59 +0200619 }
620 }
621 }
622 msb |= HDLC_FST;
623 }
624 ch->bch.tx_idx += count;
625 switch (ch->bch.state) {
626 case ISDN_P_NONE:
627 pr_info("%s: wrong protocol 0\n", __func__);
628 break;
629 case ISDN_P_B_RAW:
630 case ISDN_P_B_L2DTMF:
631 case ISDN_P_B_MODEM_ASYNC:
632 send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800633 0, count, ptr);
Karsten Keilda2272c92009-07-22 20:01:59 +0200634 break;
635 case ISDN_P_B_HDLC:
636 send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800637 msb, count, ptr);
Karsten Keilda2272c92009-07-22 20:01:59 +0200638 break;
639 case ISDN_P_B_T30_FAX:
640 if (ch->state != STFAX_ACTIV)
641 pr_debug("%s: not ACTIV\n", ch->is->name);
642 else if (ch->cmd == PCTRL_CMD_FTH)
643 send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800644 msb, count, ptr);
Karsten Keilda2272c92009-07-22 20:01:59 +0200645 else if (ch->cmd == PCTRL_CMD_FTM)
646 send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800647 0, count, ptr);
Karsten Keilda2272c92009-07-22 20:01:59 +0200648 else
649 pr_debug("%s: not FTH/FTM\n", ch->is->name);
650 break;
651 default:
652 pr_info("%s: protocol(%x) error\n",
653 __func__, ch->bch.state);
654 break;
655 }
656}
657
658static inline struct isar_ch *
659sel_bch_isar(struct isar_hw *isar, u8 dpath)
660{
661 struct isar_ch *base = &isar->ch[0];
662
663 if ((!dpath) || (dpath > 2))
664 return NULL;
665 if (base->dpath == dpath)
666 return base;
667 base++;
668 if (base->dpath == dpath)
669 return base;
670 return NULL;
671}
672
673static void
674send_next(struct isar_ch *ch)
675{
676 pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800677 ch->is->name, __func__, ch->bch.nr,
678 ch->bch.tx_skb, ch->bch.tx_idx);
Karsten Keilda2272c92009-07-22 20:01:59 +0200679 if (ch->bch.state == ISDN_P_B_T30_FAX) {
680 if (ch->cmd == PCTRL_CMD_FTH) {
681 if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) {
682 pr_debug("set NMD_DATA\n");
683 test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags);
684 }
685 } else if (ch->cmd == PCTRL_CMD_FTM) {
686 if (test_bit(FLG_DLEETX, &ch->bch.Flags)) {
687 test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags);
688 test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags);
689 }
690 }
691 }
Karsten Keil8bfddfb2012-05-15 23:51:02 +0000692 if (ch->bch.tx_skb)
Karsten Keilda2272c92009-07-22 20:01:59 +0200693 dev_kfree_skb(ch->bch.tx_skb);
Karsten Keil8bfddfb2012-05-15 23:51:02 +0000694 if (get_next_bframe(&ch->bch)) {
Karsten Keilda2272c92009-07-22 20:01:59 +0200695 isar_fill_fifo(ch);
Karsten Keil8bfddfb2012-05-15 23:51:02 +0000696 } else {
Karsten Keilda2272c92009-07-22 20:01:59 +0200697 if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) {
698 if (test_and_clear_bit(FLG_LASTDATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800699 &ch->bch.Flags)) {
Karsten Keilda2272c92009-07-22 20:01:59 +0200700 if (test_and_clear_bit(FLG_NMD_DATA,
Joe Perches475be4d2012-02-19 19:52:38 -0800701 &ch->bch.Flags)) {
Karsten Keilda2272c92009-07-22 20:01:59 +0200702 u8 zd = 0;
703 send_mbox(ch->is, SET_DPS(ch->dpath) |
Joe Perches475be4d2012-02-19 19:52:38 -0800704 ISAR_HIS_SDATA, 0x01, 1, &zd);
Karsten Keilda2272c92009-07-22 20:01:59 +0200705 }
706 test_and_set_bit(FLG_LL_OK, &ch->bch.Flags);
707 } else {
708 deliver_status(ch, HW_MOD_CONNECT);
709 }
710 }
711 }
712}
713
714static void
715check_send(struct isar_hw *isar, u8 rdm)
716{
717 struct isar_ch *ch;
718
719 pr_debug("%s: rdm %x\n", isar->name, rdm);
720 if (rdm & BSTAT_RDM1) {
721 ch = sel_bch_isar(isar, 1);
722 if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) {
723 if (ch->bch.tx_skb && (ch->bch.tx_skb->len >
Joe Perches475be4d2012-02-19 19:52:38 -0800724 ch->bch.tx_idx))
Karsten Keilda2272c92009-07-22 20:01:59 +0200725 isar_fill_fifo(ch);
726 else
727 send_next(ch);
728 }
729 }
730 if (rdm & BSTAT_RDM2) {
731 ch = sel_bch_isar(isar, 2);
732 if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) {
733 if (ch->bch.tx_skb && (ch->bch.tx_skb->len >
Joe Perches475be4d2012-02-19 19:52:38 -0800734 ch->bch.tx_idx))
Karsten Keilda2272c92009-07-22 20:01:59 +0200735 isar_fill_fifo(ch);
736 else
737 send_next(ch);
738 }
739 }
740}
741
742const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
Joe Perches475be4d2012-02-19 19:52:38 -0800743 "300", "600", "1200", "2400", "4800", "7200",
744 "9600nt", "9600t", "12000", "14400", "WRONG"};
Karsten Keilda2272c92009-07-22 20:01:59 +0200745const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
Joe Perches475be4d2012-02-19 19:52:38 -0800746 "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
Karsten Keilda2272c92009-07-22 20:01:59 +0200747
748static void
749isar_pump_status_rsp(struct isar_ch *ch) {
750 u8 ril = ch->is->buf[0];
751 u8 rim;
752
753 if (!test_and_clear_bit(ISAR_RATE_REQ, &ch->is->Flags))
754 return;
755 if (ril > 14) {
756 pr_info("%s: wrong pstrsp ril=%d\n", ch->is->name, ril);
757 ril = 15;
758 }
759 switch (ch->is->buf[1]) {
760 case 0:
761 rim = 0;
762 break;
763 case 0x20:
764 rim = 2;
765 break;
766 case 0x40:
767 rim = 3;
768 break;
769 case 0x41:
770 rim = 4;
771 break;
772 case 0x51:
773 rim = 5;
774 break;
775 case 0x61:
776 rim = 6;
777 break;
778 case 0x71:
779 rim = 7;
780 break;
781 case 0x82:
782 rim = 8;
783 break;
784 case 0x92:
785 rim = 9;
786 break;
787 case 0xa2:
788 rim = 10;
789 break;
790 default:
791 rim = 1;
792 break;
793 }
794 sprintf(ch->conmsg, "%s %s", dmril[ril], dmrim[rim]);
795 pr_debug("%s: pump strsp %s\n", ch->is->name, ch->conmsg);
796}
797
798static void
799isar_pump_statev_modem(struct isar_ch *ch, u8 devt) {
800 u8 dps = SET_DPS(ch->dpath);
801
802 switch (devt) {
803 case PSEV_10MS_TIMER:
804 pr_debug("%s: pump stev TIMER\n", ch->is->name);
805 break;
806 case PSEV_CON_ON:
807 pr_debug("%s: pump stev CONNECT\n", ch->is->name);
808 deliver_status(ch, HW_MOD_CONNECT);
809 break;
810 case PSEV_CON_OFF:
811 pr_debug("%s: pump stev NO CONNECT\n", ch->is->name);
812 send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
813 deliver_status(ch, HW_MOD_NOCARR);
814 break;
815 case PSEV_V24_OFF:
816 pr_debug("%s: pump stev V24 OFF\n", ch->is->name);
817 break;
818 case PSEV_CTS_ON:
819 pr_debug("%s: pump stev CTS ON\n", ch->is->name);
820 break;
821 case PSEV_CTS_OFF:
822 pr_debug("%s pump stev CTS OFF\n", ch->is->name);
823 break;
824 case PSEV_DCD_ON:
825 pr_debug("%s: pump stev CARRIER ON\n", ch->is->name);
826 test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags);
827 send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
828 break;
829 case PSEV_DCD_OFF:
830 pr_debug("%s: pump stev CARRIER OFF\n", ch->is->name);
831 break;
832 case PSEV_DSR_ON:
833 pr_debug("%s: pump stev DSR ON\n", ch->is->name);
834 break;
835 case PSEV_DSR_OFF:
836 pr_debug("%s: pump stev DSR_OFF\n", ch->is->name);
837 break;
838 case PSEV_REM_RET:
839 pr_debug("%s: pump stev REMOTE RETRAIN\n", ch->is->name);
840 break;
841 case PSEV_REM_REN:
842 pr_debug("%s: pump stev REMOTE RENEGOTIATE\n", ch->is->name);
843 break;
844 case PSEV_GSTN_CLR:
845 pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name);
846 break;
847 default:
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200848 pr_info("u%s: unknown pump stev %x\n", ch->is->name, devt);
Karsten Keilda2272c92009-07-22 20:01:59 +0200849 break;
850 }
851}
852
853static void
854isar_pump_statev_fax(struct isar_ch *ch, u8 devt) {
855 u8 dps = SET_DPS(ch->dpath);
856 u8 p1;
857
858 switch (devt) {
859 case PSEV_10MS_TIMER:
860 pr_debug("%s: pump stev TIMER\n", ch->is->name);
861 break;
862 case PSEV_RSP_READY:
863 pr_debug("%s: pump stev RSP_READY\n", ch->is->name);
864 ch->state = STFAX_READY;
865 deliver_status(ch, HW_MOD_READY);
866#ifdef AUTOCON
867 if (test_bit(BC_FLG_ORIG, &ch->bch.Flags))
868 isar_pump_cmd(bch, HW_MOD_FRH, 3);
869 else
870 isar_pump_cmd(bch, HW_MOD_FTH, 3);
871#endif
872 break;
873 case PSEV_LINE_TX_H:
874 if (ch->state == STFAX_LINE) {
875 pr_debug("%s: pump stev LINE_TX_H\n", ch->is->name);
876 ch->state = STFAX_CONT;
877 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -0800878 PCTRL_CMD_CONT, 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +0200879 } else {
880 pr_debug("%s: pump stev LINE_TX_H wrong st %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800881 ch->is->name, ch->state);
Karsten Keilda2272c92009-07-22 20:01:59 +0200882 }
883 break;
884 case PSEV_LINE_RX_H:
885 if (ch->state == STFAX_LINE) {
886 pr_debug("%s: pump stev LINE_RX_H\n", ch->is->name);
887 ch->state = STFAX_CONT;
888 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -0800889 PCTRL_CMD_CONT, 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +0200890 } else {
891 pr_debug("%s: pump stev LINE_RX_H wrong st %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800892 ch->is->name, ch->state);
Karsten Keilda2272c92009-07-22 20:01:59 +0200893 }
894 break;
895 case PSEV_LINE_TX_B:
896 if (ch->state == STFAX_LINE) {
897 pr_debug("%s: pump stev LINE_TX_B\n", ch->is->name);
898 ch->state = STFAX_CONT;
899 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -0800900 PCTRL_CMD_CONT, 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +0200901 } else {
902 pr_debug("%s: pump stev LINE_TX_B wrong st %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800903 ch->is->name, ch->state);
Karsten Keilda2272c92009-07-22 20:01:59 +0200904 }
905 break;
906 case PSEV_LINE_RX_B:
907 if (ch->state == STFAX_LINE) {
908 pr_debug("%s: pump stev LINE_RX_B\n", ch->is->name);
909 ch->state = STFAX_CONT;
910 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -0800911 PCTRL_CMD_CONT, 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +0200912 } else {
913 pr_debug("%s: pump stev LINE_RX_B wrong st %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800914 ch->is->name, ch->state);
Karsten Keilda2272c92009-07-22 20:01:59 +0200915 }
916 break;
917 case PSEV_RSP_CONN:
918 if (ch->state == STFAX_CONT) {
919 pr_debug("%s: pump stev RSP_CONN\n", ch->is->name);
920 ch->state = STFAX_ACTIV;
921 test_and_set_bit(ISAR_RATE_REQ, &ch->is->Flags);
922 send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
923 if (ch->cmd == PCTRL_CMD_FTH) {
924 int delay = (ch->mod == 3) ? 1000 : 200;
925 /* 1s (200 ms) Flags before data */
926 if (test_and_set_bit(FLG_FTI_RUN,
Joe Perches475be4d2012-02-19 19:52:38 -0800927 &ch->bch.Flags))
Karsten Keilda2272c92009-07-22 20:01:59 +0200928 del_timer(&ch->ftimer);
929 ch->ftimer.expires =
Joe Perches475be4d2012-02-19 19:52:38 -0800930 jiffies + ((delay * HZ) / 1000);
Karsten Keilda2272c92009-07-22 20:01:59 +0200931 test_and_set_bit(FLG_LL_CONN,
Joe Perches475be4d2012-02-19 19:52:38 -0800932 &ch->bch.Flags);
Karsten Keilda2272c92009-07-22 20:01:59 +0200933 add_timer(&ch->ftimer);
934 } else {
935 deliver_status(ch, HW_MOD_CONNECT);
936 }
937 } else {
938 pr_debug("%s: pump stev RSP_CONN wrong st %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800939 ch->is->name, ch->state);
Karsten Keilda2272c92009-07-22 20:01:59 +0200940 }
941 break;
942 case PSEV_FLAGS_DET:
943 pr_debug("%s: pump stev FLAGS_DET\n", ch->is->name);
944 break;
945 case PSEV_RSP_DISC:
946 pr_debug("%s: pump stev RSP_DISC state(%d)\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800947 ch->is->name, ch->state);
Karsten Keilda2272c92009-07-22 20:01:59 +0200948 if (ch->state == STFAX_ESCAPE) {
949 p1 = 5;
950 switch (ch->newcmd) {
951 case 0:
952 ch->state = STFAX_READY;
953 break;
954 case PCTRL_CMD_FTM:
955 p1 = 2;
956 case PCTRL_CMD_FTH:
957 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -0800958 PCTRL_CMD_SILON, 1, &p1);
Karsten Keilda2272c92009-07-22 20:01:59 +0200959 ch->state = STFAX_SILDET;
960 break;
961 case PCTRL_CMD_FRH:
962 case PCTRL_CMD_FRM:
963 ch->mod = ch->newmod;
964 p1 = ch->newmod;
965 ch->newmod = 0;
966 ch->cmd = ch->newcmd;
967 ch->newcmd = 0;
968 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -0800969 ch->cmd, 1, &p1);
Karsten Keilda2272c92009-07-22 20:01:59 +0200970 ch->state = STFAX_LINE;
971 ch->try_mod = 3;
972 break;
973 default:
974 pr_debug("%s: RSP_DISC unknown newcmd %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800975 ch->is->name, ch->newcmd);
Karsten Keilda2272c92009-07-22 20:01:59 +0200976 break;
977 }
978 } else if (ch->state == STFAX_ACTIV) {
979 if (test_and_clear_bit(FLG_LL_OK, &ch->bch.Flags))
980 deliver_status(ch, HW_MOD_OK);
981 else if (ch->cmd == PCTRL_CMD_FRM)
982 deliver_status(ch, HW_MOD_NOCARR);
983 else
984 deliver_status(ch, HW_MOD_FCERROR);
985 ch->state = STFAX_READY;
986 } else if (ch->state != STFAX_SILDET) {
987 /* ignore in STFAX_SILDET */
988 ch->state = STFAX_READY;
989 deliver_status(ch, HW_MOD_FCERROR);
990 }
991 break;
992 case PSEV_RSP_SILDET:
993 pr_debug("%s: pump stev RSP_SILDET\n", ch->is->name);
994 if (ch->state == STFAX_SILDET) {
995 ch->mod = ch->newmod;
996 p1 = ch->newmod;
997 ch->newmod = 0;
998 ch->cmd = ch->newcmd;
999 ch->newcmd = 0;
1000 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -08001001 ch->cmd, 1, &p1);
Karsten Keilda2272c92009-07-22 20:01:59 +02001002 ch->state = STFAX_LINE;
1003 ch->try_mod = 3;
1004 }
1005 break;
1006 case PSEV_RSP_SILOFF:
1007 pr_debug("%s: pump stev RSP_SILOFF\n", ch->is->name);
1008 break;
1009 case PSEV_RSP_FCERR:
1010 if (ch->state == STFAX_LINE) {
1011 pr_debug("%s: pump stev RSP_FCERR try %d\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001012 ch->is->name, ch->try_mod);
Karsten Keilda2272c92009-07-22 20:01:59 +02001013 if (ch->try_mod--) {
1014 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL,
Joe Perches475be4d2012-02-19 19:52:38 -08001015 ch->cmd, 1, &ch->mod);
Karsten Keilda2272c92009-07-22 20:01:59 +02001016 break;
1017 }
1018 }
1019 pr_debug("%s: pump stev RSP_FCERR\n", ch->is->name);
1020 ch->state = STFAX_ESCAPE;
1021 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
Joe Perches475be4d2012-02-19 19:52:38 -08001022 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +02001023 deliver_status(ch, HW_MOD_FCERROR);
1024 break;
1025 default:
1026 break;
1027 }
1028}
1029
1030void
1031mISDNisar_irq(struct isar_hw *isar)
1032{
1033 struct isar_ch *ch;
1034
1035 get_irq_infos(isar);
1036 switch (isar->iis & ISAR_IIS_MSCMSD) {
1037 case ISAR_IIS_RDATA:
1038 ch = sel_bch_isar(isar, isar->iis >> 6);
1039 if (ch)
1040 isar_rcv_frame(ch);
1041 else {
1042 pr_debug("%s: ISAR spurious IIS_RDATA %x/%x/%x\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001043 isar->name, isar->iis, isar->cmsb,
1044 isar->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +02001045 isar->write_reg(isar->hw, ISAR_IIA, 0);
1046 }
1047 break;
1048 case ISAR_IIS_GSTEV:
1049 isar->write_reg(isar->hw, ISAR_IIA, 0);
1050 isar->bstat |= isar->cmsb;
1051 check_send(isar, isar->cmsb);
1052 break;
1053 case ISAR_IIS_BSTEV:
1054#ifdef ERROR_STATISTIC
1055 ch = sel_bch_isar(isar, isar->iis >> 6);
1056 if (ch) {
1057 if (isar->cmsb == BSTEV_TBO)
1058 ch->bch.err_tx++;
1059 if (isar->cmsb == BSTEV_RBO)
1060 ch->bch.err_rdo++;
1061 }
1062#endif
1063 pr_debug("%s: Buffer STEV dpath%d msb(%x)\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001064 isar->name, isar->iis >> 6, isar->cmsb);
Karsten Keilda2272c92009-07-22 20:01:59 +02001065 isar->write_reg(isar->hw, ISAR_IIA, 0);
1066 break;
1067 case ISAR_IIS_PSTEV:
1068 ch = sel_bch_isar(isar, isar->iis >> 6);
1069 if (ch) {
1070 rcv_mbox(isar, NULL);
1071 if (ch->bch.state == ISDN_P_B_MODEM_ASYNC)
1072 isar_pump_statev_modem(ch, isar->cmsb);
1073 else if (ch->bch.state == ISDN_P_B_T30_FAX)
1074 isar_pump_statev_fax(ch, isar->cmsb);
1075 else if (ch->bch.state == ISDN_P_B_RAW) {
1076 int tt;
1077 tt = isar->cmsb | 0x30;
1078 if (tt == 0x3e)
1079 tt = '*';
1080 else if (tt == 0x3f)
1081 tt = '#';
1082 else if (tt > '9')
1083 tt += 7;
1084 tt |= DTMF_TONE_VAL;
1085 _queue_data(&ch->bch.ch, PH_CONTROL_IND,
Joe Perches475be4d2012-02-19 19:52:38 -08001086 MISDN_ID_ANY, sizeof(tt), &tt,
1087 GFP_ATOMIC);
Karsten Keilda2272c92009-07-22 20:01:59 +02001088 } else
1089 pr_debug("%s: ISAR IIS_PSTEV pm %d sta %x\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001090 isar->name, ch->bch.state,
1091 isar->cmsb);
Karsten Keilda2272c92009-07-22 20:01:59 +02001092 } else {
1093 pr_debug("%s: ISAR spurious IIS_PSTEV %x/%x/%x\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001094 isar->name, isar->iis, isar->cmsb,
1095 isar->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +02001096 isar->write_reg(isar->hw, ISAR_IIA, 0);
1097 }
1098 break;
1099 case ISAR_IIS_PSTRSP:
1100 ch = sel_bch_isar(isar, isar->iis >> 6);
1101 if (ch) {
1102 rcv_mbox(isar, NULL);
1103 isar_pump_status_rsp(ch);
1104 } else {
1105 pr_debug("%s: ISAR spurious IIS_PSTRSP %x/%x/%x\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001106 isar->name, isar->iis, isar->cmsb,
1107 isar->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +02001108 isar->write_reg(isar->hw, ISAR_IIA, 0);
1109 }
1110 break;
1111 case ISAR_IIS_DIAG:
1112 case ISAR_IIS_BSTRSP:
1113 case ISAR_IIS_IOM2RSP:
1114 rcv_mbox(isar, NULL);
1115 break;
1116 case ISAR_IIS_INVMSG:
1117 rcv_mbox(isar, NULL);
1118 pr_debug("%s: invalid msg his:%x\n", isar->name, isar->cmsb);
1119 break;
1120 default:
1121 rcv_mbox(isar, NULL);
1122 pr_debug("%s: unhandled msg iis(%x) ctrl(%x/%x)\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001123 isar->name, isar->iis, isar->cmsb, isar->clsb);
Karsten Keilda2272c92009-07-22 20:01:59 +02001124 break;
1125 }
1126}
1127EXPORT_SYMBOL(mISDNisar_irq);
1128
1129static void
1130ftimer_handler(unsigned long data)
1131{
1132 struct isar_ch *ch = (struct isar_ch *)data;
1133
1134 pr_debug("%s: ftimer flags %lx\n", ch->is->name, ch->bch.Flags);
1135 test_and_clear_bit(FLG_FTI_RUN, &ch->bch.Flags);
1136 if (test_and_clear_bit(FLG_LL_CONN, &ch->bch.Flags))
1137 deliver_status(ch, HW_MOD_CONNECT);
1138}
1139
1140static void
1141setup_pump(struct isar_ch *ch) {
1142 u8 dps = SET_DPS(ch->dpath);
1143 u8 ctrl, param[6];
1144
1145 switch (ch->bch.state) {
1146 case ISDN_P_NONE:
1147 case ISDN_P_B_RAW:
1148 case ISDN_P_B_HDLC:
1149 send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
1150 break;
1151 case ISDN_P_B_L2DTMF:
1152 if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) {
1153 param[0] = 5; /* TOA 5 db */
1154 send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG,
Joe Perches475be4d2012-02-19 19:52:38 -08001155 PMOD_DTMF_TRANS, 1, param);
Karsten Keilda2272c92009-07-22 20:01:59 +02001156 } else {
1157 param[0] = 40; /* REL -46 dbm */
1158 send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG,
Joe Perches475be4d2012-02-19 19:52:38 -08001159 PMOD_DTMF, 1, param);
Karsten Keilda2272c92009-07-22 20:01:59 +02001160 }
1161 case ISDN_P_B_MODEM_ASYNC:
1162 ctrl = PMOD_DATAMODEM;
1163 if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) {
1164 ctrl |= PCTRL_ORIG;
1165 param[5] = PV32P6_CTN;
1166 } else {
1167 param[5] = PV32P6_ATN;
1168 }
1169 param[0] = 6; /* 6 db */
1170 param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
1171 PV32P2_V22C | PV32P2_V21 | PV32P2_BEL;
1172 param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
1173 param[3] = PV32P4_UT144;
1174 param[4] = PV32P5_UT144;
1175 send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
1176 break;
1177 case ISDN_P_B_T30_FAX:
1178 ctrl = PMOD_FAX;
1179 if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) {
1180 ctrl |= PCTRL_ORIG;
1181 param[1] = PFAXP2_CTN;
1182 } else {
1183 param[1] = PFAXP2_ATN;
1184 }
1185 param[0] = 6; /* 6 db */
1186 send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
1187 ch->state = STFAX_NULL;
1188 ch->newcmd = 0;
1189 ch->newmod = 0;
1190 test_and_set_bit(FLG_FTI_RUN, &ch->bch.Flags);
1191 break;
1192 }
1193 udelay(1000);
1194 send_mbox(ch->is, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
1195 udelay(1000);
1196}
1197
1198static void
1199setup_sart(struct isar_ch *ch) {
1200 u8 dps = SET_DPS(ch->dpath);
1201 u8 ctrl, param[2] = {0, 0};
1202
1203 switch (ch->bch.state) {
1204 case ISDN_P_NONE:
1205 send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE,
Joe Perches475be4d2012-02-19 19:52:38 -08001206 0, NULL);
Karsten Keilda2272c92009-07-22 20:01:59 +02001207 break;
1208 case ISDN_P_B_RAW:
1209 case ISDN_P_B_L2DTMF:
1210 send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_BINARY,
Joe Perches475be4d2012-02-19 19:52:38 -08001211 2, param);
Karsten Keilda2272c92009-07-22 20:01:59 +02001212 break;
1213 case ISDN_P_B_HDLC:
1214 case ISDN_P_B_T30_FAX:
1215 send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, SMODE_HDLC,
Joe Perches475be4d2012-02-19 19:52:38 -08001216 1, param);
Karsten Keilda2272c92009-07-22 20:01:59 +02001217 break;
1218 case ISDN_P_B_MODEM_ASYNC:
1219 ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
1220 param[0] = S_P1_CHS_8;
1221 param[1] = S_P2_BFT_DEF;
1222 send_mbox(ch->is, dps | ISAR_HIS_SARTCFG, ctrl, 2, param);
1223 break;
1224 }
1225 udelay(1000);
1226 send_mbox(ch->is, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
1227 udelay(1000);
1228}
1229
1230static void
1231setup_iom2(struct isar_ch *ch) {
1232 u8 dps = SET_DPS(ch->dpath);
1233 u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD, 0, 0, 0, 0};
1234
1235 if (ch->bch.nr == 2) {
1236 msg[1] = 1;
1237 msg[3] = 1;
1238 }
1239 switch (ch->bch.state) {
1240 case ISDN_P_NONE:
1241 cmsb = 0;
1242 /* dummy slot */
1243 msg[1] = ch->dpath + 2;
1244 msg[3] = ch->dpath + 2;
1245 break;
1246 case ISDN_P_B_RAW:
1247 case ISDN_P_B_HDLC:
1248 break;
1249 case ISDN_P_B_MODEM_ASYNC:
1250 case ISDN_P_B_T30_FAX:
1251 cmsb |= IOM_CTRL_RCV;
1252 case ISDN_P_B_L2DTMF:
1253 if (test_bit(FLG_DTMFSEND, &ch->bch.Flags))
1254 cmsb |= IOM_CTRL_RCV;
1255 cmsb |= IOM_CTRL_ALAW;
1256 break;
1257 }
1258 send_mbox(ch->is, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg);
1259 udelay(1000);
1260 send_mbox(ch->is, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL);
1261 udelay(1000);
1262}
1263
1264static int
1265modeisar(struct isar_ch *ch, u32 bprotocol)
1266{
1267 /* Here we are selecting the best datapath for requested protocol */
1268 if (ch->bch.state == ISDN_P_NONE) { /* New Setup */
1269 switch (bprotocol) {
1270 case ISDN_P_NONE: /* init */
1271 if (!ch->dpath)
1272 /* no init for dpath 0 */
1273 return 0;
1274 test_and_clear_bit(FLG_HDLC, &ch->bch.Flags);
1275 test_and_clear_bit(FLG_TRANSPARENT, &ch->bch.Flags);
1276 break;
1277 case ISDN_P_B_RAW:
1278 case ISDN_P_B_HDLC:
1279 /* best is datapath 2 */
1280 if (!test_and_set_bit(ISAR_DP2_USE, &ch->is->Flags))
1281 ch->dpath = 2;
1282 else if (!test_and_set_bit(ISAR_DP1_USE,
Joe Perches475be4d2012-02-19 19:52:38 -08001283 &ch->is->Flags))
Karsten Keilda2272c92009-07-22 20:01:59 +02001284 ch->dpath = 1;
1285 else {
1286 pr_info("modeisar both pathes in use\n");
1287 return -EBUSY;
1288 }
1289 if (bprotocol == ISDN_P_B_HDLC)
1290 test_and_set_bit(FLG_HDLC, &ch->bch.Flags);
1291 else
1292 test_and_set_bit(FLG_TRANSPARENT,
Joe Perches475be4d2012-02-19 19:52:38 -08001293 &ch->bch.Flags);
Karsten Keilda2272c92009-07-22 20:01:59 +02001294 break;
1295 case ISDN_P_B_MODEM_ASYNC:
1296 case ISDN_P_B_T30_FAX:
1297 case ISDN_P_B_L2DTMF:
1298 /* only datapath 1 */
1299 if (!test_and_set_bit(ISAR_DP1_USE, &ch->is->Flags))
1300 ch->dpath = 1;
1301 else {
1302 pr_info("%s: ISAR modeisar analog functions"
1303 "only with DP1\n", ch->is->name);
1304 return -EBUSY;
1305 }
1306 break;
1307 default:
1308 pr_info("%s: protocol not known %x\n", ch->is->name,
1309 bprotocol);
1310 return -ENOPROTOOPT;
1311 }
1312 }
1313 pr_debug("%s: ISAR ch%d dp%d protocol %x->%x\n", ch->is->name,
Joe Perches475be4d2012-02-19 19:52:38 -08001314 ch->bch.nr, ch->dpath, ch->bch.state, bprotocol);
Karsten Keilda2272c92009-07-22 20:01:59 +02001315 ch->bch.state = bprotocol;
1316 setup_pump(ch);
1317 setup_iom2(ch);
1318 setup_sart(ch);
1319 if (ch->bch.state == ISDN_P_NONE) {
1320 /* Clear resources */
1321 if (ch->dpath == 1)
1322 test_and_clear_bit(ISAR_DP1_USE, &ch->is->Flags);
1323 else if (ch->dpath == 2)
1324 test_and_clear_bit(ISAR_DP2_USE, &ch->is->Flags);
1325 ch->dpath = 0;
1326 ch->is->ctrl(ch->is->hw, HW_DEACT_IND, ch->bch.nr);
1327 } else
1328 ch->is->ctrl(ch->is->hw, HW_ACTIVATE_IND, ch->bch.nr);
1329 return 0;
1330}
1331
1332static void
1333isar_pump_cmd(struct isar_ch *ch, u32 cmd, u8 para)
1334{
1335 u8 dps = SET_DPS(ch->dpath);
1336 u8 ctrl = 0, nom = 0, p1 = 0;
1337
1338 pr_debug("%s: isar_pump_cmd %x/%x state(%x)\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001339 ch->is->name, cmd, para, ch->bch.state);
Karsten Keilda2272c92009-07-22 20:01:59 +02001340 switch (cmd) {
1341 case HW_MOD_FTM:
1342 if (ch->state == STFAX_READY) {
1343 p1 = para;
1344 ctrl = PCTRL_CMD_FTM;
1345 nom = 1;
1346 ch->state = STFAX_LINE;
1347 ch->cmd = ctrl;
1348 ch->mod = para;
1349 ch->newmod = 0;
1350 ch->newcmd = 0;
1351 ch->try_mod = 3;
1352 } else if ((ch->state == STFAX_ACTIV) &&
Joe Perches475be4d2012-02-19 19:52:38 -08001353 (ch->cmd == PCTRL_CMD_FTM) && (ch->mod == para))
Karsten Keilda2272c92009-07-22 20:01:59 +02001354 deliver_status(ch, HW_MOD_CONNECT);
1355 else {
1356 ch->newmod = para;
1357 ch->newcmd = PCTRL_CMD_FTM;
1358 nom = 0;
1359 ctrl = PCTRL_CMD_ESC;
1360 ch->state = STFAX_ESCAPE;
1361 }
1362 break;
1363 case HW_MOD_FTH:
1364 if (ch->state == STFAX_READY) {
1365 p1 = para;
1366 ctrl = PCTRL_CMD_FTH;
1367 nom = 1;
1368 ch->state = STFAX_LINE;
1369 ch->cmd = ctrl;
1370 ch->mod = para;
1371 ch->newmod = 0;
1372 ch->newcmd = 0;
1373 ch->try_mod = 3;
1374 } else if ((ch->state == STFAX_ACTIV) &&
Joe Perches475be4d2012-02-19 19:52:38 -08001375 (ch->cmd == PCTRL_CMD_FTH) && (ch->mod == para))
1376 deliver_status(ch, HW_MOD_CONNECT);
Karsten Keilda2272c92009-07-22 20:01:59 +02001377 else {
1378 ch->newmod = para;
1379 ch->newcmd = PCTRL_CMD_FTH;
1380 nom = 0;
1381 ctrl = PCTRL_CMD_ESC;
1382 ch->state = STFAX_ESCAPE;
1383 }
1384 break;
1385 case HW_MOD_FRM:
1386 if (ch->state == STFAX_READY) {
1387 p1 = para;
1388 ctrl = PCTRL_CMD_FRM;
1389 nom = 1;
1390 ch->state = STFAX_LINE;
1391 ch->cmd = ctrl;
1392 ch->mod = para;
1393 ch->newmod = 0;
1394 ch->newcmd = 0;
1395 ch->try_mod = 3;
1396 } else if ((ch->state == STFAX_ACTIV) &&
Joe Perches475be4d2012-02-19 19:52:38 -08001397 (ch->cmd == PCTRL_CMD_FRM) && (ch->mod == para))
Karsten Keilda2272c92009-07-22 20:01:59 +02001398 deliver_status(ch, HW_MOD_CONNECT);
1399 else {
1400 ch->newmod = para;
1401 ch->newcmd = PCTRL_CMD_FRM;
1402 nom = 0;
1403 ctrl = PCTRL_CMD_ESC;
1404 ch->state = STFAX_ESCAPE;
1405 }
1406 break;
1407 case HW_MOD_FRH:
1408 if (ch->state == STFAX_READY) {
1409 p1 = para;
1410 ctrl = PCTRL_CMD_FRH;
1411 nom = 1;
1412 ch->state = STFAX_LINE;
1413 ch->cmd = ctrl;
1414 ch->mod = para;
1415 ch->newmod = 0;
1416 ch->newcmd = 0;
1417 ch->try_mod = 3;
1418 } else if ((ch->state == STFAX_ACTIV) &&
Joe Perches475be4d2012-02-19 19:52:38 -08001419 (ch->cmd == PCTRL_CMD_FRH) && (ch->mod == para))
Karsten Keilda2272c92009-07-22 20:01:59 +02001420 deliver_status(ch, HW_MOD_CONNECT);
1421 else {
1422 ch->newmod = para;
1423 ch->newcmd = PCTRL_CMD_FRH;
1424 nom = 0;
1425 ctrl = PCTRL_CMD_ESC;
1426 ch->state = STFAX_ESCAPE;
1427 }
1428 break;
1429 case PCTRL_CMD_TDTMF:
1430 p1 = para;
1431 nom = 1;
1432 ctrl = PCTRL_CMD_TDTMF;
1433 break;
1434 }
1435 if (ctrl)
1436 send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
1437}
1438
1439static void
1440isar_setup(struct isar_hw *isar)
1441{
1442 u8 msg;
1443 int i;
1444
1445 /* Dpath 1, 2 */
1446 msg = 61;
1447 for (i = 0; i < 2; i++) {
1448 /* Buffer Config */
1449 send_mbox(isar, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
Joe Perches475be4d2012-02-19 19:52:38 -08001450 ISAR_HIS_P12CFG, 4, 1, &msg);
Karsten Keilda2272c92009-07-22 20:01:59 +02001451 isar->ch[i].mml = msg;
1452 isar->ch[i].bch.state = 0;
1453 isar->ch[i].dpath = i + 1;
1454 modeisar(&isar->ch[i], ISDN_P_NONE);
1455 }
1456}
1457
1458static int
1459isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1460{
1461 struct bchannel *bch = container_of(ch, struct bchannel, ch);
1462 struct isar_ch *ich = container_of(bch, struct isar_ch, bch);
1463 int ret = -EINVAL;
1464 struct mISDNhead *hh = mISDN_HEAD_P(skb);
1465 u32 id, *val;
1466 u_long flags;
1467
1468 switch (hh->prim) {
1469 case PH_DATA_REQ:
1470 spin_lock_irqsave(ich->is->hwlock, flags);
1471 ret = bchannel_senddata(bch, skb);
1472 if (ret > 0) { /* direct TX */
Karsten Keilda2272c92009-07-22 20:01:59 +02001473 ret = 0;
1474 isar_fill_fifo(ich);
Karsten Keil8bfddfb2012-05-15 23:51:02 +00001475 }
1476 spin_unlock_irqrestore(ich->is->hwlock, flags);
Karsten Keilda2272c92009-07-22 20:01:59 +02001477 return ret;
1478 case PH_ACTIVATE_REQ:
1479 spin_lock_irqsave(ich->is->hwlock, flags);
1480 if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
1481 ret = modeisar(ich, ch->protocol);
1482 else
1483 ret = 0;
1484 spin_unlock_irqrestore(ich->is->hwlock, flags);
1485 if (!ret)
1486 _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
Joe Perches475be4d2012-02-19 19:52:38 -08001487 NULL, GFP_KERNEL);
Karsten Keilda2272c92009-07-22 20:01:59 +02001488 break;
1489 case PH_DEACTIVATE_REQ:
1490 spin_lock_irqsave(ich->is->hwlock, flags);
1491 mISDN_clear_bchannel(bch);
1492 modeisar(ich, ISDN_P_NONE);
1493 spin_unlock_irqrestore(ich->is->hwlock, flags);
1494 _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
Joe Perches475be4d2012-02-19 19:52:38 -08001495 NULL, GFP_KERNEL);
Karsten Keilda2272c92009-07-22 20:01:59 +02001496 ret = 0;
1497 break;
1498 case PH_CONTROL_REQ:
1499 val = (u32 *)skb->data;
1500 pr_debug("%s: PH_CONTROL | REQUEST %x/%x\n", ich->is->name,
Joe Perches475be4d2012-02-19 19:52:38 -08001501 hh->id, *val);
Karsten Keilda2272c92009-07-22 20:01:59 +02001502 if ((hh->id == 0) && ((*val & ~DTMF_TONE_MASK) ==
Joe Perches475be4d2012-02-19 19:52:38 -08001503 DTMF_TONE_VAL)) {
Karsten Keilda2272c92009-07-22 20:01:59 +02001504 if (bch->state == ISDN_P_B_L2DTMF) {
1505 char tt = *val & DTMF_TONE_MASK;
1506
1507 if (tt == '*')
1508 tt = 0x1e;
1509 else if (tt == '#')
1510 tt = 0x1f;
1511 else if (tt > '9')
1512 tt -= 7;
1513 tt &= 0x1f;
1514 spin_lock_irqsave(ich->is->hwlock, flags);
1515 isar_pump_cmd(ich, PCTRL_CMD_TDTMF, tt);
1516 spin_unlock_irqrestore(ich->is->hwlock, flags);
1517 } else {
1518 pr_info("%s: DTMF send wrong protocol %x\n",
1519 __func__, bch->state);
1520 return -EINVAL;
1521 }
1522 } else if ((hh->id == HW_MOD_FRM) || (hh->id == HW_MOD_FRH) ||
Joe Perches475be4d2012-02-19 19:52:38 -08001523 (hh->id == HW_MOD_FTM) || (hh->id == HW_MOD_FTH)) {
Karsten Keilda2272c92009-07-22 20:01:59 +02001524 for (id = 0; id < FAXMODCNT; id++)
1525 if (faxmodulation[id] == *val)
1526 break;
1527 if ((FAXMODCNT > id) &&
1528 test_bit(FLG_INITIALIZED, &bch->Flags)) {
1529 pr_debug("%s: isar: new mod\n", ich->is->name);
1530 isar_pump_cmd(ich, hh->id, *val);
1531 ret = 0;
1532 } else {
1533 pr_info("%s: wrong modulation\n",
1534 ich->is->name);
1535 ret = -EINVAL;
1536 }
1537 } else if (hh->id == HW_MOD_LASTDATA)
1538 test_and_set_bit(FLG_DLEETX, &bch->Flags);
1539 else {
1540 pr_info("%s: unknown PH_CONTROL_REQ %x\n",
1541 ich->is->name, hh->id);
1542 ret = -EINVAL;
1543 }
1544 default:
1545 pr_info("%s: %s unknown prim(%x,%x)\n",
1546 ich->is->name, __func__, hh->prim, hh->id);
1547 ret = -EINVAL;
1548 }
1549 if (!ret)
1550 dev_kfree_skb(skb);
1551 return ret;
1552}
1553
1554static int
1555channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1556{
Karsten Keil034005a2012-05-15 23:51:06 +00001557 return mISDN_ctrl_bchannel(bch, cq);
Karsten Keilda2272c92009-07-22 20:01:59 +02001558}
1559
1560static int
1561isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
1562{
1563 struct bchannel *bch = container_of(ch, struct bchannel, ch);
1564 struct isar_ch *ich = container_of(bch, struct isar_ch, bch);
1565 int ret = -EINVAL;
1566 u_long flags;
1567
1568 pr_debug("%s: %s cmd:%x %p\n", ich->is->name, __func__, cmd, arg);
1569 switch (cmd) {
1570 case CLOSE_CHANNEL:
1571 test_and_clear_bit(FLG_OPEN, &bch->Flags);
Karsten Keil13681122012-05-15 23:51:01 +00001572 spin_lock_irqsave(ich->is->hwlock, flags);
1573 mISDN_freebchannel(bch);
1574 modeisar(ich, ISDN_P_NONE);
1575 spin_unlock_irqrestore(ich->is->hwlock, flags);
Karsten Keilda2272c92009-07-22 20:01:59 +02001576 ch->protocol = ISDN_P_NONE;
1577 ch->peer = NULL;
1578 module_put(ich->is->owner);
1579 ret = 0;
1580 break;
1581 case CONTROL_CHANNEL:
1582 ret = channel_bctrl(bch, arg);
1583 break;
1584 default:
1585 pr_info("%s: %s unknown prim(%x)\n",
1586 ich->is->name, __func__, cmd);
1587 }
1588 return ret;
1589}
1590
1591static void
1592free_isar(struct isar_hw *isar)
1593{
1594 modeisar(&isar->ch[0], ISDN_P_NONE);
1595 modeisar(&isar->ch[1], ISDN_P_NONE);
1596 del_timer(&isar->ch[0].ftimer);
1597 del_timer(&isar->ch[1].ftimer);
1598 test_and_clear_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags);
1599 test_and_clear_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags);
1600}
1601
1602static int
1603init_isar(struct isar_hw *isar)
1604{
1605 int cnt = 3;
1606
1607 while (cnt--) {
1608 isar->version = ISARVersion(isar);
1609 if (isar->ch[0].bch.debug & DEBUG_HW)
1610 pr_notice("%s: Testing version %d (%d time)\n",
Joe Perches475be4d2012-02-19 19:52:38 -08001611 isar->name, isar->version, 3 - cnt);
Karsten Keilda2272c92009-07-22 20:01:59 +02001612 if (isar->version == 1)
1613 break;
1614 isar->ctrl(isar->hw, HW_RESET_REQ, 0);
1615 }
1616 if (isar->version != 1)
1617 return -EINVAL;
1618 isar->ch[0].ftimer.function = &ftimer_handler;
1619 isar->ch[0].ftimer.data = (long)&isar->ch[0];
1620 init_timer(&isar->ch[0].ftimer);
1621 test_and_set_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags);
1622 isar->ch[1].ftimer.function = &ftimer_handler;
1623 isar->ch[1].ftimer.data = (long)&isar->ch[1];
1624 init_timer(&isar->ch[1].ftimer);
1625 test_and_set_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags);
1626 return 0;
1627}
1628
1629static int
1630isar_open(struct isar_hw *isar, struct channel_req *rq)
1631{
1632 struct bchannel *bch;
1633
Dan Carpenter819a1002012-03-26 21:20:48 +00001634 if (rq->adr.channel == 0 || rq->adr.channel > 2)
Karsten Keilda2272c92009-07-22 20:01:59 +02001635 return -EINVAL;
1636 if (rq->protocol == ISDN_P_NONE)
1637 return -EINVAL;
1638 bch = &isar->ch[rq->adr.channel - 1].bch;
1639 if (test_and_set_bit(FLG_OPEN, &bch->Flags))
1640 return -EBUSY; /* b-channel can be only open once */
1641 test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
1642 bch->ch.protocol = rq->protocol;
1643 rq->ch = &bch->ch;
1644 return 0;
1645}
1646
1647u32
1648mISDNisar_init(struct isar_hw *isar, void *hw)
1649{
1650 u32 ret, i;
1651
1652 isar->hw = hw;
1653 for (i = 0; i < 2; i++) {
1654 isar->ch[i].bch.nr = i + 1;
Karsten Keil034005a2012-05-15 23:51:06 +00001655 mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32);
Karsten Keilda2272c92009-07-22 20:01:59 +02001656 isar->ch[i].bch.ch.nr = i + 1;
1657 isar->ch[i].bch.ch.send = &isar_l2l1;
1658 isar->ch[i].bch.ch.ctrl = isar_bctrl;
1659 isar->ch[i].bch.hw = hw;
1660 isar->ch[i].is = isar;
1661 }
1662
1663 isar->init = &init_isar;
1664 isar->release = &free_isar;
1665 isar->firmware = &load_firmware;
1666 isar->open = &isar_open;
1667
1668 ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
1669 (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)) |
1670 (1 << (ISDN_P_B_L2DTMF & ISDN_P_B_MASK)) |
1671 (1 << (ISDN_P_B_MODEM_ASYNC & ISDN_P_B_MASK)) |
1672 (1 << (ISDN_P_B_T30_FAX & ISDN_P_B_MASK));
1673
1674 return ret;
1675}
1676EXPORT_SYMBOL(mISDNisar_init);
1677
Peter Huewe88850742009-12-22 09:27:06 +01001678static int __init isar_mod_init(void)
Karsten Keilda2272c92009-07-22 20:01:59 +02001679{
1680 pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV);
1681 return 0;
1682}
1683
Peter Huewe88850742009-12-22 09:27:06 +01001684static void __exit isar_mod_cleanup(void)
Karsten Keilda2272c92009-07-22 20:01:59 +02001685{
1686 pr_notice("mISDN: ISAR module unloaded\n");
1687}
1688module_init(isar_mod_init);
1689module_exit(isar_mod_cleanup);