📄 hfc4s8s_l1.c
字号:
Write_hfc8(l1p->hw, R_ST_SEL, l1p->st_num); l1p->l1_state = Read_hfc8(l1p->hw, A_ST_RD_STA) & 0xf; if (((l1p->l1_state == 3) && ((oldstate == 7) || (oldstate == 8))) || ((timer_pending (&l1p->l1_timer)) && (l1p->l1_state == 8))) { mod_timer(&l1p->l1_timer, L1_TIMER_T4 + jiffies); } else { if (l1p->l1_state == 7) { del_timer(&l1p-> l1_timer); l1p->d_if.ifc. l1l2(&l1p-> d_if.ifc, PH_ACTIVATE | INDICATION, NULL); tx_d_frame(l1p); } if (l1p->l1_state == 3) { if (oldstate != 3) l1p->d_if. ifc. l1l2 (&l1p-> d_if. ifc, PH_DEACTIVATE | INDICATION, NULL); } } printk(KERN_INFO "HFC-4S/8S: TE %d ch %d l1 state %d -> %d\n", l1p->hw->cardnum, l1p->st_num, oldstate, l1p->l1_state); } } } b <<= 1; l1p++; } /* now handle the fifos */ idx = 0; fifo_stat = hw->mr.r_irq_fifo_blx; l1p = hw->l1; while (idx < hw->driver_data.max_st_ports) { if (hw->mr.timer_irq) { *fifo_stat |= hw->mr.fifo_rx_trans_enables[idx]; if (hw->fifo_sched_cnt <= 0) { *fifo_stat |= hw->mr.fifo_slow_timer_service[l1p-> st_num]; } } /* ignore fifo 6 (TX E fifo) */ *fifo_stat &= 0xff - 0x40; while (*fifo_stat) { if (!l1p->nt_mode) { /* RX Fifo has data to read */ if ((*fifo_stat & 0x20)) { *fifo_stat &= ~0x20; rx_d_frame(l1p, 0); } /* E Fifo has data to read */ if ((*fifo_stat & 0x80)) { *fifo_stat &= ~0x80; rx_d_frame(l1p, 1); } /* TX Fifo completed send */ if ((*fifo_stat & 0x10)) { *fifo_stat &= ~0x10; tx_d_frame(l1p); } } /* B1 RX Fifo has data to read */ if ((*fifo_stat & 0x2)) { *fifo_stat &= ~0x2; rx_b_frame(l1p->b_ch); } /* B1 TX Fifo has send completed */ if ((*fifo_stat & 0x1)) { *fifo_stat &= ~0x1; tx_b_frame(l1p->b_ch); } /* B2 RX Fifo has data to read */ if ((*fifo_stat & 0x8)) { *fifo_stat &= ~0x8; rx_b_frame(l1p->b_ch + 1); } /* B2 TX Fifo has send completed */ if ((*fifo_stat & 0x4)) { *fifo_stat &= ~0x4; tx_b_frame(l1p->b_ch + 1); } } fifo_stat++; l1p++; idx++; } if (hw->fifo_sched_cnt <= 0) hw->fifo_sched_cnt += (1 << (7 - TRANS_TIMER_MODE)); hw->mr.timer_irq = 0; /* clear requested timer irq */} /* hfc4s8s_bh *//*********************//* interrupt handler *//*********************/static irqreturn_thfc4s8s_interrupt(int intno, void *dev_id, struct pt_regs *regs){ hfc4s8s_hw *hw = dev_id; u_char b, ovr; volatile u_char *ovp; int idx; u_char old_ioreg; if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN)) return IRQ_NONE;#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM /* read current selected regsister */ old_ioreg = GetRegAddr(hw);#endif /* Layer 1 State change */ hw->mr.r_irq_statech |= (Read_hfc8(hw, R_SCI) & hw->mr.r_irqmsk_statchg); if (! (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))&& !hw->mr.r_irq_statech) {#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM SetRegAddr(hw, old_ioreg);#endif return IRQ_NONE; } /* timer event */ if (Read_hfc8(hw, R_IRQ_MISC) & M_TI_IRQ) { hw->mr.timer_irq = 1; hw->fifo_sched_cnt--; } /* FIFO event */ if ((ovr = Read_hfc8(hw, R_IRQ_OVIEW))) { hw->mr.r_irq_oview |= ovr; idx = R_IRQ_FIFO_BL0; ovp = hw->mr.r_irq_fifo_blx; while (ovr) { if ((ovr & 1)) { *ovp |= Read_hfc8(hw, idx); } ovp++; idx++; ovr >>= 1; } } /* queue the request to allow other cards to interrupt */ schedule_work(&hw->tqueue);#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM SetRegAddr(hw, old_ioreg);#endif return IRQ_HANDLED;} /* hfc4s8s_interrupt *//***********************************************************************//* reset the complete chip, don't release the chips irq but disable it *//***********************************************************************/static voidchipreset(hfc4s8s_hw * hw){ u_long flags; spin_lock_irqsave(&hw->lock, flags); Write_hfc8(hw, R_CTRL, 0); /* use internal RAM */ Write_hfc8(hw, R_RAM_MISC, 0); /* 32k*8 RAM */ Write_hfc8(hw, R_FIFO_MD, 0); /* fifo mode 386 byte/fifo simple mode */ Write_hfc8(hw, R_CIRM, M_SRES); /* reset chip */ hw->mr.r_irq_ctrl = 0; /* interrupt is inactive */ spin_unlock_irqrestore(&hw->lock, flags); udelay(3); Write_hfc8(hw, R_CIRM, 0); /* disable reset */ wait_busy(hw); Write_hfc8(hw, R_PCM_MD0, M_PCM_MD); /* master mode */ Write_hfc8(hw, R_RAM_MISC, M_FZ_MD); /* transmit fifo option */ if (hw->driver_data.clock_mode == 1) Write_hfc8(hw, R_BRG_PCM_CFG, M_PCM_CLK); /* PCM clk / 2 */ Write_hfc8(hw, R_TI_WD, TRANS_TIMER_MODE); /* timer interval */ memset(&hw->mr, 0, sizeof(hw->mr));} /* chipreset *//********************************************//* disable/enable hardware in nt or te mode *//********************************************/static voidhfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode){ u_long flags; char if_name[40]; int i; if (enable) { /* save system vars */ hw->nt_mode = nt_mode; /* enable fifo and state irqs, but not global irq enable */ hw->mr.r_irq_ctrl = M_FIFO_IRQ; Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl); hw->mr.r_irqmsk_statchg = 0; Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg); Write_hfc8(hw, R_PWM_MD, 0x80); Write_hfc8(hw, R_PWM1, 26); if (!nt_mode) Write_hfc8(hw, R_ST_SYNC, M_AUTO_SYNC); /* enable the line interfaces and fifos */ for (i = 0; i < hw->driver_data.max_st_ports; i++) { hw->mr.r_irqmsk_statchg |= (1 << i); Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg); Write_hfc8(hw, R_ST_SEL, i); Write_hfc8(hw, A_ST_CLK_DLY, ((nt_mode) ? CLKDEL_NT : CLKDEL_TE)); hw->mr.r_ctrl0 = ((nt_mode) ? CTRL0_NT : CTRL0_TE); Write_hfc8(hw, A_ST_CTRL0, hw->mr.r_ctrl0); Write_hfc8(hw, A_ST_CTRL2, 3); Write_hfc8(hw, A_ST_WR_STA, 0); /* enable state machine */ hw->l1[i].enabled = 1; hw->l1[i].nt_mode = nt_mode; if (!nt_mode) { /* setup E-fifo */ Write_hfc8(hw, R_FIFO, i * 8 + 7); /* E fifo */ wait_busy(hw); Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */ Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */ Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */ Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */ wait_busy(hw); /* setup D RX-fifo */ Write_hfc8(hw, R_FIFO, i * 8 + 5); /* RX fifo */ wait_busy(hw); Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */ Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */ Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */ Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */ wait_busy(hw); /* setup D TX-fifo */ Write_hfc8(hw, R_FIFO, i * 8 + 4); /* TX fifo */ wait_busy(hw); Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */ Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */ Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */ Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */ wait_busy(hw); } sprintf(if_name, "hfc4s8s_%d%d_", hw->cardnum, i); if (hisax_register (&hw->l1[i].d_if, hw->l1[i].b_table, if_name, ((nt_mode) ? 3 : 2))) { hw->l1[i].enabled = 0; hw->mr.r_irqmsk_statchg &= ~(1 << i); Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg); printk(KERN_INFO "HFC-4S/8S: Unable to register S/T device %s, break\n", if_name); break; } } spin_lock_irqsave(&hw->lock, flags); hw->mr.r_irq_ctrl |= M_GLOB_IRQ_EN; Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl); spin_unlock_irqrestore(&hw->lock, flags); } else { /* disable hardware */ spin_lock_irqsave(&hw->lock, flags); hw->mr.r_irq_ctrl &= ~M_GLOB_IRQ_EN; Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl); spin_unlock_irqrestore(&hw->lock, flags); for (i = hw->driver_data.max_st_ports - 1; i >= 0; i--) { hw->l1[i].enabled = 0; hisax_unregister(&hw->l1[i].d_if); del_timer(&hw->l1[i].l1_timer); skb_queue_purge(&hw->l1[i].d_tx_queue); skb_queue_purge(&hw->l1[i].b_ch[0].tx_queue); skb_queue_purge(&hw->l1[i].b_ch[1].tx_queue); } chipreset(hw); }} /* hfc_hardware_enable *//******************************************//* disable memory mapped ports / io ports *//******************************************/static voidrelease_pci_ports(hfc4s8s_hw * hw){ pci_write_config_word(hw->pdev, PCI_COMMAND, 0);#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM if (hw->membase) iounmap((void *) hw->membase);#else if (hw->iobase) release_region(hw->iobase, 8);#endif}/*****************************************//* enable memory mapped ports / io ports *//*****************************************/static voidenable_pci_ports(hfc4s8s_hw * hw){#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_MEMIO);#else pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_REGIO);#endif}/*************************************//* initialise the HFC-4s/8s hardware *//* return 0 on success. *//*************************************/static int __devinitsetup_instance(hfc4s8s_hw * hw){ int err = -EIO; int i; for (i = 0; i < HFC_MAX_ST; i++) { struct hfc4s8s_l1 *l1p; l1p = hw->l1 + i; spin_lock_init(&l1p->lock); l1p->hw = hw; l1p->l1_timer.function = (void *) hfc_l1_timer; l1p->l1_timer.data = (long) (l1p); init_timer(&l1p->l1_timer); l1p->st_num = i; skb_queue_head_init(&l1p->d_tx_queue); l1p->d_if.ifc.priv = hw->l1 + i; l1p->d_if.ifc.l2l1 = (void *) dch_l2l1; spin_lock_init(&l1p->b_ch[0].lock); l1p->b_ch[0].b_if.ifc.l2l1 = (void *) bch_l2l1; l1p->b_ch[0].b_if.ifc.priv = (void *) &l1p->b_ch[0]; l1p->b_ch[0].l1p = hw->l1 + i; l1p->b_ch[0].bchan = 1; l1p->b_table[0] = &l1p->b_ch[0].b_if; skb_queue_head_init(&l1p->b_ch[0].tx_queue); spin_lock_init(&l1p->b_ch[1].lock); l1p->b_ch[1].b_if.ifc.l2l1 = (void *) bch_l2l1; l1p->b_ch[1].b_if.ifc.priv = (void *) &l1p->b_ch[1]; l1p->b_ch[1].l1p = hw->l1 + i; l1p->b_ch[1].bchan = 2; l1p->b_table[1] = &l1p->b_ch[1].b_if; skb_queue_head_init(&l1p->b_ch[1].tx_queue); } enable_pci_ports(hw); chipreset(hw); i = Read_hfc8(hw, R_CHIP_ID) >> CHIP_ID_SHIFT; if (i != hw->driver_data.chip_id) { printk(KERN_INFO "HFC-4S/8S: invalid chip id 0x%x instead of 0x%x, card ignored\n", i, hw->driver_data.chip_id); goto out; } i = Read_hfc8(hw, R_CHIP_RV) & 0xf; if (!i) { printk(KERN_INFO "HFC-4S/8S: chip revision 0 not supported, card ignored\n"); goto out; } INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw); if (request_irq (hw->irq, hfc4s8s_interrupt, SA_SHIRQ, hw->card_name, hw)) { printk(KERN_INFO "HFC-4S/8S: unable to alloc irq %d, card ignored\n", hw->irq); goto out; }#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM printk(KERN_INFO "HFC-4S/8S: found PCI card at membase 0x%p, irq %d\n", hw->hw_membase, hw->irq);#else printk(KERN_INFO "HFC-4S/8S: found PCI card at iobase 0x%x, irq %d\n", hw->iobase, hw->irq);#endif hfc_hardware_enable(hw, 1, 0); return (0); out: hw->irq = 0; release_pci_ports(hw); kfree(hw); return (err);}/*****************************************//* PCI hotplug interface: probe new card *//*****************************************/static int __devinithfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ int err = -ENOMEM; hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data; hfc4s8s_hw *hw; if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) { printk(KERN_ERR "No kmem for HFC-4S/8S card\n"); return (err); } memset(hw, 0, sizeof(hfc4s8s_hw)); hw->pdev = pdev; err = pci_enable_device(pdev); if (err) goto out; hw->cardnum = card_cnt; sprintf(hw->card_name, "hfc4s8s_%d", hw->cardnum); printk(KERN_INFO "HFC-4S/8S: found adapter %s (%s) at %s\n", driver_data->device_name, hw->card_name, pci_name(pdev)); spin_lock_init(&hw->lock); hw->driver_data = *driver_data; hw->irq = pdev->irq; hw->iobase = pci_resource_start(pdev, 0);#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM hw->hw_membase = (u_char *) pci_resource_start(pdev, 1); hw->membase = ioremap((ulong) hw->hw_membase, 256);#else if (!request_region(hw->iobase, 8, hw->card_name)) { printk(KERN_INFO "HFC-4S/8S: failed to rquest address space at 0x%04x\n", hw->iobase); goto out; }#endif pci_set_drvdata(pdev, hw); err = setup_instance(hw); if (!err) card_cnt++; return (err); out: kfree(hw); return (err);}/**************************************//* PCI hotplug interface: remove card *//**************************************/static void __devexithfc4s8s_remove(struct pci_dev *pdev){ hfc4s8s_hw *hw = pci_get_drvdata(pdev); printk(KERN_INFO "HFC-4S/8S: removing card %d\n", hw->cardnum); hfc_hardware_enable(hw, 0, 0); if (hw->irq) free_irq(hw->irq, hw); hw->irq = 0; release_pci_ports(hw); card_cnt--; pci_disable_device(pdev); kfree(hw); return;}static struct pci_driver hfc4s8s_driver = { name:"hfc4s8s_l1", probe:hfc4s8s_probe, remove:__devexit_p(hfc4s8s_remove), id_table:hfc4s8s_ids,};/**********************//* driver Module init *//**********************/static int __inithfc4s8s_module_init(void){ int err; printk(KERN_INFO "HFC-4S/8S: Layer 1 driver module for HFC-4S/8S isdn chips, %s\n", hfc4s8s_rev); printk(KERN_INFO "HFC-4S/8S: (C) 2003 Cornelius Consult, www.cornelius-consult.de\n"); card_cnt = 0; err = pci_register_driver(&hfc4s8s_driver); if (err < 0) { goto out; } printk(KERN_INFO "HFC-4S/8S: found %d cards\n", card_cnt);#if !defined(CONFIG_HOTPLUG) if (err == 0) { err = -ENODEV; pci_unregister_driver(&hfc4s8s_driver); goto out; }#endif return 0; out: return (err);} /* hfc4s8s_init_hw *//*************************************//* driver module exit : *//* release the HFC-4s/8s hardware *//*************************************/static voidhfc4s8s_module_exit(void){ pci_unregister_driver(&hfc4s8s_driver); printk(KERN_INFO "HFC-4S/8S: module removed\n");} /* hfc4s8s_release_hw */module_init(hfc4s8s_module_init);module_exit(hfc4s8s_module_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -