aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hardware/mISDN/mISDNipac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/hardware/mISDN/mISDNipac.c')
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c1655
1 files changed, 1655 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
new file mode 100644
index 000000000000..613ba0435372
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -0,0 +1,1655 @@
1/*
2 * isac.c ISAC specific routines
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#include <linux/module.h>
24#include <linux/mISDNhw.h>
25#include "ipac.h"
26
27
28#define DBUSY_TIMER_VALUE 80
29#define ARCOFI_USE 1
30
31#define ISAC_REV "2.0"
32
33MODULE_AUTHOR("Karsten Keil");
34MODULE_VERSION(ISAC_REV);
35MODULE_LICENSE("GPL v2");
36
37#define ReadISAC(is, o) (is->read_reg(is->dch.hw, o + is->off))
38#define WriteISAC(is, o, v) (is->write_reg(is->dch.hw, o + is->off, v))
39#define ReadHSCX(h, o) (h->ip->read_reg(h->ip->hw, h->off + o))
40#define WriteHSCX(h, o, v) (h->ip->write_reg(h->ip->hw, h->off + o, v))
41#define ReadIPAC(ip, o) (ip->read_reg(ip->hw, o))
42#define WriteIPAC(ip, o, v) (ip->write_reg(ip->hw, o, v))
43
44static inline void
45ph_command(struct isac_hw *isac, u8 command)
46{
47 pr_debug("%s: ph_command %x\n", isac->name, command);
48 if (isac->type & IPAC_TYPE_ISACX)
49 WriteISAC(isac, ISACX_CIX0, (command << 4) | 0xE);
50 else
51 WriteISAC(isac, ISAC_CIX0, (command << 2) | 3);
52}
53
54static void
55isac_ph_state_change(struct isac_hw *isac)
56{
57 switch (isac->state) {
58 case (ISAC_IND_RS):
59 case (ISAC_IND_EI):
60 ph_command(isac, ISAC_CMD_DUI);
61 }
62 schedule_event(&isac->dch, FLG_PHCHANGE);
63}
64
65static void
66isac_ph_state_bh(struct dchannel *dch)
67{
68 struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
69
70 switch (isac->state) {
71 case ISAC_IND_RS:
72 case ISAC_IND_EI:
73 dch->state = 0;
74 l1_event(dch->l1, HW_RESET_IND);
75 break;
76 case ISAC_IND_DID:
77 dch->state = 3;
78 l1_event(dch->l1, HW_DEACT_CNF);
79 break;
80 case ISAC_IND_DR:
81 dch->state = 3;
82 l1_event(dch->l1, HW_DEACT_IND);
83 break;
84 case ISAC_IND_PU:
85 dch->state = 4;
86 l1_event(dch->l1, HW_POWERUP_IND);
87 break;
88 case ISAC_IND_RSY:
89 if (dch->state <= 5) {
90 dch->state = 5;
91 l1_event(dch->l1, ANYSIGNAL);
92 } else {
93 dch->state = 8;
94 l1_event(dch->l1, LOSTFRAMING);
95 }
96 break;
97 case ISAC_IND_ARD:
98 dch->state = 6;
99 l1_event(dch->l1, INFO2);
100 break;
101 case ISAC_IND_AI8:
102 dch->state = 7;
103 l1_event(dch->l1, INFO4_P8);
104 break;
105 case ISAC_IND_AI10:
106 dch->state = 7;
107 l1_event(dch->l1, INFO4_P10);
108 break;
109 }
110 pr_debug("%s: TE newstate %x\n", isac->name, dch->state);
111}
112
113void
114isac_empty_fifo(struct isac_hw *isac, int count)
115{
116 u8 *ptr;
117
118 pr_debug("%s: %s %d\n", isac->name, __func__, count);
119
120 if (!isac->dch.rx_skb) {
121 isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC);
122 if (!isac->dch.rx_skb) {
123 pr_info("%s: D receive out of memory\n", isac->name);
124 WriteISAC(isac, ISAC_CMDR, 0x80);
125 return;
126 }
127 }
128 if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
129 pr_debug("%s: %s overrun %d\n", isac->name, __func__,
130 isac->dch.rx_skb->len + count);
131 WriteISAC(isac, ISAC_CMDR, 0x80);
132 return;
133 }
134 ptr = skb_put(isac->dch.rx_skb, count);
135 isac->read_fifo(isac->dch.hw, isac->off, ptr, count);
136 WriteISAC(isac, ISAC_CMDR, 0x80);
137 if (isac->dch.debug & DEBUG_HW_DFIFO) {
138 char pfx[MISDN_MAX_IDLEN + 16];
139
140 snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
141 isac->name, count);
142 print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
143 }
144}
145
146static void
147isac_fill_fifo(struct isac_hw *isac)
148{
149 int count, more;
150 u8 *ptr;
151
152 if (!isac->dch.tx_skb)
153 return;
154 count = isac->dch.tx_skb->len - isac->dch.tx_idx;
155 if (count <= 0)
156 return;
157
158 more = 0;
159 if (count > 32) {
160 more = !0;
161 count = 32;
162 }
163 pr_debug("%s: %s %d\n", isac->name, __func__, count);
164 ptr = isac->dch.tx_skb->data + isac->dch.tx_idx;
165 isac->dch.tx_idx += count;
166 isac->write_fifo(isac->dch.hw, isac->off, ptr, count);
167 WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa);
168 if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
169 pr_debug("%s: %s dbusytimer running\n", isac->name, __func__);
170 del_timer(&isac->dch.timer);
171 }
172 init_timer(&isac->dch.timer);
173 isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
174 add_timer(&isac->dch.timer);
175 if (isac->dch.debug & DEBUG_HW_DFIFO) {
176 char pfx[MISDN_MAX_IDLEN + 16];
177
178 snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ",
179 isac->name, count);
180 print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
181 }
182}
183
184static void
185isac_rme_irq(struct isac_hw *isac)
186{
187 u8 val, count;
188
189 val = ReadISAC(isac, ISAC_RSTA);
190 if ((val & 0x70) != 0x20) {
191 if (val & 0x40) {
192 pr_debug("%s: ISAC RDO\n", isac->name);
193#ifdef ERROR_STATISTIC
194 isac->dch.err_rx++;
195#endif
196 }
197 if (!(val & 0x20)) {
198 pr_debug("%s: ISAC CRC error\n", isac->name);
199#ifdef ERROR_STATISTIC
200 isac->dch.err_crc++;
201#endif
202 }
203 WriteISAC(isac, ISAC_CMDR, 0x80);
204 if (isac->dch.rx_skb)
205 dev_kfree_skb(isac->dch.rx_skb);
206 isac->dch.rx_skb = NULL;
207 } else {
208 count = ReadISAC(isac, ISAC_RBCL) & 0x1f;
209 if (count == 0)
210 count = 32;
211 isac_empty_fifo(isac, count);
212 recv_Dchannel(&isac->dch);
213 }
214}
215
216static void
217isac_xpr_irq(struct isac_hw *isac)
218{
219 if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
220 del_timer(&isac->dch.timer);
221 if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) {
222 isac_fill_fifo(isac);
223 } else {
224 if (isac->dch.tx_skb)
225 dev_kfree_skb(isac->dch.tx_skb);
226 if (get_next_dframe(&isac->dch))
227 isac_fill_fifo(isac);
228 }
229}
230
231static void
232isac_retransmit(struct isac_hw *isac)
233{
234 if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
235 del_timer(&isac->dch.timer);
236 if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) {
237 /* Restart frame */
238 isac->dch.tx_idx = 0;
239 isac_fill_fifo(isac);
240 } else if (isac->dch.tx_skb) { /* should not happen */
241 pr_info("%s: tx_skb exist but not busy\n", isac->name);
242 test_and_set_bit(FLG_TX_BUSY, &isac->dch.Flags);
243 isac->dch.tx_idx = 0;
244 isac_fill_fifo(isac);
245 } else {
246 pr_info("%s: ISAC XDU no TX_BUSY\n", isac->name);
247 if (get_next_dframe(&isac->dch))
248 isac_fill_fifo(isac);
249 }
250}
251
252static void
253isac_mos_irq(struct isac_hw *isac)
254{
255 u8 val;
256 int ret;
257
258 val = ReadISAC(isac, ISAC_MOSR);
259 pr_debug("%s: ISAC MOSR %02x\n", isac->name, val);
260#if ARCOFI_USE
261 if (val & 0x08) {
262 if (!isac->mon_rx) {
263 isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
264 if (!isac->mon_rx) {
265 pr_info("%s: ISAC MON RX out of memory!\n",
266 isac->name);
267 isac->mocr &= 0xf0;
268 isac->mocr |= 0x0a;
269 WriteISAC(isac, ISAC_MOCR, isac->mocr);
270 goto afterMONR0;
271 } else
272 isac->mon_rxp = 0;
273 }
274 if (isac->mon_rxp >= MAX_MON_FRAME) {
275 isac->mocr &= 0xf0;
276 isac->mocr |= 0x0a;
277 WriteISAC(isac, ISAC_MOCR, isac->mocr);
278 isac->mon_rxp = 0;
279 pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
280 goto afterMONR0;
281 }
282 isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0);
283 pr_debug("%s: ISAC MOR0 %02x\n", isac->name,
284 isac->mon_rx[isac->mon_rxp - 1]);
285 if (isac->mon_rxp == 1) {
286 isac->mocr |= 0x04;
287 WriteISAC(isac, ISAC_MOCR, isac->mocr);
288 }
289 }
290afterMONR0:
291 if (val & 0x80) {
292 if (!isac->mon_rx) {
293 isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
294 if (!isac->mon_rx) {
295 pr_info("%s: ISAC MON RX out of memory!\n",
296 isac->name);
297 isac->mocr &= 0x0f;
298 isac->mocr |= 0xa0;
299 WriteISAC(isac, ISAC_MOCR, isac->mocr);
300 goto afterMONR1;
301 } else
302 isac->mon_rxp = 0;
303 }
304 if (isac->mon_rxp >= MAX_MON_FRAME) {
305 isac->mocr &= 0x0f;
306 isac->mocr |= 0xa0;
307 WriteISAC(isac, ISAC_MOCR, isac->mocr);
308 isac->mon_rxp = 0;
309 pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
310 goto afterMONR1;
311 }
312 isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1);
313 pr_debug("%s: ISAC MOR1 %02x\n", isac->name,
314 isac->mon_rx[isac->mon_rxp - 1]);
315 isac->mocr |= 0x40;
316 WriteISAC(isac, ISAC_MOCR, isac->mocr);
317 }
318afterMONR1:
319 if (val & 0x04) {
320 isac->mocr &= 0xf0;
321 WriteISAC(isac, ISAC_MOCR, isac->mocr);
322 isac->mocr |= 0x0a;
323 WriteISAC(isac, ISAC_MOCR, isac->mocr);
324 if (isac->monitor) {
325 ret = isac->monitor(isac->dch.hw, MONITOR_RX_0,
326 isac->mon_rx, isac->mon_rxp);
327 if (ret)
328 kfree(isac->mon_rx);
329 } else {
330 pr_info("%s: MONITOR 0 received %d but no user\n",
331 isac->name, isac->mon_rxp);
332 kfree(isac->mon_rx);
333 }
334 isac->mon_rx = NULL;
335 isac->mon_rxp = 0;
336 }
337 if (val & 0x40) {
338 isac->mocr &= 0x0f;
339 WriteISAC(isac, ISAC_MOCR, isac->mocr);
340 isac->mocr |= 0xa0;
341 WriteISAC(isac, ISAC_MOCR, isac->mocr);
342 if (isac->monitor) {
343 ret = isac->monitor(isac->dch.hw, MONITOR_RX_1,
344 isac->mon_rx, isac->mon_rxp);
345 if (ret)
346 kfree(isac->mon_rx);
347 } else {
348 pr_info("%s: MONITOR 1 received %d but no user\n",
349 isac->name, isac->mon_rxp);
350 kfree(isac->mon_rx);
351 }
352 isac->mon_rx = NULL;
353 isac->mon_rxp = 0;
354 }
355 if (val & 0x02) {
356 if ((!isac->mon_tx) || (isac->mon_txc &&
357 (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
358 isac->mocr &= 0xf0;
359 WriteISAC(isac, ISAC_MOCR, isac->mocr);
360 isac->mocr |= 0x0a;
361 WriteISAC(isac, ISAC_MOCR, isac->mocr);
362 if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
363 if (isac->monitor)
364 ret = isac->monitor(isac->dch.hw,
365 MONITOR_TX_0, NULL, 0);
366 }
367 kfree(isac->mon_tx);
368 isac->mon_tx = NULL;
369 isac->mon_txc = 0;
370 isac->mon_txp = 0;
371 goto AfterMOX0;
372 }
373 if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
374 if (isac->monitor)
375 ret = isac->monitor(isac->dch.hw,
376 MONITOR_TX_0, NULL, 0);
377 kfree(isac->mon_tx);
378 isac->mon_tx = NULL;
379 isac->mon_txc = 0;
380 isac->mon_txp = 0;
381 goto AfterMOX0;
382 }
383 WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]);
384 pr_debug("%s: ISAC %02x -> MOX0\n", isac->name,
385 isac->mon_tx[isac->mon_txp - 1]);
386 }
387AfterMOX0:
388 if (val & 0x20) {
389 if ((!isac->mon_tx) || (isac->mon_txc &&
390 (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
391 isac->mocr &= 0x0f;
392 WriteISAC(isac, ISAC_MOCR, isac->mocr);
393 isac->mocr |= 0xa0;
394 WriteISAC(isac, ISAC_MOCR, isac->mocr);
395 if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
396 if (isac->monitor)
397 ret = isac->monitor(isac->dch.hw,
398 MONITOR_TX_1, NULL, 0);
399 }
400 kfree(isac->mon_tx);
401 isac->mon_tx = NULL;
402 isac->mon_txc = 0;
403 isac->mon_txp = 0;
404 goto AfterMOX1;
405 }
406 if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
407 if (isac->monitor)
408 ret = isac->monitor(isac->dch.hw,
409 MONITOR_TX_1, NULL, 0);
410 kfree(isac->mon_tx);
411 isac->mon_tx = NULL;
412 isac->mon_txc = 0;
413 isac->mon_txp = 0;
414 goto AfterMOX1;
415 }
416 WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
417 pr_debug("%s: ISAC %02x -> MOX1\n", isac->name,
418 isac->mon_tx[isac->mon_txp - 1]);
419 }
420AfterMOX1:
421 val = 0; /* dummy to avoid warning */
422#endif
423}
424
425static void
426isac_cisq_irq(struct isac_hw *isac) {
427 u8 val;
428
429 val = ReadISAC(isac, ISAC_CIR0);
430 pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val);
431 if (val & 2) {
432 pr_debug("%s: ph_state change %x->%x\n", isac->name,
433 isac->state, (val >> 2) & 0xf);
434 isac->state = (val >> 2) & 0xf;
435 isac_ph_state_change(isac);
436 }
437 if (val & 1) {
438 val = ReadISAC(isac, ISAC_CIR1);
439 pr_debug("%s: ISAC CIR1 %02X\n", isac->name, val);
440 }
441}
442
443static void
444isacsx_cic_irq(struct isac_hw *isac)
445{
446 u8 val;
447
448 val = ReadISAC(isac, ISACX_CIR0);
449 pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
450 if (val & ISACX_CIR0_CIC0) {
451 pr_debug("%s: ph_state change %x->%x\n", isac->name,
452 isac->state, val >> 4);
453 isac->state = val >> 4;
454 isac_ph_state_change(isac);
455 }
456}
457
458static void
459isacsx_rme_irq(struct isac_hw *isac)
460{
461 int count;
462 u8 val;
463
464 val = ReadISAC(isac, ISACX_RSTAD);
465 if ((val & (ISACX_RSTAD_VFR |
466 ISACX_RSTAD_RDO |
467 ISACX_RSTAD_CRC |
468 ISACX_RSTAD_RAB))
469 != (ISACX_RSTAD_VFR | ISACX_RSTAD_CRC)) {
470 pr_debug("%s: RSTAD %#x, dropped\n", isac->name, val);
471#ifdef ERROR_STATISTIC
472 if (val & ISACX_RSTAD_CRC)
473 isac->dch.err_rx++;
474 else
475 isac->dch.err_crc++;
476#endif
477 WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
478 if (isac->dch.rx_skb)
479 dev_kfree_skb(isac->dch.rx_skb);
480 isac->dch.rx_skb = NULL;
481 } else {
482 count = ReadISAC(isac, ISACX_RBCLD) & 0x1f;
483 if (count == 0)
484 count = 32;
485 isac_empty_fifo(isac, count);
486 if (isac->dch.rx_skb) {
487 skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1);
488 pr_debug("%s: dchannel received %d\n", isac->name,
489 isac->dch.rx_skb->len);
490 recv_Dchannel(&isac->dch);
491 }
492 }
493}
494
495irqreturn_t
496mISDNisac_irq(struct isac_hw *isac, u8 val)
497{
498 if (unlikely(!val))
499 return IRQ_NONE;
500 pr_debug("%s: ISAC interrupt %02x\n", isac->name, val);
501 if (isac->type & IPAC_TYPE_ISACX) {
502 if (val & ISACX__CIC)
503 isacsx_cic_irq(isac);
504 if (val & ISACX__ICD) {
505 val = ReadISAC(isac, ISACX_ISTAD);
506 pr_debug("%s: ISTAD %02x\n", isac->name, val);
507 if (val & ISACX_D_XDU) {
508 pr_debug("%s: ISAC XDU\n", isac->name);
509#ifdef ERROR_STATISTIC
510 isac->dch.err_tx++;
511#endif
512 isac_retransmit(isac);
513 }
514 if (val & ISACX_D_XMR) {
515 pr_debug("%s: ISAC XMR\n", isac->name);
516#ifdef ERROR_STATISTIC
517 isac->dch.err_tx++;
518#endif
519 isac_retransmit(isac);
520 }
521 if (val & ISACX_D_XPR)
522 isac_xpr_irq(isac);
523 if (val & ISACX_D_RFO) {
524 pr_debug("%s: ISAC RFO\n", isac->name);
525 WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
526 }
527 if (val & ISACX_D_RME)
528 isacsx_rme_irq(isac);
529 if (val & ISACX_D_RPF)
530 isac_empty_fifo(isac, 0x20);
531 }
532 } else {
533 if (val & 0x80) /* RME */
534 isac_rme_irq(isac);
535 if (val & 0x40) /* RPF */
536 isac_empty_fifo(isac, 32);
537 if (val & 0x10) /* XPR */
538 isac_xpr_irq(isac);
539 if (val & 0x04) /* CISQ */
540 isac_cisq_irq(isac);
541 if (val & 0x20) /* RSC - never */
542 pr_debug("%s: ISAC RSC interrupt\n", isac->name);
543 if (val & 0x02) /* SIN - never */
544 pr_debug("%s: ISAC SIN interrupt\n", isac->name);
545 if (val & 0x01) { /* EXI */
546 val = ReadISAC(isac, ISAC_EXIR);
547 pr_debug("%s: ISAC EXIR %02x\n", isac->name, val);
548 if (val & 0x80) /* XMR */
549 pr_debug("%s: ISAC XMR\n", isac->name);
550 if (val & 0x40) { /* XDU */
551 pr_debug("%s: ISAC XDU\n", isac->name);
552#ifdef ERROR_STATISTIC
553 isac->dch.err_tx++;
554#endif
555 isac_retransmit(isac);
556 }
557 if (val & 0x04) /* MOS */
558 isac_mos_irq(isac);
559 }
560 }
561 return IRQ_HANDLED;
562}
563EXPORT_SYMBOL(mISDNisac_irq);
564
565static int
566isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
567{
568 struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
569 struct dchannel *dch = container_of(dev, struct dchannel, dev);
570 struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
571 int ret = -EINVAL;
572 struct mISDNhead *hh = mISDN_HEAD_P(skb);
573 u32 id;
574 u_long flags;
575
576 switch (hh->prim) {
577 case PH_DATA_REQ:
578 spin_lock_irqsave(isac->hwlock, flags);
579 ret = dchannel_senddata(dch, skb);
580 if (ret > 0) { /* direct TX */
581 id = hh->id; /* skb can be freed */
582 isac_fill_fifo(isac);
583 ret = 0;
584 spin_unlock_irqrestore(isac->hwlock, flags);
585 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
586 } else
587 spin_unlock_irqrestore(isac->hwlock, flags);
588 return ret;
589 case PH_ACTIVATE_REQ:
590 ret = l1_event(dch->l1, hh->prim);
591 break;
592 case PH_DEACTIVATE_REQ:
593 test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
594 ret = l1_event(dch->l1, hh->prim);
595 break;
596 }
597
598 if (!ret)
599 dev_kfree_skb(skb);
600 return ret;
601}
602
603static int
604isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
605{
606 u8 tl = 0;
607 u_long flags;
608
609 switch (cmd) {
610 case HW_TESTLOOP:
611 spin_lock_irqsave(isac->hwlock, flags);
612 if (!(isac->type & IPAC_TYPE_ISACX)) {
613 /* TODO: implement for IPAC_TYPE_ISACX */
614 if (para & 1) /* B1 */
615 tl |= 0x0c;
616 else if (para & 2) /* B2 */
617 tl |= 0x3;
618 /* we only support IOM2 mode */
619 WriteISAC(isac, ISAC_SPCR, tl);
620 if (tl)
621 WriteISAC(isac, ISAC_ADF1, 0x8);
622 else
623 WriteISAC(isac, ISAC_ADF1, 0x0);
624 }
625 spin_unlock_irqrestore(isac->hwlock, flags);
626 break;
627 default:
628 pr_debug("%s: %s unknown command %x %lx\n", isac->name,
629 __func__, cmd, para);
630 return -1;
631 }
632 return 0;
633}
634
635static int
636isac_l1cmd(struct dchannel *dch, u32 cmd)
637{
638 struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
639 u_long flags;
640
641 pr_debug("%s: cmd(%x) state(%02x)\n", isac->name, cmd, isac->state);
642 switch (cmd) {
643 case INFO3_P8:
644 spin_lock_irqsave(isac->hwlock, flags);
645 ph_command(isac, ISAC_CMD_AR8);
646 spin_unlock_irqrestore(isac->hwlock, flags);
647 break;
648 case INFO3_P10:
649 spin_lock_irqsave(isac->hwlock, flags);
650 ph_command(isac, ISAC_CMD_AR10);
651 spin_unlock_irqrestore(isac->hwlock, flags);
652 break;
653 case HW_RESET_REQ:
654 spin_lock_irqsave(isac->hwlock, flags);
655 if ((isac->state == ISAC_IND_EI) ||
656 (isac->state == ISAC_IND_DR) ||
657 (isac->state == ISAC_IND_RS))
658 ph_command(isac, ISAC_CMD_TIM);
659 else
660 ph_command(isac, ISAC_CMD_RS);
661 spin_unlock_irqrestore(isac->hwlock, flags);
662 break;
663 case HW_DEACT_REQ:
664 skb_queue_purge(&dch->squeue);
665 if (dch->tx_skb) {
666 dev_kfree_skb(dch->tx_skb);
667 dch->tx_skb = NULL;
668 }
669 dch->tx_idx = 0;
670 if (dch->rx_skb) {
671 dev_kfree_skb(dch->rx_skb);
672 dch->rx_skb = NULL;
673 }
674 test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
675 if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
676 del_timer(&dch->timer);
677 break;
678 case HW_POWERUP_REQ:
679 spin_lock_irqsave(isac->hwlock, flags);
680 ph_command(isac, ISAC_CMD_TIM);
681 spin_unlock_irqrestore(isac->hwlock, flags);
682 break;
683 case PH_ACTIVATE_IND:
684 test_and_set_bit(FLG_ACTIVE, &dch->Flags);
685 _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
686 GFP_ATOMIC);
687 break;
688 case PH_DEACTIVATE_IND:
689 test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
690 _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
691 GFP_ATOMIC);
692 break;
693 default:
694 pr_debug("%s: %s unknown command %x\n", isac->name,
695 __func__, cmd);
696 return -1;
697 }
698 return 0;
699}
700
701static void
702isac_release(struct isac_hw *isac)
703{
704 if (isac->type & IPAC_TYPE_ISACX)
705 WriteISAC(isac, ISACX_MASK, 0xff);
706 else
707 WriteISAC(isac, ISAC_MASK, 0xff);
708 if (isac->dch.timer.function != NULL) {
709 del_timer(&isac->dch.timer);
710 isac->dch.timer.function = NULL;
711 }
712 kfree(isac->mon_rx);
713 isac->mon_rx = NULL;
714 kfree(isac->mon_tx);
715 isac->mon_tx = NULL;
716 if (isac->dch.l1)
717 l1_event(isac->dch.l1, CLOSE_CHANNEL);
718 mISDN_freedchannel(&isac->dch);
719}
720
721static void
722dbusy_timer_handler(struct isac_hw *isac)
723{
724 int rbch, star;
725 u_long flags;
726
727 if (test_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
728 spin_lock_irqsave(isac->hwlock, flags);
729 rbch = ReadISAC(isac, ISAC_RBCH);
730 star = ReadISAC(isac, ISAC_STAR);
731 pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
732 isac->name, rbch, star);
733 if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */
734 test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags);
735 else {
736 /* discard frame; reset transceiver */
737 test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags);
738 if (isac->dch.tx_idx)
739 isac->dch.tx_idx = 0;
740 else
741 pr_info("%s: ISAC D-Channel Busy no tx_idx\n",
742 isac->name);
743 /* Transmitter reset */
744 WriteISAC(isac, ISAC_CMDR, 0x01);
745 }
746 spin_unlock_irqrestore(isac->hwlock, flags);
747 }
748}
749
750static int
751open_dchannel(struct isac_hw *isac, struct channel_req *rq)
752{
753 pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__,
754 isac->dch.dev.id, __builtin_return_address(1));
755 if (rq->protocol != ISDN_P_TE_S0)
756 return -EINVAL;
757 if (rq->adr.channel == 1)
758 /* E-Channel not supported */
759 return -EINVAL;
760 rq->ch = &isac->dch.dev.D;
761 rq->ch->protocol = rq->protocol;
762 if (isac->dch.state == 7)
763 _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
764 0, NULL, GFP_KERNEL);
765 return 0;
766}
767
768static const char *ISACVer[] =
769{"2086/2186 V1.1", "2085 B1", "2085 B2",
770 "2085 V2.3"};
771
772static int
773isac_init(struct isac_hw *isac)
774{
775 u8 val;
776 int err = 0;
777
778 if (!isac->dch.l1) {
779 err = create_l1(&isac->dch, isac_l1cmd);
780 if (err)
781 return err;
782 }
783 isac->mon_tx = NULL;
784 isac->mon_rx = NULL;
785 isac->dch.timer.function = (void *) dbusy_timer_handler;
786 isac->dch.timer.data = (long)isac;
787 init_timer(&isac->dch.timer);
788 isac->mocr = 0xaa;
789 if (isac->type & IPAC_TYPE_ISACX) {
790 /* Disable all IRQ */
791 WriteISAC(isac, ISACX_MASK, 0xff);
792 val = ReadISAC(isac, ISACX_STARD);
793 pr_debug("%s: ISACX STARD %x\n", isac->name, val);
794 val = ReadISAC(isac, ISACX_ISTAD);
795 pr_debug("%s: ISACX ISTAD %x\n", isac->name, val);
796 val = ReadISAC(isac, ISACX_ISTA);
797 pr_debug("%s: ISACX ISTA %x\n", isac->name, val);
798 /* clear LDD */
799 WriteISAC(isac, ISACX_TR_CONF0, 0x00);
800 /* enable transmitter */
801 WriteISAC(isac, ISACX_TR_CONF2, 0x00);
802 /* transparent mode 0, RAC, stop/go */
803 WriteISAC(isac, ISACX_MODED, 0xc9);
804 /* all HDLC IRQ unmasked */
805 val = ReadISAC(isac, ISACX_ID);
806 if (isac->dch.debug & DEBUG_HW)
807 pr_notice("%s: ISACX Design ID %x\n",
808 isac->name, val & 0x3f);
809 val = ReadISAC(isac, ISACX_CIR0);
810 pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
811 isac->state = val >> 4;
812 isac_ph_state_change(isac);
813 ph_command(isac, ISAC_CMD_RS);
814 WriteISAC(isac, ISACX_MASK, IPACX__ON);
815 WriteISAC(isac, ISACX_MASKD, 0x00);
816 } else { /* old isac */
817 WriteISAC(isac, ISAC_MASK, 0xff);
818 val = ReadISAC(isac, ISAC_STAR);
819 pr_debug("%s: ISAC STAR %x\n", isac->name, val);
820 val = ReadISAC(isac, ISAC_MODE);
821 pr_debug("%s: ISAC MODE %x\n", isac->name, val);
822 val = ReadISAC(isac, ISAC_ADF2);
823 pr_debug("%s: ISAC ADF2 %x\n", isac->name, val);
824 val = ReadISAC(isac, ISAC_ISTA);
825 pr_debug("%s: ISAC ISTA %x\n", isac->name, val);
826 if (val & 0x01) {
827 val = ReadISAC(isac, ISAC_EXIR);
828 pr_debug("%s: ISAC EXIR %x\n", isac->name, val);
829 }
830 val = ReadISAC(isac, ISAC_RBCH);
831 if (isac->dch.debug & DEBUG_HW)
832 pr_notice("%s: ISAC version (%x): %s\n", isac->name,
833 val, ISACVer[(val >> 5) & 3]);
834 isac->type |= ((val >> 5) & 3);
835 if (!isac->adf2)
836 isac->adf2 = 0x80;
837 if (!(isac->adf2 & 0x80)) { /* only IOM 2 Mode */
838 pr_info("%s: only support IOM2 mode but adf2=%02x\n",
839 isac->name, isac->adf2);
840 isac_release(isac);
841 return -EINVAL;
842 }
843 WriteISAC(isac, ISAC_ADF2, isac->adf2);
844 WriteISAC(isac, ISAC_SQXR, 0x2f);
845 WriteISAC(isac, ISAC_SPCR, 0x00);
846 WriteISAC(isac, ISAC_STCR, 0x70);
847 WriteISAC(isac, ISAC_MODE, 0xc9);
848 WriteISAC(isac, ISAC_TIMR, 0x00);
849 WriteISAC(isac, ISAC_ADF1, 0x00);
850 val = ReadISAC(isac, ISAC_CIR0);
851 pr_debug("%s: ISAC CIR0 %x\n", isac->name, val);
852 isac->state = (val >> 2) & 0xf;
853 isac_ph_state_change(isac);
854 ph_command(isac, ISAC_CMD_RS);
855 WriteISAC(isac, ISAC_MASK, 0);
856 }
857 return err;
858}
859
860int
861mISDNisac_init(struct isac_hw *isac, void *hw)
862{
863 mISDN_initdchannel(&isac->dch, MAX_DFRAME_LEN_L1, isac_ph_state_bh);
864 isac->dch.hw = hw;
865 isac->dch.dev.D.send = isac_l1hw;
866 isac->init = isac_init;
867 isac->release = isac_release;
868 isac->ctrl = isac_ctrl;
869 isac->open = open_dchannel;
870 isac->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);
871 isac->dch.dev.nrbchan = 2;
872 return 0;
873}
874EXPORT_SYMBOL(mISDNisac_init);
875
876static void
877waitforCEC(struct hscx_hw *hx)
878{
879 u8 starb, to = 50;
880
881 while (to) {
882 starb = ReadHSCX(hx, IPAC_STARB);
883 if (!(starb & 0x04))
884 break;
885 udelay(1);
886 to--;
887 }
888 if (to < 50)
889 pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr,
890 50 - to);
891 if (!to)
892 pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr);
893}
894
895
896static void
897waitforXFW(struct hscx_hw *hx)
898{
899 u8 starb, to = 50;
900
901 while (to) {
902 starb = ReadHSCX(hx, IPAC_STARB);
903 if ((starb & 0x44) == 0x40)
904 break;
905 udelay(1);
906 to--;
907 }
908 if (to < 50)
909 pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr,
910 50 - to);
911 if (!to)
912 pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr);
913}
914
915static void
916hscx_cmdr(struct hscx_hw *hx, u8 cmd)
917{
918 if (hx->ip->type & IPAC_TYPE_IPACX)
919 WriteHSCX(hx, IPACX_CMDRB, cmd);
920 else {
921 waitforCEC(hx);
922 WriteHSCX(hx, IPAC_CMDRB, cmd);
923 }
924}
925
926static void
927hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
928{
929 u8 *p;
930
931 pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
932 if (!hscx->bch.rx_skb) {
933 hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC);
934 if (!hscx->bch.rx_skb) {
935 pr_info("%s: B receive out of memory\n",
936 hscx->ip->name);
937 hscx_cmdr(hscx, 0x80); /* RMC */
938 return;
939 }
940 }
941 if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) {
942 pr_debug("%s: overrun %d\n", hscx->ip->name,
943 hscx->bch.rx_skb->len + count);
944 skb_trim(hscx->bch.rx_skb, 0);
945 hscx_cmdr(hscx, 0x80); /* RMC */
946 return;
947 }
948 p = skb_put(hscx->bch.rx_skb, count);
949
950 if (hscx->ip->type & IPAC_TYPE_IPACX)
951 hscx->ip->read_fifo(hscx->ip->hw,
952 hscx->off + IPACX_RFIFOB, p, count);
953 else
954 hscx->ip->read_fifo(hscx->ip->hw,
955 hscx->off, p, count);
956
957 hscx_cmdr(hscx, 0x80); /* RMC */
958
959 if (hscx->bch.debug & DEBUG_HW_BFIFO) {
960 snprintf(hscx->log, 64, "B%1d-recv %s %d ",
961 hscx->bch.nr, hscx->ip->name, count);
962 print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
963 }
964}
965
966static void
967hscx_fill_fifo(struct hscx_hw *hscx)
968{
969 int count, more;
970 u8 *p;
971
972 if (!hscx->bch.tx_skb)
973 return;
974 count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
975 if (count <= 0)
976 return;
977 p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
978
979 more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
980 if (count > hscx->fifo_size) {
981 count = hscx->fifo_size;
982 more = 1;
983 }
984 pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count,
985 hscx->bch.tx_idx, hscx->bch.tx_skb->len);
986 hscx->bch.tx_idx += count;
987
988 if (hscx->ip->type & IPAC_TYPE_IPACX)
989 hscx->ip->write_fifo(hscx->ip->hw,
990 hscx->off + IPACX_XFIFOB, p, count);
991 else {
992 waitforXFW(hscx);
993 hscx->ip->write_fifo(hscx->ip->hw,
994 hscx->off, p, count);
995 }
996 hscx_cmdr(hscx, more ? 0x08 : 0x0a);
997
998 if (hscx->bch.debug & DEBUG_HW_BFIFO) {
999 snprintf(hscx->log, 64, "B%1d-send %s %d ",
1000 hscx->bch.nr, hscx->ip->name, count);
1001 print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
1002 }
1003}
1004
1005static void
1006hscx_xpr(struct hscx_hw *hx)
1007{
1008 if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len)
1009 hscx_fill_fifo(hx);
1010 else {
1011 if (hx->bch.tx_skb) {
1012 /* send confirm, on trans, free on hdlc. */
1013 if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
1014 confirm_Bsend(&hx->bch);
1015 dev_kfree_skb(hx->bch.tx_skb);
1016 }
1017 if (get_next_bframe(&hx->bch))
1018 hscx_fill_fifo(hx);
1019 }
1020}
1021
1022static void
1023ipac_rme(struct hscx_hw *hx)
1024{
1025 int count;
1026 u8 rstab;
1027
1028 if (hx->ip->type & IPAC_TYPE_IPACX)
1029 rstab = ReadHSCX(hx, IPACX_RSTAB);
1030 else
1031 rstab = ReadHSCX(hx, IPAC_RSTAB);
1032 pr_debug("%s: B%1d RSTAB %02x\n", hx->ip->name, hx->bch.nr, rstab);
1033 if ((rstab & 0xf0) != 0xa0) {
1034 /* !(VFR && !RDO && CRC && !RAB) */
1035 if (!(rstab & 0x80)) {
1036 if (hx->bch.debug & DEBUG_HW_BCHANNEL)
1037 pr_notice("%s: B%1d invalid frame\n",
1038 hx->ip->name, hx->bch.nr);
1039 }
1040 if (rstab & 0x40) {
1041 if (hx->bch.debug & DEBUG_HW_BCHANNEL)
1042 pr_notice("%s: B%1d RDO proto=%x\n",
1043 hx->ip->name, hx->bch.nr,
1044 hx->bch.state);
1045 }
1046 if (!(rstab & 0x20)) {
1047 if (hx->bch.debug & DEBUG_HW_BCHANNEL)
1048 pr_notice("%s: B%1d CRC error\n",
1049 hx->ip->name, hx->bch.nr);
1050 }
1051 hscx_cmdr(hx, 0x80); /* Do RMC */
1052 return;
1053 }
1054 if (hx->ip->type & IPAC_TYPE_IPACX)
1055 count = ReadHSCX(hx, IPACX_RBCLB);
1056 else
1057 count = ReadHSCX(hx, IPAC_RBCLB);
1058 count &= (hx->fifo_size - 1);
1059 if (count == 0)
1060 count = hx->fifo_size;
1061 hscx_empty_fifo(hx, count);
1062 if (!hx->bch.rx_skb)
1063 return;
1064 if (hx->bch.rx_skb->len < 2) {
1065 pr_debug("%s: B%1d frame to short %d\n",
1066 hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
1067 skb_trim(hx->bch.rx_skb, 0);
1068 } else {
1069 skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
1070 recv_Bchannel(&hx->bch, 0);
1071 }
1072}
1073
1074static void
1075ipac_irq(struct hscx_hw *hx, u8 ista)
1076{
1077 u8 istab, m, exirb = 0;
1078
1079 if (hx->ip->type & IPAC_TYPE_IPACX)
1080 istab = ReadHSCX(hx, IPACX_ISTAB);
1081 else if (hx->ip->type & IPAC_TYPE_IPAC) {
1082 istab = ReadHSCX(hx, IPAC_ISTAB);
1083 m = (hx->bch.nr & 1) ? IPAC__EXA : IPAC__EXB;
1084 if (m & ista) {
1085 exirb = ReadHSCX(hx, IPAC_EXIRB);
1086 pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
1087 hx->bch.nr, exirb);
1088 }
1089 } else if (hx->bch.nr & 2) { /* HSCX B */
1090 if (ista & (HSCX__EXA | HSCX__ICA))
1091 ipac_irq(&hx->ip->hscx[0], ista);
1092 if (ista & HSCX__EXB) {
1093 exirb = ReadHSCX(hx, IPAC_EXIRB);
1094 pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
1095 hx->bch.nr, exirb);
1096 }
1097 istab = ista & 0xF8;
1098 } else { /* HSCX A */
1099 istab = ReadHSCX(hx, IPAC_ISTAB);
1100 if (ista & HSCX__EXA) {
1101 exirb = ReadHSCX(hx, IPAC_EXIRB);
1102 pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
1103 hx->bch.nr, exirb);
1104 }
1105 istab = istab & 0xF8;
1106 }
1107 if (exirb & IPAC_B_XDU)
1108 istab |= IPACX_B_XDU;
1109 if (exirb & IPAC_B_RFO)
1110 istab |= IPACX_B_RFO;
1111 pr_debug("%s: B%1d ISTAB %02x\n", hx->ip->name, hx->bch.nr, istab);
1112
1113 if (!test_bit(FLG_ACTIVE, &hx->bch.Flags))
1114 return;
1115
1116 if (istab & IPACX_B_RME)
1117 ipac_rme(hx);
1118
1119 if (istab & IPACX_B_RPF) {
1120 hscx_empty_fifo(hx, hx->fifo_size);
1121 if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
1122 /* receive transparent audio data */
1123 if (hx->bch.rx_skb)
1124 recv_Bchannel(&hx->bch, 0);
1125 }
1126 }
1127
1128 if (istab & IPACX_B_RFO) {
1129 pr_debug("%s: B%1d RFO error\n", hx->ip->name, hx->bch.nr);
1130 hscx_cmdr(hx, 0x40); /* RRES */
1131 }
1132
1133 if (istab & IPACX_B_XPR)
1134 hscx_xpr(hx);
1135
1136 if (istab & IPACX_B_XDU) {
1137 if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
1138 hscx_fill_fifo(hx);
1139 return;
1140 }
1141 pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
1142 hx->bch.nr, hx->bch.tx_idx);
1143 hx->bch.tx_idx = 0;
1144 hscx_cmdr(hx, 0x01); /* XRES */
1145 }
1146}
1147
1148irqreturn_t
1149mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
1150{
1151 int cnt = maxloop + 1;
1152 u8 ista, istad;
1153 struct isac_hw *isac = &ipac->isac;
1154
1155 if (ipac->type & IPAC_TYPE_IPACX) {
1156 ista = ReadIPAC(ipac, ISACX_ISTA);
1157 while (ista && cnt--) {
1158 pr_debug("%s: ISTA %02x\n", ipac->name, ista);
1159 if (ista & IPACX__ICA)
1160 ipac_irq(&ipac->hscx[0], ista);
1161 if (ista & IPACX__ICB)
1162 ipac_irq(&ipac->hscx[1], ista);
1163 if (ista & (ISACX__ICD | ISACX__CIC))
1164 mISDNisac_irq(&ipac->isac, ista);
1165 ista = ReadIPAC(ipac, ISACX_ISTA);
1166 }
1167 } else if (ipac->type & IPAC_TYPE_IPAC) {
1168 ista = ReadIPAC(ipac, IPAC_ISTA);
1169 while (ista && cnt--) {
1170 pr_debug("%s: ISTA %02x\n", ipac->name, ista);
1171 if (ista & (IPAC__ICD | IPAC__EXD)) {
1172 istad = ReadISAC(isac, ISAC_ISTA);
1173 pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
1174 if (istad & IPAC_D_TIN2)
1175 pr_debug("%s TIN2 irq\n", ipac->name);
1176 if (ista & IPAC__EXD)
1177 istad |= 1; /* ISAC EXI */
1178 mISDNisac_irq(isac, istad);
1179 }
1180 if (ista & (IPAC__ICA | IPAC__EXA))
1181 ipac_irq(&ipac->hscx[0], ista);
1182 if (ista & (IPAC__ICB | IPAC__EXB))
1183 ipac_irq(&ipac->hscx[1], ista);
1184 ista = ReadIPAC(ipac, IPAC_ISTA);
1185 }
1186 } else if (ipac->type & IPAC_TYPE_HSCX) {
1187 while (cnt) {
1188 ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
1189 pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
1190 if (ista)
1191 ipac_irq(&ipac->hscx[1], ista);
1192 istad = ReadISAC(isac, ISAC_ISTA);
1193 pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
1194 if (istad)
1195 mISDNisac_irq(isac, istad);
1196 if (0 == (ista | istad))
1197 break;
1198 cnt--;
1199 }
1200 }
1201 if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
1202 return IRQ_NONE;
1203 if (cnt < maxloop)
1204 pr_debug("%s: %d irqloops cpu%d\n", ipac->name,
1205 maxloop - cnt, smp_processor_id());
1206 if (maxloop && !cnt)
1207 pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name,
1208 maxloop, smp_processor_id());
1209 return IRQ_HANDLED;
1210}
1211EXPORT_SYMBOL(mISDNipac_irq);
1212
1213static int
1214hscx_mode(struct hscx_hw *hscx, u32 bprotocol)
1215{
1216 pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name,
1217 '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
1218 if (hscx->ip->type & IPAC_TYPE_IPACX) {
1219 if (hscx->bch.nr & 1) { /* B1 and ICA */
1220 WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80);
1221 WriteIPAC(hscx->ip, ISACX_BCHA_CR, 0x88);
1222 } else { /* B2 and ICB */
1223 WriteIPAC(hscx->ip, ISACX_BCHB_TSDP_BC1, 0x81);
1224 WriteIPAC(hscx->ip, ISACX_BCHB_CR, 0x88);
1225 }
1226 switch (bprotocol) {
1227 case ISDN_P_NONE: /* init */
1228 WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* rec off */
1229 WriteHSCX(hscx, IPACX_EXMB, 0x30); /* std adj. */
1230 WriteHSCX(hscx, IPACX_MASKB, 0xFF); /* ints off */
1231 hscx_cmdr(hscx, 0x41);
1232 test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
1233 test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1234 break;
1235 case ISDN_P_B_RAW:
1236 WriteHSCX(hscx, IPACX_MODEB, 0x88); /* ex trans */
1237 WriteHSCX(hscx, IPACX_EXMB, 0x00); /* trans */
1238 hscx_cmdr(hscx, 0x41);
1239 WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
1240 test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1241 break;
1242 case ISDN_P_B_HDLC:
1243 WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* trans */
1244 WriteHSCX(hscx, IPACX_EXMB, 0x00); /* hdlc,crc */
1245 hscx_cmdr(hscx, 0x41);
1246 WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
1247 test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
1248 break;
1249 default:
1250 pr_info("%s: protocol not known %x\n", hscx->ip->name,
1251 bprotocol);
1252 return -ENOPROTOOPT;
1253 }
1254 } else if (hscx->ip->type & IPAC_TYPE_IPAC) { /* IPAC */
1255 WriteHSCX(hscx, IPAC_CCR1, 0x82);
1256 WriteHSCX(hscx, IPAC_CCR2, 0x30);
1257 WriteHSCX(hscx, IPAC_XCCR, 0x07);
1258 WriteHSCX(hscx, IPAC_RCCR, 0x07);
1259 WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
1260 WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
1261 switch (bprotocol) {
1262 case ISDN_P_NONE:
1263 WriteHSCX(hscx, IPAC_TSAX, 0x1F);
1264 WriteHSCX(hscx, IPAC_TSAR, 0x1F);
1265 WriteHSCX(hscx, IPAC_MODEB, 0x84);
1266 WriteHSCX(hscx, IPAC_CCR1, 0x82);
1267 WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
1268 test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
1269 test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1270 break;
1271 case ISDN_P_B_RAW:
1272 WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
1273 WriteHSCX(hscx, IPAC_CCR1, 0x82);
1274 hscx_cmdr(hscx, 0x41);
1275 WriteHSCX(hscx, IPAC_MASKB, 0);
1276 test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1277 break;
1278 case ISDN_P_B_HDLC:
1279 WriteHSCX(hscx, IPAC_MODEB, 0x8c);
1280 WriteHSCX(hscx, IPAC_CCR1, 0x8a);
1281 hscx_cmdr(hscx, 0x41);
1282 WriteHSCX(hscx, IPAC_MASKB, 0);
1283 test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
1284 break;
1285 default:
1286 pr_info("%s: protocol not known %x\n", hscx->ip->name,
1287 bprotocol);
1288 return -ENOPROTOOPT;
1289 }
1290 } else if (hscx->ip->type & IPAC_TYPE_HSCX) { /* HSCX */
1291 WriteHSCX(hscx, IPAC_CCR1, 0x85);
1292 WriteHSCX(hscx, IPAC_CCR2, 0x30);
1293 WriteHSCX(hscx, IPAC_XCCR, 0x07);
1294 WriteHSCX(hscx, IPAC_RCCR, 0x07);
1295 WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
1296 WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
1297 switch (bprotocol) {
1298 case ISDN_P_NONE:
1299 WriteHSCX(hscx, IPAC_TSAX, 0x1F);
1300 WriteHSCX(hscx, IPAC_TSAR, 0x1F);
1301 WriteHSCX(hscx, IPAC_MODEB, 0x84);
1302 WriteHSCX(hscx, IPAC_CCR1, 0x85);
1303 WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
1304 test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
1305 test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1306 break;
1307 case ISDN_P_B_RAW:
1308 WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
1309 WriteHSCX(hscx, IPAC_CCR1, 0x85);
1310 hscx_cmdr(hscx, 0x41);
1311 WriteHSCX(hscx, IPAC_MASKB, 0);
1312 test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
1313 break;
1314 case ISDN_P_B_HDLC:
1315 WriteHSCX(hscx, IPAC_MODEB, 0x8c);
1316 WriteHSCX(hscx, IPAC_CCR1, 0x8d);
1317 hscx_cmdr(hscx, 0x41);
1318 WriteHSCX(hscx, IPAC_MASKB, 0);
1319 test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
1320 break;
1321 default:
1322 pr_info("%s: protocol not known %x\n", hscx->ip->name,
1323 bprotocol);
1324 return -ENOPROTOOPT;
1325 }
1326 } else
1327 return -EINVAL;
1328 hscx->bch.state = bprotocol;
1329 return 0;
1330}
1331
1332static int
1333hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1334{
1335 struct bchannel *bch = container_of(ch, struct bchannel, ch);
1336 struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
1337 int ret = -EINVAL;
1338 struct mISDNhead *hh = mISDN_HEAD_P(skb);
1339 u32 id;
1340 u_long flags;
1341
1342 switch (hh->prim) {
1343 case PH_DATA_REQ:
1344 spin_lock_irqsave(hx->ip->hwlock, flags);
1345 ret = bchannel_senddata(bch, skb);
1346 if (ret > 0) { /* direct TX */
1347 id = hh->id; /* skb can be freed */
1348 ret = 0;
1349 hscx_fill_fifo(hx);
1350 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1351 if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
1352 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
1353 } else
1354 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1355 return ret;
1356 case PH_ACTIVATE_REQ:
1357 spin_lock_irqsave(hx->ip->hwlock, flags);
1358 if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
1359 ret = hscx_mode(hx, ch->protocol);
1360 else
1361 ret = 0;
1362 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1363 if (!ret)
1364 _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
1365 NULL, GFP_KERNEL);
1366 break;
1367 case PH_DEACTIVATE_REQ:
1368 spin_lock_irqsave(hx->ip->hwlock, flags);
1369 mISDN_clear_bchannel(bch);
1370 hscx_mode(hx, ISDN_P_NONE);
1371 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1372 _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
1373 NULL, GFP_KERNEL);
1374 ret = 0;
1375 break;
1376 default:
1377 pr_info("%s: %s unknown prim(%x,%x)\n",
1378 hx->ip->name, __func__, hh->prim, hh->id);
1379 ret = -EINVAL;
1380 }
1381 if (!ret)
1382 dev_kfree_skb(skb);
1383 return ret;
1384}
1385
1386static int
1387channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
1388{
1389 int ret = 0;
1390
1391 switch (cq->op) {
1392 case MISDN_CTRL_GETOP:
1393 cq->op = 0;
1394 break;
1395 /* Nothing implemented yet */
1396 case MISDN_CTRL_FILL_EMPTY:
1397 default:
1398 pr_info("%s: unknown Op %x\n", __func__, cq->op);
1399 ret = -EINVAL;
1400 break;
1401 }
1402 return ret;
1403}
1404
1405static int
1406hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
1407{
1408 struct bchannel *bch = container_of(ch, struct bchannel, ch);
1409 struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
1410 int ret = -EINVAL;
1411 u_long flags;
1412
1413 pr_debug("%s: %s cmd:%x %p\n", hx->ip->name, __func__, cmd, arg);
1414 switch (cmd) {
1415 case CLOSE_CHANNEL:
1416 test_and_clear_bit(FLG_OPEN, &bch->Flags);
1417 if (test_bit(FLG_ACTIVE, &bch->Flags)) {
1418 spin_lock_irqsave(hx->ip->hwlock, flags);
1419 mISDN_freebchannel(bch);
1420 hscx_mode(hx, ISDN_P_NONE);
1421 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1422 } else {
1423 skb_queue_purge(&bch->rqueue);
1424 bch->rcount = 0;
1425 }
1426 ch->protocol = ISDN_P_NONE;
1427 ch->peer = NULL;
1428 module_put(hx->ip->owner);
1429 ret = 0;
1430 break;
1431 case CONTROL_CHANNEL:
1432 ret = channel_bctrl(bch, arg);
1433 break;
1434 default:
1435 pr_info("%s: %s unknown prim(%x)\n",
1436 hx->ip->name, __func__, cmd);
1437 }
1438 return ret;
1439}
1440
1441static void
1442free_ipac(struct ipac_hw *ipac)
1443{
1444 isac_release(&ipac->isac);
1445}
1446
1447static const char *HSCXVer[] =
1448{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
1449 "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
1450
1451
1452
1453static void
1454hscx_init(struct hscx_hw *hx)
1455{
1456 u8 val;
1457
1458 WriteHSCX(hx, IPAC_RAH2, 0xFF);
1459 WriteHSCX(hx, IPAC_XBCH, 0x00);
1460 WriteHSCX(hx, IPAC_RLCR, 0x00);
1461
1462 if (hx->ip->type & IPAC_TYPE_HSCX) {
1463 WriteHSCX(hx, IPAC_CCR1, 0x85);
1464 val = ReadHSCX(hx, HSCX_VSTR);
1465 pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val);
1466 if (hx->bch.debug & DEBUG_HW)
1467 pr_notice("%s: HSCX version %s\n", hx->ip->name,
1468 HSCXVer[val & 0x0f]);
1469 } else
1470 WriteHSCX(hx, IPAC_CCR1, 0x82);
1471 WriteHSCX(hx, IPAC_CCR2, 0x30);
1472 WriteHSCX(hx, IPAC_XCCR, 0x07);
1473 WriteHSCX(hx, IPAC_RCCR, 0x07);
1474}
1475
1476static int
1477ipac_init(struct ipac_hw *ipac)
1478{
1479 u8 val;
1480
1481 if (ipac->type & IPAC_TYPE_HSCX) {
1482 hscx_init(&ipac->hscx[0]);
1483 hscx_init(&ipac->hscx[1]);
1484 val = ReadIPAC(ipac, IPAC_ID);
1485 } else if (ipac->type & IPAC_TYPE_IPAC) {
1486 hscx_init(&ipac->hscx[0]);
1487 hscx_init(&ipac->hscx[1]);
1488 WriteIPAC(ipac, IPAC_MASK, IPAC__ON);
1489 val = ReadIPAC(ipac, IPAC_CONF);
1490 /* conf is default 0, but can be overwritten by card setup */
1491 pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name,
1492 val, ipac->conf);
1493 WriteIPAC(ipac, IPAC_CONF, ipac->conf);
1494 val = ReadIPAC(ipac, IPAC_ID);
1495 if (ipac->hscx[0].bch.debug & DEBUG_HW)
1496 pr_notice("%s: IPAC Design ID %02x\n", ipac->name, val);
1497 }
1498 /* nothing special for IPACX to do here */
1499 return isac_init(&ipac->isac);
1500}
1501
1502static int
1503open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
1504{
1505 struct bchannel *bch;
1506
1507 if (rq->adr.channel > 2)
1508 return -EINVAL;
1509 if (rq->protocol == ISDN_P_NONE)
1510 return -EINVAL;
1511 bch = &ipac->hscx[rq->adr.channel - 1].bch;
1512 if (test_and_set_bit(FLG_OPEN, &bch->Flags))
1513 return -EBUSY; /* b-channel can be only open once */
1514 test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
1515 bch->ch.protocol = rq->protocol;
1516 rq->ch = &bch->ch;
1517 return 0;
1518}
1519
1520static int
1521channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
1522{
1523 int ret = 0;
1524
1525 switch (cq->op) {
1526 case MISDN_CTRL_GETOP:
1527 cq->op = MISDN_CTRL_LOOP;
1528 break;
1529 case MISDN_CTRL_LOOP:
1530 /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
1531 if (cq->channel < 0 || cq->channel > 3) {
1532 ret = -EINVAL;
1533 break;
1534 }
1535 ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
1536 break;
1537 default:
1538 pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
1539 ret = -EINVAL;
1540 break;
1541 }
1542 return ret;
1543}
1544
1545static int
1546ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
1547{
1548 struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
1549 struct dchannel *dch = container_of(dev, struct dchannel, dev);
1550 struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
1551 struct ipac_hw *ipac = container_of(isac, struct ipac_hw, isac);
1552 struct channel_req *rq;
1553 int err = 0;
1554
1555 pr_debug("%s: DCTRL: %x %p\n", ipac->name, cmd, arg);
1556 switch (cmd) {
1557 case OPEN_CHANNEL:
1558 rq = arg;
1559 if (rq->protocol == ISDN_P_TE_S0)
1560 err = open_dchannel(isac, rq);
1561 else
1562 err = open_bchannel(ipac, rq);
1563 if (err)
1564 break;
1565 if (!try_module_get(ipac->owner))
1566 pr_info("%s: cannot get module\n", ipac->name);
1567 break;
1568 case CLOSE_CHANNEL:
1569 pr_debug("%s: dev(%d) close from %p\n", ipac->name,
1570 dch->dev.id, __builtin_return_address(0));
1571 module_put(ipac->owner);
1572 break;
1573 case CONTROL_CHANNEL:
1574 err = channel_ctrl(ipac, arg);
1575 break;
1576 default:
1577 pr_debug("%s: unknown DCTRL command %x\n", ipac->name, cmd);
1578 return -EINVAL;
1579 }
1580 return err;
1581}
1582
1583u32
1584mISDNipac_init(struct ipac_hw *ipac, void *hw)
1585{
1586 u32 ret;
1587 u8 i;
1588
1589 ipac->hw = hw;
1590 if (ipac->isac.dch.debug & DEBUG_HW)
1591 pr_notice("%s: ipac type %x\n", ipac->name, ipac->type);
1592 if (ipac->type & IPAC_TYPE_HSCX) {
1593 ipac->isac.type = IPAC_TYPE_ISAC;
1594 ipac->hscx[0].off = 0;
1595 ipac->hscx[1].off = 0x40;
1596 ipac->hscx[0].fifo_size = 32;
1597 ipac->hscx[1].fifo_size = 32;
1598 } else if (ipac->type & IPAC_TYPE_IPAC) {
1599 ipac->isac.type = IPAC_TYPE_IPAC | IPAC_TYPE_ISAC;
1600 ipac->hscx[0].off = 0;
1601 ipac->hscx[1].off = 0x40;
1602 ipac->hscx[0].fifo_size = 64;
1603 ipac->hscx[1].fifo_size = 64;
1604 } else if (ipac->type & IPAC_TYPE_IPACX) {
1605 ipac->isac.type = IPAC_TYPE_IPACX | IPAC_TYPE_ISACX;
1606 ipac->hscx[0].off = IPACX_OFF_ICA;
1607 ipac->hscx[1].off = IPACX_OFF_ICB;
1608 ipac->hscx[0].fifo_size = 64;
1609 ipac->hscx[1].fifo_size = 64;
1610 } else
1611 return 0;
1612
1613 mISDNisac_init(&ipac->isac, hw);
1614
1615 ipac->isac.dch.dev.D.ctrl = ipac_dctrl;
1616
1617 for (i = 0; i < 2; i++) {
1618 ipac->hscx[i].bch.nr = i + 1;
1619 set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
1620 list_add(&ipac->hscx[i].bch.ch.list,
1621 &ipac->isac.dch.dev.bchannels);
1622 mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM);
1623 ipac->hscx[i].bch.ch.nr = i + 1;
1624 ipac->hscx[i].bch.ch.send = &hscx_l2l1;
1625 ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
1626 ipac->hscx[i].bch.hw = hw;
1627 ipac->hscx[i].ip = ipac;
1628 /* default values for IOM time slots
1629 * can be overwriten by card */
1630 ipac->hscx[i].slot = (i == 0) ? 0x2f : 0x03;
1631 }
1632
1633 ipac->init = ipac_init;
1634 ipac->release = free_ipac;
1635
1636 ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
1637 (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
1638 return ret;
1639}
1640EXPORT_SYMBOL(mISDNipac_init);
1641
1642static int __init
1643isac_mod_init(void)
1644{
1645 pr_notice("mISDNipac module version %s\n", ISAC_REV);
1646 return 0;
1647}
1648
1649static void __exit
1650isac_mod_cleanup(void)
1651{
1652 pr_notice("mISDNipac module unloaded\n");
1653}
1654module_init(isac_mod_init);
1655module_exit(isac_mod_cleanup);