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

📄 idt77252.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		printk("%s: Connection %d:\n", card->name, vc->index);		dump_tct(card, vc->index);	}}#endif/*****************************************************************************//*                                                                           *//* SCQ Handling                                                              *//*                                                                           *//*****************************************************************************/static intsb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue){	struct sb_pool *pool = &card->sbpool[queue];	int index;	index = pool->index;	while (pool->skb[index]) {		index = (index + 1) & FBQ_MASK;		if (index == pool->index)			return -ENOBUFS;	}	pool->skb[index] = skb;	IDT77252_PRV_POOL(skb) = POOL_HANDLE(queue, index);	pool->index = (index + 1) & FBQ_MASK;	return 0;}static voidsb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb){	unsigned int queue, index;	u32 handle;	handle = IDT77252_PRV_POOL(skb);	queue = POOL_QUEUE(handle);	if (queue > 3)		return;	index = POOL_INDEX(handle);	if (index > FBQ_SIZE - 1)		return;	card->sbpool[queue].skb[index] = NULL;}static struct sk_buff *sb_pool_skb(struct idt77252_dev *card, u32 handle){	unsigned int queue, index;	queue = POOL_QUEUE(handle);	if (queue > 3)		return NULL;	index = POOL_INDEX(handle);	if (index > FBQ_SIZE - 1)		return NULL;	return card->sbpool[queue].skb[index];}static struct scq_info *alloc_scq(struct idt77252_dev *card, int class){	struct scq_info *scq;	scq = (struct scq_info *) kmalloc(sizeof(struct scq_info), GFP_KERNEL);	if (!scq)		return NULL;	memset(scq, 0, sizeof(struct scq_info));	scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE,					 &scq->paddr);	if (scq->base == NULL) {		kfree(scq);		return NULL;	}	memset(scq->base, 0, SCQ_SIZE);	scq->next = scq->base;	scq->last = scq->base + (SCQ_ENTRIES - 1);	atomic_set(&scq->used, 0);	spin_lock_init(&scq->lock);	spin_lock_init(&scq->skblock);	skb_queue_head_init(&scq->transmit);	skb_queue_head_init(&scq->pending);	TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08x\n",		 scq->base, scq->next, scq->last, scq->paddr);	return scq;}static voidfree_scq(struct idt77252_dev *card, struct scq_info *scq){	struct sk_buff *skb;	struct atm_vcc *vcc;	pci_free_consistent(card->pcidev, SCQ_SIZE,			    scq->base, scq->paddr);	while ((skb = skb_dequeue(&scq->transmit))) {		pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),				 skb->len, PCI_DMA_TODEVICE);		vcc = ATM_SKB(skb)->vcc;		if (vcc->pop)			vcc->pop(vcc, skb);		else			dev_kfree_skb(skb);	}	while ((skb = skb_dequeue(&scq->pending))) {		pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),				 skb->len, PCI_DMA_TODEVICE);		vcc = ATM_SKB(skb)->vcc;		if (vcc->pop)			vcc->pop(vcc, skb);		else			dev_kfree_skb(skb);	}	kfree(scq);}static intpush_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb){	struct scq_info *scq = vc->scq;	unsigned long flags;	struct scqe *tbd;	int entries;	TXPRINTK("%s: SCQ: next 0x%p\n", card->name, scq->next);	atomic_inc(&scq->used);	entries = atomic_read(&scq->used);	if (entries > (SCQ_ENTRIES - 1)) {		atomic_dec(&scq->used);		goto out;	}	skb_queue_tail(&scq->transmit, skb);	spin_lock_irqsave(&vc->lock, flags);	if (vc->estimator) {		struct atm_vcc *vcc = vc->tx_vcc;		vc->estimator->cells += (skb->len + 47) / 48;		if (atomic_read(&vcc->tx_inuse) > (vcc->sk->sndbuf >> 1)) {			u32 cps = vc->estimator->maxcps;			vc->estimator->cps = cps;			vc->estimator->avcps = cps << 5;			if (vc->lacr < vc->init_er) {				vc->lacr = vc->init_er;				writel(TCMDQ_LACR | (vc->lacr << 16) |				       vc->index, SAR_REG_TCMDQ);			}		}	}	spin_unlock_irqrestore(&vc->lock, flags);	tbd = &IDT77252_PRV_TBD(skb);	spin_lock_irqsave(&scq->lock, flags);	scq->next->word_1 = cpu_to_le32(tbd->word_1 |					SAR_TBD_TSIF | SAR_TBD_GTSI);	scq->next->word_2 = cpu_to_le32(tbd->word_2);	scq->next->word_3 = cpu_to_le32(tbd->word_3);	scq->next->word_4 = cpu_to_le32(tbd->word_4);	if (scq->next == scq->last)		scq->next = scq->base;	else		scq->next++;	write_sram(card, scq->scd,		   scq->paddr +		   (u32)((unsigned long)scq->next - (unsigned long)scq->base));	spin_unlock_irqrestore(&scq->lock, flags);	scq->trans_start = jiffies;	if (test_and_clear_bit(VCF_IDLE, &vc->flags)) {		writel(TCMDQ_START_LACR | (vc->lacr << 16) | vc->index,		       SAR_REG_TCMDQ);	}	TXPRINTK("%d entries in SCQ used (push).\n", atomic_read(&scq->used));	XPRINTK("%s: SCQ (after push %2d) head = 0x%x, next = 0x%p.\n",		card->name, atomic_read(&scq->used),		read_sram(card, scq->scd + 1), scq->next);	return 0;out:	if (jiffies - scq->trans_start > HZ) {		printk("%s: Error pushing TBD for %d.%d\n",		       card->name, vc->tx_vcc->vpi, vc->tx_vcc->vci);#ifdef CONFIG_ATM_IDT77252_DEBUG		idt77252_tx_dump(card);#endif		scq->trans_start = jiffies;	}	return -ENOBUFS;}static voiddrain_scq(struct idt77252_dev *card, struct vc_map *vc){	struct scq_info *scq = vc->scq;	struct sk_buff *skb;	struct atm_vcc *vcc;	TXPRINTK("%s: SCQ (before drain %2d) next = 0x%p.\n",		 card->name, atomic_read(&scq->used), scq->next);	skb = skb_dequeue(&scq->transmit);	if (skb) {		TXPRINTK("%s: freeing skb at %p.\n", card->name, skb);		pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),				 skb->len, PCI_DMA_TODEVICE);		vcc = ATM_SKB(skb)->vcc;		if (vcc->pop)			vcc->pop(vcc, skb);		else			dev_kfree_skb(skb);		atomic_inc(&vcc->stats->tx);	}	atomic_dec(&scq->used);	spin_lock(&scq->skblock);	while ((skb = skb_dequeue(&scq->pending))) {		if (push_on_scq(card, vc, skb)) {			skb_queue_head(&vc->scq->pending, skb);			break;		}	}	spin_unlock(&scq->skblock);}static intqueue_skb(struct idt77252_dev *card, struct vc_map *vc,	  struct sk_buff *skb, int oam){	struct atm_vcc *vcc;	struct scqe *tbd;	unsigned long flags;	int error;	int aal;	if (skb->len == 0) {		printk("%s: invalid skb->len (%d)\n", card->name, skb->len);		return -EINVAL;	}	TXPRINTK("%s: Sending %d bytes of data.\n",		 card->name, skb->len);	tbd = &IDT77252_PRV_TBD(skb);	vcc = ATM_SKB(skb)->vcc;	IDT77252_PRV_PADDR(skb) = pci_map_single(card->pcidev, skb->data,						 skb->len, PCI_DMA_TODEVICE);	error = -EINVAL;	if (oam) {		if (skb->len != 52)			goto errout;		tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;		tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;		tbd->word_3 = 0x00000000;		tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |			      (skb->data[2] <<  8) | (skb->data[3] <<  0);		if (test_bit(VCF_RSV, &vc->flags))			vc = card->vcs[0];		goto done;	}	if (test_bit(VCF_RSV, &vc->flags)) {		printk("%s: Trying to transmit on reserved VC\n", card->name);		goto errout;	}	aal = vcc->qos.aal;	switch (aal) {	case ATM_AAL0:	case ATM_AAL34:		if (skb->len > 52)			goto errout;		if (aal == ATM_AAL0)			tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL0 |				      ATM_CELL_PAYLOAD;		else			tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL34 |				      ATM_CELL_PAYLOAD;		tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;		tbd->word_3 = 0x00000000;		tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |			      (skb->data[2] <<  8) | (skb->data[3] <<  0);		break;	case ATM_AAL5:		tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL5 | skb->len;		tbd->word_2 = IDT77252_PRV_PADDR(skb);		tbd->word_3 = skb->len;		tbd->word_4 = (vcc->vpi << SAR_TBD_VPI_SHIFT) |			      (vcc->vci << SAR_TBD_VCI_SHIFT);		break;	case ATM_AAL1:	case ATM_AAL2:	default:		printk("%s: Traffic type not supported.\n", card->name);		error = -EPROTONOSUPPORT;		goto errout;	}done:	spin_lock_irqsave(&vc->scq->skblock, flags);	skb_queue_tail(&vc->scq->pending, skb);	while ((skb = skb_dequeue(&vc->scq->pending))) {		if (push_on_scq(card, vc, skb)) {			skb_queue_head(&vc->scq->pending, skb);			break;		}	}	spin_unlock_irqrestore(&vc->scq->skblock, flags);	return 0;errout:	pci_unmap_single(card->pcidev, IDT77252_PRV_PADDR(skb),			 skb->len, PCI_DMA_TODEVICE);	return error;}static unsigned longget_free_scd(struct idt77252_dev *card, struct vc_map *vc){	int i;	for (i = 0; i < card->scd_size; i++) {		if (!card->scd2vc[i]) {			card->scd2vc[i] = vc;			vc->scd_index = i;			return card->scd_base + i * SAR_SRAM_SCD_SIZE;		}	}	return 0;}static voidfill_scd(struct idt77252_dev *card, struct scq_info *scq, int class){	write_sram(card, scq->scd, scq->paddr);	write_sram(card, scq->scd + 1, 0x00000000);	write_sram(card, scq->scd + 2, 0xffffffff);	write_sram(card, scq->scd + 3, 0x00000000);}static voidclear_scd(struct idt77252_dev *card, struct scq_info *scq, int class){	return;}/*****************************************************************************//*                                                                           *//* RSQ Handling                                                              *//*                                                                           *//*****************************************************************************/static intinit_rsq(struct idt77252_dev *card){	struct rsq_entry *rsqe;	card->rsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE,					      &card->rsq.paddr);	if (card->rsq.base == NULL) {		printk("%s: can't allocate RSQ.\n", card->name);		return -1;	}	memset(card->rsq.base, 0, RSQSIZE);	card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1;	card->rsq.next = card->rsq.last;	for (rsqe = card->rsq.base; rsqe <= card->rsq.last; rsqe++)		rsqe->word_4 = 0;	writel((unsigned long) card->rsq.last - (unsigned long) card->rsq.base,	       SAR_REG_RSQH);	writel(card->rsq.paddr, SAR_REG_RSQB);	IPRINTK("%s: RSQ base at 0x%lx (0x%x).\n", card->name,		(unsigned long) card->rsq.base,		readl(SAR_REG_RSQB));	IPRINTK("%s: RSQ head = 0x%x, base = 0x%x, tail = 0x%x.\n",		card->name,		readl(SAR_REG_RSQH),		readl(SAR_REG_RSQB),		readl(SAR_REG_RSQT));	return 0;}static voiddeinit_rsq(struct idt77252_dev *card){	pci_free_consistent(card->pcidev, RSQSIZE,			    card->rsq.base, card->rsq.paddr);}static voiddequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe){	struct atm_vcc *vcc;	struct sk_buff *skb;	struct rx_pool *rpp;	struct vc_map *vc;	u32 header, vpi, vci;	u32 stat;	int i;	stat = le32_to_cpu(rsqe->word_4);	if (stat & SAR_RSQE_IDLE) {		RXPRINTK("%s: message about inactive connection.\n",			 card->name);		return;	}	skb = sb_pool_skb(card, le32_to_cpu(rsqe->word_2));	if (skb == NULL) {		printk("%s: NULL skb in %s, rsqe: %08x %08x %08x %08x\n",		       card->name, __FUNCTION__,		       le32_to_cpu(rsqe->word_1), le32_to_cpu(rsqe->word_2),		       le32_to_cpu(rsqe->word_3), le32_to_cpu(rsqe->word_4));		return;	}	header = le32_to_cpu(rsqe->word_1);	vpi = (header >> 16) & 0x00ff;	vci = (header >>  0) & 0xffff;	RXPRINTK("%s: SDU for %d.%d received in buffer 0x%p (data 0x%p).\n",		 card->name, vpi, vci, skb, skb->data);	if ((vpi >= (1 << card->vpibits)) || (vci != (vci & card->vcimask))) {		printk("%s: SDU received for out-of-range vc %u.%u\n",		       card->name, vpi, vci);		recycle_rx_skb(card, skb);		return;	}	vc = card->vcs[VPCI2VC(card, vpi, vci)];	if (!vc || !test_bit(VCF_RX, &vc->flags)) {		printk("%s: SDU received on non RX vc %u.%u\n",		       card->name, vpi, vci);		recycle_rx_skb(card, skb);		return;	}	vcc = vc->rx_vcc;	pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(skb),			    skb->end - skb->data, PCI_DMA_FROMDEVICE);	if ((vcc->qos.aal == ATM_AAL0) ||	    (vcc->qos.aal == ATM_AAL34)) {		struct sk_buff *sb;		unsigned char *cell;		u32 aal0;		cell = skb->data;		for (i = (stat & SAR_RSQE_CELLCNT); i; i--) {			if ((sb = dev_alloc_skb(64)) == NULL) {				printk("%s: Can't allocate buffers for aal0.\n",				       card->name);				atomic_add(i, &vcc->stats->rx_drop);				break;			}			if (!atm_charge(vcc, sb->truesize)) {				RXPRINTK("%s: atm_charge() dropped aal0 packets.\n",					 card->name);				atomic_add(i - 1, &vcc->stats->rx_drop);				dev_kfree_skb(sb);				break;			}			aal0 = (vpi << ATM_HDR_VPI_SHIFT) |			       (vci << ATM_HDR_VCI_SHIFT);			aal0 |= (stat & SAR_RSQE_EPDU) ? 0x00000002 : 0;			aal0 |= (stat & SAR_RSQE_CLP)  ? 0x00000001 : 0;			*((u32 *) sb->data) = aal0;			skb_put(sb, sizeof(u32));			memcpy(skb_put(sb, ATM_CELL_PAYLOAD),			       cell, ATM_CELL_PAYLOAD);			ATM_SKB(sb)->vcc = vcc;			sb->stamp = xtime;			vcc->push(vcc, sb);			atomic_inc(&vcc->stats->rx);			cell += ATM_CELL_PAYLOAD;		}		recycle_rx_skb(card, skb);		return;	}	if (vcc->qos.aal != ATM_AAL5) {		printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n",		       card->name, vcc->qos.aal);		recycle_rx_skb(card, skb);		return;	}	skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD;	rpp = &vc->rcv.rx_pool;	rpp->len += skb->len;	if (!rpp->count++)		rpp->first = skb;	*rpp->last = skb;	rpp->last = &skb->next;	if (stat & SAR_RSQE_EPDU) {		unsigned char *l1l2;		unsigned int len;		l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);		len = (l1l2[0] << 8) | l1l2[1];		len = len ? len : 0x10000;		RXPRINTK("%s: PDU has %d bytes.\n", card->name, len);		if ((len + 8 > rpp->len) || (len + (47 + 8) < rpp->len)) {			RXPRINTK("%s: AAL5 PDU size mismatch: %d != %d. "

⌨️ 快捷键说明

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