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

📄 skfddi.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * File Name: *   skfddi.c * * Copyright Information: *   Copyright SysKonnect 1998,1999. * * 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. * * The information in this file is provided "AS IS" without warranty. * * Abstract: *   A Linux device driver supporting the SysKonnect FDDI PCI controller *   familie. * * Maintainers: *   CG    Christoph Goos (cgoos@syskonnect.de) * * Contributors: *   DM    David S. Miller * * Address all question to: *   linux@syskonnect.de * * The technical manual for the adapters is available from SysKonnect's * web pages: www.syskonnect.com * Goto "Support" and search Knowledge Base for "manual". * * Driver Architecture: *   The driver architecture is based on the DEC FDDI driver by *   Lawrence V. Stefani and several ethernet drivers. *   I also used an existing Windows NT miniport driver. *   All hardware dependant fuctions are handled by the SysKonnect *   Hardware Module. *   The only headerfiles that are directly related to this source *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h. *   The others belong to the SysKonnect FDDI Hardware Module and *   should better not be changed. * NOTE: *   Compiling this driver produces some warnings, but I did not fix *   this, because the Hardware Module source is used for different *   drivers, and fixing it for Linux might bring problems on other *   projects. To keep the source common for all those drivers (and *   thus simplify fixes to it), please do not clean it up! * * Modification History: *              Date            Name    Description *              02-Mar-98       CG	Created. * *		10-Mar-99	CG	Support for 2.2.x added. *		25-Mar-99	CG	Corrected IRQ routing for SMP (APIC) *		26-Oct-99	CG	Fixed compilation error on 2.2.13 *		12-Nov-99	CG	Source code release *		22-Nov-99	CG	Included in kernel source. *		07-May-00	DM	64 bit fixes, new dma interface * * Compilation options (-Dxxx): *              DRIVERDEBUG     print lots of messages to log file *              DUMPPACKETS     print received/transmitted packets to logfile *  * Tested cpu architectures: *	- i386 *	- sparc64 *//* Version information string - should be updated prior to *//* each new release!!! */#define VERSION		"2.06"static const char *boot_msg = 	"SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"	"  SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)";/* 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/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/delay.h>#include <asm/byteorder.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/ctype.h>	// isdigit#include <linux/netdevice.h>#include <linux/fddidevice.h>#include <linux/skbuff.h>#include	"h/types.h"#undef ADDR			// undo Linux definition#include	"h/skfbi.h"#include	"h/fddi.h"#include	"h/smc.h"#include	"h/smtstate.h"// Define global routinesint skfp_probe(struct net_device *dev);// Define module-wide (static) routinesstatic struct net_device *alloc_device(struct net_device *dev, u_long iobase);static struct net_device *insert_device(struct net_device *dev,				    int (*init) (struct net_device *));static int fddi_dev_index(unsigned char *s);static void init_dev(struct net_device *dev, u_long iobase);static void link_modules(struct net_device *dev, struct net_device *tmp);static int skfp_driver_init(struct net_device *dev);static int skfp_open(struct net_device *dev);static int skfp_close(struct net_device *dev);static void skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs);static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev);static void skfp_ctl_set_multicast_list(struct net_device *dev);static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr);static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev);static void send_queued_packets(struct s_smc *smc);static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr);static void ResetAdapter(struct s_smc *smc);// Functions needed by the hardware modulevoid *mac_drv_get_space(struct s_smc *smc, u_int size);void *mac_drv_get_desc_mem(struct s_smc *smc, u_int size);unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt);unsigned long dma_master(struct s_smc *smc, void *virt, int len, int flag);void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,		  int flag);void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd);void llc_restart_tx(struct s_smc *smc);void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,			 int frag_count, int len);void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,			 int frag_count);void mac_drv_fill_rxd(struct s_smc *smc);void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,		       int frag_count);int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,		    int la_len);void smt_timer_poll(struct s_smc *smc);void ring_status_indication(struct s_smc *smc, u_long status);unsigned long smt_get_time(void);void smt_stat_counter(struct s_smc *smc, int stat);void cfm_state_change(struct s_smc *smc, int c_state);void ecm_state_change(struct s_smc *smc, int e_state);void pcm_state_change(struct s_smc *smc, int plc, int p_state);void rmt_state_change(struct s_smc *smc, int r_state);void drv_reset_indication(struct s_smc *smc);void dump_data(unsigned char *Data, int length);// External functions from the hardware moduleextern u_int mac_drv_check_space();extern void read_address(struct s_smc *smc, u_char * mac_addr);extern void card_stop(struct s_smc *smc);extern int mac_drv_init(struct s_smc *smc);extern void hwm_tx_frag(struct s_smc *smc, char far * virt, u_long phys,			int len, int frame_status);extern int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count,		       int frame_len, int frame_status);extern int init_smt(struct s_smc *smc, u_char * mac_addr);extern void fddi_isr(struct s_smc *smc);extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,			int len, int frame_status);extern void mac_drv_rx_mode(struct s_smc *smc, int mode);extern void mac_drv_clear_tx_queue(struct s_smc *smc);extern void mac_drv_clear_rx_queue(struct s_smc *smc);extern void mac_clear_multicast(struct s_smc *smc);extern void enable_tx_irq(struct s_smc *smc, u_short queue);extern void mac_drv_clear_txd(struct s_smc *smc);static struct pci_device_id skfddi_pci_tbl[] __initdata = {	{ PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },	{ }			/* Terminating entry */};MODULE_DEVICE_TABLE(pci, skfddi_pci_tbl);MODULE_LICENSE("GPL");// Define module-wide (static) variablesstatic int num_boards;	/* total number of adapters configured */static int num_fddi;static int autoprobed;#ifdef MODULEint init_module(void);void cleanup_module(void);static struct net_device *unlink_modules(struct net_device *p);static int loading_module = 1;#elsestatic int loading_module;#endif				// MODULE#ifdef DRIVERDEBUG#define PRINTK(s, args...) printk(s, ## args)#else#define PRINTK(s, args...)#endif				// DRIVERDEBUG#define PRIV(dev) (&(((struct s_smc *)dev->priv)->os))/* * ============== * = skfp_probe = * ============== *    * Overview: *   Probes for supported FDDI 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. *   If loaded as a module, it will detect and initialize all  *   adapters the first time it is called. * *   Let's say that skfp_probe() is getting called to initialize fddi0. *   Furthermore, let's say there are three supported controllers in the *   system.  Before skfp_probe() leaves, devices fddi0, fddi1, and fddi2 *   will be initialized and a global flag will be set to indicate that *   skfp_probe() has already been called. * *   However...the OS doesn't know that we've already initialized *   devices fddi1 and fddi2 so skfp_probe() gets called again and again *   until it reaches the end of the device list for FDDI (presently, *   fddi7).  It's important that the driver "pretend" to probe for *   devices fddi1 and fddi2 and return success.  Devices fddi3 *   through fddi7 will return failure since they weren't initialized. * *   This algorithm seems to work for the time being.  As other FDDI *   drivers are written for Linux, a more generic approach (perhaps *   similar to the Ethernet card approach) may need to be implemented. *    * Return Codes: *   0           - This device (fddi0, fddi1, etc) configured successfully *   -ENODEV - No devices present, or no SysKonnect FDDI PCI device *                         present for this device name * * * Side Effects: *   Device structures for FDDI adapters (fddi0, fddi1, etc) are *   initialized and the board resources are read and stored in *   the device structure. */int skfp_probe(struct net_device *dev){	int i;			/* used in for loops */	struct pci_dev *pdev = NULL;	/* PCI device structure */#ifndef MEM_MAPPED_IO	u16 port;		/* temporary I/O (port) address */	int port_len;		/* length of port address range (in bytes) */#else	unsigned long port;#endif	u16 command;	/* PCI Configuration space Command register val */	struct s_smc *smc;	/* board pointer */	struct net_device *tmp = dev;	u8 first_dev_used = 0;	u16 SubSysId;	PRINTK(KERN_INFO "entering skfp_probe\n");	/*	 * Verify whether we're going through skfp_probe() again	 *	 * If so, see if we're going through for a subsequent fddi device that	 * we've already initialized.  If we are, return success (0).  If not,	 * return failure (-ENODEV).	 */	if (autoprobed) {		PRINTK(KERN_INFO "Already entered skfp_probe\n");		if (dev != NULL) {			if ((strncmp(dev->name, "fddi", 4) == 0) &&			    (dev->base_addr != 0)) {				return (0);			}			return (-ENODEV);		}	}	autoprobed = 1;		/* set global flag */	printk("%s\n", boot_msg);	/* Scan for Syskonnect FDDI PCI controllers */	if (!pci_present()) {	/* is PCI BIOS even present? */		printk("no PCI BIOS present\n");		return (-ENODEV);	}	for (i = 0; i < SKFP_MAX_NUM_BOARDS; i++) {	// scan for PCI cards		PRINTK(KERN_INFO "Check device %d\n", i);		if ((pdev=pci_find_device(PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP,			pdev)) == 0) {			break;		}		if (pci_enable_device(pdev))			continue;#ifndef MEM_MAPPED_IO		/* Verify that I/O enable bit is set (PCI slot is enabled) */		pci_read_config_word(pdev, PCI_COMMAND, &command);		if ((command & PCI_COMMAND_IO) == 0) {			PRINTK("I/O enable bit not set!");			PRINTK(" Verify that slot is enabled\n");			continue;		}		/* Turn off memory mapped space and enable mastering */		PRINTK(KERN_INFO "Command Reg: %04x\n", command);		command |= PCI_COMMAND_MASTER;		command &= ~PCI_COMMAND_MEMORY;		pci_write_config_word(pdev, PCI_COMMAND, command);		/* Read I/O base address from PCI Configuration Space */		pci_read_config_word(pdev, PCI_BASE_ADDRESS_1, &port);		port &= PCI_BASE_ADDRESS_IO_MASK; // clear I/O bit (bit 0)		/* Verify port address range is not already being used */		port_len = FP_IO_LEN;		if (check_region(port, port_len) != 0) {			printk("I/O range allocated to adapter");			printk(" (0x%X-0x%X) is already being used!\n", port,			       (port + port_len - 1));			continue;		}#else		/* Verify that MEM enable bit is set (PCI slot is enabled) */		pci_read_config_word(pdev, PCI_COMMAND, &command);		if ((command & PCI_COMMAND_MEMORY) == 0) {			PRINTK("MEMORY-I/O enable bit not set!");			PRINTK(" Verify that slot is enabled\n");			continue;		}		/* Turn off IO mapped space and enable mastering */		PRINTK(KERN_INFO "Command Reg: %04x\n", command);		command |= PCI_COMMAND_MASTER;		command &= ~PCI_COMMAND_IO;		pci_write_config_word(pdev, PCI_COMMAND, command);		port = pci_resource_start(pdev, 0);		port = (unsigned long)ioremap(port, 0x4000);		if (!port){			printk("skfp:  Unable to map MEMORY register, "			"FDDI adapter will be disabled.\n");			break;		}#endif		if ((!loading_module) || first_dev_used) {			/* Allocate a device structure for this adapter */			tmp = alloc_device(dev, port);		}		first_dev_used = 1;	// only significant first time		pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &SubSysId);		if (tmp != NULL) {			if (loading_module)				link_modules(dev, tmp);			dev = tmp;			init_dev(dev, port);			dev->irq = pdev->irq;			/* Initialize board structure with bus-specific info */			smc = (struct s_smc *) dev->priv;			smc->os.dev = dev;			smc->os.bus_type = SK_BUS_TYPE_PCI;			smc->os.pdev = *pdev;			smc->os.QueueSkb = MAX_TX_QUEUE_LEN;			smc->os.MaxFrameSize = MAX_FRAME_SIZE;			smc->os.dev = dev;			smc->hw.slot = -1;			smc->os.ResetRequested = FALSE;			skb_queue_head_init(&smc->os.SendSkbQueue);			if (skfp_driver_init(dev) == 0) {				// only increment global board 				// count on success				num_boards++;				request_region(dev->base_addr,					       FP_IO_LEN, dev->name);				if ((SubSysId & 0xff00) == 0x5500 ||					(SubSysId & 0xff00) == 0x5800) {				printk("%s: SysKonnect FDDI PCI adapter"				       " found (SK-%04X)\n", dev->name,					SubSysId);				} else {				printk("%s: FDDI PCI adapter found\n",					dev->name);				}			} else {				kfree(dev);				i = SKFP_MAX_NUM_BOARDS;	// stop search			}		}		// if (dev != NULL)	}			// for SKFP_MAX_NUM_BOARDS

⌨️ 快捷键说明

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