1/* $Id: icc.c,v 1.8.2.3 2004/01/13 14:31:25 keil Exp $ 2 * 3 * ICC specific routines 4 * 5 * Author Matt Henderson & Guy Ellis 6 * Copyright by Traverse Technologies Pty Ltd, www.travers.com.au 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 * 1999.6.25 Initial implementation of routines for Siemens ISDN 12 * Communication Controller PEB 2070 based on the ISAC routines 13 * written by Karsten Keil. 14 * 15 */ 16 17#include <linux/init.h> 18#include "hisax.h" 19#include "icc.h" 20// #include "arcofi.h" 21#include "isdnl1.h" 22#include <linux/interrupt.h> 23#include <linux/slab.h> 24 25#define DBUSY_TIMER_VALUE 80 26#define ARCOFI_USE 0 27 28static char *ICCVer[] = 29{"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"}; 30 31void 32ICCVersion(struct IsdnCardState *cs, char *s) 33{ 34 int val; 35 36 val = cs->readisac(cs, ICC_RBCH); 37 printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]); 38} 39 40static void 41ph_command(struct IsdnCardState *cs, unsigned int command) 42{ 43 if (cs->debug & L1_DEB_ISAC) 44 debugl1(cs, "ph_command %x", command); 45 cs->writeisac(cs, ICC_CIX0, (command << 2) | 3); 46} 47 48 49static void 50icc_new_ph(struct IsdnCardState *cs) 51{ 52 switch (cs->dc.icc.ph_state) { 53 case (ICC_IND_EI1): 54 ph_command(cs, ICC_CMD_DI); 55 l1_msg(cs, HW_RESET | INDICATION, NULL); 56 break; 57 case (ICC_IND_DC): 58 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); 59 break; 60 case (ICC_IND_DR): 61 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); 62 break; 63 case (ICC_IND_PU): 64 l1_msg(cs, HW_POWERUP | CONFIRM, NULL); 65 break; 66 case (ICC_IND_FJ): 67 l1_msg(cs, HW_RSYNC | INDICATION, NULL); 68 break; 69 case (ICC_IND_AR): 70 l1_msg(cs, HW_INFO2 | INDICATION, NULL); 71 break; 72 case (ICC_IND_AI): 73 l1_msg(cs, HW_INFO4 | INDICATION, NULL); 74 break; 75 default: 76 break; 77 } 78} 79 80static void 81icc_bh(struct work_struct *work) 82{ 83 struct IsdnCardState *cs = 84 container_of(work, struct IsdnCardState, tqueue); 85 struct PStack *stptr; 86 87 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { 88 if (cs->debug) 89 debugl1(cs, "D-Channel Busy cleared"); 90 stptr = cs->stlist; 91 while (stptr != NULL) { 92 stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); 93 stptr = stptr->next; 94 } 95 } 96 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) 97 icc_new_ph(cs); 98 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) 99 DChannel_proc_rcv(cs); 100 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) 101 DChannel_proc_xmt(cs); 102#if ARCOFI_USE 103 if (!test_bit(HW_ARCOFI, &cs->HW_Flags)) 104 return; 105 if (test_and_clear_bit(D_RX_MON1, &cs->event)) 106 arcofi_fsm(cs, ARCOFI_RX_END, NULL); 107 if (test_and_clear_bit(D_TX_MON1, &cs->event)) 108 arcofi_fsm(cs, ARCOFI_TX_END, NULL); 109#endif 110} 111 112static void 113icc_empty_fifo(struct IsdnCardState *cs, int count) 114{ 115 u_char *ptr; 116 117 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 118 debugl1(cs, "icc_empty_fifo"); 119 120 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { 121 if (cs->debug & L1_DEB_WARN) 122 debugl1(cs, "icc_empty_fifo overrun %d", 123 cs->rcvidx + count); 124 cs->writeisac(cs, ICC_CMDR, 0x80); 125 cs->rcvidx = 0; 126 return; 127 } 128 ptr = cs->rcvbuf + cs->rcvidx; 129 cs->rcvidx += count; 130 cs->readisacfifo(cs, ptr, count); 131 cs->writeisac(cs, ICC_CMDR, 0x80); 132 if (cs->debug & L1_DEB_ISAC_FIFO) { 133 char *t = cs->dlog; 134 135 t += sprintf(t, "icc_empty_fifo cnt %d", count); 136 QuickHex(t, ptr, count); 137 debugl1(cs, "%s", cs->dlog); 138 } 139} 140 141static void 142icc_fill_fifo(struct IsdnCardState *cs) 143{ 144 int count, more; 145 u_char *ptr; 146 147 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 148 debugl1(cs, "icc_fill_fifo"); 149 150 if (!cs->tx_skb) 151 return; 152 153 count = cs->tx_skb->len; 154 if (count <= 0) 155 return; 156 157 more = 0; 158 if (count > 32) { 159 more = !0; 160 count = 32; 161 } 162 ptr = cs->tx_skb->data; 163 skb_pull(cs->tx_skb, count); 164 cs->tx_cnt += count; 165 cs->writeisacfifo(cs, ptr, count); 166 cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa); 167 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 168 debugl1(cs, "icc_fill_fifo dbusytimer running"); 169 del_timer(&cs->dbusytimer); 170 } 171 init_timer(&cs->dbusytimer); 172 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); 173 add_timer(&cs->dbusytimer); 174 if (cs->debug & L1_DEB_ISAC_FIFO) { 175 char *t = cs->dlog; 176 177 t += sprintf(t, "icc_fill_fifo cnt %d", count); 178 QuickHex(t, ptr, count); 179 debugl1(cs, "%s", cs->dlog); 180 } 181} 182 183void 184icc_interrupt(struct IsdnCardState *cs, u_char val) 185{ 186 u_char exval, v1; 187 struct sk_buff *skb; 188 unsigned int count; 189 190 if (cs->debug & L1_DEB_ISAC) 191 debugl1(cs, "ICC interrupt %x", val); 192 if (val & 0x80) { /* RME */ 193 exval = cs->readisac(cs, ICC_RSTA); 194 if ((exval & 0x70) != 0x20) { 195 if (exval & 0x40) { 196 if (cs->debug & L1_DEB_WARN) 197 debugl1(cs, "ICC RDO"); 198#ifdef ERROR_STATISTIC 199 cs->err_rx++; 200#endif 201 } 202 if (!(exval & 0x20)) { 203 if (cs->debug & L1_DEB_WARN) 204 debugl1(cs, "ICC CRC error"); 205#ifdef ERROR_STATISTIC 206 cs->err_crc++; 207#endif 208 } 209 cs->writeisac(cs, ICC_CMDR, 0x80); 210 } else { 211 count = cs->readisac(cs, ICC_RBCL) & 0x1f; 212 if (count == 0) 213 count = 32; 214 icc_empty_fifo(cs, count); 215 if ((count = cs->rcvidx) > 0) { 216 cs->rcvidx = 0; 217 if (!(skb = alloc_skb(count, GFP_ATOMIC))) 218 printk(KERN_WARNING "HiSax: D receive out of memory\n"); 219 else { 220 memcpy(skb_put(skb, count), cs->rcvbuf, count); 221 skb_queue_tail(&cs->rq, skb); 222 } 223 } 224 } 225 cs->rcvidx = 0; 226 schedule_event(cs, D_RCVBUFREADY); 227 } 228 if (val & 0x40) { /* RPF */ 229 icc_empty_fifo(cs, 32); 230 } 231 if (val & 0x20) { /* RSC */ 232 /* never */ 233 if (cs->debug & L1_DEB_WARN) 234 debugl1(cs, "ICC RSC interrupt"); 235 } 236 if (val & 0x10) { /* XPR */ 237 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 238 del_timer(&cs->dbusytimer); 239 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 240 schedule_event(cs, D_CLEARBUSY); 241 if (cs->tx_skb) { 242 if (cs->tx_skb->len) { 243 icc_fill_fifo(cs); 244 goto afterXPR; 245 } else { 246 dev_kfree_skb_irq(cs->tx_skb); 247 cs->tx_cnt = 0; 248 cs->tx_skb = NULL; 249 } 250 } 251 if ((cs->tx_skb = skb_dequeue(&cs->sq))) { 252 cs->tx_cnt = 0; 253 icc_fill_fifo(cs); 254 } else 255 schedule_event(cs, D_XMTBUFREADY); 256 } 257afterXPR: 258 if (val & 0x04) { /* CISQ */ 259 exval = cs->readisac(cs, ICC_CIR0); 260 if (cs->debug & L1_DEB_ISAC) 261 debugl1(cs, "ICC CIR0 %02X", exval); 262 if (exval & 2) { 263 cs->dc.icc.ph_state = (exval >> 2) & 0xf; 264 if (cs->debug & L1_DEB_ISAC) 265 debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state); 266 schedule_event(cs, D_L1STATECHANGE); 267 } 268 if (exval & 1) { 269 exval = cs->readisac(cs, ICC_CIR1); 270 if (cs->debug & L1_DEB_ISAC) 271 debugl1(cs, "ICC CIR1 %02X", exval); 272 } 273 } 274 if (val & 0x02) { /* SIN */ 275 /* never */ 276 if (cs->debug & L1_DEB_WARN) 277 debugl1(cs, "ICC SIN interrupt"); 278 } 279 if (val & 0x01) { /* EXI */ 280 exval = cs->readisac(cs, ICC_EXIR); 281 if (cs->debug & L1_DEB_WARN) 282 debugl1(cs, "ICC EXIR %02x", exval); 283 if (exval & 0x80) { /* XMR */ 284 debugl1(cs, "ICC XMR"); 285 printk(KERN_WARNING "HiSax: ICC XMR\n"); 286 } 287 if (exval & 0x40) { /* XDU */ 288 debugl1(cs, "ICC XDU"); 289 printk(KERN_WARNING "HiSax: ICC XDU\n"); 290#ifdef ERROR_STATISTIC 291 cs->err_tx++; 292#endif 293 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 294 del_timer(&cs->dbusytimer); 295 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 296 schedule_event(cs, D_CLEARBUSY); 297 if (cs->tx_skb) { /* Restart frame */ 298 skb_push(cs->tx_skb, cs->tx_cnt); 299 cs->tx_cnt = 0; 300 icc_fill_fifo(cs); 301 } else { 302 printk(KERN_WARNING "HiSax: ICC XDU no skb\n"); 303 debugl1(cs, "ICC XDU no skb"); 304 } 305 } 306 if (exval & 0x04) { /* MOS */ 307 v1 = cs->readisac(cs, ICC_MOSR); 308 if (cs->debug & L1_DEB_MONITOR) 309 debugl1(cs, "ICC MOSR %02x", v1); 310#if ARCOFI_USE 311 if (v1 & 0x08) { 312 if (!cs->dc.icc.mon_rx) { 313 if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { 314 if (cs->debug & L1_DEB_WARN) 315 debugl1(cs, "ICC MON RX out of memory!"); 316 cs->dc.icc.mocr &= 0xf0; 317 cs->dc.icc.mocr |= 0x0a; 318 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 319 goto afterMONR0; 320 } else 321 cs->dc.icc.mon_rxp = 0; 322 } 323 if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { 324 cs->dc.icc.mocr &= 0xf0; 325 cs->dc.icc.mocr |= 0x0a; 326 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 327 cs->dc.icc.mon_rxp = 0; 328 if (cs->debug & L1_DEB_WARN) 329 debugl1(cs, "ICC MON RX overflow!"); 330 goto afterMONR0; 331 } 332 cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0); 333 if (cs->debug & L1_DEB_MONITOR) 334 debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp - 1]); 335 if (cs->dc.icc.mon_rxp == 1) { 336 cs->dc.icc.mocr |= 0x04; 337 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 338 } 339 } 340 afterMONR0: 341 if (v1 & 0x80) { 342 if (!cs->dc.icc.mon_rx) { 343 if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { 344 if (cs->debug & L1_DEB_WARN) 345 debugl1(cs, "ICC MON RX out of memory!"); 346 cs->dc.icc.mocr &= 0x0f; 347 cs->dc.icc.mocr |= 0xa0; 348 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 349 goto afterMONR1; 350 } else 351 cs->dc.icc.mon_rxp = 0; 352 } 353 if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { 354 cs->dc.icc.mocr &= 0x0f; 355 cs->dc.icc.mocr |= 0xa0; 356 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 357 cs->dc.icc.mon_rxp = 0; 358 if (cs->debug & L1_DEB_WARN) 359 debugl1(cs, "ICC MON RX overflow!"); 360 goto afterMONR1; 361 } 362 cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1); 363 if (cs->debug & L1_DEB_MONITOR) 364 debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp - 1]); 365 cs->dc.icc.mocr |= 0x40; 366 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 367 } 368 afterMONR1: 369 if (v1 & 0x04) { 370 cs->dc.icc.mocr &= 0xf0; 371 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 372 cs->dc.icc.mocr |= 0x0a; 373 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 374 schedule_event(cs, D_RX_MON0); 375 } 376 if (v1 & 0x40) { 377 cs->dc.icc.mocr &= 0x0f; 378 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 379 cs->dc.icc.mocr |= 0xa0; 380 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 381 schedule_event(cs, D_RX_MON1); 382 } 383 if (v1 & 0x02) { 384 if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && 385 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && 386 !(v1 & 0x08))) { 387 cs->dc.icc.mocr &= 0xf0; 388 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 389 cs->dc.icc.mocr |= 0x0a; 390 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 391 if (cs->dc.icc.mon_txc && 392 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) 393 schedule_event(cs, D_TX_MON0); 394 goto AfterMOX0; 395 } 396 if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { 397 schedule_event(cs, D_TX_MON0); 398 goto AfterMOX0; 399 } 400 cs->writeisac(cs, ICC_MOX0, 401 cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); 402 if (cs->debug & L1_DEB_MONITOR) 403 debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]); 404 } 405 AfterMOX0: 406 if (v1 & 0x20) { 407 if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && 408 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && 409 !(v1 & 0x80))) { 410 cs->dc.icc.mocr &= 0x0f; 411 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 412 cs->dc.icc.mocr |= 0xa0; 413 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 414 if (cs->dc.icc.mon_txc && 415 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) 416 schedule_event(cs, D_TX_MON1); 417 goto AfterMOX1; 418 } 419 if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { 420 schedule_event(cs, D_TX_MON1); 421 goto AfterMOX1; 422 } 423 cs->writeisac(cs, ICC_MOX1, 424 cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); 425 if (cs->debug & L1_DEB_MONITOR) 426 debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]); 427 } 428 AfterMOX1: ; 429#endif 430 } 431 } 432} 433 434static void 435ICC_l1hw(struct PStack *st, int pr, void *arg) 436{ 437 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; 438 struct sk_buff *skb = arg; 439 u_long flags; 440 int val; 441 442 switch (pr) { 443 case (PH_DATA | REQUEST): 444 if (cs->debug & DEB_DLOG_HEX) 445 LogFrame(cs, skb->data, skb->len); 446 if (cs->debug & DEB_DLOG_VERBOSE) 447 dlogframe(cs, skb, 0); 448 spin_lock_irqsave(&cs->lock, flags); 449 if (cs->tx_skb) { 450 skb_queue_tail(&cs->sq, skb); 451#ifdef L2FRAME_DEBUG /* psa */ 452 if (cs->debug & L1_DEB_LAPD) 453 Logl2Frame(cs, skb, "PH_DATA Queued", 0); 454#endif 455 } else { 456 cs->tx_skb = skb; 457 cs->tx_cnt = 0; 458#ifdef L2FRAME_DEBUG /* psa */ 459 if (cs->debug & L1_DEB_LAPD) 460 Logl2Frame(cs, skb, "PH_DATA", 0); 461#endif 462 icc_fill_fifo(cs); 463 } 464 spin_unlock_irqrestore(&cs->lock, flags); 465 break; 466 case (PH_PULL | INDICATION): 467 spin_lock_irqsave(&cs->lock, flags); 468 if (cs->tx_skb) { 469 if (cs->debug & L1_DEB_WARN) 470 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); 471 skb_queue_tail(&cs->sq, skb); 472 spin_unlock_irqrestore(&cs->lock, flags); 473 break; 474 } 475 if (cs->debug & DEB_DLOG_HEX) 476 LogFrame(cs, skb->data, skb->len); 477 if (cs->debug & DEB_DLOG_VERBOSE) 478 dlogframe(cs, skb, 0); 479 cs->tx_skb = skb; 480 cs->tx_cnt = 0; 481#ifdef L2FRAME_DEBUG /* psa */ 482 if (cs->debug & L1_DEB_LAPD) 483 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); 484#endif 485 icc_fill_fifo(cs); 486 spin_unlock_irqrestore(&cs->lock, flags); 487 break; 488 case (PH_PULL | REQUEST): 489#ifdef L2FRAME_DEBUG /* psa */ 490 if (cs->debug & L1_DEB_LAPD) 491 debugl1(cs, "-> PH_REQUEST_PULL"); 492#endif 493 if (!cs->tx_skb) { 494 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 495 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); 496 } else 497 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 498 break; 499 case (HW_RESET | REQUEST): 500 spin_lock_irqsave(&cs->lock, flags); 501 if ((cs->dc.icc.ph_state == ICC_IND_EI1) || 502 (cs->dc.icc.ph_state == ICC_IND_DR)) 503 ph_command(cs, ICC_CMD_DI); 504 else 505 ph_command(cs, ICC_CMD_RES); 506 spin_unlock_irqrestore(&cs->lock, flags); 507 break; 508 case (HW_ENABLE | REQUEST): 509 spin_lock_irqsave(&cs->lock, flags); 510 ph_command(cs, ICC_CMD_DI); 511 spin_unlock_irqrestore(&cs->lock, flags); 512 break; 513 case (HW_INFO1 | REQUEST): 514 spin_lock_irqsave(&cs->lock, flags); 515 ph_command(cs, ICC_CMD_AR); 516 spin_unlock_irqrestore(&cs->lock, flags); 517 break; 518 case (HW_INFO3 | REQUEST): 519 spin_lock_irqsave(&cs->lock, flags); 520 ph_command(cs, ICC_CMD_AI); 521 spin_unlock_irqrestore(&cs->lock, flags); 522 break; 523 case (HW_TESTLOOP | REQUEST): 524 spin_lock_irqsave(&cs->lock, flags); 525 val = 0; 526 if (1 & (long) arg) 527 val |= 0x0c; 528 if (2 & (long) arg) 529 val |= 0x3; 530 if (test_bit(HW_IOM1, &cs->HW_Flags)) { 531 /* IOM 1 Mode */ 532 if (!val) { 533 cs->writeisac(cs, ICC_SPCR, 0xa); 534 cs->writeisac(cs, ICC_ADF1, 0x2); 535 } else { 536 cs->writeisac(cs, ICC_SPCR, val); 537 cs->writeisac(cs, ICC_ADF1, 0xa); 538 } 539 } else { 540 /* IOM 2 Mode */ 541 cs->writeisac(cs, ICC_SPCR, val); 542 if (val) 543 cs->writeisac(cs, ICC_ADF1, 0x8); 544 else 545 cs->writeisac(cs, ICC_ADF1, 0x0); 546 } 547 spin_unlock_irqrestore(&cs->lock, flags); 548 break; 549 case (HW_DEACTIVATE | RESPONSE): 550 skb_queue_purge(&cs->rq); 551 skb_queue_purge(&cs->sq); 552 if (cs->tx_skb) { 553 dev_kfree_skb_any(cs->tx_skb); 554 cs->tx_skb = NULL; 555 } 556 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 557 del_timer(&cs->dbusytimer); 558 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 559 schedule_event(cs, D_CLEARBUSY); 560 break; 561 default: 562 if (cs->debug & L1_DEB_WARN) 563 debugl1(cs, "icc_l1hw unknown %04x", pr); 564 break; 565 } 566} 567 568static void 569setstack_icc(struct PStack *st, struct IsdnCardState *cs) 570{ 571 st->l1.l1hw = ICC_l1hw; 572} 573 574static void 575DC_Close_icc(struct IsdnCardState *cs) { 576 kfree(cs->dc.icc.mon_rx); 577 cs->dc.icc.mon_rx = NULL; 578 kfree(cs->dc.icc.mon_tx); 579 cs->dc.icc.mon_tx = NULL; 580} 581 582static void 583dbusy_timer_handler(struct IsdnCardState *cs) 584{ 585 struct PStack *stptr; 586 int rbch, star; 587 588 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 589 rbch = cs->readisac(cs, ICC_RBCH); 590 star = cs->readisac(cs, ICC_STAR); 591 if (cs->debug) 592 debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x", 593 rbch, star); 594 if (rbch & ICC_RBCH_XAC) { /* D-Channel Busy */ 595 test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); 596 stptr = cs->stlist; 597 while (stptr != NULL) { 598 stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); 599 stptr = stptr->next; 600 } 601 } else { 602 /* discard frame; reset transceiver */ 603 test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); 604 if (cs->tx_skb) { 605 dev_kfree_skb_any(cs->tx_skb); 606 cs->tx_cnt = 0; 607 cs->tx_skb = NULL; 608 } else { 609 printk(KERN_WARNING "HiSax: ICC D-Channel Busy no skb\n"); 610 debugl1(cs, "D-Channel Busy no skb"); 611 } 612 cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */ 613 cs->irq_func(cs->irq, cs); 614 } 615 } 616} 617 618void 619initicc(struct IsdnCardState *cs) 620{ 621 cs->setstack_d = setstack_icc; 622 cs->DC_Close = DC_Close_icc; 623 cs->dc.icc.mon_tx = NULL; 624 cs->dc.icc.mon_rx = NULL; 625 cs->writeisac(cs, ICC_MASK, 0xff); 626 cs->dc.icc.mocr = 0xaa; 627 if (test_bit(HW_IOM1, &cs->HW_Flags)) { 628 /* IOM 1 Mode */ 629 cs->writeisac(cs, ICC_ADF2, 0x0); 630 cs->writeisac(cs, ICC_SPCR, 0xa); 631 cs->writeisac(cs, ICC_ADF1, 0x2); 632 cs->writeisac(cs, ICC_STCR, 0x70); 633 cs->writeisac(cs, ICC_MODE, 0xc9); 634 } else { 635 /* IOM 2 Mode */ 636 if (!cs->dc.icc.adf2) 637 cs->dc.icc.adf2 = 0x80; 638 cs->writeisac(cs, ICC_ADF2, cs->dc.icc.adf2); 639 cs->writeisac(cs, ICC_SQXR, 0xa0); 640 cs->writeisac(cs, ICC_SPCR, 0x20); 641 cs->writeisac(cs, ICC_STCR, 0x70); 642 cs->writeisac(cs, ICC_MODE, 0xca); 643 cs->writeisac(cs, ICC_TIMR, 0x00); 644 cs->writeisac(cs, ICC_ADF1, 0x20); 645 } 646 ph_command(cs, ICC_CMD_RES); 647 cs->writeisac(cs, ICC_MASK, 0x0); 648 ph_command(cs, ICC_CMD_DI); 649} 650 651void 652clear_pending_icc_ints(struct IsdnCardState *cs) 653{ 654 int val, eval; 655 656 val = cs->readisac(cs, ICC_STAR); 657 debugl1(cs, "ICC STAR %x", val); 658 val = cs->readisac(cs, ICC_MODE); 659 debugl1(cs, "ICC MODE %x", val); 660 val = cs->readisac(cs, ICC_ADF2); 661 debugl1(cs, "ICC ADF2 %x", val); 662 val = cs->readisac(cs, ICC_ISTA); 663 debugl1(cs, "ICC ISTA %x", val); 664 if (val & 0x01) { 665 eval = cs->readisac(cs, ICC_EXIR); 666 debugl1(cs, "ICC EXIR %x", eval); 667 } 668 val = cs->readisac(cs, ICC_CIR0); 669 debugl1(cs, "ICC CIR0 %x", val); 670 cs->dc.icc.ph_state = (val >> 2) & 0xf; 671 schedule_event(cs, D_L1STATECHANGE); 672 /* Disable all IRQ */ 673 cs->writeisac(cs, ICC_MASK, 0xFF); 674} 675 676void setup_icc(struct IsdnCardState *cs) 677{ 678 INIT_WORK(&cs->tqueue, icc_bh); 679 cs->dbusytimer.function = (void *) dbusy_timer_handler; 680 cs->dbusytimer.data = (long) cs; 681 init_timer(&cs->dbusytimer); 682} 683