1/* $Id: icc.c,v 1.1.1.1 2007/08/03 18:52:35 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 24#define DBUSY_TIMER_VALUE 80 25#define ARCOFI_USE 0 26 27static char *ICCVer[] = 28{"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"}; 29 30void 31ICCVersion(struct IsdnCardState *cs, char *s) 32{ 33 int val; 34 35 val = cs->readisac(cs, ICC_RBCH); 36 printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]); 37} 38 39static void 40ph_command(struct IsdnCardState *cs, unsigned int command) 41{ 42 if (cs->debug & L1_DEB_ISAC) 43 debugl1(cs, "ph_command %x", command); 44 cs->writeisac(cs, ICC_CIX0, (command << 2) | 3); 45} 46 47 48static void 49icc_new_ph(struct IsdnCardState *cs) 50{ 51 switch (cs->dc.icc.ph_state) { 52 case (ICC_IND_EI1): 53 ph_command(cs, ICC_CMD_DI); 54 l1_msg(cs, HW_RESET | INDICATION, NULL); 55 break; 56 case (ICC_IND_DC): 57 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); 58 break; 59 case (ICC_IND_DR): 60 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); 61 break; 62 case (ICC_IND_PU): 63 l1_msg(cs, HW_POWERUP | CONFIRM, NULL); 64 break; 65 case (ICC_IND_FJ): 66 l1_msg(cs, HW_RSYNC | INDICATION, NULL); 67 break; 68 case (ICC_IND_AR): 69 l1_msg(cs, HW_INFO2 | INDICATION, NULL); 70 break; 71 case (ICC_IND_AI): 72 l1_msg(cs, HW_INFO4 | INDICATION, NULL); 73 break; 74 default: 75 break; 76 } 77} 78 79static void 80icc_bh(struct work_struct *work) 81{ 82 struct IsdnCardState *cs = 83 container_of(work, struct IsdnCardState, tqueue); 84 struct PStack *stptr; 85 86 if (!cs) 87 return; 88 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { 89 if (cs->debug) 90 debugl1(cs, "D-Channel Busy cleared"); 91 stptr = cs->stlist; 92 while (stptr != NULL) { 93 stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); 94 stptr = stptr->next; 95 } 96 } 97 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) 98 icc_new_ph(cs); 99 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) 100 DChannel_proc_rcv(cs); 101 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) 102 DChannel_proc_xmt(cs); 103#if ARCOFI_USE 104 if (!test_bit(HW_ARCOFI, &cs->HW_Flags)) 105 return; 106 if (test_and_clear_bit(D_RX_MON1, &cs->event)) 107 arcofi_fsm(cs, ARCOFI_RX_END, NULL); 108 if (test_and_clear_bit(D_TX_MON1, &cs->event)) 109 arcofi_fsm(cs, ARCOFI_TX_END, NULL); 110#endif 111} 112 113static void 114icc_empty_fifo(struct IsdnCardState *cs, int count) 115{ 116 u_char *ptr; 117 118 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 119 debugl1(cs, "icc_empty_fifo"); 120 121 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { 122 if (cs->debug & L1_DEB_WARN) 123 debugl1(cs, "icc_empty_fifo overrun %d", 124 cs->rcvidx + count); 125 cs->writeisac(cs, ICC_CMDR, 0x80); 126 cs->rcvidx = 0; 127 return; 128 } 129 ptr = cs->rcvbuf + cs->rcvidx; 130 cs->rcvidx += count; 131 cs->readisacfifo(cs, ptr, count); 132 cs->writeisac(cs, ICC_CMDR, 0x80); 133 if (cs->debug & L1_DEB_ISAC_FIFO) { 134 char *t = cs->dlog; 135 136 t += sprintf(t, "icc_empty_fifo cnt %d", count); 137 QuickHex(t, ptr, count); 138 debugl1(cs, cs->dlog); 139 } 140} 141 142static void 143icc_fill_fifo(struct IsdnCardState *cs) 144{ 145 int count, more; 146 u_char *ptr; 147 148 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 149 debugl1(cs, "icc_fill_fifo"); 150 151 if (!cs->tx_skb) 152 return; 153 154 count = cs->tx_skb->len; 155 if (count <= 0) 156 return; 157 158 more = 0; 159 if (count > 32) { 160 more = !0; 161 count = 32; 162 } 163 ptr = cs->tx_skb->data; 164 skb_pull(cs->tx_skb, count); 165 cs->tx_cnt += count; 166 cs->writeisacfifo(cs, ptr, count); 167 cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa); 168 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 169 debugl1(cs, "icc_fill_fifo dbusytimer running"); 170 del_timer(&cs->dbusytimer); 171 } 172 init_timer(&cs->dbusytimer); 173 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); 174 add_timer(&cs->dbusytimer); 175 if (cs->debug & L1_DEB_ISAC_FIFO) { 176 char *t = cs->dlog; 177 178 t += sprintf(t, "icc_fill_fifo cnt %d", count); 179 QuickHex(t, ptr, count); 180 debugl1(cs, cs->dlog); 181 } 182} 183 184void 185icc_interrupt(struct IsdnCardState *cs, u_char val) 186{ 187 u_char exval, v1; 188 struct sk_buff *skb; 189 unsigned int count; 190 191 if (cs->debug & L1_DEB_ISAC) 192 debugl1(cs, "ICC interrupt %x", val); 193 if (val & 0x80) { /* RME */ 194 exval = cs->readisac(cs, ICC_RSTA); 195 if ((exval & 0x70) != 0x20) { 196 if (exval & 0x40) { 197 if (cs->debug & L1_DEB_WARN) 198 debugl1(cs, "ICC RDO"); 199#ifdef ERROR_STATISTIC 200 cs->err_rx++; 201#endif 202 } 203 if (!(exval & 0x20)) { 204 if (cs->debug & L1_DEB_WARN) 205 debugl1(cs, "ICC CRC error"); 206#ifdef ERROR_STATISTIC 207 cs->err_crc++; 208#endif 209 } 210 cs->writeisac(cs, ICC_CMDR, 0x80); 211 } else { 212 count = cs->readisac(cs, ICC_RBCL) & 0x1f; 213 if (count == 0) 214 count = 32; 215 icc_empty_fifo(cs, count); 216 if ((count = cs->rcvidx) > 0) { 217 cs->rcvidx = 0; 218 if (!(skb = alloc_skb(count, GFP_ATOMIC))) 219 printk(KERN_WARNING "HiSax: D receive out of memory\n"); 220 else { 221 memcpy(skb_put(skb, count), cs->rcvbuf, count); 222 skb_queue_tail(&cs->rq, skb); 223 } 224 } 225 } 226 cs->rcvidx = 0; 227 schedule_event(cs, D_RCVBUFREADY); 228 } 229 if (val & 0x40) { /* RPF */ 230 icc_empty_fifo(cs, 32); 231 } 232 if (val & 0x20) { /* RSC */ 233 /* never */ 234 if (cs->debug & L1_DEB_WARN) 235 debugl1(cs, "ICC RSC interrupt"); 236 } 237 if (val & 0x10) { /* XPR */ 238 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 239 del_timer(&cs->dbusytimer); 240 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 241 schedule_event(cs, D_CLEARBUSY); 242 if (cs->tx_skb) { 243 if (cs->tx_skb->len) { 244 icc_fill_fifo(cs); 245 goto afterXPR; 246 } else { 247 dev_kfree_skb_irq(cs->tx_skb); 248 cs->tx_cnt = 0; 249 cs->tx_skb = NULL; 250 } 251 } 252 if ((cs->tx_skb = skb_dequeue(&cs->sq))) { 253 cs->tx_cnt = 0; 254 icc_fill_fifo(cs); 255 } else 256 schedule_event(cs, D_XMTBUFREADY); 257 } 258 afterXPR: 259 if (val & 0x04) { /* CISQ */ 260 exval = cs->readisac(cs, ICC_CIR0); 261 if (cs->debug & L1_DEB_ISAC) 262 debugl1(cs, "ICC CIR0 %02X", exval ); 263 if (exval & 2) { 264 cs->dc.icc.ph_state = (exval >> 2) & 0xf; 265 if (cs->debug & L1_DEB_ISAC) 266 debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state); 267 schedule_event(cs, D_L1STATECHANGE); 268 } 269 if (exval & 1) { 270 exval = cs->readisac(cs, ICC_CIR1); 271 if (cs->debug & L1_DEB_ISAC) 272 debugl1(cs, "ICC CIR1 %02X", exval ); 273 } 274 } 275 if (val & 0x02) { /* SIN */ 276 /* never */ 277 if (cs->debug & L1_DEB_WARN) 278 debugl1(cs, "ICC SIN interrupt"); 279 } 280 if (val & 0x01) { /* EXI */ 281 exval = cs->readisac(cs, ICC_EXIR); 282 if (cs->debug & L1_DEB_WARN) 283 debugl1(cs, "ICC EXIR %02x", exval); 284 if (exval & 0x80) { /* XMR */ 285 debugl1(cs, "ICC XMR"); 286 printk(KERN_WARNING "HiSax: ICC XMR\n"); 287 } 288 if (exval & 0x40) { /* XDU */ 289 debugl1(cs, "ICC XDU"); 290 printk(KERN_WARNING "HiSax: ICC XDU\n"); 291#ifdef ERROR_STATISTIC 292 cs->err_tx++; 293#endif 294 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 295 del_timer(&cs->dbusytimer); 296 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 297 schedule_event(cs, D_CLEARBUSY); 298 if (cs->tx_skb) { /* Restart frame */ 299 skb_push(cs->tx_skb, cs->tx_cnt); 300 cs->tx_cnt = 0; 301 icc_fill_fifo(cs); 302 } else { 303 printk(KERN_WARNING "HiSax: ICC XDU no skb\n"); 304 debugl1(cs, "ICC XDU no skb"); 305 } 306 } 307 if (exval & 0x04) { /* MOS */ 308 v1 = cs->readisac(cs, ICC_MOSR); 309 if (cs->debug & L1_DEB_MONITOR) 310 debugl1(cs, "ICC MOSR %02x", v1); 311#if ARCOFI_USE 312 if (v1 & 0x08) { 313 if (!cs->dc.icc.mon_rx) { 314 if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { 315 if (cs->debug & L1_DEB_WARN) 316 debugl1(cs, "ICC MON RX out of memory!"); 317 cs->dc.icc.mocr &= 0xf0; 318 cs->dc.icc.mocr |= 0x0a; 319 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 320 goto afterMONR0; 321 } else 322 cs->dc.icc.mon_rxp = 0; 323 } 324 if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { 325 cs->dc.icc.mocr &= 0xf0; 326 cs->dc.icc.mocr |= 0x0a; 327 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 328 cs->dc.icc.mon_rxp = 0; 329 if (cs->debug & L1_DEB_WARN) 330 debugl1(cs, "ICC MON RX overflow!"); 331 goto afterMONR0; 332 } 333 cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0); 334 if (cs->debug & L1_DEB_MONITOR) 335 debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]); 336 if (cs->dc.icc.mon_rxp == 1) { 337 cs->dc.icc.mocr |= 0x04; 338 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 339 } 340 } 341 afterMONR0: 342 if (v1 & 0x80) { 343 if (!cs->dc.icc.mon_rx) { 344 if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { 345 if (cs->debug & L1_DEB_WARN) 346 debugl1(cs, "ICC MON RX out of memory!"); 347 cs->dc.icc.mocr &= 0x0f; 348 cs->dc.icc.mocr |= 0xa0; 349 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 350 goto afterMONR1; 351 } else 352 cs->dc.icc.mon_rxp = 0; 353 } 354 if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { 355 cs->dc.icc.mocr &= 0x0f; 356 cs->dc.icc.mocr |= 0xa0; 357 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 358 cs->dc.icc.mon_rxp = 0; 359 if (cs->debug & L1_DEB_WARN) 360 debugl1(cs, "ICC MON RX overflow!"); 361 goto afterMONR1; 362 } 363 cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1); 364 if (cs->debug & L1_DEB_MONITOR) 365 debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]); 366 cs->dc.icc.mocr |= 0x40; 367 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 368 } 369 afterMONR1: 370 if (v1 & 0x04) { 371 cs->dc.icc.mocr &= 0xf0; 372 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 373 cs->dc.icc.mocr |= 0x0a; 374 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 375 schedule_event(cs, D_RX_MON0); 376 } 377 if (v1 & 0x40) { 378 cs->dc.icc.mocr &= 0x0f; 379 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 380 cs->dc.icc.mocr |= 0xa0; 381 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 382 schedule_event(cs, D_RX_MON1); 383 } 384 if (v1 & 0x02) { 385 if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && 386 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && 387 !(v1 & 0x08))) { 388 cs->dc.icc.mocr &= 0xf0; 389 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 390 cs->dc.icc.mocr |= 0x0a; 391 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 392 if (cs->dc.icc.mon_txc && 393 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) 394 schedule_event(cs, D_TX_MON0); 395 goto AfterMOX0; 396 } 397 if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { 398 schedule_event(cs, D_TX_MON0); 399 goto AfterMOX0; 400 } 401 cs->writeisac(cs, ICC_MOX0, 402 cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); 403 if (cs->debug & L1_DEB_MONITOR) 404 debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]); 405 } 406 AfterMOX0: 407 if (v1 & 0x20) { 408 if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && 409 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && 410 !(v1 & 0x80))) { 411 cs->dc.icc.mocr &= 0x0f; 412 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 413 cs->dc.icc.mocr |= 0xa0; 414 cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); 415 if (cs->dc.icc.mon_txc && 416 (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) 417 schedule_event(cs, D_TX_MON1); 418 goto AfterMOX1; 419 } 420 if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { 421 schedule_event(cs, D_TX_MON1); 422 goto AfterMOX1; 423 } 424 cs->writeisac(cs, ICC_MOX1, 425 cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); 426 if (cs->debug & L1_DEB_MONITOR) 427 debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]); 428 } 429 AfterMOX1: 430#endif 431 } 432 } 433} 434 435static void 436ICC_l1hw(struct PStack *st, int pr, void *arg) 437{ 438 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; 439 struct sk_buff *skb = arg; 440 u_long flags; 441 int val; 442 443 switch (pr) { 444 case (PH_DATA |REQUEST): 445 if (cs->debug & DEB_DLOG_HEX) 446 LogFrame(cs, skb->data, skb->len); 447 if (cs->debug & DEB_DLOG_VERBOSE) 448 dlogframe(cs, skb, 0); 449 spin_lock_irqsave(&cs->lock, flags); 450 if (cs->tx_skb) { 451 skb_queue_tail(&cs->sq, skb); 452#ifdef L2FRAME_DEBUG /* psa */ 453 if (cs->debug & L1_DEB_LAPD) 454 Logl2Frame(cs, skb, "PH_DATA Queued", 0); 455#endif 456 } else { 457 cs->tx_skb = skb; 458 cs->tx_cnt = 0; 459#ifdef L2FRAME_DEBUG /* psa */ 460 if (cs->debug & L1_DEB_LAPD) 461 Logl2Frame(cs, skb, "PH_DATA", 0); 462#endif 463 icc_fill_fifo(cs); 464 } 465 spin_unlock_irqrestore(&cs->lock, flags); 466 break; 467 case (PH_PULL |INDICATION): 468 spin_lock_irqsave(&cs->lock, flags); 469 if (cs->tx_skb) { 470 if (cs->debug & L1_DEB_WARN) 471 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); 472 skb_queue_tail(&cs->sq, skb); 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 __devinit 677setup_icc(struct IsdnCardState *cs) 678{ 679 INIT_WORK(&cs->tqueue, icc_bh); 680 cs->dbusytimer.function = (void *) dbusy_timer_handler; 681 cs->dbusytimer.data = (long) cs; 682 init_timer(&cs->dbusytimer); 683} 684