📄 skfddi.c
字号:
/* * 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 + -