| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * File Name: | 
|  | 3 | *   skfddi.c | 
|  | 4 | * | 
|  | 5 | * Copyright Information: | 
|  | 6 | *   Copyright SysKonnect 1998,1999. | 
|  | 7 | * | 
|  | 8 | * This program is free software; you can redistribute it and/or modify | 
|  | 9 | * it under the terms of the GNU General Public License as published by | 
|  | 10 | * the Free Software Foundation; either version 2 of the License, or | 
|  | 11 | * (at your option) any later version. | 
|  | 12 | * | 
|  | 13 | * The information in this file is provided "AS IS" without warranty. | 
|  | 14 | * | 
|  | 15 | * Abstract: | 
|  | 16 | *   A Linux device driver supporting the SysKonnect FDDI PCI controller | 
|  | 17 | *   familie. | 
|  | 18 | * | 
|  | 19 | * Maintainers: | 
|  | 20 | *   CG    Christoph Goos (cgoos@syskonnect.de) | 
|  | 21 | * | 
|  | 22 | * Contributors: | 
|  | 23 | *   DM    David S. Miller | 
|  | 24 | * | 
|  | 25 | * Address all question to: | 
|  | 26 | *   linux@syskonnect.de | 
|  | 27 | * | 
|  | 28 | * The technical manual for the adapters is available from SysKonnect's | 
|  | 29 | * web pages: www.syskonnect.com | 
|  | 30 | * Goto "Support" and search Knowledge Base for "manual". | 
|  | 31 | * | 
|  | 32 | * Driver Architecture: | 
|  | 33 | *   The driver architecture is based on the DEC FDDI driver by | 
|  | 34 | *   Lawrence V. Stefani and several ethernet drivers. | 
|  | 35 | *   I also used an existing Windows NT miniport driver. | 
| Stefan Weil | eef35c2 | 2010-08-06 21:11:15 +0200 | [diff] [blame] | 36 | *   All hardware dependent functions are handled by the SysKonnect | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 37 | *   Hardware Module. | 
|  | 38 | *   The only headerfiles that are directly related to this source | 
|  | 39 | *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h. | 
|  | 40 | *   The others belong to the SysKonnect FDDI Hardware Module and | 
|  | 41 | *   should better not be changed. | 
|  | 42 | * | 
|  | 43 | * Modification History: | 
|  | 44 | *              Date            Name    Description | 
|  | 45 | *              02-Mar-98       CG	Created. | 
|  | 46 | * | 
|  | 47 | *		10-Mar-99	CG	Support for 2.2.x added. | 
|  | 48 | *		25-Mar-99	CG	Corrected IRQ routing for SMP (APIC) | 
|  | 49 | *		26-Oct-99	CG	Fixed compilation error on 2.2.13 | 
|  | 50 | *		12-Nov-99	CG	Source code release | 
|  | 51 | *		22-Nov-99	CG	Included in kernel source. | 
|  | 52 | *		07-May-00	DM	64 bit fixes, new dma interface | 
|  | 53 | *		31-Jul-03	DB	Audit copy_*_user in skfp_ioctl | 
|  | 54 | *					  Daniele Bellucci <bellucda@tiscali.it> | 
|  | 55 | *		03-Dec-03	SH	Convert to PCI device model | 
|  | 56 | * | 
|  | 57 | * Compilation options (-Dxxx): | 
|  | 58 | *              DRIVERDEBUG     print lots of messages to log file | 
|  | 59 | *              DUMPPACKETS     print received/transmitted packets to logfile | 
|  | 60 | * | 
|  | 61 | * Tested cpu architectures: | 
|  | 62 | *	- i386 | 
|  | 63 | *	- sparc64 | 
|  | 64 | */ | 
|  | 65 |  | 
|  | 66 | /* Version information string - should be updated prior to */ | 
|  | 67 | /* each new release!!! */ | 
|  | 68 | #define VERSION		"2.07" | 
|  | 69 |  | 
| Arjan van de Ven | f71e130 | 2006-03-03 21:33:57 -0500 | [diff] [blame] | 70 | static const char * const boot_msg = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 71 | "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n" | 
|  | 72 | "  SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)"; | 
|  | 73 |  | 
|  | 74 | /* Include files */ | 
|  | 75 |  | 
| Alexey Dobriyan | d43c36d | 2009-10-07 17:09:06 +0400 | [diff] [blame] | 76 | #include <linux/capability.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 77 | #include <linux/module.h> | 
|  | 78 | #include <linux/kernel.h> | 
|  | 79 | #include <linux/errno.h> | 
|  | 80 | #include <linux/ioport.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 81 | #include <linux/interrupt.h> | 
|  | 82 | #include <linux/pci.h> | 
|  | 83 | #include <linux/netdevice.h> | 
|  | 84 | #include <linux/fddidevice.h> | 
|  | 85 | #include <linux/skbuff.h> | 
|  | 86 | #include <linux/bitops.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 87 | #include <linux/gfp.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 |  | 
|  | 89 | #include <asm/byteorder.h> | 
|  | 90 | #include <asm/io.h> | 
|  | 91 | #include <asm/uaccess.h> | 
|  | 92 |  | 
|  | 93 | #include	"h/types.h" | 
|  | 94 | #undef ADDR			// undo Linux definition | 
|  | 95 | #include	"h/skfbi.h" | 
|  | 96 | #include	"h/fddi.h" | 
|  | 97 | #include	"h/smc.h" | 
|  | 98 | #include	"h/smtstate.h" | 
|  | 99 |  | 
|  | 100 |  | 
|  | 101 | // Define module-wide (static) routines | 
|  | 102 | static int skfp_driver_init(struct net_device *dev); | 
|  | 103 | static int skfp_open(struct net_device *dev); | 
|  | 104 | static int skfp_close(struct net_device *dev); | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 105 | static irqreturn_t skfp_interrupt(int irq, void *dev_id); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 106 | static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev); | 
|  | 107 | static void skfp_ctl_set_multicast_list(struct net_device *dev); | 
|  | 108 | static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev); | 
|  | 109 | static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr); | 
|  | 110 | static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 
| Stephen Hemminger | 61357325 | 2009-08-31 19:50:58 +0000 | [diff] [blame] | 111 | static netdev_tx_t skfp_send_pkt(struct sk_buff *skb, | 
|  | 112 | struct net_device *dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 113 | static void send_queued_packets(struct s_smc *smc); | 
|  | 114 | static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr); | 
|  | 115 | static void ResetAdapter(struct s_smc *smc); | 
|  | 116 |  | 
|  | 117 |  | 
|  | 118 | // Functions needed by the hardware module | 
|  | 119 | void *mac_drv_get_space(struct s_smc *smc, u_int size); | 
|  | 120 | void *mac_drv_get_desc_mem(struct s_smc *smc, u_int size); | 
|  | 121 | unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt); | 
|  | 122 | unsigned long dma_master(struct s_smc *smc, void *virt, int len, int flag); | 
|  | 123 | void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, | 
|  | 124 | int flag); | 
|  | 125 | void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd); | 
|  | 126 | void llc_restart_tx(struct s_smc *smc); | 
|  | 127 | void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, | 
|  | 128 | int frag_count, int len); | 
|  | 129 | void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, | 
|  | 130 | int frag_count); | 
|  | 131 | void mac_drv_fill_rxd(struct s_smc *smc); | 
|  | 132 | void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, | 
|  | 133 | int frag_count); | 
|  | 134 | int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, | 
|  | 135 | int la_len); | 
|  | 136 | void dump_data(unsigned char *Data, int length); | 
|  | 137 |  | 
|  | 138 | // External functions from the hardware module | 
|  | 139 | extern u_int mac_drv_check_space(void); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 140 | extern int mac_drv_init(struct s_smc *smc); | 
|  | 141 | extern void hwm_tx_frag(struct s_smc *smc, char far * virt, u_long phys, | 
|  | 142 | int len, int frame_status); | 
|  | 143 | extern int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, | 
|  | 144 | int frame_len, int frame_status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | extern void fddi_isr(struct s_smc *smc); | 
|  | 146 | extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys, | 
|  | 147 | int len, int frame_status); | 
|  | 148 | extern void mac_drv_rx_mode(struct s_smc *smc, int mode); | 
|  | 149 | extern void mac_drv_clear_rx_queue(struct s_smc *smc); | 
|  | 150 | extern void enable_tx_irq(struct s_smc *smc, u_short queue); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 151 |  | 
| Alexey Dobriyan | a3aa188 | 2010-01-07 11:58:11 +0000 | [diff] [blame] | 152 | static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 153 | { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, | 
|  | 154 | { }			/* Terminating entry */ | 
|  | 155 | }; | 
|  | 156 | MODULE_DEVICE_TABLE(pci, skfddi_pci_tbl); | 
|  | 157 | MODULE_LICENSE("GPL"); | 
|  | 158 | MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>"); | 
|  | 159 |  | 
|  | 160 | // Define module-wide (static) variables | 
|  | 161 |  | 
|  | 162 | static int num_boards;	/* total number of adapters configured */ | 
|  | 163 |  | 
| Stephen Hemminger | 145186a | 2008-11-20 20:29:48 -0800 | [diff] [blame] | 164 | static const struct net_device_ops skfp_netdev_ops = { | 
|  | 165 | .ndo_open		= skfp_open, | 
|  | 166 | .ndo_stop		= skfp_close, | 
|  | 167 | .ndo_start_xmit		= skfp_send_pkt, | 
|  | 168 | .ndo_get_stats		= skfp_ctl_get_stats, | 
|  | 169 | .ndo_change_mtu		= fddi_change_mtu, | 
| Jiri Pirko | afc4b13 | 2011-08-16 06:29:01 +0000 | [diff] [blame] | 170 | .ndo_set_rx_mode	= skfp_ctl_set_multicast_list, | 
| Stephen Hemminger | 145186a | 2008-11-20 20:29:48 -0800 | [diff] [blame] | 171 | .ndo_set_mac_address	= skfp_ctl_set_mac_address, | 
|  | 172 | .ndo_do_ioctl		= skfp_ioctl, | 
|  | 173 | }; | 
|  | 174 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 175 | /* | 
|  | 176 | * ================= | 
|  | 177 | * = skfp_init_one = | 
|  | 178 | * ================= | 
|  | 179 | * | 
|  | 180 | * Overview: | 
|  | 181 | *   Probes for supported FDDI PCI controllers | 
|  | 182 | * | 
|  | 183 | * Returns: | 
|  | 184 | *   Condition code | 
|  | 185 | * | 
|  | 186 | * Arguments: | 
|  | 187 | *   pdev - pointer to PCI device information | 
|  | 188 | * | 
|  | 189 | * Functional Description: | 
|  | 190 | *   This is now called by PCI driver registration process | 
|  | 191 | *   for each board found. | 
|  | 192 | * | 
|  | 193 | * Return Codes: | 
|  | 194 | *   0           - This device (fddi0, fddi1, etc) configured successfully | 
|  | 195 | *   -ENODEV - No devices present, or no SysKonnect FDDI PCI device | 
|  | 196 | *                         present for this device name | 
|  | 197 | * | 
|  | 198 | * | 
|  | 199 | * Side Effects: | 
|  | 200 | *   Device structures for FDDI adapters (fddi0, fddi1, etc) are | 
|  | 201 | *   initialized and the board resources are read and stored in | 
|  | 202 | *   the device structure. | 
|  | 203 | */ | 
|  | 204 | static int skfp_init_one(struct pci_dev *pdev, | 
|  | 205 | const struct pci_device_id *ent) | 
|  | 206 | { | 
|  | 207 | struct net_device *dev; | 
|  | 208 | struct s_smc *smc;	/* board pointer */ | 
|  | 209 | void __iomem *mem; | 
|  | 210 | int err; | 
|  | 211 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 212 | pr_debug("entering skfp_init_one\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 213 |  | 
|  | 214 | if (num_boards == 0) | 
|  | 215 | printk("%s\n", boot_msg); | 
|  | 216 |  | 
|  | 217 | err = pci_enable_device(pdev); | 
|  | 218 | if (err) | 
|  | 219 | return err; | 
|  | 220 |  | 
|  | 221 | err = pci_request_regions(pdev, "skfddi"); | 
|  | 222 | if (err) | 
|  | 223 | goto err_out1; | 
|  | 224 |  | 
|  | 225 | pci_set_master(pdev); | 
|  | 226 |  | 
|  | 227 | #ifdef MEM_MAPPED_IO | 
|  | 228 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { | 
|  | 229 | printk(KERN_ERR "skfp: region is not an MMIO resource\n"); | 
|  | 230 | err = -EIO; | 
|  | 231 | goto err_out2; | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 | mem = ioremap(pci_resource_start(pdev, 0), 0x4000); | 
|  | 235 | #else | 
|  | 236 | if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) { | 
|  | 237 | printk(KERN_ERR "skfp: region is not PIO resource\n"); | 
|  | 238 | err = -EIO; | 
|  | 239 | goto err_out2; | 
|  | 240 | } | 
|  | 241 |  | 
|  | 242 | mem = ioport_map(pci_resource_start(pdev, 1), FP_IO_LEN); | 
|  | 243 | #endif | 
|  | 244 | if (!mem) { | 
|  | 245 | printk(KERN_ERR "skfp:  Unable to map register, " | 
|  | 246 | "FDDI adapter will be disabled.\n"); | 
|  | 247 | err = -EIO; | 
|  | 248 | goto err_out2; | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | dev = alloc_fddidev(sizeof(struct s_smc)); | 
|  | 252 | if (!dev) { | 
|  | 253 | printk(KERN_ERR "skfp: Unable to allocate fddi device, " | 
|  | 254 | "FDDI adapter will be disabled.\n"); | 
|  | 255 | err = -ENOMEM; | 
|  | 256 | goto err_out3; | 
|  | 257 | } | 
|  | 258 |  | 
|  | 259 | dev->irq = pdev->irq; | 
| Stephen Hemminger | 145186a | 2008-11-20 20:29:48 -0800 | [diff] [blame] | 260 | dev->netdev_ops = &skfp_netdev_ops; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 261 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 262 | SET_NETDEV_DEV(dev, &pdev->dev); | 
|  | 263 |  | 
|  | 264 | /* Initialize board structure with bus-specific info */ | 
|  | 265 | smc = netdev_priv(dev); | 
|  | 266 | smc->os.dev = dev; | 
|  | 267 | smc->os.bus_type = SK_BUS_TYPE_PCI; | 
|  | 268 | smc->os.pdev = *pdev; | 
|  | 269 | smc->os.QueueSkb = MAX_TX_QUEUE_LEN; | 
|  | 270 | smc->os.MaxFrameSize = MAX_FRAME_SIZE; | 
|  | 271 | smc->os.dev = dev; | 
|  | 272 | smc->hw.slot = -1; | 
|  | 273 | smc->hw.iop = mem; | 
|  | 274 | smc->os.ResetRequested = FALSE; | 
|  | 275 | skb_queue_head_init(&smc->os.SendSkbQueue); | 
|  | 276 |  | 
|  | 277 | dev->base_addr = (unsigned long)mem; | 
|  | 278 |  | 
|  | 279 | err = skfp_driver_init(dev); | 
|  | 280 | if (err) | 
|  | 281 | goto err_out4; | 
|  | 282 |  | 
|  | 283 | err = register_netdev(dev); | 
|  | 284 | if (err) | 
|  | 285 | goto err_out5; | 
|  | 286 |  | 
|  | 287 | ++num_boards; | 
|  | 288 | pci_set_drvdata(pdev, dev); | 
|  | 289 |  | 
|  | 290 | if ((pdev->subsystem_device & 0xff00) == 0x5500 || | 
|  | 291 | (pdev->subsystem_device & 0xff00) == 0x5800) | 
|  | 292 | printk("%s: SysKonnect FDDI PCI adapter" | 
|  | 293 | " found (SK-%04X)\n", dev->name, | 
|  | 294 | pdev->subsystem_device); | 
|  | 295 | else | 
|  | 296 | printk("%s: FDDI PCI adapter found\n", dev->name); | 
|  | 297 |  | 
|  | 298 | return 0; | 
|  | 299 | err_out5: | 
|  | 300 | if (smc->os.SharedMemAddr) | 
|  | 301 | pci_free_consistent(pdev, smc->os.SharedMemSize, | 
|  | 302 | smc->os.SharedMemAddr, | 
|  | 303 | smc->os.SharedMemDMA); | 
|  | 304 | pci_free_consistent(pdev, MAX_FRAME_SIZE, | 
|  | 305 | smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA); | 
|  | 306 | err_out4: | 
|  | 307 | free_netdev(dev); | 
|  | 308 | err_out3: | 
|  | 309 | #ifdef MEM_MAPPED_IO | 
|  | 310 | iounmap(mem); | 
|  | 311 | #else | 
|  | 312 | ioport_unmap(mem); | 
|  | 313 | #endif | 
|  | 314 | err_out2: | 
|  | 315 | pci_release_regions(pdev); | 
|  | 316 | err_out1: | 
|  | 317 | pci_disable_device(pdev); | 
|  | 318 | return err; | 
|  | 319 | } | 
|  | 320 |  | 
|  | 321 | /* | 
|  | 322 | * Called for each adapter board from pci_unregister_driver | 
|  | 323 | */ | 
|  | 324 | static void __devexit skfp_remove_one(struct pci_dev *pdev) | 
|  | 325 | { | 
|  | 326 | struct net_device *p = pci_get_drvdata(pdev); | 
|  | 327 | struct s_smc *lp = netdev_priv(p); | 
|  | 328 |  | 
|  | 329 | unregister_netdev(p); | 
|  | 330 |  | 
|  | 331 | if (lp->os.SharedMemAddr) { | 
|  | 332 | pci_free_consistent(&lp->os.pdev, | 
|  | 333 | lp->os.SharedMemSize, | 
|  | 334 | lp->os.SharedMemAddr, | 
|  | 335 | lp->os.SharedMemDMA); | 
|  | 336 | lp->os.SharedMemAddr = NULL; | 
|  | 337 | } | 
|  | 338 | if (lp->os.LocalRxBuffer) { | 
|  | 339 | pci_free_consistent(&lp->os.pdev, | 
|  | 340 | MAX_FRAME_SIZE, | 
|  | 341 | lp->os.LocalRxBuffer, | 
|  | 342 | lp->os.LocalRxBufferDMA); | 
|  | 343 | lp->os.LocalRxBuffer = NULL; | 
|  | 344 | } | 
|  | 345 | #ifdef MEM_MAPPED_IO | 
|  | 346 | iounmap(lp->hw.iop); | 
|  | 347 | #else | 
|  | 348 | ioport_unmap(lp->hw.iop); | 
|  | 349 | #endif | 
|  | 350 | pci_release_regions(pdev); | 
|  | 351 | free_netdev(p); | 
|  | 352 |  | 
|  | 353 | pci_disable_device(pdev); | 
|  | 354 | pci_set_drvdata(pdev, NULL); | 
|  | 355 | } | 
|  | 356 |  | 
|  | 357 | /* | 
|  | 358 | * ==================== | 
|  | 359 | * = skfp_driver_init = | 
|  | 360 | * ==================== | 
|  | 361 | * | 
|  | 362 | * Overview: | 
|  | 363 | *   Initializes remaining adapter board structure information | 
|  | 364 | *   and makes sure adapter is in a safe state prior to skfp_open(). | 
|  | 365 | * | 
|  | 366 | * Returns: | 
|  | 367 | *   Condition code | 
|  | 368 | * | 
|  | 369 | * Arguments: | 
|  | 370 | *   dev - pointer to device information | 
|  | 371 | * | 
|  | 372 | * Functional Description: | 
|  | 373 | *   This function allocates additional resources such as the host memory | 
|  | 374 | *   blocks needed by the adapter. | 
|  | 375 | *   The adapter is also reset. The OS must call skfp_open() to open | 
|  | 376 | *   the adapter and bring it on-line. | 
|  | 377 | * | 
|  | 378 | * Return Codes: | 
|  | 379 | *    0 - initialization succeeded | 
|  | 380 | *   -1 - initialization failed | 
|  | 381 | */ | 
|  | 382 | static  int skfp_driver_init(struct net_device *dev) | 
|  | 383 | { | 
|  | 384 | struct s_smc *smc = netdev_priv(dev); | 
|  | 385 | skfddi_priv *bp = &smc->os; | 
|  | 386 | int err = -EIO; | 
|  | 387 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 388 | pr_debug("entering skfp_driver_init\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 389 |  | 
|  | 390 | // set the io address in private structures | 
|  | 391 | bp->base_addr = dev->base_addr; | 
|  | 392 |  | 
|  | 393 | // Get the interrupt level from the PCI Configuration Table | 
|  | 394 | smc->hw.irq = dev->irq; | 
|  | 395 |  | 
|  | 396 | spin_lock_init(&bp->DriverLock); | 
|  | 397 |  | 
|  | 398 | // Allocate invalid frame | 
|  | 399 | bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA); | 
|  | 400 | if (!bp->LocalRxBuffer) { | 
|  | 401 | printk("could not allocate mem for "); | 
|  | 402 | printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE); | 
|  | 403 | goto fail; | 
|  | 404 | } | 
|  | 405 |  | 
|  | 406 | // Determine the required size of the 'shared' memory area. | 
|  | 407 | bp->SharedMemSize = mac_drv_check_space(); | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 408 | pr_debug("Memory for HWM: %ld\n", bp->SharedMemSize); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 409 | if (bp->SharedMemSize > 0) { | 
|  | 410 | bp->SharedMemSize += 16;	// for descriptor alignment | 
|  | 411 |  | 
|  | 412 | bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev, | 
|  | 413 | bp->SharedMemSize, | 
|  | 414 | &bp->SharedMemDMA); | 
| Dan Carpenter | 4a5fc4e | 2010-12-23 19:17:34 +0000 | [diff] [blame] | 415 | if (!bp->SharedMemAddr) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 416 | printk("could not allocate mem for "); | 
|  | 417 | printk("hardware module: %ld byte\n", | 
|  | 418 | bp->SharedMemSize); | 
|  | 419 | goto fail; | 
|  | 420 | } | 
|  | 421 | bp->SharedMemHeap = 0;	// Nothing used yet. | 
|  | 422 |  | 
|  | 423 | } else { | 
|  | 424 | bp->SharedMemAddr = NULL; | 
|  | 425 | bp->SharedMemHeap = 0; | 
|  | 426 | }			// SharedMemSize > 0 | 
|  | 427 |  | 
|  | 428 | memset(bp->SharedMemAddr, 0, bp->SharedMemSize); | 
|  | 429 |  | 
|  | 430 | card_stop(smc);		// Reset adapter. | 
|  | 431 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 432 | pr_debug("mac_drv_init()..\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 433 | if (mac_drv_init(smc) != 0) { | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 434 | pr_debug("mac_drv_init() failed\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 435 | goto fail; | 
|  | 436 | } | 
|  | 437 | read_address(smc, NULL); | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 438 | pr_debug("HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 439 | memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6); | 
|  | 440 |  | 
|  | 441 | smt_reset_defaults(smc, 0); | 
|  | 442 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 443 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 444 |  | 
|  | 445 | fail: | 
|  | 446 | if (bp->SharedMemAddr) { | 
|  | 447 | pci_free_consistent(&bp->pdev, | 
|  | 448 | bp->SharedMemSize, | 
|  | 449 | bp->SharedMemAddr, | 
|  | 450 | bp->SharedMemDMA); | 
|  | 451 | bp->SharedMemAddr = NULL; | 
|  | 452 | } | 
|  | 453 | if (bp->LocalRxBuffer) { | 
|  | 454 | pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE, | 
|  | 455 | bp->LocalRxBuffer, bp->LocalRxBufferDMA); | 
|  | 456 | bp->LocalRxBuffer = NULL; | 
|  | 457 | } | 
|  | 458 | return err; | 
|  | 459 | }				// skfp_driver_init | 
|  | 460 |  | 
|  | 461 |  | 
|  | 462 | /* | 
|  | 463 | * ============= | 
|  | 464 | * = skfp_open = | 
|  | 465 | * ============= | 
|  | 466 | * | 
|  | 467 | * Overview: | 
|  | 468 | *   Opens the adapter | 
|  | 469 | * | 
|  | 470 | * Returns: | 
|  | 471 | *   Condition code | 
|  | 472 | * | 
|  | 473 | * Arguments: | 
|  | 474 | *   dev - pointer to device information | 
|  | 475 | * | 
|  | 476 | * Functional Description: | 
|  | 477 | *   This function brings the adapter to an operational state. | 
|  | 478 | * | 
|  | 479 | * Return Codes: | 
|  | 480 | *   0           - Adapter was successfully opened | 
|  | 481 | *   -EAGAIN - Could not register IRQ | 
|  | 482 | */ | 
|  | 483 | static int skfp_open(struct net_device *dev) | 
|  | 484 | { | 
|  | 485 | struct s_smc *smc = netdev_priv(dev); | 
|  | 486 | int err; | 
|  | 487 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 488 | pr_debug("entering skfp_open\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 489 | /* Register IRQ - support shared interrupts by passing device ptr */ | 
| Al Viro | 2f220e3 | 2008-03-16 22:22:24 +0000 | [diff] [blame] | 490 | err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 491 | dev->name, dev); | 
|  | 492 | if (err) | 
|  | 493 | return err; | 
|  | 494 |  | 
|  | 495 | /* | 
|  | 496 | * Set current address to factory MAC address | 
|  | 497 | * | 
|  | 498 | * Note: We've already done this step in skfp_driver_init. | 
|  | 499 | *       However, it's possible that a user has set a node | 
|  | 500 | *               address override, then closed and reopened the | 
|  | 501 | *               adapter.  Unless we reset the device address field | 
|  | 502 | *               now, we'll continue to use the existing modified | 
|  | 503 | *               address. | 
|  | 504 | */ | 
|  | 505 | read_address(smc, NULL); | 
|  | 506 | memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6); | 
|  | 507 |  | 
|  | 508 | init_smt(smc, NULL); | 
|  | 509 | smt_online(smc, 1); | 
|  | 510 | STI_FBI(); | 
|  | 511 |  | 
|  | 512 | /* Clear local multicast address tables */ | 
|  | 513 | mac_clear_multicast(smc); | 
|  | 514 |  | 
|  | 515 | /* Disable promiscuous filter settings */ | 
|  | 516 | mac_drv_rx_mode(smc, RX_DISABLE_PROMISC); | 
|  | 517 |  | 
|  | 518 | netif_start_queue(dev); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 519 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 520 | }				// skfp_open | 
|  | 521 |  | 
|  | 522 |  | 
|  | 523 | /* | 
|  | 524 | * ============== | 
|  | 525 | * = skfp_close = | 
|  | 526 | * ============== | 
|  | 527 | * | 
|  | 528 | * Overview: | 
|  | 529 | *   Closes the device/module. | 
|  | 530 | * | 
|  | 531 | * Returns: | 
|  | 532 | *   Condition code | 
|  | 533 | * | 
|  | 534 | * Arguments: | 
|  | 535 | *   dev - pointer to device information | 
|  | 536 | * | 
|  | 537 | * Functional Description: | 
|  | 538 | *   This routine closes the adapter and brings it to a safe state. | 
|  | 539 | *   The interrupt service routine is deregistered with the OS. | 
|  | 540 | *   The adapter can be opened again with another call to skfp_open(). | 
|  | 541 | * | 
|  | 542 | * Return Codes: | 
|  | 543 | *   Always return 0. | 
|  | 544 | * | 
|  | 545 | * Assumptions: | 
|  | 546 | *   No further requests for this adapter are made after this routine is | 
|  | 547 | *   called.  skfp_open() can be called to reset and reinitialize the | 
|  | 548 | *   adapter. | 
|  | 549 | */ | 
|  | 550 | static int skfp_close(struct net_device *dev) | 
|  | 551 | { | 
|  | 552 | struct s_smc *smc = netdev_priv(dev); | 
|  | 553 | skfddi_priv *bp = &smc->os; | 
|  | 554 |  | 
|  | 555 | CLI_FBI(); | 
|  | 556 | smt_reset_defaults(smc, 1); | 
|  | 557 | card_stop(smc); | 
|  | 558 | mac_drv_clear_tx_queue(smc); | 
|  | 559 | mac_drv_clear_rx_queue(smc); | 
|  | 560 |  | 
|  | 561 | netif_stop_queue(dev); | 
|  | 562 | /* Deregister (free) IRQ */ | 
|  | 563 | free_irq(dev->irq, dev); | 
|  | 564 |  | 
|  | 565 | skb_queue_purge(&bp->SendSkbQueue); | 
|  | 566 | bp->QueueSkb = MAX_TX_QUEUE_LEN; | 
|  | 567 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 568 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 569 | }				// skfp_close | 
|  | 570 |  | 
|  | 571 |  | 
|  | 572 | /* | 
|  | 573 | * ================== | 
|  | 574 | * = skfp_interrupt = | 
|  | 575 | * ================== | 
|  | 576 | * | 
|  | 577 | * Overview: | 
|  | 578 | *   Interrupt processing routine | 
|  | 579 | * | 
|  | 580 | * Returns: | 
|  | 581 | *   None | 
|  | 582 | * | 
|  | 583 | * Arguments: | 
|  | 584 | *   irq        - interrupt vector | 
|  | 585 | *   dev_id     - pointer to device information | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 586 | * | 
|  | 587 | * Functional Description: | 
|  | 588 | *   This routine calls the interrupt processing routine for this adapter.  It | 
|  | 589 | *   disables and reenables adapter interrupts, as appropriate.  We can support | 
|  | 590 | *   shared interrupts since the incoming dev_id pointer provides our device | 
|  | 591 | *   structure context. All the real work is done in the hardware module. | 
|  | 592 | * | 
|  | 593 | * Return Codes: | 
|  | 594 | *   None | 
|  | 595 | * | 
|  | 596 | * Assumptions: | 
|  | 597 | *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC | 
|  | 598 | *   on Intel-based systems) is done by the operating system outside this | 
|  | 599 | *   routine. | 
|  | 600 | * | 
|  | 601 | *       System interrupts are enabled through this call. | 
|  | 602 | * | 
|  | 603 | * Side Effects: | 
|  | 604 | *   Interrupts are disabled, then reenabled at the adapter. | 
|  | 605 | */ | 
|  | 606 |  | 
| Hannes Eder | 409b204 | 2008-12-26 00:06:28 -0800 | [diff] [blame] | 607 | static irqreturn_t skfp_interrupt(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 608 | { | 
| Jeff Garzik | c31f28e | 2006-10-06 14:56:04 -0400 | [diff] [blame] | 609 | struct net_device *dev = dev_id; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 610 | struct s_smc *smc;	/* private board structure pointer */ | 
|  | 611 | skfddi_priv *bp; | 
|  | 612 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 613 | smc = netdev_priv(dev); | 
|  | 614 | bp = &smc->os; | 
|  | 615 |  | 
|  | 616 | // IRQs enabled or disabled ? | 
|  | 617 | if (inpd(ADDR(B0_IMSK)) == 0) { | 
|  | 618 | // IRQs are disabled: must be shared interrupt | 
|  | 619 | return IRQ_NONE; | 
|  | 620 | } | 
|  | 621 | // Note: At this point, IRQs are enabled. | 
|  | 622 | if ((inpd(ISR_A) & smc->hw.is_imask) == 0) {	// IRQ? | 
|  | 623 | // Adapter did not issue an IRQ: must be shared interrupt | 
|  | 624 | return IRQ_NONE; | 
|  | 625 | } | 
|  | 626 | CLI_FBI();		// Disable IRQs from our adapter. | 
|  | 627 | spin_lock(&bp->DriverLock); | 
|  | 628 |  | 
|  | 629 | // Call interrupt handler in hardware module (HWM). | 
|  | 630 | fddi_isr(smc); | 
|  | 631 |  | 
|  | 632 | if (smc->os.ResetRequested) { | 
|  | 633 | ResetAdapter(smc); | 
|  | 634 | smc->os.ResetRequested = FALSE; | 
|  | 635 | } | 
|  | 636 | spin_unlock(&bp->DriverLock); | 
|  | 637 | STI_FBI();		// Enable IRQs from our adapter. | 
|  | 638 |  | 
|  | 639 | return IRQ_HANDLED; | 
|  | 640 | }				// skfp_interrupt | 
|  | 641 |  | 
|  | 642 |  | 
|  | 643 | /* | 
|  | 644 | * ====================== | 
|  | 645 | * = skfp_ctl_get_stats = | 
|  | 646 | * ====================== | 
|  | 647 | * | 
|  | 648 | * Overview: | 
|  | 649 | *   Get statistics for FDDI adapter | 
|  | 650 | * | 
|  | 651 | * Returns: | 
|  | 652 | *   Pointer to FDDI statistics structure | 
|  | 653 | * | 
|  | 654 | * Arguments: | 
|  | 655 | *   dev - pointer to device information | 
|  | 656 | * | 
|  | 657 | * Functional Description: | 
|  | 658 | *   Gets current MIB objects from adapter, then | 
|  | 659 | *   returns FDDI statistics structure as defined | 
|  | 660 | *   in if_fddi.h. | 
|  | 661 | * | 
|  | 662 | *   Note: Since the FDDI statistics structure is | 
|  | 663 | *   still new and the device structure doesn't | 
|  | 664 | *   have an FDDI-specific get statistics handler, | 
|  | 665 | *   we'll return the FDDI statistics structure as | 
|  | 666 | *   a pointer to an Ethernet statistics structure. | 
|  | 667 | *   That way, at least the first part of the statistics | 
|  | 668 | *   structure can be decoded properly. | 
|  | 669 | *   We'll have to pay attention to this routine as the | 
|  | 670 | *   device structure becomes more mature and LAN media | 
|  | 671 | *   independent. | 
|  | 672 | * | 
|  | 673 | */ | 
| Hannes Eder | 409b204 | 2008-12-26 00:06:28 -0800 | [diff] [blame] | 674 | static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 675 | { | 
|  | 676 | struct s_smc *bp = netdev_priv(dev); | 
|  | 677 |  | 
|  | 678 | /* Fill the bp->stats structure with driver-maintained counters */ | 
|  | 679 |  | 
|  | 680 | bp->os.MacStat.port_bs_flag[0] = 0x1234; | 
|  | 681 | bp->os.MacStat.port_bs_flag[1] = 0x5678; | 
|  | 682 | // goos: need to fill out fddi statistic | 
|  | 683 | #if 0 | 
|  | 684 | /* Get FDDI SMT MIB objects */ | 
|  | 685 |  | 
|  | 686 | /* Fill the bp->stats structure with the SMT MIB object values */ | 
|  | 687 |  | 
|  | 688 | memcpy(bp->stats.smt_station_id, &bp->cmd_rsp_virt->smt_mib_get.smt_station_id, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_station_id)); | 
|  | 689 | bp->stats.smt_op_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id; | 
|  | 690 | bp->stats.smt_hi_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id; | 
|  | 691 | bp->stats.smt_lo_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id; | 
|  | 692 | memcpy(bp->stats.smt_user_data, &bp->cmd_rsp_virt->smt_mib_get.smt_user_data, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_user_data)); | 
|  | 693 | bp->stats.smt_mib_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id; | 
|  | 694 | bp->stats.smt_mac_cts = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct; | 
|  | 695 | bp->stats.smt_non_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct; | 
|  | 696 | bp->stats.smt_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct; | 
|  | 697 | bp->stats.smt_available_paths = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths; | 
|  | 698 | bp->stats.smt_config_capabilities = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities; | 
|  | 699 | bp->stats.smt_config_policy = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy; | 
|  | 700 | bp->stats.smt_connection_policy = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy; | 
|  | 701 | bp->stats.smt_t_notify = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify; | 
|  | 702 | bp->stats.smt_stat_rpt_policy = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy; | 
|  | 703 | bp->stats.smt_trace_max_expiration = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration; | 
|  | 704 | bp->stats.smt_bypass_present = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present; | 
|  | 705 | bp->stats.smt_ecm_state = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state; | 
|  | 706 | bp->stats.smt_cf_state = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state; | 
|  | 707 | bp->stats.smt_remote_disconnect_flag = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag; | 
|  | 708 | bp->stats.smt_station_status = bp->cmd_rsp_virt->smt_mib_get.smt_station_status; | 
|  | 709 | bp->stats.smt_peer_wrap_flag = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag; | 
|  | 710 | bp->stats.smt_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls; | 
|  | 711 | bp->stats.smt_transition_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls; | 
|  | 712 | bp->stats.mac_frame_status_functions = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions; | 
|  | 713 | bp->stats.mac_t_max_capability = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability; | 
|  | 714 | bp->stats.mac_tvx_capability = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability; | 
|  | 715 | bp->stats.mac_available_paths = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths; | 
|  | 716 | bp->stats.mac_current_path = bp->cmd_rsp_virt->smt_mib_get.mac_current_path; | 
|  | 717 | memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN); | 
|  | 718 | memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN); | 
|  | 719 | memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN); | 
|  | 720 | memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN); | 
|  | 721 | bp->stats.mac_dup_address_test = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test; | 
|  | 722 | bp->stats.mac_requested_paths = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths; | 
|  | 723 | bp->stats.mac_downstream_port_type = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type; | 
|  | 724 | memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN); | 
|  | 725 | bp->stats.mac_t_req = bp->cmd_rsp_virt->smt_mib_get.mac_t_req; | 
|  | 726 | bp->stats.mac_t_neg = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg; | 
|  | 727 | bp->stats.mac_t_max = bp->cmd_rsp_virt->smt_mib_get.mac_t_max; | 
|  | 728 | bp->stats.mac_tvx_value = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value; | 
|  | 729 | bp->stats.mac_frame_error_threshold = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold; | 
|  | 730 | bp->stats.mac_frame_error_ratio = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio; | 
|  | 731 | bp->stats.mac_rmt_state = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state; | 
|  | 732 | bp->stats.mac_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag; | 
|  | 733 | bp->stats.mac_una_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag; | 
|  | 734 | bp->stats.mac_frame_error_flag = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag; | 
|  | 735 | bp->stats.mac_ma_unitdata_available = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available; | 
|  | 736 | bp->stats.mac_hardware_present = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present; | 
|  | 737 | bp->stats.mac_ma_unitdata_enable = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable; | 
|  | 738 | bp->stats.path_tvx_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound; | 
|  | 739 | bp->stats.path_t_max_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound; | 
|  | 740 | bp->stats.path_max_t_req = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req; | 
|  | 741 | memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration)); | 
|  | 742 | bp->stats.port_my_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0]; | 
|  | 743 | bp->stats.port_my_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1]; | 
|  | 744 | bp->stats.port_neighbor_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0]; | 
|  | 745 | bp->stats.port_neighbor_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1]; | 
|  | 746 | bp->stats.port_connection_policies[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0]; | 
|  | 747 | bp->stats.port_connection_policies[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1]; | 
|  | 748 | bp->stats.port_mac_indicated[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0]; | 
|  | 749 | bp->stats.port_mac_indicated[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1]; | 
|  | 750 | bp->stats.port_current_path[0] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0]; | 
|  | 751 | bp->stats.port_current_path[1] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1]; | 
|  | 752 | memcpy(&bp->stats.port_requested_paths[0 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3); | 
|  | 753 | memcpy(&bp->stats.port_requested_paths[1 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3); | 
|  | 754 | bp->stats.port_mac_placement[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0]; | 
|  | 755 | bp->stats.port_mac_placement[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1]; | 
|  | 756 | bp->stats.port_available_paths[0] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0]; | 
|  | 757 | bp->stats.port_available_paths[1] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1]; | 
|  | 758 | bp->stats.port_pmd_class[0] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0]; | 
|  | 759 | bp->stats.port_pmd_class[1] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1]; | 
|  | 760 | bp->stats.port_connection_capabilities[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0]; | 
|  | 761 | bp->stats.port_connection_capabilities[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1]; | 
|  | 762 | bp->stats.port_bs_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0]; | 
|  | 763 | bp->stats.port_bs_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1]; | 
|  | 764 | bp->stats.port_ler_estimate[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0]; | 
|  | 765 | bp->stats.port_ler_estimate[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1]; | 
|  | 766 | bp->stats.port_ler_cutoff[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0]; | 
|  | 767 | bp->stats.port_ler_cutoff[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1]; | 
|  | 768 | bp->stats.port_ler_alarm[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0]; | 
|  | 769 | bp->stats.port_ler_alarm[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1]; | 
|  | 770 | bp->stats.port_connect_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0]; | 
|  | 771 | bp->stats.port_connect_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1]; | 
|  | 772 | bp->stats.port_pcm_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0]; | 
|  | 773 | bp->stats.port_pcm_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1]; | 
|  | 774 | bp->stats.port_pc_withhold[0] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0]; | 
|  | 775 | bp->stats.port_pc_withhold[1] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1]; | 
|  | 776 | bp->stats.port_ler_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0]; | 
|  | 777 | bp->stats.port_ler_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1]; | 
|  | 778 | bp->stats.port_hardware_present[0] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0]; | 
|  | 779 | bp->stats.port_hardware_present[1] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1]; | 
|  | 780 |  | 
|  | 781 |  | 
|  | 782 | /* Fill the bp->stats structure with the FDDI counter values */ | 
|  | 783 |  | 
|  | 784 | bp->stats.mac_frame_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls; | 
|  | 785 | bp->stats.mac_copied_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls; | 
|  | 786 | bp->stats.mac_transmit_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls; | 
|  | 787 | bp->stats.mac_error_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls; | 
|  | 788 | bp->stats.mac_lost_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls; | 
|  | 789 | bp->stats.port_lct_fail_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls; | 
|  | 790 | bp->stats.port_lct_fail_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls; | 
|  | 791 | bp->stats.port_lem_reject_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls; | 
|  | 792 | bp->stats.port_lem_reject_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls; | 
|  | 793 | bp->stats.port_lem_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls; | 
|  | 794 | bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls; | 
|  | 795 |  | 
|  | 796 | #endif | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 797 | return (struct net_device_stats *)&bp->os.MacStat; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 798 | }				// ctl_get_stat | 
|  | 799 |  | 
|  | 800 |  | 
|  | 801 | /* | 
|  | 802 | * ============================== | 
|  | 803 | * = skfp_ctl_set_multicast_list = | 
|  | 804 | * ============================== | 
|  | 805 | * | 
|  | 806 | * Overview: | 
|  | 807 | *   Enable/Disable LLC frame promiscuous mode reception | 
|  | 808 | *   on the adapter and/or update multicast address table. | 
|  | 809 | * | 
|  | 810 | * Returns: | 
|  | 811 | *   None | 
|  | 812 | * | 
|  | 813 | * Arguments: | 
|  | 814 | *   dev - pointer to device information | 
|  | 815 | * | 
|  | 816 | * Functional Description: | 
|  | 817 | *   This function acquires the driver lock and only calls | 
|  | 818 | *   skfp_ctl_set_multicast_list_wo_lock then. | 
|  | 819 | *   This routine follows a fairly simple algorithm for setting the | 
|  | 820 | *   adapter filters and CAM: | 
|  | 821 | * | 
|  | 822 | *      if IFF_PROMISC flag is set | 
|  | 823 | *              enable promiscuous mode | 
|  | 824 | *      else | 
|  | 825 | *              disable promiscuous mode | 
|  | 826 | *              if number of multicast addresses <= max. multicast number | 
|  | 827 | *                      add mc addresses to adapter table | 
|  | 828 | *              else | 
|  | 829 | *                      enable promiscuous mode | 
|  | 830 | *              update adapter filters | 
|  | 831 | * | 
|  | 832 | * Assumptions: | 
|  | 833 | *   Multicast addresses are presented in canonical (LSB) format. | 
|  | 834 | * | 
|  | 835 | * Side Effects: | 
|  | 836 | *   On-board adapter filters are updated. | 
|  | 837 | */ | 
|  | 838 | static void skfp_ctl_set_multicast_list(struct net_device *dev) | 
|  | 839 | { | 
|  | 840 | struct s_smc *smc = netdev_priv(dev); | 
|  | 841 | skfddi_priv *bp = &smc->os; | 
|  | 842 | unsigned long Flags; | 
|  | 843 |  | 
|  | 844 | spin_lock_irqsave(&bp->DriverLock, Flags); | 
|  | 845 | skfp_ctl_set_multicast_list_wo_lock(dev); | 
|  | 846 | spin_unlock_irqrestore(&bp->DriverLock, Flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 847 | }				// skfp_ctl_set_multicast_list | 
|  | 848 |  | 
|  | 849 |  | 
|  | 850 |  | 
|  | 851 | static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) | 
|  | 852 | { | 
|  | 853 | struct s_smc *smc = netdev_priv(dev); | 
| Jiri Pirko | 22bedad3 | 2010-04-01 21:22:57 +0000 | [diff] [blame] | 854 | struct netdev_hw_addr *ha; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 855 |  | 
|  | 856 | /* Enable promiscuous mode, if necessary */ | 
|  | 857 | if (dev->flags & IFF_PROMISC) { | 
|  | 858 | mac_drv_rx_mode(smc, RX_ENABLE_PROMISC); | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 859 | pr_debug("PROMISCUOUS MODE ENABLED\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 860 | } | 
|  | 861 | /* Else, update multicast address table */ | 
|  | 862 | else { | 
|  | 863 | mac_drv_rx_mode(smc, RX_DISABLE_PROMISC); | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 864 | pr_debug("PROMISCUOUS MODE DISABLED\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 865 |  | 
|  | 866 | // Reset all MC addresses | 
|  | 867 | mac_clear_multicast(smc); | 
|  | 868 | mac_drv_rx_mode(smc, RX_DISABLE_ALLMULTI); | 
|  | 869 |  | 
|  | 870 | if (dev->flags & IFF_ALLMULTI) { | 
|  | 871 | mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI); | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 872 | pr_debug("ENABLE ALL MC ADDRESSES\n"); | 
| Jiri Pirko | 4cd24ea | 2010-02-08 04:30:35 +0000 | [diff] [blame] | 873 | } else if (!netdev_mc_empty(dev)) { | 
|  | 874 | if (netdev_mc_count(dev) <= FPMAX_MULTICAST) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 875 | /* use exact filtering */ | 
|  | 876 |  | 
|  | 877 | // point to first multicast addr | 
| Jiri Pirko | 22bedad3 | 2010-04-01 21:22:57 +0000 | [diff] [blame] | 878 | netdev_for_each_mc_addr(ha, dev) { | 
|  | 879 | mac_add_multicast(smc, | 
|  | 880 | (struct fddi_addr *)ha->addr, | 
|  | 881 | 1); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 882 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 883 | pr_debug("ENABLE MC ADDRESS: %pMF\n", | 
|  | 884 | ha->addr); | 
| Jiri Pirko | 5508590 | 2010-02-18 00:42:54 +0000 | [diff] [blame] | 885 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 886 |  | 
|  | 887 | } else {	// more MC addresses than HW supports | 
|  | 888 |  | 
|  | 889 | mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI); | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 890 | pr_debug("ENABLE ALL MC ADDRESSES\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 891 | } | 
|  | 892 | } else {	// no MC addresses | 
|  | 893 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 894 | pr_debug("DISABLE ALL MC ADDRESSES\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 895 | } | 
|  | 896 |  | 
|  | 897 | /* Update adapter filters */ | 
|  | 898 | mac_update_multicast(smc); | 
|  | 899 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 900 | }				// skfp_ctl_set_multicast_list_wo_lock | 
|  | 901 |  | 
|  | 902 |  | 
|  | 903 | /* | 
|  | 904 | * =========================== | 
|  | 905 | * = skfp_ctl_set_mac_address = | 
|  | 906 | * =========================== | 
|  | 907 | * | 
|  | 908 | * Overview: | 
|  | 909 | *   set new mac address on adapter and update dev_addr field in device table. | 
|  | 910 | * | 
|  | 911 | * Returns: | 
|  | 912 | *   None | 
|  | 913 | * | 
|  | 914 | * Arguments: | 
|  | 915 | *   dev  - pointer to device information | 
|  | 916 | *   addr - pointer to sockaddr structure containing unicast address to set | 
|  | 917 | * | 
|  | 918 | * Assumptions: | 
|  | 919 | *   The address pointed to by addr->sa_data is a valid unicast | 
|  | 920 | *   address and is presented in canonical (LSB) format. | 
|  | 921 | */ | 
|  | 922 | static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr) | 
|  | 923 | { | 
|  | 924 | struct s_smc *smc = netdev_priv(dev); | 
|  | 925 | struct sockaddr *p_sockaddr = (struct sockaddr *) addr; | 
|  | 926 | skfddi_priv *bp = &smc->os; | 
|  | 927 | unsigned long Flags; | 
|  | 928 |  | 
|  | 929 |  | 
|  | 930 | memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN); | 
|  | 931 | spin_lock_irqsave(&bp->DriverLock, Flags); | 
|  | 932 | ResetAdapter(smc); | 
|  | 933 | spin_unlock_irqrestore(&bp->DriverLock, Flags); | 
|  | 934 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 935 | return 0;		/* always return zero */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 936 | }				// skfp_ctl_set_mac_address | 
|  | 937 |  | 
|  | 938 |  | 
|  | 939 | /* | 
|  | 940 | * ============== | 
|  | 941 | * = skfp_ioctl = | 
|  | 942 | * ============== | 
|  | 943 | * | 
|  | 944 | * Overview: | 
|  | 945 | * | 
|  | 946 | * Perform IOCTL call functions here. Some are privileged operations and the | 
|  | 947 | * effective uid is checked in those cases. | 
|  | 948 | * | 
|  | 949 | * Returns: | 
|  | 950 | *   status value | 
|  | 951 | *   0 - success | 
|  | 952 | *   other - failure | 
|  | 953 | * | 
|  | 954 | * Arguments: | 
|  | 955 | *   dev  - pointer to device information | 
|  | 956 | *   rq - pointer to ioctl request structure | 
|  | 957 | *   cmd - ? | 
|  | 958 | * | 
|  | 959 | */ | 
|  | 960 |  | 
|  | 961 |  | 
|  | 962 | static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 
|  | 963 | { | 
|  | 964 | struct s_smc *smc = netdev_priv(dev); | 
|  | 965 | skfddi_priv *lp = &smc->os; | 
|  | 966 | struct s_skfp_ioctl ioc; | 
|  | 967 | int status = 0; | 
|  | 968 |  | 
|  | 969 | if (copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl))) | 
|  | 970 | return -EFAULT; | 
|  | 971 |  | 
|  | 972 | switch (ioc.cmd) { | 
|  | 973 | case SKFP_GET_STATS:	/* Get the driver statistics */ | 
|  | 974 | ioc.len = sizeof(lp->MacStat); | 
|  | 975 | status = copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len) | 
|  | 976 | ? -EFAULT : 0; | 
|  | 977 | break; | 
|  | 978 | case SKFP_CLR_STATS:	/* Zero out the driver statistics */ | 
|  | 979 | if (!capable(CAP_NET_ADMIN)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 980 | status = -EPERM; | 
| Roel Kluin | c25b9ab | 2009-01-29 17:32:20 -0800 | [diff] [blame] | 981 | } else { | 
|  | 982 | memset(&lp->MacStat, 0, sizeof(lp->MacStat)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 983 | } | 
|  | 984 | break; | 
|  | 985 | default: | 
| André Goddard Rosa | af901ca | 2009-11-14 13:09:05 -0200 | [diff] [blame] | 986 | printk("ioctl for %s: unknown cmd: %04x\n", dev->name, ioc.cmd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 987 | status = -EOPNOTSUPP; | 
|  | 988 |  | 
|  | 989 | }			// switch | 
|  | 990 |  | 
|  | 991 | return status; | 
|  | 992 | }				// skfp_ioctl | 
|  | 993 |  | 
|  | 994 |  | 
|  | 995 | /* | 
|  | 996 | * ===================== | 
|  | 997 | * = skfp_send_pkt     = | 
|  | 998 | * ===================== | 
|  | 999 | * | 
|  | 1000 | * Overview: | 
|  | 1001 | *   Queues a packet for transmission and try to transmit it. | 
|  | 1002 | * | 
|  | 1003 | * Returns: | 
|  | 1004 | *   Condition code | 
|  | 1005 | * | 
|  | 1006 | * Arguments: | 
|  | 1007 | *   skb - pointer to sk_buff to queue for transmission | 
|  | 1008 | *   dev - pointer to device information | 
|  | 1009 | * | 
|  | 1010 | * Functional Description: | 
|  | 1011 | *   Here we assume that an incoming skb transmit request | 
|  | 1012 | *   is contained in a single physically contiguous buffer | 
|  | 1013 | *   in which the virtual address of the start of packet | 
|  | 1014 | *   (skb->data) can be converted to a physical address | 
|  | 1015 | *   by using pci_map_single(). | 
|  | 1016 | * | 
|  | 1017 | *   We have an internal queue for packets we can not send | 
|  | 1018 | *   immediately. Packets in this queue can be given to the | 
|  | 1019 | *   adapter if transmit buffers are freed. | 
|  | 1020 | * | 
|  | 1021 | *   We can't free the skb until after it's been DMA'd | 
|  | 1022 | *   out by the adapter, so we'll keep it in the driver and | 
|  | 1023 | *   return it in mac_drv_tx_complete. | 
|  | 1024 | * | 
|  | 1025 | * Return Codes: | 
|  | 1026 | *   0 - driver has queued and/or sent packet | 
|  | 1027 | *       1 - caller should requeue the sk_buff for later transmission | 
|  | 1028 | * | 
|  | 1029 | * Assumptions: | 
|  | 1030 | *   The entire packet is stored in one physically | 
|  | 1031 | *   contiguous buffer which is not cached and whose | 
|  | 1032 | *   32-bit physical address can be determined. | 
|  | 1033 | * | 
|  | 1034 | *   It's vital that this routine is NOT reentered for the | 
|  | 1035 | *   same board and that the OS is not in another section of | 
|  | 1036 | *   code (eg. skfp_interrupt) for the same board on a | 
|  | 1037 | *   different thread. | 
|  | 1038 | * | 
|  | 1039 | * Side Effects: | 
|  | 1040 | *   None | 
|  | 1041 | */ | 
| Stephen Hemminger | 61357325 | 2009-08-31 19:50:58 +0000 | [diff] [blame] | 1042 | static netdev_tx_t skfp_send_pkt(struct sk_buff *skb, | 
|  | 1043 | struct net_device *dev) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1044 | { | 
|  | 1045 | struct s_smc *smc = netdev_priv(dev); | 
|  | 1046 | skfddi_priv *bp = &smc->os; | 
|  | 1047 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1048 | pr_debug("skfp_send_pkt\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1049 |  | 
|  | 1050 | /* | 
|  | 1051 | * Verify that incoming transmit request is OK | 
|  | 1052 | * | 
|  | 1053 | * Note: The packet size check is consistent with other | 
|  | 1054 | *               Linux device drivers, although the correct packet | 
|  | 1055 | *               size should be verified before calling the | 
|  | 1056 | *               transmit routine. | 
|  | 1057 | */ | 
|  | 1058 |  | 
|  | 1059 | if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) { | 
|  | 1060 | bp->MacStat.gen.tx_errors++;	/* bump error counter */ | 
|  | 1061 | // dequeue packets from xmt queue and send them | 
|  | 1062 | netif_start_queue(dev); | 
|  | 1063 | dev_kfree_skb(skb); | 
| Patrick McHardy | ec634fe | 2009-07-05 19:23:38 -0700 | [diff] [blame] | 1064 | return NETDEV_TX_OK;	/* return "success" */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1065 | } | 
|  | 1066 | if (bp->QueueSkb == 0) {	// return with tbusy set: queue full | 
|  | 1067 |  | 
|  | 1068 | netif_stop_queue(dev); | 
| Patrick McHardy | 5b54814 | 2009-06-12 06:22:29 +0000 | [diff] [blame] | 1069 | return NETDEV_TX_BUSY; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1070 | } | 
|  | 1071 | bp->QueueSkb--; | 
|  | 1072 | skb_queue_tail(&bp->SendSkbQueue, skb); | 
|  | 1073 | send_queued_packets(netdev_priv(dev)); | 
|  | 1074 | if (bp->QueueSkb == 0) { | 
|  | 1075 | netif_stop_queue(dev); | 
|  | 1076 | } | 
| Patrick McHardy | 6ed1065 | 2009-06-23 06:03:08 +0000 | [diff] [blame] | 1077 | return NETDEV_TX_OK; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1078 |  | 
|  | 1079 | }				// skfp_send_pkt | 
|  | 1080 |  | 
|  | 1081 |  | 
|  | 1082 | /* | 
|  | 1083 | * ======================= | 
|  | 1084 | * = send_queued_packets = | 
|  | 1085 | * ======================= | 
|  | 1086 | * | 
|  | 1087 | * Overview: | 
|  | 1088 | *   Send packets from the driver queue as long as there are some and | 
|  | 1089 | *   transmit resources are available. | 
|  | 1090 | * | 
|  | 1091 | * Returns: | 
|  | 1092 | *   None | 
|  | 1093 | * | 
|  | 1094 | * Arguments: | 
|  | 1095 | *   smc - pointer to smc (adapter) structure | 
|  | 1096 | * | 
|  | 1097 | * Functional Description: | 
|  | 1098 | *   Take a packet from queue if there is any. If not, then we are done. | 
|  | 1099 | *   Check if there are resources to send the packet. If not, requeue it | 
|  | 1100 | *   and exit. | 
|  | 1101 | *   Set packet descriptor flags and give packet to adapter. | 
|  | 1102 | *   Check if any send resources can be freed (we do not use the | 
|  | 1103 | *   transmit complete interrupt). | 
|  | 1104 | */ | 
|  | 1105 | static void send_queued_packets(struct s_smc *smc) | 
|  | 1106 | { | 
|  | 1107 | skfddi_priv *bp = &smc->os; | 
|  | 1108 | struct sk_buff *skb; | 
|  | 1109 | unsigned char fc; | 
|  | 1110 | int queue; | 
|  | 1111 | struct s_smt_fp_txd *txd;	// Current TxD. | 
|  | 1112 | dma_addr_t dma_address; | 
|  | 1113 | unsigned long Flags; | 
|  | 1114 |  | 
|  | 1115 | int frame_status;	// HWM tx frame status. | 
|  | 1116 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1117 | pr_debug("send queued packets\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1118 | for (;;) { | 
|  | 1119 | // send first buffer from queue | 
|  | 1120 | skb = skb_dequeue(&bp->SendSkbQueue); | 
|  | 1121 |  | 
|  | 1122 | if (!skb) { | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1123 | pr_debug("queue empty\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1124 | return; | 
|  | 1125 | }		// queue empty ! | 
|  | 1126 |  | 
|  | 1127 | spin_lock_irqsave(&bp->DriverLock, Flags); | 
|  | 1128 | fc = skb->data[0]; | 
|  | 1129 | queue = (fc & FC_SYNC_BIT) ? QUEUE_S : QUEUE_A0; | 
|  | 1130 | #ifdef ESS | 
|  | 1131 | // Check if the frame may/must be sent as a synchronous frame. | 
|  | 1132 |  | 
|  | 1133 | if ((fc & ~(FC_SYNC_BIT | FC_LLC_PRIOR)) == FC_ASYNC_LLC) { | 
|  | 1134 | // It's an LLC frame. | 
|  | 1135 | if (!smc->ess.sync_bw_available) | 
|  | 1136 | fc &= ~FC_SYNC_BIT; // No bandwidth available. | 
|  | 1137 |  | 
|  | 1138 | else {	// Bandwidth is available. | 
|  | 1139 |  | 
|  | 1140 | if (smc->mib.fddiESSSynchTxMode) { | 
|  | 1141 | // Send as sync. frame. | 
|  | 1142 | fc |= FC_SYNC_BIT; | 
|  | 1143 | } | 
|  | 1144 | } | 
|  | 1145 | } | 
|  | 1146 | #endif				// ESS | 
|  | 1147 | frame_status = hwm_tx_init(smc, fc, 1, skb->len, queue); | 
|  | 1148 |  | 
|  | 1149 | if ((frame_status & (LOC_TX | LAN_TX)) == 0) { | 
|  | 1150 | // Unable to send the frame. | 
|  | 1151 |  | 
|  | 1152 | if ((frame_status & RING_DOWN) != 0) { | 
|  | 1153 | // Ring is down. | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1154 | pr_debug("Tx attempt while ring down.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1155 | } else if ((frame_status & OUT_OF_TXD) != 0) { | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1156 | pr_debug("%s: out of TXDs.\n", bp->dev->name); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1157 | } else { | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1158 | pr_debug("%s: out of transmit resources", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1159 | bp->dev->name); | 
|  | 1160 | } | 
|  | 1161 |  | 
|  | 1162 | // Note: We will retry the operation as soon as | 
|  | 1163 | // transmit resources become available. | 
|  | 1164 | skb_queue_head(&bp->SendSkbQueue, skb); | 
|  | 1165 | spin_unlock_irqrestore(&bp->DriverLock, Flags); | 
|  | 1166 | return;	// Packet has been queued. | 
|  | 1167 |  | 
|  | 1168 | }		// if (unable to send frame) | 
|  | 1169 |  | 
|  | 1170 | bp->QueueSkb++;	// one packet less in local queue | 
|  | 1171 |  | 
|  | 1172 | // source address in packet ? | 
|  | 1173 | CheckSourceAddress(skb->data, smc->hw.fddi_canon_addr.a); | 
|  | 1174 |  | 
|  | 1175 | txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue); | 
|  | 1176 |  | 
|  | 1177 | dma_address = pci_map_single(&bp->pdev, skb->data, | 
|  | 1178 | skb->len, PCI_DMA_TODEVICE); | 
|  | 1179 | if (frame_status & LAN_TX) { | 
|  | 1180 | txd->txd_os.skb = skb;			// save skb | 
|  | 1181 | txd->txd_os.dma_addr = dma_address;	// save dma mapping | 
|  | 1182 | } | 
|  | 1183 | hwm_tx_frag(smc, skb->data, dma_address, skb->len, | 
|  | 1184 | frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF); | 
|  | 1185 |  | 
|  | 1186 | if (!(frame_status & LAN_TX)) {		// local only frame | 
|  | 1187 | pci_unmap_single(&bp->pdev, dma_address, | 
|  | 1188 | skb->len, PCI_DMA_TODEVICE); | 
|  | 1189 | dev_kfree_skb_irq(skb); | 
|  | 1190 | } | 
|  | 1191 | spin_unlock_irqrestore(&bp->DriverLock, Flags); | 
|  | 1192 | }			// for | 
|  | 1193 |  | 
|  | 1194 | return;			// never reached | 
|  | 1195 |  | 
|  | 1196 | }				// send_queued_packets | 
|  | 1197 |  | 
|  | 1198 |  | 
|  | 1199 | /************************ | 
|  | 1200 | * | 
|  | 1201 | * CheckSourceAddress | 
|  | 1202 | * | 
|  | 1203 | * Verify if the source address is set. Insert it if necessary. | 
|  | 1204 | * | 
|  | 1205 | ************************/ | 
| Hannes Eder | 409b204 | 2008-12-26 00:06:28 -0800 | [diff] [blame] | 1206 | static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1207 | { | 
|  | 1208 | unsigned char SRBit; | 
|  | 1209 |  | 
|  | 1210 | if ((((unsigned long) frame[1 + 6]) & ~0x01) != 0) // source routing bit | 
|  | 1211 |  | 
|  | 1212 | return; | 
|  | 1213 | if ((unsigned short) frame[1 + 10] != 0) | 
|  | 1214 | return; | 
|  | 1215 | SRBit = frame[1 + 6] & 0x01; | 
|  | 1216 | memcpy(&frame[1 + 6], hw_addr, 6); | 
|  | 1217 | frame[8] |= SRBit; | 
|  | 1218 | }				// CheckSourceAddress | 
|  | 1219 |  | 
|  | 1220 |  | 
|  | 1221 | /************************ | 
|  | 1222 | * | 
|  | 1223 | *	ResetAdapter | 
|  | 1224 | * | 
|  | 1225 | *	Reset the adapter and bring it back to operational mode. | 
|  | 1226 | * Args | 
|  | 1227 | *	smc - A pointer to the SMT context struct. | 
|  | 1228 | * Out | 
|  | 1229 | *	Nothing. | 
|  | 1230 | * | 
|  | 1231 | ************************/ | 
|  | 1232 | static void ResetAdapter(struct s_smc *smc) | 
|  | 1233 | { | 
|  | 1234 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1235 | pr_debug("[fddi: ResetAdapter]\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1236 |  | 
|  | 1237 | // Stop the adapter. | 
|  | 1238 |  | 
|  | 1239 | card_stop(smc);		// Stop all activity. | 
|  | 1240 |  | 
|  | 1241 | // Clear the transmit and receive descriptor queues. | 
|  | 1242 | mac_drv_clear_tx_queue(smc); | 
|  | 1243 | mac_drv_clear_rx_queue(smc); | 
|  | 1244 |  | 
|  | 1245 | // Restart the adapter. | 
|  | 1246 |  | 
|  | 1247 | smt_reset_defaults(smc, 1);	// Initialize the SMT module. | 
|  | 1248 |  | 
|  | 1249 | init_smt(smc, (smc->os.dev)->dev_addr);	// Initialize the hardware. | 
|  | 1250 |  | 
|  | 1251 | smt_online(smc, 1);	// Insert into the ring again. | 
|  | 1252 | STI_FBI(); | 
|  | 1253 |  | 
|  | 1254 | // Restore original receive mode (multicasts, promiscuous, etc.). | 
|  | 1255 | skfp_ctl_set_multicast_list_wo_lock(smc->os.dev); | 
|  | 1256 | }				// ResetAdapter | 
|  | 1257 |  | 
|  | 1258 |  | 
|  | 1259 | //--------------- functions called by hardware module ---------------- | 
|  | 1260 |  | 
|  | 1261 | /************************ | 
|  | 1262 | * | 
|  | 1263 | *	llc_restart_tx | 
|  | 1264 | * | 
|  | 1265 | *	The hardware driver calls this routine when the transmit complete | 
|  | 1266 | *	interrupt bits (end of frame) for the synchronous or asynchronous | 
|  | 1267 | *	queue is set. | 
|  | 1268 | * | 
|  | 1269 | * NOTE The hardware driver calls this function also if no packets are queued. | 
|  | 1270 | *	The routine must be able to handle this case. | 
|  | 1271 | * Args | 
|  | 1272 | *	smc - A pointer to the SMT context struct. | 
|  | 1273 | * Out | 
|  | 1274 | *	Nothing. | 
|  | 1275 | * | 
|  | 1276 | ************************/ | 
|  | 1277 | void llc_restart_tx(struct s_smc *smc) | 
|  | 1278 | { | 
|  | 1279 | skfddi_priv *bp = &smc->os; | 
|  | 1280 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1281 | pr_debug("[llc_restart_tx]\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1282 |  | 
|  | 1283 | // Try to send queued packets | 
|  | 1284 | spin_unlock(&bp->DriverLock); | 
|  | 1285 | send_queued_packets(smc); | 
|  | 1286 | spin_lock(&bp->DriverLock); | 
|  | 1287 | netif_start_queue(bp->dev);// system may send again if it was blocked | 
|  | 1288 |  | 
|  | 1289 | }				// llc_restart_tx | 
|  | 1290 |  | 
|  | 1291 |  | 
|  | 1292 | /************************ | 
|  | 1293 | * | 
|  | 1294 | *	mac_drv_get_space | 
|  | 1295 | * | 
|  | 1296 | *	The hardware module calls this function to allocate the memory | 
|  | 1297 | *	for the SMT MBufs if the define MB_OUTSIDE_SMC is specified. | 
|  | 1298 | * Args | 
|  | 1299 | *	smc - A pointer to the SMT context struct. | 
|  | 1300 | * | 
|  | 1301 | *	size - Size of memory in bytes to allocate. | 
|  | 1302 | * Out | 
|  | 1303 | *	!= 0	A pointer to the virtual address of the allocated memory. | 
|  | 1304 | *	== 0	Allocation error. | 
|  | 1305 | * | 
|  | 1306 | ************************/ | 
|  | 1307 | void *mac_drv_get_space(struct s_smc *smc, unsigned int size) | 
|  | 1308 | { | 
|  | 1309 | void *virt; | 
|  | 1310 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1311 | pr_debug("mac_drv_get_space (%d bytes), ", size); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1312 | virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap); | 
|  | 1313 |  | 
|  | 1314 | if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) { | 
|  | 1315 | printk("Unexpected SMT memory size requested: %d\n", size); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1316 | return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1317 | } | 
|  | 1318 | smc->os.SharedMemHeap += size;	// Move heap pointer. | 
|  | 1319 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1320 | pr_debug("mac_drv_get_space end\n"); | 
|  | 1321 | pr_debug("virt addr: %lx\n", (ulong) virt); | 
|  | 1322 | pr_debug("bus  addr: %lx\n", (ulong) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1323 | (smc->os.SharedMemDMA + | 
|  | 1324 | ((char *) virt - (char *)smc->os.SharedMemAddr))); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1325 | return virt; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1326 | }				// mac_drv_get_space | 
|  | 1327 |  | 
|  | 1328 |  | 
|  | 1329 | /************************ | 
|  | 1330 | * | 
|  | 1331 | *	mac_drv_get_desc_mem | 
|  | 1332 | * | 
|  | 1333 | *	This function is called by the hardware dependent module. | 
|  | 1334 | *	It allocates the memory for the RxD and TxD descriptors. | 
|  | 1335 | * | 
|  | 1336 | *	This memory must be non-cached, non-movable and non-swappable. | 
|  | 1337 | *	This memory should start at a physical page boundary. | 
|  | 1338 | * Args | 
|  | 1339 | *	smc - A pointer to the SMT context struct. | 
|  | 1340 | * | 
|  | 1341 | *	size - Size of memory in bytes to allocate. | 
|  | 1342 | * Out | 
|  | 1343 | *	!= 0	A pointer to the virtual address of the allocated memory. | 
|  | 1344 | *	== 0	Allocation error. | 
|  | 1345 | * | 
|  | 1346 | ************************/ | 
|  | 1347 | void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size) | 
|  | 1348 | { | 
|  | 1349 |  | 
|  | 1350 | char *virt; | 
|  | 1351 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1352 | pr_debug("mac_drv_get_desc_mem\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1353 |  | 
|  | 1354 | // Descriptor memory must be aligned on 16-byte boundary. | 
|  | 1355 |  | 
|  | 1356 | virt = mac_drv_get_space(smc, size); | 
|  | 1357 |  | 
|  | 1358 | size = (u_int) (16 - (((unsigned long) virt) & 15UL)); | 
|  | 1359 | size = size % 16; | 
|  | 1360 |  | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1361 | pr_debug("Allocate %u bytes alignment gap ", size); | 
|  | 1362 | pr_debug("for descriptor memory.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1363 |  | 
|  | 1364 | if (!mac_drv_get_space(smc, size)) { | 
|  | 1365 | printk("fddi: Unable to align descriptor memory.\n"); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1366 | return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1367 | } | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1368 | return virt + size; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1369 | }				// mac_drv_get_desc_mem | 
|  | 1370 |  | 
|  | 1371 |  | 
|  | 1372 | /************************ | 
|  | 1373 | * | 
|  | 1374 | *	mac_drv_virt2phys | 
|  | 1375 | * | 
|  | 1376 | *	Get the physical address of a given virtual address. | 
|  | 1377 | * Args | 
|  | 1378 | *	smc - A pointer to the SMT context struct. | 
|  | 1379 | * | 
|  | 1380 | *	virt - A (virtual) pointer into our 'shared' memory area. | 
|  | 1381 | * Out | 
|  | 1382 | *	Physical address of the given virtual address. | 
|  | 1383 | * | 
|  | 1384 | ************************/ | 
|  | 1385 | unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt) | 
|  | 1386 | { | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1387 | return smc->os.SharedMemDMA + | 
|  | 1388 | ((char *) virt - (char *)smc->os.SharedMemAddr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1389 | }				// mac_drv_virt2phys | 
|  | 1390 |  | 
|  | 1391 |  | 
|  | 1392 | /************************ | 
|  | 1393 | * | 
|  | 1394 | *	dma_master | 
|  | 1395 | * | 
|  | 1396 | *	The HWM calls this function, when the driver leads through a DMA | 
|  | 1397 | *	transfer. If the OS-specific module must prepare the system hardware | 
|  | 1398 | *	for the DMA transfer, it should do it in this function. | 
|  | 1399 | * | 
|  | 1400 | *	The hardware module calls this dma_master if it wants to send an SMT | 
|  | 1401 | *	frame.  This means that the virt address passed in here is part of | 
|  | 1402 | *      the 'shared' memory area. | 
|  | 1403 | * Args | 
|  | 1404 | *	smc - A pointer to the SMT context struct. | 
|  | 1405 | * | 
|  | 1406 | *	virt - The virtual address of the data. | 
|  | 1407 | * | 
|  | 1408 | *	len - The length in bytes of the data. | 
|  | 1409 | * | 
|  | 1410 | *	flag - Indicates the transmit direction and the buffer type: | 
|  | 1411 | *		DMA_RD	(0x01)	system RAM ==> adapter buffer memory | 
|  | 1412 | *		DMA_WR	(0x02)	adapter buffer memory ==> system RAM | 
|  | 1413 | *		SMT_BUF (0x80)	SMT buffer | 
|  | 1414 | * | 
|  | 1415 | *	>> NOTE: SMT_BUF and DMA_RD are always set for PCI. << | 
|  | 1416 | * Out | 
|  | 1417 | *	Returns the pyhsical address for the DMA transfer. | 
|  | 1418 | * | 
|  | 1419 | ************************/ | 
|  | 1420 | u_long dma_master(struct s_smc * smc, void *virt, int len, int flag) | 
|  | 1421 | { | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1422 | return smc->os.SharedMemDMA + | 
|  | 1423 | ((char *) virt - (char *)smc->os.SharedMemAddr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1424 | }				// dma_master | 
|  | 1425 |  | 
|  | 1426 |  | 
|  | 1427 | /************************ | 
|  | 1428 | * | 
|  | 1429 | *	dma_complete | 
|  | 1430 | * | 
|  | 1431 | *	The hardware module calls this routine when it has completed a DMA | 
|  | 1432 | *	transfer. If the operating system dependent module has set up the DMA | 
|  | 1433 | *	channel via dma_master() (e.g. Windows NT or AIX) it should clean up | 
|  | 1434 | *	the DMA channel. | 
|  | 1435 | * Args | 
|  | 1436 | *	smc - A pointer to the SMT context struct. | 
|  | 1437 | * | 
|  | 1438 | *	descr - A pointer to a TxD or RxD, respectively. | 
|  | 1439 | * | 
|  | 1440 | *	flag - Indicates the DMA transfer direction / SMT buffer: | 
|  | 1441 | *		DMA_RD	(0x01)	system RAM ==> adapter buffer memory | 
|  | 1442 | *		DMA_WR	(0x02)	adapter buffer memory ==> system RAM | 
|  | 1443 | *		SMT_BUF (0x80)	SMT buffer (managed by HWM) | 
|  | 1444 | * Out | 
|  | 1445 | *	Nothing. | 
|  | 1446 | * | 
|  | 1447 | ************************/ | 
|  | 1448 | void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag) | 
|  | 1449 | { | 
|  | 1450 | /* For TX buffers, there are two cases.  If it is an SMT transmit | 
|  | 1451 | * buffer, there is nothing to do since we use consistent memory | 
|  | 1452 | * for the 'shared' memory area.  The other case is for normal | 
|  | 1453 | * transmit packets given to us by the networking stack, and in | 
|  | 1454 | * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete | 
|  | 1455 | * below. | 
|  | 1456 | * | 
|  | 1457 | * For RX buffers, we have to unmap dynamic PCI DMA mappings here | 
|  | 1458 | * because the hardware module is about to potentially look at | 
|  | 1459 | * the contents of the buffer.  If we did not call the PCI DMA | 
|  | 1460 | * unmap first, the hardware module could read inconsistent data. | 
|  | 1461 | */ | 
|  | 1462 | if (flag & DMA_WR) { | 
|  | 1463 | skfddi_priv *bp = &smc->os; | 
|  | 1464 | volatile struct s_smt_fp_rxd *r = &descr->r; | 
|  | 1465 |  | 
|  | 1466 | /* If SKB is NULL, we used the local buffer. */ | 
|  | 1467 | if (r->rxd_os.skb && r->rxd_os.dma_addr) { | 
|  | 1468 | int MaxFrameSize = bp->MaxFrameSize; | 
|  | 1469 |  | 
|  | 1470 | pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr, | 
|  | 1471 | MaxFrameSize, PCI_DMA_FROMDEVICE); | 
|  | 1472 | r->rxd_os.dma_addr = 0; | 
|  | 1473 | } | 
|  | 1474 | } | 
|  | 1475 | }				// dma_complete | 
|  | 1476 |  | 
|  | 1477 |  | 
|  | 1478 | /************************ | 
|  | 1479 | * | 
|  | 1480 | *	mac_drv_tx_complete | 
|  | 1481 | * | 
|  | 1482 | *	Transmit of a packet is complete. Release the tx staging buffer. | 
|  | 1483 | * | 
|  | 1484 | * Args | 
|  | 1485 | *	smc - A pointer to the SMT context struct. | 
|  | 1486 | * | 
|  | 1487 | *	txd - A pointer to the last TxD which is used by the frame. | 
|  | 1488 | * Out | 
|  | 1489 | *	Returns nothing. | 
|  | 1490 | * | 
|  | 1491 | ************************/ | 
|  | 1492 | void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd) | 
|  | 1493 | { | 
|  | 1494 | struct sk_buff *skb; | 
|  | 1495 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1496 | pr_debug("entering mac_drv_tx_complete\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1497 | // Check if this TxD points to a skb | 
|  | 1498 |  | 
|  | 1499 | if (!(skb = txd->txd_os.skb)) { | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1500 | pr_debug("TXD with no skb assigned.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1501 | return; | 
|  | 1502 | } | 
|  | 1503 | txd->txd_os.skb = NULL; | 
|  | 1504 |  | 
|  | 1505 | // release the DMA mapping | 
|  | 1506 | pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr, | 
|  | 1507 | skb->len, PCI_DMA_TODEVICE); | 
|  | 1508 | txd->txd_os.dma_addr = 0; | 
|  | 1509 |  | 
|  | 1510 | smc->os.MacStat.gen.tx_packets++;	// Count transmitted packets. | 
|  | 1511 | smc->os.MacStat.gen.tx_bytes+=skb->len;	// Count bytes | 
|  | 1512 |  | 
|  | 1513 | // free the skb | 
|  | 1514 | dev_kfree_skb_irq(skb); | 
|  | 1515 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1516 | pr_debug("leaving mac_drv_tx_complete\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1517 | }				// mac_drv_tx_complete | 
|  | 1518 |  | 
|  | 1519 |  | 
|  | 1520 | /************************ | 
|  | 1521 | * | 
|  | 1522 | * dump packets to logfile | 
|  | 1523 | * | 
|  | 1524 | ************************/ | 
|  | 1525 | #ifdef DUMPPACKETS | 
|  | 1526 | void dump_data(unsigned char *Data, int length) | 
|  | 1527 | { | 
|  | 1528 | int i, j; | 
|  | 1529 | unsigned char s[255], sh[10]; | 
|  | 1530 | if (length > 64) { | 
|  | 1531 | length = 64; | 
|  | 1532 | } | 
|  | 1533 | printk(KERN_INFO "---Packet start---\n"); | 
|  | 1534 | for (i = 0, j = 0; i < length / 8; i++, j += 8) | 
|  | 1535 | printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n", | 
|  | 1536 | Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3], | 
|  | 1537 | Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]); | 
|  | 1538 | strcpy(s, ""); | 
|  | 1539 | for (i = 0; i < length % 8; i++) { | 
|  | 1540 | sprintf(sh, "%02x ", Data[j + i]); | 
|  | 1541 | strcat(s, sh); | 
|  | 1542 | } | 
|  | 1543 | printk(KERN_INFO "%s\n", s); | 
|  | 1544 | printk(KERN_INFO "------------------\n"); | 
|  | 1545 | }				// dump_data | 
|  | 1546 | #else | 
|  | 1547 | #define dump_data(data,len) | 
|  | 1548 | #endif				// DUMPPACKETS | 
|  | 1549 |  | 
|  | 1550 | /************************ | 
|  | 1551 | * | 
|  | 1552 | *	mac_drv_rx_complete | 
|  | 1553 | * | 
|  | 1554 | *	The hardware module calls this function if an LLC frame is received | 
|  | 1555 | *	in a receive buffer. Also the SMT, NSA, and directed beacon frames | 
|  | 1556 | *	from the network will be passed to the LLC layer by this function | 
|  | 1557 | *	if passing is enabled. | 
|  | 1558 | * | 
|  | 1559 | *	mac_drv_rx_complete forwards the frame to the LLC layer if it should | 
|  | 1560 | *	be received. It also fills the RxD ring with new receive buffers if | 
|  | 1561 | *	some can be queued. | 
|  | 1562 | * Args | 
|  | 1563 | *	smc - A pointer to the SMT context struct. | 
|  | 1564 | * | 
|  | 1565 | *	rxd - A pointer to the first RxD which is used by the receive frame. | 
|  | 1566 | * | 
|  | 1567 | *	frag_count - Count of RxDs used by the received frame. | 
|  | 1568 | * | 
|  | 1569 | *	len - Frame length. | 
|  | 1570 | * Out | 
|  | 1571 | *	Nothing. | 
|  | 1572 | * | 
|  | 1573 | ************************/ | 
|  | 1574 | void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, | 
|  | 1575 | int frag_count, int len) | 
|  | 1576 | { | 
|  | 1577 | skfddi_priv *bp = &smc->os; | 
|  | 1578 | struct sk_buff *skb; | 
|  | 1579 | unsigned char *virt, *cp; | 
|  | 1580 | unsigned short ri; | 
|  | 1581 | u_int RifLength; | 
|  | 1582 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1583 | pr_debug("entering mac_drv_rx_complete (len=%d)\n", len); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1584 | if (frag_count != 1) {	// This is not allowed to happen. | 
|  | 1585 |  | 
|  | 1586 | printk("fddi: Multi-fragment receive!\n"); | 
|  | 1587 | goto RequeueRxd;	// Re-use the given RXD(s). | 
|  | 1588 |  | 
|  | 1589 | } | 
|  | 1590 | skb = rxd->rxd_os.skb; | 
|  | 1591 | if (!skb) { | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1592 | pr_debug("No skb in rxd\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1593 | smc->os.MacStat.gen.rx_errors++; | 
|  | 1594 | goto RequeueRxd; | 
|  | 1595 | } | 
|  | 1596 | virt = skb->data; | 
|  | 1597 |  | 
|  | 1598 | // The DMA mapping was released in dma_complete above. | 
|  | 1599 |  | 
|  | 1600 | dump_data(skb->data, len); | 
|  | 1601 |  | 
|  | 1602 | /* | 
|  | 1603 | * FDDI Frame format: | 
|  | 1604 | * +-------+-------+-------+------------+--------+------------+ | 
|  | 1605 | * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] | | 
|  | 1606 | * +-------+-------+-------+------------+--------+------------+ | 
|  | 1607 | * | 
|  | 1608 | * FC = Frame Control | 
|  | 1609 | * DA = Destination Address | 
|  | 1610 | * SA = Source Address | 
|  | 1611 | * RIF = Routing Information Field | 
|  | 1612 | * LLC = Logical Link Control | 
|  | 1613 | */ | 
|  | 1614 |  | 
|  | 1615 | // Remove Routing Information Field (RIF), if present. | 
|  | 1616 |  | 
|  | 1617 | if ((virt[1 + 6] & FDDI_RII) == 0) | 
|  | 1618 | RifLength = 0; | 
|  | 1619 | else { | 
|  | 1620 | int n; | 
|  | 1621 | // goos: RIF removal has still to be tested | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1622 | pr_debug("RIF found\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1623 | // Get RIF length from Routing Control (RC) field. | 
|  | 1624 | cp = virt + FDDI_MAC_HDR_LEN;	// Point behind MAC header. | 
|  | 1625 |  | 
| Al Viro | 2f220e3 | 2008-03-16 22:22:24 +0000 | [diff] [blame] | 1626 | ri = ntohs(*((__be16 *) cp)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1627 | RifLength = ri & FDDI_RCF_LEN_MASK; | 
|  | 1628 | if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) { | 
|  | 1629 | printk("fddi: Invalid RIF.\n"); | 
|  | 1630 | goto RequeueRxd;	// Discard the frame. | 
|  | 1631 |  | 
|  | 1632 | } | 
|  | 1633 | virt[1 + 6] &= ~FDDI_RII;	// Clear RII bit. | 
|  | 1634 | // regions overlap | 
|  | 1635 |  | 
|  | 1636 | virt = cp + RifLength; | 
|  | 1637 | for (n = FDDI_MAC_HDR_LEN; n; n--) | 
|  | 1638 | *--virt = *--cp; | 
|  | 1639 | // adjust sbd->data pointer | 
|  | 1640 | skb_pull(skb, RifLength); | 
|  | 1641 | len -= RifLength; | 
|  | 1642 | RifLength = 0; | 
|  | 1643 | } | 
|  | 1644 |  | 
|  | 1645 | // Count statistics. | 
|  | 1646 | smc->os.MacStat.gen.rx_packets++;	// Count indicated receive | 
|  | 1647 | // packets. | 
|  | 1648 | smc->os.MacStat.gen.rx_bytes+=len;	// Count bytes. | 
|  | 1649 |  | 
|  | 1650 | // virt points to header again | 
|  | 1651 | if (virt[1] & 0x01) {	// Check group (multicast) bit. | 
|  | 1652 |  | 
|  | 1653 | smc->os.MacStat.gen.multicast++; | 
|  | 1654 | } | 
|  | 1655 |  | 
|  | 1656 | // deliver frame to system | 
|  | 1657 | rxd->rxd_os.skb = NULL; | 
|  | 1658 | skb_trim(skb, len); | 
|  | 1659 | skb->protocol = fddi_type_trans(skb, bp->dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1660 |  | 
|  | 1661 | netif_rx(skb); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1662 |  | 
|  | 1663 | HWM_RX_CHECK(smc, RX_LOW_WATERMARK); | 
|  | 1664 | return; | 
|  | 1665 |  | 
|  | 1666 | RequeueRxd: | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1667 | pr_debug("Rx: re-queue RXD.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1668 | mac_drv_requeue_rxd(smc, rxd, frag_count); | 
|  | 1669 | smc->os.MacStat.gen.rx_errors++;	// Count receive packets | 
|  | 1670 | // not indicated. | 
|  | 1671 |  | 
|  | 1672 | }				// mac_drv_rx_complete | 
|  | 1673 |  | 
|  | 1674 |  | 
|  | 1675 | /************************ | 
|  | 1676 | * | 
|  | 1677 | *	mac_drv_requeue_rxd | 
|  | 1678 | * | 
|  | 1679 | *	The hardware module calls this function to request the OS-specific | 
|  | 1680 | *	module to queue the receive buffer(s) represented by the pointer | 
|  | 1681 | *	to the RxD and the frag_count into the receive queue again. This | 
|  | 1682 | *	buffer was filled with an invalid frame or an SMT frame. | 
|  | 1683 | * Args | 
|  | 1684 | *	smc - A pointer to the SMT context struct. | 
|  | 1685 | * | 
|  | 1686 | *	rxd - A pointer to the first RxD which is used by the receive frame. | 
|  | 1687 | * | 
|  | 1688 | *	frag_count - Count of RxDs used by the received frame. | 
|  | 1689 | * Out | 
|  | 1690 | *	Nothing. | 
|  | 1691 | * | 
|  | 1692 | ************************/ | 
|  | 1693 | void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, | 
|  | 1694 | int frag_count) | 
|  | 1695 | { | 
|  | 1696 | volatile struct s_smt_fp_rxd *next_rxd; | 
|  | 1697 | volatile struct s_smt_fp_rxd *src_rxd; | 
|  | 1698 | struct sk_buff *skb; | 
|  | 1699 | int MaxFrameSize; | 
|  | 1700 | unsigned char *v_addr; | 
|  | 1701 | dma_addr_t b_addr; | 
|  | 1702 |  | 
|  | 1703 | if (frag_count != 1)	// This is not allowed to happen. | 
|  | 1704 |  | 
|  | 1705 | printk("fddi: Multi-fragment requeue!\n"); | 
|  | 1706 |  | 
|  | 1707 | MaxFrameSize = smc->os.MaxFrameSize; | 
|  | 1708 | src_rxd = rxd; | 
|  | 1709 | for (; frag_count > 0; frag_count--) { | 
|  | 1710 | next_rxd = src_rxd->rxd_next; | 
|  | 1711 | rxd = HWM_GET_CURR_RXD(smc); | 
|  | 1712 |  | 
|  | 1713 | skb = src_rxd->rxd_os.skb; | 
|  | 1714 | if (skb == NULL) {	// this should not happen | 
|  | 1715 |  | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1716 | pr_debug("Requeue with no skb in rxd!\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1717 | skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); | 
|  | 1718 | if (skb) { | 
|  | 1719 | // we got a skb | 
|  | 1720 | rxd->rxd_os.skb = skb; | 
|  | 1721 | skb_reserve(skb, 3); | 
|  | 1722 | skb_put(skb, MaxFrameSize); | 
|  | 1723 | v_addr = skb->data; | 
|  | 1724 | b_addr = pci_map_single(&smc->os.pdev, | 
|  | 1725 | v_addr, | 
|  | 1726 | MaxFrameSize, | 
|  | 1727 | PCI_DMA_FROMDEVICE); | 
|  | 1728 | rxd->rxd_os.dma_addr = b_addr; | 
|  | 1729 | } else { | 
|  | 1730 | // no skb available, use local buffer | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1731 | pr_debug("Queueing invalid buffer!\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1732 | rxd->rxd_os.skb = NULL; | 
|  | 1733 | v_addr = smc->os.LocalRxBuffer; | 
|  | 1734 | b_addr = smc->os.LocalRxBufferDMA; | 
|  | 1735 | } | 
|  | 1736 | } else { | 
|  | 1737 | // we use skb from old rxd | 
|  | 1738 | rxd->rxd_os.skb = skb; | 
|  | 1739 | v_addr = skb->data; | 
|  | 1740 | b_addr = pci_map_single(&smc->os.pdev, | 
|  | 1741 | v_addr, | 
|  | 1742 | MaxFrameSize, | 
|  | 1743 | PCI_DMA_FROMDEVICE); | 
|  | 1744 | rxd->rxd_os.dma_addr = b_addr; | 
|  | 1745 | } | 
|  | 1746 | hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, | 
|  | 1747 | FIRST_FRAG | LAST_FRAG); | 
|  | 1748 |  | 
|  | 1749 | src_rxd = next_rxd; | 
|  | 1750 | } | 
|  | 1751 | }				// mac_drv_requeue_rxd | 
|  | 1752 |  | 
|  | 1753 |  | 
|  | 1754 | /************************ | 
|  | 1755 | * | 
|  | 1756 | *	mac_drv_fill_rxd | 
|  | 1757 | * | 
|  | 1758 | *	The hardware module calls this function at initialization time | 
|  | 1759 | *	to fill the RxD ring with receive buffers. It is also called by | 
|  | 1760 | *	mac_drv_rx_complete if rx_free is large enough to queue some new | 
|  | 1761 | *	receive buffers into the RxD ring. mac_drv_fill_rxd queues new | 
|  | 1762 | *	receive buffers as long as enough RxDs and receive buffers are | 
|  | 1763 | *	available. | 
|  | 1764 | * Args | 
|  | 1765 | *	smc - A pointer to the SMT context struct. | 
|  | 1766 | * Out | 
|  | 1767 | *	Nothing. | 
|  | 1768 | * | 
|  | 1769 | ************************/ | 
|  | 1770 | void mac_drv_fill_rxd(struct s_smc *smc) | 
|  | 1771 | { | 
|  | 1772 | int MaxFrameSize; | 
|  | 1773 | unsigned char *v_addr; | 
|  | 1774 | unsigned long b_addr; | 
|  | 1775 | struct sk_buff *skb; | 
|  | 1776 | volatile struct s_smt_fp_rxd *rxd; | 
|  | 1777 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1778 | pr_debug("entering mac_drv_fill_rxd\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1779 |  | 
|  | 1780 | // Walk through the list of free receive buffers, passing receive | 
|  | 1781 | // buffers to the HWM as long as RXDs are available. | 
|  | 1782 |  | 
|  | 1783 | MaxFrameSize = smc->os.MaxFrameSize; | 
|  | 1784 | // Check if there is any RXD left. | 
|  | 1785 | while (HWM_GET_RX_FREE(smc) > 0) { | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1786 | pr_debug(".\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1787 |  | 
|  | 1788 | rxd = HWM_GET_CURR_RXD(smc); | 
|  | 1789 | skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); | 
|  | 1790 | if (skb) { | 
|  | 1791 | // we got a skb | 
|  | 1792 | skb_reserve(skb, 3); | 
|  | 1793 | skb_put(skb, MaxFrameSize); | 
|  | 1794 | v_addr = skb->data; | 
|  | 1795 | b_addr = pci_map_single(&smc->os.pdev, | 
|  | 1796 | v_addr, | 
|  | 1797 | MaxFrameSize, | 
|  | 1798 | PCI_DMA_FROMDEVICE); | 
|  | 1799 | rxd->rxd_os.dma_addr = b_addr; | 
|  | 1800 | } else { | 
|  | 1801 | // no skb available, use local buffer | 
|  | 1802 | // System has run out of buffer memory, but we want to | 
|  | 1803 | // keep the receiver running in hope of better times. | 
|  | 1804 | // Multiple descriptors may point to this local buffer, | 
|  | 1805 | // so data in it must be considered invalid. | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1806 | pr_debug("Queueing invalid buffer!\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1807 | v_addr = smc->os.LocalRxBuffer; | 
|  | 1808 | b_addr = smc->os.LocalRxBufferDMA; | 
|  | 1809 | } | 
|  | 1810 |  | 
|  | 1811 | rxd->rxd_os.skb = skb; | 
|  | 1812 |  | 
|  | 1813 | // Pass receive buffer to HWM. | 
|  | 1814 | hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, | 
|  | 1815 | FIRST_FRAG | LAST_FRAG); | 
|  | 1816 | } | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 1817 | pr_debug("leaving mac_drv_fill_rxd\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1818 | }				// mac_drv_fill_rxd | 
|  | 1819 |  | 
|  | 1820 |  | 
|  | 1821 | /************************ | 
|  | 1822 | * | 
|  | 1823 | *	mac_drv_clear_rxd | 
|  | 1824 | * | 
|  | 1825 | *	The hardware module calls this function to release unused | 
|  | 1826 | *	receive buffers. | 
|  | 1827 | * Args | 
|  | 1828 | *	smc - A pointer to the SMT context struct. | 
|  | 1829 | * | 
|  | 1830 | *	rxd - A pointer to the first RxD which is used by the receive buffer. | 
|  | 1831 | * | 
|  | 1832 | *	frag_count - Count of RxDs used by the receive buffer. | 
|  | 1833 | * Out | 
|  | 1834 | *	Nothing. | 
|  | 1835 | * | 
|  | 1836 | ************************/ | 
|  | 1837 | void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, | 
|  | 1838 | int frag_count) | 
|  | 1839 | { | 
|  | 1840 |  | 
|  | 1841 | struct sk_buff *skb; | 
|  | 1842 |  | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1843 | pr_debug("entering mac_drv_clear_rxd\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1844 |  | 
|  | 1845 | if (frag_count != 1)	// This is not allowed to happen. | 
|  | 1846 |  | 
|  | 1847 | printk("fddi: Multi-fragment clear!\n"); | 
|  | 1848 |  | 
|  | 1849 | for (; frag_count > 0; frag_count--) { | 
|  | 1850 | skb = rxd->rxd_os.skb; | 
|  | 1851 | if (skb != NULL) { | 
|  | 1852 | skfddi_priv *bp = &smc->os; | 
|  | 1853 | int MaxFrameSize = bp->MaxFrameSize; | 
|  | 1854 |  | 
|  | 1855 | pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr, | 
|  | 1856 | MaxFrameSize, PCI_DMA_FROMDEVICE); | 
|  | 1857 |  | 
|  | 1858 | dev_kfree_skb(skb); | 
|  | 1859 | rxd->rxd_os.skb = NULL; | 
|  | 1860 | } | 
|  | 1861 | rxd = rxd->rxd_next;	// Next RXD. | 
|  | 1862 |  | 
|  | 1863 | } | 
|  | 1864 | }				// mac_drv_clear_rxd | 
|  | 1865 |  | 
|  | 1866 |  | 
|  | 1867 | /************************ | 
|  | 1868 | * | 
|  | 1869 | *	mac_drv_rx_init | 
|  | 1870 | * | 
|  | 1871 | *	The hardware module calls this routine when an SMT or NSA frame of the | 
|  | 1872 | *	local SMT should be delivered to the LLC layer. | 
|  | 1873 | * | 
|  | 1874 | *	It is necessary to have this function, because there is no other way to | 
|  | 1875 | *	copy the contents of SMT MBufs into receive buffers. | 
|  | 1876 | * | 
|  | 1877 | *	mac_drv_rx_init allocates the required target memory for this frame, | 
|  | 1878 | *	and receives the frame fragment by fragment by calling mac_drv_rx_frag. | 
|  | 1879 | * Args | 
|  | 1880 | *	smc - A pointer to the SMT context struct. | 
|  | 1881 | * | 
|  | 1882 | *	len - The length (in bytes) of the received frame (FC, DA, SA, Data). | 
|  | 1883 | * | 
|  | 1884 | *	fc - The Frame Control field of the received frame. | 
|  | 1885 | * | 
|  | 1886 | *	look_ahead - A pointer to the lookahead data buffer (may be NULL). | 
|  | 1887 | * | 
|  | 1888 | *	la_len - The length of the lookahead data stored in the lookahead | 
|  | 1889 | *	buffer (may be zero). | 
|  | 1890 | * Out | 
|  | 1891 | *	Always returns zero (0). | 
|  | 1892 | * | 
|  | 1893 | ************************/ | 
|  | 1894 | int mac_drv_rx_init(struct s_smc *smc, int len, int fc, | 
|  | 1895 | char *look_ahead, int la_len) | 
|  | 1896 | { | 
|  | 1897 | struct sk_buff *skb; | 
|  | 1898 |  | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1899 | pr_debug("entering mac_drv_rx_init(len=%d)\n", len); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1900 |  | 
|  | 1901 | // "Received" a SMT or NSA frame of the local SMT. | 
|  | 1902 |  | 
|  | 1903 | if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) { | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1904 | pr_debug("fddi: Discard invalid local SMT frame\n"); | 
|  | 1905 | pr_debug("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1906 | len, la_len, (unsigned long) look_ahead); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1907 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1908 | } | 
|  | 1909 | skb = alloc_skb(len + 3, GFP_ATOMIC); | 
|  | 1910 | if (!skb) { | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1911 | pr_debug("fddi: Local SMT: skb memory exhausted.\n"); | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1912 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1913 | } | 
|  | 1914 | skb_reserve(skb, 3); | 
|  | 1915 | skb_put(skb, len); | 
| Arnaldo Carvalho de Melo | 27d7ff4 | 2007-03-31 11:55:19 -0300 | [diff] [blame] | 1916 | skb_copy_to_linear_data(skb, look_ahead, len); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1917 |  | 
|  | 1918 | // deliver frame to system | 
|  | 1919 | skb->protocol = fddi_type_trans(skb, smc->os.dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1920 | netif_rx(skb); | 
|  | 1921 |  | 
| Eric Dumazet | 807540b | 2010-09-23 05:40:09 +0000 | [diff] [blame] | 1922 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1923 | }				// mac_drv_rx_init | 
|  | 1924 |  | 
|  | 1925 |  | 
|  | 1926 | /************************ | 
|  | 1927 | * | 
|  | 1928 | *	smt_timer_poll | 
|  | 1929 | * | 
|  | 1930 | *	This routine is called periodically by the SMT module to clean up the | 
|  | 1931 | *	driver. | 
|  | 1932 | * | 
|  | 1933 | *	Return any queued frames back to the upper protocol layers if the ring | 
|  | 1934 | *	is down. | 
|  | 1935 | * Args | 
|  | 1936 | *	smc - A pointer to the SMT context struct. | 
|  | 1937 | * Out | 
|  | 1938 | *	Nothing. | 
|  | 1939 | * | 
|  | 1940 | ************************/ | 
|  | 1941 | void smt_timer_poll(struct s_smc *smc) | 
|  | 1942 | { | 
|  | 1943 | }				// smt_timer_poll | 
|  | 1944 |  | 
|  | 1945 |  | 
|  | 1946 | /************************ | 
|  | 1947 | * | 
|  | 1948 | *	ring_status_indication | 
|  | 1949 | * | 
|  | 1950 | *	This function indicates a change of the ring state. | 
|  | 1951 | * Args | 
|  | 1952 | *	smc - A pointer to the SMT context struct. | 
|  | 1953 | * | 
|  | 1954 | *	status - The current ring status. | 
|  | 1955 | * Out | 
|  | 1956 | *	Nothing. | 
|  | 1957 | * | 
|  | 1958 | ************************/ | 
|  | 1959 | void ring_status_indication(struct s_smc *smc, u_long status) | 
|  | 1960 | { | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1961 | pr_debug("ring_status_indication( "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1962 | if (status & RS_RES15) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1963 | pr_debug("RS_RES15 "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1964 | if (status & RS_HARDERROR) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1965 | pr_debug("RS_HARDERROR "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1966 | if (status & RS_SOFTERROR) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1967 | pr_debug("RS_SOFTERROR "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1968 | if (status & RS_BEACON) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1969 | pr_debug("RS_BEACON "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1970 | if (status & RS_PATHTEST) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1971 | pr_debug("RS_PATHTEST "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1972 | if (status & RS_SELFTEST) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1973 | pr_debug("RS_SELFTEST "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1974 | if (status & RS_RES9) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1975 | pr_debug("RS_RES9 "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1976 | if (status & RS_DISCONNECT) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1977 | pr_debug("RS_DISCONNECT "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1978 | if (status & RS_RES7) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1979 | pr_debug("RS_RES7 "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1980 | if (status & RS_DUPADDR) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1981 | pr_debug("RS_DUPADDR "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1982 | if (status & RS_NORINGOP) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1983 | pr_debug("RS_NORINGOP "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1984 | if (status & RS_VERSION) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1985 | pr_debug("RS_VERSION "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1986 | if (status & RS_STUCKBYPASSS) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1987 | pr_debug("RS_STUCKBYPASSS "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1988 | if (status & RS_EVENT) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1989 | pr_debug("RS_EVENT "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1990 | if (status & RS_RINGOPCHANGE) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1991 | pr_debug("RS_RINGOPCHANGE "); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1992 | if (status & RS_RES0) | 
| Alexander Beregalov | ebc06ee | 2009-05-15 10:22:42 +0000 | [diff] [blame] | 1993 | pr_debug("RS_RES0 "); | 
|  | 1994 | pr_debug("]\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1995 | }				// ring_status_indication | 
|  | 1996 |  | 
|  | 1997 |  | 
|  | 1998 | /************************ | 
|  | 1999 | * | 
|  | 2000 | *	smt_get_time | 
|  | 2001 | * | 
|  | 2002 | *	Gets the current time from the system. | 
|  | 2003 | * Args | 
|  | 2004 | *	None. | 
|  | 2005 | * Out | 
|  | 2006 | *	The current time in TICKS_PER_SECOND. | 
|  | 2007 | * | 
|  | 2008 | *	TICKS_PER_SECOND has the unit 'count of timer ticks per second'. It is | 
|  | 2009 | *	defined in "targetos.h". The definition of TICKS_PER_SECOND must comply | 
|  | 2010 | *	to the time returned by smt_get_time(). | 
|  | 2011 | * | 
|  | 2012 | ************************/ | 
|  | 2013 | unsigned long smt_get_time(void) | 
|  | 2014 | { | 
|  | 2015 | return jiffies; | 
|  | 2016 | }				// smt_get_time | 
|  | 2017 |  | 
|  | 2018 |  | 
|  | 2019 | /************************ | 
|  | 2020 | * | 
|  | 2021 | *	smt_stat_counter | 
|  | 2022 | * | 
|  | 2023 | *	Status counter update (ring_op, fifo full). | 
|  | 2024 | * Args | 
|  | 2025 | *	smc - A pointer to the SMT context struct. | 
|  | 2026 | * | 
|  | 2027 | *	stat -	= 0: A ring operational change occurred. | 
|  | 2028 | *		= 1: The FORMAC FIFO buffer is full / FIFO overflow. | 
|  | 2029 | * Out | 
|  | 2030 | *	Nothing. | 
|  | 2031 | * | 
|  | 2032 | ************************/ | 
|  | 2033 | void smt_stat_counter(struct s_smc *smc, int stat) | 
|  | 2034 | { | 
|  | 2035 | //      BOOLEAN RingIsUp ; | 
|  | 2036 |  | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2037 | pr_debug("smt_stat_counter\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2038 | switch (stat) { | 
|  | 2039 | case 0: | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2040 | pr_debug("Ring operational change.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2041 | break; | 
|  | 2042 | case 1: | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2043 | pr_debug("Receive fifo overflow.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2044 | smc->os.MacStat.gen.rx_errors++; | 
|  | 2045 | break; | 
|  | 2046 | default: | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2047 | pr_debug("Unknown status (%d).\n", stat); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2048 | break; | 
|  | 2049 | } | 
|  | 2050 | }				// smt_stat_counter | 
|  | 2051 |  | 
|  | 2052 |  | 
|  | 2053 | /************************ | 
|  | 2054 | * | 
|  | 2055 | *	cfm_state_change | 
|  | 2056 | * | 
|  | 2057 | *	Sets CFM state in custom statistics. | 
|  | 2058 | * Args | 
|  | 2059 | *	smc - A pointer to the SMT context struct. | 
|  | 2060 | * | 
|  | 2061 | *	c_state - Possible values are: | 
|  | 2062 | * | 
|  | 2063 | *		EC0_OUT, EC1_IN, EC2_TRACE, EC3_LEAVE, EC4_PATH_TEST, | 
|  | 2064 | *		EC5_INSERT, EC6_CHECK, EC7_DEINSERT | 
|  | 2065 | * Out | 
|  | 2066 | *	Nothing. | 
|  | 2067 | * | 
|  | 2068 | ************************/ | 
|  | 2069 | void cfm_state_change(struct s_smc *smc, int c_state) | 
|  | 2070 | { | 
|  | 2071 | #ifdef DRIVERDEBUG | 
|  | 2072 | char *s; | 
|  | 2073 |  | 
|  | 2074 | switch (c_state) { | 
|  | 2075 | case SC0_ISOLATED: | 
|  | 2076 | s = "SC0_ISOLATED"; | 
|  | 2077 | break; | 
|  | 2078 | case SC1_WRAP_A: | 
|  | 2079 | s = "SC1_WRAP_A"; | 
|  | 2080 | break; | 
|  | 2081 | case SC2_WRAP_B: | 
|  | 2082 | s = "SC2_WRAP_B"; | 
|  | 2083 | break; | 
|  | 2084 | case SC4_THRU_A: | 
|  | 2085 | s = "SC4_THRU_A"; | 
|  | 2086 | break; | 
|  | 2087 | case SC5_THRU_B: | 
|  | 2088 | s = "SC5_THRU_B"; | 
|  | 2089 | break; | 
|  | 2090 | case SC7_WRAP_S: | 
|  | 2091 | s = "SC7_WRAP_S"; | 
|  | 2092 | break; | 
|  | 2093 | case SC9_C_WRAP_A: | 
|  | 2094 | s = "SC9_C_WRAP_A"; | 
|  | 2095 | break; | 
|  | 2096 | case SC10_C_WRAP_B: | 
|  | 2097 | s = "SC10_C_WRAP_B"; | 
|  | 2098 | break; | 
|  | 2099 | case SC11_C_WRAP_S: | 
|  | 2100 | s = "SC11_C_WRAP_S"; | 
|  | 2101 | break; | 
|  | 2102 | default: | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2103 | pr_debug("cfm_state_change: unknown %d\n", c_state); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2104 | return; | 
|  | 2105 | } | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2106 | pr_debug("cfm_state_change: %s\n", s); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2107 | #endif				// DRIVERDEBUG | 
|  | 2108 | }				// cfm_state_change | 
|  | 2109 |  | 
|  | 2110 |  | 
|  | 2111 | /************************ | 
|  | 2112 | * | 
|  | 2113 | *	ecm_state_change | 
|  | 2114 | * | 
|  | 2115 | *	Sets ECM state in custom statistics. | 
|  | 2116 | * Args | 
|  | 2117 | *	smc - A pointer to the SMT context struct. | 
|  | 2118 | * | 
|  | 2119 | *	e_state - Possible values are: | 
|  | 2120 | * | 
|  | 2121 | *		SC0_ISOLATED, SC1_WRAP_A (5), SC2_WRAP_B (6), SC4_THRU_A (12), | 
|  | 2122 | *		SC5_THRU_B (7), SC7_WRAP_S (8) | 
|  | 2123 | * Out | 
|  | 2124 | *	Nothing. | 
|  | 2125 | * | 
|  | 2126 | ************************/ | 
|  | 2127 | void ecm_state_change(struct s_smc *smc, int e_state) | 
|  | 2128 | { | 
|  | 2129 | #ifdef DRIVERDEBUG | 
|  | 2130 | char *s; | 
|  | 2131 |  | 
|  | 2132 | switch (e_state) { | 
|  | 2133 | case EC0_OUT: | 
|  | 2134 | s = "EC0_OUT"; | 
|  | 2135 | break; | 
|  | 2136 | case EC1_IN: | 
|  | 2137 | s = "EC1_IN"; | 
|  | 2138 | break; | 
|  | 2139 | case EC2_TRACE: | 
|  | 2140 | s = "EC2_TRACE"; | 
|  | 2141 | break; | 
|  | 2142 | case EC3_LEAVE: | 
|  | 2143 | s = "EC3_LEAVE"; | 
|  | 2144 | break; | 
|  | 2145 | case EC4_PATH_TEST: | 
|  | 2146 | s = "EC4_PATH_TEST"; | 
|  | 2147 | break; | 
|  | 2148 | case EC5_INSERT: | 
|  | 2149 | s = "EC5_INSERT"; | 
|  | 2150 | break; | 
|  | 2151 | case EC6_CHECK: | 
|  | 2152 | s = "EC6_CHECK"; | 
|  | 2153 | break; | 
|  | 2154 | case EC7_DEINSERT: | 
|  | 2155 | s = "EC7_DEINSERT"; | 
|  | 2156 | break; | 
|  | 2157 | default: | 
|  | 2158 | s = "unknown"; | 
|  | 2159 | break; | 
|  | 2160 | } | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2161 | pr_debug("ecm_state_change: %s\n", s); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2162 | #endif				//DRIVERDEBUG | 
|  | 2163 | }				// ecm_state_change | 
|  | 2164 |  | 
|  | 2165 |  | 
|  | 2166 | /************************ | 
|  | 2167 | * | 
|  | 2168 | *	rmt_state_change | 
|  | 2169 | * | 
|  | 2170 | *	Sets RMT state in custom statistics. | 
|  | 2171 | * Args | 
|  | 2172 | *	smc - A pointer to the SMT context struct. | 
|  | 2173 | * | 
|  | 2174 | *	r_state - Possible values are: | 
|  | 2175 | * | 
|  | 2176 | *		RM0_ISOLATED, RM1_NON_OP, RM2_RING_OP, RM3_DETECT, | 
|  | 2177 | *		RM4_NON_OP_DUP, RM5_RING_OP_DUP, RM6_DIRECTED, RM7_TRACE | 
|  | 2178 | * Out | 
|  | 2179 | *	Nothing. | 
|  | 2180 | * | 
|  | 2181 | ************************/ | 
|  | 2182 | void rmt_state_change(struct s_smc *smc, int r_state) | 
|  | 2183 | { | 
|  | 2184 | #ifdef DRIVERDEBUG | 
|  | 2185 | char *s; | 
|  | 2186 |  | 
|  | 2187 | switch (r_state) { | 
|  | 2188 | case RM0_ISOLATED: | 
|  | 2189 | s = "RM0_ISOLATED"; | 
|  | 2190 | break; | 
|  | 2191 | case RM1_NON_OP: | 
|  | 2192 | s = "RM1_NON_OP - not operational"; | 
|  | 2193 | break; | 
|  | 2194 | case RM2_RING_OP: | 
|  | 2195 | s = "RM2_RING_OP - ring operational"; | 
|  | 2196 | break; | 
|  | 2197 | case RM3_DETECT: | 
|  | 2198 | s = "RM3_DETECT - detect dupl addresses"; | 
|  | 2199 | break; | 
|  | 2200 | case RM4_NON_OP_DUP: | 
|  | 2201 | s = "RM4_NON_OP_DUP - dupl. addr detected"; | 
|  | 2202 | break; | 
|  | 2203 | case RM5_RING_OP_DUP: | 
|  | 2204 | s = "RM5_RING_OP_DUP - ring oper. with dupl. addr"; | 
|  | 2205 | break; | 
|  | 2206 | case RM6_DIRECTED: | 
|  | 2207 | s = "RM6_DIRECTED - sending directed beacons"; | 
|  | 2208 | break; | 
|  | 2209 | case RM7_TRACE: | 
|  | 2210 | s = "RM7_TRACE - trace initiated"; | 
|  | 2211 | break; | 
|  | 2212 | default: | 
|  | 2213 | s = "unknown"; | 
|  | 2214 | break; | 
|  | 2215 | } | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2216 | pr_debug("[rmt_state_change: %s]\n", s); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2217 | #endif				// DRIVERDEBUG | 
|  | 2218 | }				// rmt_state_change | 
|  | 2219 |  | 
|  | 2220 |  | 
|  | 2221 | /************************ | 
|  | 2222 | * | 
|  | 2223 | *	drv_reset_indication | 
|  | 2224 | * | 
|  | 2225 | *	This function is called by the SMT when it has detected a severe | 
|  | 2226 | *	hardware problem. The driver should perform a reset on the adapter | 
|  | 2227 | *	as soon as possible, but not from within this function. | 
|  | 2228 | * Args | 
|  | 2229 | *	smc - A pointer to the SMT context struct. | 
|  | 2230 | * Out | 
|  | 2231 | *	Nothing. | 
|  | 2232 | * | 
|  | 2233 | ************************/ | 
|  | 2234 | void drv_reset_indication(struct s_smc *smc) | 
|  | 2235 | { | 
| Joe Perches | d81e27c | 2010-09-11 19:10:56 +0000 | [diff] [blame] | 2236 | pr_debug("entering drv_reset_indication\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2237 |  | 
|  | 2238 | smc->os.ResetRequested = TRUE;	// Set flag. | 
|  | 2239 |  | 
|  | 2240 | }				// drv_reset_indication | 
|  | 2241 |  | 
|  | 2242 | static struct pci_driver skfddi_pci_driver = { | 
|  | 2243 | .name		= "skfddi", | 
|  | 2244 | .id_table	= skfddi_pci_tbl, | 
|  | 2245 | .probe		= skfp_init_one, | 
|  | 2246 | .remove		= __devexit_p(skfp_remove_one), | 
|  | 2247 | }; | 
|  | 2248 |  | 
|  | 2249 | static int __init skfd_init(void) | 
|  | 2250 | { | 
| Jeff Garzik | 2991762 | 2006-08-19 17:48:59 -0400 | [diff] [blame] | 2251 | return pci_register_driver(&skfddi_pci_driver); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2252 | } | 
|  | 2253 |  | 
|  | 2254 | static void __exit skfd_exit(void) | 
|  | 2255 | { | 
|  | 2256 | pci_unregister_driver(&skfddi_pci_driver); | 
|  | 2257 | } | 
|  | 2258 |  | 
|  | 2259 | module_init(skfd_init); | 
|  | 2260 | module_exit(skfd_exit); |