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

📄 skfddi.c

📁 h内核
💻 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 dependent 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. * * 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 *		31-Jul-03	DB	Audit copy_*_user in skfp_ioctl *					  Daniele Bellucci <bellucda@tiscali.it> *		03-Dec-03	SH	Convert to PCI device model * * 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.07"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/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/fddidevice.h>#include <linux/skbuff.h>#include <linux/bitops.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/uaccess.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 module-wide (static) routinesstatic 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 irqreturn_t 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 dump_data(unsigned char *Data, int length);// External functions from the hardware moduleextern u_int mac_drv_check_space(void);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_rx_queue(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[] = {	{ 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");MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");// Define module-wide (static) variablesstatic int num_boards;	/* total number of adapters configured */#ifdef DRIVERDEBUG#define PRINTK(s, args...) printk(s, ## args)#else#define PRINTK(s, args...)#endif				// DRIVERDEBUG/* * ================= * = skfp_init_one = * ================= *    * Overview: *   Probes for supported FDDI PCI controllers *   * Returns: *   Condition code *        * Arguments: *   pdev - pointer to PCI device information * * Functional Description: *   This is now called by PCI driver registration process *   for each board found. *    * 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. */static int skfp_init_one(struct pci_dev *pdev,				const struct pci_device_id *ent){	struct net_device *dev;	struct s_smc *smc;	/* board pointer */	void __iomem *mem;	int err;	PRINTK(KERN_INFO "entering skfp_init_one\n");	if (num_boards == 0) 		printk("%s\n", boot_msg);	err = pci_enable_device(pdev);	if (err)		return err;	err = pci_request_regions(pdev, "skfddi");	if (err)		goto err_out1;	pci_set_master(pdev);#ifdef MEM_MAPPED_IO	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {		printk(KERN_ERR "skfp: region is not an MMIO resource\n");		err = -EIO;		goto err_out2;	}	mem = ioremap(pci_resource_start(pdev, 0), 0x4000);#else	if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) {		printk(KERN_ERR "skfp: region is not PIO resource\n");		err = -EIO;		goto err_out2;	}	mem = ioport_map(pci_resource_start(pdev, 1), FP_IO_LEN);#endif	if (!mem) {		printk(KERN_ERR "skfp:  Unable to map register, "				"FDDI adapter will be disabled.\n");		err = -EIO;		goto err_out2;	}	dev = alloc_fddidev(sizeof(struct s_smc));	if (!dev) {		printk(KERN_ERR "skfp: Unable to allocate fddi device, "				"FDDI adapter will be disabled.\n");		err = -ENOMEM;		goto err_out3;	}	dev->irq = pdev->irq;	dev->get_stats = &skfp_ctl_get_stats;	dev->open = &skfp_open;	dev->stop = &skfp_close;	dev->hard_start_xmit = &skfp_send_pkt;	dev->set_multicast_list = &skfp_ctl_set_multicast_list;	dev->set_mac_address = &skfp_ctl_set_mac_address;	dev->do_ioctl = &skfp_ioctl;	dev->header_cache_update = NULL;	/* not supported */	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pdev->dev);	/* Initialize board structure with bus-specific info */	smc = netdev_priv(dev);	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->hw.iop = mem;	smc->os.ResetRequested = FALSE;	skb_queue_head_init(&smc->os.SendSkbQueue);	dev->base_addr = (unsigned long)mem;	err = skfp_driver_init(dev);	if (err)		goto err_out4;	err = register_netdev(dev);	if (err)		goto err_out5;	++num_boards;	pci_set_drvdata(pdev, dev);	if ((pdev->subsystem_device & 0xff00) == 0x5500 ||	    (pdev->subsystem_device & 0xff00) == 0x5800) 		printk("%s: SysKonnect FDDI PCI adapter"		       " found (SK-%04X)\n", dev->name,			       pdev->subsystem_device);	else		printk("%s: FDDI PCI adapter found\n", dev->name);	return 0;err_out5:	if (smc->os.SharedMemAddr) 		pci_free_consistent(pdev, smc->os.SharedMemSize,				    smc->os.SharedMemAddr, 				    smc->os.SharedMemDMA);	pci_free_consistent(pdev, MAX_FRAME_SIZE,			    smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);err_out4:	free_netdev(dev);err_out3:#ifdef MEM_MAPPED_IO	iounmap(mem);#else	ioport_unmap(mem);#endiferr_out2:	pci_release_regions(pdev);err_out1:	pci_disable_device(pdev);	return err;}/* * Called for each adapter board from pci_unregister_driver */static void __devexit skfp_remove_one(struct pci_dev *pdev){	struct net_device *p = pci_get_drvdata(pdev);	struct s_smc *lp = netdev_priv(p);	unregister_netdev(p);	if (lp->os.SharedMemAddr) {		pci_free_consistent(&lp->os.pdev,				    lp->os.SharedMemSize,				    lp->os.SharedMemAddr,				    lp->os.SharedMemDMA);		lp->os.SharedMemAddr = NULL;	}	if (lp->os.LocalRxBuffer) {		pci_free_consistent(&lp->os.pdev,				    MAX_FRAME_SIZE,				    lp->os.LocalRxBuffer,				    lp->os.LocalRxBufferDMA);		lp->os.LocalRxBuffer = NULL;	}#ifdef MEM_MAPPED_IO	iounmap(lp->hw.iop);#else	ioport_unmap(lp->hw.iop);#endif	pci_release_regions(pdev);	free_netdev(p);	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);}/* * ==================== * = skfp_driver_init = * ==================== *    * Overview: *   Initializes remaining adapter board structure information *   and makes sure adapter is in a safe state prior to skfp_open(). *   * Returns: *   Condition code *        * Arguments: *   dev - pointer to device information * * Functional Description: *   This function allocates additional resources such as the host memory *   blocks needed by the adapter. *   The adapter is also reset. The OS must call skfp_open() to open  *   the adapter and bring it on-line. * * Return Codes: *    0 - initialization succeeded *   -1 - initialization failed */static  int skfp_driver_init(struct net_device *dev){	struct s_smc *smc = netdev_priv(dev);	skfddi_priv *bp = &smc->os;	int err = -EIO;	PRINTK(KERN_INFO "entering skfp_driver_init\n");	// set the io address in private structures	bp->base_addr = dev->base_addr;	// Get the interrupt level from the PCI Configuration Table	smc->hw.irq = dev->irq;	spin_lock_init(&bp->DriverLock);		// Allocate invalid frame	bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA);	if (!bp->LocalRxBuffer) {		printk("could not allocate mem for ");		printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE);		goto fail;	}	// Determine the required size of the 'shared' memory area.	bp->SharedMemSize = mac_drv_check_space();	PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize);	if (bp->SharedMemSize > 0) {		bp->SharedMemSize += 16;	// for descriptor alignment		bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,							 bp->SharedMemSize,							 &bp->SharedMemDMA);		if (!bp->SharedMemSize) {			printk("could not allocate mem for ");			printk("hardware module: %ld byte\n",			       bp->SharedMemSize);			goto fail;		}		bp->SharedMemHeap = 0;	// Nothing used yet.	} else {		bp->SharedMemAddr = NULL;		bp->SharedMemHeap = 0;	}			// SharedMemSize > 0	memset(bp->SharedMemAddr, 0, bp->SharedMemSize);	card_stop(smc);		// Reset adapter.	PRINTK(KERN_INFO "mac_drv_init()..\n");	if (mac_drv_init(smc) != 0) {		PRINTK(KERN_INFO "mac_drv_init() failed.\n");		goto fail;	}	read_address(smc, NULL);	PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n",	       smc->hw.fddi_canon_addr.a[0],	       smc->hw.fddi_canon_addr.a[1],	       smc->hw.fddi_canon_addr.a[2],	       smc->hw.fddi_canon_addr.a[3],	       smc->hw.fddi_canon_addr.a[4],	       smc->hw.fddi_canon_addr.a[5]);	memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);	smt_reset_defaults(smc, 0);

⌨️ 快捷键说明

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