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