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

📄 lanai.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* lanai.c -- Copyright 1999 by Mitchell Blank Jr <mitch@sfgoth.com> * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version *  2 of the License, or (at your option) any later version. * * This driver supports ATM cards based on the Efficient "Lanai" * chipset such as the Speedstream 3010 and the ENI-25p.  The * Speedstream 3060 is currently not supported since we don't * have the code to drive the on-board Alcatel DSL chipset (yet). * * Thanks to Efficient for supporting this project with hardware, * documentation, and by answering my questions. * * Things not working yet: * * o  We're only set up to compile as a module currently.  i.e. *    you should put the source in drivers/atm/lanai.c and then *    just do "make drivers/atm/lanai.o" from the main *    source directory.  This will produce a drivers/atm/lanai.o *    file suitable for insmod'ing * * o  We don't support the Speedstream 3060 yet - this card has *    an on-board DSL modem chip by Alcatel and the driver will *    need some extra code added to handle it * * o  Note that due to limitations of the Lanai only one VCC can be *    in CBR at once * * o We don't currently parse the EEPROM at all.  The code is all *   there as per the spec, but it doesn't actually work.  I think *   there may be some issues with the docs.  Anyway, do NOT *   enable it yet - bugs in that code may actually damage your *   hardware!  Because of this you should hardware an ESI before *   trying to use this in a LANE or MPOA environment. * * o  AAL0 is stubbed in but the actual rx/tx path isn't written yet: *	vcc_tx_aal0() needs to send or queue a SKB *	vcc_tx_unqueue_aal0() needs to attempt to send queued SKBs *	vcc_rx_aal0() needs to handle AAL0 interrupts *    This isn't too much work - I just wanted to get other things *    done first. * * o  lanai_change_qos() isn't written yet * * o  There aren't any ioctl's yet -- I'd like to eventually support *    setting loopback and LED modes that way.  (see lanai_ioctl) * * o  If the segmentation engine or DMA gets shut down we should restart *    card as per section 17.0i.  (see lanai_reset) * * o setsockopt(SO_CIRANGE) isn't done (although despite what the *   API says it isn't exactly commonly implemented) *//* Version history: *   v.0.02 -- 11-JAN-2000 -- Endian fixes *   v.0.01 -- 30-NOV-1999 -- Initial release */#include <linux/module.h>#include <linux/mm.h>#include <linux/atmdev.h>#include <asm/io.h>#include <asm/byteorder.h>#include <linux/spinlock.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/interrupt.h>#ifndef PCI_VENDOR_ID_EF_ATM_LANAI2/* These need to eventually go into <linux/pci.h> - they're here for now */#define PCI_VENDOR_ID_EF_ATM_LANAI2	0x0003#define PCI_VENDOR_ID_EF_ATM_LANAIHB	0x0005#endif/* -------------------- TUNABLE PARAMATERS: *//* * Maximum number of VCIs per card.  Setting it lower could theoretically * save some memory, but since we allocate our vcc list with get_free_pages, * it's not really likely for most architectures */#define NUM_VCI			(1024)/* * Enable extra debugging */#define DEBUG/* * Debug _all_ register operations with card, except the memory test. * Also disables the timed poll to prevent extra chattiness.  This * isn't for normal use */#undef DEBUG_RW/* * The programming guide specifies a full test of the on-board SRAM * at initialization time.  Undefine to remove this */#define FULL_MEMORY_TEST/* * This is the number of (4 byte) service entries that we will * try to allocate at startup.  Note that we will end up with * one PAGE_SIZE's worth regardless of what this is set to */#define SERVICE_ENTRIES		(1024)/* TODO: make above a module load-time option *//* * We normally read the onboard EEPROM in order to discover our MAC * address.  Undefine to _not_ do this *//* #define READ_EEPROM */ /* ***DONT ENABLE YET*** *//* TODO: make above a module load-time option (also) *//* * Depth of TX fifo (in 128 byte units; range 2-31) * Smaller numbers are better for network latency * Larger numbers are better for PCI latency * I'm really sure where the best tradeoff is, but the BSD driver uses * 7 and it seems to work ok. */#define TX_FIFO_DEPTH		(7)/* TODO: make above a module load-time option *//* * How often (in jiffies) we will try to unstick stuck connections - * shouldn't need to happen much */#define LANAI_POLL_PERIOD	(10*HZ)/* TODO: make above a module load-time option *//* * When allocating an AAL5 receiving buffer, try to make it at least * large enough to hold this many max_sdu sized PDUs */#define AAL5_RX_MULTIPLIER	(3)/* TODO: make above a module load-time option *//* * Same for transmitting buffer */#define AAL5_TX_MULTIPLIER	(3)/* TODO: make above a module load-time option *//* * When allocating an AAL0 transmiting buffer, how many cells should fit. * Remember we'll end up with a PAGE_SIZE of them anyway, so this isn't * really critical */#define AAL0_TX_MULTIPLIER	(40)/* TODO: make above a module load-time option *//* * How large should we make the AAL0 receiving buffer.  Remember that this * is shared between all AAL0 VC's */#define AAL0_RX_BUFFER_SIZE	(PAGE_SIZE)/* TODO: make above a module load-time option *//* * Should we use Lanai's "powerdown" feature when no vcc's are bound? *//* #define USE_POWERDOWN *//* TODO: make above a module load-time option (also) *//* -------------------- DEBUGGING AIDS: */#define DEV_LABEL "lanai"#ifdef DEBUG#define DPRINTK(format, args...) \	printk(KERN_DEBUG DEV_LABEL ": " format, ##args)#define APRINTK(truth, format, args...) \	do { \		if (!(truth)) \			printk(KERN_ERR DEV_LABEL ": " format, ##args); \	} while (0)#else /* !DEBUG */#define DPRINTK(format, args...)#define APRINTK(truth, format, args...)#endif /* DEBUG */#ifdef DEBUG_RW#define RWDEBUG(format, args...) \	printk(KERN_DEBUG DEV_LABEL ": " format, ##args)#else /* !DEBUG_RW */#define RWDEBUG(format, args...)#endif/* -------------------- DATA DEFINITIONS: */#define LANAI_MAPPING_SIZE	(0x40000)#define LANAI_EEPROM_SIZE	(128)typedef int vci_t;typedef unsigned long bus_addr_t;/* A bitfield large enough for NUM_VCI */#define VCI_BITFIELD_NELEM  ((NUM_VCI + BITS_PER_LONG - 1) / BITS_PER_LONG)typedef struct {	unsigned long ul[VCI_BITFIELD_NELEM];} vci_bitfield;/* DMA buffer in host memory for TX, RX, or service list. */struct lanai_buffer {	u32 *start;	/* From get_free_pages */	u32 *end;	/* One past last byte */	u32 *ptr;	/* Pointer to current host location */	int order;	/* log2(size/PAGE_SIZE) */};struct lanai_vcc_stats {	unsigned rx_nomem;	union {		struct {			unsigned rx_badlen;			unsigned service_trash;			unsigned service_stream;			unsigned service_rxcrc;		} aal5;		struct {		} aal0;	} x;};struct lanai_dev;			/* Forward declaration *//* * This is the card-specific per-vcc data.  Note that unlike some other * drivers there is NOT a 1-to-1 correspondance between these and * atm_vcc's - each one of these represents an actual 2-way vcc, but * an atm_vcc can be 1-way and share with a 1-way vcc in the other * direction.  To make it weirder, there can even be 0-way vccs * bound to us, waiting to do a change_qos */struct lanai_vcc {	bus_addr_t vbase;		/* Base of VCC's registers */	struct lanai_vcc_stats stats;	int nref;			/* # of atm_vcc's who reference us */	vci_t vci;	struct {		struct lanai_buffer buf;		struct atm_vcc *atmvcc;	/* atm_vcc who is receiver */	} rx;	struct {		struct lanai_buffer buf;		struct atm_vcc *atmvcc;	/* atm_vcc who is transmitter */		int endptr;		/* last endptr from service entry */		struct sk_buff_head backlog;		struct sk_buff *inprogress;	/* We're streaming this PDU */		unsigned char *pptr;		/* Where we are in above */		int inprogleft;		/* Bytes left to send "inprogress" */		void (*unqueue)(struct lanai_dev *, struct lanai_vcc *, int);	} tx;};enum lanai_type {	lanai2	= PCI_VENDOR_ID_EF_ATM_LANAI2,	lanaihb	= PCI_VENDOR_ID_EF_ATM_LANAIHB};struct lanai_dev_stats {	unsigned ovfl_trash;	/* # of cells dropped - buffer overflow */	unsigned vci_trash;	/* # of cells dropped - closed vci */	unsigned hec_err;	/* # of cells dropped - bad HEC */	unsigned atm_ovfl;	/* # of cells dropped - rx fifo overflow */	unsigned pcierr_parity_detect;	unsigned pcierr_serr_set;	unsigned pcierr_master_abort;	unsigned pcierr_m_target_abort;	unsigned pcierr_s_target_abort;	unsigned pcierr_master_parity;	unsigned service_novcc_rx;	unsigned service_novcc_tx;	unsigned service_notx;	unsigned service_norx;	unsigned service_rxnotaal5;	unsigned dma_reenable;	unsigned card_reset;};struct lanai_dev {	bus_addr_t base;	struct lanai_dev_stats stats;	struct lanai_buffer service;	struct lanai_vcc **vccs;#ifdef USE_POWERDOWN	int nbound;			/* number of bound vccs */#endif	enum lanai_type type;	vci_t num_vci;			/* Currently just NUM_VCI */	u8 eeprom[LANAI_EEPROM_SIZE];	u32 serialno, magicno;	struct pci_dev *pci;	vci_bitfield backlog_vccs;	/* VCCs that are backlogged */	vci_bitfield transmit_ready;	/* VCCs that have transmit space */	struct timer_list timer;	int naal0;	struct lanai_buffer aal0buf;	/* AAL0 RX buffers */	u32 conf1, conf2;		/* CONFIG[12] registers */	u32 status;			/* STATUS register */	spinlock_t txlock;	spinlock_t servicelock;	struct atm_vcc *cbrvcc;	int number;	int board_rev;	u8 pci_revision;/* TODO - look at race conditions with maintence of conf1/conf2 *//* TODO - transmit locking: should we use _irq not _irqsave? *//* TODO - organize above in some rational fashion (see <asm/cache.h>) */};/* -------------------- VCI_BITFIELD UTILITIES: *//* * These functions assume that BITS_PER_LONG is a power of two, which * should be safe */#if (BITS_PER_LONG & (BITS_PER_LONG - 1))#error lanai driver requires type long to have a power of two number of bits#endif/* * In vci_bitfield_{set,clear} we do the operation in three * parts to ensure that gcc doesn't cast anything down to * 32 bits (and then sign extend them later) on 64-bit * platforms like the alpha */static inline void vci_bitfield_set(vci_bitfield *bf, vci_t vci){	unsigned long bit = 1;	bit <<= (unsigned long) (vci & (BITS_PER_LONG - 1));	bf->ul[vci / BITS_PER_LONG] |= bit;}static inline void vci_bitfield_clear(vci_bitfield *bf, vci_t vci){	unsigned long bit = 1;	bit <<= (unsigned long) (vci & (BITS_PER_LONG - 1));	bf->ul[vci / BITS_PER_LONG] &= ~bit;}static inline void vci_bitfield_init(vci_bitfield *bf){	memset(bf, 0, sizeof(*bf));}static void vci_bitfield_iterate(struct lanai_dev *lanai,	const vci_bitfield *bf, void (*func)(struct lanai_dev *,vci_t vci)){	vci_t vci;	unsigned long mask;	const unsigned long *lp = &(bf->ul[0]);	for (vci = 0; vci < NUM_VCI; lp++)		if (*lp == 0)			vci += BITS_PER_LONG;		else			for (mask = 1; mask != 0; mask <<= 1, vci++)				if (*lp & mask)					func(lanai, vci);}/* -------------------- BUFFER  UTILITIES: *//* * Lanai needs DMA buffers aligned to 256 bytes of at least 1024 bytes - * we assume that any page allocation will do.  I'm sure this is * never going to be a problem, but it's good to document assumtions */#if PAGE_SIZE < 1024#error PAGE_SIZE too small to support LANAI chipset#endif/* * We also assume that the maximum buffer size will be some number * of whole pages, although that wouldn't be too hard to fix */#if PAGE_SIZE > (128 * 1024)#error PAGE_SIZE too large to support LANAI chipset#endif/* Convert a size to "order" for __get_free_pages */static int bytes_to_order(int bytes){	int order = 0;	if (bytes > (128 * 1024))		bytes = 128 * 1024;	/* Max buffer size for lanai */	while ((PAGE_SIZE << order) < bytes)		order++;	return order;}/* * Allocate a buffer in host RAM for service list, RX, or TX

⌨️ 快捷键说明

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