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

📄 hisax_fcpcipnp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Here we lost an TX interrupt, so	 * restart transmitting the whole frame.	 */	bcs->ctrl.sr.xml = 0;	bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;	adapter->write_ctrl(bcs, 1);	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;	if (!bcs->tx_skb) {		DBG(0x10, "XDU without skb");		adapter->write_ctrl(bcs, 1);		return;	}	/* only hdlc restarts the frame, transparent mode must continue */	if (bcs->mode == L1_MODE_HDLC) {		skb_push(bcs->tx_skb, bcs->tx_cnt);		bcs->tx_cnt = 0;	}}static inline void hdlc_xpr_irq(struct fritz_bcs *bcs){	struct sk_buff *skb;	skb = bcs->tx_skb;	if (!skb)		return;	if (skb->len) {		hdlc_fill_fifo(bcs);		return;	}	bcs->tx_cnt = 0;	bcs->tx_skb = NULL;	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);	dev_kfree_skb_irq(skb);}static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat){	DBG(0x10, "ch%d stat %#x", bcs->channel, stat);	if (stat & HDLC_INT_RPR) {		DBG(0x10, "RPR");		hdlc_rpr_irq(bcs, stat);	}	if (stat & HDLC_INT_XDU) {		DBG(0x10, "XDU");		hdlc_xdu_irq(bcs);		hdlc_xpr_irq(bcs);		return;	}	if (stat & HDLC_INT_XPR) {		DBG(0x10, "XPR");		hdlc_xpr_irq(bcs);	}}static inline void hdlc_irq(struct fritz_adapter *adapter){	int nr;	u32 stat;	for (nr = 0; nr < 2; nr++) {		stat = adapter->read_hdlc_status(adapter, nr);		DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);		if (stat & HDLC_INT_MASK)			hdlc_irq_one(&adapter->bcs[nr], stat);	}}static void modehdlc(struct fritz_bcs *bcs, int mode){	struct fritz_adapter *adapter = bcs->adapter;		DBG(0x40, "hdlc %c mode %d --> %d",	    'A' + bcs->channel, bcs->mode, mode);	if (bcs->mode == mode)		return;	bcs->fifo_size = 32;	bcs->ctrl.ctrl = 0;	bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;	switch (mode) {	case L1_MODE_NULL:		bcs->ctrl.sr.mode = HDLC_MODE_TRANS;		adapter->write_ctrl(bcs, 5);		break;	case L1_MODE_TRANS:	case L1_MODE_HDLC:		bcs->rcvidx = 0;		bcs->tx_cnt = 0;		bcs->tx_skb = NULL;		if (mode == L1_MODE_TRANS) {			bcs->ctrl.sr.mode = HDLC_MODE_TRANS;		} else {			bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;		}		adapter->write_ctrl(bcs, 5);		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;		adapter->write_ctrl(bcs, 1);		bcs->ctrl.sr.cmd = 0;		break;	}	bcs->mode = mode;}static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg){	struct fritz_bcs *bcs = ifc->priv;	struct sk_buff *skb = arg;	int mode;	DBG(0x10, "pr %#x", pr);	switch (pr) {	case PH_DATA | REQUEST:		if (bcs->tx_skb)			BUG();				bcs->tx_skb = skb;		DBG_SKB(1, skb);		hdlc_fill_fifo(bcs);		break;	case PH_ACTIVATE | REQUEST:		mode = (int) arg;		DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);		modehdlc(bcs, mode);		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);		break;	case PH_DEACTIVATE | REQUEST:		DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);		modehdlc(bcs, L1_MODE_NULL);		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);		break;	}}// ----------------------------------------------------------------------static irqreturn_tfcpci2_irq(int intno, void *dev, struct pt_regs *regs){	struct fritz_adapter *adapter = dev;	unsigned char val;	val = inb(adapter->io + AVM_STATUS0);	if (!(val & AVM_STATUS0_IRQ_MASK))		/* hopefully a shared  IRQ reqest */		return IRQ_NONE;	DBG(2, "STATUS0 %#x", val);	if (val & AVM_STATUS0_IRQ_ISAC)		isacsx_irq(&adapter->isac);	if (val & AVM_STATUS0_IRQ_HDLC)		hdlc_irq(adapter);	if (val & AVM_STATUS0_IRQ_ISAC)		isacsx_irq(&adapter->isac);	return IRQ_HANDLED;}static irqreturn_tfcpci_irq(int intno, void *dev, struct pt_regs *regs){	struct fritz_adapter *adapter = dev;	unsigned char sval;	sval = inb(adapter->io + 2);	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)		/* possibly a shared  IRQ reqest */		return IRQ_NONE;	DBG(2, "sval %#x", sval);	if (!(sval & AVM_STATUS0_IRQ_ISAC))		isac_irq(&adapter->isac);	if (!(sval & AVM_STATUS0_IRQ_HDLC))		hdlc_irq(adapter);	return IRQ_HANDLED;}// ----------------------------------------------------------------------static inline void fcpci2_init(struct fritz_adapter *adapter){	outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);	outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);}static inline void fcpci_init(struct fritz_adapter *adapter){	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | 	     AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);	outb(AVM_STATUS1_ENA_IOM | adapter->irq, 	     adapter->io + AVM_STATUS1);	mdelay(10);}// ----------------------------------------------------------------------static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter){	u32 val = 0;	int retval;	DBG(1,"");	isac_init(&adapter->isac); // FIXME is this okay now	retval = -EBUSY;	if (!request_region(adapter->io, 32, "fcpcipnp"))		goto err;	switch (adapter->type) {	case AVM_FRITZ_PCIV2:		retval = request_irq(adapter->irq, fcpci2_irq, SA_SHIRQ, 				     "fcpcipnp", adapter);		break;	case AVM_FRITZ_PCI:		retval = request_irq(adapter->irq, fcpci_irq, SA_SHIRQ,				     "fcpcipnp", adapter);		break;	case AVM_FRITZ_PNP:		retval = request_irq(adapter->irq, fcpci_irq, 0,				     "fcpcipnp", adapter);		break;	}	if (retval)		goto err_region;	switch (adapter->type) {	case AVM_FRITZ_PCIV2:	case AVM_FRITZ_PCI:		val = inl(adapter->io);		break;	case AVM_FRITZ_PNP:		val = inb(adapter->io);		val |= inb(adapter->io + 1) << 8;		break;	}	DBG(1, "stat %#x Class %X Rev %d",	    val, val & 0xff, (val>>8) & 0xff);	spin_lock_init(&adapter->hw_lock);	adapter->isac.priv = adapter;	switch (adapter->type) {	case AVM_FRITZ_PCIV2:		adapter->isac.read_isac       = &fcpci2_read_isac;		adapter->isac.write_isac      = &fcpci2_write_isac;		adapter->isac.read_isac_fifo  = &fcpci2_read_isac_fifo;		adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;		adapter->read_hdlc_status     = &fcpci2_read_hdlc_status;		adapter->write_ctrl           = &fcpci2_write_ctrl;		break;	case AVM_FRITZ_PCI:		adapter->isac.read_isac       = &fcpci_read_isac;		adapter->isac.write_isac      = &fcpci_write_isac;		adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;		adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;		adapter->read_hdlc_status     = &fcpci_read_hdlc_status;		adapter->write_ctrl           = &fcpci_write_ctrl;		break;	case AVM_FRITZ_PNP:		adapter->isac.read_isac       = &fcpci_read_isac;		adapter->isac.write_isac      = &fcpci_write_isac;		adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;		adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;		adapter->read_hdlc_status     = &fcpnp_read_hdlc_status;		adapter->write_ctrl           = &fcpnp_write_ctrl;		break;	}	// Reset	outb(0, adapter->io + AVM_STATUS0);	mdelay(10);	outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);	mdelay(10);	outb(0, adapter->io + AVM_STATUS0);	mdelay(10);	switch (adapter->type) {	case AVM_FRITZ_PCIV2:		fcpci2_init(adapter);		isacsx_setup(&adapter->isac);		break;	case AVM_FRITZ_PCI:	case AVM_FRITZ_PNP:		fcpci_init(adapter);		isac_setup(&adapter->isac);		break;	}	val = adapter->read_hdlc_status(adapter, 0);	DBG(0x20, "HDLC A STA %x", val);	val = adapter->read_hdlc_status(adapter, 1);	DBG(0x20, "HDLC B STA %x", val);	adapter->bcs[0].mode = -1;	adapter->bcs[1].mode = -1;	modehdlc(&adapter->bcs[0], L1_MODE_NULL);	modehdlc(&adapter->bcs[1], L1_MODE_NULL);	return 0; err_region:	release_region(adapter->io, 32); err:	return retval;}static void __devexit fcpcipnp_release(struct fritz_adapter *adapter){	DBG(1,"");	outb(0, adapter->io + AVM_STATUS0);	free_irq(adapter->irq, adapter);	release_region(adapter->io, 32);}// ----------------------------------------------------------------------static struct fritz_adapter * __devinit new_adapter(void){	struct fritz_adapter *adapter;	struct hisax_b_if *b_if[2];	int i;	adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL);	if (!adapter)		return NULL;	memset(adapter, 0, sizeof(struct fritz_adapter));	adapter->isac.hisax_d_if.owner = THIS_MODULE;	adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;	adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;		for (i = 0; i < 2; i++) {		adapter->bcs[i].adapter = adapter;		adapter->bcs[i].channel = i;		adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];		adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;	}	for (i = 0; i < 2; i++)		b_if[i] = &adapter->bcs[i].b_if;	hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp", protocol);	return adapter;}static void delete_adapter(struct fritz_adapter *adapter){	hisax_unregister(&adapter->isac.hisax_d_if);	kfree(adapter);}static int __devinit fcpci_probe(struct pci_dev *pdev,				 const struct pci_device_id *ent){	struct fritz_adapter *adapter;	int retval;	retval = -ENOMEM;	adapter = new_adapter();	if (!adapter)		goto err;	pci_set_drvdata(pdev, adapter);	if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) 		adapter->type = AVM_FRITZ_PCIV2;	else		adapter->type = AVM_FRITZ_PCI;	retval = pci_enable_device(pdev);	if (retval)		goto err_free;	adapter->io = pci_resource_start(pdev, 1);	adapter->irq = pdev->irq;	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",	       (char *) ent->driver_data, pci_name(pdev));	retval = fcpcipnp_setup(adapter);	if (retval)		goto err_free;	return 0;	 err_free:	delete_adapter(adapter); err:	return retval;}#ifdef __ISAPNP__static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id){	struct fritz_adapter *adapter;	int retval;	if (!pdev)		return(-ENODEV);	retval = -ENOMEM;	adapter = new_adapter();	if (!adapter)		goto err;	pnp_set_drvdata(pdev, adapter);	adapter->type = AVM_FRITZ_PNP;	pnp_disable_dev(pdev);	retval = pnp_activate_dev(pdev);	if (retval < 0) {		printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,			(char *)dev_id->driver_data, retval);		goto err_free;	}	adapter->io = pnp_port_start(pdev, 0);	adapter->irq = pnp_irq(pdev, 0);	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",	       (char *) dev_id->driver_data, adapter->io, adapter->irq);	retval = fcpcipnp_setup(adapter);	if (retval)		goto err_free;	return 0;	 err_free:	delete_adapter(adapter); err:	return retval;}static void __devexit fcpnp_remove(struct pnp_dev *pdev){	struct fritz_adapter *adapter = pnp_get_drvdata(pdev);	if (adapter) {		fcpcipnp_release(adapter);		delete_adapter(adapter);	}	pnp_disable_dev(pdev);}static struct pnp_driver fcpnp_driver = {	.name		= "fcpnp",	.probe		= fcpnp_probe,	.remove		= __devexit_p(fcpnp_remove),	.id_table	= fcpnp_ids,};#endifstatic void __devexit fcpci_remove(struct pci_dev *pdev){	struct fritz_adapter *adapter = pci_get_drvdata(pdev);	fcpcipnp_release(adapter);	pci_disable_device(pdev);	delete_adapter(adapter);}static struct pci_driver fcpci_driver = {	.name		= "fcpci",	.probe		= fcpci_probe,	.remove		= __devexit_p(fcpci_remove),	.id_table	= fcpci_ids,};static int __init hisax_fcpcipnp_init(void){	int retval;	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");	retval = pci_register_driver(&fcpci_driver);	if (retval)		goto out;#ifdef __ISAPNP__	retval = pnp_register_driver(&fcpnp_driver);	if (retval < 0)		goto out_unregister_pci;#endif	return 0; out_unregister_pci:	pci_unregister_driver(&fcpci_driver); out:	return retval;}static void __exit hisax_fcpcipnp_exit(void){#ifdef __ISAPNP__	pnp_unregister_driver(&fcpnp_driver);#endif	pci_unregister_driver(&fcpci_driver);}module_init(hisax_fcpcipnp_init);module_exit(hisax_fcpcipnp_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -