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