⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfc4s8s_l1.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
					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 + -