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

📄 eni.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci){	struct atm_vcc *walk;	if (*vpi == ATM_VPI_ANY) *vpi = 0;	if (*vci == ATM_VCI_ANY) {		for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) {			if (vcc->qos.rxtp.traffic_class != ATM_NONE &&			    ENI_DEV(vcc->dev)->rx_map[*vci])				continue;			if (vcc->qos.txtp.traffic_class != ATM_NONE) {				for (walk = vcc->dev->vccs; walk;				    walk = walk->next)					if (test_bit(ATM_VF_ADDR,&walk->flags)					    && walk->vci == *vci &&					    walk->qos.txtp.traffic_class !=					    ATM_NONE)						break;				if (walk) continue;			}			break;		}		return *vci == NR_VCI ? -EADDRINUSE : 0;	}	if (*vci == ATM_VCI_UNSPEC) return 0;	if (vcc->qos.rxtp.traffic_class != ATM_NONE &&	    ENI_DEV(vcc->dev)->rx_map[*vci])		return -EADDRINUSE;	if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;	for (walk = vcc->dev->vccs; walk; walk = walk->next)		if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci &&		    walk->qos.txtp.traffic_class != ATM_NONE)			return -EADDRINUSE;	return 0;}static int eni_open(struct atm_vcc *vcc,short vpi,int vci){	struct eni_dev *eni_dev;	struct eni_vcc *eni_vcc;	int error;	DPRINTK(">eni_open\n");	EVENT("eni_open\n",0,0);	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ENI_VCC(vcc) = NULL;	eni_dev = ENI_DEV(vcc->dev);	error = get_ci(vcc,&vpi,&vci);	if (error) return error;	vcc->vpi = vpi;	vcc->vci = vci;	if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)		set_bit(ATM_VF_ADDR,&vcc->flags);	if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5)		return -EINVAL;	DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi,	    vcc->vci);	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) {		eni_vcc = kmalloc(sizeof(struct eni_vcc),GFP_KERNEL);		if (!eni_vcc) return -ENOMEM;		ENI_VCC(vcc) = eni_vcc;		eni_vcc->tx = NULL; /* for eni_close after open_rx */		if ((error = open_rx_first(vcc))) {			eni_close(vcc);			return error;		}		if ((error = open_tx_first(vcc))) {			eni_close(vcc);			return error;		}	}	if (vci == ATM_VPI_UNSPEC || vpi == ATM_VCI_UNSPEC) return 0;	if ((error = open_rx_second(vcc))) {		eni_close(vcc);		return error;	}	if ((error = open_tx_second(vcc))) {		eni_close(vcc);		return error;	}	set_bit(ATM_VF_READY,&vcc->flags);	/* should power down SUNI while !ref_count @@@ */	return 0;}static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs){	struct eni_dev *eni_dev = ENI_DEV(vcc->dev);	struct eni_tx *tx = ENI_VCC(vcc)->tx;	struct sk_buff *skb;	int error,rate,rsv,shp;	if (qos->txtp.traffic_class == ATM_NONE) return 0;	if (tx == eni_dev->ubr) return -EBADFD;	rate = atm_pcr_goal(&qos->txtp);	if (rate < 0) rate = -rate;	rsv = shp = 0;	if ((flgs & ATM_MF_DEC_RSV) && rate && rate < tx->reserved) rsv = 1;	if ((flgs & ATM_MF_INC_RSV) && (!rate || rate > tx->reserved)) rsv = 1;	if ((flgs & ATM_MF_DEC_SHP) && rate && rate < tx->shaping) shp = 1;	if ((flgs & ATM_MF_INC_SHP) && (!rate || rate > tx->shaping)) shp = 1;	if (!rsv && !shp) return 0;	error = reserve_or_set_tx(vcc,&qos->txtp,rsv,shp);	if (error) return error;	if (shp && !(flgs & ATM_MF_IMMED)) return 0;	/*	 * Walk through the send buffer and patch the rate information in all	 * segmentation buffer descriptors of this VCC.	 */	tasklet_disable(&eni_dev->task);	for (skb = eni_dev->tx_queue.next; skb !=	    (struct sk_buff *) &eni_dev->tx_queue; skb = skb->next) {		unsigned long dsc;		if (ATM_SKB(skb)->vcc != vcc) continue;		dsc = tx->send+ENI_PRV_POS(skb)*4;		writel((readl(dsc) & ~(MID_SEG_RATE | MID_SEG_PR)) |		    (tx->prescaler << MID_SEG_PR_SHIFT) |		    (tx->resolution << MID_SEG_RATE_SHIFT), dsc);	}	tasklet_enable(&eni_dev->task);	return 0;}static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg){	struct eni_dev *eni_dev = ENI_DEV(dev);	if (cmd == ENI_MEMDUMP) {		if (!capable(CAP_NET_ADMIN)) return -EPERM;		printk(KERN_WARNING "Please use /proc/atm/" DEV_LABEL ":%d "		    "instead of obsolete ioctl ENI_MEMDUMP\n",dev->number);		dump(dev);		return 0;	}	if (cmd == ENI_SETMULT) {		struct eni_multipliers mult;		if (!capable(CAP_NET_ADMIN)) return -EPERM;		if (copy_from_user(&mult,(void *) arg,		    sizeof(struct eni_multipliers)))			return -EFAULT;		if ((mult.tx && mult.tx <= 100) || (mult.rx &&mult.rx <= 100) ||		    mult.tx > 65536 || mult.rx > 65536)			return -EINVAL;		if (mult.tx) eni_dev->tx_mult = mult.tx;		if (mult.rx) eni_dev->rx_mult = mult.rx;		return 0;	}	if (cmd == ATM_SETCIRANGE) {		struct atm_cirange ci;		if (copy_from_user(&ci,(void *) arg,sizeof(struct atm_cirange)))			return -EFAULT;		if ((ci.vpi_bits == 0 || ci.vpi_bits == ATM_CI_MAX) &&		    (ci.vci_bits == NR_VCI_LD || ci.vpi_bits == ATM_CI_MAX))		    return 0;		return -EINVAL;	}	if (!dev->phy->ioctl) return -ENOIOCTLCMD;	return dev->phy->ioctl(dev,cmd,arg);}static int eni_getsockopt(struct atm_vcc *vcc,int level,int optname,    void *optval,int optlen){	return -EINVAL;}static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname,    void *optval,int optlen){	return -EINVAL;}static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb){	enum enq_res res;	DPRINTK(">eni_send\n");	if (!ENI_VCC(vcc)->tx) {		if (vcc->pop) vcc->pop(vcc,skb);		else dev_kfree_skb(skb);		return -EINVAL;	}	if (!skb) {		printk(KERN_CRIT "!skb in eni_send ?\n");		if (vcc->pop) vcc->pop(vcc,skb);		return -EINVAL;	}	if (vcc->qos.aal == ATM_AAL0) {		if (skb->len != ATM_CELL_SIZE-1) {			if (vcc->pop) vcc->pop(vcc,skb);			else dev_kfree_skb(skb);			return -EINVAL;		}		*(u32 *) skb->data = htonl(*(u32 *) skb->data);	}submitted++;	ATM_SKB(skb)->vcc = vcc;	tasklet_disable(&ENI_DEV(vcc->dev)->task);	res = do_tx(skb);	tasklet_enable(&ENI_DEV(vcc->dev)->task);	if (res == enq_ok) return 0;	skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);backlogged++;	tasklet_schedule(&ENI_DEV(vcc->dev)->task);	return 0;}static int eni_sg_send(struct atm_vcc *vcc,unsigned long start,    unsigned long size){	return vcc->qos.aal == ATM_AAL5 && !((start | size) & 3);		/* don't tolerate misalignment */}static void eni_phy_put(struct atm_dev *dev,unsigned char value,    unsigned long addr){	writel(value,ENI_DEV(dev)->phy+addr*4);}static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr){	return readl(ENI_DEV(dev)->phy+addr*4);}static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page){	static const char *signal[] = { "LOST","unknown","okay" };	struct eni_dev *eni_dev = ENI_DEV(dev);	struct atm_vcc *vcc;	int left,i;	left = *pos;	if (!left)		return sprintf(page,DEV_LABEL "(itf %d) signal %s, %dkB, "		    "%d cps remaining\n",dev->number,signal[(int) dev->signal],		    eni_dev->mem >> 10,eni_dev->tx_bw);	if (!--left)		return sprintf(page,"%4sBursts: TX"#if !defined(CONFIG_ATM_ENI_BURST_TX_16W) && \    !defined(CONFIG_ATM_ENI_BURST_TX_8W) && \    !defined(CONFIG_ATM_ENI_BURST_TX_4W) && \    !defined(CONFIG_ATM_ENI_BURST_TX_2W)		    " none"#endif#ifdef CONFIG_ATM_ENI_BURST_TX_16W		    " 16W"#endif#ifdef CONFIG_ATM_ENI_BURST_TX_8W		    " 8W"#endif#ifdef CONFIG_ATM_ENI_BURST_TX_4W		    " 4W"#endif#ifdef CONFIG_ATM_ENI_BURST_TX_2W		    " 2W"#endif		    ", RX"#if !defined(CONFIG_ATM_ENI_BURST_RX_16W) && \    !defined(CONFIG_ATM_ENI_BURST_RX_8W) && \    !defined(CONFIG_ATM_ENI_BURST_RX_4W) && \    !defined(CONFIG_ATM_ENI_BURST_RX_2W)		    " none"#endif#ifdef CONFIG_ATM_ENI_BURST_RX_16W		    " 16W"#endif#ifdef CONFIG_ATM_ENI_BURST_RX_8W		    " 8W"#endif#ifdef CONFIG_ATM_ENI_BURST_RX_4W		    " 4W"#endif#ifdef CONFIG_ATM_ENI_BURST_RX_2W		    " 2W"#endif#ifndef CONFIG_ATM_ENI_TUNE_BURST		    " (default)"#endif		    "\n","");	if (!--left) 		return sprintf(page,"%4sBuffer multipliers: tx %d%%, rx %d%%\n",		    "",eni_dev->tx_mult,eni_dev->rx_mult);	for (i = 0; i < NR_CHAN; i++) {		struct eni_tx *tx = eni_dev->tx+i;		if (!tx->send) continue;		if (!--left) {			return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx "			    "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,			    tx->send-eni_dev->ram,			    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,			    tx->reserved,tx->shaping,			    tx == eni_dev->ubr ? " (UBR)" : "");		}		if (--left) continue;		return sprintf(page,"%10sbacklog %u packets\n","",		    skb_queue_len(&tx->backlog));	}	for (vcc = dev->vccs; vcc; vcc = vcc->next) {		struct eni_vcc *eni_vcc = ENI_VCC(vcc);		int length;		if (--left) continue;		length = sprintf(page,"vcc %4d: ",vcc->vci);		if (eni_vcc->rx) {			length += sprintf(page+length,"0x%06lx-0x%06lx "			    "(%6ld bytes)",			    eni_vcc->recv-eni_dev->ram,			    eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,			    eni_vcc->words*4);			if (eni_vcc->tx) length += sprintf(page+length,", ");		}		if (eni_vcc->tx)			length += sprintf(page+length,"tx[%d], txing %d bytes",			    eni_vcc->tx->index,eni_vcc->txing);		page[length] = '\n';		return length+1;	}	for (i = 0; i < eni_dev->free_len; i++) {		struct eni_free *fe = eni_dev->free_list+i;		unsigned long offset;		if (--left) continue;		offset = eni_dev->ram+eni_dev->base_diff;		return sprintf(page,"free      0x%06lx-0x%06lx (%6d bytes)\n",		    fe->start-offset,fe->start-offset+(1 << fe->order)-1,		    1 << fe->order);	}	return 0;}static const struct atmdev_ops ops = {	open:		eni_open,	close:		eni_close,	ioctl:		eni_ioctl,	getsockopt:	eni_getsockopt,	setsockopt:	eni_setsockopt,	send:		eni_send,	sg_send:	eni_sg_send,	phy_put:	eni_phy_put,	phy_get:	eni_phy_get,	change_qos:	eni_change_qos,	proc_read:	eni_proc_read};static int __devinit eni_init_one(struct pci_dev *pci_dev,    const struct pci_device_id *ent){	struct atm_dev *dev;	struct eni_dev *eni_dev;	int error = -ENOMEM;	DPRINTK("eni_init_one\n");	MOD_INC_USE_COUNT; /* @@@ we don't support unloading yet */	if (pci_enable_device(pci_dev)) {		error = -EIO;		goto out0;	}	eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL);	if (!eni_dev) goto out0;	if (!cpu_zeroes) {		cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,		    &zeroes);		if (!cpu_zeroes) goto out1;	}	dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);	if (!dev) goto out2;	pci_set_drvdata(pci_dev, dev);	eni_dev->pci_dev = pci_dev;	ENI_DEV(dev) = eni_dev;	eni_dev->asic = ent->driver_data;	error = eni_do_init(dev);	if (error) goto out3;	error = eni_start(dev);	if (error) goto out3;	eni_dev->more = eni_boards;	eni_boards = dev;	return 0;out3:	atm_dev_deregister(dev);out2:	pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes);	cpu_zeroes = NULL;out1:	kfree(eni_dev);out0:	MOD_DEC_USE_COUNT; /* @@@ we don't support unloading yet */	return error;}static struct pci_device_id eni_pci_tbl[] __devinitdata = {	{ PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_FPGA, PCI_ANY_ID, PCI_ANY_ID,	  0, 0, 0 /* FPGA */ },	{ PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID,	  0, 0, 1 /* ASIC */ },	{ 0, }};MODULE_DEVICE_TABLE(pci,eni_pci_tbl);static void __devexit eni_remove_one(struct pci_dev *pci_dev){	/* grrr */}static struct pci_driver eni_driver = {	name:		DEV_LABEL,	id_table:	eni_pci_tbl,	probe:		eni_init_one,	remove:		__devexit_p(eni_remove_one),};static int __init eni_init(void){	struct sk_buff *skb; /* dummy for sizeof */	if (sizeof(skb->cb) < sizeof(struct eni_skb_prv)) {		printk(KERN_ERR "eni_detect: skb->cb is too small (%d < %d)\n",		    sizeof(skb->cb),sizeof(struct eni_skb_prv));		return -EIO;	}	if (pci_register_driver(&eni_driver) > 0) return 0;	pci_unregister_driver (&eni_driver);	return -ENODEV;}static void __exit eni_cleanup(void){	/*	 * Well, there's no way to get rid of the driver yet, so we don't	 * have to clean up, right ? :-)	 */}module_init(eni_init);module_exit(eni_cleanup);EXPORT_NO_SYMBOLS;MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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