1/* 2 * 3 * IPACX specific routines 4 * 5 * Author Joerg Petersohn 6 * Derived from hisax_isac.c, isac.c, hscx.c and others 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 */ 12#include <linux/kernel.h> 13#include <linux/slab.h> 14#include <linux/init.h> 15#include "hisax_if.h" 16#include "hisax.h" 17#include "isdnl1.h" 18#include "ipacx.h" 19 20#define DBUSY_TIMER_VALUE 80 21#define TIMER3_VALUE 7000 22#define MAX_DFRAME_LEN_L1 300 23#define B_FIFO_SIZE 64 24#define D_FIFO_SIZE 32 25 26 27// ipacx interrupt mask values 28#define _MASK_IMASK 0x2E // global mask 29#define _MASKB_IMASK 0x0B 30#define _MASKD_IMASK 0x03 // all on 31 32//---------------------------------------------------------- 33// local function declarations 34//---------------------------------------------------------- 35static void ph_command(struct IsdnCardState *cs, unsigned int command); 36static inline void cic_int(struct IsdnCardState *cs); 37static void dch_l2l1(struct PStack *st, int pr, void *arg); 38static void dbusy_timer_handler(struct IsdnCardState *cs); 39static void dch_empty_fifo(struct IsdnCardState *cs, int count); 40static void dch_fill_fifo(struct IsdnCardState *cs); 41static inline void dch_int(struct IsdnCardState *cs); 42static void dch_setstack(struct PStack *st, struct IsdnCardState *cs); 43static void dch_init(struct IsdnCardState *cs); 44static void bch_l2l1(struct PStack *st, int pr, void *arg); 45static void bch_empty_fifo(struct BCState *bcs, int count); 46static void bch_fill_fifo(struct BCState *bcs); 47static void bch_int(struct IsdnCardState *cs, u_char hscx); 48static void bch_mode(struct BCState *bcs, int mode, int bc); 49static void bch_close_state(struct BCState *bcs); 50static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs); 51static int bch_setstack(struct PStack *st, struct BCState *bcs); 52static void bch_init(struct IsdnCardState *cs, int hscx); 53static void clear_pending_ints(struct IsdnCardState *cs); 54 55//---------------------------------------------------------- 56// Issue Layer 1 command to chip 57//---------------------------------------------------------- 58static void 59ph_command(struct IsdnCardState *cs, unsigned int command) 60{ 61 if (cs->debug & L1_DEB_ISAC) 62 debugl1(cs, "ph_command (%#x) in (%#x)", command, 63 cs->dc.isac.ph_state); 64//################################### 65// printk(KERN_INFO "ph_command (%#x)\n", command); 66//################################### 67 cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E); 68} 69 70//---------------------------------------------------------- 71// Transceiver interrupt handler 72//---------------------------------------------------------- 73static inline void 74cic_int(struct IsdnCardState *cs) 75{ 76 u_char event; 77 78 event = cs->readisac(cs, IPACX_CIR0) >> 4; 79 if (cs->debug & L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event); 80//######################################### 81// printk(KERN_INFO "cic_int(%x)\n", event); 82//######################################### 83 cs->dc.isac.ph_state = event; 84 schedule_event(cs, D_L1STATECHANGE); 85} 86 87//========================================================== 88// D channel functions 89//========================================================== 90 91//---------------------------------------------------------- 92// Command entry point 93//---------------------------------------------------------- 94static void 95dch_l2l1(struct PStack *st, int pr, void *arg) 96{ 97 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; 98 struct sk_buff *skb = arg; 99 u_char cda1_cr; 100 101 switch (pr) { 102 case (PH_DATA | REQUEST): 103 if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); 104 if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); 105 if (cs->tx_skb) { 106 skb_queue_tail(&cs->sq, skb); 107#ifdef L2FRAME_DEBUG 108 if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0); 109#endif 110 } else { 111 cs->tx_skb = skb; 112 cs->tx_cnt = 0; 113#ifdef L2FRAME_DEBUG 114 if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0); 115#endif 116 dch_fill_fifo(cs); 117 } 118 break; 119 120 case (PH_PULL | INDICATION): 121 if (cs->tx_skb) { 122 if (cs->debug & L1_DEB_WARN) 123 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); 124 skb_queue_tail(&cs->sq, skb); 125 break; 126 } 127 if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); 128 if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); 129 cs->tx_skb = skb; 130 cs->tx_cnt = 0; 131#ifdef L2FRAME_DEBUG 132 if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); 133#endif 134 dch_fill_fifo(cs); 135 break; 136 137 case (PH_PULL | REQUEST): 138#ifdef L2FRAME_DEBUG 139 if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); 140#endif 141 if (!cs->tx_skb) { 142 clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 143 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); 144 } else 145 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 146 break; 147 148 case (HW_RESET | REQUEST): 149 case (HW_ENABLE | REQUEST): 150 if ((cs->dc.isac.ph_state == IPACX_IND_RES) || 151 (cs->dc.isac.ph_state == IPACX_IND_DR) || 152 (cs->dc.isac.ph_state == IPACX_IND_DC)) 153 ph_command(cs, IPACX_CMD_TIM); 154 else 155 ph_command(cs, IPACX_CMD_RES); 156 break; 157 158 case (HW_INFO3 | REQUEST): 159 ph_command(cs, IPACX_CMD_AR8); 160 break; 161 162 case (HW_TESTLOOP | REQUEST): 163 cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 164 cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 165 cda1_cr = cs->readisac(cs, IPACX_CDA1_CR); 166 (void) cs->readisac(cs, IPACX_CDA2_CR); 167 if ((long)arg & 1) { // loop B1 168 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr | 0x0a); 169 } 170 else { // B1 off 171 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr & ~0x0a); 172 } 173 if ((long)arg & 2) { // loop B2 174 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr | 0x14); 175 } 176 else { // B2 off 177 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr & ~0x14); 178 } 179 break; 180 181 case (HW_DEACTIVATE | RESPONSE): 182 skb_queue_purge(&cs->rq); 183 skb_queue_purge(&cs->sq); 184 if (cs->tx_skb) { 185 dev_kfree_skb_any(cs->tx_skb); 186 cs->tx_skb = NULL; 187 } 188 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 189 del_timer(&cs->dbusytimer); 190 break; 191 192 default: 193 if (cs->debug & L1_DEB_WARN) debugl1(cs, "dch_l2l1 unknown %04x", pr); 194 break; 195 } 196} 197 198//---------------------------------------------------------- 199//---------------------------------------------------------- 200static void 201dbusy_timer_handler(struct IsdnCardState *cs) 202{ 203 struct PStack *st; 204 int rbchd, stard; 205 206 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 207 rbchd = cs->readisac(cs, IPACX_RBCHD); 208 stard = cs->readisac(cs, IPACX_STARD); 209 if (cs->debug) 210 debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard); 211 if (!(stard & 0x40)) { // D-Channel Busy 212 set_bit(FLG_L1_DBUSY, &cs->HW_Flags); 213 for (st = cs->stlist; st; st = st->next) { 214 st->l1.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on 215 } 216 } else { 217 // seems we lost an interrupt; reset transceiver */ 218 clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); 219 if (cs->tx_skb) { 220 dev_kfree_skb_any(cs->tx_skb); 221 cs->tx_cnt = 0; 222 cs->tx_skb = NULL; 223 } else { 224 printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); 225 debugl1(cs, "D-Channel Busy no skb"); 226 } 227 cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR 228 } 229 } 230} 231 232//---------------------------------------------------------- 233// Fill buffer from receive FIFO 234//---------------------------------------------------------- 235static void 236dch_empty_fifo(struct IsdnCardState *cs, int count) 237{ 238 u_char *ptr; 239 240 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 241 debugl1(cs, "dch_empty_fifo()"); 242 243 // message too large, remove 244 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { 245 if (cs->debug & L1_DEB_WARN) 246 debugl1(cs, "dch_empty_fifo() incoming message too large"); 247 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC 248 cs->rcvidx = 0; 249 return; 250 } 251 252 ptr = cs->rcvbuf + cs->rcvidx; 253 cs->rcvidx += count; 254 255 cs->readisacfifo(cs, ptr, count); 256 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC 257 258 if (cs->debug & L1_DEB_ISAC_FIFO) { 259 char *t = cs->dlog; 260 261 t += sprintf(t, "dch_empty_fifo() cnt %d", count); 262 QuickHex(t, ptr, count); 263 debugl1(cs, "%s", cs->dlog); 264 } 265} 266 267//---------------------------------------------------------- 268// Fill transmit FIFO 269//---------------------------------------------------------- 270static void 271dch_fill_fifo(struct IsdnCardState *cs) 272{ 273 int count; 274 u_char cmd, *ptr; 275 276 if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 277 debugl1(cs, "dch_fill_fifo()"); 278 279 if (!cs->tx_skb) return; 280 count = cs->tx_skb->len; 281 if (count <= 0) return; 282 283 if (count > D_FIFO_SIZE) { 284 count = D_FIFO_SIZE; 285 cmd = 0x08; // XTF 286 } else { 287 cmd = 0x0A; // XTF | XME 288 } 289 290 ptr = cs->tx_skb->data; 291 skb_pull(cs->tx_skb, count); 292 cs->tx_cnt += count; 293 cs->writeisacfifo(cs, ptr, count); 294 cs->writeisac(cs, IPACX_CMDRD, cmd); 295 296 // set timeout for transmission contol 297 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 298 debugl1(cs, "dch_fill_fifo dbusytimer running"); 299 del_timer(&cs->dbusytimer); 300 } 301 init_timer(&cs->dbusytimer); 302 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); 303 add_timer(&cs->dbusytimer); 304 305 if (cs->debug & L1_DEB_ISAC_FIFO) { 306 char *t = cs->dlog; 307 308 t += sprintf(t, "dch_fill_fifo() cnt %d", count); 309 QuickHex(t, ptr, count); 310 debugl1(cs, "%s", cs->dlog); 311 } 312} 313 314//---------------------------------------------------------- 315// D channel interrupt handler 316//---------------------------------------------------------- 317static inline void 318dch_int(struct IsdnCardState *cs) 319{ 320 struct sk_buff *skb; 321 u_char istad, rstad; 322 int count; 323 324 istad = cs->readisac(cs, IPACX_ISTAD); 325//############################################## 326// printk(KERN_WARNING "dch_int(istad=%02x)\n", istad); 327//############################################## 328 329 if (istad & 0x80) { // RME 330 rstad = cs->readisac(cs, IPACX_RSTAD); 331 if ((rstad & 0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) 332 if (!(rstad & 0x80)) 333 if (cs->debug & L1_DEB_WARN) 334 debugl1(cs, "dch_int(): invalid frame"); 335 if ((rstad & 0x40)) 336 if (cs->debug & L1_DEB_WARN) 337 debugl1(cs, "dch_int(): RDO"); 338 if (!(rstad & 0x20)) 339 if (cs->debug & L1_DEB_WARN) 340 debugl1(cs, "dch_int(): CRC error"); 341 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC 342 } else { // received frame ok 343 count = cs->readisac(cs, IPACX_RBCLD); 344 if (count) count--; // RSTAB is last byte 345 count &= D_FIFO_SIZE - 1; 346 if (count == 0) count = D_FIFO_SIZE; 347 dch_empty_fifo(cs, count); 348 if ((count = cs->rcvidx) > 0) { 349 cs->rcvidx = 0; 350 if (!(skb = dev_alloc_skb(count))) 351 printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n"); 352 else { 353 memcpy(skb_put(skb, count), cs->rcvbuf, count); 354 skb_queue_tail(&cs->rq, skb); 355 } 356 } 357 } 358 cs->rcvidx = 0; 359 schedule_event(cs, D_RCVBUFREADY); 360 } 361 362 if (istad & 0x40) { // RPF 363 dch_empty_fifo(cs, D_FIFO_SIZE); 364 } 365 366 if (istad & 0x20) { // RFO 367 if (cs->debug & L1_DEB_WARN) debugl1(cs, "dch_int(): RFO"); 368 cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES 369 } 370 371 if (istad & 0x10) { // XPR 372 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 373 del_timer(&cs->dbusytimer); 374 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 375 schedule_event(cs, D_CLEARBUSY); 376 if (cs->tx_skb) { 377 if (cs->tx_skb->len) { 378 dch_fill_fifo(cs); 379 goto afterXPR; 380 } 381 else { 382 dev_kfree_skb_irq(cs->tx_skb); 383 cs->tx_skb = NULL; 384 cs->tx_cnt = 0; 385 } 386 } 387 if ((cs->tx_skb = skb_dequeue(&cs->sq))) { 388 cs->tx_cnt = 0; 389 dch_fill_fifo(cs); 390 } 391 else { 392 schedule_event(cs, D_XMTBUFREADY); 393 } 394 } 395afterXPR: 396 397 if (istad & 0x0C) { // XDU or XMR 398 if (cs->debug & L1_DEB_WARN) debugl1(cs, "dch_int(): XDU"); 399 if (cs->tx_skb) { 400 skb_push(cs->tx_skb, cs->tx_cnt); // retransmit 401 cs->tx_cnt = 0; 402 dch_fill_fifo(cs); 403 } else { 404 printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); 405 debugl1(cs, "ISAC XDU no skb"); 406 } 407 } 408} 409 410//---------------------------------------------------------- 411//---------------------------------------------------------- 412static void 413dch_setstack(struct PStack *st, struct IsdnCardState *cs) 414{ 415 st->l1.l1hw = dch_l2l1; 416} 417 418//---------------------------------------------------------- 419//---------------------------------------------------------- 420static void 421dch_init(struct IsdnCardState *cs) 422{ 423 printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n"); 424 425 cs->setstack_d = dch_setstack; 426 427 cs->dbusytimer.function = (void *) dbusy_timer_handler; 428 cs->dbusytimer.data = (long) cs; 429 init_timer(&cs->dbusytimer); 430 431 cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD 432 cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter 433 cs->writeisac(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go 434 cs->writeisac(cs, IPACX_MON_CR, 0x00); // disable monitor channel 435} 436 437 438//========================================================== 439// B channel functions 440//========================================================== 441 442//---------------------------------------------------------- 443// Entry point for commands 444//---------------------------------------------------------- 445static void 446bch_l2l1(struct PStack *st, int pr, void *arg) 447{ 448 struct BCState *bcs = st->l1.bcs; 449 struct sk_buff *skb = arg; 450 u_long flags; 451 452 switch (pr) { 453 case (PH_DATA | REQUEST): 454 spin_lock_irqsave(&bcs->cs->lock, flags); 455 if (bcs->tx_skb) { 456 skb_queue_tail(&bcs->squeue, skb); 457 } else { 458 bcs->tx_skb = skb; 459 set_bit(BC_FLG_BUSY, &bcs->Flag); 460 bcs->hw.hscx.count = 0; 461 bch_fill_fifo(bcs); 462 } 463 spin_unlock_irqrestore(&bcs->cs->lock, flags); 464 break; 465 case (PH_PULL | INDICATION): 466 spin_lock_irqsave(&bcs->cs->lock, flags); 467 if (bcs->tx_skb) { 468 printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n"); 469 } else { 470 set_bit(BC_FLG_BUSY, &bcs->Flag); 471 bcs->tx_skb = skb; 472 bcs->hw.hscx.count = 0; 473 bch_fill_fifo(bcs); 474 } 475 spin_unlock_irqrestore(&bcs->cs->lock, flags); 476 break; 477 case (PH_PULL | REQUEST): 478 if (!bcs->tx_skb) { 479 clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 480 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); 481 } else 482 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 483 break; 484 case (PH_ACTIVATE | REQUEST): 485 spin_lock_irqsave(&bcs->cs->lock, flags); 486 set_bit(BC_FLG_ACTIV, &bcs->Flag); 487 bch_mode(bcs, st->l1.mode, st->l1.bc); 488 spin_unlock_irqrestore(&bcs->cs->lock, flags); 489 l1_msg_b(st, pr, arg); 490 break; 491 case (PH_DEACTIVATE | REQUEST): 492 l1_msg_b(st, pr, arg); 493 break; 494 case (PH_DEACTIVATE | CONFIRM): 495 spin_lock_irqsave(&bcs->cs->lock, flags); 496 clear_bit(BC_FLG_ACTIV, &bcs->Flag); 497 clear_bit(BC_FLG_BUSY, &bcs->Flag); 498 bch_mode(bcs, 0, st->l1.bc); 499 spin_unlock_irqrestore(&bcs->cs->lock, flags); 500 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); 501 break; 502 } 503} 504 505//---------------------------------------------------------- 506// Read B channel fifo to receive buffer 507//---------------------------------------------------------- 508static void 509bch_empty_fifo(struct BCState *bcs, int count) 510{ 511 u_char *ptr, hscx; 512 struct IsdnCardState *cs; 513 int cnt; 514 515 cs = bcs->cs; 516 hscx = bcs->hw.hscx.hscx; 517 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) 518 debugl1(cs, "bch_empty_fifo()"); 519 520 // message too large, remove 521 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { 522 if (cs->debug & L1_DEB_WARN) 523 debugl1(cs, "bch_empty_fifo() incoming packet too large"); 524 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC 525 bcs->hw.hscx.rcvidx = 0; 526 return; 527 } 528 529 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; 530 cnt = count; 531 while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); 532 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC 533 534 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; 535 bcs->hw.hscx.rcvidx += count; 536 537 if (cs->debug & L1_DEB_HSCX_FIFO) { 538 char *t = bcs->blog; 539 540 t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); 541 QuickHex(t, ptr, count); 542 debugl1(cs, "%s", bcs->blog); 543 } 544} 545 546//---------------------------------------------------------- 547// Fill buffer to transmit FIFO 548//---------------------------------------------------------- 549static void 550bch_fill_fifo(struct BCState *bcs) 551{ 552 struct IsdnCardState *cs; 553 int more, count, cnt; 554 u_char *ptr, *p, hscx; 555 556 cs = bcs->cs; 557 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) 558 debugl1(cs, "bch_fill_fifo()"); 559 560 if (!bcs->tx_skb) return; 561 if (bcs->tx_skb->len <= 0) return; 562 563 hscx = bcs->hw.hscx.hscx; 564 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; 565 if (bcs->tx_skb->len > B_FIFO_SIZE) { 566 more = 1; 567 count = B_FIFO_SIZE; 568 } else { 569 count = bcs->tx_skb->len; 570 } 571 cnt = count; 572 573 p = ptr = bcs->tx_skb->data; 574 skb_pull(bcs->tx_skb, count); 575 bcs->tx_cnt -= count; 576 bcs->hw.hscx.count += count; 577 while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); 578 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a)); 579 580 if (cs->debug & L1_DEB_HSCX_FIFO) { 581 char *t = bcs->blog; 582 583 t += sprintf(t, "%s() B-%d cnt %d", __func__, hscx, count); 584 QuickHex(t, ptr, count); 585 debugl1(cs, "%s", bcs->blog); 586 } 587} 588 589//---------------------------------------------------------- 590// B channel interrupt handler 591//---------------------------------------------------------- 592static void 593bch_int(struct IsdnCardState *cs, u_char hscx) 594{ 595 u_char istab; 596 struct BCState *bcs; 597 struct sk_buff *skb; 598 int count; 599 u_char rstab; 600 601 bcs = cs->bcs + hscx; 602 istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB); 603//############################################## 604// printk(KERN_WARNING "bch_int(istab=%02x)\n", istab); 605//############################################## 606 if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return; 607 608 if (istab & 0x80) { // RME 609 rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB); 610 if ((rstab & 0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) 611 if (!(rstab & 0x80)) 612 if (cs->debug & L1_DEB_WARN) 613 debugl1(cs, "bch_int() B-%d: invalid frame", hscx); 614 if ((rstab & 0x40) && (bcs->mode != L1_MODE_NULL)) 615 if (cs->debug & L1_DEB_WARN) 616 debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); 617 if (!(rstab & 0x20)) 618 if (cs->debug & L1_DEB_WARN) 619 debugl1(cs, "bch_int() B-%d: CRC error", hscx); 620 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC 621 } 622 else { // received frame ok 623 count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) & (B_FIFO_SIZE - 1); 624 if (count == 0) count = B_FIFO_SIZE; 625 bch_empty_fifo(bcs, count); 626 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { 627 if (cs->debug & L1_DEB_HSCX_FIFO) 628 debugl1(cs, "bch_int Frame %d", count); 629 if (!(skb = dev_alloc_skb(count))) 630 printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n"); 631 else { 632 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); 633 skb_queue_tail(&bcs->rqueue, skb); 634 } 635 } 636 } 637 bcs->hw.hscx.rcvidx = 0; 638 schedule_event(bcs, B_RCVBUFREADY); 639 } 640 641 if (istab & 0x40) { // RPF 642 bch_empty_fifo(bcs, B_FIFO_SIZE); 643 644 if (bcs->mode == L1_MODE_TRANS) { // queue every chunk 645 // receive transparent audio data 646 if (!(skb = dev_alloc_skb(B_FIFO_SIZE))) 647 printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n"); 648 else { 649 memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE); 650 skb_queue_tail(&bcs->rqueue, skb); 651 } 652 bcs->hw.hscx.rcvidx = 0; 653 schedule_event(bcs, B_RCVBUFREADY); 654 } 655 } 656 657 if (istab & 0x20) { // RFO 658 if (cs->debug & L1_DEB_WARN) 659 debugl1(cs, "bch_int() B-%d: RFO error", hscx); 660 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES 661 } 662 663 if (istab & 0x10) { // XPR 664 if (bcs->tx_skb) { 665 if (bcs->tx_skb->len) { 666 bch_fill_fifo(bcs); 667 goto afterXPR; 668 } else { 669 if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) && 670 (PACKET_NOACK != bcs->tx_skb->pkt_type)) { 671 u_long flags; 672 spin_lock_irqsave(&bcs->aclock, flags); 673 bcs->ackcnt += bcs->hw.hscx.count; 674 spin_unlock_irqrestore(&bcs->aclock, flags); 675 schedule_event(bcs, B_ACKPENDING); 676 } 677 } 678 dev_kfree_skb_irq(bcs->tx_skb); 679 bcs->hw.hscx.count = 0; 680 bcs->tx_skb = NULL; 681 } 682 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { 683 bcs->hw.hscx.count = 0; 684 set_bit(BC_FLG_BUSY, &bcs->Flag); 685 bch_fill_fifo(bcs); 686 } else { 687 clear_bit(BC_FLG_BUSY, &bcs->Flag); 688 schedule_event(bcs, B_XMTBUFREADY); 689 } 690 } 691afterXPR: 692 693 if (istab & 0x04) { // XDU 694 if (bcs->mode == L1_MODE_TRANS) { 695 bch_fill_fifo(bcs); 696 } 697 else { 698 if (bcs->tx_skb) { // restart transmitting the whole frame 699 skb_push(bcs->tx_skb, bcs->hw.hscx.count); 700 bcs->tx_cnt += bcs->hw.hscx.count; 701 bcs->hw.hscx.count = 0; 702 } 703 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES 704 if (cs->debug & L1_DEB_WARN) 705 debugl1(cs, "bch_int() B-%d XDU error", hscx); 706 } 707 } 708} 709 710//---------------------------------------------------------- 711//---------------------------------------------------------- 712static void 713bch_mode(struct BCState *bcs, int mode, int bc) 714{ 715 struct IsdnCardState *cs = bcs->cs; 716 int hscx = bcs->hw.hscx.hscx; 717 718 bc = bc ? 1 : 0; // in case bc is greater than 1 719 if (cs->debug & L1_DEB_HSCX) 720 debugl1(cs, "mode_bch() switch B-%d mode %d chan %d", hscx, mode, bc); 721 bcs->mode = mode; 722 bcs->channel = bc; 723 724 // map controller to according timeslot 725 if (!hscx) 726 { 727 cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc); 728 cs->writeisac(cs, IPACX_BCHA_CR, 0x88); 729 } 730 else 731 { 732 cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc); 733 cs->writeisac(cs, IPACX_BCHB_CR, 0x88); 734 } 735 736 switch (mode) { 737 case (L1_MODE_NULL): 738 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0); // rec off 739 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x30); // std adj. 740 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF); // ints off 741 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments 742 break; 743 case (L1_MODE_TRANS): 744 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88); // ext transp mode 745 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x00); // xxx00000 746 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments 747 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); 748 break; 749 case (L1_MODE_HDLC): 750 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8); // transp mode 0 751 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled 752 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments 753 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); 754 break; 755 } 756} 757 758//---------------------------------------------------------- 759//---------------------------------------------------------- 760static void 761bch_close_state(struct BCState *bcs) 762{ 763 bch_mode(bcs, 0, bcs->channel); 764 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { 765 kfree(bcs->hw.hscx.rcvbuf); 766 bcs->hw.hscx.rcvbuf = NULL; 767 kfree(bcs->blog); 768 bcs->blog = NULL; 769 skb_queue_purge(&bcs->rqueue); 770 skb_queue_purge(&bcs->squeue); 771 if (bcs->tx_skb) { 772 dev_kfree_skb_any(bcs->tx_skb); 773 bcs->tx_skb = NULL; 774 clear_bit(BC_FLG_BUSY, &bcs->Flag); 775 } 776 } 777} 778 779//---------------------------------------------------------- 780//---------------------------------------------------------- 781static int 782bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) 783{ 784 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { 785 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { 786 printk(KERN_WARNING 787 "HiSax open_bchstate(): No memory for hscx.rcvbuf\n"); 788 clear_bit(BC_FLG_INIT, &bcs->Flag); 789 return (1); 790 } 791 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { 792 printk(KERN_WARNING 793 "HiSax open_bchstate: No memory for bcs->blog\n"); 794 clear_bit(BC_FLG_INIT, &bcs->Flag); 795 kfree(bcs->hw.hscx.rcvbuf); 796 bcs->hw.hscx.rcvbuf = NULL; 797 return (2); 798 } 799 skb_queue_head_init(&bcs->rqueue); 800 skb_queue_head_init(&bcs->squeue); 801 } 802 bcs->tx_skb = NULL; 803 clear_bit(BC_FLG_BUSY, &bcs->Flag); 804 bcs->event = 0; 805 bcs->hw.hscx.rcvidx = 0; 806 bcs->tx_cnt = 0; 807 return (0); 808} 809 810//---------------------------------------------------------- 811//---------------------------------------------------------- 812static int 813bch_setstack(struct PStack *st, struct BCState *bcs) 814{ 815 bcs->channel = st->l1.bc; 816 if (bch_open_state(st->l1.hardware, bcs)) return (-1); 817 st->l1.bcs = bcs; 818 st->l2.l2l1 = bch_l2l1; 819 setstack_manager(st); 820 bcs->st = st; 821 setstack_l1_B(st); 822 return (0); 823} 824 825//---------------------------------------------------------- 826//---------------------------------------------------------- 827static void 828bch_init(struct IsdnCardState *cs, int hscx) 829{ 830 cs->bcs[hscx].BC_SetStack = bch_setstack; 831 cs->bcs[hscx].BC_Close = bch_close_state; 832 cs->bcs[hscx].hw.hscx.hscx = hscx; 833 cs->bcs[hscx].cs = cs; 834 bch_mode(cs->bcs + hscx, 0, hscx); 835} 836 837 838//========================================================== 839// Shared functions 840//========================================================== 841 842//---------------------------------------------------------- 843// Main interrupt handler 844//---------------------------------------------------------- 845void 846interrupt_ipacx(struct IsdnCardState *cs) 847{ 848 u_char ista; 849 850 while ((ista = cs->readisac(cs, IPACX_ISTA))) { 851//################################################# 852// printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista); 853//################################################# 854 if (ista & 0x80) bch_int(cs, 0); // B channel interrupts 855 if (ista & 0x40) bch_int(cs, 1); 856 857 if (ista & 0x01) dch_int(cs); // D channel 858 if (ista & 0x10) cic_int(cs); // Layer 1 state 859 } 860} 861 862//---------------------------------------------------------- 863// Clears chip interrupt status 864//---------------------------------------------------------- 865static void 866clear_pending_ints(struct IsdnCardState *cs) 867{ 868 int ista; 869 870 // all interrupts off 871 cs->writeisac(cs, IPACX_MASK, 0xff); 872 cs->writeisac(cs, IPACX_MASKD, 0xff); 873 cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff); 874 cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff); 875 876 ista = cs->readisac(cs, IPACX_ISTA); 877 if (ista & 0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB); 878 if (ista & 0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB); 879 if (ista & 0x10) cs->readisac(cs, IPACX_CIR0); 880 if (ista & 0x01) cs->readisac(cs, IPACX_ISTAD); 881} 882 883//---------------------------------------------------------- 884// Does chip configuration work 885// Work to do depends on bit mask in part 886//---------------------------------------------------------- 887void 888init_ipacx(struct IsdnCardState *cs, int part) 889{ 890 if (part & 1) { // initialise chip 891//################################################## 892// printk(KERN_INFO "init_ipacx(%x)\n", part); 893//################################################## 894 clear_pending_ints(cs); 895 bch_init(cs, 0); 896 bch_init(cs, 1); 897 dch_init(cs); 898 } 899 if (part & 2) { // reenable all interrupts and start chip 900 cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK); 901 cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK); 902 cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK); 903 cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register 904 905 // reset HDLC Transmitters/receivers 906 cs->writeisac(cs, IPACX_CMDRD, 0x41); 907 cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41); 908 cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41); 909 ph_command(cs, IPACX_CMD_RES); 910 } 911} 912 913//----------------- end of file ----------------------- 914