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

📄 hfc_sx.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
{	struct IsdnCardState *cs = bcs->cs;	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {	  hfcsx_fill_fifo(bcs);		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);	} else		debugl1(cs, "send_data %d blocked", bcs->channel);}/***************************************************************//* activate/deactivate hardware for selected channels and mode *//***************************************************************/static voidmode_hfcsx(struct BCState *bcs, int mode, int bc){	struct IsdnCardState *cs = bcs->cs;	int fifo2;	if (cs->debug & L1_DEB_HSCX)		debugl1(cs, "HFCSX bchannel mode %d bchan %d/%d",			mode, bc, bcs->channel);	bcs->mode = mode;	bcs->channel = bc;	fifo2 = bc;	if (cs->chanlimit > 1) {		cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */		cs->hw.hfcsx.sctrl_e &= ~0x80;	} else {		if (bc) {			if (mode != L1_MODE_NULL) {				cs->hw.hfcsx.bswapped = 1;	/* B1 and B2 exchanged */				cs->hw.hfcsx.sctrl_e |= 0x80;			} else {				cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */				cs->hw.hfcsx.sctrl_e &= ~0x80;			}			fifo2 = 0;		} else {			cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */			cs->hw.hfcsx.sctrl_e &= ~0x80;		}	}	switch (mode) {		case (L1_MODE_NULL):			if (bc) {				cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;				cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;			} else {				cs->hw.hfcsx.sctrl &= ~SCTRL_B1_ENA;				cs->hw.hfcsx.sctrl_r &= ~SCTRL_B1_ENA;			}			if (fifo2) {				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);			} else {				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);			}			break;		case (L1_MODE_TRANS):			if (bc) {				cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;				cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;			} else {				cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;				cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;			}			if (fifo2) {				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);				cs->hw.hfcsx.ctmt |= 2;				cs->hw.hfcsx.conn &= ~0x18;			} else {				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);				cs->hw.hfcsx.ctmt |= 1;				cs->hw.hfcsx.conn &= ~0x03;			}			break;		case (L1_MODE_HDLC):			if (bc) {				cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;				cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;			} else {				cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;				cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;			}			if (fifo2) {				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);				cs->hw.hfcsx.ctmt &= ~2;				cs->hw.hfcsx.conn &= ~0x18;			} else {				cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);				cs->hw.hfcsx.ctmt &= ~1;				cs->hw.hfcsx.conn &= ~0x03;			}			break;		case (L1_MODE_EXTRN):			if (bc) {				cs->hw.hfcsx.conn |= 0x10;				cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;				cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);			} else {				cs->hw.hfcsx.conn |= 0x02;				cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;				cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;				cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);			}			break;	}	Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e);	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);	if (mode != L1_MODE_EXTRN) {	  reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX);	  reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX);	}}/******************************//* Layer2 -> Layer 1 Transfer *//******************************/static voidhfcsx_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->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 "hfc_l2l1: this shouldn't happen\n");			} else {//				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);				bcs->tx_skb = skb;				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);			mode_hfcsx(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);			mode_hfcsx(bcs, 0, st->l1.bc);			spin_unlock_irqrestore(&bcs->cs->lock, flags);			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);			break;	}}/******************************************//* deactivate B-channel access and queues *//******************************************/static voidclose_hfcsx(struct BCState *bcs){	mode_hfcsx(bcs, 0, bcs->channel);	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {		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);		}	}}/*************************************//* init B-channel queues and control *//*************************************/static intopen_hfcsxstate(struct IsdnCardState *cs, struct BCState *bcs){	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {		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->tx_cnt = 0;	return (0);}/*********************************//* inits the stack for B-channel *//*********************************/static intsetstack_2b(struct PStack *st, struct BCState *bcs){	bcs->channel = st->l1.bc;	if (open_hfcsxstate(st->l1.hardware, bcs))		return (-1);	st->l1.bcs = bcs;	st->l2.l2l1 = hfcsx_l2l1;	setstack_manager(st);	bcs->st = st;	setstack_l1_B(st);	return (0);}/***************************//* handle L1 state changes *//***************************/static voidhfcsx_bh(struct IsdnCardState *cs){	u_long flags;	if (!cs)		return;	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {		if (!cs->hw.hfcsx.nt_mode)			switch (cs->dc.hfcsx.ph_state) {				case (0):					l1_msg(cs, HW_RESET | INDICATION, NULL);					break;				case (3):					l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);					break;				case (8):					l1_msg(cs, HW_RSYNC | INDICATION, NULL);					break;				case (6):					l1_msg(cs, HW_INFO2 | INDICATION, NULL);					break;				case (7):					l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);					break;				default:					break;		} else {			switch (cs->dc.hfcsx.ph_state) {				case (2):					spin_lock_irqsave(&cs->lock, flags);					if (cs->hw.hfcsx.nt_timer < 0) {						cs->hw.hfcsx.nt_timer = 0;						cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;						Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);						/* Clear already pending ints */						if (Read_hfc(cs, HFCSX_INT_S1));						Write_hfc(cs, HFCSX_STATES, 4 | HFCSX_LOAD_STATE);						udelay(10);						Write_hfc(cs, HFCSX_STATES, 4);						cs->dc.hfcsx.ph_state = 4;					} else {						cs->hw.hfcsx.int_m1 |= HFCSX_INTS_TIMER;						Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);						cs->hw.hfcsx.ctmt &= ~HFCSX_AUTO_TIMER;						cs->hw.hfcsx.ctmt |= HFCSX_TIM3_125;						Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);						Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);						cs->hw.hfcsx.nt_timer = NT_T1_COUNT;						Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3);	/* allow G2 -> G3 transition */					}					spin_unlock_irqrestore(&cs->lock, flags);					break;				case (1):				case (3):				case (4):					spin_lock_irqsave(&cs->lock, flags);					cs->hw.hfcsx.nt_timer = 0;					cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;					Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);					spin_unlock_irqrestore(&cs->lock, flags);					break;				default:					break;			}		}	}	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))		DChannel_proc_rcv(cs);	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))		DChannel_proc_xmt(cs);}/********************************//* called for card init message *//********************************/static void __devinitinithfcsx(struct IsdnCardState *cs){	cs->setstack_d = setstack_hfcsx;	cs->BC_Send_Data = &hfcsx_send_data;	cs->bcs[0].BC_SetStack = setstack_2b;	cs->bcs[1].BC_SetStack = setstack_2b;	cs->bcs[0].BC_Close = close_hfcsx;	cs->bcs[1].BC_Close = close_hfcsx;	mode_hfcsx(cs->bcs, 0, 0);	mode_hfcsx(cs->bcs + 1, 0, 1);}/*******************************************//* handle card messages from control layer *//*******************************************/static inthfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg){	u_long flags;	if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "HFCSX: card_msg %x", mt);	switch (mt) {		case CARD_RESET:			spin_lock_irqsave(&cs->lock, flags);			reset_hfcsx(cs);			spin_unlock_irqrestore(&cs->lock, flags);			return (0);		case CARD_RELEASE:			release_io_hfcsx(cs);			return (0);		case CARD_INIT:			spin_lock_irqsave(&cs->lock, flags);			inithfcsx(cs);			spin_unlock_irqrestore(&cs->lock, flags);			msleep(80);				/* Timeout 80ms */			/* now switch timer interrupt off */			spin_lock_irqsave(&cs->lock, flags);			cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;			Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);			/* reinit mode reg */			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);			spin_unlock_irqrestore(&cs->lock, flags);			return (0);		case CARD_TEST:			return (0);	}	return (0);}#ifdef __ISAPNP__static struct isapnp_device_id hfc_ids[] __devinitdata = {	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),	  ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), 	  (unsigned long) "Teles 16.3c2" },	{ 0, }};static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];static struct pnp_card *pnp_c __devinitdata = NULL;#endifint __devinitsetup_hfcsx(struct IsdnCard *card){	struct IsdnCardState *cs = card->cs;	char tmp[64];	strcpy(tmp, hfcsx_revision);	printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));#ifdef __ISAPNP__	if (!card->para[1] && isapnp_present()) {		struct pnp_dev *pnp_d;		while(ipid->card_vendor) {			if ((pnp_c = pnp_find_card(ipid->card_vendor,				ipid->card_device, pnp_c))) {				pnp_d = NULL;				if ((pnp_d = pnp_find_dev(pnp_c,					ipid->vendor, ipid->function, pnp_d))) {					int err;					printk(KERN_INFO "HiSax: %s detected\n",						(char *)ipid->driver_data);					pnp_disable_dev(pnp_d);					err = pnp_activate_dev(pnp_d);					if (err<0) {						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",							__FUNCTION__, err);						return(0);					}					card->para[1] = pnp_port_start(pnp_d, 0);					card->para[0] = pnp_irq(pnp_d, 0);					if (!card->para[0] || !card->para[1]) {						printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",							card->para[0], card->para[1]);						pnp_disable_dev(pnp_d);						return(0);					}					break;				} else {					printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");				}			}			ipid++;			pnp_c = NULL;		} 		if (!ipid->card_vendor) {			printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");			return(0);		}	}#endif	cs->hw.hfcsx.base = card->para[1] & 0xfffe;	cs->irq = card->para[0];	cs->hw.hfcsx.int_s1 = 0;	cs->dc.hfcsx.ph_state = 0;	cs->hw.hfcsx.fifo = 255;	if ((cs->typ == ISDN_CTYPE_HFC_SX) || 	    (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) {	        if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) {		  printk(KERN_WARNING			 "HiSax: HFC-SX io-base %#lx already in use\n",		          cs->hw.hfcsx.base);		  return(0);		}		byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);		byteout(cs->hw.hfcsx.base + 1,			((cs->hw.hfcsx.base >> 8) & 3) | 0x54);		udelay(10);	        cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);                switch (cs->hw.hfcsx.chip >> 4) {		  case 1: 		    tmp[0] ='+';		    break;		  case 9: 		    tmp[0] ='P';		    break;		  default:		    printk(KERN_WARNING			   "HFC-SX: invalid chip id 0x%x\n",			   cs->hw.hfcsx.chip >> 4);		    release_region(cs->hw.hfcsx.base, 2);		    return(0);		}  		if (!ccd_sp_irqtab[cs->irq & 0xF]) {		  printk(KERN_WARNING 			 "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF);		  release_region(cs->hw.hfcsx.base, 2);		  return(0);		}  		if (!(cs->hw.hfcsx.extra = (void *)		      kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {		  release_region(cs->hw.hfcsx.base, 2);		  printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");		  return(0);		}		printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",			tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ);		cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */		cs->hw.hfcsx.int_m1 = 0;		Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);		Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);	} else		return (0);	/* no valid card type */	cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;	cs->dbusytimer.data = (long) cs;	init_timer(&cs->dbusytimer);	INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs);	cs->readisac = NULL;	cs->writeisac = NULL;	cs->readisacfifo = NULL;	cs->writeisacfifo = NULL;	cs->BC_Read_Reg = NULL;	cs->BC_Write_Reg = NULL;	cs->irq_func = &hfcsx_interrupt;	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;	cs->hw.hfcsx.timer.data = (long) cs;	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */	init_timer(&cs->hw.hfcsx.timer);	reset_hfcsx(cs);	cs->cardmsg = &hfcsx_card_msg;	cs->auxcmd = &hfcsx_auxcmd;	return (1);}

⌨️ 快捷键说明

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