📄 hfc_sx.c
字号:
{ struct IsdnCardState *cs = bcs->cs; if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcsx_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "send_data %d blocked", bcs->channel);}/***************************************************************//* activate/deactivate hardware for selected channels and mode *//***************************************************************/static voidmode_hfcsx(struct BCState *bcs, int mode, int bc){ struct IsdnCardState *cs = bcs->cs; int fifo2; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HFCSX bchannel mode %d bchan %d/%d", mode, bc, bcs->channel); bcs->mode = mode; bcs->channel = bc; fifo2 = bc; if (cs->chanlimit > 1) { cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcsx.sctrl_e &= ~0x80; } else { if (bc) { if (mode != L1_MODE_NULL) { cs->hw.hfcsx.bswapped = 1; /* B1 and B2 exchanged */ cs->hw.hfcsx.sctrl_e |= 0x80; } else { cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcsx.sctrl_e &= ~0x80; } fifo2 = 0; } else { cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcsx.sctrl_e &= ~0x80; } } switch (mode) { case (L1_MODE_NULL): if (bc) { cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA; } else { cs->hw.hfcsx.sctrl &= ~SCTRL_B1_ENA; cs->hw.hfcsx.sctrl_r &= ~SCTRL_B1_ENA; } if (fifo2) { cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC); } else { cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC); } break; case (L1_MODE_TRANS): if (bc) { cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA; cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA; } else { cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA; cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA; } if (fifo2) { cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC); cs->hw.hfcsx.ctmt |= 2; cs->hw.hfcsx.conn &= ~0x18; } else { cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC); cs->hw.hfcsx.ctmt |= 1; cs->hw.hfcsx.conn &= ~0x03; } break; case (L1_MODE_HDLC): if (bc) { cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA; cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA; } else { cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA; cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA; } if (fifo2) { cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC); cs->hw.hfcsx.ctmt &= ~2; cs->hw.hfcsx.conn &= ~0x18; } else { cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC); cs->hw.hfcsx.ctmt &= ~1; cs->hw.hfcsx.conn &= ~0x03; } break; case (L1_MODE_EXTRN): if (bc) { cs->hw.hfcsx.conn |= 0x10; cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA; cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA; cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC); } else { cs->hw.hfcsx.conn |= 0x02; cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA; cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA; cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC); } break; } Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl); Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r); Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt); Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); if (mode != L1_MODE_EXTRN) { reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX); reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX); }}/******************************//* Layer2 -> Layer 1 Transfer *//******************************/static voidhfcsx_l2l1(struct PStack *st, int pr, void *arg){ struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; u_long flags; switch (pr) { case (PH_DATA | REQUEST): spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->tx_skb) { skb_queue_tail(&bcs->squeue, skb); } else { bcs->tx_skb = skb;// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); bcs->cs->BC_Send_Data(bcs); } spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->tx_skb) { printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); } else {// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); bcs->tx_skb = skb; bcs->cs->BC_Send_Data(bcs); } spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): if (!bcs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): spin_lock_irqsave(&bcs->cs->lock, flags); test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); mode_hfcsx(bcs, st->l1.mode, st->l1.bc); spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): spin_lock_irqsave(&bcs->cs->lock, flags); test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); mode_hfcsx(bcs, 0, st->l1.bc); spin_unlock_irqrestore(&bcs->cs->lock, flags); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; }}/******************************************//* deactivate B-channel access and queues *//******************************************/static voidclose_hfcsx(struct BCState *bcs){ mode_hfcsx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } }}/*************************************//* init B-channel queues and control *//*************************************/static intopen_hfcsxstate(struct IsdnCardState *cs, struct BCState *bcs){ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; bcs->tx_cnt = 0; return (0);}/*********************************//* inits the stack for B-channel *//*********************************/static intsetstack_2b(struct PStack *st, struct BCState *bcs){ bcs->channel = st->l1.bc; if (open_hfcsxstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = hfcsx_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0);}/***************************//* handle L1 state changes *//***************************/static voidhfcsx_bh(struct IsdnCardState *cs){ u_long flags; if (!cs) return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcsx.nt_mode) switch (cs->dc.hfcsx.ph_state) { case (0): l1_msg(cs, HW_RESET | INDICATION, NULL); break; case (3): l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); break; case (8): l1_msg(cs, HW_RSYNC | INDICATION, NULL); break; case (6): l1_msg(cs, HW_INFO2 | INDICATION, NULL); break; case (7): l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); break; default: break; } else { switch (cs->dc.hfcsx.ph_state) { case (2): spin_lock_irqsave(&cs->lock, flags); if (cs->hw.hfcsx.nt_timer < 0) { cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); /* Clear already pending ints */ if (Read_hfc(cs, HFCSX_INT_S1)); Write_hfc(cs, HFCSX_STATES, 4 | HFCSX_LOAD_STATE); udelay(10); Write_hfc(cs, HFCSX_STATES, 4); cs->dc.hfcsx.ph_state = 4; } else { cs->hw.hfcsx.int_m1 |= HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); cs->hw.hfcsx.ctmt &= ~HFCSX_AUTO_TIMER; cs->hw.hfcsx.ctmt |= HFCSX_TIM3_125; Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER); Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER); cs->hw.hfcsx.nt_timer = NT_T1_COUNT; Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */ } spin_unlock_irqrestore(&cs->lock, flags); break; case (1): case (3): case (4): spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); spin_unlock_irqrestore(&cs->lock, flags); break; default: break; } } } if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) DChannel_proc_rcv(cs); if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) DChannel_proc_xmt(cs);}/********************************//* called for card init message *//********************************/static void __devinitinithfcsx(struct IsdnCardState *cs){ cs->setstack_d = setstack_hfcsx; cs->BC_Send_Data = &hfcsx_send_data; cs->bcs[0].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[0].BC_Close = close_hfcsx; cs->bcs[1].BC_Close = close_hfcsx; mode_hfcsx(cs->bcs, 0, 0); mode_hfcsx(cs->bcs + 1, 0, 1);}/*******************************************//* handle card messages from control layer *//*******************************************/static inthfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg){ u_long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCSX: card_msg %x", mt); switch (mt) { case CARD_RESET: spin_lock_irqsave(&cs->lock, flags); reset_hfcsx(cs); spin_unlock_irqrestore(&cs->lock, flags); return (0); case CARD_RELEASE: release_io_hfcsx(cs); return (0); case CARD_INIT: spin_lock_irqsave(&cs->lock, flags); inithfcsx(cs); spin_unlock_irqrestore(&cs->lock, flags); msleep(80); /* Timeout 80ms */ /* now switch timer interrupt off */ spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); /* reinit mode reg */ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); spin_unlock_irqrestore(&cs->lock, flags); return (0); case CARD_TEST: return (0); } return (0);}#ifdef __ISAPNP__static struct isapnp_device_id hfc_ids[] __devinitdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), (unsigned long) "Teles 16.3c2" }, { 0, }};static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];static struct pnp_card *pnp_c __devinitdata = NULL;#endifint __devinitsetup_hfcsx(struct IsdnCard *card){ struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcsx_revision); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));#ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { struct pnp_dev *pnp_d; while(ipid->card_vendor) { if ((pnp_c = pnp_find_card(ipid->card_vendor, ipid->card_device, pnp_c))) { pnp_d = NULL; if ((pnp_d = pnp_find_dev(pnp_c, ipid->vendor, ipid->function, pnp_d))) { int err; printk(KERN_INFO "HiSax: %s detected\n", (char *)ipid->driver_data); pnp_disable_dev(pnp_d); err = pnp_activate_dev(pnp_d); if (err<0) { printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", __FUNCTION__, err); return(0); } card->para[1] = pnp_port_start(pnp_d, 0); card->para[0] = pnp_irq(pnp_d, 0); if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", card->para[0], card->para[1]); pnp_disable_dev(pnp_d); return(0); } break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); } } ipid++; pnp_c = NULL; } if (!ipid->card_vendor) { printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); return(0); } }#endif cs->hw.hfcsx.base = card->para[1] & 0xfffe; cs->irq = card->para[0]; cs->hw.hfcsx.int_s1 = 0; cs->dc.hfcsx.ph_state = 0; cs->hw.hfcsx.fifo = 255; if ((cs->typ == ISDN_CTYPE_HFC_SX) || (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) { if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) { printk(KERN_WARNING "HiSax: HFC-SX io-base %#lx already in use\n", cs->hw.hfcsx.base); return(0); } byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); udelay(10); cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); switch (cs->hw.hfcsx.chip >> 4) { case 1: tmp[0] ='+'; break; case 9: tmp[0] ='P'; break; default: printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", cs->hw.hfcsx.chip >> 4); release_region(cs->hw.hfcsx.base, 2); return(0); } if (!ccd_sp_irqtab[cs->irq & 0xF]) { printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF); release_region(cs->hw.hfcsx.base, 2); return(0); } if (!(cs->hw.hfcsx.extra = (void *) kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) { release_region(cs->hw.hfcsx.base, 2); printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); return(0); } printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ); cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcsx.int_m1 = 0; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); } else return (0); /* no valid card type */ cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs); cs->readisac = NULL; cs->writeisac = NULL; cs->readisacfifo = NULL; cs->writeisacfifo = NULL; cs->BC_Read_Reg = NULL; cs->BC_Write_Reg = NULL; cs->irq_func = &hfcsx_interrupt; cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; cs->hw.hfcsx.timer.data = (long) cs; cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ init_timer(&cs->hw.hfcsx.timer); reset_hfcsx(cs); cs->cardmsg = &hfcsx_card_msg; cs->auxcmd = &hfcsx_auxcmd; return (1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -