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

📄 avm_pci.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (cs->subtyp == AVM_FRITZ_PCI) {		stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);	} else {		stat = ReadHDLCPnP(cs, 0, HDLC_STATUS);		if (stat & HDLC_INT_RPR)			stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS+1))<<8;	}	if (stat & HDLC_INT_MASK) {		if (!(bcs = Sel_BCS(cs, 0))) {			if (cs->debug)				debugl1(cs, "hdlc spurious channel 0 IRQ");		} else			HDLC_irq(bcs, stat);	}	if (cs->subtyp == AVM_FRITZ_PCI) {		stat = ReadHDLCPCI(cs, 1, HDLC_STATUS);	} else {		stat = ReadHDLCPnP(cs, 1, HDLC_STATUS);		if (stat & HDLC_INT_RPR)			stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS+1))<<8;	}	if (stat & HDLC_INT_MASK) {		if (!(bcs = Sel_BCS(cs, 1))) {			if (cs->debug)				debugl1(cs, "hdlc spurious channel 1 IRQ");		} else			HDLC_irq(bcs, stat);	}}static voidhdlc_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->hw.hdlc.count = 0;				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 "hdlc_l2l1: this shouldn't happen\n");			} else {				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);				bcs->tx_skb = skb;				bcs->hw.hdlc.count = 0;				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);			modehdlc(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);			modehdlc(bcs, 0, st->l1.bc);			spin_unlock_irqrestore(&bcs->cs->lock, flags);			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);			break;	}}static voidclose_hdlcstate(struct BCState *bcs){	modehdlc(bcs, 0, 0);	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {		kfree(bcs->hw.hdlc.rcvbuf);		bcs->hw.hdlc.rcvbuf = NULL;		kfree(bcs->blog);		bcs->blog = NULL;		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);		}	}}static intopen_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs){	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {		if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {			printk(KERN_WARNING			       "HiSax: No memory for hdlc.rcvbuf\n");			return (1);		}		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {			printk(KERN_WARNING				"HiSax: No memory for bcs->blog\n");			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);			kfree(bcs->hw.hdlc.rcvbuf);			bcs->hw.hdlc.rcvbuf = NULL;			return (2);		}		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->hw.hdlc.rcvidx = 0;	bcs->tx_cnt = 0;	return (0);}static intsetstack_hdlc(struct PStack *st, struct BCState *bcs){	bcs->channel = st->l1.bc;	if (open_hdlcstate(st->l1.hardware, bcs))		return (-1);	st->l1.bcs = bcs;	st->l2.l2l1 = hdlc_l2l1;	setstack_manager(st);	bcs->st = st;	setstack_l1_B(st);	return (0);}#if 0void __initclear_pending_hdlc_ints(struct IsdnCardState *cs){	u_int val;	if (cs->subtyp == AVM_FRITZ_PCI) {		val = ReadHDLCPCI(cs, 0, HDLC_STATUS);		debugl1(cs, "HDLC 1 STA %x", val);		val = ReadHDLCPCI(cs, 1, HDLC_STATUS);		debugl1(cs, "HDLC 2 STA %x", val);	} else {		val = ReadHDLCPnP(cs, 0, HDLC_STATUS);		debugl1(cs, "HDLC 1 STA %x", val);		val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1);		debugl1(cs, "HDLC 1 RML %x", val);		val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2);		debugl1(cs, "HDLC 1 MODE %x", val);		val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3);		debugl1(cs, "HDLC 1 VIN %x", val);		val = ReadHDLCPnP(cs, 1, HDLC_STATUS);		debugl1(cs, "HDLC 2 STA %x", val);		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1);		debugl1(cs, "HDLC 2 RML %x", val);		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2);		debugl1(cs, "HDLC 2 MODE %x", val);		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);		debugl1(cs, "HDLC 2 VIN %x", val);	}}#endif  /*  0  */static voidinithdlc(struct IsdnCardState *cs){	cs->bcs[0].BC_SetStack = setstack_hdlc;	cs->bcs[1].BC_SetStack = setstack_hdlc;	cs->bcs[0].BC_Close = close_hdlcstate;	cs->bcs[1].BC_Close = close_hdlcstate;	modehdlc(cs->bcs, -1, 0);	modehdlc(cs->bcs + 1, -1, 1);}static irqreturn_tavm_pcipnp_interrupt(int intno, void *dev_id){	struct IsdnCardState *cs = dev_id;	u_long flags;	u_char val;	u_char sval;	spin_lock_irqsave(&cs->lock, flags);	sval = inb(cs->hw.avm.cfg_reg + 2);	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {		/* possible a shared  IRQ reqest */		spin_unlock_irqrestore(&cs->lock, flags);		return IRQ_NONE;	}	if (!(sval & AVM_STATUS0_IRQ_ISAC)) {		val = ReadISAC(cs, ISAC_ISTA);		isac_interrupt(cs, val);	}	if (!(sval & AVM_STATUS0_IRQ_HDLC)) {		HDLC_irq_main(cs);	}	WriteISAC(cs, ISAC_MASK, 0xFF);	WriteISAC(cs, ISAC_MASK, 0x0);	spin_unlock_irqrestore(&cs->lock, flags);	return IRQ_HANDLED;}static voidreset_avmpcipnp(struct IsdnCardState *cs){	printk(KERN_INFO "AVM PCI/PnP: reset\n");	outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);	mdelay(10);	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);	outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);	mdelay(10);	printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));}static intAVM_card_msg(struct IsdnCardState *cs, int mt, void *arg){	u_long flags;	switch (mt) {		case CARD_RESET:			spin_lock_irqsave(&cs->lock, flags);			reset_avmpcipnp(cs);			spin_unlock_irqrestore(&cs->lock, flags);			return(0);		case CARD_RELEASE:			outb(0, cs->hw.avm.cfg_reg + 2);			release_region(cs->hw.avm.cfg_reg, 32);			return(0);		case CARD_INIT:			spin_lock_irqsave(&cs->lock, flags);			reset_avmpcipnp(cs);			clear_pending_isac_ints(cs);			initisac(cs);			inithdlc(cs);			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,				cs->hw.avm.cfg_reg + 2);			WriteISAC(cs, ISAC_MASK, 0);			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |				AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);			/* RESET Receiver and Transmitter */			WriteISAC(cs, ISAC_CMDR, 0x41);			spin_unlock_irqrestore(&cs->lock, flags);			return(0);		case CARD_TEST:			return(0);	}	return(0);}static int __devinit avm_setup_rest(struct IsdnCardState *cs){	u_int val, ver;	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;	if (!request_region(cs->hw.avm.cfg_reg, 32,		(cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {		printk(KERN_WARNING		       "HiSax: Fritz!PCI/PNP config port %x-%x already in use\n",		       cs->hw.avm.cfg_reg,		       cs->hw.avm.cfg_reg + 31);		return (0);	}	switch (cs->subtyp) {	  case AVM_FRITZ_PCI:		val = inl(cs->hw.avm.cfg_reg);		printk(KERN_INFO "AVM PCI: stat %#x\n", val);		printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",			val & 0xff, (val>>8) & 0xff);		cs->BC_Read_Reg = &ReadHDLC_s;		cs->BC_Write_Reg = &WriteHDLC_s;		break;	  case AVM_FRITZ_PNP:		val = inb(cs->hw.avm.cfg_reg);		ver = inb(cs->hw.avm.cfg_reg + 1);		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);		cs->BC_Read_Reg = &ReadHDLCPnP;		cs->BC_Write_Reg = &WriteHDLCPnP;		break;	  default:	  	printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);	  	return(0);	}	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",		cs->irq, cs->hw.avm.cfg_reg);	setup_isac(cs);	cs->readisac = &ReadISAC;	cs->writeisac = &WriteISAC;	cs->readisacfifo = &ReadISACfifo;	cs->writeisacfifo = &WriteISACfifo;	cs->BC_Send_Data = &hdlc_fill_fifo;	cs->cardmsg = &AVM_card_msg;	cs->irq_func = &avm_pcipnp_interrupt;	cs->writeisac(cs, ISAC_MASK, 0xFF);	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");	return (1);}#ifndef __ISAPNP__static int __devinit avm_pnp_setup(struct IsdnCardState *cs){	return(1);	/* no-op: success */}#elsestatic struct pnp_card *pnp_avm_c __devinitdata = NULL;static int __devinit avm_pnp_setup(struct IsdnCardState *cs){	struct pnp_dev *pnp_avm_d = NULL;	if (!isapnp_present())		return(1);	/* no-op: success */	if ((pnp_avm_c = pnp_find_card(		ISAPNP_VENDOR('A', 'V', 'M'),		ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {		if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,			ISAPNP_VENDOR('A', 'V', 'M'),			ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {			int err;			pnp_disable_dev(pnp_avm_d);			err = pnp_activate_dev(pnp_avm_d);			if (err<0) {				printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",					__FUNCTION__, err);				return(0);			}			cs->hw.avm.cfg_reg =				pnp_port_start(pnp_avm_d, 0);			cs->irq = pnp_irq(pnp_avm_d, 0);			if (!cs->irq) {				printk(KERN_ERR "FritzPnP:No IRQ\n");				return(0);			}			if (!cs->hw.avm.cfg_reg) {				printk(KERN_ERR "FritzPnP:No IO address\n");				return(0);			}			cs->subtyp = AVM_FRITZ_PNP;			return (2);	/* goto 'ready' label */		}	}	return (1);}#endif /* __ISAPNP__ */#ifndef CONFIG_PCI_LEGACYstatic int __devinit avm_pci_setup(struct IsdnCardState *cs){	return(1);	/* no-op: success */}#elsestatic struct pci_dev *dev_avm __devinitdata = NULL;static int __devinit avm_pci_setup(struct IsdnCardState *cs){	if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,		PCI_DEVICE_ID_AVM_A1, dev_avm))) {		if (pci_enable_device(dev_avm))			return(0);		cs->irq = dev_avm->irq;		if (!cs->irq) {			printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");			return(0);		}		cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);		if (!cs->hw.avm.cfg_reg) {			printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");			return(0);		}		cs->subtyp = AVM_FRITZ_PCI;	} else {		printk(KERN_WARNING "FritzPCI: No PCI card found\n");		return(0);	}	cs->irq_flags |= IRQF_SHARED;	return (1);}#endif /* CONFIG_PCI_LEGACY */int __devinitsetup_avm_pcipnp(struct IsdnCard *card){	struct IsdnCardState *cs = card->cs;	char tmp[64];	int rc;	strcpy(tmp, avm_pci_rev);	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));	if (cs->typ != ISDN_CTYPE_FRITZPCI)		return (0);	if (card->para[1]) {		/* old manual method */		cs->hw.avm.cfg_reg = card->para[1];		cs->irq = card->para[0];		cs->subtyp = AVM_FRITZ_PNP;		goto ready;	}	rc = avm_pnp_setup(cs);	if (rc < 1)		return (0);	if (rc == 2)		goto ready;	rc = avm_pci_setup(cs);	if (rc < 1)		return (0);ready:	return avm_setup_rest(cs);}

⌨️ 快捷键说明

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