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