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

📄 avm_pci.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
							bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);						skb_queue_tail(&bcs->rqueue, skb);					}					bcs->hw.hdlc.rcvidx = 0;					hdlc_sched_event(bcs, B_RCVBUFREADY);				} else {					if (bcs->cs->debug & L1_DEB_HSCX)						debugl1(bcs->cs, "invalid frame");					else						debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);					bcs->hw.hdlc.rcvidx = 0;				}			}		}	}	if (stat & HDLC_INT_XDU) {		/* Here we lost an TX interrupt, so		 * restart transmitting the whole frame.		 */		if (bcs->tx_skb) {			skb_push(bcs->tx_skb, bcs->hw.hdlc.count);			bcs->tx_cnt += bcs->hw.hdlc.count;			bcs->hw.hdlc.count = 0;//			hdlc_sched_event(bcs, B_XMTBUFREADY);			if (bcs->cs->debug & L1_DEB_WARN)				debugl1(bcs->cs, "ch%d XDU", bcs->channel);		} else if (bcs->cs->debug & L1_DEB_WARN)			debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);		bcs->hw.hdlc.ctrl.sr.xml = 0;		bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;		write_ctrl(bcs, 1);		bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;		write_ctrl(bcs, 1);		hdlc_fill_fifo(bcs);	} else if (stat & HDLC_INT_XPR) {		if (bcs->tx_skb) {			if (bcs->tx_skb->len) {				hdlc_fill_fifo(bcs);				return;			} else {				if (bcs->st->lli.l1writewakeup &&					(PACKET_NOACK != bcs->tx_skb->pkt_type))					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count);				dev_kfree_skb_irq(bcs->tx_skb);				bcs->hw.hdlc.count = 0;				bcs->tx_skb = NULL;			}		}		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {			bcs->hw.hdlc.count = 0;			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);			hdlc_fill_fifo(bcs);		} else {			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);			hdlc_sched_event(bcs, B_XMTBUFREADY);		}	}}inline voidHDLC_irq_main(struct IsdnCardState *cs){	u_int stat;	long  flags;	struct BCState *bcs;	save_flags(flags);	cli();	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);	}	restore_flags(flags);}voidhdlc_l2l1(struct PStack *st, int pr, void *arg){	struct sk_buff *skb = arg;	long flags;	switch (pr) {		case (PH_DATA | REQUEST):			save_flags(flags);			cli();			if (st->l1.bcs->tx_skb) {				skb_queue_tail(&st->l1.bcs->squeue, skb);				restore_flags(flags);			} else {				st->l1.bcs->tx_skb = skb;				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);				st->l1.bcs->hw.hdlc.count = 0;				restore_flags(flags);				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);			}			break;		case (PH_PULL | INDICATION):			if (st->l1.bcs->tx_skb) {				printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");				break;			}			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);			st->l1.bcs->tx_skb = skb;			st->l1.bcs->hw.hdlc.count = 0;			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);			break;		case (PH_PULL | REQUEST):			if (!st->l1.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):			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);			modehdlc(st->l1.bcs, st->l1.mode, st->l1.bc);			l1_msg_b(st, pr, arg);			break;		case (PH_DEACTIVATE | REQUEST):			l1_msg_b(st, pr, arg);			break;		case (PH_DEACTIVATE | CONFIRM):			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);			modehdlc(st->l1.bcs, 0, st->l1.bc);			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);			break;	}}voidclose_hdlcstate(struct BCState *bcs){	modehdlc(bcs, 0, 0);	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {		if (bcs->hw.hdlc.rcvbuf) {			kfree(bcs->hw.hdlc.rcvbuf);			bcs->hw.hdlc.rcvbuf = NULL;		}		if (bcs->blog) {			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);		}	}}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);}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);}void __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);	}}void __initinithdlc(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 voidavm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs){	struct IsdnCardState *cs = dev_id;	u_char val;	u_char sval;	if (!cs) {		printk(KERN_WARNING "AVM PCI: Spurious interrupt!\n");		return;	}	sval = inb(cs->hw.avm.cfg_reg + 2);	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)		/* possible a shared  IRQ reqest */		return;	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);}static voidreset_avmpcipnp(struct IsdnCardState *cs){	long flags;	printk(KERN_INFO "AVM PCI/PnP: reset\n");	save_flags(flags);	sti();	outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */	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);	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */	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){	switch (mt) {		case CARD_RESET:			reset_avmpcipnp(cs);			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:			clear_pending_isac_ints(cs);			initisac(cs);			clear_pending_hdlc_ints(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);			return(0);		case CARD_TEST:			return(0);	}	return(0);}static struct pci_dev *dev_avm __initdata = NULL;int __initsetup_avm_pcipnp(struct IsdnCard *card){	u_int val, ver;	struct IsdnCardState *cs = card->cs;	char tmp[64];	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]) {		cs->hw.avm.cfg_reg = card->para[1];		cs->irq = card->para[0];		cs->subtyp = AVM_FRITZ_PNP;	} else {#if CONFIG_PCI		if (!pci_present()) {			printk(KERN_ERR "FritzPCI: no PCI bus present\n");			return(0);		}		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {			cs->irq = dev_avm->irq;			if (!cs->irq) {				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");				return(0);			}			if (pci_enable_device(dev_avm))				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 |= SA_SHIRQ;#else		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");		return (0);#endif /* CONFIG_PCI */	}	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;	if (check_region((cs->hw.avm.cfg_reg), 32)) {		printk(KERN_WARNING		       "HiSax: %s config port %x-%x already in use\n",		       CardType[card->typ],		       cs->hw.avm.cfg_reg,		       cs->hw.avm.cfg_reg + 31);		return (0);	} else {		request_region(cs->hw.avm.cfg_reg, 32,			(cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP");	}	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);		reset_avmpcipnp(cs);		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);	cs->readisac = &ReadISAC;	cs->writeisac = &WriteISAC;	cs->readisacfifo = &ReadISACfifo;	cs->writeisacfifo = &WriteISACfifo;	cs->BC_Send_Data = &fill_hdlc;	cs->cardmsg = &AVM_card_msg;	cs->irq_func = &avm_pcipnp_interrupt;	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");	return (1);}

⌨️ 快捷键说明

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