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

📄 lanai.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	skb->stamp = xtime;	vcc_rx_memcpy(skb->data, lvcc, size);	lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);	atomic_inc(&lvcc->rx.atmvcc->stats->rx);    out:	lvcc->rx.buf.ptr = end;	cardvcc_write(lvcc, endptr, vcc_rxreadptr);}static void vcc_rx_aal0(struct lanai_dev *lanai){	printk(KERN_INFO DEV_LABEL ": vcc_rx_aal0: not implemented\n");	/* Remember to get vcclist_read_lock while looking up VC */	/* Remember to increment lvcc->rx.atmvcc->stats->rx */}/* -------------------- MANAGING HOST-BASED VCC TABLE: *//* Decide whether to use vmalloc or get_free_page for VCC table */#if (NUM_VCI * BITS_PER_LONG) <= PAGE_SIZE#define VCCTABLE_GETFREEPAGE#else#include <linux/vmalloc.h>#endifstatic int __init vcc_table_allocate(struct lanai_dev *lanai){#ifdef VCCTABLE_GETFREEPAGE	APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE,	    "vcc table > PAGE_SIZE!");	lanai->vccs = (struct lanai_vcc **) get_free_page(GFP_KERNEL);	return (lanai->vccs == NULL) ? -ENOMEM : 0;#else	int bytes = (lanai->num_vci) * sizeof(struct lanai_vcc *);	lanai->vccs = (struct lanai_vcc **) vmalloc(bytes);	if (lanai->vccs == NULL)		return -ENOMEM;	memset(lanai->vccs, 0, bytes);	return 0;#endif}static inline void vcc_table_deallocate(const struct lanai_dev *lanai){#ifdef VCCTABLE_GETFREEPAGE	free_page((unsigned long) lanai->vccs);#else	vfree(lanai->vccs);#endif}/* Allocate a fresh lanai_vcc, with the appropriate things cleared */static inline struct lanai_vcc *new_lanai_vcc(void){	struct lanai_vcc *lvcc;	lvcc = (struct lanai_vcc *) kmalloc(sizeof(*lvcc), GFP_KERNEL);	if (lvcc != NULL) {		lvcc->vbase = 0;		lvcc->rx.atmvcc = lvcc->tx.atmvcc = NULL;		lvcc->nref = 0;		memset(&lvcc->stats, 0, sizeof lvcc->stats);		lvcc->rx.buf.start = lvcc->tx.buf.start = NULL;		skb_queue_head_init(&lvcc->tx.backlog);		lvcc->tx.inprogress = NULL;#ifdef DEBUG		lvcc->tx.unqueue = NULL;		lvcc->vci = -1;#endif	}	return lvcc;}static int lanai_get_sized_buffer(int number, struct lanai_buffer *buf,	int max_sdu, int multiplier, int min, const char *name){	int size;	if (max_sdu < 1)		max_sdu = 1;	max_sdu = aal5_size(max_sdu);	size = (max_sdu + 16) * multiplier + 16;	lanai_buf_allocate(buf, size, min);	if (buf->order < 0)		return -ENOMEM;	if (lanai_buf_size(buf) < size)		printk(KERN_WARNING DEV_LABEL "(itf %d): wanted %d bytes "		    "for %s buffer, got only %d\n", number, size, name,		    lanai_buf_size(buf));	DPRINTK("Allocated %d byte %s buffer\n", lanai_buf_size(buf), name);	return 0;}/* Setup a RX buffer for a currently unbound AAL5 vci */static inline int lanai_setup_rx_vci_aal5(int number, struct lanai_vcc *lvcc,	const struct atm_qos *qos){	return lanai_get_sized_buffer(number, &lvcc->rx.buf,	    qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, qos->rxtp.max_sdu + 32,	    "RX");}/* Setup a TX buffer for a currently unbound AAL5 vci */static int lanai_setup_tx_vci(int number, struct lanai_vcc *lvcc,	const struct atm_qos *qos){	int max_sdu, multiplier;	if (qos->aal == ATM_AAL0) {		lvcc->tx.unqueue = vcc_tx_unqueue_aal0;		max_sdu = ATM_CELL_SIZE - 1;		multiplier = AAL0_TX_MULTIPLIER;	} else {		lvcc->tx.unqueue = vcc_tx_unqueue_aal5;		max_sdu = qos->txtp.max_sdu;		multiplier = AAL5_TX_MULTIPLIER;	}	return lanai_get_sized_buffer(number, &lvcc->tx.buf, max_sdu,	    multiplier, 80, "TX");}static inline void host_vcc_bind(struct lanai_dev *lanai,	struct lanai_vcc *lvcc, vci_t vci){	if (lvcc->vbase != 0)		return;    /* We already were bound in the other direction */	DPRINTK("Binding vci %d\n", vci);#ifdef USE_POWERDOWN	if (lanai->nbound++ == 0) {		DPRINTK("Coming out of powerdown\n");		lanai->conf1 &= ~CONFIG1_POWERDOWN;		conf1_write(lanai);		conf2_write(lanai);	}#endif	lvcc->vbase = cardvcc_addr(lanai, vci);	lanai->vccs[lvcc->vci = vci] = lvcc;}static inline void host_vcc_unbind(struct lanai_dev *lanai,	struct lanai_vcc *lvcc){	if (lvcc->vbase == 0)		return;	/* This vcc was never bound */	DPRINTK("Unbinding vci %d\n", lvcc->vci);	lvcc->vbase = 0;	lanai->vccs[lvcc->vci] = NULL;#ifdef USE_POWERDOWN	if (--lanai->nbound == 0) {		DPRINTK("Going into powerdown\n");		lanai->conf1 |= CONFIG1_POWERDOWN;		conf1_write(lanai);	}#endif}/* -------------------- RESET CARD: */static void lanai_reset(struct lanai_dev *lanai){	printk(KERN_CRIT DEV_LABEL "(itf %d): *NOT* reseting - not "	    "implemented\n", lanai->number);	/* TODO */	/* The following is just a hack until we write the real	 * resetter - at least ack whatever interrupt sent us	 * here	 */	reg_write(lanai, INT_ALL, IntAck_Reg);	lanai->stats.card_reset++;}/* -------------------- SERVICE LIST UTILITIES: *//* * Allocate service buffer and tell card about it */static int __init service_buffer_allocate(struct lanai_dev *lanai){	lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 0);	if (lanai->service.order < 0)		return -ENOMEM;	DPRINTK("allocated service buffer at 0x%08lX, size %d(%d)\n",	    (unsigned long) lanai->service.start,	    lanai_buf_size(&lanai->service),	    lanai_buf_size_cardorder(&lanai->service));	/* Clear ServWrite register to be safe */	reg_write(lanai, 0, ServWrite_Reg);	/* ServiceStuff register contains size and address of buffer */	reg_write(lanai,	    SSTUFF_SET_SIZE(lanai_buf_size_cardorder(&lanai->service)) |	    SSTUFF_SET_ADDR(lanai_buf_dmaaddr(&lanai->service)),	    ServiceStuff_Reg);	return 0;}static inline void service_buffer_deallocate(struct lanai_dev *lanai){	lanai_buf_deallocate(&lanai->service);}/* Bitfields in service list */#define SERVICE_TX	(0x80000000)	/* Was from transmission */#define SERVICE_TRASH	(0x40000000)	/* RXed PDU was trashed */#define SERVICE_CRCERR	(0x20000000)	/* RXed PDU had CRC error */#define SERVICE_CI	(0x10000000)	/* RXed PDU had CI set */#define SERVICE_CLP	(0x08000000)	/* RXed PDU had CLP set */#define SERVICE_STREAM	(0x04000000)	/* RX Stream mode */#define SERVICE_GET_VCI(x) (((x)>>16)&0x3FF)#define SERVICE_GET_END(x) ((x)&0x1FFF)/* Handle one thing from the service list - returns true if it marked a * VCC ready for xmit */static int handle_service(struct lanai_dev *lanai, u32 s){	vci_t vci = SERVICE_GET_VCI(s);	struct lanai_vcc *lvcc;	vcclist_read_lock();	lvcc = lanai->vccs[vci];	if (lvcc == NULL) {		vcclist_read_unlock();		DPRINTK("(itf %d) got service entry 0x%X for nonexistent "		    "vcc %d\n", lanai->number, s, vci);		if (s & SERVICE_TX)			lanai->stats.service_novcc_tx++;		else			lanai->stats.service_novcc_rx++;		return 0;	}	if (s & SERVICE_TX) {			/* segmentation interrupt */		if (lvcc->tx.atmvcc == NULL) {			vcclist_read_unlock();			DPRINTK("(itf %d) got service entry 0x%X for non-TX "			    "vcc %d\n", lanai->number, s, vci);			lanai->stats.service_notx++;			return 0;		}		vci_bitfield_set(&lanai->transmit_ready, vci);		lvcc->tx.endptr = SERVICE_GET_END(s);		vcclist_read_unlock();		return 1;	}	if (lvcc->rx.atmvcc == NULL) {		vcclist_read_unlock();		DPRINTK("(itf %d) got service entry 0x%X for non-RX "		    "vcc %d\n", lanai->number, s, vci);		lanai->stats.service_norx++;		return 0;	}	if (lvcc->rx.atmvcc->qos.aal != ATM_AAL5) {		vcclist_read_unlock();		DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "		    "vcc %d\n", lanai->number, s, vci);		lanai->stats.service_rxnotaal5++;		atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);		return 0;	}	if ((s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)) == 0) {		vcc_rx_aal5(lvcc, SERVICE_GET_END(s));		vcclist_read_unlock();		return 0;	}	if (s & SERVICE_TRASH) {		int bytes;		vcclist_read_unlock();		DPRINTK("got trashed rx pdu on vci %d\n", vci);		atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);		lvcc->stats.x.aal5.service_trash++;		bytes = (SERVICE_GET_END(s) * 16) -		    (((unsigned long) lvcc->rx.buf.ptr) -		    ((unsigned long) lvcc->rx.buf.start)) + 47;		if (bytes < 0)			bytes += lanai_buf_size(&lvcc->rx.buf);		lanai->stats.ovfl_trash += (bytes / 48);		return 0;	}	if (s & SERVICE_STREAM) {		vcclist_read_unlock();		atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);		lvcc->stats.x.aal5.service_stream++;		printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "		    "PDU on VCI %d!\n", lanai->number, vci);		lanai_reset(lanai);		return 0;	}	DPRINTK("got rx crc error on vci %d\n", vci);	atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);	lvcc->stats.x.aal5.service_rxcrc++;	lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];	cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);	vcclist_read_unlock();	return 0;}/* Try transmitting on all VCIs that we marked ready to serve */static void iter_transmit(struct lanai_dev *lanai, vci_t vci){	struct lanai_vcc *lvcc = lanai->vccs[vci];	if (!vcc_is_backlogged(lvcc))		return;	lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr);}/* Run service queue -- called from interrupt context or with * interrupts otherwise disabled and with the lanai->servicelock * lock held */static void run_service(struct lanai_dev *lanai){	int ntx = 0;	u32 wreg = reg_read(lanai, ServWrite_Reg);	const u32 *end = lanai->service.start + wreg;	while (lanai->service.ptr != end) {		ntx += handle_service(lanai,		    le32_to_cpup(lanai->service.ptr++));		if (lanai->service.ptr >= lanai->service.end)			lanai->service.ptr = lanai->service.start;	}	reg_write(lanai, wreg, ServRead_Reg);	if (ntx != 0) {		spin_lock(&lanai->txlock);		vcclist_read_lock();		vci_bitfield_iterate(lanai, &lanai->transmit_ready,		    iter_transmit);		vci_bitfield_init(&lanai->transmit_ready);		vcclist_read_unlock();		spin_unlock(&lanai->txlock);	}}/* -------------------- GATHER STATISTICS: */static void get_statistics(struct lanai_dev *lanai){	u32 statreg = reg_read(lanai, Statistics_Reg);	lanai->stats.atm_ovfl += STATS_GET_FIFO_OVFL(statreg);	lanai->stats.hec_err += STATS_GET_HEC_ERR(statreg);	lanai->stats.vci_trash += STATS_GET_BAD_VCI(statreg);	lanai->stats.ovfl_trash += STATS_GET_BUF_OVFL(statreg);}/* -------------------- POLLING TIMER: */static void lanai_timed_poll(unsigned long arg){#ifndef DEBUG_RW	struct lanai_dev *lanai = (struct lanai_dev *) arg;	unsigned long flags;#ifdef USE_POWERDOWN	if (lanai->conf1 & CONFIG1_POWERDOWN)		return;#endif	spin_lock_irqsave(&lanai->servicelock, flags);	run_service(lanai);	spin_unlock_irqrestore(&lanai->servicelock, flags);	vcc_tx_dequeue_all(lanai);	get_statistics(lanai);	mod_timer(&lanai->timer, jiffies + LANAI_POLL_PERIOD);#endif /* DEBUG_RW */}static inline void lanai_timed_poll_start(struct lanai_dev *lanai){	init_timer(&lanai->timer);	lanai->timer.expires = jiffies + LANAI_POLL_PERIOD;	lanai->timer.data = (unsigned long) lanai;	lanai->timer.function = lanai_timed_poll;	add_timer(&lanai->timer);}static inline void lanai_timed_poll_stop(struct lanai_dev *lanai){	del_timer(&lanai->timer);}/* -------------------- INTERRUPT SERVICE: */static inline void lanai_int_1(struct lanai_dev *lanai, u32 reason){	u32 ack = 0;	if (reason & INT_SERVICE) {		ack = INT_SERVICE;		spin_lock(&lanai->servicelock);		run_service(lanai);		spin_unlock(&lanai->servicelock);	}	if (reason & (INT_AAL0_STR | INT_AAL0)) {		ack |= reason & (INT_AAL0_STR | INT_AAL0);		vcc_rx_aal0(lanai);	}	if (reason & INT_STATS) {		reason &= ~INT_STATS;	/* No need to ack */		get_statistics(lanai);	}	if (reason & INT_STATUS) {		ack |= reason & INT_STATUS;		lanai_check_status(lanai);	}	if (reason & INT_DMASHUT) {		printk(KERN_ERR DEV_LABEL "(itf %d): driver error - DMA "		    

⌨️ 快捷键说明

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