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

📄 defxx.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * File Name: *   defxx.c * * Copyright Information: *   Copyright Digital Equipment Corporation 1996. * *   This software may be used and distributed according to the terms of *   the GNU Public License, incorporated herein by reference. * * Abstract: *   A Linux device driver supporting the Digital Equipment Corporation *   FDDI EISA and PCI controller families.  Supported adapters include: * *		DEC FDDIcontroller/EISA (DEFEA) *		DEC FDDIcontroller/PCI  (DEFPA) * * Maintainers: *   LVS	Lawrence V. Stefani * * Contact: *	 The author may be reached at: * *		Inet: stefani@lkg.dec.com *		Mail: Digital Equipment Corporation *			  550 King Street *			  M/S: LKG1-3/M07 *			  Littleton, MA  01460 * * Credits: *   I'd like to thank Patricia Cross for helping me get started with *   Linux, David Davies for a lot of help upgrading and configuring *   my development system and for answering many OS and driver *   development questions, and Alan Cox for recommendations and *   integration help on getting FDDI support into Linux.  LVS * * Driver Architecture: *   The driver architecture is largely based on previous driver work *   for other operating systems.  The upper edge interface and *   functions were largely taken from existing Linux device drivers *   such as David Davies' DE4X5.C driver and Donald Becker's TULIP.C *   driver. * *   Adapter Probe - *		The driver scans for supported EISA adapters by reading the *		SLOT ID register for each EISA slot and making a match *		against the expected value.  The supported PCI adapters are *		discovered using successive calls to pcibios_find_device. *		The first time the probe routine is called, all supported *		devices are discovered and initialized.  The adapters aren't *		brought up to an operational state until the open routine is *		called. * *   Bus-Specific Initialization - *		This driver currently supports both EISA and PCI controller *		families.  While the custom DMA chip and FDDI logic is similar *		or identical, the bus logic is very different.  After *		initialization, the	only bus-specific differences is in how the *		driver enables and disables interrupts.  Other than that, the *		run-time critical code behaves the same on both families. *		It's important to note that both adapter families are configured *		to I/O map, rather than memory map, the adapter registers. * *   Driver Open/Close - *		In the driver open routine, the driver ISR (interrupt service *		routine) is registered and the adapter is brought to an *		operational state.  In the driver close routine, the opposite *		occurs; the driver ISR is deregistered and the adapter is *		brought to a safe, but closed state.  Users may use consecutive *		commands to bring the adapter up and down as in the following *		example: *					ifconfig fddi0 up *					ifconfig fddi0 down *					ifconfig fddi0 up * *   Driver Shutdown - *		Apparently, there is no shutdown or halt routine support under *		Linux.  This routine would be called during "reboot" or *		"shutdown" to allow the driver to place the adapter in a safe *		state before a warm reboot occurs.  To be really safe, the user *		should close the adapter before shutdown (eg. ifconfig fddi0 down) *		to ensure that the adapter DMA engine is taken off-line.  However, *		the current driver code anticipates this problem and always issues *		a soft reset of the adapter	at the beginning of driver initialization. *		A future driver enhancement in this area may occur in 2.1.X where *		Alan indicated that a shutdown handler may be implemented. * *   Interrupt Service Routine - *		The driver supports shared interrupts, so the ISR is registered for *		each board with the appropriate flag and the pointer to that board's *		device structure.  This provides the context during interrupt *		processing to support shared interrupts and multiple boards. * *		Interrupt enabling/disabling can occur at many levels.  At the host *		end, you can disable system interrupts, or disable interrupts at the *		PIC (on Intel systems).  Across the bus, both EISA and PCI adapters *		have a bus-logic chip interrupt enable/disable as well as a DMA *		controller interrupt enable/disable. * *		The driver currently enables and disables adapter interrupts at the *		bus-logic chip and assumes that Linux will take care of clearing or *		acknowledging any host-based interrupt chips. * *   Control Functions - *		Control functions are those used to support functions such as adding *		or deleting multicast addresses, enabling or disabling packet *		reception filters, or other custom/proprietary commands.  Presently, *		the driver supports the "get statistics", "set multicast list", and *		"set mac address" functions defined by Linux.  A list of possible *		enhancements include: * *				- Custom ioctl interface for executing port interface commands *				- Custom ioctl interface for adding unicast addresses to *				  adapter CAM (to support bridge functions). *				- Custom ioctl interface for supporting firmware upgrades. * *   Hardware (port interface) Support Routines - *		The driver function names that start with "dfx_hw_" represent *		low-level port interface routines that are called frequently.  They *		include issuing a DMA or port control command to the adapter, *		resetting the adapter, or reading the adapter state.  Since the *		driver initialization and run-time code must make calls into the *		port interface, these routines were written to be as generic and *		usable as possible. * *   Receive Path - *		The adapter DMA engine supports a 256 entry receive descriptor block *		of which up to 255 entries can be used at any given time.  The *		architecture is a standard producer, consumer, completion model in *		which the driver "produces" receive buffers to the adapter, the *		adapter "consumes" the receive buffers by DMAing incoming packet data, *		and the driver "completes" the receive buffers by servicing the *		incoming packet, then "produces" a new buffer and starts the cycle *		again.  Receive buffers can be fragmented in up to 16 fragments *		(descriptor	entries).  For simplicity, this driver posts *		single-fragment receive buffers of 4608 bytes, then allocates a *		sk_buff, copies the data, then reposts the buffer.  To reduce CPU *		utilization, a better approach would be to pass up the receive *		buffer (no extra copy) then allocate and post a replacement buffer. *		This is a performance enhancement that should be looked into at *		some point. * *   Transmit Path - *		Like the receive path, the adapter DMA engine supports a 256 entry *		transmit descriptor block of which up to 255 entries can be used at *		any	given time.  Transmit buffers can be fragmented	in up to 255 *		fragments (descriptor entries).  This driver always posts one *		fragment per transmit packet request. * *		The fragment contains the entire packet from FC to end of data. *		Before posting the buffer to the adapter, the driver sets a three-byte *		packet request header (PRH) which is required by the Motorola MAC chip *		used on the adapters.  The PRH tells the MAC the type of token to *		receive/send, whether or not to generate and append the CRC, whether *		synchronous or asynchronous framing is used, etc.  Since the PRH *		definition is not necessarily consistent across all FDDI chipsets, *		the driver, rather than the common FDDI packet handler routines, *		sets these bytes. * *		To reduce the amount of descriptor fetches needed per transmit request, *		the driver takes advantage of the fact that there are at least three *		bytes available before the skb->data field on the outgoing transmit *		request.  This is guaranteed by having fddi_setup() in net_init.c set *		dev->hard_header_len to 24 bytes.  21 bytes accounts for the largest *		header in an 802.2 SNAP frame.  The other 3 bytes are the extra "pad" *		bytes which we'll use to store the PRH. * *		There's a subtle advantage to adding these pad bytes to the *		hard_header_len, it ensures that the data portion of the packet for *		an 802.2 SNAP frame is longword aligned.  Other FDDI driver *		implementations may not need the extra padding and can start copying *		or DMAing directly from the FC byte which starts at skb->data.  Should *		another driver implementation need ADDITIONAL padding, the net_init.c *		module should be updated and dev->hard_header_len should be increased. *		NOTE: To maintain the alignment on the data portion of the packet, *		dev->hard_header_len should always be evenly divisible by 4 and at *		least 24 bytes in size. * * Modification History: *		Date		Name	Description *		16-Aug-96	LVS		Created. *		20-Aug-96	LVS		Updated dfx_probe so that version information *							string is only displayed if 1 or more cards are *							found.  Changed dfx_rcv_queue_process to copy *							3 NULL bytes before FC to ensure that data is *							longword aligned in receive buffer. *		09-Sep-96	LVS		Updated dfx_ctl_set_multicast_list to enable *							LLC group promiscuous mode if multicast list *							is too large.  LLC individual/group promiscuous *							mode is now disabled if IFF_PROMISC flag not set. *							dfx_xmt_queue_pkt no longer checks for NULL skb *							on Alan Cox recommendation.  Added node address *							override support. *		12-Sep-96	LVS		Reset current address to factory address during *							device open.  Updated transmit path to post a *							single fragment which includes PRH->end of data. *//* Version information string - should be updated prior to each new release!!! */static const char *version = "defxx.c:v1.04 09/16/96  Lawrence V. Stefani (stefani@lkg.dec.com)\n";/* Include files */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/init.h>#include <asm/byteorder.h>#include <asm/bitops.h>#include <asm/io.h>#include <linux/netdevice.h>#include <linux/fddidevice.h>#include <linux/skbuff.h>#include "defxx.h"#define DYNAMIC_BUFFERS 1#define SKBUFF_RX_COPYBREAK 200/* * NEW_SKB_SIZE = PI_RCV_DATA_K_SIZE_MAX+128 to allow 128 byte * alignment for compatibility with old EISA boards. */#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)/* Define global routines */int	dfx_probe(struct device *dev);/* Define module-wide (static) routines */static struct	device *dfx_alloc_device(struct device *dev, u16 iobase);static void		dfx_bus_init(struct device *dev);static void		dfx_bus_config_check(DFX_board_t *bp);static int		dfx_driver_init(struct device *dev);static int		dfx_adap_init(DFX_board_t *bp);static int		dfx_open(struct device *dev);static int		dfx_close(struct device *dev);static void		dfx_int_pr_halt_id(DFX_board_t *bp);static void		dfx_int_type_0_process(DFX_board_t *bp);static void		dfx_int_common(DFX_board_t *bp);static void		dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs);static struct		net_device_stats *dfx_ctl_get_stats(struct device *dev);static void		dfx_ctl_set_multicast_list(struct device *dev);static int		dfx_ctl_set_mac_address(struct device *dev, void *addr);static int		dfx_ctl_update_cam(DFX_board_t *bp);static int		dfx_ctl_update_filters(DFX_board_t *bp);static int		dfx_hw_dma_cmd_req(DFX_board_t *bp);static int		dfx_hw_port_ctrl_req(DFX_board_t *bp, PI_UINT32	command, PI_UINT32 data_a, PI_UINT32 data_b, PI_UINT32 *host_data);static void		dfx_hw_adap_reset(DFX_board_t *bp, PI_UINT32 type);static int		dfx_hw_adap_state_rd(DFX_board_t *bp);static int		dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type);static void		dfx_rcv_init(DFX_board_t *bp);static void		dfx_rcv_queue_process(DFX_board_t *bp);static int		dfx_xmt_queue_pkt(struct sk_buff *skb, struct device *dev);static void		dfx_xmt_done(DFX_board_t *bp);static void		dfx_xmt_flush(DFX_board_t *bp);/* Define module-wide (static) variables */static int		num_boards = 0;			/* total number of adapters configured */static int		already_probed = 0;		/* have we already entered dfx_probe? *//* * ======================= * = dfx_port_write_byte = * = dfx_port_read_byte	 = * = dfx_port_write_long = * = dfx_port_read_long  = * ======================= *    * Overview: *   Routines for reading and writing values from/to adapter *   * Returns: *   None *        * Arguments: *   bp     - pointer to board information *   offset - register offset from base I/O address *   data   - for dfx_port_write_byte and dfx_port_write_long, this *			  is a value to write. *			  for dfx_port_read_byte and dfx_port_read_byte, this *			  is a pointer to store the read value. * * Functional Description: *   These routines perform the correct operation to read or write *   the adapter register. *    *   EISA port block base addresses are based on the slot number in which the *   controller is installed.  For example, if the EISA controller is installed *   in slot 4, the port block base address is 0x4000.  If the controller is *   installed in slot 2, the port block base address is 0x2000, and so on. *   This port block can be used to access PDQ, ESIC, and DEFEA on-board *   registers using the register offsets defined in DEFXX.H. * *   PCI port block base addresses are assigned by the PCI BIOS or system *	 firmware.  There is one 128 byte port block which can be accessed.  It *   allows for I/O mapping of both PDQ and PFI registers using the register *   offsets defined in DEFXX.H. * * Return Codes: *   None * * Assumptions: *   bp->base_addr is a valid base I/O address for this adapter. *   offset is a valid register offset for this adapter. * * Side Effects: *   Rather than produce macros for these functions, these routines *   are defined using "inline" to ensure that the compiler will *   generate inline code and not waste a procedure call and return. *   This provides all the benefits of macros, but with the *   advantage of strict data type checking. */static inline void dfx_port_write_byte(	DFX_board_t	*bp,	int			offset,	u8			data	)	{	u16 port = bp->base_addr + offset;	outb(data, port);	return;	}static inline void dfx_port_read_byte(	DFX_board_t	*bp,	int			offset,	u8			*data	)	{	u16 port = bp->base_addr + offset;	*data = inb(port);	return;	}static inline void dfx_port_write_long(	DFX_board_t	*bp,	int			offset,	u32			data	)	{	u16 port = bp->base_addr + offset;	outl(data, port);	return;	}static inline void dfx_port_read_long(	DFX_board_t	*bp,	int			offset,	u32			*data	)	{	u16 port = bp->base_addr + offset;	*data = inl(port);	return;	}/* * ============= * = dfx_probe = * ============= *    * Overview: *   Probes for supported FDDI EISA and PCI controllers *   * Returns: *   Condition code *        * Arguments: *   dev - pointer to device information * * Functional Description: *   This routine is called by the OS for each FDDI device name (fddi0, *   fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c.  Since *   the DEFXX.C driver currently does not support being loaded as a *   module, dfx_probe() will initialize all devices the first time *   it is called. * *   Let's say that dfx_probe() is getting called to initialize fddi0. *   Furthermore, let's say there are three supported controllers in the *   system.  Before dfx_probe() leaves, devices fddi0, fddi1, and fddi2

⌨️ 快捷键说明

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