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

📄 pc300_drv.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE);	if (card->hw.type == PC300_TE) {		cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,			   cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |			   (CPLD_REG2_FALC_LED1 << (2 * ch)));	}	CPC_UNLOCK(card, flags);	dev_kfree_skb(skb);	return 0;}void cpc_net_rx(hdlc_device * hdlc){	struct net_device *dev = hdlc_to_dev(hdlc);	pc300dev_t *d = (pc300dev_t *) dev->priv;	pc300ch_t *chan = (pc300ch_t *) d->chan;	pc300_t *card = (pc300_t *) chan->card;	struct net_device_stats *stats = &d->hdlc->stats;	int ch = chan->channel;#ifdef PC300_DEBUG_RX	int i;#endif	int rxb;	struct sk_buff *skb;	while (1) {		if ((rxb = dma_get_rx_frame_size(card, ch)) == -1)			return;		if (!netif_carrier_ok(dev)) {			/* DCD must be OFF: drop packet */		    printk("%s : DCD is OFF - drop %d rx bytes\n", dev->name, rxb); 			skb = NULL;		} else {			if (rxb > (dev->mtu + 40)) { /* add headers */				printk("%s : MTU exceeded %d\n", dev->name, rxb); 				skb = NULL;			} else {				skb = dev_alloc_skb(rxb);				if (skb == NULL) {					printk("%s: Memory squeeze!!\n", dev->name);					return;				}				skb->dev = dev;			}		}		if (((rxb = dma_buf_read(card, ch, skb)) <= 0) || (skb == NULL)) {#ifdef PC300_DEBUG_RX			printk("%s: rxb = %x\n", dev->name, rxb);#endif			if ((skb == NULL) && (rxb > 0)) {				/* rxb > dev->mtu */				stats->rx_errors++;				stats->rx_length_errors++;				continue;			}			if (rxb < 0) {	/* Invalid frame */				rxb = -rxb;				if (rxb & DST_OVR) {					stats->rx_errors++;					stats->rx_fifo_errors++;				}				if (rxb & DST_CRC) {					stats->rx_errors++;					stats->rx_crc_errors++;				}				if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) {					stats->rx_errors++;					stats->rx_frame_errors++;				}			}			if (skb) {				dev_kfree_skb_irq(skb);			}			continue;		}		stats->rx_bytes += rxb;#ifdef PC300_DEBUG_RX		printk("%s R:", dev->name);		for (i = 0; i < skb->len; i++)			printk(" %02x", *(skb->data + i));		printk("\n");#endif		if (d->trace_on) {			cpc_trace(dev, skb, 'R');		}		stats->rx_packets++;		skb->mac.raw = skb->data;		skb->protocol = hdlc_type_trans(skb, dev);		netif_rx(skb);	}}/************************************//***   PC300 Interrupt Routines   ***//************************************/static void sca_tx_intr(pc300dev_t *dev){	pc300ch_t *chan = (pc300ch_t *)dev->chan; 	pc300_t *card = (pc300_t *)chan->card; 	int ch = chan->channel; 	volatile pcsca_bd_t * ptdescr; 	struct net_device_stats *stats = &dev->hdlc->stats;     /* Clean up descriptors from previous transmission */	ptdescr = (pcsca_bd_t *)(card->hw.rambase +						TX_BD_ADDR(ch,chan->tx_first_bd));	while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) != 							TX_BD_ADDR(ch,chan->tx_first_bd)) && 			(cpc_readb(&ptdescr->status) & DST_OSB)) {		stats->tx_packets++;		stats->tx_bytes += cpc_readw(&ptdescr->len);		cpc_writeb(&ptdescr->status, DST_OSB);		cpc_writew(&ptdescr->len, 0);		chan->nfree_tx_bd++;		chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);		ptdescr = (pcsca_bd_t *)(card->hw.rambase +						TX_BD_ADDR(ch,chan->tx_first_bd));    }#ifdef CONFIG_PC300_MLPPP	if (chan->conf.proto == PC300_PROTO_MLPPP) {			cpc_tty_trigger_poll(dev);	} else {#endif	/* Tell the upper layer we are ready to transmit more packets */		netif_wake_queue((struct net_device*)dev->hdlc);#ifdef CONFIG_PC300_MLPPP	}#endif}static void sca_intr(pc300_t * card){	uclong scabase = card->hw.scabase;	volatile uclong status;	int ch;	int intr_count = 0;	unsigned char dsr_rx;	while ((status = cpc_readl(scabase + ISR0)) != 0) {		for (ch = 0; ch < card->hw.nchan; ch++) {			pc300ch_t *chan = &card->chan[ch];			pc300dev_t *d = &chan->d;			hdlc_device *hdlc = d->hdlc;			struct net_device *dev = hdlc_to_dev(hdlc);			spin_lock(&card->card_lock);	    /**** Reception ****/			if (status & IR0_DRX((IR0_DMIA | IR0_DMIB), ch)) {				ucchar drx_stat = cpc_readb(scabase + DSR_RX(ch));				/* Clear RX interrupts */				cpc_writeb(scabase + DSR_RX(ch), drx_stat | DSR_DWE);#ifdef PC300_DEBUG_INTR				printk ("sca_intr: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n",					 ch, status, drx_stat);#endif				if (status & IR0_DRX(IR0_DMIA, ch)) {					if (drx_stat & DSR_BOF) {#ifdef CONFIG_PC300_MLPPP						if (chan->conf.proto == PC300_PROTO_MLPPP) {							/* verify if driver is TTY */							if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {								rx_dma_stop(card, ch);							}							cpc_tty_receive(d);							rx_dma_start(card, ch);						} else #endif						{							if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {								rx_dma_stop(card, ch);							}							cpc_net_rx(hdlc);							/* Discard invalid frames */							hdlc->stats.rx_errors++;							hdlc->stats.rx_over_errors++;							chan->rx_first_bd = 0;							chan->rx_last_bd = N_DMA_RX_BUF - 1;							rx_dma_start(card, ch);						}					}				}				if (status & IR0_DRX(IR0_DMIB, ch)) {					if (drx_stat & DSR_EOM) {						if (card->hw.type == PC300_TE) {							cpc_writeb(card->hw.falcbase +								   card->hw.cpld_reg2,								   cpc_readb (card->hw.falcbase +								    	card->hw.cpld_reg2) |								   (CPLD_REG2_FALC_LED1 << (2 * ch)));						}#ifdef CONFIG_PC300_MLPPP						if (chan->conf.proto == PC300_PROTO_MLPPP) {							/* verify if driver is TTY */							cpc_tty_receive(d);						} else {							cpc_net_rx(hdlc);						}#else						cpc_net_rx(hdlc);#endif						if (card->hw.type == PC300_TE) {							cpc_writeb(card->hw.falcbase +								   card->hw.cpld_reg2,								   cpc_readb (card->hw.falcbase +								    		card->hw.cpld_reg2) &								   ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));						}					}				}				if (!(dsr_rx = cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {#ifdef PC300_DEBUG_INTR		printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n", 					dev->name, ch, status, drx_stat, dsr_rx);#endif					cpc_writeb(scabase + DSR_RX(ch), (dsr_rx | DSR_DE) & 0xfe);				}			}	    /**** Transmission ****/			if (status & IR0_DTX((IR0_EFT | IR0_DMIA | IR0_DMIB), ch)) {				ucchar dtx_stat = cpc_readb(scabase + DSR_TX(ch));				/* Clear TX interrupts */				cpc_writeb(scabase + DSR_TX(ch), dtx_stat | DSR_DWE);#ifdef PC300_DEBUG_INTR				printk ("sca_intr: TX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n",					 ch, status, dtx_stat);#endif				if (status & IR0_DTX(IR0_EFT, ch)) {					if (dtx_stat & DSR_UDRF) {						if (cpc_readb (scabase + M_REG(TBN, ch)) != 0) {							cpc_writeb(scabase + M_REG(CMD,ch), CMD_TX_BUF_CLR);						}						if (card->hw.type == PC300_TE) {							cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,								   cpc_readb (card->hw.falcbase + 										   card->hw.cpld_reg2) &								   ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));						}						hdlc->stats.tx_errors++;						hdlc->stats.tx_fifo_errors++;						sca_tx_intr(d);					}				}				if (status & IR0_DTX(IR0_DMIA, ch)) {					if (dtx_stat & DSR_BOF) {					}				}				if (status & IR0_DTX(IR0_DMIB, ch)) {					if (dtx_stat & DSR_EOM) {						if (card->hw.type == PC300_TE) {							cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,								   cpc_readb (card->hw.falcbase +								    			card->hw.cpld_reg2) &								   ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));						}						sca_tx_intr(d);					}				}			}	    /**** MSCI ****/			if (status & IR0_M(IR0_RXINTA, ch)) {				ucchar st1 = cpc_readb(scabase + M_REG(ST1, ch));				/* Clear MSCI interrupts */				cpc_writeb(scabase + M_REG(ST1, ch), st1);#ifdef PC300_DEBUG_INTR				printk("sca_intr: MSCI intr chan[%d] (st=0x%08lx, st1=0x%02x)\n",					 ch, status, st1);#endif				if (st1 & ST1_CDCD) {	/* DCD changed */					if (cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD) {						printk ("%s: DCD is OFF. Going administrative down.\n",							 dev->name);#ifdef CONFIG_PC300_MLPPP						if (chan->conf.proto != PC300_PROTO_MLPPP) {							netif_carrier_off(dev);						}#else						netif_carrier_off(dev);#endif						card->chan[ch].d.line_off++;					} else {	/* DCD = 1 */						printk ("%s: DCD is ON. Going administrative up.\n",							 dev->name);#ifdef CONFIG_PC300_MLPPP						if (chan->conf.proto != PC300_PROTO_MLPPP)							/* verify if driver is not TTY */#endif							netif_carrier_on(dev);						card->chan[ch].d.line_on++;					}				}			}			spin_unlock(&card->card_lock);		}		if (++intr_count == 10)			/* Too much work at this board. Force exit */			break;	}}static void falc_t1_loop_detection(pc300_t * card, int ch, ucchar frs1){	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];	falc_t *pfalc = (falc_t *) & chan->falc;	uclong falcbase = card->hw.falcbase;	if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&	    !pfalc->loop_gen) {		if (frs1 & FRS1_LLBDD) {			// A Line Loop Back Deactivation signal detected			if (pfalc->loop_active) {				falc_remote_loop(card, ch, 0);			}		} else {			if ((frs1 & FRS1_LLBAD) &&			    ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {				// A Line Loop Back Activation signal detected  				if (!pfalc->loop_active) {					falc_remote_loop(card, ch, 1);				}			}		}	}}static void falc_e1_loop_detection(pc300_t * card, int ch, ucchar rsp){	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];	falc_t *pfalc = (falc_t *) & chan->falc;	uclong falcbase = card->hw.falcbase;	if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&	    !pfalc->loop_gen) {		if (rsp & RSP_LLBDD) {			// A Line Loop Back Deactivation signal detected			if (pfalc->loop_active) {				falc_remote_loop(card, ch, 0);			}		} else {			if ((rsp & RSP_LLBAD) &&			    ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {				// A Line Loop Back Activation signal detected  				if (!pfalc->loop_active) {					falc_remote_loop(card, ch, 1);				}			}		}	}}static void falc_t1_intr(pc300_t * card, int ch){	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];	falc_t *pfalc = (falc_t *) & chan->falc;	uclong falcbase = card->hw.falcbase;	ucchar isr0, isr3, gis;	ucchar dummy;	while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {		if (gis & GIS_ISR0) {			isr0 = cpc_readb(falcbase + F_REG(FISR0, ch));			if (isr0 & FISR0_PDEN) {				/* Read the bit to clear the situation */				if (cpc_readb(falcbase + F_REG(FRS1, ch)) &				    FRS1_PDEN) {					pfalc->pden++;				}			}		}		if (gis & GIS_ISR1) {			dummy = cpc_readb(falcbase + F_REG(FISR1, ch));		}		if (gis & GIS_ISR2) {			dummy = cpc_readb(falcbase + F_REG(FISR2, ch));		}		if (gis & GIS_ISR3) {			isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));			if (isr3 & FISR3_SEC) {				pfalc->sec++;				falc_update_stats(card, ch);				falc_check_status(card, ch,						  cpc_readb(falcbase + F_REG(FRS0, ch)));			}			if (isr3 & FISR3_ES) {				pfalc->es++;			}			if (isr3 & FISR3_LLBSC) {				falc_t1_loop_detection(card, ch,						       cpc_readb(falcbase + F_REG(FRS1, ch)));			}		}	}}static void falc_e1_intr(pc300_t * card, int ch){	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];	falc_t *pfalc = (falc_t *) & chan->falc;	uclong falcbase = ca

⌨️ 快捷键说明

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