11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * File Name:
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   skfddi.c
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright Information:
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Copyright SysKonnect 1998,1999.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The information in this file is provided "AS IS" without warranty.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Abstract:
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   A Linux device driver supporting the SysKonnect FDDI PCI controller
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   familie.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Maintainers:
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   CG    Christoph Goos (cgoos@syskonnect.de)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Contributors:
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   DM    David S. Miller
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Address all question to:
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   linux@syskonnect.de
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The technical manual for the adapters is available from SysKonnect's
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * web pages: www.syskonnect.com
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Goto "Support" and search Knowledge Base for "manual".
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver Architecture:
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The driver architecture is based on the DEC FDDI driver by
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Lawrence V. Stefani and several ethernet drivers.
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   I also used an existing Windows NT miniport driver.
36eef35c2d41ddcc653c20d26b977acaa45c811e1fStefan Weil *   All hardware dependent functions are handled by the SysKonnect
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Hardware Module.
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The only headerfiles that are directly related to this source
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The others belong to the SysKonnect FDDI Hardware Module and
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   should better not be changed.
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modification History:
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              Date            Name    Description
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              02-Mar-98       CG	Created.
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		10-Mar-99	CG	Support for 2.2.x added.
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		25-Mar-99	CG	Corrected IRQ routing for SMP (APIC)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		26-Oct-99	CG	Fixed compilation error on 2.2.13
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		12-Nov-99	CG	Source code release
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		22-Nov-99	CG	Included in kernel source.
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		07-May-00	DM	64 bit fixes, new dma interface
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		31-Jul-03	DB	Audit copy_*_user in skfp_ioctl
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *					  Daniele Bellucci <bellucda@tiscali.it>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		03-Dec-03	SH	Convert to PCI device model
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Compilation options (-Dxxx):
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              DRIVERDEBUG     print lots of messages to log file
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              DUMPPACKETS     print received/transmitted packets to logfile
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Tested cpu architectures:
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	- i386
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	- sparc64
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Version information string - should be updated prior to */
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* each new release!!! */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VERSION		"2.07"
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
70f71e130966ba429dbd24be08ddbcdf263df9a5adArjan van de Venstatic const char * const boot_msg =
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"  SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)";
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Include files */
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
76d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/capability.h>
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fddidevice.h>
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h>
875a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/byteorder.h>
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include	"h/types.h"
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ADDR			// undo Linux definition
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include	"h/skfbi.h"
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include	"h/fddi.h"
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include	"h/smc.h"
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include	"h/smtstate.h"
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Define module-wide (static) routines
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_driver_init(struct net_device *dev);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_open(struct net_device *dev);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_close(struct net_device *dev);
1057d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t skfp_interrupt(int irq, void *dev_id);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void skfp_ctl_set_multicast_list(struct net_device *dev);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_ctl_set_mac_address(struct net_device *dev, void *addr);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
11161357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
11261357325f377889a1daffa14962d705dc814dd0eStephen Hemminger				       struct net_device *dev);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void send_queued_packets(struct s_smc *smc);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ResetAdapter(struct s_smc *smc);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Functions needed by the hardware module
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid *mac_drv_get_space(struct s_smc *smc, u_int size);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid *mac_drv_get_desc_mem(struct s_smc *smc, u_int size);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long dma_master(struct s_smc *smc, void *virt, int len, int flag);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  int flag);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid llc_restart_tx(struct s_smc *smc);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int frag_count, int len);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int frag_count);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_fill_rxd(struct s_smc *smc);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       int frag_count);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    int la_len);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dump_data(unsigned char *Data, int length);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// External functions from the hardware module
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern u_int mac_drv_check_space(void);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int mac_drv_init(struct s_smc *smc);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hwm_tx_frag(struct s_smc *smc, char far * virt, u_long phys,
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int len, int frame_status);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count,
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       int frame_len, int frame_status);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void fddi_isr(struct s_smc *smc);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int len, int frame_status);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void mac_drv_rx_mode(struct s_smc *smc, int mode);
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void mac_drv_clear_rx_queue(struct s_smc *smc);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void enable_tx_irq(struct s_smc *smc, u_short queue);
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
152a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = {
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ }			/* Terminating entry */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, skfddi_pci_tbl);
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// Define module-wide (static) variables
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int num_boards;	/* total number of adapters configured */
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
164145186a39570244aead77dc2efc559e5cac90548Stephen Hemmingerstatic const struct net_device_ops skfp_netdev_ops = {
165145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_open		= skfp_open,
166145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_stop		= skfp_close,
167145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_start_xmit		= skfp_send_pkt,
168145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_get_stats		= skfp_ctl_get_stats,
169145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_change_mtu		= fddi_change_mtu,
170afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= skfp_ctl_set_multicast_list,
171145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_set_mac_address	= skfp_ctl_set_mac_address,
172145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	.ndo_do_ioctl		= skfp_ioctl,
173145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger};
174145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =================
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_init_one =
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =================
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Probes for supported FDDI PCI controllers
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Condition code
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   pdev - pointer to PCI device information
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This is now called by PCI driver registration process
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   for each board found.
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes:
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   0           - This device (fddi0, fddi1, etc) configured successfully
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   -ENODEV - No devices present, or no SysKonnect FDDI PCI device
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                         present for this device name
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Side Effects:
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   initialized and the board resources are read and stored in
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   the device structure.
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_init_one(struct pci_dev *pdev,
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				const struct pci_device_id *ent)
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc;	/* board pointer */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *mem;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering skfp_init_one\n");
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (num_boards == 0)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s\n", boot_msg);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = pci_enable_device(pdev);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = pci_request_regions(pdev, "skfddi");
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out1;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_master(pdev);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MEM_MAPPED_IO
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "skfp: region is not an MMIO resource\n");
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out2;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mem = ioremap(pci_resource_start(pdev, 0), 0x4000);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) {
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "skfp: region is not PIO resource\n");
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out2;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mem = ioport_map(pci_resource_start(pdev, 1), FP_IO_LEN);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!mem) {
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "skfp:  Unable to map register, "
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"FDDI adapter will be disabled.\n");
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out2;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev = alloc_fddidev(sizeof(struct s_smc));
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev) {
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "skfp: Unable to allocate fddi device, "
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"FDDI adapter will be disabled.\n");
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out3;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->irq = pdev->irq;
260145186a39570244aead77dc2efc559e5cac90548Stephen Hemminger	dev->netdev_ops = &skfp_netdev_ops;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SET_NETDEV_DEV(dev, &pdev->dev);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize board structure with bus-specific info */
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc = netdev_priv(dev);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.dev = dev;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.bus_type = SK_BUS_TYPE_PCI;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.pdev = *pdev;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.MaxFrameSize = MAX_FRAME_SIZE;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.dev = dev;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->hw.slot = -1;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->hw.iop = mem;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.ResetRequested = FALSE;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_head_init(&smc->os.SendSkbQueue);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->base_addr = (unsigned long)mem;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = skfp_driver_init(dev);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out4;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = register_netdev(dev);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out5;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	++num_boards;
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, dev);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((pdev->subsystem_device & 0xff00) == 0x5500 ||
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (pdev->subsystem_device & 0xff00) == 0x5800)
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s: SysKonnect FDDI PCI adapter"
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       " found (SK-%04X)\n", dev->name,
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       pdev->subsystem_device);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s: FDDI PCI adapter found\n", dev->name);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out5:
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smc->os.SharedMemAddr)
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(pdev, smc->os.SharedMemSize,
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    smc->os.SharedMemAddr,
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    smc->os.SharedMemDMA);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_consistent(pdev, MAX_FRAME_SIZE,
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out4:
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_netdev(dev);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out3:
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MEM_MAPPED_IO
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(mem);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ioport_unmap(mem);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out2:
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(pdev);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out1:
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called for each adapter board from pci_unregister_driver
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit skfp_remove_one(struct pci_dev *pdev)
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *p = pci_get_drvdata(pdev);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *lp = netdev_priv(p);
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unregister_netdev(p);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->os.SharedMemAddr) {
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(&lp->os.pdev,
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    lp->os.SharedMemSize,
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    lp->os.SharedMemAddr,
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    lp->os.SharedMemDMA);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->os.SharedMemAddr = NULL;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->os.LocalRxBuffer) {
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(&lp->os.pdev,
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    MAX_FRAME_SIZE,
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    lp->os.LocalRxBuffer,
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    lp->os.LocalRxBufferDMA);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->os.LocalRxBuffer = NULL;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MEM_MAPPED_IO
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(lp->hw.iop);
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ioport_unmap(lp->hw.iop);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_release_regions(pdev);
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_netdev(p);
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(pdev);
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_drvdata(pdev, NULL);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ====================
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_driver_init =
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ====================
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Initializes remaining adapter board structure information
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   and makes sure adapter is in a safe state prior to skfp_open().
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Condition code
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev - pointer to device information
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This function allocates additional resources such as the host memory
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   blocks needed by the adapter.
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The adapter is also reset. The OS must call skfp_open() to open
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   the adapter and bring it on-line.
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes:
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - initialization succeeded
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   -1 - initialization failed
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic  int skfp_driver_init(struct net_device *dev)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -EIO;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
388d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering skfp_driver_init\n");
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// set the io address in private structures
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->base_addr = dev->base_addr;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Get the interrupt level from the PCI Configuration Table
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->hw.irq = dev->irq;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&bp->DriverLock);
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Allocate invalid frame
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!bp->LocalRxBuffer) {
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("could not allocate mem for ");
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Determine the required size of the 'shared' memory area.
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->SharedMemSize = mac_drv_check_space();
408d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("Memory for HWM: %ld\n", bp->SharedMemSize);
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bp->SharedMemSize > 0) {
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->SharedMemSize += 16;	// for descriptor alignment
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 bp->SharedMemSize,
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							 &bp->SharedMemDMA);
4154a5fc4e179d79c79ad87bfc12a2d7e9b2371e40cDan Carpenter		if (!bp->SharedMemAddr) {
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("could not allocate mem for ");
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("hardware module: %ld byte\n",
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       bp->SharedMemSize);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->SharedMemHeap = 0;	// Nothing used yet.
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->SharedMemAddr = NULL;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->SharedMemHeap = 0;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}			// SharedMemSize > 0
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(bp->SharedMemAddr, 0, bp->SharedMemSize);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	card_stop(smc);		// Reset adapter.
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
432d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("mac_drv_init()..\n");
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mac_drv_init(smc) != 0) {
434d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("mac_drv_init() failed\n");
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	read_address(smc, NULL);
438d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smt_reset_defaults(smc, 0);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
443807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail:
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bp->SharedMemAddr) {
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(&bp->pdev,
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    bp->SharedMemSize,
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    bp->SharedMemAddr,
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    bp->SharedMemDMA);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->SharedMemAddr = NULL;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bp->LocalRxBuffer) {
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE,
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    bp->LocalRxBuffer, bp->LocalRxBufferDMA);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->LocalRxBuffer = NULL;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_driver_init
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =============
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_open =
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =============
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Opens the adapter
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Condition code
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev - pointer to device information
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This function brings the adapter to an operational state.
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes:
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   0           - Adapter was successfully opened
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   -EAGAIN - Could not register IRQ
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_open(struct net_device *dev)
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
488d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering skfp_open\n");
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Register IRQ - support shared interrupts by passing device ptr */
4902f220e305b23ab277aa0f91e2a65978f5cc1a785Al Viro	err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  dev->name, dev);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Set current address to factory MAC address
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note: We've already done this step in skfp_driver_init.
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *       However, it's possible that a user has set a node
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               address override, then closed and reopened the
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               adapter.  Unless we reset the device address field
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               now, we'll continue to use the existing modified
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               address.
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	read_address(smc, NULL);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_smt(smc, NULL);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smt_online(smc, 1);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	STI_FBI();
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear local multicast address tables */
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_clear_multicast(smc);
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable promiscuous filter settings */
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_start_queue(dev);
519807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_open
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==============
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_close =
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==============
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Closes the device/module.
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Condition code
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev - pointer to device information
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This routine closes the adapter and brings it to a safe state.
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The interrupt service routine is deregistered with the OS.
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The adapter can be opened again with another call to skfp_open().
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes:
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Always return 0.
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assumptions:
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   No further requests for this adapter are made after this routine is
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   called.  skfp_open() can be called to reset and reinitialize the
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   adapter.
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_close(struct net_device *dev)
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	CLI_FBI();
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smt_reset_defaults(smc, 1);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	card_stop(smc);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_drv_clear_tx_queue(smc);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_drv_clear_rx_queue(smc);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue(dev);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Deregister (free) IRQ */
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(dev->irq, dev);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&bp->SendSkbQueue);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->QueueSkb = MAX_TX_QUEUE_LEN;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
568807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_close
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==================
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_interrupt =
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==================
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Interrupt processing routine
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   None
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   irq        - interrupt vector
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev_id     - pointer to device information
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This routine calls the interrupt processing routine for this adapter.  It
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   disables and reenables adapter interrupts, as appropriate.  We can support
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   shared interrupts since the incoming dev_id pointer provides our device
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   structure context. All the real work is done in the hardware module.
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes:
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   None
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assumptions:
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   on Intel-based systems) is done by the operating system outside this
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   routine.
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       System interrupts are enabled through this call.
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Side Effects:
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Interrupts are disabled, then reenabled at the adapter.
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
607409b204435b85f7e159230c216f334a862cb3b95Hannes Ederstatic irqreturn_t skfp_interrupt(int irq, void *dev_id)
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
609c31f28e778ab299a5035ea2bda64f245b8915d7cJeff Garzik	struct net_device *dev = dev_id;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc;	/* private board structure pointer */
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc = netdev_priv(dev);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp = &smc->os;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// IRQs enabled or disabled ?
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (inpd(ADDR(B0_IMSK)) == 0) {
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// IRQs are disabled: must be shared interrupt
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_NONE;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Note: At this point, IRQs are enabled.
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((inpd(ISR_A) & smc->hw.is_imask) == 0) {	// IRQ?
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Adapter did not issue an IRQ: must be shared interrupt
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_NONE;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	CLI_FBI();		// Disable IRQs from our adapter.
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&bp->DriverLock);
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Call interrupt handler in hardware module (HWM).
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fddi_isr(smc);
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (smc->os.ResetRequested) {
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ResetAdapter(smc);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smc->os.ResetRequested = FALSE;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&bp->DriverLock);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	STI_FBI();		// Enable IRQs from our adapter.
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_interrupt
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ======================
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_ctl_get_stats =
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ======================
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Get statistics for FDDI adapter
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Pointer to FDDI statistics structure
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev - pointer to device information
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Gets current MIB objects from adapter, then
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   returns FDDI statistics structure as defined
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   in if_fddi.h.
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Note: Since the FDDI statistics structure is
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   still new and the device structure doesn't
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   have an FDDI-specific get statistics handler,
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   we'll return the FDDI statistics structure as
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   a pointer to an Ethernet statistics structure.
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   That way, at least the first part of the statistics
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   structure can be decoded properly.
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   We'll have to pay attention to this routine as the
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   device structure becomes more mature and LAN media
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   independent.
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
674409b204435b85f7e159230c216f334a862cb3b95Hannes Ederstatic struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev)
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *bp = netdev_priv(dev);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fill the bp->stats structure with driver-maintained counters */
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->os.MacStat.port_bs_flag[0] = 0x1234;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->os.MacStat.port_bs_flag[1] = 0x5678;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// goos: need to fill out fddi statistic
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get FDDI SMT MIB objects */
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Fill the bp->stats structure with the SMT MIB object values */
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	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));
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_op_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_hi_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_lo_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	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));
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_mib_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_mac_cts = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_non_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_available_paths = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_config_capabilities = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_config_policy = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_connection_policy = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_t_notify = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_stat_rpt_policy = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_trace_max_expiration = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_bypass_present = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_ecm_state = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_cf_state = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_remote_disconnect_flag = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_station_status = bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_peer_wrap_flag = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.smt_transition_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_frame_status_functions = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_t_max_capability = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_tvx_capability = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_available_paths = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_current_path = bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_dup_address_test = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_requested_paths = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_downstream_port_type = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_t_req = bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_t_neg = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_t_max = bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_tvx_value = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_frame_error_threshold = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_frame_error_ratio = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_rmt_state = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_una_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_frame_error_flag = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_ma_unitdata_available = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_hardware_present = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_ma_unitdata_enable = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.path_tvx_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.path_t_max_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.path_max_t_req = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_my_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_my_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_neighbor_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_neighbor_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_connection_policies[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_connection_policies[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_mac_indicated[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_mac_indicated[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_current_path[0] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_current_path[1] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&bp->stats.port_requested_paths[0 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&bp->stats.port_requested_paths[1 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_mac_placement[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_mac_placement[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_available_paths[0] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_available_paths[1] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_pmd_class[0] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_pmd_class[1] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_connection_capabilities[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_connection_capabilities[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_bs_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_bs_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_estimate[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_estimate[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_cutoff[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_cutoff[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_alarm[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_alarm[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_connect_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_connect_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_pcm_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_pcm_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_pc_withhold[0] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_pc_withhold[1] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_ler_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_hardware_present[0] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_hardware_present[1] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fill the bp->stats structure with the FDDI counter values */
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_frame_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_copied_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_transmit_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_error_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.mac_lost_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_lct_fail_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_lct_fail_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_lem_reject_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_lem_reject_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_lem_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
797807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return (struct net_device_stats *)&bp->os.MacStat;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// ctl_get_stat
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==============================
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_ctl_set_multicast_list =
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==============================
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Enable/Disable LLC frame promiscuous mode reception
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   on the adapter and/or update multicast address table.
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   None
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev - pointer to device information
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This function acquires the driver lock and only calls
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   skfp_ctl_set_multicast_list_wo_lock then.
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   This routine follows a fairly simple algorithm for setting the
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   adapter filters and CAM:
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      if IFF_PROMISC flag is set
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              enable promiscuous mode
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      else
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              disable promiscuous mode
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              if number of multicast addresses <= max. multicast number
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      add mc addresses to adapter table
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              else
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                      enable promiscuous mode
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              update adapter filters
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assumptions:
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Multicast addresses are presented in canonical (LSB) format.
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Side Effects:
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   On-board adapter filters are updated.
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void skfp_ctl_set_multicast_list(struct net_device *dev)
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long Flags;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&bp->DriverLock, Flags);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfp_ctl_set_multicast_list_wo_lock(dev);
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&bp->DriverLock, Flags);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_ctl_set_multicast_list
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
85422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	struct netdev_hw_addr *ha;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable promiscuous mode, if necessary */
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->flags & IFF_PROMISC) {
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
859d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("PROMISCUOUS MODE ENABLED\n");
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Else, update multicast address table */
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
864d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("PROMISCUOUS MODE DISABLED\n");
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Reset all MC addresses
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mac_clear_multicast(smc);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mac_drv_rx_mode(smc, RX_DISABLE_ALLMULTI);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev->flags & IFF_ALLMULTI) {
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
872d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches			pr_debug("ENABLE ALL MC ADDRESSES\n");
8734cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko		} else if (!netdev_mc_empty(dev)) {
8744cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko			if (netdev_mc_count(dev) <= FPMAX_MULTICAST) {
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* use exact filtering */
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// point to first multicast addr
87822bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko				netdev_for_each_mc_addr(ha, dev) {
87922bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko					mac_add_multicast(smc,
88022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko						(struct fddi_addr *)ha->addr,
88122bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko						1);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
883d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches					pr_debug("ENABLE MC ADDRESS: %pMF\n",
884d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches						 ha->addr);
8855508590c193661bc1484ad7b952af5fceacea40dJiri Pirko				}
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {	// more MC addresses than HW supports
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
890d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches				pr_debug("ENABLE ALL MC ADDRESSES\n");
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {	// no MC addresses
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
894d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches			pr_debug("DISABLE ALL MC ADDRESSES\n");
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Update adapter filters */
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mac_update_multicast(smc);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_ctl_set_multicast_list_wo_lock
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ===========================
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_ctl_set_mac_address =
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ===========================
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   set new mac address on adapter and update dev_addr field in device table.
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   None
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev  - pointer to device information
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   addr - pointer to sockaddr structure containing unicast address to set
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assumptions:
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The address pointed to by addr->sa_data is a valid unicast
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   address and is presented in canonical (LSB) format.
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_ctl_set_mac_address(struct net_device *dev, void *addr)
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long Flags;
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&bp->DriverLock, Flags);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ResetAdapter(smc);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&bp->DriverLock, Flags);
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
935807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;		/* always return zero */
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_ctl_set_mac_address
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==============
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_ioctl =
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ==============
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Perform IOCTL call functions here. Some are privileged operations and the
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * effective uid is checked in those cases.
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   status value
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   0 - success
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   other - failure
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev  - pointer to device information
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   rq - pointer to ioctl request structure
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   cmd - ?
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *lp = &smc->os;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_skfp_ioctl ioc;
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int status = 0;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl)))
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ioc.cmd) {
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SKFP_GET_STATS:	/* Get the driver statistics */
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ioc.len = sizeof(lp->MacStat);
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len)
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				? -EFAULT : 0;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SKFP_CLR_STATS:	/* Zero out the driver statistics */
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_NET_ADMIN)) {
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = -EPERM;
981c25b9abbc2c2c0da88e180c3933d6e773245815aRoel Kluin		} else {
982c25b9abbc2c2c0da88e180c3933d6e773245815aRoel Kluin			memset(&lp->MacStat, 0, sizeof(lp->MacStat));
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
986af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa		printk("ioctl for %s: unknown cmd: %04x\n", dev->name, ioc.cmd);
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = -EOPNOTSUPP;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}			// switch
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return status;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_ioctl
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =====================
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = skfp_send_pkt     =
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =====================
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Queues a packet for transmission and try to transmit it.
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Condition code
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   skb - pointer to sk_buff to queue for transmission
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   dev - pointer to device information
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Here we assume that an incoming skb transmit request
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   is contained in a single physically contiguous buffer
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   in which the virtual address of the start of packet
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   (skb->data) can be converted to a physical address
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   by using pci_map_single().
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   We have an internal queue for packets we can not send
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   immediately. Packets in this queue can be given to the
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   adapter if transmit buffers are freed.
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   We can't free the skb until after it's been DMA'd
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   out by the adapter, so we'll keep it in the driver and
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   return it in mac_drv_tx_complete.
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return Codes:
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   0 - driver has queued and/or sent packet
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       1 - caller should requeue the sk_buff for later transmission
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assumptions:
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   The entire packet is stored in one physically
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   contiguous buffer which is not cached and whose
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   32-bit physical address can be determined.
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   It's vital that this routine is NOT reentered for the
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   same board and that the OS is not in another section of
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   code (eg. skfp_interrupt) for the same board on a
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   different thread.
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Side Effects:
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   None
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
104261357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
104361357325f377889a1daffa14962d705dc814dd0eStephen Hemminger				       struct net_device *dev)
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smc *smc = netdev_priv(dev);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1048d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("skfp_send_pkt\n");
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Verify that incoming transmit request is OK
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note: The packet size check is consistent with other
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               Linux device drivers, although the correct packet
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               size should be verified before calling the
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *               transmit routine.
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->MacStat.gen.tx_errors++;	/* bump error counter */
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// dequeue packets from xmt queue and send them
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_start_queue(dev);
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb(skb);
1064ec634fe328182a1a098585bfc7b69e5042bdb08dPatrick McHardy		return NETDEV_TX_OK;	/* return "success" */
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bp->QueueSkb == 0) {	// return with tbusy set: queue full
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_stop_queue(dev);
10695b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy		return NETDEV_TX_BUSY;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bp->QueueSkb--;
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&bp->SendSkbQueue, skb);
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_queued_packets(netdev_priv(dev));
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bp->QueueSkb == 0) {
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_stop_queue(dev);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10776ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// skfp_send_pkt
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =======================
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = send_queued_packets =
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * =======================
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overview:
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Send packets from the driver queue as long as there are some and
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   transmit resources are available.
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns:
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   None
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arguments:
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   smc - pointer to smc (adapter) structure
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Functional Description:
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Take a packet from queue if there is any. If not, then we are done.
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Check if there are resources to send the packet. If not, requeue it
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   and exit.
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Set packet descriptor flags and give packet to adapter.
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   Check if any send resources can be freed (we do not use the
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   transmit complete interrupt).
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void send_queued_packets(struct s_smc *smc)
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char fc;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int queue;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct s_smt_fp_txd *txd;	// Current TxD.
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_addr_t dma_address;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long Flags;
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int frame_status;	// HWM tx frame status.
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1117d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("send queued packets\n");
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;;) {
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// send first buffer from queue
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = skb_dequeue(&bp->SendSkbQueue);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!skb) {
1123d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches			pr_debug("queue empty\n");
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}		// queue empty !
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&bp->DriverLock, Flags);
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fc = skb->data[0];
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		queue = (fc & FC_SYNC_BIT) ? QUEUE_S : QUEUE_A0;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ESS
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Check if the frame may/must be sent as a synchronous frame.
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((fc & ~(FC_SYNC_BIT | FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// It's an LLC frame.
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!smc->ess.sync_bw_available)
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				fc &= ~FC_SYNC_BIT; // No bandwidth available.
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {	// Bandwidth is available.
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (smc->mib.fddiESSSynchTxMode) {
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					// Send as sync. frame.
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					fc |= FC_SYNC_BIT;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif				// ESS
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		frame_status = hwm_tx_init(smc, fc, 1, skb->len, queue);
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((frame_status & (LOC_TX | LAN_TX)) == 0) {
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Unable to send the frame.
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((frame_status & RING_DOWN) != 0) {
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Ring is down.
1154ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov				pr_debug("Tx attempt while ring down.\n");
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if ((frame_status & OUT_OF_TXD) != 0) {
1156ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov				pr_debug("%s: out of TXDs.\n", bp->dev->name);
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
1158ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov				pr_debug("%s: out of transmit resources",
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					bp->dev->name);
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Note: We will retry the operation as soon as
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// transmit resources become available.
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_head(&bp->SendSkbQueue, skb);
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&bp->DriverLock, Flags);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;	// Packet has been queued.
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}		// if (unable to send frame)
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bp->QueueSkb++;	// one packet less in local queue
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// source address in packet ?
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		CheckSourceAddress(skb->data, smc->hw.fddi_canon_addr.a);
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue);
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_address = pci_map_single(&bp->pdev, skb->data,
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     skb->len, PCI_DMA_TODEVICE);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (frame_status & LAN_TX) {
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			txd->txd_os.skb = skb;			// save skb
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			txd->txd_os.dma_addr = dma_address;	// save dma mapping
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwm_tx_frag(smc, skb->data, dma_address, skb->len,
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF);
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(frame_status & LAN_TX)) {		// local only frame
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_unmap_single(&bp->pdev, dma_address,
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 skb->len, PCI_DMA_TODEVICE);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb_irq(skb);
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&bp->DriverLock, Flags);
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}			// for
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;			// never reached
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// send_queued_packets
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CheckSourceAddress
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Verify if the source address is set. Insert it if necessary.
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
1206409b204435b85f7e159230c216f334a862cb3b95Hannes Ederstatic void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char SRBit;
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((((unsigned long) frame[1 + 6]) & ~0x01) != 0) // source routing bit
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((unsigned short) frame[1 + 10] != 0)
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SRBit = frame[1 + 6] & 0x01;
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&frame[1 + 6], hw_addr, 6);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	frame[8] |= SRBit;
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// CheckSourceAddress
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	ResetAdapter
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Reset the adapter and bring it back to operational mode.
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ResetAdapter(struct s_smc *smc)
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1235d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("[fddi: ResetAdapter]\n");
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Stop the adapter.
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	card_stop(smc);		// Stop all activity.
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Clear the transmit and receive descriptor queues.
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_drv_clear_tx_queue(smc);
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_drv_clear_rx_queue(smc);
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Restart the adapter.
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smt_reset_defaults(smc, 1);	// Initialize the SMT module.
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_smt(smc, (smc->os.dev)->dev_addr);	// Initialize the hardware.
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smt_online(smc, 1);	// Insert into the ring again.
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	STI_FBI();
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Restore original receive mode (multicasts, promiscuous, etc.).
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfp_ctl_set_multicast_list_wo_lock(smc->os.dev);
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// ResetAdapter
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//--------------- functions called by hardware module ----------------
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	llc_restart_tx
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware driver calls this routine when the transmit complete
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	interrupt bits (end of frame) for the synchronous or asynchronous
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	queue is set.
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE The hardware driver calls this function also if no packets are queued.
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The routine must be able to handle this case.
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid llc_restart_tx(struct s_smc *smc)
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("[llc_restart_tx]\n");
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Try to send queued packets
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&bp->DriverLock);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_queued_packets(smc);
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&bp->DriverLock);
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_start_queue(bp->dev);// system may send again if it was blocked
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// llc_restart_tx
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_get_space
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this function to allocate the memory
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	for the SMT MBufs if the define MB_OUTSIDE_SMC is specified.
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	size - Size of memory in bytes to allocate.
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	!= 0	A pointer to the virtual address of the allocated memory.
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	== 0	Allocation error.
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid *mac_drv_get_space(struct s_smc *smc, unsigned int size)
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *virt;
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("mac_drv_get_space (%d bytes), ", size);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Unexpected SMT memory size requested: %d\n", size);
1316807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return NULL;
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.SharedMemHeap += size;	// Move heap pointer.
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1320d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("mac_drv_get_space end\n");
1321d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("virt addr: %lx\n", (ulong) virt);
1322d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("bus  addr: %lx\n", (ulong)
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (smc->os.SharedMemDMA +
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		((char *) virt - (char *)smc->os.SharedMemAddr)));
1325807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return virt;
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_get_space
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_get_desc_mem
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This function is called by the hardware dependent module.
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	It allocates the memory for the RxD and TxD descriptors.
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This memory must be non-cached, non-movable and non-swappable.
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This memory should start at a physical page boundary.
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	size - Size of memory in bytes to allocate.
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	!= 0	A pointer to the virtual address of the allocated memory.
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	== 0	Allocation error.
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *virt;
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1352d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("mac_drv_get_desc_mem\n");
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Descriptor memory must be aligned on 16-byte boundary.
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	virt = mac_drv_get_space(smc, size);
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = (u_int) (16 - (((unsigned long) virt) & 15UL));
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = size % 16;
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov	pr_debug("Allocate %u bytes alignment gap ", size);
1362ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov	pr_debug("for descriptor memory.\n");
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!mac_drv_get_space(smc, size)) {
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("fddi: Unable to align descriptor memory.\n");
1366807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return NULL;
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1368807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return virt + size;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_get_desc_mem
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_virt2phys
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Get the physical address of a given virtual address.
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	virt - A (virtual) pointer into our 'shared' memory area.
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Physical address of the given virtual address.
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1387807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return smc->os.SharedMemDMA +
1388807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		((char *) virt - (char *)smc->os.SharedMemAddr);
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_virt2phys
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	dma_master
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The HWM calls this function, when the driver leads through a DMA
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	transfer. If the OS-specific module must prepare the system hardware
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	for the DMA transfer, it should do it in this function.
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this dma_master if it wants to send an SMT
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	frame.  This means that the virt address passed in here is part of
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      the 'shared' memory area.
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	virt - The virtual address of the data.
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	len - The length in bytes of the data.
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	flag - Indicates the transmit direction and the buffer type:
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		DMA_RD	(0x01)	system RAM ==> adapter buffer memory
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		DMA_WR	(0x02)	adapter buffer memory ==> system RAM
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		SMT_BUF (0x80)	SMT buffer
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	>> NOTE: SMT_BUF and DMA_RD are always set for PCI. <<
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Returns the pyhsical address for the DMA transfer.
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu_long dma_master(struct s_smc * smc, void *virt, int len, int flag)
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1422807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return smc->os.SharedMemDMA +
1423807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		((char *) virt - (char *)smc->os.SharedMemAddr);
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// dma_master
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	dma_complete
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this routine when it has completed a DMA
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	transfer. If the operating system dependent module has set up the DMA
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	channel via dma_master() (e.g. Windows NT or AIX) it should clean up
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	the DMA channel.
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	descr - A pointer to a TxD or RxD, respectively.
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	flag - Indicates the DMA transfer direction / SMT buffer:
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		DMA_RD	(0x01)	system RAM ==> adapter buffer memory
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		DMA_WR	(0x02)	adapter buffer memory ==> system RAM
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		SMT_BUF (0x80)	SMT buffer (managed by HWM)
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag)
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* For TX buffers, there are two cases.  If it is an SMT transmit
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * buffer, there is nothing to do since we use consistent memory
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * for the 'shared' memory area.  The other case is for normal
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * transmit packets given to us by the networking stack, and in
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * below.
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * For RX buffers, we have to unmap dynamic PCI DMA mappings here
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * because the hardware module is about to potentially look at
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the contents of the buffer.  If we did not call the PCI DMA
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unmap first, the hardware module could read inconsistent data.
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (flag & DMA_WR) {
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skfddi_priv *bp = &smc->os;
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		volatile struct s_smt_fp_rxd *r = &descr->r;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* If SKB is NULL, we used the local buffer. */
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (r->rxd_os.skb && r->rxd_os.dma_addr) {
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int MaxFrameSize = bp->MaxFrameSize;
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr,
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 MaxFrameSize, PCI_DMA_FROMDEVICE);
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->rxd_os.dma_addr = 0;
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// dma_complete
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_tx_complete
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Transmit of a packet is complete. Release the tx staging buffer.
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	txd - A pointer to the last TxD which is used by the frame.
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Returns nothing.
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1496d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering mac_drv_tx_complete\n");
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Check if this TxD points to a skb
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb = txd->txd_os.skb)) {
1500ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("TXD with no skb assigned.\n");
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	txd->txd_os.skb = NULL;
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// release the DMA mapping
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr,
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 skb->len, PCI_DMA_TODEVICE);
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	txd->txd_os.dma_addr = 0;
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.MacStat.gen.tx_packets++;	// Count transmitted packets.
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.MacStat.gen.tx_bytes+=skb->len;	// Count bytes
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// free the skb
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_kfree_skb_irq(skb);
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1516d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("leaving mac_drv_tx_complete\n");
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_tx_complete
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dump packets to logfile
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DUMPPACKETS
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dump_data(unsigned char *Data, int length)
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j;
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char s[255], sh[10];
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (length > 64) {
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = 64;
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "---Packet start---\n");
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0, j = 0; i < length / 8; i++, j += 8)
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n",
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3],
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]);
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(s, "");
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < length % 8; i++) {
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(sh, "%02x ", Data[j + i]);
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		strcat(s, sh);
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "%s\n", s);
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "------------------\n");
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// dump_data
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dump_data(data,len)
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif				// DUMPPACKETS
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_rx_complete
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this function if an LLC frame is received
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	in a receive buffer. Also the SMT, NSA, and directed beacon frames
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	from the network will be passed to the LLC layer by this function
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	if passing is enabled.
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_rx_complete forwards the frame to the LLC layer if it should
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	be received. It also fills the RxD ring with new receive buffers if
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	some can be queued.
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	rxd - A pointer to the first RxD which is used by the receive frame.
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	frag_count - Count of RxDs used by the received frame.
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	len - Frame length.
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int frag_count, int len)
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skfddi_priv *bp = &smc->os;
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *virt, *cp;
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short ri;
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_int RifLength;
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1583d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering mac_drv_rx_complete (len=%d)\n", len);
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (frag_count != 1) {	// This is not allowed to happen.
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("fddi: Multi-fragment receive!\n");
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto RequeueRxd;	// Re-use the given RXD(s).
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb = rxd->rxd_os.skb;
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb) {
1592d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("No skb in rxd\n");
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smc->os.MacStat.gen.rx_errors++;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto RequeueRxd;
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	virt = skb->data;
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// The DMA mapping was released in dma_complete above.
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_data(skb->data, len);
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * FDDI Frame format:
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * +-------+-------+-------+------------+--------+------------+
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] |
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * +-------+-------+-------+------------+--------+------------+
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * FC = Frame Control
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * DA = Destination Address
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * SA = Source Address
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * RIF = Routing Information Field
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * LLC = Logical Link Control
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Remove Routing Information Field (RIF), if present.
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((virt[1 + 6] & FDDI_RII) == 0)
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		RifLength = 0;
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int n;
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// goos: RIF removal has still to be tested
1622d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("RIF found\n");
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Get RIF length from Routing Control (RC) field.
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cp = virt + FDDI_MAC_HDR_LEN;	// Point behind MAC header.
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16262f220e305b23ab277aa0f91e2a65978f5cc1a785Al Viro		ri = ntohs(*((__be16 *) cp));
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		RifLength = ri & FDDI_RCF_LEN_MASK;
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("fddi: Invalid RIF.\n");
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto RequeueRxd;	// Discard the frame.
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		virt[1 + 6] &= ~FDDI_RII;	// Clear RII bit.
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// regions overlap
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		virt = cp + RifLength;
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (n = FDDI_MAC_HDR_LEN; n; n--)
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*--virt = *--cp;
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// adjust sbd->data pointer
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_pull(skb, RifLength);
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= RifLength;
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		RifLength = 0;
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Count statistics.
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.MacStat.gen.rx_packets++;	// Count indicated receive
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						// packets.
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.MacStat.gen.rx_bytes+=len;	// Count bytes.
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// virt points to header again
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (virt[1] & 0x01) {	// Check group (multicast) bit.
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smc->os.MacStat.gen.multicast++;
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// deliver frame to system
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rxd->rxd_os.skb = NULL;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_trim(skb, len);
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb->protocol = fddi_type_trans(skb, bp->dev);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_rx(skb);
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      RequeueRxd:
1667d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("Rx: re-queue RXD.\n");
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mac_drv_requeue_rxd(smc, rxd, frag_count);
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.MacStat.gen.rx_errors++;	// Count receive packets
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						// not indicated.
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_rx_complete
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_requeue_rxd
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this function to request the OS-specific
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	module to queue the receive buffer(s) represented by the pointer
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	to the RxD and the frag_count into the receive queue again. This
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	buffer was filled with an invalid frame or an SMT frame.
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	rxd - A pointer to the first RxD which is used by the receive frame.
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	frag_count - Count of RxDs used by the received frame.
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int frag_count)
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile struct s_smt_fp_rxd *next_rxd;
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile struct s_smt_fp_rxd *src_rxd;
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int MaxFrameSize;
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *v_addr;
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_addr_t b_addr;
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (frag_count != 1)	// This is not allowed to happen.
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("fddi: Multi-fragment requeue!\n");
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MaxFrameSize = smc->os.MaxFrameSize;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	src_rxd = rxd;
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; frag_count > 0; frag_count--) {
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		next_rxd = src_rxd->rxd_next;
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rxd = HWM_GET_CURR_RXD(smc);
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = src_rxd->rxd_os.skb;
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb == NULL) {	// this should not happen
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1716ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov			pr_debug("Requeue with no skb in rxd!\n");
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (skb) {
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// we got a skb
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rxd->rxd_os.skb = skb;
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				skb_reserve(skb, 3);
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				skb_put(skb, MaxFrameSize);
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				v_addr = skb->data;
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				b_addr = pci_map_single(&smc->os.pdev,
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							v_addr,
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							MaxFrameSize,
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							PCI_DMA_FROMDEVICE);
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rxd->rxd_os.dma_addr = b_addr;
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// no skb available, use local buffer
1731ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov				pr_debug("Queueing invalid buffer!\n");
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rxd->rxd_os.skb = NULL;
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				v_addr = smc->os.LocalRxBuffer;
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				b_addr = smc->os.LocalRxBufferDMA;
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// we use skb from old rxd
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rxd->rxd_os.skb = skb;
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			v_addr = skb->data;
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			b_addr = pci_map_single(&smc->os.pdev,
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						v_addr,
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						MaxFrameSize,
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						PCI_DMA_FROMDEVICE);
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rxd->rxd_os.dma_addr = b_addr;
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    FIRST_FRAG | LAST_FRAG);
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		src_rxd = next_rxd;
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_requeue_rxd
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_fill_rxd
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this function at initialization time
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	to fill the RxD ring with receive buffers. It is also called by
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_rx_complete if rx_free is large enough to queue some new
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	receive buffers into the RxD ring. mac_drv_fill_rxd queues new
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	receive buffers as long as enough RxDs and receive buffers are
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	available.
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_fill_rxd(struct s_smc *smc)
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int MaxFrameSize;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *v_addr;
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long b_addr;
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile struct s_smt_fp_rxd *rxd;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1778d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering mac_drv_fill_rxd\n");
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Walk through the list of free receive buffers, passing receive
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// buffers to the HWM as long as RXDs are available.
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MaxFrameSize = smc->os.MaxFrameSize;
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// Check if there is any RXD left.
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (HWM_GET_RX_FREE(smc) > 0) {
1786d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug(".\n");
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rxd = HWM_GET_CURR_RXD(smc);
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb) {
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// we got a skb
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_reserve(skb, 3);
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_put(skb, MaxFrameSize);
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			v_addr = skb->data;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			b_addr = pci_map_single(&smc->os.pdev,
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						v_addr,
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						MaxFrameSize,
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						PCI_DMA_FROMDEVICE);
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rxd->rxd_os.dma_addr = b_addr;
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// no skb available, use local buffer
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// System has run out of buffer memory, but we want to
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// keep the receiver running in hope of better times.
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Multiple descriptors may point to this local buffer,
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// so data in it must be considered invalid.
1806ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov			pr_debug("Queueing invalid buffer!\n");
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			v_addr = smc->os.LocalRxBuffer;
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			b_addr = smc->os.LocalRxBufferDMA;
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rxd->rxd_os.skb = skb;
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// Pass receive buffer to HWM.
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    FIRST_FRAG | LAST_FRAG);
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1817d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("leaving mac_drv_fill_rxd\n");
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_fill_rxd
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_clear_rxd
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this function to release unused
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	receive buffers.
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	rxd - A pointer to the first RxD which is used by the receive buffer.
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	frag_count - Count of RxDs used by the receive buffer.
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       int frag_count)
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1843ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov	pr_debug("entering mac_drv_clear_rxd\n");
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (frag_count != 1)	// This is not allowed to happen.
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("fddi: Multi-fragment clear!\n");
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; frag_count > 0; frag_count--) {
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = rxd->rxd_os.skb;
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb != NULL) {
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skfddi_priv *bp = &smc->os;
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int MaxFrameSize = bp->MaxFrameSize;
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr,
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 MaxFrameSize, PCI_DMA_FROMDEVICE);
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb(skb);
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rxd->rxd_os.skb = NULL;
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rxd = rxd->rxd_next;	// Next RXD.
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_clear_rxd
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_rx_init
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The hardware module calls this routine when an SMT or NSA frame of the
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	local SMT should be delivered to the LLC layer.
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	It is necessary to have this function, because there is no other way to
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	copy the contents of SMT MBufs into receive buffers.
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	mac_drv_rx_init allocates the required target memory for this frame,
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	and receives the frame fragment by fragment by calling mac_drv_rx_frag.
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	len - The length (in bytes) of the received frame (FC, DA, SA, Data).
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	fc - The Frame Control field of the received frame.
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	look_ahead - A pointer to the lookahead data buffer (may be NULL).
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	la_len - The length of the lookahead data stored in the lookahead
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	buffer (may be zero).
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Always returns zero (0).
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mac_drv_rx_init(struct s_smc *smc, int len, int fc,
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    char *look_ahead, int la_len)
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1899ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov	pr_debug("entering mac_drv_rx_init(len=%d)\n", len);
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// "Received" a SMT or NSA frame of the local SMT.
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) {
1904ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("fddi: Discard invalid local SMT frame\n");
1905ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       len, la_len, (unsigned long) look_ahead);
1907807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return 0;
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb = alloc_skb(len + 3, GFP_ATOMIC);
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb) {
1911ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("fddi: Local SMT: skb memory exhausted.\n");
1912807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return 0;
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_reserve(skb, 3);
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_put(skb, len);
191627d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo	skb_copy_to_linear_data(skb, look_ahead, len);
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// deliver frame to system
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb->protocol = fddi_type_trans(skb, smc->os.dev);
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_rx(skb);
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1922807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// mac_drv_rx_init
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smt_timer_poll
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This routine is called periodically by the SMT module to clean up the
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	driver.
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Return any queued frames back to the upper protocol layers if the ring
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	is down.
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid smt_timer_poll(struct s_smc *smc)
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// smt_timer_poll
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	ring_status_indication
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This function indicates a change of the ring state.
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	status - The current ring status.
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ring_status_indication(struct s_smc *smc, u_long status)
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1961ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov	pr_debug("ring_status_indication( ");
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_RES15)
1963ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_RES15 ");
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_HARDERROR)
1965ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_HARDERROR ");
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_SOFTERROR)
1967ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_SOFTERROR ");
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_BEACON)
1969ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_BEACON ");
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_PATHTEST)
1971ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_PATHTEST ");
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_SELFTEST)
1973ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_SELFTEST ");
19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_RES9)
1975ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_RES9 ");
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_DISCONNECT)
1977ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_DISCONNECT ");
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_RES7)
1979ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_RES7 ");
19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_DUPADDR)
1981ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_DUPADDR ");
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_NORINGOP)
1983ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_NORINGOP ");
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_VERSION)
1985ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_VERSION ");
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_STUCKBYPASSS)
1987ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_STUCKBYPASSS ");
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_EVENT)
1989ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_EVENT ");
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_RINGOPCHANGE)
1991ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_RINGOPCHANGE ");
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & RS_RES0)
1993ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov		pr_debug("RS_RES0 ");
1994ebc06eeb7260ecad3bd69202ba6291138691d27bAlexander Beregalov	pr_debug("]\n");
19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// ring_status_indication
19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smt_get_time
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Gets the current time from the system.
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	None.
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	The current time in TICKS_PER_SECOND.
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	TICKS_PER_SECOND has the unit 'count of timer ticks per second'. It is
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	defined in "targetos.h". The definition of TICKS_PER_SECOND must comply
20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	to the time returned by smt_get_time().
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long smt_get_time(void)
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return jiffies;
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// smt_get_time
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smt_stat_counter
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Status counter update (ring_op, fifo full).
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	stat -	= 0: A ring operational change occurred.
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		= 1: The FORMAC FIFO buffer is full / FIFO overflow.
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid smt_stat_counter(struct s_smc *smc, int stat)
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//      BOOLEAN RingIsUp ;
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2037d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("smt_stat_counter\n");
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (stat) {
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:
2040d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("Ring operational change.\n");
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
2043d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("Receive fifo overflow.\n");
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		smc->os.MacStat.gen.rx_errors++;
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2047d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("Unknown status (%d).\n", stat);
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// smt_stat_counter
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	cfm_state_change
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Sets CFM state in custom statistics.
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	c_state - Possible values are:
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		EC0_OUT, EC1_IN, EC2_TRACE, EC3_LEAVE, EC4_PATH_TEST,
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		EC5_INSERT, EC6_CHECK, EC7_DEINSERT
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cfm_state_change(struct s_smc *smc, int c_state)
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DRIVERDEBUG
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *s;
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (c_state) {
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC0_ISOLATED:
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC0_ISOLATED";
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC1_WRAP_A:
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC1_WRAP_A";
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC2_WRAP_B:
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC2_WRAP_B";
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC4_THRU_A:
20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC4_THRU_A";
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC5_THRU_B:
20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC5_THRU_B";
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC7_WRAP_S:
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC7_WRAP_S";
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC9_C_WRAP_A:
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC9_C_WRAP_A";
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC10_C_WRAP_B:
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC10_C_WRAP_B";
20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SC11_C_WRAP_S:
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "SC11_C_WRAP_S";
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2103d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches		pr_debug("cfm_state_change: unknown %d\n", c_state);
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2106d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("cfm_state_change: %s\n", s);
21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif				// DRIVERDEBUG
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// cfm_state_change
21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	ecm_state_change
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Sets ECM state in custom statistics.
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	e_state - Possible values are:
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		SC0_ISOLATED, SC1_WRAP_A (5), SC2_WRAP_B (6), SC4_THRU_A (12),
21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		SC5_THRU_B (7), SC7_WRAP_S (8)
21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ecm_state_change(struct s_smc *smc, int e_state)
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DRIVERDEBUG
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *s;
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e_state) {
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC0_OUT:
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC0_OUT";
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC1_IN:
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC1_IN";
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC2_TRACE:
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC2_TRACE";
21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC3_LEAVE:
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC3_LEAVE";
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC4_PATH_TEST:
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC4_PATH_TEST";
21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC5_INSERT:
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC5_INSERT";
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC6_CHECK:
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC6_CHECK";
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EC7_DEINSERT:
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "EC7_DEINSERT";
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "unknown";
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2161d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("ecm_state_change: %s\n", s);
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif				//DRIVERDEBUG
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// ecm_state_change
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	rmt_state_change
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Sets RMT state in custom statistics.
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	r_state - Possible values are:
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		RM0_ISOLATED, RM1_NON_OP, RM2_RING_OP, RM3_DETECT,
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		RM4_NON_OP_DUP, RM5_RING_OP_DUP, RM6_DIRECTED, RM7_TRACE
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid rmt_state_change(struct s_smc *smc, int r_state)
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DRIVERDEBUG
21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *s;
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (r_state) {
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM0_ISOLATED:
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM0_ISOLATED";
21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM1_NON_OP:
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM1_NON_OP - not operational";
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM2_RING_OP:
21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM2_RING_OP - ring operational";
21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM3_DETECT:
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM3_DETECT - detect dupl addresses";
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM4_NON_OP_DUP:
22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM4_NON_OP_DUP - dupl. addr detected";
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM5_RING_OP_DUP:
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM5_RING_OP_DUP - ring oper. with dupl. addr";
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM6_DIRECTED:
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM6_DIRECTED - sending directed beacons";
22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case RM7_TRACE:
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "RM7_TRACE - trace initiated";
22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s = "unknown";
22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2216d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("[rmt_state_change: %s]\n", s);
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif				// DRIVERDEBUG
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// rmt_state_change
22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	drv_reset_indication
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This function is called by the SMT when it has detected a severe
22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	hardware problem. The driver should perform a reset on the adapter
22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	as soon as possible, but not from within this function.
22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Args
22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	smc - A pointer to the SMT context struct.
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Out
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Nothing.
22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************/
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid drv_reset_indication(struct s_smc *smc)
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2236d81e27cf4e2a5050245f9962539292ea2c9e2206Joe Perches	pr_debug("entering drv_reset_indication\n");
22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smc->os.ResetRequested = TRUE;	// Set flag.
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				// drv_reset_indication
22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver skfddi_pci_driver = {
22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "skfddi",
22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= skfddi_pci_tbl,
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= skfp_init_one,
22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= __devexit_p(skfp_remove_one),
22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init skfd_init(void)
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2251299176206b266f204be859adf9e66efd06628ab2Jeff Garzik	return pci_register_driver(&skfddi_pci_driver);
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit skfd_exit(void)
22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unregister_driver(&skfddi_pci_driver);
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(skfd_init);
22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(skfd_exit);
2261