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

📄 w6692.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (val && icnt) {		icnt--;		goto StartW6692;	}	if (!icnt) {		printk(KERN_WARNING "W6692 IRQ LOOP\n");		cs->writeW6692(cs, W_IMASK, 0xff);	}	spin_unlock_irqrestore(&cs->lock, flags);	return IRQ_HANDLED;}static voidW6692_l1hw(struct PStack *st, int pr, void *arg){	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;	struct sk_buff *skb = arg;	u_long flags;	int val;	switch (pr) {		case (PH_DATA | REQUEST):			if (cs->debug & DEB_DLOG_HEX)				LogFrame(cs, skb->data, skb->len);			if (cs->debug & DEB_DLOG_VERBOSE)				dlogframe(cs, skb, 0);			spin_lock_irqsave(&cs->lock, flags);			if (cs->tx_skb) {				skb_queue_tail(&cs->sq, skb);#ifdef L2FRAME_DEBUG		/* psa */				if (cs->debug & L1_DEB_LAPD)					Logl2Frame(cs, skb, "PH_DATA Queued", 0);#endif			} else {				cs->tx_skb = skb;				cs->tx_cnt = 0;#ifdef L2FRAME_DEBUG		/* psa */				if (cs->debug & L1_DEB_LAPD)					Logl2Frame(cs, skb, "PH_DATA", 0);#endif				W6692_fill_fifo(cs);			}			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (PH_PULL | INDICATION):			spin_lock_irqsave(&cs->lock, flags);			if (cs->tx_skb) {				if (cs->debug & L1_DEB_WARN)					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");				skb_queue_tail(&cs->sq, skb);				spin_unlock_irqrestore(&cs->lock, flags);				break;			}			if (cs->debug & DEB_DLOG_HEX)				LogFrame(cs, skb->data, skb->len);			if (cs->debug & DEB_DLOG_VERBOSE)				dlogframe(cs, skb, 0);			cs->tx_skb = skb;			cs->tx_cnt = 0;#ifdef L2FRAME_DEBUG		/* psa */			if (cs->debug & L1_DEB_LAPD)				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);#endif			W6692_fill_fifo(cs);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (PH_PULL | REQUEST):#ifdef L2FRAME_DEBUG		/* psa */			if (cs->debug & L1_DEB_LAPD)				debugl1(cs, "-> PH_REQUEST_PULL");#endif			if (!cs->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 (HW_RESET | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) {				ph_command(cs, W_L1CMD_ECK);				spin_unlock_irqrestore(&cs->lock, flags);			} else {				ph_command(cs, W_L1CMD_RST);				cs->dc.w6692.ph_state = W_L1CMD_RST;				spin_unlock_irqrestore(&cs->lock, flags);				W6692_new_ph(cs);			}			break;		case (HW_ENABLE | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			ph_command(cs, W_L1CMD_ECK);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_INFO3 | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			ph_command(cs, W_L1CMD_AR8);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_TESTLOOP | REQUEST):			val = 0;			if (1 & (long) arg)				val |= 0x0c;			if (2 & (long) arg)				val |= 0x3;			/* !!! not implemented yet */			break;		case (HW_DEACTIVATE | RESPONSE):			skb_queue_purge(&cs->rq);			skb_queue_purge(&cs->sq);			if (cs->tx_skb) {				dev_kfree_skb_any(cs->tx_skb);				cs->tx_skb = NULL;			}			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))				del_timer(&cs->dbusytimer);			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))				schedule_event(cs, D_CLEARBUSY);			break;		default:			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "W6692_l1hw unknown %04x", pr);			break;	}}static voidsetstack_W6692(struct PStack *st, struct IsdnCardState *cs){	st->l1.l1hw = W6692_l1hw;}static voidDC_Close_W6692(struct IsdnCardState *cs){}static voiddbusy_timer_handler(struct IsdnCardState *cs){	struct PStack *stptr;	int rbch, star;	u_long flags;	spin_lock_irqsave(&cs->lock, flags);	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {		rbch = cs->readW6692(cs, W_D_RBCH);		star = cs->readW6692(cs, W_D_STAR);		if (cs->debug)			debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x",				rbch, star);		if (star & W_D_STAR_XBZ) {	/* D-Channel Busy */			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);			stptr = cs->stlist;			while (stptr != NULL) {				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);				stptr = stptr->next;			}		} else {			/* discard frame; reset transceiver */			test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);			if (cs->tx_skb) {				dev_kfree_skb_any(cs->tx_skb);				cs->tx_cnt = 0;				cs->tx_skb = NULL;			} else {				printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n");				debugl1(cs, "D-Channel Busy no skb");			}			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);	/* Transmitter reset */			spin_unlock_irqrestore(&cs->lock, flags);			cs->irq_func(cs->irq, cs, NULL);			return;		}	}	spin_unlock_irqrestore(&cs->lock, flags);}static voidW6692Bmode(struct BCState *bcs, int mode, int bchan){	struct IsdnCardState *cs = bcs->cs;	if (cs->debug & L1_DEB_HSCX)		debugl1(cs, "w6692 %c mode %d ichan %d",			'1' + bchan, mode, bchan);	bcs->mode = mode;	bcs->channel = bchan;	bcs->hw.w6692.bchan = bchan;	switch (mode) {		case (L1_MODE_NULL):			cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0);			break;		case (L1_MODE_TRANS):			cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS);			break;		case (L1_MODE_HDLC):			cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF);			cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff);			cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff);			break;	}	if (mode)		cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST |				 W_B_CMDR_RACT | W_B_CMDR_XRST);	cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00);}static voidW6692_l2l1(struct PStack *st, int pr, void *arg){	struct sk_buff *skb = arg;	struct BCState *bcs = st->l1.bcs; 	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.w6692.count = 0;				bcs->cs->BC_Send_Data(bcs);			}			spin_unlock_irqrestore(&bcs->cs->lock, flags);			break;		case (PH_PULL | INDICATION):			if (bcs->tx_skb) {				printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n");				break;			}			spin_lock_irqsave(&bcs->cs->lock, flags);			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);			bcs->tx_skb = skb;			bcs->hw.w6692.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);			W6692Bmode(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);			W6692Bmode(bcs, 0, st->l1.bc);			spin_unlock_irqrestore(&bcs->cs->lock, flags);			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);			break;	}}static voidclose_w6692state(struct BCState *bcs){	W6692Bmode(bcs, 0, bcs->channel);	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {		kfree(bcs->hw.w6692.rcvbuf);		bcs->hw.w6692.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_w6692state(struct IsdnCardState *cs, struct BCState *bcs){	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {		if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {			printk(KERN_WARNING			       "HiSax: No memory for w6692.rcvbuf\n");			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);			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.w6692.rcvbuf);			bcs->hw.w6692.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.w6692.rcvidx = 0;	bcs->tx_cnt = 0;	return (0);}static intsetstack_w6692(struct PStack *st, struct BCState *bcs){	bcs->channel = st->l1.bc;	if (open_w6692state(st->l1.hardware, bcs))		return (-1);	st->l1.bcs = bcs;	st->l2.l2l1 = W6692_l2l1;	setstack_manager(st);	bcs->st = st;	setstack_l1_B(st);	return (0);}static void resetW6692(struct IsdnCardState *cs){	cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);	mdelay(10);	cs->writeW6692(cs, W_D_CTL, 0x00);	mdelay(10);	cs->writeW6692(cs, W_IMASK, 0xff);	cs->writeW6692(cs, W_D_SAM, 0xff);	cs->writeW6692(cs, W_D_TAM, 0xff);	cs->writeW6692(cs, W_D_EXIM, 0x00);	cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);	cs->writeW6692(cs, W_IMASK, 0x18);	if (cs->subtyp == W6692_USR) {		/* seems that USR implemented some power control features		 * Pin 79 is connected to the oscilator circuit so we		 * have to handle it here		 */		cs->writeW6692(cs, W_PCTL, 0x80);		cs->writeW6692(cs, W_XDATA, 0x00);	}}static void __init initW6692(struct IsdnCardState *cs, int part){	if (part & 1) {		cs->setstack_d = setstack_W6692;		cs->DC_Close = DC_Close_W6692;		cs->dbusytimer.function = (void *) dbusy_timer_handler;		cs->dbusytimer.data = (long) cs;		init_timer(&cs->dbusytimer);		resetW6692(cs);		ph_command(cs, W_L1CMD_RST);		cs->dc.w6692.ph_state = W_L1CMD_RST;		W6692_new_ph(cs);		ph_command(cs, W_L1CMD_ECK);		cs->bcs[0].BC_SetStack = setstack_w6692;		cs->bcs[1].BC_SetStack = setstack_w6692;		cs->bcs[0].BC_Close = close_w6692state;		cs->bcs[1].BC_Close = close_w6692state;		W6692Bmode(cs->bcs, 0, 0);		W6692Bmode(cs->bcs + 1, 0, 0);	}	if (part & 2) {		/* Reenable all IRQ */		cs->writeW6692(cs, W_IMASK, 0x18);		cs->writeW6692(cs, W_D_EXIM, 0x00);		cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00);		cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00);		/* Reset D-chan receiver and transmitter */		cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);	}}/* Interface functions */static u_charReadW6692(struct IsdnCardState *cs, u_char offset){	return (inb(cs->hw.w6692.iobase + offset));}static voidWriteW6692(struct IsdnCardState *cs, u_char offset, u_char value){	outb(value, cs->hw.w6692.iobase + offset);}static voidReadISACfifo(struct IsdnCardState *cs, u_char * data, int size){	insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);}static voidWriteISACfifo(struct IsdnCardState *cs, u_char * data, int size){	outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);}static u_charReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset){	return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset));}static voidWriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value){	outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);}static intw6692_card_msg(struct IsdnCardState *cs, int mt, void *arg){	switch (mt) {		case CARD_RESET:			resetW6692(cs);			return (0);		case CARD_RELEASE:			cs->writeW6692(cs, W_IMASK, 0xff);			release_region(cs->hw.w6692.iobase, 256);			if (cs->subtyp == W6692_USR) {				cs->writeW6692(cs, W_XDATA, 0x04);			}			return (0);		case CARD_INIT:			initW6692(cs, 3);			return (0);		case CARD_TEST:			return (0);	}	return (0);}static int id_idx ;static struct pci_dev *dev_w6692 __initdata = NULL;int __init setup_w6692(struct IsdnCard *card){	struct IsdnCardState *cs = card->cs;	char tmp[64];	u_char found = 0;	u_char pci_irq = 0;	u_int pci_ioaddr = 0;	strcpy(tmp, w6692_revision);	printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));	if (cs->typ != ISDN_CTYPE_W6692)		return (0);#ifdef CONFIG_PCI	while (id_list[id_idx].vendor_id) {		dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,					    id_list[id_idx].device_id,					    dev_w6692);		if (dev_w6692) {			if (pci_enable_device(dev_w6692))				continue;			cs->subtyp = id_idx;			break;		}		id_idx++;	}	if (dev_w6692) {		found = 1;		pci_irq = dev_w6692->irq;		/* I think address 0 is allways the configuration area */		/* and address 1 is the real IO space KKe 03.09.99 */		pci_ioaddr = pci_resource_start(dev_w6692, 1);		/* USR ISDN PCI card TA need some special handling */		if (cs->subtyp == W6692_WINBOND) {			if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&			    (W6692_SD_USR == dev_w6692->subsystem_device)) {				cs->subtyp = W6692_USR;			}		}	}	if (!found) {		printk(KERN_WARNING "W6692: No PCI card found\n");		return (0);	}	cs->irq = pci_irq;	if (!cs->irq) {		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");		return (0);	}	if (!pci_ioaddr) {		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");		return (0);	}	cs->hw.w6692.iobase = pci_ioaddr;	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,	       pci_ioaddr, pci_irq);	if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) {		printk(KERN_WARNING		       "HiSax: %s I/O ports %x-%x already in use\n",		       id_list[cs->subtyp].card_name,		       cs->hw.w6692.iobase,		       cs->hw.w6692.iobase + 255);		return (0);	}#else	printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");	printk(KERN_WARNING "HiSax: W6692 unable to config\n");	return (0);#endif				/* CONFIG_PCI */	printk(KERN_INFO	       "HiSax: %s config irq:%d I/O:%x\n",	       id_list[cs->subtyp].card_name, cs->irq,	       cs->hw.w6692.iobase);	INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs);	cs->readW6692 = &ReadW6692;	cs->writeW6692 = &WriteW6692;	cs->readisacfifo = &ReadISACfifo;	cs->writeisacfifo = &WriteISACfifo;	cs->BC_Read_Reg = &ReadW6692B;	cs->BC_Write_Reg = &WriteW6692B;	cs->BC_Send_Data = &W6692B_fill_fifo;	cs->cardmsg = &w6692_card_msg;	cs->irq_func = &W6692_interrupt;	cs->irq_flags |= SA_SHIRQ;	W6692Version(cs, "W6692:");	printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA));	printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK));	printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR));	printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM));	printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA));	return (1);}

⌨️ 快捷键说明

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