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

📄 dscc4.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
				if(dscc4_do_action(dev, "IDR"))					goto err_xpr;				dpriv->flags &= ~NeedIDR;				mb();				/* Activate receiver and misc */				writel(0x08050008, scc_offset + CCR2);			}		err_xpr:			if (!(state &= ~Xpr))				goto try;		}	} else { /* ! SccEvt */		if (state & Hi) {#ifdef EXPERIMENTAL_POLLING			while(!dscc4_tx_poll(dpriv, dev));#endif			state &= ~Hi;		}		/*		 * FIXME: it may be avoided. Re-re-re-read the manual.		 */		if (state & Err) {			printk(KERN_ERR "%s: Tx ERR\n", dev->name);			dpriv->stats.tx_errors++;			state &= ~Err;		}	}	goto try;}static __inline__ void dscc4_rx_irq(struct dscc4_pci_priv *priv, struct net_device *dev){	struct dscc4_dev_priv *dpriv = dev->priv;	u32 state;	int cur;try:	cur = dpriv->iqrx_current%IRQ_RING_SIZE;	state = dpriv->iqrx[cur];	if (!state)		return;	dpriv->iqrx[cur] = 0;	dpriv->iqrx_current++;#ifdef DEBUG_PARANOID	if (SOURCE_ID(state) != dpriv->dev_id) {		printk(KERN_DEBUG "%s (Rx): Source Id=%d, state=%08x\n",		       dev->name, SOURCE_ID(state), state);		goto try;	}	if (state & 0x0df80c00) {		printk(KERN_DEBUG "%s (Rx): state=%08x (UFO alert)\n",		       dev->name, state);		goto try;	}#endif	if (!(state & SccEvt)){		struct RxFD *rx_fd;		state &= 0x00ffffff;		if (state & Err) { /* Hold or reset */			printk(KERN_DEBUG "%s (Rx): ERR\n", dev->name);			cur = dpriv->rx_current;			rx_fd = dpriv->rx_fd + cur;			/*			 * Presume we're not facing a DMAC receiver reset. 			 * As We use the rx size-filtering feature of the 			 * DSCC4, the beginning of a new frame is waiting in 			 * the rx fifo. I bet a Receive Data Overflow will 			 * happen most of time but let's try and avoid it.			 * Btw (as for RDO) if one experiences ERR whereas			 * the system looks rather idle, there may be a 			 * problem with latency. In this case, increasing			 * RX_RING_SIZE may help.			 */			while (dpriv->rx_needs_refill) {				while(!(rx_fd->state1 & Hold)) {					rx_fd++;					cur++;					if (!(cur = cur%RX_RING_SIZE))						rx_fd = dpriv->rx_fd;				}				dpriv->rx_needs_refill--;				try_get_rx_skb(dpriv, cur, dev);				if (!rx_fd->data)					goto try;				rx_fd->state1 &= ~Hold;				rx_fd->state2 = 0x00000000;				rx_fd->end = 0xbabeface;			}			goto try;		}		if (state & Fi) {			cur = dpriv->rx_current%RX_RING_SIZE;			rx_fd = dpriv->rx_fd + cur;			dscc4_rx_skb(dpriv, cur, rx_fd, dev);			dpriv->rx_current++;			goto try;		}		if (state & Hi ) { /* HI bit */			state &= ~Hi;			goto try;		}	} else { /* ! SccEvt */#ifdef DEBUG_PARANOIA		int i;		static struct {			u32 mask;			const char *irq_name;		} evts[] = {			{ 0x00008000, "TIN"},			{ 0x00004000, "CSC"},			{ 0x00000020, "RSC"},			{ 0x00000010, "PCE"},			{ 0x00000008, "PLLA"},			{ 0x00000004, "CDSC"},			{ 0, NULL}		};#endif /* DEBUG_PARANOIA */		state &= 0x00ffffff;#ifdef DEBUG_PARANOIA		for (i = 0; evts[i].irq_name; i++) {			if (state & evts[i].mask) {				printk(KERN_DEBUG "dscc4(%s): %s\n",					dev->name, evts[i].irq_name);				if (!(state &= ~evts[i].mask))					goto try;			}		}#endif /* DEBUG_PARANOIA */		/*		 * Receive Data Overflow (FIXME: untested)		 */		if (state & Rdo) {			u32 ioaddr, scc_offset, scc_addr;			struct RxFD *rx_fd;			int cur;			//if (debug)			//	dscc4_rx_dump(dpriv);			ioaddr = dev->base_addr;			scc_addr = ioaddr + 0x0c*dpriv->dev_id;			scc_offset = ioaddr + SCC_REG_START(dpriv->dev_id);			writel(readl(scc_offset + CCR2) & ~RxActivate, 			       scc_offset + CCR2);			/*			 * This has no effect. Why ?			 * ORed with TxSccRes, one sees the CFG ack (for			 * the TX part only).			 */				writel(RxSccRes, scc_offset + CMDR);			dpriv->flags |= RdoSet;			/* 			 * Let's try and save something in the received data.			 * rx_current must be incremented at least once to			 * avoid HOLD in the BRDA-to-be-pointed desc.			 */			do {				cur = dpriv->rx_current++%RX_RING_SIZE;				rx_fd = dpriv->rx_fd + cur;				if (!(rx_fd->state2 & DataComplete))					break;				if (rx_fd->state2 & FrameAborted) {					dpriv->stats.rx_over_errors++;					rx_fd->state1 |= Hold;					rx_fd->state2 = 0x00000000;					rx_fd->end = 0xbabeface;				} else 					dscc4_rx_skb(dpriv, cur, rx_fd, dev);			} while (1);			if (debug) {				if (dpriv->flags & RdoSet)					printk(KERN_DEBUG 					       "dscc4: no RDO in Rx data\n");			}#ifdef DSCC4_RDO_EXPERIMENTAL_RECOVERY			/*			 * FIXME: must the reset be this violent ?			 */			writel(dpriv->rx_fd_dma + 			       (dpriv->rx_current%RX_RING_SIZE)*			       sizeof(struct RxFD), scc_addr + CH0BRDA);			writel(MTFi|Rdr|Idr, scc_addr + CH0CFG);			if(dscc4_do_action(dev, "RDR")) {				printk(KERN_ERR "%s: RDO recovery failed(%s)\n",				       dev->name, "RDR");				goto rdo_end;			}			writel(MTFi|Idr, scc_addr + CH0CFG);			if(dscc4_do_action(dev, "IDR")) {				printk(KERN_ERR "%s: RDO recovery failed(%s)\n",				       dev->name, "IDR");				goto rdo_end;			}		rdo_end:#endif			writel(readl(scc_offset + CCR2) | RxActivate, 			       scc_offset + CCR2);			goto try;		}		/* These will be used later */		if (state & Rfs) {			if (!(state &= ~Rfs))				goto try;		}		if (state & Rfo) {			if (!(state &= ~Rfo))				goto try;		}		if (state & Flex) {			if (!(state &= ~Flex))				goto try;		}	}}static int dscc4_init_ring(struct net_device *dev){	struct dscc4_dev_priv *dpriv = (struct dscc4_dev_priv *)dev->priv;	struct TxFD *tx_fd;	struct RxFD *rx_fd;	int i;	tx_fd = (struct TxFD *) pci_alloc_consistent(dpriv->pci_priv->pdev,		TX_RING_SIZE*sizeof(struct TxFD), &dpriv->tx_fd_dma);	if (!tx_fd)		goto err_out;	rx_fd = (struct RxFD *) pci_alloc_consistent(dpriv->pci_priv->pdev,		RX_RING_SIZE*sizeof(struct RxFD), &dpriv->rx_fd_dma);	if (!rx_fd)		goto err_free_dma_tx;	dpriv->tx_fd = tx_fd;	dpriv->rx_fd = rx_fd;	dpriv->rx_current = 0;	dpriv->tx_current = 0;	dpriv->tx_dirty = 0;	/* the dma core of the dscc4 will be locked on the first desc */	for(i = 0; i < TX_RING_SIZE; ) {		reset_TxFD(tx_fd);	        /* FIXME: NULL should be ok - to be tried */	        tx_fd->data = dpriv->tx_fd_dma;	        dpriv->tx_skbuff[i] = NULL;		i++;		tx_fd->next = (u32)(dpriv->tx_fd_dma + i*sizeof(struct TxFD));		tx_fd++;	}	(--tx_fd)->next = (u32)dpriv->tx_fd_dma;{	/*	 * XXX: I would expect the following to work for the first descriptor	 * (tx_fd->state = 0xc0000000)	 * - Hold=1 (don't try and branch to the next descripto);	 * - No=0 (I want an empty data section, i.e. size=0);	 * - Fe=1 (required by No=0 or we got an Err irq and must reset).	 * Alas, it fails (and locks solid). Thus the introduction of a dummy	 * skb to avoid No=0 (choose one: Ugly [ ] Tasteless [ ] VMS [ ]).	 * TODO: fiddle the tx threshold when time permits.	 */	struct sk_buff *skb;	skb = dev_alloc_skb(32);	if (!skb)		goto err_free_dma_tx;	skb->len = 32;	memset(skb->data, 0xaa, 16);	tx_fd -= (TX_RING_SIZE - 1);	tx_fd->state = 0xc0000000;	tx_fd->state |= ((u32)(skb->len & TxSizeMax)) << 16;	tx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data, 				     skb->len, PCI_DMA_TODEVICE);	dpriv->tx_skbuff[0] = skb;}	for (i = 0; i < RX_RING_SIZE;) {		/* size set by the host. Multiple of 4 bytes please */	        rx_fd->state1 = HiDesc; /* Hi, no Hold */	        rx_fd->state2 = 0x00000000;	        rx_fd->end = 0xbabeface;	        rx_fd->state1 |= ((u32)(HDLC_MAX_MRU & RxSizeMax)) << 16;		try_get_rx_skb(dpriv, i, dev);		i++;		rx_fd->next = (u32)(dpriv->rx_fd_dma + i*sizeof(struct RxFD));		rx_fd++;	}	(--rx_fd)->next = (u32)dpriv->rx_fd_dma;	rx_fd->state1 |= 0x40000000; /* Hold */	return 0;err_free_dma_tx:	pci_free_consistent(dpriv->pci_priv->pdev, TX_RING_SIZE*sizeof(*tx_fd),			    tx_fd, dpriv->tx_fd_dma);err_out:	return -1;}static struct net_device_stats *dscc4_get_stats(struct net_device *dev){	struct dscc4_dev_priv *priv = (struct dscc4_dev_priv *)dev->priv;	return &priv->stats;}static void __exit dscc4_remove_one(struct pci_dev *pdev){	struct dscc4_pci_priv *ppriv;	struct net_device *root;	int i;	ppriv = pci_get_drvdata(pdev);	root = ppriv->root;	free_irq(pdev->irq, root);	pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), ppriv->iqcfg, 			    ppriv->iqcfg_dma);	for (i=0; i < dev_per_card; i++) {		struct dscc4_dev_priv *dpriv;		struct net_device *dev;		dev = ppriv->root + i;		dscc4_unattach_hdlc_device(dev);		dpriv = (struct dscc4_dev_priv *)dev->priv;		pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), 				    dpriv->iqrx, dpriv->iqrx_dma);		pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), 				    dpriv->iqtx, dpriv->iqtx_dma);		unregister_netdev(dev);	}	kfree(root->priv);	iounmap((void *)root->base_addr);	kfree(root);	kfree(ppriv);	release_mem_region(pci_resource_start(pdev, 1),			   pci_resource_len(pdev, 1));	release_mem_region(pci_resource_start(pdev, 0),			   pci_resource_len(pdev, 0));}static int dscc4_hdlc_ioctl(struct hdlc_device_struct *hdlc, struct ifreq *ifr, int cmd){	struct net_device *dev = (struct net_device *)hdlc->netdev.base_addr;	int result;	/* FIXME: locking ? */	result = dscc4_ioctl(dev, ifr, cmd);	return result;}static int dscc4_hdlc_open(struct hdlc_device_struct *hdlc){	struct net_device *dev = (struct net_device *)(hdlc->netdev.base_addr);        if (netif_running(dev)) {		printk(KERN_DEBUG "%s: already running\n", dev->name); // DEBUG		return 0;	}	return dscc4_open(dev);}static int dscc4_hdlc_xmit(hdlc_device *hdlc, struct sk_buff *skb){	struct net_device *dev = (struct net_device *)hdlc->netdev.base_addr;	return dscc4_start_xmit(skb, dev);}static void dscc4_hdlc_close(struct hdlc_device_struct *hdlc){	struct net_device *dev = (struct net_device *)hdlc->netdev.base_addr;	struct dscc4_dev_priv *dpriv;	dpriv = dev->priv;	--dpriv->usecount;}/* Operated under dev lock */static int dscc4_attach_hdlc_device(struct net_device *dev) {	struct dscc4_dev_priv *dpriv = dev->priv;	struct hdlc_device_struct *hdlc;	int result;	hdlc = &dpriv->hdlc;	/* XXX: Don't look at the next line */	hdlc->netdev.base_addr = (unsigned long)dev;	hdlc->set_mode = NULL;	hdlc->open = dscc4_hdlc_open;	hdlc->close = dscc4_hdlc_close;	hdlc->ioctl = dscc4_hdlc_ioctl;	hdlc->xmit = dscc4_hdlc_xmit;	result = register_hdlc_device(hdlc);	if (!result)		dpriv->usecount++;	return result;}/* Operated under dev lock */static void dscc4_unattach_hdlc_device(struct net_device *dev) {	struct dscc4_dev_priv *dpriv = dev->priv;	unregister_hdlc_device(&dpriv->hdlc);	dpriv->usecount--;}static struct pci_device_id dscc4_pci_tbl[] __devinitdata = {	{ PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4,	        PCI_ANY_ID, PCI_ANY_ID, },	{ 0,}};MODULE_DEVICE_TABLE(pci, dscc4_pci_tbl);static struct pci_driver dscc4_driver = {	name:           "dscc4",	id_table:       dscc4_pci_tbl,	probe:          dscc4_init_one,	remove:         dscc4_remove_one,};static int __init dscc4_init_module(void){	return pci_module_init(&dscc4_driver);}static void __exit dscc4_cleanup_module(void){	pci_unregister_driver(&dscc4_driver);}module_init(dscc4_init_module);module_exit(dscc4_cleanup_module);

⌨️ 快捷键说明

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