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

📄 amd7930_fn.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	init_timer(&cs->dbusytimer);	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);	add_timer(&cs->dbusytimer);	if (cs->debug & L1_DEB_ISAC_FIFO) {		char *t = cs->dlog;		t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);		QuickHex(t, deb_ptr, count);		debugl1(cs, cs->dlog);	}	/* AMD interrupts on */        AmdIrqOn(cs);}void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags){	BYTE dsr1, dsr2, lsr;        WORD der; while (irflags) {        dsr1 = rByteAMD(cs, 0x02);        der  = rWordAMD(cs, 0x03);        dsr2 = rByteAMD(cs, 0x07);        lsr  = rByteAMD(cs, 0xA1);	if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der);        /* D error -> read DER and DSR2 bit 2 */	if (der || (dsr2 & 4)) {                if (cs->debug & L1_DEB_WARN)			debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der);                /* RX, TX abort if collision detected */                if (der & 2) {                        wByteAMD(cs, 0x21, 0xC2);                        wByteAMD(cs, 0x21, 0x02);			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);                        /* restart frame */                        if (cs->tx_skb) {				skb_push(cs->tx_skb, cs->tx_cnt);				cs->tx_cnt = 0;                                cs->dc.amd7930.tx_xmtlen = 0;				Amd7930_fill_Dfifo(cs);			} else {				printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n");				debugl1(cs, "Amd7930: interrupt: D-Collision, no skb");			}                }                /* remove damaged data from fifo */		Amd7930_empty_Dfifo(cs, 1);		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);                /* restart TX-Frame */                if (cs->tx_skb) {			skb_push(cs->tx_skb, cs->tx_cnt);			cs->tx_cnt = 0;                        cs->dc.amd7930.tx_xmtlen = 0;			Amd7930_fill_Dfifo(cs);		}	}        /* D TX FIFO empty -> fill */	if (irflags & 1) {		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data");		/* AMD interrupts off */                AmdIrqOff(cs);                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);		if (cs->tx_skb) {			if (cs->tx_skb->len)				Amd7930_fill_Dfifo(cs);		}		/* AMD interrupts on */                AmdIrqOn(cs);	}        /* D RX FIFO full or tiny packet in Fifo -> empty */	if ((irflags & 2) || (dsr1 & 2)) {                if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "Amd7930: interrupt: empty D-FIFO");                Amd7930_empty_Dfifo(cs, 0);	}        /* D-Frame transmit complete */	if (dsr1 & 64) {		if (cs->debug & L1_DEB_ISAC) {			debugl1(cs, "Amd7930: interrupt: transmit packet ready");        	}		/* AMD interrupts off */                AmdIrqOff(cs);                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);                if (cs->tx_skb) {        		if (cs->debug & L1_DEB_ISAC)	        		debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb");                        dev_kfree_skb_irq(cs->tx_skb);			cs->tx_cnt = 0;                        cs->dc.amd7930.tx_xmtlen=0;			cs->tx_skb = NULL;                }                if ((cs->tx_skb = skb_dequeue(&cs->sq))) {        		if (cs->debug & L1_DEB_ISAC)	        		debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued");	        	cs->tx_cnt = 0;                        cs->dc.amd7930.tx_xmtlen=0;			Amd7930_fill_Dfifo(cs);		}                else			schedule_event(cs, D_XMTBUFREADY);		/* AMD interrupts on */                AmdIrqOn(cs);        }	/* LIU status interrupt -> read LSR, check statechanges */	if (lsr & 0x38) {                /* AMD interrupts off */                AmdIrqOff(cs);		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) +2));		cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;		schedule_event(cs, D_L1STATECHANGE);		/* AMD interrupts on */                AmdIrqOn(cs);	}        /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */        irflags = rByteAMD(cs, 0x00); }}static voidAmd7930_l1hw(struct PStack *st, int pr, void *arg){        struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;	struct sk_buff *skb = arg;	u_long flags;        if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr);	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, "Amd7930: l1hw: PH_DATA Queued", 0);#endif			} else {				cs->tx_skb = skb;				cs->tx_cnt = 0;                                cs->dc.amd7930.tx_xmtlen=0;#ifdef L2FRAME_DEBUG		/* psa */				if (cs->debug & L1_DEB_LAPD)					Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0);#endif				Amd7930_fill_Dfifo(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, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen");				skb_queue_tail(&cs->sq, skb);				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;                        cs->dc.amd7930.tx_xmtlen=0;#ifdef L2FRAME_DEBUG		/* psa */			if (cs->debug & L1_DEB_LAPD)				Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0);#endif			Amd7930_fill_Dfifo(cs);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (PH_PULL | REQUEST):#ifdef L2FRAME_DEBUG		/* psa */			if (cs->debug & L1_DEB_LAPD)				debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb)? "yes":"no");#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.amd7930.ph_state == 8)) {				/* b-channels off, PH-AR cleared				 * change to F3 */				Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5				spin_unlock_irqrestore(&cs->lock, flags);			} else {				Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");				cs->dc.amd7930.ph_state = 2;				spin_unlock_irqrestore(&cs->lock, flags);				Amd7930_new_ph(cs);			}			break;		case (HW_ENABLE | REQUEST):                        cs->dc.amd7930.ph_state = 9;                        Amd7930_new_ph(cs);			break;		case (HW_INFO3 | REQUEST):			// automatic			break;		case (HW_TESTLOOP | REQUEST):			/* 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(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, "Amd7930: l1hw: unknown %04x", pr);			break;	}}static voidsetstack_Amd7930(struct PStack *st, struct IsdnCardState *cs){        if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "Amd7930: setstack called");        st->l1.l1hw = Amd7930_l1hw;}static voidDC_Close_Amd7930(struct IsdnCardState *cs) {        if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "Amd7930: DC_Close called");}static voiddbusy_timer_handler(struct IsdnCardState *cs){	u_long flags;	struct PStack *stptr;        WORD dtcr, der;        BYTE dsr1, dsr2;        if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "Amd7930: dbusy_timer expired!");	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {		spin_lock_irqsave(&cs->lock, flags);                /* D Transmit Byte Count Register:                 * Counts down packet's number of Bytes, 0 if packet ready */                dtcr = rWordAMD(cs, 0x85);                dsr1 = rByteAMD(cs, 0x02);                dsr2 = rByteAMD(cs, 0x07);                der  = rWordAMD(cs, 0x03);	        if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt);		if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) {	/* D-Channel Busy */			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);			stptr = cs->stlist;			spin_unlock_irqrestore(&cs->lock, flags);			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;                                cs->dc.amd7930.tx_xmtlen = 0;			} else {				printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n");				debugl1(cs, "Amd7930: D-Channel Busy no skb");			}			/* Transmitter reset, abort transmit */			wByteAMD(cs, 0x21, 0x82);			wByteAMD(cs, 0x21, 0x02);			spin_unlock_irqrestore(&cs->lock, flags);			cs->irq_func(cs->irq, cs, NULL);                        if (cs->debug & L1_DEB_ISAC)				debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");		}	}}void __devinitAmd7930_init(struct IsdnCardState *cs){    WORD *ptr;    BYTE cmd, cnt;        if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "Amd7930: initamd called");        cs->dc.amd7930.tx_xmtlen = 0;        cs->dc.amd7930.old_state = 0;        cs->dc.amd7930.lmr1 = 0x40;        cs->dc.amd7930.ph_command = Amd7930_ph_command;	cs->setstack_d = setstack_Amd7930;	cs->DC_Close = DC_Close_Amd7930;	/* AMD Initialisation */	for (ptr = initAMD; *ptr != 0xFFFF; ) {		cmd = LOBYTE(*ptr);                /* read */                if (*ptr++ >= 0x100) {			if (cmd < 8)                                /* setzt Register zur點k */                                rByteAMD(cs, cmd);			else {				wByteAMD(cs, 0x00, cmd);				for (cnt = *ptr++; cnt > 0; cnt--)					rByteAMD(cs, 0x01);			}		}                /* write */                else if (cmd < 8)			wByteAMD(cs, cmd, LOBYTE(*ptr++));		else {			wByteAMD(cs, 0x00, cmd);			for (cnt = *ptr++; cnt > 0; cnt--)				wByteAMD(cs, 0x01, LOBYTE(*ptr++));		}	}}void __devinitsetup_Amd7930(struct IsdnCardState *cs){        INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs);	cs->dbusytimer.function = (void *) dbusy_timer_handler;	cs->dbusytimer.data = (long) cs;	init_timer(&cs->dbusytimer);}

⌨️ 快捷键说明

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