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

📄 idt77252.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
{	unsigned long flags;	int res;	spin_lock_irqsave(&card->tst_lock, flags);	res = __clear_tst(card, vc);	set_bit(TST_SWITCH_PENDING, &card->tst_state);	if (!timer_pending(&card->tst_timer))		mod_timer(&card->tst_timer, jiffies + 1);	spin_unlock_irqrestore(&card->tst_lock, flags);	return res;}static intchange_tst(struct idt77252_dev *card, struct vc_map *vc,	   int n, unsigned int opc){	unsigned long flags;	int res;	spin_lock_irqsave(&card->tst_lock, flags);	__clear_tst(card, vc);	res = __fill_tst(card, vc, n, opc);	set_bit(TST_SWITCH_PENDING, &card->tst_state);	if (!timer_pending(&card->tst_timer))		mod_timer(&card->tst_timer, jiffies + 1);	spin_unlock_irqrestore(&card->tst_lock, flags);	return res;}static intset_tct(struct idt77252_dev *card, struct vc_map *vc){	unsigned long tct;	tct = (unsigned long) (card->tct_base + vc->index * SAR_SRAM_TCT_SIZE);	switch (vc->class) {	case SCHED_CBR:		OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",		        card->name, tct, vc->scq->scd);		write_sram(card, tct + 0, TCT_CBR | vc->scq->scd);		write_sram(card, tct + 1, 0);		write_sram(card, tct + 2, 0);		write_sram(card, tct + 3, 0);		write_sram(card, tct + 4, 0);		write_sram(card, tct + 5, 0);		write_sram(card, tct + 6, 0);		write_sram(card, tct + 7, 0);		break;	case SCHED_UBR:		OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",		        card->name, tct, vc->scq->scd);		write_sram(card, tct + 0, TCT_UBR | vc->scq->scd);		write_sram(card, tct + 1, 0);		write_sram(card, tct + 2, TCT_TSIF);		write_sram(card, tct + 3, TCT_HALT | TCT_IDLE);		write_sram(card, tct + 4, 0);		write_sram(card, tct + 5, vc->init_er);		write_sram(card, tct + 6, 0);		write_sram(card, tct + 7, TCT_FLAG_UBR);		break;	case SCHED_VBR:	case SCHED_ABR:	default:		return -ENOSYS;	}	return 0;}/*****************************************************************************//*                                                                           *//* FBQ Handling                                                              *//*                                                                           *//*****************************************************************************/static __inline__ intidt77252_fbq_level(struct idt77252_dev *card, int queue){	return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) & 0x0f;}static __inline__ intidt77252_fbq_full(struct idt77252_dev *card, int queue){	return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) == 0x0f;}static intpush_rx_skb(struct idt77252_dev *card, struct sk_buff *skb, int queue){	unsigned long flags;	u32 handle;	u32 addr;	skb->data = skb->tail = skb->head;	skb->len = 0;	skb_reserve(skb, 16);	switch (queue) {	case 0:		skb_put(skb, SAR_FB_SIZE_0);		break;	case 1:		skb_put(skb, SAR_FB_SIZE_1);		break;	case 2:		skb_put(skb, SAR_FB_SIZE_2);		break;	case 3:		skb_put(skb, SAR_FB_SIZE_3);		break;	default:		dev_kfree_skb(skb);		return -1;	}	if (idt77252_fbq_full(card, queue))		return -1;	memset(&skb->data[(skb->len & ~(0x3f)) - 64], 0, 2 * sizeof(u32));	handle = IDT77252_PRV_POOL(skb);	addr = IDT77252_PRV_PADDR(skb);	spin_lock_irqsave(&card->cmd_lock, flags);	writel(handle, card->fbq[queue]);	writel(addr, card->fbq[queue]);	spin_unlock_irqrestore(&card->cmd_lock, flags);	return 0;}static voidadd_rx_skb(struct idt77252_dev *card, int queue,	   unsigned int size, unsigned int count){	struct sk_buff *skb;	dma_addr_t paddr;	u32 handle;	while (count--) {		skb = dev_alloc_skb(size);		if (!skb)			return;		if (sb_pool_add(card, skb, queue)) {			printk("%s: SB POOL full\n", __FUNCTION__);			goto outfree;		}		paddr = pci_map_single(card->pcidev, skb->data,				       skb->end - skb->data,				       PCI_DMA_FROMDEVICE);		IDT77252_PRV_PADDR(skb) = paddr;		if (push_rx_skb(card, skb, queue)) {			printk("%s: FB QUEUE full\n", __FUNCTION__);			goto outunmap;		}	}	return;outunmap:	pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),			 skb->end - skb->data, PCI_DMA_FROMDEVICE);	handle = IDT77252_PRV_POOL(skb);	card->sbpool[POOL_QUEUE(handle)].skb[POOL_INDEX(handle)] = NULL;outfree:	dev_kfree_skb(skb);}static voidrecycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb){	u32 handle = IDT77252_PRV_POOL(skb);	int err;	err = push_rx_skb(card, skb, POOL_QUEUE(handle));	if (err) {		pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),				 skb->end - skb->data, PCI_DMA_FROMDEVICE);		sb_pool_remove(card, skb);		dev_kfree_skb(skb);	}}static voidflush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp){	rpp->len = 0;	rpp->count = 0;	rpp->first = NULL;	rpp->last = &rpp->first;}static voidrecycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp){	struct sk_buff *skb, *next;	int i;	skb = rpp->first;	for (i = 0; i < rpp->count; i++) {		next = skb->next;		skb->next = NULL;		recycle_rx_skb(card, skb);		skb = next;	}	flush_rx_pool(card, rpp);}/*****************************************************************************//*                                                                           *//* ATM Interface                                                             *//*                                                                           *//*****************************************************************************/static voididt77252_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr){	write_utility(dev->dev_data, 0x100 + (addr & 0x1ff), value);}static unsigned charidt77252_phy_get(struct atm_dev *dev, unsigned long addr){	return read_utility(dev->dev_data, 0x100 + (addr & 0x1ff));}static intidt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam){	struct atm_dev *dev = vcc->dev;	struct idt77252_dev *card = dev->dev_data;	struct vc_map *vc = vcc->dev_data;	int err;	if (vc == NULL) {		printk("%s: NULL connection in send().\n", card->name);		atomic_inc(&vcc->stats->tx_err);		dev_kfree_skb(skb);		return -EINVAL;	}	if (!test_bit(VCF_TX, &vc->flags)) {		printk("%s: Trying to transmit on a non-tx VC.\n", card->name);		atomic_inc(&vcc->stats->tx_err);		dev_kfree_skb(skb);		return -EINVAL;	}	switch (vcc->qos.aal) {	case ATM_AAL0:	case ATM_AAL1:	case ATM_AAL5:		break;	default:		printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);		atomic_inc(&vcc->stats->tx_err);		dev_kfree_skb(skb);		return -EINVAL;	}	if (ATM_SKB(skb)->iovcnt != 0) {		printk("%s: No scatter-gather yet.\n", card->name);		atomic_inc(&vcc->stats->tx_err);		dev_kfree_skb(skb);		return -EINVAL;	}	ATM_SKB(skb)->vcc = vcc;	err = queue_skb(card, vc, skb, oam);	if (err) {		atomic_inc(&vcc->stats->tx_err);		dev_kfree_skb(skb);		return err;	}	return 0;}intidt77252_send(struct atm_vcc *vcc, struct sk_buff *skb){	return idt77252_send_skb(vcc, skb, 0);}static intidt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags){	struct atm_dev *dev = vcc->dev;	struct idt77252_dev *card = dev->dev_data;	struct sk_buff *skb;	skb = dev_alloc_skb(64);	if (!skb) {		printk("%s: Out of memory in send_oam().\n", card->name);		atomic_inc(&vcc->stats->tx_err);		return -ENOMEM;	}	atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->tx_inuse);	ATM_SKB(skb)->iovcnt = 0;	memcpy(skb_put(skb, 52), cell, 52);	return idt77252_send_skb(vcc, skb, 1);}static __inline__ unsigned intidt77252_fls(unsigned int x){	int r = 1;	if (x == 0)		return 0;	if (x & 0xffff0000) {		x >>= 16;		r += 16;	}	if (x & 0xff00) {		x >>= 8;		r += 8;	}	if (x & 0xf0) {		x >>= 4;		r += 4;	}	if (x & 0xc) {		x >>= 2;		r += 2;	}	if (x & 0x2)		r += 1;	return r;}static u16idt77252_int_to_atmfp(unsigned int rate){	u16 m, e;	if (rate == 0)		return 0;	e = idt77252_fls(rate) - 1;	if (e < 9)		m = (rate - (1 << e)) << (9 - e);	else if (e == 9)		m = (rate - (1 << e));	else /* e > 9 */		m = (rate - (1 << e)) >> (e - 9);	return 0x4000 | (e << 9) | m;}static u8idt77252_rate_logindex(struct idt77252_dev *card, int pcr){	u16 afp;	afp = idt77252_int_to_atmfp(pcr < 0 ? -pcr : pcr);	if (pcr < 0)		return rate_to_log[(afp >> 5) & 0x1ff];	return rate_to_log[((afp >> 5) + 1) & 0x1ff];}static voididt77252_est_timer(unsigned long data){	struct vc_map *vc = (struct vc_map *)data;	struct idt77252_dev *card = vc->card;	struct rate_estimator *est;	unsigned long flags;	u32 rate, cps;	u64 ncells;	u8 lacr;	spin_lock_irqsave(&vc->lock, flags);	est = vc->estimator;	if (!est)		goto out;	ncells = est->cells;	rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval);	est->last_cells = ncells;	est->avcps += ((long)rate - (long)est->avcps) >> est->ewma_log;	est->cps = (est->avcps + 0x1f) >> 5;	cps = est->cps;	if (cps < (est->maxcps >> 4))		cps = est->maxcps >> 4;	lacr = idt77252_rate_logindex(card, cps);	if (lacr > vc->max_er)		lacr = vc->max_er;	if (lacr != vc->lacr) {		vc->lacr = lacr;		writel(TCMDQ_LACR|(vc->lacr << 16)|vc->index, SAR_REG_TCMDQ);	}	est->timer.expires = jiffies + ((HZ / 4) << est->interval);	add_timer(&est->timer);out:	spin_unlock_irqrestore(&vc->lock, flags);}static struct rate_estimator *idt77252_init_est(struct vc_map *vc, int pcr){	struct rate_estimator *est;	est = kmalloc(sizeof(struct rate_estimator), GFP_KERNEL);	if (!est)		return NULL;	memset(est, 0, sizeof(*est));	est->maxcps = pcr < 0 ? -pcr : pcr;	est->cps = est->maxcps;	est->avcps = est->cps << 5;	est->interval = 2;		/* XXX: make this configurable */	est->ewma_log = 2;		/* XXX: make this configurable */	est->timer.data = (unsigned long)vc;	est->timer.function = idt77252_est_timer;	init_timer(&est->timer);	est->timer.expires = jiffies + ((HZ / 4) << est->interval);	add_timer(&est->timer);	return est;}static intidt77252_init_cbr(struct idt77252_dev *card, struct vc_map *vc,		  struct atm_vcc *vcc, struct atm_qos *qos){	int tst_free, tst_used, tst_entries;	unsigned long tmpl, modl;	int tcr, tcra;	if ((qos->txtp.max_pcr == 0) &&	    (qos->txtp.pcr == 0) && (qos->txtp.min_pcr == 0)) {		printk("%s: trying to open a CBR VC with cell rate = 0\n",		       card->name);		return -EINVAL;	}	tst_used = 0;	tst_free = card->tst_free;	if (test_bit(VCF_TX, &vc->flags))		tst_used = vc->ntste;	tst_free += tst_used;	tcr = atm_pcr_goal(&qos->txtp);	tcra = tcr >= 0 ? tcr : -tcr;	TXPRINTK("%s: CBR target cell rate = %d\n", card->name, tcra);	tmpl = (unsigned long) tcra * ((unsigned long) card->tst_size - 2);	modl = tmpl % (unsigned long)card->utopia_pcr;	tst_entries = (int) (tmpl / card->utopia_pcr);	if (tcr > 0) {		if (modl > 0)			tst_entries++;	} else if (tcr == 0) {		tst_entries = tst_free - SAR_TST_RESERVED;		if (tst_entries <= 0) {			printk("%s: no CBR bandwidth free.\n", card->name);			return -ENOSR;		}	}	if (tst_entries == 0) {		printk("%s: selected CBR bandwidth < granularity.\n",		       card->name);		return -EINVAL;	}	if (tst_entries > (tst_free - SAR_TST_RESERVED)) {		printk("%s: not enough CBR bandwidth free.\n", card->name);		return -ENOSR;	}	vc->ntste = tst_entries;	card->tst_free = tst_free - tst_entries;	if (test_bit(VCF_TX, &vc->flags)) {		if (tst_used == tst_entries)			return 0;		OPRINTK("%s: modify %d -> %d entries in TST.\n",			card->name, tst_used, tst_entries);		change_tst(card, vc, tst_entries, TSTE_OPC_CBR);		return 0;	}	OPRINTK("%s: setting %d entries in TST.\n", card->name, tst_entries);	fill_tst(card, vc, tst_entries, TSTE_OPC_CBR);	return 0;}static intidt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc,		  struct atm_vcc *vcc, struct atm_qos *qos){	unsigned long flags;	int tcr;	spin_lock_irqsave(&vc->lock, flags);	if (vc->estimator) {		del_timer(&vc->estimator->timer);		kfree(vc->estimator);		vc->estimator = NULL;	}	spin_unlock_irqrestore(&vc->lock, flags);	tcr = atm_pcr_goal(&qos->txtp);	if (tcr == 0)		tcr = card->link_pcr;	vc->estimator = idt77252_init_est(vc, tcr);	vc->class = SCHED_UBR;	vc->init_er = idt77252_rate_logindex(card, tcr);	vc->lacr = vc->init_er;	if (tcr < 0)		vc->max_er = vc->init_er;	else		vc->max_er = 0xff;	return 0;}static intidt77252_init_tx(struct idt77252_dev *card, struct vc_map *vc,		 struct atm_vcc *vcc, struct atm_qos *qos){	int error;	if (test_bit(VCF_TX, &vc->flags))		return -EBUSY;	switch (qos->txtp.traffic_class) {		case ATM_CBR:			vc->class = SCHED_CBR;			break;		case ATM_UBR:			vc->class = SCHED_UBR;			break;

⌨️ 快捷键说明

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