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

📄 lanai.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	u32 val, enum lanai_vcc_offset offset){	APRINTK(lvcc->vbase != 0, "cardvcc_write: unbound vcc!\n");	APRINTK((val & ~0xFFFF) == 0,	    "cardvcc_write: bad val 0x%X (vci=%d, addr=0x%02X)\n",	    val, lvcc->vci, (int) offset);	RWDEBUG("VW vci=%04d 0x%02X > 0x%08X\n",	    lvcc->vci, (int) offset, val);	writel(val, lvcc->vbase + (bus_addr_t) offset);}/* -------------------- COMPUTE SIZE OF AN AAL5 PDU: *//* How many bytes will an AAL5 PDU take to transmit - remember that: *   o  we need to add 8 bytes for length, CPI, UU, and CRC *   o  we need to round up to 48 bytes for cells */static inline int aal5_size(int size){	int cells = (size + 8 + 47) / 48;	return cells * 48;}/* How many bytes can we send if we have "space" space, assuming we have * to send full cells */static inline int aal5_spacefor(int space){	int cells = space / 48;	return cells * 48;}/* -------------------- FREE AN ATM SKB: */static inline void lanai_free_skb(struct atm_vcc *atmvcc, struct sk_buff *skb){	if (atmvcc->pop != NULL)		atmvcc->pop(atmvcc, skb);	else		dev_kfree_skb_any(skb);}/* -------------------- TURN VCCS ON AND OFF: */static void host_vcc_start_rx(const struct lanai_vcc *lvcc){	u32 addr1;	if (lvcc->rx.atmvcc->qos.aal == ATM_AAL5) {		unsigned long dmaaddr = lanai_buf_dmaaddr(&lvcc->rx.buf);		cardvcc_write(lvcc, 0xFFFF, vcc_rxcrc1);		cardvcc_write(lvcc, 0xFFFF, vcc_rxcrc2);		cardvcc_write(lvcc, 0, vcc_rxwriteptr);		cardvcc_write(lvcc, 0, vcc_rxbufstart);		cardvcc_write(lvcc, 0, vcc_rxreadptr);		cardvcc_write(lvcc, (dmaaddr >> 16) & 0xFFFF, vcc_rxaddr2);		addr1 = ((dmaaddr >> 8) & 0xFF) |		    RXADDR1_SET_SIZE(lanai_buf_size_cardorder(&lvcc->rx.buf))|		    RXADDR1_SET_RMMODE(RMMODE_TRASH) |	/* ??? */		 /* RXADDR1_OAM_PRESERVE |	--- no OAM support yet */		    RXADDR1_SET_MODE(RXMODE_AAL5);	} else		addr1 = RXADDR1_SET_RMMODE(RMMODE_PRESERVE) | /* ??? */		    RXADDR1_OAM_PRESERVE |		      /* ??? */		    RXADDR1_SET_MODE(RXMODE_AAL0);	/* This one must be last! */	cardvcc_write(lvcc, addr1, vcc_rxaddr1);}static void host_vcc_start_tx(const struct lanai_vcc *lvcc){	unsigned long dmaaddr = lanai_buf_dmaaddr(&lvcc->tx.buf);	cardvcc_write(lvcc, 0, vcc_txicg);	cardvcc_write(lvcc, 0xFFFF, vcc_txcrc1);	cardvcc_write(lvcc, 0xFFFF, vcc_txcrc2);	cardvcc_write(lvcc, 0, vcc_txreadptr);	cardvcc_write(lvcc, 0, vcc_txendptr);	cardvcc_write(lvcc, 0, vcc_txwriteptr);	cardvcc_write(lvcc,		(lvcc->tx.atmvcc->qos.txtp.traffic_class == ATM_CBR) ?		TXCBR_NEXT_BOZO | lvcc->vci : 0, vcc_txcbr_next);	cardvcc_write(lvcc, (dmaaddr >> 16) & 0xFFFF, vcc_txaddr2);	cardvcc_write(lvcc,	    ((dmaaddr >> 8) & 0xFF) |	    TXADDR1_SET_SIZE(lanai_buf_size_cardorder(&lvcc->tx.buf)),	    vcc_txaddr1);}/* Shutdown receiving on card */static void lanai_shutdown_rx_vci(const struct lanai_vcc *lvcc){	if (lvcc->vbase == 0)		/* We were never bound to a VCI */		return;	/* 15.1.1 - set to trashing, wait one cell time (15us) */	cardvcc_write(lvcc,	    RXADDR1_SET_RMMODE(RMMODE_TRASH) |	    RXADDR1_SET_MODE(RXMODE_TRASH), vcc_rxaddr1);	udelay(15);	/* 15.1.2 - clear rest of entries */	cardvcc_write(lvcc, 0, vcc_rxaddr2);	cardvcc_write(lvcc, 0, vcc_rxcrc1);	cardvcc_write(lvcc, 0, vcc_rxcrc2);	cardvcc_write(lvcc, 0, vcc_rxwriteptr);	cardvcc_write(lvcc, 0, vcc_rxbufstart);	cardvcc_write(lvcc, 0, vcc_rxreadptr);}/* Shutdown transmitting on card. * Unfortunately the lanai needs us to wait until all the data * drains out of the buffer before we can dealloc it, so this * can take awhile -- up to 370ms for a full 128KB buffer * assuming everone else is quiet.  In theory the time is * boundless if there's a CBR VCC holding things up. */static void lanai_shutdown_tx_vci(struct lanai_dev *lanai,	struct lanai_vcc *lvcc){	struct sk_buff *skb;	unsigned long flags, timeout;	int read, write, lastread = -1;	APRINTK(!in_interrupt(),	    "lanai_shutdown_tx_vci called w/o process context!\n");	if (lvcc->vbase == 0)		/* We were never bound to a VCI */		return;	/* 15.2.1 - wait for queue to drain */	spin_lock_irqsave(&lanai->txlock, flags);	if (lvcc->tx.inprogress != NULL) {		lanai_free_skb(lvcc->tx.atmvcc, lvcc->tx.inprogress);		lvcc->tx.inprogress = NULL;	}	while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL)		lanai_free_skb(lvcc->tx.atmvcc, skb);	vcc_unmark_backlogged(lanai, lvcc);	spin_unlock_irqrestore(&lanai->txlock, flags);	timeout = jiffies + ((lanai_buf_size(&lvcc->tx.buf) * HZ) >> 17);	write = TXWRITEPTR_GET_PTR(cardvcc_read(lvcc, vcc_txwriteptr));	goto start;	while (time_before_eq(jiffies, timeout)) {		schedule_timeout(HZ / 25);	    start:		read = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr));		if (read == write &&	   /* Is TX buffer empty? */		    (lvcc->tx.atmvcc->qos.txtp.traffic_class != ATM_CBR ||		    (cardvcc_read(lvcc, vcc_txcbr_next) &		    TXCBR_NEXT_BOZO) == 0))			goto done;		if (read != lastread) {	   /* Has there been any progress? */			lastread = read;			timeout += HZ / 10;		}	}	printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on backlog closing "	    "vci %d\n", lvcc->tx.atmvcc->dev->number, lvcc->vci);	DPRINTK("read, write = %d, %d\n", read, write);    done:	/* 15.2.2 - clear out all tx registers */	cardvcc_write(lvcc, 0, vcc_txreadptr);	cardvcc_write(lvcc, 0, vcc_txwriteptr);	cardvcc_write(lvcc, 0, vcc_txendptr);	cardvcc_write(lvcc, 0, vcc_txcrc1);	cardvcc_write(lvcc, 0, vcc_txcrc2);	cardvcc_write(lvcc, 0, vcc_txaddr2);	cardvcc_write(lvcc, 0, vcc_txaddr1);}/* -------------------- MANAGING AAL0 RX BUFFER: */static inline int aal0_buffer_allocate(struct lanai_dev *lanai){	DPRINTK("aal0_buffer_allocate: allocating AAL0 RX buffer\n");	lanai_buf_allocate(&lanai->aal0buf, AAL0_RX_BUFFER_SIZE, 80);	return (lanai->aal0buf.order < 0) ? -ENOMEM : 0;}static inline void aal0_buffer_free(struct lanai_dev *lanai){	DPRINTK("aal0_buffer_allocate: freeing AAL0 RX buffer\n");	lanai_buf_deallocate(&lanai->aal0buf);}/* -------------------- EEPROM UTILITIES: *//* Offsets of data in the EEPROM */#define EEPROM_COPYRIGHT	(0)#define EEPROM_COPYRIGHT_LEN	(44)#define EEPROM_CHECKSUM		(62)#define EEPROM_CHECKSUM_REV	(63)#define EEPROM_MAC		(64)#define EEPROM_MAC_REV		(70)#define EEPROM_SERIAL		(112)#define EEPROM_SERIAL_REV	(116)#define EEPROM_MAGIC		(120)#define EEPROM_MAGIC_REV	(124)#define EEPROM_MAGIC_VALUE	(0x5AB478D2)#ifndef READ_EEPROM/* Stub functions to use if EEPROM reading is disabled */static int __init eeprom_read(struct lanai_dev *lanai){	printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n",	    lanai->number);	memset(&lanai->eeprom[EEPROM_MAC], 0, 6);	return 0;}static int __init eeprom_validate(struct lanai_dev *lanai){	lanai->serialno = 0;	lanai->magicno = EEPROM_MAGIC_VALUE;	return 0;}#else /* READ_EEPROM */static int __init eeprom_read(struct lanai_dev *lanai){	int i, address;	u8 data;	u32 tmp;#define set_config1(x)   do { lanai->conf1 = x; conf1_write(lanai); \			    } while (0)#define clock_h()	 set_config1(lanai->conf1 | CONFIG1_PROMCLK)#define clock_l()	 set_config1(lanai->conf1 &~ CONFIG1_PROMCLK)#define data_h()	 set_config1(lanai->conf1 | CONFIG1_PROMDATA)#define data_l()	 set_config1(lanai->conf1 &~ CONFIG1_PROMDATA)#define pre_read()	 do { data_h(); clock_h(); udelay(5); } while (0)#define read_pin()	 (reg_read(lanai, Status_Reg) & STATUS_PROMDATA)#define send_stop()	 do { data_l(); udelay(5); clock_h(); udelay(5); \			      data_h(); udelay(5); } while (0)	/* start with both clock and data high */	data_h(); clock_h(); udelay(5);	for (address = 0; address < LANAI_EEPROM_SIZE; address++) {		data = (address << 1) | 1;	/* Command=read + address */		/* send start bit */		data_l(); udelay(5);		clock_l(); udelay(5);		for (i = 128; i != 0; i >>= 1) {   /* write command out */			tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) |			    (data & i) ? CONFIG1_PROMDATA : 0;			if (lanai->conf1 != tmp) {				set_config1(tmp);				udelay(5);	/* Let new data settle */			}			clock_h(); udelay(5); clock_l(); udelay(5);		}		/* look for ack */		data_h(); clock_h(); udelay(5);		if (read_pin() != 0)			goto error;	/* No ack seen */		clock_l(); udelay(5);		/* read back result */		for (data = 0, i = 7; i >= 0; i--) {			data_h(); clock_h(); udelay(5);			data = (data << 1) | !!read_pin();			clock_l(); udelay(5);		}		/* look again for ack */		data_h(); clock_h(); udelay(5);		if (read_pin() == 0)			goto error;	/* Spurious ack */		clock_l(); udelay(5);		send_stop();		lanai->eeprom[address] = data;		DPRINTK("EEPROM 0x%04X %02X\n", address, data);	}	return 0;    error:	clock_l(); udelay(5);		/* finish read */	send_stop();	printk(KERN_ERR DEV_LABEL "(itf %d): error reading EEPROM byte %d\n",	    lanai->number, address);	return -EIO;#undef set_config1#undef clock_h#undef clock_l#undef data_h#undef data_l#undef pre_read#undef read_pin#undef send_stop}/* read a big-endian 4-byte value out of eeprom */static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address){	return be32_to_cpup((u32 *) (&lanai->eeprom[address]));}/* Checksum/validate EEPROM contents */static int __init eeprom_validate(struct lanai_dev *lanai){	int i, s;	u32 v;	const u8 *e = lanai->eeprom;#ifdef DEBUG	/* First, see if we can get an ASCIIZ string out of the copyright */	for (i = EEPROM_COPYRIGHT;	    i < (EEPROM_COPYRIGHT + EEPROM_COPYRIGHT_LEN); i++)		if (e[i] < 0x20 || e[i] > 0x7E)			break;	if ( i != EEPROM_COPYRIGHT &&	    i != EEPROM_COPYRIGHT + EEPROM_COPYRIGHT_LEN && e[i] == '\0')		DPRINTK("eeprom: copyright = \"%s\"\n",		    (char *) &e[EEPROM_COPYRIGHT]);	else		DPRINTK("eeprom: copyright not found\n");#endif	/* Validate checksum */	for (i = s = 0; i < EEPROM_CHECKSUM; i++)		s += e[i];	s &= 0xFF;	if (s != e[EEPROM_CHECKSUM]) {		printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM checksum bad "		    "(wanted 0x%02X, got 0x%02X)\n", lanai->number,		    s, e[EEPROM_CHECKSUM]);		return -EIO;	}	s ^= 0xFF;	if (s != e[EEPROM_CHECKSUM_REV]) {		printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM inverse checksum "		    "bad (wanted 0x%02X, got 0x%02X)\n", lanai->number,		    s, e[EEPROM_CHECKSUM_REV]);		return -EIO;	}	/* Verify MAC address */	for (i = 0; i < 6; i++)		if ((e[EEPROM_MAC + i] ^ e[EEPROM_MAC_REV + i]) != 0xFF) {			printk(KERN_ERR DEV_LABEL			    "(itf %d) : EEPROM MAC addresses don't match "			    "(0x%02X, inverse 0x%02X)\n", lanai->number,			    e[EEPROM_MAC + i], e[EEPROM_MAC_REV + i]);			return -EIO;		}	DPRINTK("eeprom: MAC address = %02X:%02X:%02X:%02X:%02X:%02X\n",		e[EEPROM_MAC + 0], e[EEPROM_MAC + 1], e[EEPROM_MAC + 2],		e[EEPROM_MAC + 3], e[EEPROM_MAC + 4], e[EEPROM_MAC + 5]);	/* Verify serial number */	lanai->serialno = eeprom_be4(lanai, EEPROM_SERIAL);	v = eeprom_be4(lanai, EEPROM_SERIAL_REV);	if ((lanai->serialno ^ v) != 0xFFFFFFFF) {		printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM serial numbers "		    "don't match (0x%08X, inverse 0x%08X)\n", lanai->number,		    lanai->serialno, v);		return -EIO;	}	DPRINTK("eeprom: Serial number = %d\n", lanai->serialno);	/* Verify magic number */	lanai->magicno = eeprom_be4(lanai, EEPROM_MAGIC);	v = eeprom_be4(lanai, EEPROM_MAGIC_REV);	if ((lanai->magicno ^ v) != 0xFFFFFFFF) {		printk(KERN_ERR DEV_LABEL "(itf %d): EEPROM magic numbers "		    "don't match (0x%08X, inverse 0x%08X)\n", lanai->number,		    lanai->magicno, v);		return -EIO;	}	DPRINTK("eeprom: Magic number = 0x%08X\n", lanai->magicno);	if (lanai->magicno != EEPROM_MAGIC_VALUE)		printk(KERN_WARNING DEV_LABEL "(itf %d): warning - EEPROM "		    "magic not what expected (got 0x%08X, not 0x%08X)\n",		    lanai->number, lanai->magicno, EEPROM_MAGIC_VALUE);	return 0;}#endif /* READ_EEPROM */static inline const u8 *eeprom_mac(const struct lanai_dev *lanai){	return &lanai->eeprom[EEPROM_MAC];}/* -------------------- INTERRUPT HANDLING UTILITIES: *//* Interrupt types */#define INT_STATS	(0x00000002)	/* Statistics counter overflow */#define INT_SOOL	(0x00000004)	/* SOOL changed state */#define INT_LOCD	(0x00000008)	/* LOCD changed state */#define INT_LED		(0x00000010)	/* LED (HAPPI) changed state */#define INT_GPIN	(0x00000020)	/* GPIN changed state */#define INT_PING	(0x00000040)	/* PING_COUNT fulfilled */#define INT_WAKE	(0x00000080)	/* Lanai wants bus */#define INT_CBR0	(0x00000100)	/* CBR sched hit VCI 0 */#define INT_LOCK	(0x00000200)	/* Service list overflow */#define INT_MISMATCH	(0x00000400)	/* TX magic list mismatch */#define INT_AAL0_STR	(0x00000800)	/* Non-AAL5 buffer half filled */#define INT_AAL0	(0x00001000)	/* Non-AAL5 data available */#define INT_SERVICE	(0x00002000)	/* Service list entries available */#define INT_TABORTSENT	(0x00004000)	/* Target abort sent by lanai */#define INT_TABORTBM	(0x00008000)	/* Abort rcv'd as bus master */#define INT_TIMEOUTBM	(0x00010000)	/* No response to bus master */#define INT_PCIPARITY	(0x00020000)	/* Parity error on PCI *//* Sets of the above */#define INT_ALL		(0x0003FFFE)	/* All interrupts */#define INT_STATUS	(0x0000003C)	/* Some status pin changed */#define INT_DMASHUT	(0x00038000)	/* DMA engine got shut down */#define INT_SEGSHUT	(0x00000700)	/* Segmentation got shut down */static inline u32 intr_pending(const struct lanai_dev *lanai){	return reg_read(lanai, IntStatusMasked_Reg);}

⌨️ 快捷键说明

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