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

📄 he.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		he_writel(he_dev, 0x006f, G6_INMQ_S);		he_writel(he_dev, 0x206f, G6_INMQ_L);		he_writel(he_dev, 0x007f, G7_INMQ_S);		he_writel(he_dev, 0x207f, G7_INMQ_L);	} else {		he_writel(he_dev, 0x0000, G0_INMQ_S);		he_writel(he_dev, 0x0008, G0_INMQ_L);		he_writel(he_dev, 0x0001, G1_INMQ_S);		he_writel(he_dev, 0x0009, G1_INMQ_L);		he_writel(he_dev, 0x0002, G2_INMQ_S);		he_writel(he_dev, 0x000a, G2_INMQ_L);		he_writel(he_dev, 0x0003, G3_INMQ_S);		he_writel(he_dev, 0x000b, G3_INMQ_L);		he_writel(he_dev, 0x0004, G4_INMQ_S);		he_writel(he_dev, 0x000c, G4_INMQ_L);		he_writel(he_dev, 0x0005, G5_INMQ_S);		he_writel(he_dev, 0x000d, G5_INMQ_L);		he_writel(he_dev, 0x0006, G6_INMQ_S);		he_writel(he_dev, 0x000e, G6_INMQ_L);		he_writel(he_dev, 0x0007, G7_INMQ_S);		he_writel(he_dev, 0x000f, G7_INMQ_L);	}	/* 5.1.6 application tunable parameters */	he_writel(he_dev, 0x0, MCC);	he_writel(he_dev, 0x0, OEC);	he_writel(he_dev, 0x0, DCC);	he_writel(he_dev, 0x0, CEC);		/* 5.1.7 cs block initialization */	he_init_cs_block(he_dev);	/* 5.1.8 cs block connection memory initialization */		if (he_init_cs_block_rcm(he_dev) < 0)		return -ENOMEM;	/* 5.1.10 initialize host structures */	he_init_tpdrq(he_dev);#ifdef USE_TPD_POOL	he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,		sizeof(struct he_tpd), TPD_ALIGNMENT, 0);	if (he_dev->tpd_pool == NULL) {		hprintk("unable to create tpd pci_pool\n");		return -ENOMEM;         	}	INIT_LIST_HEAD(&he_dev->outstanding_tpds);#else	he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev,			CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys);	if (!he_dev->tpd_base)		return -ENOMEM;	for (i = 0; i < CONFIG_NUMTPDS; ++i) {		he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT);		he_dev->tpd_base[i].inuse = 0;	}			he_dev->tpd_head = he_dev->tpd_base;	he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS - 1];#endif	if (he_init_group(he_dev, 0) != 0)		return -ENOMEM;	for (group = 1; group < HE_NUM_GROUPS; ++group) {		he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));		he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));		he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));		he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),						G0_RBPS_BS + (group * 32));		he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32));		he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32));		he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),						G0_RBPL_QI + (group * 32));		he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32));		he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16));		he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16));		he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0),						G0_RBRQ_Q + (group * 16));		he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16));		he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16));		he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16));		he_writel(he_dev, TBRQ_THRESH(0x1),						G0_TBRQ_THRESH + (group * 16));		he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16));	}	/* host status page */	he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,				sizeof(struct he_hsp), &he_dev->hsp_phys);	if (he_dev->hsp == NULL) {		hprintk("failed to allocate host status page\n");		return -ENOMEM;	}	memset(he_dev->hsp, 0, sizeof(struct he_hsp));	he_writel(he_dev, he_dev->hsp_phys, HSP_BA);	/* initialize framer */#ifdef CONFIG_ATM_HE_USE_SUNI	suni_init(he_dev->atm_dev);	if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start)		he_dev->atm_dev->phy->start(he_dev->atm_dev);#endif /* CONFIG_ATM_HE_USE_SUNI */	if (sdh) {		/* this really should be in suni.c but for now... */		int val;		val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);		val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT);		he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);	}	/* 5.1.12 enable transmit and receive */	reg = he_readl_mbox(he_dev, CS_ERCTL0);	reg |= TX_ENABLE|ER_ENABLE;	he_writel_mbox(he_dev, reg, CS_ERCTL0);	reg = he_readl(he_dev, RC_CONFIG);	reg |= RX_ENABLE;	he_writel(he_dev, reg, RC_CONFIG);	for (i = 0; i < HE_NUM_CS_STPER; ++i) {		he_dev->cs_stper[i].inuse = 0;		he_dev->cs_stper[i].pcr = -1;	}	he_dev->total_bw = 0;	/* atm linux initialization */	he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;	he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;	he_dev->irq_peak = 0;	he_dev->rbrq_peak = 0;	he_dev->rbpl_peak = 0;	he_dev->tbrq_peak = 0;	HPRINTK("hell bent for leather!\n");	return 0;}static voidhe_stop(struct he_dev *he_dev){	u16 command;	u32 gen_cntl_0, reg;	struct pci_dev *pci_dev;	pci_dev = he_dev->pci_dev;	/* disable interrupts */	if (he_dev->membase) {		pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0);		gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB);		pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);#ifdef USE_TASKLET		tasklet_disable(&he_dev->tasklet);#endif		/* disable recv and transmit */		reg = he_readl_mbox(he_dev, CS_ERCTL0);		reg &= ~(TX_ENABLE|ER_ENABLE);		he_writel_mbox(he_dev, reg, CS_ERCTL0);		reg = he_readl(he_dev, RC_CONFIG);		reg &= ~(RX_ENABLE);		he_writel(he_dev, reg, RC_CONFIG);	}#ifdef CONFIG_ATM_HE_USE_SUNI	if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop)		he_dev->atm_dev->phy->stop(he_dev->atm_dev);#endif /* CONFIG_ATM_HE_USE_SUNI */	if (he_dev->irq)		free_irq(he_dev->irq, he_dev);	if (he_dev->irq_base)		pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1)			* sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys);	if (he_dev->hsp)		pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp),						he_dev->hsp, he_dev->hsp_phys);	if (he_dev->rbpl_base) {#ifdef USE_RBPL_POOL		for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {			void *cpuaddr = he_dev->rbpl_virt[i].virt;			dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;			pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);		}#else		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE			* CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys);#endif		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE			* sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);	}#ifdef USE_RBPL_POOL	if (he_dev->rbpl_pool)		pci_pool_destroy(he_dev->rbpl_pool);#endif#ifdef USE_RBPS	if (he_dev->rbps_base) {#ifdef USE_RBPS_POOL		for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {			void *cpuaddr = he_dev->rbps_virt[i].virt;			dma_addr_t dma_handle = he_dev->rbps_base[i].phys;			pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);		}#else		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE			* CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys);#endif		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE			* sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);	}#ifdef USE_RBPS_POOL	if (he_dev->rbps_pool)		pci_pool_destroy(he_dev->rbps_pool);#endif#endif /* USE_RBPS */	if (he_dev->rbrq_base)		pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),							he_dev->rbrq_base, he_dev->rbrq_phys);	if (he_dev->tbrq_base)		pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),							he_dev->tbrq_base, he_dev->tbrq_phys);	if (he_dev->tpdrq_base)		pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),							he_dev->tpdrq_base, he_dev->tpdrq_phys);#ifdef USE_TPD_POOL	if (he_dev->tpd_pool)		pci_pool_destroy(he_dev->tpd_pool);#else	if (he_dev->tpd_base)		pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd),							he_dev->tpd_base, he_dev->tpd_base_phys);#endif	if (he_dev->pci_dev) {		pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);		command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);		pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command);	}		if (he_dev->membase)		iounmap(he_dev->membase);}static struct he_tpd *__alloc_tpd(struct he_dev *he_dev){#ifdef USE_TPD_POOL	struct he_tpd *tpd;	dma_addr_t dma_handle; 	tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle);	if (tpd == NULL)		return NULL;				tpd->status = TPD_ADDR(dma_handle);	tpd->reserved = 0; 	tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;	tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;	tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0;	return tpd;#else	int i;	for (i = 0; i < CONFIG_NUMTPDS; ++i) {		++he_dev->tpd_head;		if (he_dev->tpd_head > he_dev->tpd_end) {			he_dev->tpd_head = he_dev->tpd_base;		}		if (!he_dev->tpd_head->inuse) {			he_dev->tpd_head->inuse = 1;			he_dev->tpd_head->status &= TPD_MASK;			he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0;			he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0;			he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0;			return he_dev->tpd_head;		}	}	hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS);	return NULL;#endif}#define AAL5_LEN(buf,len) 						\			((((unsigned char *)(buf))[(len)-6] << 8) |	\				(((unsigned char *)(buf))[(len)-5]))/* 2.10.1.2 receive * * aal5 packets can optionally return the tcp checksum in the lower * 16 bits of the crc (RSR0_TCP_CKSUM) */#define TCP_CKSUM(buf,len) 						\			((((unsigned char *)(buf))[(len)-2] << 8) |	\				(((unsigned char *)(buf))[(len-1)]))static inthe_service_rbrq(struct he_dev *he_dev, int group){	struct he_rbrq *rbrq_tail = (struct he_rbrq *)				((unsigned long)he_dev->rbrq_base |					he_dev->hsp->group[group].rbrq_tail);	struct he_rbp *rbp = NULL;	unsigned cid, lastcid = -1;	unsigned buf_len = 0;	struct sk_buff *skb;	struct atm_vcc *vcc = NULL;	struct he_vcc *he_vcc;	struct he_iovec *iov;	int pdus_assembled = 0;	int updated = 0;	read_lock(&vcc_sklist_lock);	while (he_dev->rbrq_head != rbrq_tail) {		++updated;		HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n",			he_dev->rbrq_head, group,			RBRQ_ADDR(he_dev->rbrq_head),			RBRQ_BUFLEN(he_dev->rbrq_head),			RBRQ_CID(he_dev->rbrq_head),			RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "",			RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "",			RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "",			RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "",			RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",			RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");#ifdef USE_RBPS		if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)			rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];		else#endif			rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];				buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;		cid = RBRQ_CID(he_dev->rbrq_head);		if (cid != lastcid)			vcc = __find_vcc(he_dev, cid);		lastcid = cid;		if (vcc == NULL) {			hprintk("vcc == NULL  (cid 0x%x)\n", cid);			if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))					rbp->status &= ~RBP_LOANED;								goto next_rbrq_entry;		}		he_vcc = HE_VCC(vcc);		if (he_vcc == NULL) {			hprintk("he_vcc == NULL  (cid 0x%x)\n", cid);			if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))					rbp->status &= ~RBP_LOANED;			goto next_rbrq_entry;		}		if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) {			hprintk("HBUF_ERR!  (cid 0x%x)\n", cid);				atomic_inc(&vcc->stats->rx_drop);			goto return_host_buffers;		}		he_vcc->iov_tail->iov_base = RBRQ_ADDR(he_dev->rbrq_head);		he_vcc->iov_tail->iov_len = buf_len;		he_vcc->pdu_len += buf_len;		++he_vcc->iov_tail;		if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) {			lastcid = -1;			HPRINTK("wake_up rx_waitq  (cid 0x%x)\n", cid);			wake_up(&he_vcc->rx_waitq);			goto return_host_buffers;		}#ifdef notdef		if ((he_vcc->iov_tail - he_vcc->iov_head) > HE_MAXIOV) {			hprintk("iovec full!  cid 0x%x\n", cid);			goto return_host_buffers;		}#endif		if (!RBRQ_END_PDU(he_dev->rbrq_head))			goto next_rbrq_entry;		if (RBRQ_LEN_ERR(he_dev->rbrq_head)				|| RBRQ_CRC_ERR(he_dev->rbrq_head)) {			HPRINTK("%s%s (%d.%d)\n",				RBRQ_CRC_ERR(he_dev->rbrq_head)							? "CRC_ERR " : "",				RBRQ_LEN_ERR(he_dev->rbrq_head)							? "LEN_ERR" : "",							vcc->vpi, vcc->vci);			atomic_inc(&vcc->stats->rx_err);			goto return_host_buffers;		}		skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,							GFP_ATOMIC);		if (!skb) {			HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);			goto return_host_buffers;		}		if (rx_skb_reserve > 0)			skb_reserve(skb, rx_skb_reserve);		__net_timestamp(skb);		for (iov = he_vcc->iov_head;				iov < he_vcc->iov_tail; ++iov) {#ifdef USE_RBPS			if (iov->iov_base & RBP_SMALLBUF)				memcpy(skb_put(skb, iov->iov_len),					he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);			else#endif				memcpy(skb_put(skb, iov->iov_len),					he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);		}		switch (vcc->qos.aal) {			case ATM_AAL0:				/* 2.10.1.5 raw cell receive */				skb->len = ATM_AAL0_SDU;				skb_set_tail_pointer(skb, skb->len);				break;			case ATM_AAL5:				/* 2.10.1.2 aal5 receive */

⌨️ 快捷键说明

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